PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/bower_components/CanJS/steal/can/route/route.js

https://gitlab.com/alekhya484/example-project
JavaScript | 303 lines | 294 code | 1 blank | 8 comment | 59 complexity | 3dcbef0776e1bf0eb8c287db89bd1ff3 MD5 | raw file
  1. /*!
  2. * CanJS - 2.3.23
  3. * http://canjs.com/
  4. * Copyright (c) 2016 Bitovi
  5. * Fri, 08 Apr 2016 17:58:15 GMT
  6. * Licensed MIT
  7. */
  8. /*can@2.3.23#route/route*/
  9. steal('can/util', 'can/map', 'can/list', 'can/util/string/deparam', function (can) {
  10. var matcher = /\:([\w\.]+)/g, paramsMatcher = /^(?:&[^=]+=[^&]*)+/, makeProps = function (props) {
  11. var tags = [];
  12. can.each(props, function (val, name) {
  13. tags.push((name === 'className' ? 'class' : name) + '="' + (name === 'href' ? val : can.esc(val)) + '"');
  14. });
  15. return tags.join(' ');
  16. }, matchesData = function (route, data) {
  17. var count = 0, i = 0, defaults = {};
  18. for (var name in route.defaults) {
  19. if (route.defaults[name] === data[name]) {
  20. defaults[name] = 1;
  21. count++;
  22. }
  23. }
  24. for (; i < route.names.length; i++) {
  25. if (!data.hasOwnProperty(route.names[i])) {
  26. return -1;
  27. }
  28. if (!defaults[route.names[i]]) {
  29. count++;
  30. }
  31. }
  32. return count;
  33. }, location = window.location, wrapQuote = function (str) {
  34. return (str + '').replace(/([.?*+\^$\[\]\\(){}|\-])/g, '\\$1');
  35. }, each = can.each, extend = can.extend, stringify = function (obj) {
  36. if (obj && typeof obj === 'object') {
  37. if (obj instanceof can.Map) {
  38. obj = obj;
  39. } else {
  40. obj = can.isFunction(obj.slice) ? obj.slice() : can.extend({}, obj);
  41. }
  42. can.each(obj, function (val, prop) {
  43. obj[prop] = stringify(val);
  44. });
  45. } else if (obj !== undefined && obj !== null && can.isFunction(obj.toString)) {
  46. obj = obj.toString();
  47. }
  48. return obj;
  49. }, removeBackslash = function (str) {
  50. return str.replace(/\\/g, '');
  51. }, timer, curParams, lastHash, changingData, changedAttrs = [], onRouteDataChange = function (ev, attr, how, newval) {
  52. changingData = 1;
  53. changedAttrs.push(attr);
  54. clearTimeout(timer);
  55. timer = setTimeout(function () {
  56. changingData = 0;
  57. var serialized = can.route.data.serialize(), path = can.route.param(serialized, true);
  58. can.route._call('setURL', path, changedAttrs);
  59. can.batch.trigger(eventsObject, '__url', [
  60. path,
  61. lastHash
  62. ]);
  63. lastHash = path;
  64. changedAttrs = [];
  65. }, 10);
  66. }, eventsObject = can.extend({}, can.event), stringCoercingMapDecorator = function (map) {
  67. var attrSuper = map.attr;
  68. map.attr = function (prop, val) {
  69. var serializable = this.define === undefined || this.define[prop] === undefined || !!this.define[prop].serialize, args;
  70. if (serializable) {
  71. args = stringify(Array.apply(null, arguments));
  72. } else {
  73. args = arguments;
  74. }
  75. return attrSuper.apply(this, args);
  76. };
  77. return map;
  78. };
  79. can.route = function (url, defaults) {
  80. var root = can.route._call('root');
  81. if (root.lastIndexOf('/') === root.length - 1 && url.indexOf('/') === 0) {
  82. url = url.substr(1);
  83. }
  84. defaults = defaults || {};
  85. var names = [], res, test = '', lastIndex = matcher.lastIndex = 0, next, querySeparator = can.route._call('querySeparator'), matchSlashes = can.route._call('matchSlashes');
  86. while (res = matcher.exec(url)) {
  87. names.push(res[1]);
  88. test += removeBackslash(url.substring(lastIndex, matcher.lastIndex - res[0].length));
  89. next = '\\' + (removeBackslash(url.substr(matcher.lastIndex, 1)) || querySeparator + (matchSlashes ? '' : '|/'));
  90. test += '([^' + next + ']' + (defaults[res[1]] ? '*' : '+') + ')';
  91. lastIndex = matcher.lastIndex;
  92. }
  93. test += url.substr(lastIndex).replace('\\', '');
  94. can.route.routes[url] = {
  95. test: new RegExp('^' + test + '($|' + wrapQuote(querySeparator) + ')'),
  96. route: url,
  97. names: names,
  98. defaults: defaults,
  99. length: url.split('/').length
  100. };
  101. return can.route;
  102. };
  103. extend(can.route, {
  104. param: function (data, _setRoute) {
  105. var route, matches = 0, matchCount, routeName = data.route, propCount = 0;
  106. delete data.route;
  107. each(data, function () {
  108. propCount++;
  109. });
  110. each(can.route.routes, function (temp, name) {
  111. matchCount = matchesData(temp, data);
  112. if (matchCount > matches) {
  113. route = temp;
  114. matches = matchCount;
  115. }
  116. if (matchCount >= propCount) {
  117. return false;
  118. }
  119. });
  120. if (can.route.routes[routeName] && matchesData(can.route.routes[routeName], data) === matches) {
  121. route = can.route.routes[routeName];
  122. }
  123. if (route) {
  124. var cpy = extend({}, data), res = route.route.replace(matcher, function (whole, name) {
  125. delete cpy[name];
  126. return data[name] === route.defaults[name] ? '' : encodeURIComponent(data[name]);
  127. }).replace('\\', ''), after;
  128. each(route.defaults, function (val, name) {
  129. if (cpy[name] === val) {
  130. delete cpy[name];
  131. }
  132. });
  133. after = can.param(cpy);
  134. if (_setRoute) {
  135. can.route.attr('route', route.route);
  136. }
  137. return res + (after ? can.route._call('querySeparator') + after : '');
  138. }
  139. return can.isEmptyObject(data) ? '' : can.route._call('querySeparator') + can.param(data);
  140. },
  141. deparam: function (url) {
  142. var root = can.route._call('root');
  143. if (root.lastIndexOf('/') === root.length - 1 && url.indexOf('/') === 0) {
  144. url = url.substr(1);
  145. }
  146. var route = { length: -1 }, querySeparator = can.route._call('querySeparator'), paramsMatcher = can.route._call('paramsMatcher');
  147. each(can.route.routes, function (temp, name) {
  148. if (temp.test.test(url) && temp.length > route.length) {
  149. route = temp;
  150. }
  151. });
  152. if (route.length > -1) {
  153. var parts = url.match(route.test), start = parts.shift(), remainder = url.substr(start.length - (parts[parts.length - 1] === querySeparator ? 1 : 0)), obj = remainder && paramsMatcher.test(remainder) ? can.deparam(remainder.slice(1)) : {};
  154. obj = extend(true, {}, route.defaults, obj);
  155. each(parts, function (part, i) {
  156. if (part && part !== querySeparator) {
  157. obj[route.names[i]] = decodeURIComponent(part);
  158. }
  159. });
  160. obj.route = route.route;
  161. return obj;
  162. }
  163. if (url.charAt(0) !== querySeparator) {
  164. url = querySeparator + url;
  165. }
  166. return paramsMatcher.test(url) ? can.deparam(url.slice(1)) : {};
  167. },
  168. data: stringCoercingMapDecorator(new can.Map({})),
  169. map: function (data) {
  170. var appState;
  171. if (data.prototype instanceof can.Map) {
  172. appState = new data();
  173. } else {
  174. appState = data;
  175. }
  176. can.route.data = stringCoercingMapDecorator(appState);
  177. },
  178. routes: {},
  179. ready: function (val) {
  180. if (val !== true) {
  181. can.route._setup();
  182. if (can.isBrowserWindow || can.isWebWorker) {
  183. can.route.setState();
  184. }
  185. }
  186. return can.route;
  187. },
  188. url: function (options, merge) {
  189. if (merge) {
  190. can.__observe(eventsObject, '__url');
  191. options = can.extend({}, can.route.deparam(can.route._call('matchingPartOfURL')), options);
  192. }
  193. return can.route._call('root') + can.route.param(options);
  194. },
  195. link: function (name, options, props, merge) {
  196. return '<a ' + makeProps(extend({ href: can.route.url(options, merge) }, props)) + '>' + name + '</a>';
  197. },
  198. current: function (options) {
  199. can.__observe(eventsObject, '__url');
  200. return this._call('matchingPartOfURL') === can.route.param(options);
  201. },
  202. bindings: {
  203. hashchange: {
  204. paramsMatcher: paramsMatcher,
  205. querySeparator: '&',
  206. matchSlashes: false,
  207. bind: function () {
  208. can.bind.call(window, 'hashchange', setState);
  209. },
  210. unbind: function () {
  211. can.unbind.call(window, 'hashchange', setState);
  212. },
  213. matchingPartOfURL: function () {
  214. var loc = can.route.location || location;
  215. return loc.href.split(/#!?/)[1] || '';
  216. },
  217. setURL: function (path) {
  218. if (location.hash !== '#' + path) {
  219. location.hash = '!' + path;
  220. }
  221. return path;
  222. },
  223. root: '#!'
  224. }
  225. },
  226. defaultBinding: 'hashchange',
  227. currentBinding: null,
  228. _setup: function () {
  229. if (!can.route.currentBinding) {
  230. can.route._call('bind');
  231. can.route.bind('change', onRouteDataChange);
  232. can.route.currentBinding = can.route.defaultBinding;
  233. }
  234. },
  235. _teardown: function () {
  236. if (can.route.currentBinding) {
  237. can.route._call('unbind');
  238. can.route.unbind('change', onRouteDataChange);
  239. can.route.currentBinding = null;
  240. }
  241. clearTimeout(timer);
  242. changingData = 0;
  243. },
  244. _call: function () {
  245. var args = can.makeArray(arguments), prop = args.shift(), binding = can.route.bindings[can.route.currentBinding || can.route.defaultBinding], method = binding[prop];
  246. if (method.apply) {
  247. return method.apply(binding, args);
  248. } else {
  249. return method;
  250. }
  251. }
  252. });
  253. each([
  254. 'bind',
  255. 'unbind',
  256. 'on',
  257. 'off',
  258. 'delegate',
  259. 'undelegate',
  260. 'removeAttr',
  261. 'compute',
  262. '_get',
  263. '___get',
  264. 'each'
  265. ], function (name) {
  266. can.route[name] = function () {
  267. if (!can.route.data[name]) {
  268. return;
  269. }
  270. return can.route.data[name].apply(can.route.data, arguments);
  271. };
  272. });
  273. can.route.attr = function () {
  274. return can.route.data.attr.apply(can.route.data, arguments);
  275. };
  276. can.route.batch = can.batch;
  277. var setState = can.route.setState = function () {
  278. var hash = can.route._call('matchingPartOfURL');
  279. var oldParams = curParams;
  280. curParams = can.route.deparam(hash);
  281. if (!changingData || hash !== lastHash) {
  282. can.route.batch.start();
  283. recursiveClean(oldParams, curParams, can.route.data);
  284. can.route.attr(curParams);
  285. can.route.batch.trigger(eventsObject, '__url', [
  286. hash,
  287. lastHash
  288. ]);
  289. can.route.batch.stop();
  290. }
  291. };
  292. var recursiveClean = function (old, cur, data) {
  293. for (var attr in old) {
  294. if (cur[attr] === undefined) {
  295. data.removeAttr(attr);
  296. } else if (Object.prototype.toString.call(old[attr]) === '[object Object]') {
  297. recursiveClean(old[attr], cur[attr], data.attr(attr));
  298. }
  299. }
  300. };
  301. return can.route;
  302. });