/ajax/libs/webshim/1.15.7/dev/shims/url.js
JavaScript | 327 lines | 266 code | 37 blank | 24 comment | 46 complexity | d7b2d7b6b777b46751701d99f609f889 MD5 | raw file
- webshim.register('url', function($, webshims, window, document, undefined, options){
- 'use strict';
- // URL Polyfill
- // Draft specification: http://url.spec.whatwg.org
- // Notes:
- // - Primarily useful for parsing URLs and modifying query parameters
- // - Should work in IE8+ and everything more modern
- (function (global) {
- // Browsers may have:
- // * No global URL object
- // * URL with static methods only - may have a dummy constructor
- // * URL with members except searchParams
- // * Full URL API support
- var origURL = global.URL;
- var nativeURL;
- try {
- if (origURL) {
- nativeURL = new global.URL('http://example.com');
- if ('searchParams' in nativeURL)
- return;
- if (!('href' in nativeURL))
- nativeURL = undefined;
- }
- } catch (_) {}
- function URLUtils(url) {
- if (nativeURL)
- return new origURL(url);
- var anchor = document.createElement('a');
- anchor.href = url;
- return anchor;
- }
- global.URL = function URL(url, base) {
- if (!(this instanceof global.URL))
- throw new TypeError("Failed to construct 'URL': Please use the 'new' operator.");
- if (base) {
- url = (function () {
- if (nativeURL) return new origURL(url, base).href;
- var doc;
- // Use another document/base tag/anchor for relative URL resolution, if possible
- if (document.implementation && document.implementation.createHTMLDocument) {
- doc = document.implementation.createHTMLDocument('');
- } else if (document.implementation && document.implementation.createDocument) {
- doc = document.implementation.createElement('http://www.w3.org/1999/xhtml', 'html', null);
- doc.documentElement.appendChild(doc.createElement('head'));
- doc.documentElement.appendChild(doc.createElement('body'));
- } else if (window.ActiveXObject) {
- doc = new window.ActiveXObject('htmlfile');
- doc.write('<head></head><body></body>');
- doc.close();
- }
- if (!doc) throw Error('base not supported');
- var baseTag = doc.createElement('base');
- baseTag.href = base;
- doc.getElementsByTagName('head')[0].appendChild(baseTag);
- var anchor = doc.createElement('a');
- anchor.href = url;
- return anchor.href;
- }());
- }
- // An inner object implementing URLUtils (either a native URL
- // object or an HTMLAnchorElement instance) is used to perform the
- // URL algorithms. With full ES5 getter/setter support, return a
- // regular object For IE8's limited getter/setter support, a
- // different HTMLAnchorElement is returned with properties
- // overridden
- var instance = URLUtils(url || '');
- // Detect for ES5 getter/setter support
- var ES5_GET_SET = (Object.defineProperties && (function () {
- var o = {}; Object.defineProperties(o, { p: { 'get': function () { return true; } } }); return o.p;
- }()));
- var self = ES5_GET_SET ? this : document.createElement('a');
- // NOTE: Doesn't do the encoding/decoding dance
- function parse(input, isindex) {
- var sequences = input.split('&');
- if (isindex && sequences[0].indexOf('=') === -1)
- sequences[0] = '=' + sequences[0];
- var pairs = [];
- sequences.forEach(function (bytes) {
- if (bytes.length === 0) return;
- var index = bytes.indexOf('=');
- if (index !== -1) {
- var name = bytes.substring(0, index);
- var value = bytes.substring(index + 1);
- } else {
- name = bytes;
- value = '';
- }
- name = name.replace(/\+/g, ' ');
- value = value.replace(/\+/g, ' ');
- pairs.push({ name: name, value: value });
- });
- var output = [];
- pairs.forEach(function (pair) {
- output.push({
- name: decodeURIComponent(pair.name),
- value: decodeURIComponent(pair.value)
- });
- });
- return output;
- }
- function URLSearchParams(url_object, init) {
- var pairs = [];
- if (init)
- pairs = parse(init);
- this._setPairs = function (list) { pairs = list; };
- this._updateSteps = function () { updateSteps(); };
- var updating = false;
- function updateSteps() {
- if (updating) return;
- updating = true;
- // TODO: For all associated url objects
- url_object.search = serialize(pairs);
- updating = false;
- }
- // NOTE: Doesn't do the encoding/decoding dance
- function serialize(pairs) {
- var output = '', first = true;
- pairs.forEach(function (pair) {
- var name = encodeURIComponent(pair.name);
- var value = encodeURIComponent(pair.value);
- if (!first) output += '&';
- output += name + '=' + value;
- first = false;
- });
- return output.replace(/%20/g, '+');
- }
- Object.defineProperties(this, {
- append: {
- value: function (name, value) {
- pairs.push({ name: name, value: value });
- updateSteps();
- }
- },
- 'delete': {
- value: function (name) {
- for (var i = 0; i < pairs.length;) {
- if (pairs[i].name === name)
- pairs.splice(i, 1);
- else
- ++i;
- }
- updateSteps();
- }
- },
- get: {
- value: function (name) {
- for (var i = 0; i < pairs.length; ++i) {
- if (pairs[i].name === name)
- return pairs[i].value;
- }
- return null;
- }
- },
- getAll: {
- value: function (name) {
- var result = [];
- for (var i = 0; i < pairs.length; ++i) {
- if (pairs[i].name === name)
- result.push(pairs[i].value);
- }
- return result;
- }
- },
- has: {
- value: function (name) {
- for (var i = 0; i < pairs.length; ++i) {
- if (pairs[i].name === name)
- return true;
- }
- return false;
- }
- },
- set: {
- value: function (name, value) {
- var found = false;
- for (var i = 0; i < pairs.length;) {
- if (pairs[i].name === name) {
- if (!found) {
- pairs[i].value = value;
- found = true;
- ++i;
- } else {
- pairs.splice(i, 1);
- }
- } else {
- ++i;
- }
- }
- if (!found)
- pairs.push({ name: name, value: value });
- updateSteps();
- }
- },
- toString: {
- value: function () {
- return serialize(pairs);
- }
- }
- });
- };
- var queryObject = new URLSearchParams(
- self, instance.search ? instance.search.substring(1) : null);
- Object.defineProperties(self, {
- href: {
- get: function () { return instance.href; },
- set: function (v) { instance.href = v; tidy_instance(); update_steps(); }
- },
- origin: {
- get: function () {
- if ('origin' in instance) return instance.origin;
- return this.protocol + '//' + this.host;
- }
- },
- protocol: {
- get: function () { return instance.protocol; },
- set: function (v) { instance.protocol = v; }
- },
- username: {
- get: function () { return instance.username; },
- set: function (v) { instance.username = v; }
- },
- password: {
- get: function () { return instance.password; },
- set: function (v) { instance.password = v; }
- },
- host: {
- get: function () {
- // IE returns default port in |host|
- var re = {'http:': /:80$/, 'https:': /:443$/, 'ftp:': /:21$/}[instance.protocol];
- return re ? instance.host.replace(re, '') : instance.host;
- },
- set: function (v) { instance.host = v; }
- },
- hostname: {
- get: function () { return instance.hostname; },
- set: function (v) { instance.hostname = v; }
- },
- port: {
- get: function () { return instance.port; },
- set: function (v) { instance.port = v; }
- },
- pathname: {
- get: function () {
- // IE does not include leading '/' in |pathname|
- if (instance.pathname.charAt(0) !== '/') return '/' + instance.pathname;
- return instance.pathname;
- },
- set: function (v) { instance.pathname = v; }
- },
- search: {
- get: function () { return instance.search; },
- set: function (v) {
- if (instance.search === v) return;
- instance.search = v; tidy_instance(); update_steps();
- }
- },
- searchParams: {
- get: function () { return queryObject; }
- // TODO: implement setter
- },
- hash: {
- get: function () { return instance.hash; },
- set: function (v) { instance.hash = v; tidy_instance(); }
- },
- toString: {
- value: function() { return instance.toString(); }
- },
- valueOf: {
- value: function() { return instance.valueOf(); }
- }
- });
- function tidy_instance() {
- var href = instance.href.replace(/#$|\?$|\?(?=#)/g, '');
- if (instance.href !== href)
- instance.href = href;
- }
- function update_steps() {
- queryObject._setPairs(instance.search ? parse(instance.search.substring(1)) : []);
- queryObject._updateSteps();
- };
- return self;
- };
- if (origURL) {
- for (var i in origURL) {
- if (origURL.hasOwnProperty(i))
- global.URL[i] = origURL[i];
- }
- }
- }(window));
- });