/*! * URI.js - Mutating URLs * jQuery Plugin * * Version: 1.10.2 * * Author: Rodney Rehm * Web: http://medialize.github.com/URI.js/jquery-uri-plugin.html * * Licensed under * MIT License http://www.opensource.org/licenses/mit-license * GPL v3 http://opensource.org/licenses/GPL-3.0 * */ (function (root, factory) { // https://github.com/umdjs/umd/blob/master/returnExports.js if (typeof exports === 'object') { // Node module.exports = factory(require('jquery', './URI')); } else if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['jquery', './URI'], factory); } else { // Browser globals (root is window) factory(root.jQuery, root.URI); } }(this, function ($, URI) { "use strict"; var comparable = {}; var compare = { // equals '=': function(value, target) { return value === target; }, // ~= translates to value.match((?:^|\s)target(?:\s|$)) which is useless for URIs // |= translates to value.match((?:\b)target(?:-|\s|$)) which is useless for URIs // begins with '^=': function(value, target, property) { return !!(value + "").match(new RegExp('^' + escapeRegEx(target), 'i')); }, // ends with '$=': function(value, target, property) { return !!(value + "").match(new RegExp(escapeRegEx(target) + '$', 'i')); }, // contains '*=': function(value, target, property) { if (property == 'directory') { // add trailing slash so /dir/ will match the deep-end as well value += '/'; } return !!(value + "").match(new RegExp(escapeRegEx(target), 'i')); }, 'equals:': function(uri, target) { return uri.equals(target); }, 'is:': function(uri, target) { return uri.is(target); } }; function escapeRegEx(string) { // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); } function getUriProperty(elem) { var property; // Note: IE9 will report img.href, so check img.src first (Issue #48) $.each(['src', 'href', 'action'], function(k, v) { if (v in elem ) { property = v; return false; } return true; }); // compensate ambiguous if (elem.nodeName.toLowerCase() === 'input' && elem.type !== 'image') { return undefined; } if (!property) { // you can set any property you wish. So for elements that don't have // either of [src, href, action] we simply return src. // https://github.com/medialize/URI.js/issues/69 return 'src'; } return property; } function generateAccessor(property) { return { get: function(elem) { return $(elem).uri()[property](); }, set: function(elem, value) { $(elem).uri()[property](value); return value; } }; }; // populate lookup table and register $.attr('uri:accessor') handlers $.each('authority directory domain filename fragment hash host hostname href password path pathname port protocol query resource scheme search subdomain suffix tld username'.split(" "), function(k, v) { comparable[v] = true; $.attrHooks['uri:' + v] = generateAccessor(v); }); // pipe $.attr('src') and $.attr('href') through URI.js var _attrHooks = { get: function(elem) { return $(elem).uri(); }, set: function(elem, value) { return $(elem).uri().href(value).toString(); } }; $.each(['src', 'href', 'action', 'uri'], function(k, v) { $.attrHooks[v] = { set: _attrHooks.set }; }); $.attrHooks.uri.get = _attrHooks.get; // general URI accessor $.fn.uri = function(uri) { var $this = this.first(); var elem = $this.get(0); var property = getUriProperty(elem); if (!property) { throw new Error('Element "' + elem.nodeName + '" does not have either property: href, src, action'); } if (uri !== undefined) { var old = $this.data('uri'); if (old) { return old.href(uri); } if (!(uri instanceof URI)) { uri = URI(uri); } } else { uri = $this.data('uri'); if (uri) { return uri; } else { uri = URI($this.attr(property)); } } uri._dom_element = elem; uri._dom_attribute = property; uri.normalize(); $this.data('uri', uri); return uri; }; // overwrite URI.build() to update associated DOM element if necessary URI.prototype.build = function(deferBuild) { if (this._dom_element) { // cannot defer building when hooked into a DOM element this._string = URI.build(this._parts); this._deferred_build = false; this._dom_element.setAttribute(this._dom_attribute, this._string); this._dom_element[this._dom_attribute] = this._string; } else if (deferBuild === true) { this._deferred_build = true; } else if (deferBuild === undefined || this._deferred_build) { this._string = URI.build(this._parts); this._deferred_build = false; } return this; }; // add :uri() pseudo class selector to sizzle var uriSizzle; var pseudoArgs = /^([a-zA-Z]+)\s*([\^\$*]?=|:)\s*(['"]?)(.+)\3|^\s*([a-zA-Z0-9]+)\s*$/; function uriPseudo (elem, text) { var match, property, uri; // skip anything without src|href|action and bad :uri() syntax if (!getUriProperty(elem) || !text) { return false; } match = text.match(pseudoArgs); if (!match || (!match[5] && match[2] !== ':' && !compare[match[2]])) { // abort because the given selector cannot be executed // filers seem to fail silently return false; } uri = $(elem).uri(); if (match[5]) { return uri.is(match[5]); } else if (match[2] === ':') { property = match[1].toLowerCase() + ':'; if (!compare[property]) { // filers seem to fail silently return false; } return compare[property](uri, match[4]); } else { property = match[1].toLowerCase(); if (!comparable[property]) { // filers seem to fail silently return false; } return compare[match[2]](uri[property](), match[4], property); } return false; } if ($.expr.createPseudo) { // jQuery >= 1.8 uriSizzle = $.expr.createPseudo(function (text) { return function (elem) { return uriPseudo(elem, text); }; }); } else { // jQuery < 1.8 uriSizzle = function (elem, i, match) { return uriPseudo(elem, match[3]); }; } $.expr[":"].uri = uriSizzle; // extending existing object rather than defining something new return {}; }));