mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
132 lines
6.9 KiB
JavaScript
132 lines
6.9 KiB
JavaScript
(() => {
|
|
// A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
|
|
// logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
|
|
//
|
|
// Two are provided by default:
|
|
// 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element
|
|
// 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
|
|
// without reading/writing the actual element text content, since it will be overwritten
|
|
// with the rendered template output.
|
|
// You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
|
|
// Template sources need to have the following functions:
|
|
// text() - returns the template text from your storage location
|
|
// text(value) - writes the supplied template text to your storage location
|
|
// data(key) - reads values stored using data(key, value) - see below
|
|
// data(key, value) - associates "value" with this template and the key "key". Is used to store information like "isRewritten".
|
|
//
|
|
// Optionally, template sources can also have the following functions:
|
|
// nodes() - returns a DOM element containing the nodes of this template, where available
|
|
// nodes(value) - writes the given DOM element to your storage location
|
|
// If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
|
|
// for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
|
|
//
|
|
// Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
|
|
// using and overriding "makeTemplateSource" to return an instance of your custom template source.
|
|
|
|
ko.templateSources = {};
|
|
|
|
// ---- ko.templateSources.domElement -----
|
|
|
|
// template types
|
|
var templateScript = 1,
|
|
templateTextArea = 2,
|
|
templateTemplate = 3,
|
|
templateElement = 4;
|
|
|
|
ko.templateSources.domElement = function(element) {
|
|
this.domElement = element;
|
|
|
|
if (element) {
|
|
var tagNameLower = ko.utils.tagNameLower(element);
|
|
this.templateType =
|
|
tagNameLower === "script" ? templateScript :
|
|
tagNameLower === "textarea" ? templateTextArea :
|
|
// For browsers with proper <template> element support, where the .content property gives a document fragment
|
|
tagNameLower == "template" && element.content && element.content.nodeType === 11 ? templateTemplate :
|
|
templateElement;
|
|
}
|
|
}
|
|
|
|
ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
|
|
var elemContentsProperty = this.templateType === templateScript ? "text"
|
|
: this.templateType === templateTextArea ? "value"
|
|
: "innerHTML";
|
|
|
|
if (arguments.length == 0) {
|
|
return this.domElement[elemContentsProperty];
|
|
}
|
|
var valueToWrite = arguments[0];
|
|
if (elemContentsProperty === "innerHTML")
|
|
ko.utils.setHtml(this.domElement, valueToWrite);
|
|
else
|
|
this.domElement[elemContentsProperty] = valueToWrite;
|
|
};
|
|
|
|
var dataDomDataPrefix = ko.utils.domData.nextKey() + "_";
|
|
ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
|
|
if (arguments.length === 1) {
|
|
return ko.utils.domData.get(this.domElement, dataDomDataPrefix + key);
|
|
}
|
|
ko.utils.domData.set(this.domElement, dataDomDataPrefix + key, arguments[1]);
|
|
};
|
|
|
|
var templatesDomDataKey = ko.utils.domData.nextKey();
|
|
function getTemplateDomData(element) {
|
|
return ko.utils.domData.get(element, templatesDomDataKey) || {};
|
|
}
|
|
function setTemplateDomData(element, data) {
|
|
ko.utils.domData.set(element, templatesDomDataKey, data);
|
|
}
|
|
|
|
ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
|
|
var element = this.domElement;
|
|
if (arguments.length == 0) {
|
|
var templateData = getTemplateDomData(element),
|
|
nodes = templateData.containerData || (
|
|
this.templateType === templateTemplate ? element.content :
|
|
this.templateType === templateElement ? element :
|
|
undefined);
|
|
if (!nodes || templateData.alwaysCheckText) {
|
|
// If the template is associated with an element that stores the template as text,
|
|
// parse and cache the nodes whenever there's new text content available. This allows
|
|
// the user to update the template content by updating the text of template node.
|
|
var text = this['text']();
|
|
if (text && text !== templateData.textData) {
|
|
nodes = ko.utils.parseHtmlForTemplateNodes(text, element.ownerDocument);
|
|
setTemplateDomData(element, {containerData: nodes, textData: text, alwaysCheckText: true});
|
|
}
|
|
}
|
|
return nodes;
|
|
}
|
|
var valueToWrite = arguments[0];
|
|
if (this.templateType !== undefined) {
|
|
this['text'](""); // clear the text from the node
|
|
}
|
|
setTemplateDomData(element, {containerData: valueToWrite});
|
|
};
|
|
|
|
// ---- ko.templateSources.anonymousTemplate -----
|
|
// Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
|
|
// For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
|
|
// Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
|
|
|
|
ko.templateSources.anonymousTemplate = function(element) {
|
|
this.domElement = element;
|
|
};
|
|
ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
|
|
ko.templateSources.anonymousTemplate.prototype.constructor = ko.templateSources.anonymousTemplate;
|
|
ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
|
|
if (arguments.length == 0) {
|
|
var templateData = getTemplateDomData(this.domElement);
|
|
if (templateData.textData === undefined && templateData.containerData)
|
|
templateData.textData = templateData.containerData.innerHTML;
|
|
return templateData.textData;
|
|
}
|
|
var valueToWrite = arguments[0];
|
|
setTemplateDomData(this.domElement, {textData: valueToWrite});
|
|
};
|
|
|
|
ko.exportSymbol('templateSources', ko.templateSources);
|
|
ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
|
|
ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
|
|
})();
|