-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.external_links.js
127 lines (103 loc) · 4.59 KB
/
jquery.external_links.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
!(function($) {
var datakey = '$external-link-data';
var defopts = {
favicon : true,
favicon_url : 'http://favicon.yandex.net/favicon',
url_seperator : '/',
link_class : 'external-link',
// the following means only allow 'A' dom elements will be effected by this plugin (by default)
link_selector : 'a',
span_class : 'ext-favicon',
// left or right (determines where the span is inject relative to the link)
span_position : 'right',
// array of regexps and alternative hostnames to use if a URLs host matches the corresponding regexp
special_hosts : [
[/github\.com$/, 'github.com']
]
};
var methods = {
init : function(opts) {
if (this.data(datakey))
return this; // already initialized
if (opts && $.isArray(opts.special_hosts))
$.merge(opts.special_hosts, defopts.special_hosts);
opts = $.extend({}, defopts, opts);
var manipFn = 'prependTo', // manipulation method to use when injecting the favicon span elements
url = opts.favicon ? opts.favicon_url : null,
finks = [],
furls = [],
items = (typeof opts.link_selector === 'string' && opts.link_selector.length)
? this.filter(opts.link_selector)
: this
;
if ('right' === opts.span_position)
manipFn = 'appendTo';
items
// add css class to link
.addClass(opts.link_class)
// get list of hostnames,
// map them to each given link,
// build the favicon URL and
// set the element data
.each(function(n) {
var $this = $(this),
host = this.hostname;
if (url) {
if ($.isArray(opts.special_hosts))
$.each(opts.special_hosts, function(i, v) {
if (!$.isArray(v) || v.length !== 2)
return;
if (host.match(v[0]))
host = v[1];
});
var idx = furls.indexOf(host);
if (idx === -1) {
url += opts.url_seperator + host;
finks[n] = furls.length;
furls.push(host);
} else {
finks[n] = idx;
}
}
$this.data(datakey, {
link_class : opts.link_class,
span_class : url ? opts.span_class : null,
orig_target : $this.attr('target'),
favicon_url : url,
span_position : opts.span_position === 'right' ? 'right' : 'left'
});
})
// set target attribute to point to new window
.attr('target', '_blank');
// add the favicon element
if (url) items.each(function(n) {
$('<span class="' + opts.span_class + '" style="background-image: url(' + url + ');background-position : right -' + finks[n] * 16 + 'px;"></span>')[manipFn](this);
})
// allow jQ method-chaining :)
return this;
},
destroy : function() {
return this.each(function(n) {
var $this = $(this),
opts = $this.data(datakey);
if (!$.isPlainObject(opts) || !opts.span_position)
return;
if (opts.link_class)
$this.removeClass(opts.link_class);
if (opts.favicon_url) {
var css_class = opts.span_class ? '.' + opts.span_class : '',
css_psuedo = opts.span_position === 'right' ? ':last-child' : ':first-child';
$this.children('span' + css_psuedo + css_class).remove();
}
$this.attr('target', opts.orig_target ? opts.orig_target : null);
});
}
};
$.fn.externalLinks = function(meth) {
if (methods[meth])
return methods[meth].apply(this, Array.prototype.slice.call(arguments, 1));
if (typeof meth === 'object' || !meth)
return methods.init.apply(this, arguments);
$.error('Method ' + meth + ' does not exist on jQuery.externalLinks');
};
})(window.jQuery);