PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/webshim/1.15.9/dev/shims/url.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 327 lines | 266 code | 37 blank | 24 comment | 46 complexity | d7b2d7b6b777b46751701d99f609f889 MD5 | raw file
  1. webshim.register('url', function($, webshims, window, document, undefined, options){
  2. 'use strict';
  3. // URL Polyfill
  4. // Draft specification: http://url.spec.whatwg.org
  5. // Notes:
  6. // - Primarily useful for parsing URLs and modifying query parameters
  7. // - Should work in IE8+ and everything more modern
  8. (function (global) {
  9. // Browsers may have:
  10. // * No global URL object
  11. // * URL with static methods only - may have a dummy constructor
  12. // * URL with members except searchParams
  13. // * Full URL API support
  14. var origURL = global.URL;
  15. var nativeURL;
  16. try {
  17. if (origURL) {
  18. nativeURL = new global.URL('http://example.com');
  19. if ('searchParams' in nativeURL)
  20. return;
  21. if (!('href' in nativeURL))
  22. nativeURL = undefined;
  23. }
  24. } catch (_) {}
  25. function URLUtils(url) {
  26. if (nativeURL)
  27. return new origURL(url);
  28. var anchor = document.createElement('a');
  29. anchor.href = url;
  30. return anchor;
  31. }
  32. global.URL = function URL(url, base) {
  33. if (!(this instanceof global.URL))
  34. throw new TypeError("Failed to construct 'URL': Please use the 'new' operator.");
  35. if (base) {
  36. url = (function () {
  37. if (nativeURL) return new origURL(url, base).href;
  38. var doc;
  39. // Use another document/base tag/anchor for relative URL resolution, if possible
  40. if (document.implementation && document.implementation.createHTMLDocument) {
  41. doc = document.implementation.createHTMLDocument('');
  42. } else if (document.implementation && document.implementation.createDocument) {
  43. doc = document.implementation.createElement('http://www.w3.org/1999/xhtml', 'html', null);
  44. doc.documentElement.appendChild(doc.createElement('head'));
  45. doc.documentElement.appendChild(doc.createElement('body'));
  46. } else if (window.ActiveXObject) {
  47. doc = new window.ActiveXObject('htmlfile');
  48. doc.write('<head></head><body></body>');
  49. doc.close();
  50. }
  51. if (!doc) throw Error('base not supported');
  52. var baseTag = doc.createElement('base');
  53. baseTag.href = base;
  54. doc.getElementsByTagName('head')[0].appendChild(baseTag);
  55. var anchor = doc.createElement('a');
  56. anchor.href = url;
  57. return anchor.href;
  58. }());
  59. }
  60. // An inner object implementing URLUtils (either a native URL
  61. // object or an HTMLAnchorElement instance) is used to perform the
  62. // URL algorithms. With full ES5 getter/setter support, return a
  63. // regular object For IE8's limited getter/setter support, a
  64. // different HTMLAnchorElement is returned with properties
  65. // overridden
  66. var instance = URLUtils(url || '');
  67. // Detect for ES5 getter/setter support
  68. var ES5_GET_SET = (Object.defineProperties && (function () {
  69. var o = {}; Object.defineProperties(o, { p: { 'get': function () { return true; } } }); return o.p;
  70. }()));
  71. var self = ES5_GET_SET ? this : document.createElement('a');
  72. // NOTE: Doesn't do the encoding/decoding dance
  73. function parse(input, isindex) {
  74. var sequences = input.split('&');
  75. if (isindex && sequences[0].indexOf('=') === -1)
  76. sequences[0] = '=' + sequences[0];
  77. var pairs = [];
  78. sequences.forEach(function (bytes) {
  79. if (bytes.length === 0) return;
  80. var index = bytes.indexOf('=');
  81. if (index !== -1) {
  82. var name = bytes.substring(0, index);
  83. var value = bytes.substring(index + 1);
  84. } else {
  85. name = bytes;
  86. value = '';
  87. }
  88. name = name.replace(/\+/g, ' ');
  89. value = value.replace(/\+/g, ' ');
  90. pairs.push({ name: name, value: value });
  91. });
  92. var output = [];
  93. pairs.forEach(function (pair) {
  94. output.push({
  95. name: decodeURIComponent(pair.name),
  96. value: decodeURIComponent(pair.value)
  97. });
  98. });
  99. return output;
  100. }
  101. function URLSearchParams(url_object, init) {
  102. var pairs = [];
  103. if (init)
  104. pairs = parse(init);
  105. this._setPairs = function (list) { pairs = list; };
  106. this._updateSteps = function () { updateSteps(); };
  107. var updating = false;
  108. function updateSteps() {
  109. if (updating) return;
  110. updating = true;
  111. // TODO: For all associated url objects
  112. url_object.search = serialize(pairs);
  113. updating = false;
  114. }
  115. // NOTE: Doesn't do the encoding/decoding dance
  116. function serialize(pairs) {
  117. var output = '', first = true;
  118. pairs.forEach(function (pair) {
  119. var name = encodeURIComponent(pair.name);
  120. var value = encodeURIComponent(pair.value);
  121. if (!first) output += '&';
  122. output += name + '=' + value;
  123. first = false;
  124. });
  125. return output.replace(/%20/g, '+');
  126. }
  127. Object.defineProperties(this, {
  128. append: {
  129. value: function (name, value) {
  130. pairs.push({ name: name, value: value });
  131. updateSteps();
  132. }
  133. },
  134. 'delete': {
  135. value: function (name) {
  136. for (var i = 0; i < pairs.length;) {
  137. if (pairs[i].name === name)
  138. pairs.splice(i, 1);
  139. else
  140. ++i;
  141. }
  142. updateSteps();
  143. }
  144. },
  145. get: {
  146. value: function (name) {
  147. for (var i = 0; i < pairs.length; ++i) {
  148. if (pairs[i].name === name)
  149. return pairs[i].value;
  150. }
  151. return null;
  152. }
  153. },
  154. getAll: {
  155. value: function (name) {
  156. var result = [];
  157. for (var i = 0; i < pairs.length; ++i) {
  158. if (pairs[i].name === name)
  159. result.push(pairs[i].value);
  160. }
  161. return result;
  162. }
  163. },
  164. has: {
  165. value: function (name) {
  166. for (var i = 0; i < pairs.length; ++i) {
  167. if (pairs[i].name === name)
  168. return true;
  169. }
  170. return false;
  171. }
  172. },
  173. set: {
  174. value: function (name, value) {
  175. var found = false;
  176. for (var i = 0; i < pairs.length;) {
  177. if (pairs[i].name === name) {
  178. if (!found) {
  179. pairs[i].value = value;
  180. found = true;
  181. ++i;
  182. } else {
  183. pairs.splice(i, 1);
  184. }
  185. } else {
  186. ++i;
  187. }
  188. }
  189. if (!found)
  190. pairs.push({ name: name, value: value });
  191. updateSteps();
  192. }
  193. },
  194. toString: {
  195. value: function () {
  196. return serialize(pairs);
  197. }
  198. }
  199. });
  200. };
  201. var queryObject = new URLSearchParams(
  202. self, instance.search ? instance.search.substring(1) : null);
  203. Object.defineProperties(self, {
  204. href: {
  205. get: function () { return instance.href; },
  206. set: function (v) { instance.href = v; tidy_instance(); update_steps(); }
  207. },
  208. origin: {
  209. get: function () {
  210. if ('origin' in instance) return instance.origin;
  211. return this.protocol + '//' + this.host;
  212. }
  213. },
  214. protocol: {
  215. get: function () { return instance.protocol; },
  216. set: function (v) { instance.protocol = v; }
  217. },
  218. username: {
  219. get: function () { return instance.username; },
  220. set: function (v) { instance.username = v; }
  221. },
  222. password: {
  223. get: function () { return instance.password; },
  224. set: function (v) { instance.password = v; }
  225. },
  226. host: {
  227. get: function () {
  228. // IE returns default port in |host|
  229. var re = {'http:': /:80$/, 'https:': /:443$/, 'ftp:': /:21$/}[instance.protocol];
  230. return re ? instance.host.replace(re, '') : instance.host;
  231. },
  232. set: function (v) { instance.host = v; }
  233. },
  234. hostname: {
  235. get: function () { return instance.hostname; },
  236. set: function (v) { instance.hostname = v; }
  237. },
  238. port: {
  239. get: function () { return instance.port; },
  240. set: function (v) { instance.port = v; }
  241. },
  242. pathname: {
  243. get: function () {
  244. // IE does not include leading '/' in |pathname|
  245. if (instance.pathname.charAt(0) !== '/') return '/' + instance.pathname;
  246. return instance.pathname;
  247. },
  248. set: function (v) { instance.pathname = v; }
  249. },
  250. search: {
  251. get: function () { return instance.search; },
  252. set: function (v) {
  253. if (instance.search === v) return;
  254. instance.search = v; tidy_instance(); update_steps();
  255. }
  256. },
  257. searchParams: {
  258. get: function () { return queryObject; }
  259. // TODO: implement setter
  260. },
  261. hash: {
  262. get: function () { return instance.hash; },
  263. set: function (v) { instance.hash = v; tidy_instance(); }
  264. },
  265. toString: {
  266. value: function() { return instance.toString(); }
  267. },
  268. valueOf: {
  269. value: function() { return instance.valueOf(); }
  270. }
  271. });
  272. function tidy_instance() {
  273. var href = instance.href.replace(/#$|\?$|\?(?=#)/g, '');
  274. if (instance.href !== href)
  275. instance.href = href;
  276. }
  277. function update_steps() {
  278. queryObject._setPairs(instance.search ? parse(instance.search.substring(1)) : []);
  279. queryObject._updateSteps();
  280. };
  281. return self;
  282. };
  283. if (origURL) {
  284. for (var i in origURL) {
  285. if (origURL.hasOwnProperty(i))
  286. global.URL[i] = origURL[i];
  287. }
  288. }
  289. }(window));
  290. });