can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
129 lines (128 loc) • 4.49 kB
JavaScript
/*!
* CanJS - 2.3.34
* http://canjs.com/
* Copyright (c) 2018 Bitovi
* Mon, 30 Apr 2018 20:56:51 GMT
* Licensed MIT
*/
/*can@2.3.34#view/stache/html_section*/
define([
'can/util/library',
'can/view/target',
'can/view/utils',
'can/view/mustache_core'
], function (can, target, utils, mustacheCore) {
var decodeHTML = typeof document !== 'undefined' && function () {
var el = document.createElement('div');
return function (html) {
if (html.indexOf('&') === -1) {
return html.replace(/\r\n/g, '\n');
}
el.innerHTML = html;
return el.childNodes.length === 0 ? '' : el.childNodes.item(0).nodeValue;
};
}();
var HTMLSectionBuilder = function () {
this.stack = [new HTMLSection()];
};
can.extend(HTMLSectionBuilder.prototype, utils.mixins);
can.extend(HTMLSectionBuilder.prototype, {
startSubSection: function (process) {
var newSection = new HTMLSection(process);
this.stack.push(newSection);
return newSection;
},
endSubSectionAndReturnRenderer: function () {
if (this.last().isEmpty()) {
this.stack.pop();
return null;
} else {
var htmlSection = this.endSection();
return can.proxy(htmlSection.compiled.hydrate, htmlSection.compiled);
}
},
startSection: function (process) {
var newSection = new HTMLSection(process);
this.last().add(newSection.targetCallback);
this.stack.push(newSection);
},
endSection: function () {
this.last().compile();
return this.stack.pop();
},
inverse: function () {
this.last().inverse();
},
compile: function () {
var compiled = this.stack.pop().compile();
return function (scope, options, nodeList) {
if (!(scope instanceof can.view.Scope)) {
scope = can.view.Scope.refsScope().add(scope || {});
}
if (!(options instanceof mustacheCore.Options)) {
options = new mustacheCore.Options(options || {});
}
return compiled.hydrate(scope, options, nodeList);
};
},
push: function (chars) {
this.last().push(chars);
},
pop: function () {
return this.last().pop();
}
});
var HTMLSection = function (process) {
this.data = 'targetData';
this.targetData = [];
this.targetStack = [];
var self = this;
this.targetCallback = function (scope, options, sectionNode) {
process.call(this, scope, options, sectionNode, can.proxy(self.compiled.hydrate, self.compiled), self.inverseCompiled && can.proxy(self.inverseCompiled.hydrate, self.inverseCompiled));
};
};
can.extend(HTMLSection.prototype, {
inverse: function () {
this.inverseData = [];
this.data = 'inverseData';
},
push: function (data) {
this.add(data);
this.targetStack.push(data);
},
pop: function () {
return this.targetStack.pop();
},
add: function (data) {
if (typeof data === 'string') {
data = decodeHTML(data);
}
if (this.targetStack.length) {
can.last(this.targetStack).children.push(data);
} else {
this[this.data].push(data);
}
},
compile: function () {
this.compiled = target(this.targetData, can.document || can.global.document);
if (this.inverseData) {
this.inverseCompiled = target(this.inverseData, can.document || can.global.document);
delete this.inverseData;
}
this.targetStack = this.targetData = null;
return this.compiled;
},
children: function () {
if (this.targetStack.length) {
return can.last(this.targetStack).children;
} else {
return this[this.data];
}
},
isEmpty: function () {
return !this.targetData.length;
}
});
HTMLSectionBuilder.HTMLSection = HTMLSection;
return HTMLSectionBuilder;
});