module.exports = Value.subclass({ className: 'basis.data.index.IndexWrapper', extendConstructor_: false, source: null, sourceRA_: null, dataset: null, indexConstructor: null, index: null, init: function(source, indexConstructor){ this.source = source; this.indexConstructor = indexConstructor; this.value = indexConstructor.prototype.value; Value.prototype.init.call(this); source.bindingBridge.attach(source, basis.fn.$undef, this, this.destroy); this.setDataset(source); }, setDataset: function(source){ var oldDataset = this.dataset; var newDataset = resolveDataset(this, this.setDataset, source, 'sourceRA_'); if (newDataset !== oldDataset) { var index = this.index; if (index) { index.removeHandler(INDEXWRAPPER_HANDLER, this); index.wrapperCount -= 1; if (!index.wrapperCount && !index.explicit) index.destroy(); else index.unlink(this, Value.prototype.set); } if (newDataset) { index = Index.getDatasetIndex(newDataset, this.indexConstructor); index.wrapperCount += 1; index.link(this, Value.prototype.set); index.addHandler(INDEXWRAPPER_HANDLER, this); } else { index = null; Value.prototype.set.call(this, this.initValue); } /** @cut */ basis.dev.patchInfo(this, 'sourceInfo', { /** @cut */ type: 'IndexWrapper', /** @cut */ source: index, /** @cut */ sourceTarget: source /** @cut */ }); this.dataset = newDataset; this.index = index; } }, set: function(){ /** @cut */ basis.dev.warn(this.className + ': value can\'t be set as IndexWrapper is read only'); }, destroy: function(){ this.source.bindingBridge.detach(this.source, basis.fn.$undef, this); this.setDataset(); Value.prototype.destroy.call(this); this.source = null; this.indexConstructor = null; } });
var MatchProperty = Value.subclass({ className: namespace + '.MatchProperty', matchFunction: function(child, reset){ if (!reset) { var textNodes = child._original || this.textNodeGetter(child); if (!Array.isArray(textNodes)) textNodes = [textNodes]; child._original = textNodes; var matchCount = 0; for (var i = textNodes.length; i-- > 0;) { var textNode = textNodes[i]; if (!textNode) continue; var p = textNode.nodeValue.split(this.rx); if (p.length > 1) { if (!child._replaced) child._replaced = {}; DOM.replace( child._replaced[i] || textNode, child._replaced[i] = DOM.createElement('SPAN.matched', DOM.wrap(p, this.map)) ); matchCount++; } else if (child._replaced && child._replaced[i]) { DOM.replace(child._replaced[i], textNode); delete child._replaced[i]; } } return matchCount > 0; } if (child._replaced) { for (var key in child._replaced) DOM.replace(child._replaced[key], child._original[key]); delete child._replaced; delete child._original; } return false; }, emit_change: function(oldValue){ this.rx = this.regexpGetter(this.value); Value.prototype.emit_change.call(this, oldValue); }, init: function(){ var startPoints = this.startPoints || ''; this.textNodeGetter = getter(this.textNodeGetter || defaultTextNodeGetter); if (typeof this.regexpGetter != 'function') this.regexpGetter = function(value){ return new RegExp('(' + startPoints + ')(' + basis.string.forRegExp(value) + ')', 'i'); }; this.map = {}; this.map[this.wrapElement || 'SPAN.match'] = function(v, i){ return (i % 3) == 2; }; Value.prototype.init.call(this, '', this.handlers, String.trim); } });
var Index = Value.subclass({ className: 'basis.data.index.Index', propertyDescriptors: { explicit: false, wrapperCount: false, updateEvents: false }, /** * Explicit declared * @type {boolean} */ explicit: false, /** * Count of wrapper indexes * @type {number} */ wrapperCount: 0, /** * Map of current values * @type {Object} * @private */ indexCache_: null, /** * @type {function(object)} */ valueGetter: basis.fn.$null, /** * Event names map when index must check for updates. * @type {Object} */ updateEvents: {}, /** * @inheritDocs */ value: 0, /** * @inheritDocs */ setNullOnEmitterDestroy: false, /** * @constructor */ init: function(){ this.indexCache_ = {}; Value.prototype.init.call(this); }, /** * Add value to index */ add_: function(value){ }, /** * Remove value to index */ remove_: function(value){ }, /** * Change value */ update_: function(newValue, oldValue){ }, /** * Normalize value to be computable. */ normalize: function(value){ return Number(value) || 0; }, destroy: function(){ Value.prototype.destroy.call(this); this.indexCache_ = null; } });