1
0
mirror of https://github.com/danbee/mpd-client synced 2025-03-04 08:39:09 +00:00

Update CanJS to 2.0.4.

This commit is contained in:
Dan Barber 2014-01-08 11:19:36 +00:00
parent 6bc65a23a8
commit ecdc1c8983
3 changed files with 396 additions and 270 deletions

View File

@ -1,8 +1,8 @@
/*!
* CanJS - 2.0.3
* CanJS - 2.0.4
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Thu, 19 Dec 2013 10:56:42 GMT
* Mon, 23 Dec 2013 19:49:28 GMT
* Licensed MIT
* Includes: can/view/ejs
* Download from: http://canjs.com

650
assets/js/libs/can.jquery.js Normal file → Executable file
View File

@ -1,8 +1,8 @@
/*!
* CanJS - 2.0.3
* CanJS - 2.0.4
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Thu, 19 Dec 2013 10:56:41 GMT
* Mon, 23 Dec 2013 19:49:25 GMT
* Licensed MIT
* Includes: can/component,can/construct,can/map,can/list,can/observe,can/compute,can/model,can/view,can/control,can/route,can/control/route,can/view/mustache,can/view/bindings,can/view/live,can/view/scope,can/util/string
* Download from: http://canjs.com
@ -30,7 +30,7 @@
return object._cid = (name || "") + (++cid)
}
}
can.VERSION = '2.0.3';
can.VERSION = '2.0.4';
can.simpleExtend = function(d, s) {
for (var prop in s) {
@ -58,6 +58,12 @@
}
}
} else if (elements.hasOwnProperty) {
if (can.Map && elements instanceof can.Map) {
can.__reading && can.__reading(elements, '__keys');
elements = elements.__get()
}
for (key in elements) {
if (elements.hasOwnProperty(key)) {
if (callback.call(context || elements[key], elements[key], key, elements) === false) {
@ -78,6 +84,8 @@
// Given a list of elements, check if they are in the dom, if they
// are in the dom, trigger inserted on them.
can.inserted = function(elems) {
// prevent mutations from changing the looping
elems = can.makeArray(elems);
var inDocument = false,
checked = false,
children;
@ -96,8 +104,8 @@
}
if (inDocument && elem.getElementsByTagName) {
can.trigger(elem, "inserted", [], false);
children = can.makeArray(elem.getElementsByTagName("*"));
can.trigger(elem, "inserted", [], false);
for (var j = 0, child;
(child = children[j]) !== undefined; j++) {
// Trigger the destroyed event
@ -356,6 +364,11 @@
}
return this;
},
proxy: function(fn, context) {
return function() {
return fn.apply(context, arguments)
}
}
});
@ -1240,27 +1253,6 @@
// A map that temporarily houses a reference
// to maps that have already been made for a plain ole JS object
madeMap = null,
addToMap = function(obj, instance) {
var teardown = false;
if (!madeMap) {
teardown = true;
madeMap = {}
}
// record if it has a Cid before we add one
var hasCid = obj._cid;
var cid = can.cid(obj);
// only update if there already isn't one
if (!madeMap[cid]) {
madeMap[cid] = {
obj: obj,
instance: instance,
added: !hasCid
}
}
return teardown;
},
teardownMap = function() {
for (var cid in madeMap) {
if (madeMap[cid].added) {
@ -1273,6 +1265,7 @@
return madeMap && madeMap[obj._cid] && madeMap[obj._cid].instance
};
var Map = can.Map = can.Construct.extend({
setup: function() {
@ -1284,9 +1277,13 @@
if (!this.defaults) {
this.defaults = {};
}
// a list of the compute properties
this._computes = [];
for (var prop in this.prototype) {
if (typeof this.prototype[prop] !== "function") {
this.defaults[prop] = this.prototype[prop];
} else if (this.prototype[prop].isComputed) {
this._computes.push(prop)
}
}
}
@ -1298,6 +1295,7 @@
}
},
_computes: [],
// keep so it can be overwritten
bind: can.bindAndSetup,
on: can.bindAndSetup,
@ -1305,6 +1303,28 @@
off: can.unbindAndTeardown,
id: "id",
helpers: {
addToMap: function(obj, instance) {
var teardown;
if (!madeMap) {
teardown = teardownMap;
madeMap = {}
}
// record if it has a Cid before we add one
var hasCid = obj._cid;
var cid = can.cid(obj);
// only update if there already isn't one
if (!madeMap[cid]) {
madeMap[cid] = {
obj: obj,
instance: instance,
added: !hasCid
}
}
return teardown;
},
canMakeObserve: function(obj) {
return obj && !can.isDeferred(obj) && (can.isArray(obj) || can.isPlainObject(obj) || (obj instanceof can.Map));
},
@ -1388,30 +1408,28 @@
// Sets all `attrs`.
this._init = 1;
this._setupComputes();
var teardownMapping = obj && addToMap(obj, this);
var teardownMapping = obj && can.Map.helpers.addToMap(obj, this);
var data = can.extend(can.extend(true, {}, this.constructor.defaults || {}), obj)
this.attr(data);
if (teardownMapping) {
teardownMap()
}
teardownMapping && teardownMapping()
this.bind('change', can.proxy(this._changes, this));
delete this._init;
},
_setupComputes: function() {
var prototype = this.constructor.prototype;
this._computedBindings = {}
for (var prop in prototype) {
if (prototype[prop] && prototype[prop].isComputed) {
this[prop] = prototype[prop].clone(this);
this._computedBindings[prop] = {
count: 0
}
var computes = this.constructor._computes;
this._computedBindings = {};
for (var i = 0, len = computes.length, prop; i < len; i++) {
prop = computes[i];
this[prop] = this[prop].clone(this);
this._computedBindings[prop] = {
count: 0
}
}
},
_bindsetup: makeBindSetup(),
_bindteardown: function() {
@ -1724,6 +1742,16 @@
// Helpers for `observable` lists.
var splice = [].splice,
// test if splice works correctly
spliceRemovesProps = (function() {
// IE's splice doesn't remove properties
var obj = {
0: "a",
length: 1
};
splice.call(obj, 0, 1);
return !obj[0];
})(),
list = Map(
@ -1738,11 +1766,18 @@
this.length = 0;
can.cid(this, ".map")
this._init = 1;
instances = instances || [];
if (can.isDeferred(instances)) {
this.replace(instances)
} else {
var teardownMapping = instances.length && can.Map.helpers.addToMap(instances, this);
this.push.apply(this, can.makeArray(instances || []));
}
teardownMapping && teardownMapping();
// this change needs to be ignored
this.bind('change', can.proxy(this._changes, this));
can.simpleExtend(this, options);
@ -1803,6 +1838,13 @@
howMany = args[1] = this.length - index;
}
var removed = splice.apply(this, args);
if (!spliceRemovesProps) {
for (var i = this.length; i < removed.length + this.length; i++) {
delete this[i]
}
}
can.batch.start();
if (howMany > 0) {
this._triggerChange("" + index, "remove", undefined, removed);
@ -1977,7 +2019,6 @@
return this;
}
});
can.List = Map.List = list;
return can.List;
})(__m2, __m12);
@ -3157,6 +3198,7 @@
// elements whos default value we should set
defaultValue: ["input", "textarea"],
// a map of parent element to child elements
tagMap: {
"": "span",
table: "tbody",
@ -3177,11 +3219,11 @@
th: "tr",
li: "ul"
},
// Used to determine the parentNode if el is directly within a documentFragment
getParentNode: function(el, defaultParentNode) {
return defaultParentNode && el.parentNode.nodeType === 11 ? defaultParentNode : el.parentNode;
},
// set an attribute on an element
// Set an attribute on an element
setAttr: function(el, attrName, val) {
var tagName = el.nodeName.toString().toLowerCase(),
prop = elements.attrMap[attrName];
@ -3200,14 +3242,14 @@
el.setAttribute(attrName, val);
}
},
// gets the value of an attribute
// Gets the value of an attribute.
getAttr: function(el, attrName) {
// Default to a blank string for IE7/8
return (elements.attrMap[attrName] && el[elements.attrMap[attrName]] ?
el[elements.attrMap[attrName]] :
el.getAttribute(attrName)) || '';
},
// removes the attribute
// Removes the attribute.
removeAttr: function(el, attrName) {
var setter = elements.attrMap[attrName];
if (typeof prop === "function") {
@ -3221,6 +3263,7 @@
el.removeAttribute(attrName);
}
},
// Gets a "pretty" value for something
contentText: function(text) {
if (typeof text == 'string') {
return text;
@ -3230,9 +3273,25 @@
return '';
}
return "" + text;
},
after: function(oldElements, newFrag) {
var last = oldElements[oldElements.length - 1];
// Insert it in the `document` or `documentFragment`
if (last.nextSibling) {
can.insertBefore(last.parentNode, newFrag, last.nextSibling)
} else {
can.appendChild(last.parentNode, newFrag);
}
},
replace: function(oldElements, newFrag) {
elements.after(oldElements, newFrag);
can.remove(can.$(oldElements));
}
};
// TODO: this doesn't seem to be doing anything
// feature detect if setAttribute works with styles
(function() {
// feature detect if
@ -3412,12 +3471,14 @@
fn(el);
});
var helperTags = hookupOptions.options.read('helpers._tags', {}).value,
tagName = hookupOptions.tagName,
tagCallback = (helperTags && helperTags[tagName]) || Scanner.tags[tagName]
var tagName = hookupOptions.tagName,
helperTagCallback = hookupOptions.options.read('helpers._tags.' + tagName, {
isArgument: true,
proxyMethods: false
}).value,
tagCallback = helperTagCallback || Scanner.tags[tagName];
// if this was an element like <foo-bar> that doesn't have a component, just render its content
// If this was an element like <foo-bar> that doesn't have a component, just render its content
var scope = hookupOptions.scope,
res = tagCallback ? tagCallback(el, hookupOptions) : scope;
@ -3707,7 +3768,10 @@
default:
// Track the current tag
if (lastToken === '<') {
tagName = token.split(/\s|!--/)[0];
tagName = token.substr(0, 3) === "!--" ?
"!--" : token.split(/\s/)[0];
var isClosingTag = false;
if (tagName.indexOf("/") === 0) {
@ -3905,10 +3969,11 @@
return Scanner;
})(__m19, __m21);
// ## view/node_lists.js
// ## view/node_lists/node_lists.js
var __m24 = (function(can) {
// text node expando test
// In some browsers, text nodes can not take expando properties.
// We test that here.
var canExpando = true;
try {
document.createTextNode('')._ = 0;
@ -3916,12 +3981,10 @@
canExpando = false;
}
// a mapping of element ids to nodeList ids
// A mapping of element ids to nodeList id
var nodeMap = {},
// a mapping of ids to text nodes
// A mapping of ids to text nodes
textNodeMap = {},
// a mapping of nodeList ids to nodeList
nodeListMap = {},
expando = "ejs_" + Math.random(),
_id = 0,
id = function(node) {
@ -3942,98 +4005,90 @@
return "text_" + _id;
}
},
// removes a nodeListId from a node's nodeListIds
removeNodeListId = function(node, nodeListId) {
var nodeListIds = nodeMap[id(node)];
if (nodeListIds) {
var index = can.inArray(nodeListId, nodeListIds);
splice = [].splice;
if (index >= 0) {
nodeListIds.splice(index, 1);
}
if (!nodeListIds.length) {
delete nodeMap[id(node)];
}
}
},
addNodeListId = function(node, nodeListId) {
var nodeListIds = nodeMap[id(node)];
if (!nodeListIds) {
nodeListIds = nodeMap[id(node)] = [];
}
nodeListIds.push(nodeListId);
};
var nodeLists = {
id: id,
// replaces the contents of one node list with the nodes in another list
replace: function(oldNodeList, newNodes) {
// for each node in the node list
oldNodeList = can.makeArray(oldNodeList);
// try every set
//can.each( oldNodeList, function(node){
var node = oldNodeList[0]
// for each nodeList the node is in
can.each(can.makeArray(nodeMap[id(node)]), function(nodeListId) {
// if startNode to endNode is
// within list, replace that list
// I think the problem is not the WHOLE part is being
// matched
var nodeList = nodeListMap[nodeListId],
startIndex = can.inArray(node, nodeList),
endIndex = can.inArray(oldNodeList[oldNodeList.length - 1], nodeList);
// remove this nodeListId from each node
if (startIndex >= 0 && endIndex >= 0) {
for (var i = startIndex; i <= endIndex; i++) {
var n = nodeList[i];
removeNodeListId(n, nodeListId);
}
// swap in new nodes into the nodeLIst
nodeList.splice.apply(nodeList, [startIndex, endIndex - startIndex + 1].concat(newNodes));
update: function(nodeList, newNodes) {
// Unregister all childNodes.
can.each(nodeList.childNodeLists, function(nodeList) {
nodeLists.unregister(nodeList)
})
nodeList.childNodeLists = [];
// tell these new nodes they belong to the nodeList
can.each(newNodes, function(node) {
addNodeListId(node, nodeListId);
});
} else {
nodeLists.unregister(nodeList);
// Remove old node pointers to this list.
can.each(nodeList, function(node) {
delete nodeMap[id(node)];
});
var newNodes = can.makeArray(newNodes);
// indicate the new nodes belong to this list
can.each(newNodes, function(node) {
nodeMap[id(node)] = nodeList;
});
var oldListLength = nodeList.length,
firstNode = nodeList[0];
// Replace oldNodeLists's contents'
splice.apply(nodeList, [0, oldListLength].concat(newNodes));
// update all parent nodes so they are able to replace the correct elements
var parentNodeList = nodeList;
while (parentNodeList = parentNodeList.parentNodeList) {
splice.apply(parentNodeList, [can.inArray(firstNode, parentNodeList), oldListLength].concat(newNodes));
}
},
register: function(nodeList, unregistered, parent) {
// add an id to the nodeList
nodeList.unregistered = unregistered,
nodeList.childNodeLists = [];
if (!parent) {
// find the parent by looking up where this node is
if (nodeList.length > 1) {
throw "does not work"
}
});
//});
},
// registers a list of nodes
register: function(nodeList) {
var nLId = id(nodeList);
nodeListMap[nLId] = nodeList;
can.each(nodeList, function(node) {
addNodeListId(node, nLId);
});
var nodeId = id(nodeList[0]);
parent = nodeMap[nodeId];
}
nodeList.parentNodeList = parent;
parent && parent.childNodeLists.push(nodeList);
return nodeList;
},
// removes mappings
// removes node in all parent nodes and unregisters all childNodes
unregister: function(nodeList) {
var nLId = id(nodeList);
can.each(nodeList, function(node) {
removeNodeListId(node, nLId);
});
delete nodeListMap[nLId];
if (!nodeList.isUnregistered) {
nodeList.isUnregistered = true;
// unregister all childNodeLists
delete nodeList.parentNodeList;
can.each(nodeList, function(node) {
var nodeId = id(node);
delete nodeMap[nodeId]
});
// this can unbind which will call itself
nodeList.unregistered && nodeList.unregistered();
can.each(nodeList.childNodeLists, function(nodeList) {
nodeLists.unregister(nodeList)
});
}
},
nodeMap: nodeMap,
nodeListMap: nodeListMap
}
var ids = function(nodeList) {
return nodeList.map(function(n) {
return id(n) + ":" + (n.innerHTML || n.nodeValue)
})
}
return nodeLists;
})(__m2);
})(__m2, __m21);
// ## view/live/live.js
var __m23 = (function(can, elements, view, nodeLists) {
@ -4048,12 +4103,21 @@
// `setup(HTMLElement, bind(data), unbind(data)) -> data`
// Calls bind right away, but will call unbind
// if the element is "destroyed" (removed from the DOM).
var setupCount = 0;
var setup = function(el, bind, unbind) {
var teardown = function() {
unbind(data)
can.unbind.call(el, 'removed', teardown);
return true
},
// Removing an element can call teardown which
// unregister the nodeList which calls teardown
var tornDown = false,
teardown = function() {
if (!tornDown) {
tornDown = true;
unbind(data)
can.unbind.call(el, 'removed', teardown);
}
return true
},
data = {
// returns true if no parent
teardownCheck: function(parent) {
@ -4083,65 +4147,82 @@
getAttributeParts = function(newVal) {
return (newVal || "").replace(/['"]/g, '').split('=')
},
// #### insertElementsAfter
// Appends elements after the last item in oldElements.
insertElementsAfter = function(oldElements, newFrag) {
var last = oldElements[oldElements.length - 1];
splice = [].splice;
// Insert it in the `document` or `documentFragment`
if (last.nextSibling) {
can.insertBefore(last.parentNode, newFrag, last.nextSibling)
} else {
can.appendChild(last.parentNode, newFrag);
}
};
var live = {
nodeLists: nodeLists,
list: function(el, compute, func, context, parentNode) {
// A mapping of the index to an array
// of elements that represent the item.
// Each array is registered so child or parent
// live structures can update the elements
var nodesMap = [],
// called when an item is added
list: function(el, compute, render, context, parentNode) {
// A nodeList of all elements this live-list manages.
// This is here so that if this live list is within another section
// that section is able to remove the items in this list.
var masterNodeList = [el],
// A mapping of the index of an item to an array
// of elements that represent the item.
// Each array is registered so child or parent
// live structures can update the elements.
itemIndexToNodeListsMap = [],
// A mapping of items to their indicies'
indexMap = [],
// Called when items are added to the list.
add = function(ev, items, index) {
// check that the placeholder textNode still has a parent.
// it's possible someone removed the contents of
// this element without removing the parent
if (data.teardownCheck(text.parentNode)) {
return
}
// Collect new html and mappings
var frag = document.createDocumentFragment(),
newMappings = [];
can.each(items, function(item, key) {
var itemHTML = func.call(context, item, (key + index)),
itemFrag = can.view.frag(itemHTML, parentNode);
newNodeLists = [],
newIndicies = [];
newMappings.push(can.makeArray(itemFrag.childNodes));
frag.appendChild(itemFrag);
// For each new item,
can.each(items, function(item, key) {
var itemIndex = can.compute(key + index),
// get its string content
itemHTML = render.call(context, item, itemIndex),
// and convert it into elements.
itemFrag = can.view.fragment(itemHTML)
// Add those elements to the mappings.
newNodeLists.push(
// Register those nodes with nodeLists.
nodeLists.register(can.makeArray(itemFrag.childNodes), undefined, masterNodeList));
// Hookup the fragment (which sets up child live-bindings) and
// add it to the collection of all added elements.
frag.appendChild(can.view.hookup(itemFrag));
newIndicies.push(itemIndex)
})
// Inserting at the end of the list
if (!nodesMap[index]) {
insertElementsAfter(
index == 0 ? [text] :
nodesMap[index - 1], frag)
// Check if we are adding items at the end
if (!itemIndexToNodeListsMap[index]) {
elements.after(
// If we are adding items to an empty list
index == 0 ?
// add those items after the placeholder text element.
[text] :
// otherwise, add them after the last element in the previous index.
itemIndexToNodeListsMap[index - 1], frag)
} else {
var el = nodesMap[index][0];
// Add elements before the next index's first element.
var el = itemIndexToNodeListsMap[index][0];
can.insertBefore(el.parentNode, frag, el);
}
// register each item
can.each(newMappings, function(nodeList) {
nodeLists.register(nodeList)
});
[].splice.apply(nodesMap, [index, 0].concat(newMappings));
splice.apply(itemIndexToNodeListsMap, [index, 0].concat(newNodeLists));
// update indices after insert point
splice.apply(indexMap, [index, 0].concat(newIndicies));
for (var i = index + newIndicies.length, len = indexMap.length; i < len; i++) {
indexMap[i](i)
}
},
// Remove can be called during teardown or when items are
// removed from the element.
// Called when items are removed or when the bindings are torn down.
remove = function(ev, items, index, duringTeardown) {
// If this is because an element was removed, we should
@ -4151,61 +4232,72 @@
return
}
var removedMappings = nodesMap.splice(index, items.length),
var removedMappings = itemIndexToNodeListsMap.splice(index, items.length),
itemsToRemove = [];
can.each(removedMappings, function(nodeList) {
// add items that we will remove all at once
[].push.apply(itemsToRemove, nodeList)
// Update any parent lists to remove these items
nodeLists.replace(nodeList, []);
nodeLists.update(nodeList, []);
// unregister the list
nodeLists.unregister(nodeList);
});
// update indices after remove point
indexMap.splice(index, items.length)
for (var i = index, len = indexMap.length; i < len; i++) {
indexMap[i](i)
}
can.remove(can.$(itemsToRemove));
},
parentNode = elements.getParentNode(el, parentNode),
text = document.createTextNode(""),
list;
// The current list.
list,
var teardownList = function() {
// there might be no list right away, and the list might be a plain
// array
list && list.unbind && list.unbind("add", add).unbind("remove", remove);
// use remove to clean stuff up for us
remove({}, {
length: nodesMap.length
}, 0, true);
}
// Called when the list is replaced with a new list or the binding is torn-down.
teardownList = function() {
// there might be no list right away, and the list might be a plain
// array
list && list.unbind && list.unbind("add", add).unbind("remove", remove);
// use remove to clean stuff up for us
remove({}, {
length: itemIndexToNodeListsMap.length
}, 0, true);
},
// Called when the list is replaced or setup.
updateList = function(ev, newList, oldList) {
teardownList();
// make an empty list if the compute returns null or undefined
list = newList || [];
// list might be a plain array
list.bind && list.bind("add", add).bind("remove", remove);
add({}, list, 0);
}
var updateList = function(ev, newList, oldList) {
teardownList();
// make an empty list if the compute returns null or undefined
list = newList || [];
// list might be a plain array
list.bind && list.bind("add", add).bind("remove", remove);
add({}, list, 0);
}
insertElementsAfter([el], text);
can.remove(can.$(el));
// Setup binding and teardown to add and remove events
// Setup binding and teardown to add and remove events
var data = setup(parentNode, function() {
can.isFunction(compute) && compute.bind("change", updateList)
}, function() {
can.isFunction(compute) && compute.unbind("change", updateList)
teardownList()
})
});
live.replace(masterNodeList, text, data.teardownCheck)
// run the list setup
updateList({}, can.isFunction(compute) ? compute() : compute)
},
html: function(el, compute, parentNode) {
var parentNode = elements.getParentNode(el, parentNode),
data = listen(parentNode, compute, function(ev, newVal, oldVal) {
// TODO: remove teardownCheck in 2.1
var attached = nodes[0].parentNode;
// update the nodes in the DOM with the new rendered value
if (attached) {
@ -4214,37 +4306,52 @@
data.teardownCheck(nodes[0].parentNode);
});
var nodes,
var nodes = [el],
makeAndPut = function(val) {
// create the fragment, but don't hook it up
// we need to insert it into the document first
var frag = can.view.frag(val, parentNode),
// keep a reference to each node
newNodes = can.makeArray(frag.childNodes);
// Insert it in the `document` or `documentFragment`
insertElementsAfter(nodes || [el], frag)
// nodes hasn't been set yet
if (!nodes) {
can.remove(can.$(el));
nodes = newNodes;
// set the teardown nodeList
data.nodeList = nodes;
nodeLists.register(nodes);
} else {
// Update node Array's to point to new nodes
// and then remove the old nodes.
// It has to be in this order for Mootools
// and IE because somehow, after an element
// is removed from the DOM, it loses its
// expando values.
var nodesToRemove = can.makeArray(nodes);
nodeLists.replace(nodes, newNodes);
can.remove(can.$(nodesToRemove));
}
var frag = can.view.fragment("" + val),
oldNodes = can.makeArray(nodes);
// We need to mark each node as belonging to the node list.
nodeLists.update(nodes, frag.childNodes)
frag = can.view.hookup(frag, parentNode)
elements.replace(oldNodes, frag)
};
makeAndPut(compute(), [el]);
data.nodeList = nodes;
// register the span so nodeLists knows the parentNodeList
nodeLists.register(nodes, data.teardownCheck)
makeAndPut(compute());
},
replace: function(nodes, val, teardown) {
var oldNodes = nodes.slice(0),
frag;
nodeLists.register(nodes, teardown);
if (typeof val === "string") {
frag = can.view.fragment(val)
} else if (val.nodeType !== 11) {
frag = document.createDocumentFragment();
frag.appendChild(val)
} else {
frag = val;
}
// We need to mark each node as belonging to the node list.
nodeLists.update(nodes, frag.childNodes)
if (typeof val === "string") {
// if it was a string, check for hookups
frag = can.view.hookup(frag, nodes[0].parentNode);
}
elements.replace(oldNodes, frag);
return nodes;
},
text: function(el, compute, parentNode) {
var parent = elements.getParentNode(el, parentNode);
@ -4254,20 +4361,16 @@
if (typeof node.nodeValue != 'unknown') {
node.nodeValue = "" + newVal;
}
// TODO: remove in 2.1
data.teardownCheck(node.parentNode);
});
}),
// The text node that will be updated
node = document.createTextNode(compute());
var node = document.createTextNode(compute());
if (el.parentNode !== parent) {
parent = el.parentNode;
parent.insertBefore(node, el);
parent.removeChild(el);
} else {
parent.insertBefore(node, el);
parent.removeChild(el);
}
// Replace the placeholder with the live node and do the nodeLists thing.
live.replace([el], node, data.teardownCheck);
},
attributes: function(el, compute, currentValue) {
var setAttrs = function(newVal) {
var parts = getAttributeParts(newVal),
@ -4372,6 +4475,8 @@
return /^["'].*["']$/.test(val) ? val.substr(1, val.length - 2) : val
}
can.view.live = live;
can.view.nodeLists = nodeLists;
can.view.elements = elements;
return live;
})(__m2, __m21, __m19, __m24);
@ -4538,6 +4643,7 @@
}
if (listData) {
unbind && unbind();
return "<" + tag + can.view.hook(function(el, parentNode) {
live.list(el, listData.list, listData.renderer, self, parentNode);
}) + "></" + tag + ">";
@ -4558,7 +4664,8 @@
if (status === 0 && !contentProp) {
// Return an element tag with a hookup in place of the content
return "<" + tag + can.view.hook(
escape ?
// if value is an object, it's likely something returned by .safeString
escape && typeof value != "object" ?
// If we are escaping, replace the parentNode with
// a text node who's value is `func`'s return value.
@ -5443,25 +5550,23 @@
// Implements the `each` built-in helper.
'each': function(expr, options) {
if (!expr) {
return;
}
// Check if this is a list or a compute that resolves to a list, and setup
// the incremental live-binding
if (expr.isComputed || isObserveLike(expr) && typeof expr.attr('length') !== 'undefined') {
return can.view.lists && can.view.lists(expr, function(item, key) {
// Create a compute that listens to whenever the index of the item in our list changes.
var index = function() {
var exprResolved = Mustache.resolve(expr),
fromIndex = key < (exprResolved).attr('length') ? key : undefined;
return (exprResolved).indexOf(item, fromIndex);
};
// First, see what we are dealing with. It's ok to read the compute
// because can.view.text is only temporarily binding to what is going on here.
// Calling can.view.lists prevents anything from listening on that compute.
var resolved = Mustache.resolve(expr);
if (resolved instanceof can.List) {
return can.view.lists && can.view.lists(expr, function(item, index) {
return options.fn(options.scope.add({
"@index": index
}).add(item));
});
}
expr = Mustache.resolve(expr);
expr = resolved;
if ( !! expr && isArrayLike(expr)) {
var result = [];
@ -5888,6 +5993,9 @@
scope: this.scope
});
var self = this;
// if this component has a template (that we've already converted to a renderer)
if (this.constructor.renderer) {
// add content to tags
@ -5899,15 +6007,33 @@
helpers._tags.content = function(el, rendererOptions) {
// first check if there was content within the custom tag
// otherwise, render what was within <content>, the default code
var subtemplate = hookupOptions.subtemplate || rendererOptions.subtemplate
var subtemplate = hookupOptions.subtemplate || rendererOptions.subtemplate;
if (subtemplate) {
var frag = can.view.frag(subtemplate(rendererOptions.scope, rendererOptions.options.add(helpers)));
can.insertBefore(el.parentNode, frag, el);
can.remove(can.$(el));
// rendererOptions.options is a scope of helpers where `<content>` was found, so
// the right helpers should already be available.
// However, _tags.content is going to point to this current content callback. We need to
// remove that so it will walk up the chain
delete helpers._tags.content;
can.view.live.replace([el], subtemplate(
// This is the context of where `<content>` was found
// which will have the the component's context
rendererOptions.scope,
rendererOptions.options));
// restore the content tag so it could potentially be used again (as in lists)
helpers._tags.content = arguments.callee;
}
}
// render the component's template
var frag = this.constructor.renderer(renderedScope, helpers);
var frag = this.constructor.renderer(renderedScope, hookupOptions.options.add(helpers));
} else {
// otherwise render the contents between the
var frag = can.view.frag(hookupOptions.subtemplate ? hookupOptions.subtemplate(renderedScope, hookupOptions.options.add(helpers)) : "");

File diff suppressed because one or more lines are too long