/*!
* urlInternal - v1.0 - 10/7/2009
* http://benalman.com/projects/jquery-urlinternal-plugin/
*
* Copyright (c) 2009 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
// Script: jQuery urlInternal: Easily test URL internal-, external or fragment-ness
//
// *Version: 1.0, Last updated: 10/7/2009*
//
// Project Home - http://benalman.com/projects/jquery-urlinternal-plugin/
// GitHub - http://github.com/cowboy/jquery-urlinternal/
// Source - http://github.com/cowboy/jquery-urlinternal/raw/master/jquery.ba-urlinternal.js
// (Minified) - http://github.com/cowboy/jquery-urlinternal/raw/master/jquery.ba-urlinternal.min.js (1.7kb)
//
// About: License
//
// Copyright (c) 2009 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
//
// About: Examples
//
// This working example, complete with fully commented code, illustrates a few
// ways in which this plugin can be used.
//
// http://benalman.com/code/projects/jquery-urlinternal/examples/urlinternal/
//
// About: Support and Testing
//
// Information about what version or versions of jQuery this plugin has been
// tested with, what browsers it has been tested in, and where the unit tests
// reside (so you can test it yourself).
//
// jQuery Versions - 1.3.2
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.
// Unit Tests - http://benalman.com/code/projects/jquery-urlinternal/unit/
//
// About: Release History
//
// 1.0 - (10/7/2009) Initial release
(function($){
'$:nomunge'; // Used by YUI compressor.
// Some convenient shortcuts.
var undefined,
TRUE = !0,
FALSE = !1,
loc = window.location,
aps = Array.prototype.slice,
matches = loc.href.match( /^((https?:\/\/.*?\/)?[^#]*)#?.*$/ ),
loc_fragbase = matches[1] + '#',
loc_hostbase = matches[2],
// Method references.
jq_elemUrlAttr,
jq_urlInternalHost,
jq_urlInternalRegExp,
jq_isUrlInternal,
jq_isUrlExternal,
jq_isUrlFragment,
// Reused strings.
str_elemUrlAttr = 'elemUrlAttr',
str_href = 'href',
str_src = 'src',
str_urlInternal = 'urlInternal',
str_urlExternal = 'urlExternal',
str_urlFragment = 'urlFragment',
url_regexp,
// Used by jQuery.elemUrlAttr.
elemUrlAttr_cache = {};
// Why write the same function twice? Let's curry! Mmmm, curry..
function curry( func ) {
var args = aps.call( arguments, 1 );
return function() {
return func.apply( this, args.concat( aps.call( arguments ) ) );
};
};
// Section: Methods
//
// Method: jQuery.isUrlInternal
//
// Test whether or not a URL is internal. Non-navigating URLs (ie. #anchor,
// javascript:, mailto:, news:, tel:, im: or non-http/https protocol://
// links) are not considered internal.
//
// Usage:
//
// > jQuery.isUrlInternal( url );
//
// Arguments:
//
// url - (String) a URL to test the internal-ness of.
//
// Returns:
//
// (Boolean) true if the URL is internal, false if external, or undefined if
// the URL is non-navigating.
$.isUrlInternal = jq_isUrlInternal = function( url ) {
// non-navigating: url is nonexistent or a fragment
if ( !url || jq_isUrlFragment( url ) ) { return undefined; }
// internal: url is absolute-but-internal (see $.urlInternalRegExp)
if ( url_regexp.test(url) ) { return TRUE; }
// external: url is absolute (begins with http:// or https:// or //)
if ( /^(?:https?:)?\/\//i.test(url) ) { return FALSE; }
// non-navigating: url begins with scheme:
if ( /^[a-z\d.-]+:/i.test(url) ) { return undefined; }
return TRUE;
};
// Method: jQuery.isUrlExternal
//
// Test whether or not a URL is external. Non-navigating URLs (ie. #anchor,
// mailto:, javascript:, or non-http/https protocol:// links) are not
// considered external.
//
// Usage:
//
// > jQuery.isUrlExternal( url );
//
// Arguments:
//
// url - (String) a URL to test the external-ness of.
//
// Returns:
//
// (Boolean) true if the URL is external, false if internal, or undefined if
// the URL is non-navigating.
$.isUrlExternal = jq_isUrlExternal = function( url ) {
var result = jq_isUrlInternal( url );
return typeof result === 'boolean'
? !result
: result;
};
// Method: jQuery.isUrlFragment
//
// Test whether or not a URL is a fragment in the context of the current page,
// meaning the URL can either begin with # or be a partial URL or full URI,
// but when it is navigated to, only the document.location.hash will change,
// and the page will not reload.
//
// Usage:
//
// > jQuery.isUrlFragment( url );
//
// Arguments:
//
// url - (String) a URL to test the fragment-ness of.
//
// Returns:
//
// (Boolean) true if the URL is a fragment, false otherwise.
$.isUrlFragment = jq_isUrlFragment = function( url ) {
var matches = ( url || '' ).match( /^([^#]?)([^#]*#).*$/ );
// url *might* be a fragment, since there were matches.
return !!matches && (
// url is just a fragment.
matches[2] === '#'
// url is absolute and contains a fragment, but is otherwise the same URI.
|| url.indexOf( loc_fragbase ) === 0
// url is relative, begins with '/', contains a fragment, and is otherwise
// the same URI.
|| ( matches[1] === '/' ? loc_hostbase + matches[2] === loc_fragbase
// url is relative, but doesn't begin with '/', contains a fragment, and
// is otherwise the same URI. This isn't even remotely efficient, but it's
// significantly less code than parsing everything. Besides, it will only
// even be tested on url values that contain '#', aren't absolute, and
// don't begin with '/', which is not going to be many of them.
: !/^https?:\/\//i.test( url ) && $('')[0].href.indexOf( loc_fragbase ) === 0 )
);
};
// Method: jQuery.fn.urlInternal
//
// Filter a jQuery collection of elements, returning only elements that have
// an internal URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Usage:
//
// > jQuery('selector').urlInternal( [ attr ] );
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test internal-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
// Method: jQuery.fn.urlExternal
//
// Filter a jQuery collection of elements, returning only elements that have
// an external URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Usage:
//
// > jQuery('selector').urlExternal( [ attr ] );
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test external-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
// Method: jQuery.fn.urlFragment
//
// Filter a jQuery collection of elements, returning only elements that have
// an fragment URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Note that in most browsers, selecting $("a[href^=#]") is reliable, but this
// doesn't always work in IE6/7! In order to properly test whether a URL
// attribute's value is a fragment in the context of the current page, you can
// either make your selector a bit more complicated.. or use .urlFragment!
//
// Usage:
//
// > jQuery('selector').urlFragment( [ attr ] );
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test external-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
function fn_filter( str, attr ) {
return this.filter( ':' + str + (attr ? '(' + attr + ')' : '') );
};
$.fn[ str_urlInternal ] = curry( fn_filter, str_urlInternal );
$.fn[ str_urlExternal ] = curry( fn_filter, str_urlExternal );
$.fn[ str_urlFragment ] = curry( fn_filter, str_urlFragment );
// Section: Selectors
//
// Selector: :urlInternal
//
// Filter a jQuery collection of elements, returning only elements that have
// an internal URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Usage:
//
// > jQuery('selector').filter(':urlInternal');
// > jQuery('selector').filter(':urlInternal(attr)');
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test internal-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
// Selector: :urlExternal
//
// Filter a jQuery collection of elements, returning only elements that have
// an external URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Usage:
//
// > jQuery('selector').filter(':urlExternal');
// > jQuery('selector').filter(':urlExternal(attr)');
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test external-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
// Selector: :urlFragment
//
// Filter a jQuery collection of elements, returning only elements that have
// an fragment URL (as determined by ). If URL cannot
// be determined, remove the element from the collection.
//
// Note that in most browsers, selecting $("a[href^=#]") is reliable, but this
// doesn't always work in IE6/7! In order to properly test whether a URL
// attribute's value is a fragment in the context of the current page, you can
// either make your selector a bit more complicated.. or use :urlFragment!
//
// Usage:
//
// > jQuery('selector').filter(':urlFragment');
// > jQuery('selector').filter(':urlFragment(attr)');
//
// Arguments:
//
// attr - (String) Optional name of an attribute that will contain a URL to
// test fragment-ness against. See for a list of
// default attributes.
//
// Returns:
//
// (jQuery) A filtered jQuery collection of elements.
function fn_selector( func, elem, i, match ) {
var a = match[3] || jq_elemUrlAttr()[ ( elem.nodeName || '' ).toLowerCase() ] || '';
return a ? !!func( elem.getAttribute( a ) ) : FALSE;
};
$.expr[':'][ str_urlInternal ] = curry( fn_selector, jq_isUrlInternal );
$.expr[':'][ str_urlExternal ] = curry( fn_selector, jq_isUrlExternal );
$.expr[':'][ str_urlFragment ] = curry( fn_selector, jq_isUrlFragment );
// Section: Support methods
//
// Method: jQuery.elemUrlAttr
//
// Get the internal "Default URL attribute per tag" list, or augment the list
// with additional tag-attribute pairs, in case the defaults are insufficient.
//
// In the and methods, as well
// as the <:urlInternal> and <:urlExternal> selectors, this list is used to
// determine which attribute contains the URL to be modified, if an "attr"
// param is not specified.
//
// Default Tag-Attribute List:
//
// a - href
// base - href
// iframe - src
// img - src
// input - src
// form - action
// link - href
// script - src
//
// Usage:
//
// > jQuery.elemUrlAttr( [ tag_attr ] );
//
// Arguments:
//
// tag_attr - (Object) An object containing a list of tag names and their
// associated default attribute names in the format { tag: 'attr', ... } to
// be merged into the internal tag-attribute list.
//
// Returns:
//
// (Object) An object containing all stored tag-attribute values.
// Only define function and set defaults if function doesn't already exist, as
// the jQuery BBQ plugin will provide this method as well.
$[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) {
return $.extend( elemUrlAttr_cache, obj );
})({
a: str_href,
base: str_href,
iframe: str_src,
img: str_src,
input: str_src,
form: 'action',
link: str_href,
script: str_src
});
jq_elemUrlAttr = $[ str_elemUrlAttr ];
// Method: jQuery.urlInternalHost
//
// Constructs the regular expression that matches an absolute-but-internal
// URL from the current page's protocol, hostname and port, allowing for any
// number of optional hostnames. For example, if the current page is
// http://benalman.com/test or http://www.benalman.com/test, specifying an
// argument of "www" would yield this pattern:
//
// > /^(?:http:)?\/\/(?:(?:www)\.)?benalman.com\//i
//
// This pattern will match URLs beginning with both http://benalman.com/ and
// http://www.benalman.com/. If the current page is http://benalman.com/test,
// http://www.benalman.com/test or http://foo.benalman.com/test, specifying
// arguments "www", "foo" would yield this pattern:
//
// > /^(?:http:)?\/\/(?:(?:www|foo)\.)?benalman.com\//i
//
// This pattern will match URLs beginning with http://benalman.com/,
// http://www.benalman.com/ and http://foo.benalman.com/.
//
// Not specifying any alt_hostname will disable any alt-hostname matching.
//
// Note that the plugin is initialized by default to an alt_hostname of "www".
// Should you need more control, may be used to
// completely customize the absolute-but-internal matching pattern.
//
// Usage:
//
// > jQuery.urlInternalHost( [ alt_hostname [, alt_hostname ] ... ] );
//
// Arguments:
//
// alt_hostname - (String) An optional alternate hostname to use when testing
// URL absolute-but-internal-ness.
//
// Returns:
//
// (RegExp) The absolute-but-internal pattern, as a RegExp.
$.urlInternalHost = jq_urlInternalHost = function( alt_hostname ) {
alt_hostname = alt_hostname
? '(?:(?:' + Array.prototype.join.call( arguments, '|' ) + ')\\.)?'
: '';
var re = new RegExp( '^' + alt_hostname + '(.*)', 'i' ),
pattern = '^(?:' + loc.protocol + ')?//'
+ loc.hostname.replace(re, alt_hostname + '$1').replace( /\\?\./g, '\\.' )
+ (loc.port ? ':' + loc.port : '') + '/';
return jq_urlInternalRegExp( pattern );
};
// Method: jQuery.urlInternalRegExp
//
// Set or get the regular expression that matches an absolute-but-internal
// URL.
//
// Usage:
//
// > jQuery.urlInternalRegExp( [ re ] );
//
// Arguments:
//
// re - (String or RegExp) The regular expression pattern. If not passed,
// nothing is changed.
//
// Returns:
//
// (RegExp) The absolute-but-internal pattern, as a RegExp.
$.urlInternalRegExp = jq_urlInternalRegExp = function( re ) {
if ( re ) {
url_regexp = typeof re === 'string'
? new RegExp( re, 'i' )
: re;
}
return url_regexp;
};
// Initialize url_regexp with a reasonable default.
jq_urlInternalHost( 'www' );
})(jQuery);