├── README.md
├── close.gif
├── index.html
├── jquery.liveurl.js
├── liveurl.css
├── liveurl.jquery.json
└── url-loader.gif
/README.md:
--------------------------------------------------------------------------------
1 | # jquery.liveurl - a facebook attachment clone (version 1.2.2)
2 |
3 | This plugin enables a **live preview** for an url in a *textarea*,
4 | like the facebook attachment of a post. Multiple images and a video preview is in this demo integrated.
5 |
6 | ## Features
7 | + Filters urls and images from a textarea
8 | + Multiple Images
9 | + Video Preview
10 | + NO PHP required (YQL)
11 | + Meta Tag Recognition
12 | + Body Images Inspector
13 | + Body Paragraphs Inspector for Description Fallback
14 |
15 |
16 | ## Demo
17 | **Online-Demo:** http://liveurl.ainetworks.de/demo/
18 |
19 | [](http://25.media.tumblr.com/tumblr_mdiyp1bDim1rl9djro1_1280.png)
20 |
21 | ## Installation
22 | Include this script **after** the jQuery library
23 | ```html
24 |
25 | ```
26 |
27 | ## Browser Compatibility
28 | + Google Chrome 23
29 | + Mozilla Firefox 16.0.2
30 | * Internet Explorer 7, 8 and 9
31 | + Safari 5.1.7
32 |
33 | ## Quick Usage
34 | You can use this plugin on every textarea. Start it directly:
35 |
36 | ```javascript
37 | $('textarea').liveUrl({
38 | success : function(data)
39 | {
40 | console.log(data);
41 | // this return the first found url data
42 | }
43 | });
44 | ```
45 | ### returns: ###
46 | ```javascript
47 | Object = {
48 | title: "New Car Quotes, Buy Used Cars, and Prices | The cars.com alternative | Car.com",
49 | description: "Car Reviews, Car Financing, and a Free non-obligat…e.",
50 | url: "http://www.car.com",
51 | video: null
52 | }
53 | ```
54 |
55 | ## Options
56 |
57 | | Option | Parameter | Default | Description |
58 | | ------------- | ------------- |------------- | ------------- |
59 | | *findLogo* | `[boolean (true / false)]` | `false` | should search for an image or class namend "logo" for the image preview |
60 | | *logoWord* | `[string]` | `logo` | Word, which should be searched, used for the "findLogo" option |
61 | | *findDescription* | `[boolean (true / false)]` | `true` | should search for an p tag with text, only if the description is not given |
62 | | *matchNoData* | `[boolean (true / false)]` | `true` | preview urls, which are not found (offline, 404) |
63 | | *multipleImages* | `[boolean (true / false)]` | `true` | preview more than one image of the url |
64 | | *minWidth* | `[integer]` | `100` | Value in pixel for the minimum width of each preview-image |
65 | | *minHeight* | `[integer]` | `32` | Value in pixel for the minimum height of each preview-image |
66 | | *loadStart* | `[function()]` | `{}` | This function starts if the plugin start a page download - for an optional loader |
67 | | *loadEnd* | `[function()]` | `{}` | This function starts if the plugin has finished the page download |
68 | | *success* | `[function()]` | `{data}` | Returns the information about the first found url |
69 | | *addImage* | `[function()]` | `{image}` | This function is started each time, if a picture is found |
70 | | *imgLoadStart* | `[function()]` | `{}` | Not implemented |
71 | | *imgLoadEnd* | `[function()]` | `{}` | Not implemented |
72 |
73 | ## Development
74 |
75 | - Source hosted at [GitHub](https://github.com/stephan-fischer/jQuery-LiveUrl)
76 | - Report issues, questions, feature requests on [GitHub Issues](https://github.com/stephan-fischer/jQuery-LiveUrl/issues)
77 |
78 | ## Authors
79 |
80 | [Stephan Fischer](https://github.com/stephan-fischer)
81 |
82 |
83 | ## Donation
84 | If you want to support me, make a small donation at www.paypal.com: stephan@mrfischer.de
85 |
--------------------------------------------------------------------------------
/close.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stephan-fischer/jQuery-LiveUrl/ac4f7f42c98d0b50b012ca8061ffbd35d7a06802/close.gif
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Live Url
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 0 von 0
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/jquery.liveurl.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery LiveUrl
3 | *
4 | * MIT License - You are free to use this commercial projects as long as the copyright header is left intact.
5 | * @author Stephan Fischer
6 | * @copyright (c) 2012 Stephan Fischer (www.ainetworks.de)
7 | * @version 1.2.2
8 | *
9 | * UriParser is a function from my addon "Superswitch" for Mozilla FireFox.
10 | */
11 |
12 | (function( $ )
13 | {
14 | $.fn.extend(
15 | {
16 | liveUrl : function( options)
17 | {
18 | var defaults =
19 | {
20 | meta: [
21 | ['description','name', 'description'],
22 | ['description','property', 'og:description'],
23 | ['description','property', 'pinterestapp:about'],
24 | ['image','property', 'og:image'],
25 | ['image','itemprop', 'image'],
26 | ['title','property', 'og:title'],
27 | ['video','property', 'og:video'],
28 | ['video_type','property', 'og:video:type'],
29 | ['video_width','property', 'og:video:width'],
30 | ['video_height','property', 'og:video:height']
31 | ],
32 | findLogo : false,
33 | findDescription : true,
34 | matchNoData : true,
35 | multipleImages : true,
36 | defaultProtocol : 'http://',
37 | minWidth : 100,
38 | minHeight : 32,
39 | logoWord : 'logo',
40 | success : function() {},
41 | loadStart : function() {},
42 | loadEnd : function() {},
43 | imgLoadStart : function() {},
44 | imgLoadEnd : function() {},
45 | clear : function() {},
46 | addImage : function() {}
47 | }
48 |
49 | var options = $.extend(defaults, options);
50 |
51 | this.each(function()
52 | {
53 |
54 | var o = options,
55 | core = {already : []},
56 | url = {},
57 | preview = {};
58 |
59 | core.init = function ()
60 | {
61 | core.preview = false;
62 | core.processedImg = 0;
63 | preview = {
64 | url : '',
65 | images: [],
66 | image : '',
67 | title: '' ,
68 | description: ''
69 | };
70 | };
71 |
72 | core.clear = function()
73 | {
74 | o.clear();
75 | }
76 |
77 | core.reinit = function()
78 | {
79 | core.clear();
80 | core.init();
81 | }
82 |
83 | core.textUpdate = function(self)
84 | {
85 | // read all links
86 | var links = $.urlHelper.getLinks($(self).val());
87 | core.cleanDuplicates(links);
88 |
89 | if (links != null) {
90 |
91 | if ( links.indexOf( preview.url ) == -1 )
92 | core.reinit();
93 |
94 | if (!core.preview) {
95 | core.current = $(self);
96 | core.process(links);
97 | }
98 | } else{
99 | if (core.preview)
100 | core.reinit();
101 | }
102 | };
103 |
104 | core.process = function(urlArray)
105 | {
106 |
107 | for (var index in urlArray) {
108 |
109 | var strUrl = urlArray[index] ;
110 | if (typeof strUrl == 'string') {
111 | var pLink = new $.urlHelper.UriParser(strUrl);
112 |
113 | if (pLink.subdomain && pLink.subdomain.length > 0 ||
114 | pLink.protocol && pLink.protocol.length > 0 ) {
115 |
116 | if (pLink.protocol.length == 0) {
117 | strUrl = o.defaultProtocol + strUrl;
118 | }
119 |
120 | if (!core.isDuplicate(strUrl, core.already)) {
121 |
122 | if ($.urlHelper.isImage(strUrl)) {
123 | preview.image = strUrl;
124 | core.getPreview({}, strUrl);
125 |
126 | } else {
127 | core.getData(strUrl);
128 | }
129 |
130 | return true;
131 | }
132 | }
133 | }
134 | }
135 | };
136 |
137 | core.cleanDuplicates = function(urlArray)
138 | {
139 | var links = core.createLinks(urlArray);
140 |
141 | for(var index in core.already) {
142 | var strUrl = core.already[index];
143 |
144 | if (!core.isDuplicate(strUrl, links)){
145 | var index = $.inArray(strUrl, core.already);
146 | core.already.splice(index, 1);
147 | }
148 | }
149 | };
150 |
151 | core.createLinks = function(urlArray)
152 | {
153 | var links = [];
154 |
155 | for(var index in urlArray) {
156 | var strUrl = urlArray[index];
157 | if (typeof strUrl == 'string') {
158 | var pLink = new $.urlHelper.UriParser(strUrl);
159 |
160 | if (pLink.subdomain && pLink.subdomain.length > 0 ||
161 | pLink.protocol && pLink.protocol.length > 0 ) {
162 |
163 | if (pLink.protocol.length == 0) {
164 | strUrl = o.defaultProtocol + strUrl;
165 | }
166 |
167 | links.push(strUrl);
168 | }
169 | }
170 | }
171 |
172 | return links;
173 | }
174 |
175 | core.isDuplicate = function(url, array)
176 | {
177 | var duplicate = false;
178 | $.each(array, function(key, val)
179 | {
180 | if (val == url) {
181 | duplicate = true;
182 | }
183 | });
184 |
185 | return duplicate;
186 | };
187 |
188 | core.getData = function (url)
189 | {
190 |
191 | var xpath = '//head|//body';
192 | var query = 'select * from html where url="' + url + '" and compat="html5" and xpath="'+xpath+'"';
193 |
194 | core.addLoader();
195 |
196 | $.yql(query, function()
197 | {
198 | var data = {
199 | query : {results: null}
200 | }
201 |
202 | core.ajaxSuccess(data, url);
203 | core.removeLoader();
204 | return false;
205 | },
206 | function(data)
207 | {
208 | core.ajaxSuccess(data, url)
209 | }
210 | )
211 | }; //getData
212 |
213 | core.ajaxSuccess = function(data, url)
214 | {
215 | // URL already loaded, or preview is already shown.
216 | if (core.isDuplicate(url, core.already) || core.preview) {
217 | core.removeLoader();
218 | return false;
219 | }
220 |
221 |
222 | if ($(data).find("results").text().length == 0) {
223 |
224 | if (o.matchNoData) {
225 | core.getPreview(data, url);
226 | } else {
227 | core.already.push(url);
228 | core.removeLoader();
229 | }
230 |
231 | } else {
232 | core.getPreview(data, url);
233 | }
234 | }
235 |
236 |
237 | core.hasValue = function(section){
238 | return (preview[section].length == 0) ? false : true;
239 | };
240 |
241 | core.getPreview = function(data, uri)
242 | {
243 | core.preview = true;
244 | core.already.push(uri);
245 |
246 | var title = "" ;
247 |
248 | $(data, '').find('title').each(function()
249 | {
250 | title = $(this).text();
251 | });
252 |
253 |
254 | preview.title = ( title || uri);
255 | preview.url = uri;
256 |
257 | $(data, '').find('meta').each(function()
258 | {
259 | core.setMetaData($(this));
260 |
261 | });
262 |
263 | if(o.findDescription && !core.hasValue('description')) {
264 |
265 | $(data, '').find('p').each(function()
266 | {
267 | var text = $.trim($(this).text());
268 | if(text.length > 3) {
269 | preview.description = text;
270 | return false;
271 | }
272 |
273 | });
274 | }
275 |
276 | if (!core.hasValue('image')) {
277 | // meta tag has no images:
278 |
279 | var images = $(data, '').find('img');
280 |
281 | if (o.findLogo ) {
282 | images.each(function()
283 | {
284 | var self = $(this);
285 |
286 | if (self.attr('src') && self.attr('src').search(o.logoWord, 'i') != -1 ||
287 | self.attr('id' ) && self.attr('id' ).search(o.logoWord, 'i') != -1 ||
288 | this.className && this.className.search(o.logoWord, 'i') != -1
289 | ) {
290 | preview.image = $(this).attr('src');
291 | return false;
292 | }
293 |
294 | });
295 | }
296 |
297 |
298 | if (!core.hasValue('image') && images.length > 0 ) {
299 | images.each(function()
300 | {
301 | preview.images.push($(this).attr('src'));
302 | });
303 | }
304 | }
305 |
306 | core.removeLoader();
307 |
308 | // prepare output
309 | var not = 'undefined';
310 | var data = {
311 | title : preview.title,
312 | description : preview.description,
313 | url : preview.url,
314 | video : (typeof preview.video != not && preview.video.length > 0) ? {} : null
315 | };
316 |
317 | if (data.video != null) {
318 | data.video = {
319 | file : preview.video,
320 | type : (typeof preview.video_type != not) ? preview.video_type : '',
321 | width : (typeof preview.video_width != not) ? preview.video_width : '',
322 | height: (typeof preview.video_height != not) ? preview.video_height :''
323 | }
324 | }
325 |
326 | o.success(data);
327 |
328 | if (core.hasValue('image')){
329 | preview.images.push(preview.image);
330 | preview.image = '';
331 | }
332 |
333 |
334 | core.addImages();
335 | core.current.one('clear', function()
336 | {
337 | core.init();
338 | });
339 | };
340 |
341 | core.addLoader = function()
342 | {
343 | o.loadStart();
344 | };
345 |
346 | core.removeLoader = function()
347 | {
348 | o.loadEnd();
349 | };
350 |
351 | core.setMetaData = function(val)
352 | {
353 | for (index in o.meta) {
354 | var meta = o.meta[index];
355 | preview[meta[0]] = (core.getValue(val,meta[1],meta[2])|| preview[meta[0]] );
356 | }
357 | };
358 |
359 | core.getValue = function (val,key, tag) {
360 | if (val.attr(key)) {
361 | if (val.attr(key).toLowerCase() == tag.toLowerCase()) {
362 | if (val.attr('content') && val.attr('content').length > 0) {
363 | return val.attr('content');
364 | }
365 | }
366 |
367 | }
368 | };
369 |
370 | core.addImages = function()
371 | {
372 | var images = [];
373 |
374 | for (var index in preview.images) {
375 | var image = preview.images[index];
376 |
377 | if (!$.urlHelper.isAbsolute(image)) {
378 | var pLink = new $.urlHelper.UriParser(preview.url);
379 | var host = pLink.url + pLink.subdomain + pLink.domain;
380 |
381 | if ($.urlHelper.isPathAbsolute(image))
382 | image = host + image;
383 | else image = host + $.urlHelper.stripFile(pLink.path) + '/' + image;
384 | }
385 |
386 | core.getImage(image, function(img)
387 | {
388 | if (img.width >= o.minWidth &&
389 | img.height >= o.minHeight && core.preview) {
390 |
391 | o.addImage(img);
392 |
393 | if(!o.multipleImages) {
394 | return;
395 | }
396 |
397 | }
398 | });
399 | }
400 |
401 | };
402 |
403 | core.getImage = function(src, callback)
404 | {
405 | var concat = $.urlHelper.hasParam(src) ? "&" : "?";
406 | src += concat + 'random=' + (new Date()).getTime();
407 |
408 | $(' ').attr({'src': src}).load(function()
409 | {
410 | var img = this;
411 | var tmrLoaded = window.setInterval(function()
412 | {
413 | core.processedImg++;
414 | if (img.width) {
415 | window.clearInterval(tmrLoaded);
416 | callback(img);
417 | }
418 | if(core.processedImg == preview.images.length){
419 | o.imgLoadEnd();
420 | }
421 | }, 100);
422 | });
423 | };
424 |
425 | core.init();
426 | var that = this;
427 | var self = $(this);
428 |
429 | self.on('keyup', function(e)
430 | {
431 | var links = $.urlHelper.getLinks($(self).val());
432 | core.cleanDuplicates(links);
433 |
434 | window.clearInterval(core.textTimer);
435 |
436 | var code = (e.keyCode ? e.keyCode : e.which);
437 |
438 | if(code == 13 || code == 32) { //Enter keycode
439 | core.textUpdate(that);
440 | } else {
441 | core.textTimer = window.setInterval(function()
442 | {
443 | core.textUpdate(that);
444 | window.clearInterval(core.textTimer);
445 | }, 1000);
446 | }
447 | }).on('paste', function() {core.textUpdate(that)});
448 |
449 | });
450 | }
451 | });
452 |
453 | jQuery.yql = function yql(query, error, success)
454 | {
455 | var yql = {
456 | path: 'http://query.yahooapis.com/v1/public/yql?q=',
457 | query: encodeURIComponent(query)
458 | };
459 |
460 | var isIE = /msie/.test(navigator.userAgent.toLowerCase());
461 |
462 | if (isIE && window.XDomainRequest) {
463 | var xdr = new XDomainRequest();
464 | xdr.open("get", yql['path'] + yql['query']);
465 | xdr.onload = function()
466 | {
467 | success(xdr.responseText);
468 | };
469 |
470 | xdr.send();
471 |
472 | } else {
473 |
474 | $.ajax({
475 | crossDomain : true,
476 | cache : false,
477 | type : 'GET',
478 | url : yql['path'] + yql['query'],
479 | timeout : 8000,
480 | dataType : 'xml',
481 | error : error,
482 | success : success
483 | });
484 | }
485 | };
486 |
487 | jQuery.urlHelper =
488 | {
489 | UriParser : function (uri)
490 | {
491 | this._regExp = /^((\w+):\/\/\/?)?((\w+):?(\w+)?@)?([^\/\?:]+)?(:\d+)?(.*)?/;
492 | this._regExpHost = /^(.+\.)?(.+\..+)$/;
493 |
494 | this._getVal = function(r, i)
495 | {
496 | if(!r) return null;
497 | return (typeof(r[i]) == 'undefined' ? "" : r[i]);
498 | };
499 |
500 | this.parse = function(uri)
501 | {
502 | var r = this._regExp.exec(uri);
503 | this.results = r;
504 | this.url = this._getVal(r,1);
505 | this.protocol = this._getVal(r,2);
506 | this.username = this._getVal(r,4);
507 | this.password = this._getVal(r,5);
508 | this.domain = this._getVal(r,6);
509 | this.port = this._getVal(r,7);
510 | this.path = this._getVal(r,8);
511 |
512 | var rH = this._regExpHost.exec( this.domain );
513 | this.subdomain = this._getVal(rH,1);
514 | this.domain = this._getVal(rH,2);
515 | return r;
516 | }
517 |
518 | if(uri) this.parse(uri);
519 | },
520 | getLinks : function(text)
521 | {
522 | var expression = /((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi;
523 | return (text.match(expression));
524 | },
525 | isImage : function(img, allowed)
526 | {
527 | //Match jpg, gif or png image
528 | if (allowed == null) allowed = 'jpg|gif|png|jpeg';
529 |
530 | var expression = /([^\s]+(?=\.(jpg|gif|png|jpeg))\.\2)/gm;
531 | return (img.match(expression));
532 | },
533 | isAbsolute : function(path)
534 | {
535 | var expression = /^(https?:)?\/\//i;
536 | var value = (path.match(expression) != null) ? true: false;
537 |
538 |
539 | return value;
540 | },
541 | isPathAbsolute : function(path)
542 | {
543 | if (path.substr(0,1) == '/') return true;
544 | },
545 | hasParam : function(path)
546 | {
547 | return (path.lastIndexOf('?') == -1 ) ? false : true;
548 | },
549 | stripFile : function(path) {
550 | return path.substr(0, path.lastIndexOf('/') + 1);
551 | }
552 | }
553 | })( jQuery );
--------------------------------------------------------------------------------
/liveurl.css:
--------------------------------------------------------------------------------
1 | /* Live URL */
2 |
3 | .liveurl {
4 | width: 100%;
5 | overflow: hidden;
6 | background: #F3F3F3;
7 | border-top: 1px dashed #CCC;
8 | margin-top: 10px;
9 | display: none;
10 |
11 | }
12 |
13 | .liveurl .inner {
14 | margin: 15px;
15 |
16 | overflow: hidden;
17 | }
18 |
19 | .liveurl span.image {
20 | float: left;
21 | clear: none;
22 | }
23 |
24 |
25 |
26 | .liveurl .details {
27 | float: left;
28 | overflow: hidden;
29 | width: 475px;
30 | }
31 |
32 | .liveurl .details .info * {
33 | float: left;
34 | clear: both;
35 | line-height: 13px;
36 | }
37 |
38 |
39 | .liveurl .title {
40 | font-weight: bold;
41 | }
42 |
43 | .liveurl .url {
44 | font-size: 11px;
45 | font-weight: normal;
46 | color: #666;
47 | }
48 |
49 | .liveurl .image {
50 | width: 100px;
51 | margin: 0 10px 10px 0;
52 | float: left;
53 | display: none;
54 |
55 | }
56 |
57 | .liveurl .video {
58 | clear: both;
59 | float: left;
60 | margin: 10px 0 0 0;
61 | display: none;
62 | }
63 |
64 | .liveurl img {
65 | width: 100px;
66 | height: auto;
67 | /*display: none;*/
68 | }
69 |
70 | .liveurl img.active {
71 | display: block;
72 | }
73 |
74 | .liveurl .close {
75 | float: right;
76 | cursor: pointer;
77 | margin: 5px;
78 | text-indent:-999px;
79 | width: 16px;
80 | height: 16px;
81 | background:url(close.gif);
82 | }
83 |
84 | .liveurl .thumbnail {
85 | float: left;
86 | margin: 15px 0 0 0;
87 | clear: both;
88 | display: none;
89 | }
90 |
91 | .liveurl .thumbnail label {
92 | padding: 0 0 0 5px;
93 | vertical-align: text-top;
94 | }
95 |
96 | .liveurl .button {
97 | width: 23px;
98 | height: 20px;
99 | float: left;
100 | border: 1px solid #A8A8A8;
101 | text-align: center;
102 | line-height:20px;
103 | background: #FFF;
104 | position: relative;
105 | cursor: pointer;
106 | }
107 |
108 | .liveurl .button:before {
109 | content: '';
110 | width: 0;
111 | position:absolute;
112 | left:5px;
113 | top: 5px;
114 | }
115 |
116 | .liveurl .button:active {
117 | border-color: #3B5998;
118 | }
119 |
120 | .liveurl .button.prev:before {
121 |
122 | border-top: 6px solid transparent;
123 | border-right: 12px solid #828282;
124 | border-bottom: 6px solid transparent;
125 | }
126 |
127 | .liveurl .button.next:before {
128 | border-top: 6px solid transparent;
129 | border-left: 12px solid #828282;
130 | border-bottom: 6px solid transparent;
131 | }
132 |
133 | .liveurl .button:active.prev:before {
134 | border-right: 12px solid #3B5998;
135 | }
136 |
137 | .liveurl .button:active.next:before {
138 | border-left: 12px solid #3B5998;
139 | }
140 |
141 | .liveurl .button.inactive {
142 | opacity: 0.5;
143 | filter:alpha(opacity=50);
144 | pointer-events:none;
145 | cursor: default;
146 | }
147 |
148 | .liveurl .count {
149 | float: left;
150 | margin: 0 0 0 10px;
151 | line-height: 25px;
152 | }
153 |
154 | .liveurl .controls {
155 | margin: 10px 0 0 0;
156 | }
157 |
158 | .post textarea {
159 | width: 600px;
160 | height: 140px;
161 | }
162 |
163 | .liveurl-loader {
164 | display: none;
165 | width: 16px;
166 | height: 11px;
167 | margin: 10px 0;
168 | background: url(url-loader.gif);
169 |
170 | }
171 |
172 | .liveurl * {
173 | font: 12px/1em Tahoma, Arial, Helvetica, Segoe, sans-serif;
174 | }
175 |
--------------------------------------------------------------------------------
/liveurl.jquery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "liveurl",
3 | "title": "jQuery LiveURL",
4 | "description": "jQuery plugin to get an url preview like the facebook attachment",
5 | "keywords": [
6 | "liveurl",
7 | "url",
8 | "attachement",
9 | "facebook"
10 | ],
11 | "version": "1.2.2",
12 | "author": {
13 | "name": "Stephan Fischer",
14 | "url": "https://github.com/stephan-fischer"
15 | },
16 | "maintainers": [
17 | {
18 | "name": "Stephan Fischer",
19 | "email": "stephan@ainetworks.de",
20 | "url": "http://www.ainetworks.de"
21 | }
22 | ],
23 | "licenses": [
24 | {
25 | "type": "MIT",
26 | "url" : "https://github.com/stephan-fischer/jQuery-LiveUrl"
27 | }
28 | ],
29 | "bugs": "https://github.com/stephan-fischer/jQuery-LiveUrl/issues",
30 | "homepage": "https://github.com/stephan-fischer/jQuery-LiveUrl",
31 | "docs": "https://github.com/jquery/jquery-color",
32 | "download": "https://github.com/stephan-fischer/jQuery-LiveUrl/archive/master.zip",
33 | "demo" : "http://liveurl.ainetworks.de/demo/",
34 | "dependencies": {
35 | "jquery": ">=1.8.2"
36 | }
37 | }
--------------------------------------------------------------------------------
/url-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stephan-fischer/jQuery-LiveUrl/ac4f7f42c98d0b50b012ca8061ffbd35d7a06802/url-loader.gif
--------------------------------------------------------------------------------