UNPKG

neft

Version:

Universal Platform

283 lines (209 loc) 7.97 kB
# Element 'use strict' utils = require 'src/utils' assert = require 'src/assert' signal = require 'src/signal' {isArray} = Array {Emitter} = signal {emitSignal} = Emitter assert = assert.scope 'View.Element' class Element extends Emitter @__name__ = 'Element' @__path__ = 'File.Element' @JSON_CTORS = [] JSON_CTOR_ID = @JSON_CTOR_ID = @JSON_CTORS.push(Element) - 1 i = 1 JSON_VISIBLE = i++ JSON_ARGS_LENGTH = @JSON_ARGS_LENGTH = i ## *Element* Element.fromHTML(*String* html) @fromHTML = (html) -> assert.isString html unless process.env.NEFT_PLATFORM is 'node' throw new Error 'Creating Views from HTML files is allowed only on a server' Element.parser.parse html ## *Element* Element.fromJSON(*Array*|*String* json) @fromJSON = (json) -> if typeof json is 'string' json = JSON.parse json assert.isArray json Element.JSON_CTORS[json[0]]._fromJSON json @_fromJSON = (arr, obj = new Element) -> obj._visible = arr[JSON_VISIBLE] is 1 obj @Text = require('./element/text') Element @Tag = Tag = require('./element/tag') Element ## *Element* Element::constructor() constructor: -> Emitter.call @ @_parent = null @_nextSibling = null @_previousSibling = null @_style = null @_documentStyle = null @_visible = true @_watchers = null @_inWatchers = null @_checkWatchers = 0 `//<development>` if @constructor is Element Object.seal @ `//</development>` ## *Integer* Element::index opts = utils.CONFIGURABLE utils.defineProperty @::, 'index', opts, -> @parent?.children.indexOf(@) or 0 , (val) -> assert.instanceOf @parent, Element assert.isInteger val assert.operator val, '>=', 0 parent = @_parent if not parent return false {index} = @ children = parent.children if val > children.length val = children.length if index is val or index is val - 1 return false # current siblings @_previousSibling?._nextSibling = @_nextSibling @_nextSibling?._previousSibling = @_previousSibling # children array children.splice index, 1 if val > index val-- children.splice val, 0, @ # new siblings @_previousSibling = children[val - 1] or null @_nextSibling = children[val + 1] or null @_previousSibling?._nextSibling = @ @_nextSibling?._previousSibling = @ assert.is @index, val assert.is children[val], @ assert.is @_previousSibling, children[val - 1] or null assert.is @_nextSibling, children[val + 1] or null true ## *Element* Element::nextSibling opts = utils.CONFIGURABLE utils.defineProperty @::, 'nextSibling', opts, -> @_nextSibling , null ## *Element* Element::previousSibling opts = utils.CONFIGURABLE utils.defineProperty @::, 'previousSibling', opts, -> @_previousSibling , null ## *Element* Element::parent opts = utils.CONFIGURABLE utils.defineProperty @::, 'parent', opts, -> @_parent , (val) -> assert.instanceOf @, Element assert.instanceOf val, Element if val? assert.isNot @, val old = @_parent if old is val return false # remove element if @_parent oldChildren = @_parent.children assert.ok utils.has(oldChildren, @) if not @_nextSibling assert.ok oldChildren[oldChildren.length - 1] is @ oldChildren.pop() else if not @_previousSibling assert.ok oldChildren[0] is @ oldChildren.shift() else index = oldChildren.indexOf @ oldChildren.splice index, 1 emitSignal @_parent, 'onChildrenChange', null, @ @_previousSibling?._nextSibling = @_nextSibling @_nextSibling?._previousSibling = @_previousSibling @_previousSibling = null @_nextSibling = null @_parent = parent = val # append element if parent assert.notOk utils.has(@_parent.children, @) newChildren = @_parent.children index = newChildren.push(@) - 1 emitSignal parent, 'onChildrenChange', @ if index is 0 @_previousSibling = null else @_previousSibling = newChildren[index - 1] @_previousSibling._nextSibling = @ assert.is @_parent, val assert.is @_nextSibling, null assert.is @_previousSibling, val?.children[val.children.length - 2] or null if @_previousSibling assert.is @_previousSibling._nextSibling, @ # trigger signal emitSignal @, 'onParentChange', old Tag.query.checkWatchersDeeply @, old Tag.query.checkWatchersDeeply @ true ## *Signal* Element::onParentChange(*Element* oldValue) signal.Emitter.createSignal @, 'onParentChange' ## *Renderer.Item* Element::style opts = utils.CONFIGURABLE utils.defineProperty @::, 'style', opts, -> @_style , (val) -> old = @_style if old is val return false @_style = val # trigger signal emitSignal @, 'onStyleChange', old, val true ## *Signal* Element::onStyleChange(*Renderer.Item* oldValue) signal.Emitter.createSignal @, 'onStyleChange' ## *Boolean* Element::visible opts = utils.CONFIGURABLE utils.defineProperty @::, 'visible', opts, -> @_visible , (val) -> assert.isBoolean val old = @_visible if old is val return false @_visible = val # trigger signal emitSignal @, 'onVisibleChange', old true ## *Signal* Element::onVisibleChange(*Boolean* oldValue) signal.Emitter.createSignal @, 'onVisibleChange' ## *Array* Element::queryAllParents(*String* query) queryAllParents: Tag.query.queryAllParents ## *Element* Element::queryParents(*String* query) queryParents: Tag.query.queryParents ## *Array* Element::getAccessPath([*Tag* toParent]) getAccessPath: (toParent) -> if toParent? assert.instanceOf toParent, Tag arr = [] i = 0 elem = @ parent = @ while parent = elem._parent arr.push parent.children.indexOf(elem) elem = parent if parent is toParent break arr ## *Element* Element::clone() clone: (clone = new Element) -> clone._visible = @_visible clone ## *Array* Element::toJSON() toJSON: (arr) -> unless arr arr = new Array JSON_ARGS_LENGTH arr[0] = JSON_CTOR_ID arr[JSON_VISIBLE] = if @visible then 1 else 0 arr if process.env.NEFT_PLATFORM is 'node' @parser = require('./element/parser') Element module.exports = Element