PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/android applications/24 1 2016 .net server/server1/server1/Scripts/knockout-2.1.0.debug.js

https://gitlab.com/orsanawwad/HackerULessonProjects
JavaScript | 1138 lines | 907 code | 136 blank | 95 comment | 258 complexity | e83122301f60f44223ec8e23a44b2b83 MD5 | raw file
  1. // Knockout JavaScript library v2.1.0
  2. // (c) Steven Sanderson - http://knockoutjs.com/
  3. // License: MIT (http://www.opensource.org/licenses/mit-license.php)
  4. (function(window,document,navigator,undefined){
  5. var DEBUG=true;
  6. !function(factory) {
  7. // Support three module loading scenarios
  8. if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  9. // [1] CommonJS/Node.js
  10. var target = module['exports'] || exports; // module.exports is for Node.js
  11. factory(target);
  12. } else if (typeof define === 'function' && define['amd']) {
  13. // [2] AMD anonymous module
  14. define(['exports'], factory);
  15. } else {
  16. // [3] No module loader (plain <script> tag) - put directly in global namespace
  17. factory(window['ko'] = {});
  18. }
  19. }(function(koExports){
  20. // Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
  21. // In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
  22. var ko = typeof koExports !== 'undefined' ? koExports : {};
  23. // Google Closure Compiler helpers (used only to make the minified file smaller)
  24. ko.exportSymbol = function(koPath, object) {
  25. var tokens = koPath.split(".");
  26. // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
  27. // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
  28. var target = ko;
  29. for (var i = 0; i < tokens.length - 1; i++)
  30. target = target[tokens[i]];
  31. target[tokens[tokens.length - 1]] = object;
  32. };
  33. ko.exportProperty = function(owner, publicName, object) {
  34. owner[publicName] = object;
  35. };
  36. ko.version = "2.1.0";
  37. ko.exportSymbol('version', ko.version);
  38. ko.utils = new (function () {
  39. var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  40. // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
  41. var knownEvents = {}, knownEventTypesByEventName = {};
  42. var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
  43. knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
  44. knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
  45. for (var eventType in knownEvents) {
  46. var knownEventsForType = knownEvents[eventType];
  47. if (knownEventsForType.length) {
  48. for (var i = 0, j = knownEventsForType.length; i < j; i++)
  49. knownEventTypesByEventName[knownEventsForType[i]] = eventType;
  50. }
  51. }
  52. var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
  53. // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
  54. var ieVersion = (function() {
  55. var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
  56. // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
  57. while (
  58. div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
  59. iElems[0]
  60. );
  61. return version > 4 ? version : undefined;
  62. }());
  63. var isIe6 = ieVersion === 6,
  64. isIe7 = ieVersion === 7;
  65. function isClickOnCheckableElement(element, eventType) {
  66. if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  67. if (eventType.toLowerCase() != "click") return false;
  68. var inputType = element.type;
  69. return (inputType == "checkbox") || (inputType == "radio");
  70. }
  71. return {
  72. fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  73. arrayForEach: function (array, action) {
  74. for (var i = 0, j = array.length; i < j; i++)
  75. action(array[i]);
  76. },
  77. arrayIndexOf: function (array, item) {
  78. if (typeof Array.prototype.indexOf == "function")
  79. return Array.prototype.indexOf.call(array, item);
  80. for (var i = 0, j = array.length; i < j; i++)
  81. if (array[i] === item)
  82. return i;
  83. return -1;
  84. },
  85. arrayFirst: function (array, predicate, predicateOwner) {
  86. for (var i = 0, j = array.length; i < j; i++)
  87. if (predicate.call(predicateOwner, array[i]))
  88. return array[i];
  89. return null;
  90. },
  91. arrayRemoveItem: function (array, itemToRemove) {
  92. var index = ko.utils.arrayIndexOf(array, itemToRemove);
  93. if (index >= 0)
  94. array.splice(index, 1);
  95. },
  96. arrayGetDistinctValues: function (array) {
  97. array = array || [];
  98. var result = [];
  99. for (var i = 0, j = array.length; i < j; i++) {
  100. if (ko.utils.arrayIndexOf(result, array[i]) < 0)
  101. result.push(array[i]);
  102. }
  103. return result;
  104. },
  105. arrayMap: function (array, mapping) {
  106. array = array || [];
  107. var result = [];
  108. for (var i = 0, j = array.length; i < j; i++)
  109. result.push(mapping(array[i]));
  110. return result;
  111. },
  112. arrayFilter: function (array, predicate) {
  113. array = array || [];
  114. var result = [];
  115. for (var i = 0, j = array.length; i < j; i++)
  116. if (predicate(array[i]))
  117. result.push(array[i]);
  118. return result;
  119. },
  120. arrayPushAll: function (array, valuesToPush) {
  121. if (valuesToPush instanceof Array)
  122. array.push.apply(array, valuesToPush);
  123. else
  124. for (var i = 0, j = valuesToPush.length; i < j; i++)
  125. array.push(valuesToPush[i]);
  126. return array;
  127. },
  128. extend: function (target, source) {
  129. if (source) {
  130. for(var prop in source) {
  131. if(source.hasOwnProperty(prop)) {
  132. target[prop] = source[prop];
  133. }
  134. }
  135. }
  136. return target;
  137. },
  138. emptyDomNode: function (domNode) {
  139. while (domNode.firstChild) {
  140. ko.removeNode(domNode.firstChild);
  141. }
  142. },
  143. moveCleanedNodesToContainerElement: function(nodes) {
  144. // Ensure it's a real array, as we're about to reparent the nodes and
  145. // we don't want the underlying collection to change while we're doing that.
  146. var nodesArray = ko.utils.makeArray(nodes);
  147. var container = document.createElement('div');
  148. for (var i = 0, j = nodesArray.length; i < j; i++) {
  149. ko.cleanNode(nodesArray[i]);
  150. container.appendChild(nodesArray[i]);
  151. }
  152. return container;
  153. },
  154. setDomNodeChildren: function (domNode, childNodes) {
  155. ko.utils.emptyDomNode(domNode);
  156. if (childNodes) {
  157. for (var i = 0, j = childNodes.length; i < j; i++)
  158. domNode.appendChild(childNodes[i]);
  159. }
  160. },
  161. replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
  162. var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
  163. if (nodesToReplaceArray.length > 0) {
  164. var insertionPoint = nodesToReplaceArray[0];
  165. var parent = insertionPoint.parentNode;
  166. for (var i = 0, j = newNodesArray.length; i < j; i++)
  167. parent.insertBefore(newNodesArray[i], insertionPoint);
  168. for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
  169. ko.removeNode(nodesToReplaceArray[i]);
  170. }
  171. }
  172. },
  173. setOptionNodeSelectionState: function (optionNode, isSelected) {
  174. // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
  175. if (navigator.userAgent.indexOf("MSIE 6") >= 0)
  176. optionNode.setAttribute("selected", isSelected);
  177. else
  178. optionNode.selected = isSelected;
  179. },
  180. stringTrim: function (string) {
  181. return (string || "").replace(stringTrimRegex, "");
  182. },
  183. stringTokenize: function (string, delimiter) {
  184. var result = [];
  185. var tokens = (string || "").split(delimiter);
  186. for (var i = 0, j = tokens.length; i < j; i++) {
  187. var trimmed = ko.utils.stringTrim(tokens[i]);
  188. if (trimmed !== "")
  189. result.push(trimmed);
  190. }
  191. return result;
  192. },
  193. stringStartsWith: function (string, startsWith) {
  194. string = string || "";
  195. if (startsWith.length > string.length)
  196. return false;
  197. return string.substring(0, startsWith.length) === startsWith;
  198. },
  199. buildEvalWithinScopeFunction: function (expression, scopeLevels) {
  200. // Build the source for a function that evaluates "expression"
  201. // For each scope variable, add an extra level of "with" nesting
  202. // Example result: with(sc[1]) { with(sc[0]) { return (expression) } }
  203. var functionBody = "return (" + expression + ")";
  204. for (var i = 0; i < scopeLevels; i++) {
  205. functionBody = "with(sc[" + i + "]) { " + functionBody + " } ";
  206. }
  207. return new Function("sc", functionBody);
  208. },
  209. domNodeIsContainedBy: function (node, containedByNode) {
  210. if (containedByNode.compareDocumentPosition)
  211. return (containedByNode.compareDocumentPosition(node) & 16) == 16;
  212. while (node != null) {
  213. if (node == containedByNode)
  214. return true;
  215. node = node.parentNode;
  216. }
  217. return false;
  218. },
  219. domNodeIsAttachedToDocument: function (node) {
  220. return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
  221. },
  222. tagNameLower: function(element) {
  223. // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
  224. // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
  225. // we don't need to do the .toLowerCase() as it will always be lower case anyway.
  226. return element && element.tagName && element.tagName.toLowerCase();
  227. },
  228. registerEventHandler: function (element, eventType, handler) {
  229. var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
  230. if (!mustUseAttachEvent && typeof jQuery != "undefined") {
  231. if (isClickOnCheckableElement(element, eventType)) {
  232. // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
  233. // it toggles the element checked state *after* the click event handlers run, whereas native
  234. // click events toggle the checked state *before* the event handler.
  235. // Fix this by intecepting the handler and applying the correct checkedness before it runs.
  236. var originalHandler = handler;
  237. handler = function(event, eventData) {
  238. var jQuerySuppliedCheckedState = this.checked;
  239. if (eventData)
  240. this.checked = eventData.checkedStateBeforeEvent !== true;
  241. originalHandler.call(this, event);
  242. this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
  243. };
  244. }
  245. jQuery(element)['bind'](eventType, handler);
  246. } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
  247. element.addEventListener(eventType, handler, false);
  248. else if (typeof element.attachEvent != "undefined")
  249. element.attachEvent("on" + eventType, function (event) {
  250. handler.call(element, event);
  251. });
  252. else
  253. throw new Error("Browser doesn't support addEventListener or attachEvent");
  254. },
  255. triggerEvent: function (element, eventType) {
  256. if (!(element && element.nodeType))
  257. throw new Error("element must be a DOM node when calling triggerEvent");
  258. if (typeof jQuery != "undefined") {
  259. var eventData = [];
  260. if (isClickOnCheckableElement(element, eventType)) {
  261. // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
  262. eventData.push({ checkedStateBeforeEvent: element.checked });
  263. }
  264. jQuery(element)['trigger'](eventType, eventData);
  265. } else if (typeof document.createEvent == "function") {
  266. if (typeof element.dispatchEvent == "function") {
  267. var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
  268. var event = document.createEvent(eventCategory);
  269. event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
  270. element.dispatchEvent(event);
  271. }
  272. else
  273. throw new Error("The supplied element doesn't support dispatchEvent");
  274. } else if (typeof element.fireEvent != "undefined") {
  275. // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
  276. // so to make it consistent, we'll do it manually here
  277. if (isClickOnCheckableElement(element, eventType))
  278. element.checked = element.checked !== true;
  279. element.fireEvent("on" + eventType);
  280. }
  281. else
  282. throw new Error("Browser doesn't support triggering events");
  283. },
  284. unwrapObservable: function (value) {
  285. return ko.isObservable(value) ? value() : value;
  286. },
  287. toggleDomNodeCssClass: function (node, className, shouldHaveClass) {
  288. var currentClassNames = (node.className || "").split(/\s+/);
  289. var hasClass = ko.utils.arrayIndexOf(currentClassNames, className) >= 0;
  290. if (shouldHaveClass && !hasClass) {
  291. node.className += (currentClassNames[0] ? " " : "") + className;
  292. } else if (hasClass && !shouldHaveClass) {
  293. var newClassName = "";
  294. for (var i = 0; i < currentClassNames.length; i++)
  295. if (currentClassNames[i] != className)
  296. newClassName += currentClassNames[i] + " ";
  297. node.className = ko.utils.stringTrim(newClassName);
  298. }
  299. },
  300. setTextContent: function(element, textContent) {
  301. var value = ko.utils.unwrapObservable(textContent);
  302. if ((value === null) || (value === undefined))
  303. value = "";
  304. 'innerText' in element ? element.innerText = value
  305. : element.textContent = value;
  306. if (ieVersion >= 9) {
  307. // Believe it or not, this actually fixes an IE9 rendering bug
  308. // (See https://github.com/SteveSanderson/knockout/issues/209)
  309. element.style.display = element.style.display;
  310. }
  311. },
  312. ensureSelectElementIsRenderedCorrectly: function(selectElement) {
  313. // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
  314. // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
  315. if (ieVersion >= 9) {
  316. var originalWidth = selectElement.style.width;
  317. selectElement.style.width = 0;
  318. selectElement.style.width = originalWidth;
  319. }
  320. },
  321. range: function (min, max) {
  322. min = ko.utils.unwrapObservable(min);
  323. max = ko.utils.unwrapObservable(max);
  324. var result = [];
  325. for (var i = min; i <= max; i++)
  326. result.push(i);
  327. return result;
  328. },
  329. makeArray: function(arrayLikeObject) {
  330. var result = [];
  331. for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
  332. result.push(arrayLikeObject[i]);
  333. };
  334. return result;
  335. },
  336. isIe6 : isIe6,
  337. isIe7 : isIe7,
  338. ieVersion : ieVersion,
  339. getFormFields: function(form, fieldName) {
  340. var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
  341. var isMatchingField = (typeof fieldName == 'string')
  342. ? function(field) { return field.name === fieldName }
  343. : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
  344. var matches = [];
  345. for (var i = fields.length - 1; i >= 0; i--) {
  346. if (isMatchingField(fields[i]))
  347. matches.push(fields[i]);
  348. };
  349. return matches;
  350. },
  351. parseJson: function (jsonString) {
  352. if (typeof jsonString == "string") {
  353. jsonString = ko.utils.stringTrim(jsonString);
  354. if (jsonString) {
  355. if (window.JSON && window.JSON.parse) // Use native parsing where available
  356. return window.JSON.parse(jsonString);
  357. return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
  358. }
  359. }
  360. return null;
  361. },
  362. stringifyJson: function (data, replacer, space) { // replacer and space are optional
  363. if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
  364. throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
  365. return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
  366. },
  367. postJson: function (urlOrForm, data, options) {
  368. options = options || {};
  369. var params = options['params'] || {};
  370. var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
  371. var url = urlOrForm;
  372. // If we were given a form, use its 'action' URL and pick out any requested field values
  373. if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
  374. var originalForm = urlOrForm;
  375. url = originalForm.action;
  376. for (var i = includeFields.length - 1; i >= 0; i--) {
  377. var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
  378. for (var j = fields.length - 1; j >= 0; j--)
  379. params[fields[j].name] = fields[j].value;
  380. }
  381. }
  382. data = ko.utils.unwrapObservable(data);
  383. var form = document.createElement("form");
  384. form.style.display = "none";
  385. form.action = url;
  386. form.method = "post";
  387. for (var key in data) {
  388. var input = document.createElement("input");
  389. input.name = key;
  390. input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
  391. form.appendChild(input);
  392. }
  393. for (var key in params) {
  394. var input = document.createElement("input");
  395. input.name = key;
  396. input.value = params[key];
  397. form.appendChild(input);
  398. }
  399. document.body.appendChild(form);
  400. options['submitter'] ? options['submitter'](form) : form.submit();
  401. setTimeout(function () { form.parentNode.removeChild(form); }, 0);
  402. }
  403. }
  404. })();
  405. ko.exportSymbol('utils', ko.utils);
  406. ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
  407. ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
  408. ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
  409. ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
  410. ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
  411. ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
  412. ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
  413. ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
  414. ko.exportSymbol('utils.extend', ko.utils.extend);
  415. ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
  416. ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
  417. ko.exportSymbol('utils.postJson', ko.utils.postJson);
  418. ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
  419. ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
  420. ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
  421. ko.exportSymbol('utils.range', ko.utils.range);
  422. ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
  423. ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
  424. ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
  425. if (!Function.prototype['bind']) {
  426. // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
  427. // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
  428. Function.prototype['bind'] = function (object) {
  429. var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  430. return function () {
  431. return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
  432. };
  433. };
  434. }
  435. ko.utils.domData = new (function () {
  436. var uniqueId = 0;
  437. var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
  438. var dataStore = {};
  439. return {
  440. get: function (node, key) {
  441. var allDataForNode = ko.utils.domData.getAll(node, false);
  442. return allDataForNode === undefined ? undefined : allDataForNode[key];
  443. },
  444. set: function (node, key, value) {
  445. if (value === undefined) {
  446. // Make sure we don't actually create a new domData key if we are actually deleting a value
  447. if (ko.utils.domData.getAll(node, false) === undefined)
  448. return;
  449. }
  450. var allDataForNode = ko.utils.domData.getAll(node, true);
  451. allDataForNode[key] = value;
  452. },
  453. getAll: function (node, createIfNotFound) {
  454. var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
  455. var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null");
  456. if (!hasExistingDataStore) {
  457. if (!createIfNotFound)
  458. return undefined;
  459. dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
  460. dataStore[dataStoreKey] = {};
  461. }
  462. return dataStore[dataStoreKey];
  463. },
  464. clear: function (node) {
  465. var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
  466. if (dataStoreKey) {
  467. delete dataStore[dataStoreKey];
  468. node[dataStoreKeyExpandoPropertyName] = null;
  469. }
  470. }
  471. }
  472. })();
  473. ko.exportSymbol('utils.domData', ko.utils.domData);
  474. ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
  475. ko.utils.domNodeDisposal = new (function () {
  476. var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
  477. var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document
  478. var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
  479. function getDisposeCallbacksCollection(node, createIfNotFound) {
  480. var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
  481. if ((allDisposeCallbacks === undefined) && createIfNotFound) {
  482. allDisposeCallbacks = [];
  483. ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
  484. }
  485. return allDisposeCallbacks;
  486. }
  487. function destroyCallbacksCollection(node) {
  488. ko.utils.domData.set(node, domDataKey, undefined);
  489. }
  490. function cleanSingleNode(node) {
  491. // Run all the dispose callbacks
  492. var callbacks = getDisposeCallbacksCollection(node, false);
  493. if (callbacks) {
  494. callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
  495. for (var i = 0; i < callbacks.length; i++)
  496. callbacks[i](node);
  497. }
  498. // Also erase the DOM data
  499. ko.utils.domData.clear(node);
  500. // Special support for jQuery here because it's so commonly used.
  501. // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
  502. // so notify it to tear down any resources associated with the node & descendants here.
  503. if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
  504. jQuery['cleanData']([node]);
  505. // Also clear any immediate-child comment nodes, as these wouldn't have been found by
  506. // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
  507. if (cleanableNodeTypesWithDescendants[node.nodeType])
  508. cleanImmediateCommentTypeChildren(node);
  509. }
  510. function cleanImmediateCommentTypeChildren(nodeWithChildren) {
  511. var child, nextChild = nodeWithChildren.firstChild;
  512. while (child = nextChild) {
  513. nextChild = child.nextSibling;
  514. if (child.nodeType === 8)
  515. cleanSingleNode(child);
  516. }
  517. }
  518. return {
  519. addDisposeCallback : function(node, callback) {
  520. if (typeof callback != "function")
  521. throw new Error("Callback must be a function");
  522. getDisposeCallbacksCollection(node, true).push(callback);
  523. },
  524. removeDisposeCallback : function(node, callback) {
  525. var callbacksCollection = getDisposeCallbacksCollection(node, false);
  526. if (callbacksCollection) {
  527. ko.utils.arrayRemoveItem(callbacksCollection, callback);
  528. if (callbacksCollection.length == 0)
  529. destroyCallbacksCollection(node);
  530. }
  531. },
  532. cleanNode : function(node) {
  533. // First clean this node, where applicable
  534. if (cleanableNodeTypes[node.nodeType]) {
  535. cleanSingleNode(node);
  536. // ... then its descendants, where applicable
  537. if (cleanableNodeTypesWithDescendants[node.nodeType]) {
  538. // Clone the descendants list in case it changes during iteration
  539. var descendants = [];
  540. ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
  541. for (var i = 0, j = descendants.length; i < j; i++)
  542. cleanSingleNode(descendants[i]);
  543. }
  544. }
  545. },
  546. removeNode : function(node) {
  547. ko.cleanNode(node);
  548. if (node.parentNode)
  549. node.parentNode.removeChild(node);
  550. }
  551. }
  552. })();
  553. ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
  554. ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
  555. ko.exportSymbol('cleanNode', ko.cleanNode);
  556. ko.exportSymbol('removeNode', ko.removeNode);
  557. ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
  558. ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
  559. ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
  560. (function () {
  561. var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
  562. function simpleHtmlParse(html) {
  563. // Based on jQuery's "clean" function, but only accounting for table-related elements.
  564. // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
  565. // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
  566. // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
  567. // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
  568. // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
  569. // Trim whitespace, otherwise indexOf won't work as expected
  570. var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
  571. // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
  572. var wrap = tags.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "</table>"] ||
  573. !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] ||
  574. (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
  575. /* anything else */ [0, "", ""];
  576. // Go to html and back, then peel off extra wrappers
  577. // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
  578. var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
  579. if (typeof window['innerShiv'] == "function") {
  580. div.appendChild(window['innerShiv'](markup));
  581. } else {
  582. div.innerHTML = markup;
  583. }
  584. // Move to the right depth
  585. while (wrap[0]--)
  586. div = div.lastChild;
  587. return ko.utils.makeArray(div.lastChild.childNodes);
  588. }
  589. function jQueryHtmlParse(html) {
  590. var elems = jQuery['clean']([html]);
  591. // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
  592. // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
  593. // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
  594. if (elems && elems[0]) {
  595. // Find the top-most parent element that's a direct child of a document fragment
  596. var elem = elems[0];
  597. while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
  598. elem = elem.parentNode;
  599. // ... then detach it
  600. if (elem.parentNode)
  601. elem.parentNode.removeChild(elem);
  602. }
  603. return elems;
  604. }
  605. ko.utils.parseHtmlFragment = function(html) {
  606. return typeof jQuery != 'undefined' ? jQueryHtmlParse(html) // As below, benefit from jQuery's optimisations where possible
  607. : simpleHtmlParse(html); // ... otherwise, this simple logic will do in most common cases.
  608. };
  609. ko.utils.setHtml = function(node, html) {
  610. ko.utils.emptyDomNode(node);
  611. if ((html !== null) && (html !== undefined)) {
  612. if (typeof html != 'string')
  613. html = html.toString();
  614. // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
  615. // for example <tr> elements which are not normally allowed to exist on their own.
  616. // If you've referenced jQuery we'll use that rather than duplicating its code.
  617. if (typeof jQuery != 'undefined') {
  618. jQuery(node)['html'](html);
  619. } else {
  620. // ... otherwise, use KO's own parsing logic.
  621. var parsedNodes = ko.utils.parseHtmlFragment(html);
  622. for (var i = 0; i < parsedNodes.length; i++)
  623. node.appendChild(parsedNodes[i]);
  624. }
  625. }
  626. };
  627. })();
  628. ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
  629. ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
  630. ko.memoization = (function () {
  631. var memos = {};
  632. function randomMax8HexChars() {
  633. return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
  634. }
  635. function generateRandomId() {
  636. return randomMax8HexChars() + randomMax8HexChars();
  637. }
  638. function findMemoNodes(rootNode, appendToArray) {
  639. if (!rootNode)
  640. return;
  641. if (rootNode.nodeType == 8) {
  642. var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
  643. if (memoId != null)
  644. appendToArray.push({ domNode: rootNode, memoId: memoId });
  645. } else if (rootNode.nodeType == 1) {
  646. for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
  647. findMemoNodes(childNodes[i], appendToArray);
  648. }
  649. }
  650. return {
  651. memoize: function (callback) {
  652. if (typeof callback != "function")
  653. throw new Error("You can only pass a function to ko.memoization.memoize()");
  654. var memoId = generateRandomId();
  655. memos[memoId] = callback;
  656. return "<!--[ko_memo:" + memoId + "]-->";
  657. },
  658. unmemoize: function (memoId, callbackParams) {
  659. var callback = memos[memoId];
  660. if (callback === undefined)
  661. throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
  662. try {
  663. callback.apply(null, callbackParams || []);
  664. return true;
  665. }
  666. finally { delete memos[memoId]; }
  667. },
  668. unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
  669. var memos = [];
  670. findMemoNodes(domNode, memos);
  671. for (var i = 0, j = memos.length; i < j; i++) {
  672. var node = memos[i].domNode;
  673. var combinedParams = [node];
  674. if (extraCallbackParamsArray)
  675. ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
  676. ko.memoization.unmemoize(memos[i].memoId, combinedParams);
  677. node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
  678. if (node.parentNode)
  679. node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
  680. }
  681. },
  682. parseMemoText: function (memoText) {
  683. var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
  684. return match ? match[1] : null;
  685. }
  686. };
  687. })();
  688. ko.exportSymbol('memoization', ko.memoization);
  689. ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
  690. ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
  691. ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
  692. ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
  693. ko.extenders = {
  694. 'throttle': function(target, timeout) {
  695. // Throttling means two things:
  696. // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
  697. // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
  698. target['throttleEvaluation'] = timeout;
  699. // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
  700. // so the target cannot change value synchronously or faster than a certain rate
  701. var writeTimeoutInstance = null;
  702. return ko.dependentObservable({
  703. 'read': target,
  704. 'write': function(value) {
  705. clearTimeout(writeTimeoutInstance);
  706. writeTimeoutInstance = setTimeout(function() {
  707. target(value);
  708. }, timeout);
  709. }
  710. });
  711. },
  712. 'notify': function(target, notifyWhen) {
  713. target["equalityComparer"] = notifyWhen == "always"
  714. ? function() { return false } // Treat all values as not equal
  715. : ko.observable["fn"]["equalityComparer"];
  716. return target;
  717. }
  718. };
  719. function applyExtenders(requestedExtenders) {
  720. var target = this;
  721. if (requestedExtenders) {
  722. for (var key in requestedExtenders) {
  723. var extenderHandler = ko.extenders[key];
  724. if (typeof extenderHandler == 'function') {
  725. target = extenderHandler(target, requestedExtenders[key]);
  726. }
  727. }
  728. }
  729. return target;
  730. }
  731. ko.exportSymbol('extenders', ko.extenders);
  732. ko.subscription = function (target, callback, disposeCallback) {
  733. this.target = target;
  734. this.callback = callback;
  735. this.disposeCallback = disposeCallback;
  736. ko.exportProperty(this, 'dispose', this.dispose);
  737. };
  738. ko.subscription.prototype.dispose = function () {
  739. this.isDisposed = true;
  740. this.disposeCallback();
  741. };
  742. ko.subscribable = function () {
  743. this._subscriptions = {};
  744. ko.utils.extend(this, ko.subscribable['fn']);
  745. ko.exportProperty(this, 'subscribe', this.subscribe);
  746. ko.exportProperty(this, 'extend', this.extend);
  747. ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
  748. }
  749. var defaultEvent = "change";
  750. ko.subscribable['fn'] = {
  751. subscribe: function (callback, callbackTarget, event) {
  752. event = event || defaultEvent;
  753. var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
  754. var subscription = new ko.subscription(this, boundCallback, function () {
  755. ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
  756. }.bind(this));
  757. if (!this._subscriptions[event])
  758. this._subscriptions[event] = [];
  759. this._subscriptions[event].push(subscription);
  760. return subscription;
  761. },
  762. "notifySubscribers": function (valueToNotify, event) {
  763. event = event || defaultEvent;
  764. if (this._subscriptions[event]) {
  765. ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
  766. // In case a subscription was disposed during the arrayForEach cycle, check
  767. // for isDisposed on each subscription before invoking its callback
  768. if (subscription && (subscription.isDisposed !== true))
  769. subscription.callback(valueToNotify);
  770. });
  771. }
  772. },
  773. getSubscriptionsCount: function () {
  774. var total = 0;
  775. for (var eventName in this._subscriptions) {
  776. if (this._subscriptions.hasOwnProperty(eventName))
  777. total += this._subscriptions[eventName].length;
  778. }
  779. return total;
  780. },
  781. extend: applyExtenders
  782. };
  783. ko.isSubscribable = function (instance) {
  784. return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
  785. };
  786. ko.exportSymbol('subscribable', ko.subscribable);
  787. ko.exportSymbol('isSubscribable', ko.isSubscribable);
  788. ko.dependencyDetection = (function () {
  789. var _frames = [];
  790. return {
  791. begin: function (callback) {
  792. _frames.push({ callback: callback, distinctDependencies:[] });
  793. },
  794. end: function () {
  795. _frames.pop();
  796. },
  797. registerDependency: function (subscribable) {
  798. if (!ko.isSubscribable(subscribable))
  799. throw new Error("Only subscribable things can act as dependencies");
  800. if (_frames.length > 0) {
  801. var topFrame = _frames[_frames.length - 1];
  802. if (ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
  803. return;
  804. topFrame.distinctDependencies.push(subscribable);
  805. topFrame.callback(subscribable);
  806. }
  807. }
  808. };
  809. })();
  810. var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
  811. ko.observable = function (initialValue) {
  812. var _latestValue = initialValue;
  813. function observable() {
  814. if (arguments.length > 0) {
  815. // Write
  816. // Ignore writes if the value hasn't changed
  817. if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
  818. observable.valueWillMutate();
  819. _latestValue = arguments[0];
  820. if (DEBUG) observable._latestValue = _latestValue;
  821. observable.valueHasMutated();
  822. }
  823. return this; // Permits chained assignments
  824. }
  825. else {
  826. // Read
  827. ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
  828. return _latestValue;
  829. }
  830. }
  831. if (DEBUG) observable._latestValue = _latestValue;
  832. ko.subscribable.call(observable);
  833. observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
  834. observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
  835. ko.utils.extend(observable, ko.observable['fn']);
  836. ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
  837. ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
  838. return observable;
  839. }
  840. ko.observable['fn'] = {
  841. "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
  842. var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
  843. return oldValueIsPrimitive ? (a === b) : false;
  844. }
  845. };
  846. var protoProperty = ko.observable.protoProperty = "__ko_proto__";
  847. ko.observable['fn'][protoProperty] = ko.observable;
  848. ko.hasPrototype = function(instance, prototype) {
  849. if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
  850. if (instance[protoProperty] === prototype) return true;
  851. return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
  852. };
  853. ko.isObservable = function (instance) {
  854. return ko.hasPrototype(instance, ko.observable);
  855. }
  856. ko.isWriteableObservable = function (instance) {
  857. // Observable
  858. if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
  859. return true;
  860. // Writeable dependent observable
  861. if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
  862. return true;
  863. // Anything else
  864. return false;
  865. }
  866. ko.exportSymbol('observable', ko.observable);
  867. ko.exportSymbol('isObservable', ko.isObservable);
  868. ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
  869. ko.observableArray = function (initialValues) {
  870. if (arguments.length == 0) {
  871. // Zero-parameter constructor initializes to empty array
  872. initialValues = [];
  873. }
  874. if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
  875. throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
  876. var result = ko.observable(initialValues);
  877. ko.utils.extend(result, ko.observableArray['fn']);
  878. return result;
  879. }
  880. ko.observableArray['fn'] = {
  881. 'remove': function (valueOrPredicate) {
  882. var underlyingArray = this();
  883. var removedValues = [];
  884. var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
  885. for (var i = 0; i < underlyingArray.length; i++) {
  886. var value = underlyingArray[i];
  887. if (predicate(value)) {
  888. if (removedValues.length === 0) {
  889. this.valueWillMutate();
  890. }
  891. removedValues.push(value);
  892. underlyingArray.splice(i, 1);
  893. i--;
  894. }
  895. }
  896. if (removedValues.length) {
  897. this.valueHasMutated();
  898. }
  899. return removedValues;
  900. },
  901. 'removeAll': function (arrayOfValues) {
  902. // If you passed zero args, we remove everything
  903. if (arrayOfValues === undefined) {
  904. var underlyingArray = this();
  905. var allValues = underlyingArray.slice(0);
  906. this.valueWillMutate();
  907. underlyingArray.splice(0, underlyingArray.length);
  908. this.valueHasMutated();
  909. return allValues;
  910. }
  911. // If you passed an arg, we interpret it as an array of entries to remove
  912. if (!arrayOfValues)
  913. return [];
  914. return this['remove'](function (value) {
  915. return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
  916. });
  917. },
  918. 'destroy': function (valueOrPredicate) {
  919. var underlyingArray = this();
  920. var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
  921. this.valueWillMutate();
  922. for (var i = underlyingArray.length - 1; i >= 0; i--) {
  923. var value = underlyingArray[i];
  924. if (predicate(value))
  925. underlyingArray[i]["_destroy"] = true;
  926. }
  927. this.valueHasMutated();
  928. },
  929. 'destroyAll': function (arrayOfValues) {
  930. // If you passed zero args, we destroy everything
  931. if (arrayOfValues === undefined)
  932. return this['destroy'](function() { return true });
  933. // If you passed an arg, we interpret it as an array of entries to destroy
  934. if (!arrayOfValues)
  935. return [];
  936. return this['destroy'](function (value) {
  937. return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
  938. });
  939. },
  940. 'indexOf': function (item) {
  941. var underlyingArray = this();
  942. return ko.utils.arrayIndexOf(underlyingArray, item);
  943. },
  944. 'replace': function(oldItem, newItem) {
  945. var index = this['indexOf'](oldItem);
  946. if (index >= 0) {
  947. this.valueWillMutate();
  948. this()[index] = newItem;
  949. this.valueHasMutated();
  950. }
  951. }
  952. }
  953. // Populate ko.observableArray.fn with read/write functions from native arrays
  954. ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
  955. ko.observableArray['fn'][methodName] = function () {
  956. var underlyingArray = this();
  957. this.valueWillMutate();
  958. var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
  959. this.valueHasMutated();
  960. return methodCallResult;
  961. };
  962. });
  963. // Populate ko.observableArray.fn with read-only functions from native arrays
  964. ko.utils.arrayForEach(["slice"], function (methodName) {
  965. ko.observableArray['fn'][methodName] = function () {
  966. var underlyingArray = this();
  967. return underlyingArray[methodName].apply(underlyingArray, arguments);
  968. };
  969. });
  970. ko.exportSymbol('observableArray', ko.observableArray);
  971. ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
  972. var _latestValue,
  973. _hasBeenEvaluated = false,
  974. _isBeingEvaluated = false,
  975. readFunction = evaluatorFunctionOrOptions;
  976. if (readFunction && typeof readFunction == "object") {
  977. // Single-parameter syntax - everything is on this "options" param
  978. options = readFunction;
  979. readFunction = options["read"];
  980. } else {
  981. // Multi-parameter syntax - construct the options according to the params passed
  982. options = options || {};
  983. if (!readFunction)
  984. readFunction = options["read"];
  985. }
  986. // By here, "options" is always non-null
  987. if (typeof readFunction != "function")
  988. throw new Error("Pass a function that returns the value of the ko.computed");
  989. var writeFunction = options["write"];
  990. if (!evaluatorFunctionTarget)
  991. evaluatorFunctionTarget = options["owner"];
  992. var _subscriptionsToDependencies = [];
  993. function disposeAllSubscriptionsToDependencies() {
  994. ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
  995. subscription.dispose();
  996. });
  997. _subscriptionsToDependencies = [];
  998. }
  999. var dispose = disposeAllSubscriptionsToDependencies;
  1000. // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values
  1001. // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
  1002. // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node