UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

185 lines (184 loc) 7.34 kB
/*! * 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/target/target*/ define([ 'can/util/library', 'can/elements' ], function (can, elements, vdom) { var processNodes = function (nodes, paths, location, document) { var frag = document.createDocumentFragment(); for (var i = 0, len = nodes.length; i < len; i++) { var node = nodes[i]; frag.appendChild(processNode(node, paths, location.concat(i), document)); } return frag; }, keepsTextNodes = typeof document !== 'undefined' && function () { var testFrag = document.createDocumentFragment(); var div = document.createElement('div'); div.appendChild(document.createTextNode('')); div.appendChild(document.createTextNode('')); testFrag.appendChild(div); var cloned = testFrag.cloneNode(true); return can.childNodes(cloned.firstChild).length === 2; }(), clonesWork = typeof document !== 'undefined' && function () { var a = document.createElement('a'); a.innerHTML = '<xyz></xyz>'; var clone = a.cloneNode(true); return clone.innerHTML === '<xyz></xyz>'; }(), namespacesWork = typeof document !== 'undefined' && !!document.createElementNS, setAttribute = can.attr.setAttribute; var cloneNode = clonesWork ? function (el) { return el.cloneNode(true); } : function (node) { var copy; if (node.nodeType === 1) { copy = document.createElement(node.nodeName); } else if (node.nodeType === 3) { copy = document.createTextNode(node.nodeValue); } else if (node.nodeType === 8) { copy = document.createComment(node.nodeValue); } else if (node.nodeType === 11) { copy = document.createDocumentFragment(); } if (node.attributes) { var attributes = can.makeArray(node.attributes); can.each(attributes, function (node) { if (node && node.specified) { setAttribute(copy, node.nodeName, node.nodeValue); } }); } if (node.childNodes) { can.each(node.childNodes, function (child) { copy.appendChild(cloneNode(child)); }); } return copy; }; function processNode(node, paths, location, document) { var callback, loc = location, nodeType = typeof node, el, p, i, len; var getCallback = function () { if (!callback) { callback = { path: location, callbacks: [] }; paths.push(callback); loc = []; } return callback; }; var setAttr = function (el, attr) { var value = node.attrs[attr]; if (typeof value === 'function') { getCallback().callbacks.push({ callback: value }); } else { setAttribute(el, attr, value); } }; if (nodeType === 'object') { if (node.tag) { if (namespacesWork && node.namespace) { el = document.createElementNS(node.namespace, node.tag); } else { el = document.createElement(node.tag); } if (node.attrs) { if (node.tag === 'input' && node.attrs.type) { setAttr(el, 'type'); delete node.attrs.type; } for (var attrName in node.attrs) { setAttr(el, attrName); } } if (node.attributes) { for (i = 0, len = node.attributes.length; i < len; i++) { getCallback().callbacks.push({ callback: node.attributes[i] }); } } if (node.children && node.children.length) { if (callback) { p = callback.paths = []; } else { p = paths; } el.appendChild(processNodes(node.children, p, loc, document)); } } else if (node.comment) { el = document.createComment(node.comment); if (node.callbacks) { for (i = 0, len = node.attributes.length; i < len; i++) { getCallback().callbacks.push({ callback: node.callbacks[i] }); } } } } else if (nodeType === 'string') { el = document.createTextNode(node); } else if (nodeType === 'function') { if (keepsTextNodes) { el = document.createTextNode(''); getCallback().callbacks.push({ callback: node }); } else { el = document.createComment('~'); getCallback().callbacks.push({ callback: function () { var el = document.createTextNode(''); elements.replace([this], el); return node.apply(el, arguments); } }); } } return el; } function getCallbacks(el, pathData, elementCallbacks) { var path = pathData.path, callbacks = pathData.callbacks, paths = pathData.paths, child = el, pathLength = path ? path.length : 0, pathsLength = paths ? paths.length : 0; for (var i = 0; i < pathLength; i++) { child = child.childNodes.item(path[i]); } for (i = 0; i < pathsLength; i++) { getCallbacks(child, paths[i], elementCallbacks); } elementCallbacks.push({ element: child, callbacks: callbacks }); } function hydrateCallbacks(callbacks, args) { var len = callbacks.length, callbacksLength, callbackElement, callbackData; for (var i = 0; i < len; i++) { callbackData = callbacks[i]; callbacksLength = callbackData.callbacks.length; callbackElement = callbackData.element; for (var c = 0; c < callbacksLength; c++) { callbackData.callbacks[c].callback.apply(callbackElement, args); } } } function makeTarget(nodes, doc) { var paths = []; var frag = processNodes(nodes, paths, [], doc || can.global.document); return { paths: paths, clone: frag, hydrate: function () { var cloned = cloneNode(this.clone); var args = can.makeArray(arguments); var callbacks = []; for (var i = 0; i < paths.length; i++) { getCallbacks(cloned, paths[i], callbacks); } hydrateCallbacks(callbacks, args); return cloned; } }; } makeTarget.keepsTextNodes = keepsTextNodes; can.view.target = makeTarget; return makeTarget; });