PageSourceSearch

https://www.tvaruzky.cz/wp-content/plugins/booking-system/assets/j…ery.dop.frontend.BSPSearch.js?ver=2.9.9.6.9

js tvaruzky.cz collected 2026-09-24 20:30:29 UTC 98,405 bytes, 2,362 lines download raw bytes

1
2/*
3* Title                   : Pinpoint Booking System WordPress Plugin (PRO)
4* Version                 : 2.1.2
5* File                    : assets/js/jquery.dop.frontend.BSPSearch.js
6* File Version            : 1.0.2
7* Created / Last Modified : 11 October 2015
8* Author                  : Dot on Paper
9* Copyright               : © 2012 Dot on Paper
10* Website                 : http://www.dotonpaper.net
11* Description             : Front end search jQuery plugin.
12*/
13
14(function($){
15    'use strict';
16    
17    $.fn.DOPBSPSearch = function(options){
18        /*
19         * Private variables. 
20         */
21        var Data = {"availability": {"data": {"enabled": false,
22                                              "max": 10,
23                                              "min": 1},
24                                     "text": {"title": "No. book items"}},
25                    "currency": {"data": {"code": "USD",
26                                          "position": "before",
27                                          "sign": "$"},
28                                 "text":{},         
29                    "days": {"data": {"first": 1,
30                                      "multipleSelect": true},
31                             "text": {"names": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
32                                      "shortNames": ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]}},
33                    "hours": {"data": {"ampm": false,
34                                       "definitions": [{"value": "00:00"},{"value": "01:00"},{"value": "02:00"},{"value": "03:00"},{"value": "04:00"},{"value": "05:00"},{"value": "06:00"},{"value": "07:00"},{"value": "08:00"},{"value": "09:00"},{"value": "10:00"},{"value": "11:00"},{"value": "12:00"},{"value": "13:00"},{"value": "14:00"},{"value": "15:00"},{"value": "16:00"},{"value": "17:00"},{"value": "18:00"},{"value": "19:00"},{"value": "20:00"},{"value": "21:00"},{"value": "22:00"},{"value": "23:00"}],
35                                       "enabled": false,
36                                       "multipleSelect": true},
37                              "text": {}},
38                    "ID": 0,
39                    "months": {"data": {},
40                               "text": {"names": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
40November", "December"],
41                                        "nextMonth": "Next month",
42                                        "previousMonth": "Previous month",
43                                        "shortNames": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]}},
44                    "price": {"data": {"enabled": true,
45                                       "max": 1000,
46                                       "min": 0},
47                              "text": {}},
48                    "search": {"data": {"dateType": 1,
49                                        "enabled": false,
50                                        "language": 'en',
51                                        "template": 'default'},
52                               "text": {"checkIn": "Check in",
53                                        "checkOut": "Check out",
54                                        "hourEnd": "Finish at",
55                                        "hourStart": "Start at",
56                                        "title": "Search"}},  
57                    "sort": {"data": {},
58                             "text": {"name": "Name",
59                                      "price": "Price",
60                                      "title": "Sort by"}},
61                    "URL": "",
62                    "view": {"data": {"default": "list",
63                                      "gridEnabled": false,
64                                      "listEnabled": true,
65                                      "mapEnabled": false,
66                                      "results": 10},
67                             "text": {"grid": "Grid view",
68                                      "list": "List view",
69                                      "map": "Map view"}}}},
70                              
71        ajaxRequestInProgress,
72        ajaxURL = '',
73        Container = this,
74        ID = 0,
75        
76// ***************************************************************************** Main methods.
77
78// 1. Main methods.
79
80        methods = {
81            init:function(){
82                /*
83                 * Initialize jQuery plugin.
84                 */
85                return this.each(function(){
86                    if (options){
87                        $.extend(Data, options);
88                    }
89
90                    methods.parse();
91                    $(window).bind('resize.DOPBSPSearch', methods.rp);                          
92                });
93            },
94            parse:function(){
95                ajaxURL = prototypes.acaoBuster(Data['URL']);
96                
97                methods_availability.data = Data['availability']['data'];
98                methods_availability.text = Data['availability']['text'];
99                
100                methods_currency.data = Data['currency']['data'];
101                methods_currency.text = Data['currency']['text'];
102                
103                methods_days.data = Data['days']['data'];
104                methods_days.text = Data['days']['text'];
105                
106                methods_hours.data = Data['hours']['data'];
107                methods_hours.text = Data['hours']['text'];
108                
109                ID = Data['ID'];
110                
111                methods_months.data = Data['months']['data'];
112                methods_months.text = Data['months']['text'];
113                
114                methods_price.data = Data['price']['data'];
115                methods_price.text = Data['price']['text'];
116                
117                methods_search.data = Data['search']['data'];
118                methods_search.text = Data['search']['text'];
119                
120                methods_sort.data = Data['sort']['data'];
121                methods_sort.text = Data['sort']['text'];
122                
123                methods_view.data = Data['view']['data'];
124                methods_view.text = Data['view']['text'];
125                
126                methods_components.init();
127            },
128            rp:function(){
129		var $container = $(Container),
130		width = $container.width();
131		
132		/*
133		 * Reset data.
134		 */
135		$container.removeClass('desktop')
136			  .removeClass('laptop')
137			  .removeClass('tablet')
138			  .removeClass('mobile');
139		  
140		if (width >= 1170){
141		    $container.addClass('desktop');
142		}
143		else if (width >= 940
144			    && width <= 1169){
145		    $container.addClass('laptop');
146		}
147		else if (width >= 700
148			    && width <= 939){
149		    $container.addClass('tablet');
150		}
151		else if (width <= 699){
152		    $container.addClass('mobile');
153		}
154            }
155        },
156                
157// 2. Components
158        
159        methods_components = {
160            init:function(){
161            /*
162             * Initialize search components.
163             */ 
164                /*
165                 * Initialize today date.
166                 */
167                methods_search.vars.todayDate = new Date();
168                methods_search.vars.todayDay = methods_search.vars.todayDate.getDate();
169                methods_search.vars.todayMonth = methods_search.vars.todayDate.getMonth()+1;
170                methods_search.vars.todayYear = methods_search.vars.todayDate.getFullYear(); 
171                
172                /*
173                 * Initialize map.
174                 */
175                if (methods_view.data['mapEnabled']){
176                    methods_map.load();
177                }
178                
179                /*
180                 * Initialize sidebar.
181                 */
182                methods_sidebar.init();
183                methods.rp();
184                
185                $('#DOPBSPSearch-loader'+ID).remove();
186                $(Container).removeClass('DOPBSPSearch-hidden');
187                
188                methods_search.get();
189            }
190        },  
191                
192// 3. Currency
193        
194        methods_currency = {
195            data:{},
196            text:{},
197            vars: {currencies: {}},
198            
199            init: function() {
200                //methods_currency.parse();
201            },
202            
203            parse: function(){
204                var currencies = {};
205                
206                if (typeof methods_currency.data['currencies'] !== 'undefined') {
207                    var currenciesJSON = methods_currency.data['currencies'].replace(new RegExp('"', 'g'), ""),
208                        currenciesJSON = currenciesJSON.replace(new RegExp(';;;', 'g'), '"');
209                
210                        currencies = JSON.parse(currenciesJSON);
211                }
212            
213                methods_currency.vars.currencies = currencies;
214                
215            },
216            
217            exchange: function(amount, currency_code, type){ 
218                var currencies = methods_currency.vars.currencies;
219                //methods_currency.data['sign']
220                if (methods_currency.data['code'] !== currency_code) {
221                    
222                    for (var index in currencies){
223
224                        if (currencies[index]['code'] === currency_code) {
225                            
226                            if (type === 'exchange') {
227                                amount = parseInt(amount*currencies[index]['rate']);
228                            } else {
229                                amount = parseInt(amount*currencies[index]['inverse']);
230                            }
231                        }
232                    }
233                }
234                
235                return amount;
236            }
237            
238        },   
239   
240// ***************************************************************************** Search methods.
241
242// 4. Search
243        
244        methods_search = {
245            data: {},
246            text: {},
247            vars: {todayDate: new Date(),
248                   todayDay: new Date(),
249                   todayMonth: new Date(),
250                   todayYear: new Date()},
251            
252            init: function(){
253                methods_days.init();
254                
255                if (methods_hours.data['enabled']){
256                    methods_hours.init();
257                }
258                
259                if (methods_availability.data['enabled']){
260                    methods_availability.init();
261                }
262                
263                if (methods_price.data['enabled']){
264                    methods_price.init();
265                }
266                
267                methods_sort.init();
268                methods_view.init();
269            },
270            
271            get:function(page){
272                var $checkIn = $('#DOPBSPSearch-check-in'+ID).val(),
273                $checkOut = $('#DOPBSPSearch-check-out'+ID).val(),
274                $startHour = $('#DOPBSPSearch-start-hour'+ID).val(),
275                $endHour = $('#DOPBSPSearch-end-hour'+ID).val(),
276                checkIn = $checkIn === undefined ? '':$checkIn,
277                checkOut = $checkOut === undefined || $checkOut === '' ? checkIn:$checkOut,
278                startHour = $startHour === undefined ? '':$startHour,
279                endHour = $endHour === undefined || $endHour === '' ? startHour:$endHour;
280        
281                page = page === undefined ? 1:page;
282                
283                if (ajaxRequestInProgress !== undefined){
284                    ajaxRequestInProgress.abort();
285                }
286                $('#DOPBSPSearch-results-loader'+ID).removeClass('DOPBSPSearch-hidden');
287                $('#DOPBSPSearch-results'+ID).html('');
288                
289                ajaxRequestInProgress = $.post(ajaxURL, {action: 'dopbsp_search_results_get',
290                                                         dopbsp_frontend_ajax_request: true,
291                                                         id: ID,
292                                                         language: methods_search.data['language'],
293                                                         check_in: checkIn,
294                                                         check_out: checkOut,
295                                                         start_hour: startHour,
296                                                         end_hour: endHour,
297                                                         no_items: $('#DOPBSPSearch-no-items'+ID).val() === undefined ? '':$('#DOPBSPSearch-no-items'+ID).val(),
298                                                         price_min: $('#DOPBSPSearch-price-min-value'+ID).val() === undefined ? '':$('#DOPBSPSearch-price-min-value'+ID).val(),
299                                                         price_max: $('#DOPBSPSearch-price-max-value'+ID).val() === undefined ? '':$('#DOPBSPSearch-price-max-value'+ID).val(),
300                                                         sort_by: $('#DOPBSPSearch-sort-by'+ID).val() === undefined ? 'price':$('#DOPBSPSearch-sort-by'+ID).val(),
301                                                         sort_direction: $('#DOPBSPSearch-sort-direction-value'+ID).val() === undefined ? 'ASC':$('#DOPBSPSearch-sort-direction-value'+ID).val(),
302                                                         view: $('#DOPBSPSearch-view'+ID).val() === undefined ? 'list':$('#DOPBSPSearch-view'+ID).val(),
303                                                         results: methods_view.data['results'],
304                                                         page: page}, function(data){
305                        data = $.trim(data);
306                        
307                        switch ($('#DOPBSPSearch-view'+ID).val()){
308                            case 'map':
309                                methods_map.display(data);
310                                break;
311                            default:
312                                $('#DOPBSPSearch-results-loader'+ID).addClass('DOPBSPSearch-hidden');
313                                $('#DOPBSPSearch-results'+ID).html(data);
314                                methods_search.events();
315                        }
316                });
317            },
318            
319            events:function(){
320                $('#DOPBSPSearch-results'+ID+' .dopbsp-pagination li').unbind('click');
321                $('#DOPBSPSearch-results'+ID+' .dopbsp-pagination li').bind('click', function(){
322                    if (!$(this).hasClass('selected')){
323                        methods_search.get($(this).attr('class').split('dopbsp-page')[1]);
324                    }
325                });
326            }
327        },      
328        
329// 5. Sidebar
330        
331        methods_sidebar = {
332            data:{},
333            text:{},
334            
335            init:function(){
336                methods_search.init();
337                
338                // $('.dopbsp-search-sidebar-form', Container).isotope({itemSelector: '.dopbsp-module', layoutMode: 'fitRows' });
339            }
340        },    
341                
342// 6. Months
343        
344        methods_months = {
345            data:{},
346            text:{}
347        },
348                
349// 7. Days
350        
351        methods_days = {
352            data:{},
353            text:{},
354            
355            init:function(){
356            /*
357             * Initialize sidebar search days.
358             */ 
359                methods_days.events.init();
360                methods_search.get();
361            },
362            initDatepicker:function(id,
363                                    altId,    
364                                    minDate){
365            /*
366             * Initialize sidebar search datepicker.
367             * 
368             * @param id (String): input(text) field ID
369             * @param aldId (String): alternative input(hidden) field ID
370             * @param minDate (Number): start date from today
371             */                            
372                minDate = minDate === undefined ? 0:minDate;  
373
374                $(id).datepicker('destroy');
375                $(id).datepicker({altField: altId,
376                                  altFormat: 'yy-mm-dd',
377                                  beforeShow: function(input, inst){
378                                    $('#ui-datepicker-div').removeClass('DOPBSPSearch-datepicker')
379                                                           .addClass('DOPBSPSearch-datepicker');
380                                  },
381                                  dateFormat: methods_search.data['dateType'] === 1 ? 'MM dd, yy':'dd MM yy',
382                                  dayNames: methods_days.text['names'],
383                                  dayNamesMin: methods_days.text['shortNames'],
384                                  firstDay: methods_days.data['first'],
385                                  minDate: minDate,
386                                  monthNames: methods_months.text['names'],
387                                  monthNamesMin: methods_months.text['shortNames'],
388                                  nextText: methods_months.text['nextMonth'],
389                                  prevText: methods_months.text['previousMonth']});
390                $('.ui-datepicker').removeClass('notranslate').addClass('notranslate');
391            },
392            validate:function(day){
393            /*
394             * Validate day format.
395             * 
396             * @param day (String): day format to be verified
397             * 
398             * @return true if format is "YYYY-MM-DD"
399             */    
400                var dayPieces = day.split('-');
401
402                if (day === ''
403                        || dayPieces.length !== 3
404                        || dayPieces[0].length !== 4
405                        || dayPieces[1].length !== 2
406                        || dayPieces[2].length !== 2){
407                    return false;
408                }
409                else{
410                    return true;
411                }
412            },
413
414            events: {
415                init:function(){
416                /*
417                 * Initialize sidebar search days events.
418                 */    
419                    /*
420                     * Initialize check in datepicker.
421                     */
422                    methods_days.initDatepicker('#DOPBSPSearch-check-in-view'+ID,
423                                                       '#DOPBSPSearch-check-in'+ID);
424                    methods_days.events.checkIn();
425
426                    if (methods_days.data['multipleSelect']){
427                        /*
428                         * Initialize check out datepicker.
429                         */
430                        methods_days.initDatepicker('#DOPBSPSearch-check-out-view'+ID,
431                                                           '#DOPBSPSearch-check-out'+ID);
432                        methods_days.events.checkOut();
433                    }
434                },
435                checkIn:function(){
436                /*
437                 * Initialize sidebar search days events when multiple days need to be selected.
438                 */
439                    /*
440                     * Check in click event.
441                     */
442                    $('#DOPBSPSearch-check-in-view'+ID).unbind('click');
443                    $('#DOPBSPSearch-check-in-view'+ID).bind('click', function(){
444                        $(this).val('');
445                        $('#DOPBSPSearch-check-in'+ID).val('');
446
447                    });
448
449                    /*
450                     * Check in blur event.
451                     */
452                    $('#DOPBSPSearch-check-in-view'+ID).unbind('blur');
453                    $('#DOPBSPSearch-check-in-view'+ID).bind('blur', function(){  
454                        var $this = $(this);
455
456                        if ($this.val() === ''){
457                            $this.val(methods_search.text['checkIn']);
458                            $('#DOPBSPSearch-check-in'+ID).val('');
459                        }
460                    });
461
462                    /*
463                     * Check in change event.
464                     */
465                    $('#DOPBSPSearch-check-in-view'+ID).unbind('change');
466                    $('#DOPBSPSearch-check-in-view'+ID).bind('change', function(){
467                        var ciDay = $('#DOPBSPSearch-check-in'+ID).val(),
468                        minDateValue;
469
470                        if (methods_days.validate(ciDay)){
471                            if (methods_days.data['multipleSelect']){
472                                minDateValue = prototypes.getNoDays(prototypes.getToday(), ciDay)-1;
473
474                                methods_days.initDatepicker('#DOPBSPSearch-check-out-view'+ID,
475                                                            '#DOPBSPSearch-check-out'+ID,
476                                                            minDateValue);
477
478                                if (($('#DOPBSPSearch-check-in'+ID).val() > $('#DOPBSPSearch-check-out'+ID).val()
479                                                && $('#DOPBSPSearch-check-out'+ID).val() !== '')
480                                        || $('#DOPBSPSearch-check-out'+ID).val() === ''){
481                                    setTimeout(function(){
482                                        $('#DOPBSPSearch-check-out-view'+ID).val('')
483                                                                              .select();  
484                                        $('#DOPBSPSearch-check-out'+ID).val('');
485                                    }, 100);
486                                }
487                                else{
488                                    methods_search.get();
489                                }
490                            }
491                            else{
492                                methods_search.get();
493                            }
494                        }
495                        else{
496                            $('#DOPBSPSearch-check-in-view'+ID).val(methods_search.text['checkIn']);
497                            $('#DOPBSPSearch-check-in'+ID).val('');
498                        }
499                    });
500                },
501                checkOut:function(){
502                    /*
503                     * Check out click event.
504                     */
505                    $('#DOPBSPSearch-check-out-view'+ID).unbind('click');
506                    $('#DOPBSPSearch-check-out-view'+ID).bind('click', function(){  
507                        $(this).val(''); 
508                        $('#DOPBSPSearch-check-out'+ID).val('');
509                    });
510
511                    /*
512                     * Check out blur event.
513                     */
514                    $('#DOPBSPSearch-check-out-view'+ID).unbind('blur');
515                    $('#DOPBSPSearch-check-out-view'+ID).bind('blur', function(){ 
516                        var $this = $(this);
517
518                        if ($this.val() === ''){
519                            $this.val(methods_search.text['checkOut']);
520                            $('#DOPBSPSearch-check-out'+ID).val('');
521                        }
522                    });
523
524                    /*
525                     * Check out change event.
526                     */
527                    $('#DOPBSPSearch-check-out-view'+ID).unbind('change');
528                    $('#DOPBSPSearch-check-out-view'+ID).bind('change', function(){
529                        var coDay = $('#DOPBSPSearch-check-out'+ID).val();
530                        
531                        if (methods_days.validate(coDay)){
532                            if ($('#DOPBSPSearch-check-in'+ID).val() !== ''){
533                                methods_search.get();
534                            }
535                        }
536                        else{
537                            $('#DOPBSPSearch-check-out-view'+ID).val(methods_search.text['checkOut']);
538                            $('#DOPBSPSearch-check-out'+ID).val('');
539                        }
540                    });
541                }
542            }
543        },
544                
545// 8. Hours
546        
547        methods_hours = {
548            data:{},
549            text:{},
550                
551            init:function(){
552                $('#DOPBSPSearch-start-hour'+ID).DOPSelect();
553
554                if (methods_hours.data['multipleSelect']){
555                    $('#DOPBSPSearch-end-hour'+ID).DOPSelect();
556                }
557                methods_hours.events();
558            },
559            set:function(){
560                var HTML = new Array(),
561                hours = methods_hours.data['definitions'],
562                i,
563                startHour = $('#DOPBSPSearch-start-hour'+ID).val(),
564                endHour = $('#DOPBSPSearch-end-hour'+ID).val();
565
566                HTML.push('<select id="DOPBSPSearch-end-hour'+ID+'" class="dopbsp-small">');
567
568                for (i=0; i<hours.length; i++){
569                    if (startHour <= hours[i]['value']){
570                        HTML.push('     <option value="'+hours[i]['value']+'"'+(endHour === hours[i]['value'] ? ' selected="selected"':'')+'>'+(methods_hours.data['ampm'] === true ? prototypes.getAMPM(hours[i]['value']):hours[i]['value'])+'</option>');
571                    }
572                }
573                HTML.push('</select>');
574
575                $('#DOPSelect-DOPBSPSearch-end-hour'+ID).replaceWith(HTML.join());
576                $('#DOPBSPSearch-end-hour'+ID).DOPSelect();
577                methods_hours.events();
578            },
579
580            events:function(){
581                $('#DOPBSPSearch-start-hour'+ID).unbind('change');
582                $('#DOPBSPSearch-start-hour'+ID).bind('change',function(){
583                    if (methods_hours.data['multipleSelect']){
584                        methods_hours.set();
585                    }
586                    methods_search.get();
587                });
588
589                if (methods_hours.data['multipleSelect']){
590                    $('#DOPBSPSearch-end-hour'+ID).unbind('change');
591                    $('#DOPBSPSearch-end-hour'+ID).bind('change',function(){
592                        if ($('#DOPBSPSearch-start-hour'+ID).val() !== ''){
593                            methods_search.get();
594                        }
595                    });
596                }
597            }
598        },
599                
600// 9. No items.
601        
602        methods_availability = {
603            data:{},
604            text:{},
605            
606            init:function(){
607                $('#DOPBSPSearch-no-items'+ID).DOPSelect();
608                methods_availability.events();
609            },
610
611            events:function(){
612                $('#DOPBSPSearch-no-items'+ID).unbind('change');
613                $('#DOPBSPSearch-no-items'+ID).bind('change',function(){
614                    methods_search.get();
615                });
616            }
617        },
618                
619// 10. Price         
620                
621        methods_price = {
622            data:{},
623            text:{},
624            
625            init:function(){
626                $('#DOPBSPSearch-price'+ID).slider({max: methods_price.data['max'],
627                                                    min: methods_price.data['min'],
628                                                    values: [methods_price.data['min'], methods_price.data['max']],
629                                                    range: true,
630                                                    step: 0.1,
631                                                    create:function(event, ui){
632                                                        $('#DOPBSPSearch-price-min'+ID).html(methods_price.set(methods_price.data['min']));
633                                                        $('#DOPBSPSearch-price-max'+ID).html(methods_price.set(methods_price.data['max']));
634                                                        
635                                                        $('#DOPBSPSearch-price-min-value'+ID).val(methods_price.data['min']);
636                                                        $('#DOPBSPSearch-price-max-value'+ID).val(methods_price.data['max']);
637                                                    },
638                                                    slide:function(event, ui){
639                                                        $('#DOPBSPSearch-price-min'+ID).html(methods_price.set(ui.values[0]));
640                                                        $('#DOPBSPSearch-price-max'+ID).html(methods_price.set(ui.values[1]));
641                                                        
642                                                        $('#DOPBSPSearch-price-min-value'+ID).val(ui.values[0]);
643                                                        $('#DOPBSPSearch-price-max-value'+ID).val(ui.values[1]);
644                                                    },
645                                                    stop:function(event, ui){
646                                                        methods_search.get();
647                                                    }});
648            },
649            
650            set:function(price){
651            /*
652             * Display price with currency in set format.
653             * 
654             * @param price (Number): price value
655             * 
656             * @return price with currency
657             */ 
658                var priceDisplayed = '';
659                
660                price = prototypes.getWithDecimals(Math.abs(price), 
661                                                   2);
662                                                   
663                switch (methods_currency.data['position']){
664                    case 'after':
665                        priceDisplayed =  price+methods_currency.data['sign'];
666                        break;
667                    case 'after_with_space':
668                        priceDisplayed =  price+' '+methods_currency.data['sign'];
669                        break;
670                    case 'before_with_space':
671                        priceDisplayed =  methods_currency.data['sign']+' '+price;
672                        break;
673                    default:
674                        priceDisplayed = methods_currency.data['sign']+price;
675                }
676                
677                return priceDisplayed;
678            }
679        },   
680                
681// 11. Sort
682        
683        methods_sort = {
684            data:{},
685            text:{},
686            
687            init:function(){
688                $('#DOPBSPSearch-sort-by'+ID).DOPSelect();
689                methods_sort.events();
690            },
691
692            events: function(){
693                $('#DOPBSPSearch-sort-by'+ID).unbind('change');
694                $('#DOPBSPSearch-sort-by'+ID).bind('change',function(){
695                    methods_search.get();
696                });
697
698                $('#DOPBSPSearch-sort-direction'+ID).unbind('click');
699                $('#DOPBSPSearch-sort-direction'+ID).bind('click',function(){
700                    if ($(this).hasClass('dopbsp-asc')){
701                        $(this).removeClass('dopbsp-asc')
702                               .addClass('dopbsp-desc');
703                        $('#DOPBSPSearch-sort-direction-value'+ID).val('DESC');
704                    }
705                    else{
706                        $(this).removeClass('dopbsp-desc')
707                               .addClass('dopbsp-asc');
708                        $('#DOPBSPSearch-sort-direction-value'+ID).val('ASC');
709                    }
710                    methods_search.get();
711                });
712            }
713        },
714                
715// 12. View
716        
717        methods_view = {
718            data:{},
719            text:{},
720            
721            init:function(){
722                methods_view.events();
723            },
724            
725            events:function(){
726                if (methods_view.data['listEnabled']){
727                    $('#DOPBSPSearch-view-list'+ID).unbind('click');
728                    $('#DOPBSPSearch-view-list'+ID).bind('click',function(){
729                        if (!$(this).hasClass('dopbsp-selected')){
730                            methods_view.data['gridEnabled'] ? $('#DOPBSPSearch-view-grid'+ID).removeClass('dopbsp-selected'):'';
731                            methods_view.data['mapEnabled'] ? $('#DOPBSPSearch-view-map'+ID).removeClass('dopbsp-selected'):'';
732                            $(this).addClass('dopbsp-selected');
733                            
734                            $('#DOPBSPSearch-view'+ID).val('list');
735                            methods_search.get();
736                        }
737                    });
738                }
739                
740                if (methods_view.data['gridEnabled']){
741                    $('#DOPBSPSearch-view-grid'+ID).unbind('click');
742                    $('#DOPBSPSearch-view-grid'+ID).bind('click',function(){
743                        if (!$(this).hasClass('dopbsp-selected')){
744                            methods_view.data['listEnabled'] ? $('#DOPBSPSearch-view-list'+ID).removeClass('dopbsp-selected'):'';
745                            methods_view.data['mapEnabled'] ? $('#DOPBSPSearch-view-map'+ID).removeClass('dopbsp-selected'):'';
746                            $(this).addClass('dopbsp-selected');
747                            
748                            $('#DOPBSPSearch-view'+ID).val('grid');
749                            methods_search.get();
750                        }
751                    });
752                }
753                
754                if (methods_view.data['mapEnabled']){
755                    $('#DOPBSPSearch-view-map'+ID).unbind('click');
756                    $('#DOPBSPSearch-view-map'+ID).bind('click',function(){
757                        if (!$(this).hasClass('dopbsp-selected')){
758                            methods_view.data['listEnabled'] ? $('#DOPBSPSearch-view-list'+ID).removeClass('dopbsp-selected'):'';
759                            methods_view.data['gridEnabled'] ? $('#DOPBSPSearch-view-grid'+ID).removeClass('dopbsp-selected'):'';
760                            $(this).addClass('dopbsp-selected');
761                            
762                            $('#DOPBSPSearch-view'+ID).val('map');
763                            methods_search.get();
764                        }
765                    });
766                }
767            }
768        },
769                
770// 13. Map
771        
772        methods_map = {
773            vars:{locations: new Array(),
774                  map: null},
775            
776            load:function(){
777                if (typeof google !== 'object' 
778                        || typeof google.maps !== 'object'){
779                    var script = document.createElement('script');
780                    
781                    script.type = 'text/JavaScript';
782                    script.src = 'https://maps.googleapis.com/ma
782ps/api/js?key='+dopbspGoogleAPIkey+'&v=3.exp&libraries=places&callback=DOPBSPSearchLoadInfobox';
783                    
784                    $('body').append(script);
785                }
786                else{
787                    DOPBSPSearchLoadInfobox();
788                }
789            },
790            
791            display:function(data){
792                var HTML = new Array();
793                if (typeof google === 'object' 
794                        && typeof google.maps === 'object'
795                        && typeof InfoBox === 'function'){
796                    methods_map.vars.locations = JSON.parse(data.split(';;;;;')[0]);
797                    
798                    HTML.push('<div id="DOPBSPSearch-results-map'+ID+'" class="dopbsp-map"></div>');
799                    HTML.push(data.split(';;;;;')[1]);
800                    
801                    $('#DOPBSPSearch-results-loader'+ID).addClass('DOPBSPSearch-hidden');
802                    $('#DOPBSPSearch-results'+ID).html(HTML.join(''));
803                    
804                    methods_search.events();
805                    
806                    setTimeout(function(){
807                        google.maps.event.addDomListener(window, 'load', methods_map.init());
808                    }, 100);
809                }
810                else{
811                    setTimeout(function(){
812                        methods_map.display();
813                    }, 500);
814                }
815                
816            },
817            init:function(){
818                var //$coordinates = $('#DOPBSP-location-coordinates').val(),
819                //coordinates = $coordinates === undefined || $coordinates === '' || $coordinates === ' ' ? [0, 0]:JSON.parse($coordinates),
820                options;
821               // zoom = coordinates[0] === 0 && coordinates[1] === 0  ? 2:17;
822
823                options = {center: new google.maps.LatLng(0, 0),
824                           mapTypeId: google.maps.MapTypeId.ROADMAP,
825                           zoom: 2};
826                /*
827                 * Create the map
828                 */          
829                methods_map.vars.map = new google.maps.Map(document.getElementById('DOPBSPSearch-results-map'+ID), options);
830
831//                DOPBSPBackEndLocationMapMarker.set(map,
832//                                            coordinates);
833                methods_map.set();
834            },
835            set:function(){
836                var bounds = new google.maps.LatLngBounds(),
837                coordinates,
838                icon = new google.maps.MarkerImage(methods_search.data['template']+'/images/marker.png',
839                                                   new google.maps.Size(36, 52),
840                                                   new google.maps.Point(1, 0),
841                                                   new google.maps.Point(18, 52)),
842                i,
843                locations = methods_map.vars.locations,
844                markers = new Array(),
845                position = new Array(),
846                shadow = new google.maps.MarkerImage(methods_search.data['template']+'/images/marker.png',
847                                                     new google.maps.Size(36, 52),
848                                                     new google.maps.Point(1, 0),
849                                                     new google.maps.Point(18, 52)),
850                shape = {coord: [0, 0, 36, 0, 36, 52, 0, 52],
851                         type: 'poly'};   
852                     
853                for (i=0; i<locations.length; i++){
854                    coordinates = JSON.parse(locations[i]['coordinates']);
855                    position = new google.maps.LatLng(coordinates[0], coordinates[1]);
856                    bounds.extend(position);
857                    
858                    markers[i] = new google.maps.Marker({animation: null,
859                                                         clickable: true,
860                                                         draggable: false,
861                                                         icon: icon,
862                                                         map: methods_map.vars.map,
863                                                         position: position,
864                                                         shadow: shadow,
865                                                         shape: shape});
866
867                    markers[i].info = new InfoBox({alignBottom: true,
868                                                   boxClass: 'dopbsp-infobox',
869                                                   closeBoxMargin: '0px',
870                                                   closeBoxURL: methods_search.data['template']+'/images/close.png',
871                                                   disableAutoPan: false,
872                                                   content: methods_map.get(locations[i]['calendars'], i),
873                                                   isHidden: false,
874                                                   infoBoxClearance: new google.maps.Size(20, 20),
875                                                   pixelOffset: new google.maps.Size(-190, -60),
876                                                   position: position});
877                                               
878                    markers[i].index = i;
879                                               
880                    google.maps.event.addListener(markers[i], 'click', function(){
881                        var index = this.index;
882                        
883                        for (i=0; i<locations.length; i++){
884                            markers[i].info.close();
885                        }
886                        this.info.open(methods_map.vars.map, this);
887                        
888                        setTimeout(function(){
889                            methods_map.events(index);
890                        }, 100);
891                    });
892                }
893                methods_map.vars.map.fitBounds(bounds);
894            },
895            
896            get:function(calendars,
897                         index){
898                var HTML = new Array(),
899                i;
900                
901                HTML.push('<ul class="dopbsp-locations" id="DOPBSPSearch-locations-'+ID+'-'+index+'">');
902                for (i=0; i<calendars.length; i++){
903                    HTML.push('<li>');
904                    HTML.push('     <div class="dopbsp-image">');
905                    HTML.push('         <a href="'+calendars[i]['link']+'" target="_self" style="background-image: url('+calendars[i]['image']+');">');
906                    HTML.push('             <img src="'+calendars[i]['image']+'" alt="'+calendars[i]['name']+'" title="'+calendars[i]['name']+'" />');
907                    HTML.push('         </a>');
908                    HTML.push('     </div>');
909                    HTML.push('     <div class="dopbsp-content">');
910                    HTML.push('         <h3>');
911                    HTML.push('             <a href="'+calendars[i]['link']+'" target="_self">'+calendars[i]['name']+'</a>');
912                    HTML.push('         </h3>');
913                    HTML.push('         <div class="dopbsp-address">'+(calendars[i]['address_alt'] === '' ? calendars[i]['address']:calendars[i]['address_alt'])+'</div>');
914                    HTML.push('         <div class="dopbsp-price-wrapper">'+calendars[i]['price']+'</div>');
915                    HTML.push('     </div>');
916                    HTML.push('</li>');
917                }
918                HTML.push('</ul>');                                         
919                
920                if (calendars.length > 1){
921                    HTML.push('<div class="dopbsp-navigation" id="DOPBSPSearch-locations-navigation-'+ID+'-'+index+'">');
922                    HTML.push('     <a href="javascript:void(0)" class="dopbsp-prev dopbsp-disabled"></a>');
923                    HTML.push('     <a href="javascript:void(0)" class="dopbsp-next"></a>');
924                    HTML.push('</div>');
925                }
926                
927                return HTML.join(''); 
928            },
929            
930            events:function(i){
931                $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-prev').unbind('click');
932                $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-prev').bind('click', function(){
933                    var $this = $(this),
934                    id = $this.parent().attr('id').split('DOPBSPSearch-locations-navigation-')[1],
935                    $li = $('#DOPBSPSearch-locations-'+id+' li:first-child');
936                    
937                    if (!$this.hasClass('dopbsp-disabled')){
938                        $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-next').removeClass('dopbsp-disabled');
939                        $li.css('margin-top', parseInt($li.css('margin-top'))+($li.height()+parseInt($li.css('margin-bottom'))));
940                        
941                        setTimeout(function(){
942                            if (parseInt($li.css('margin-top')) >= 0){
943                                $this.addClass('dopbsp-disabled');
944                            }
945                        }, 150);
946                    }
947                });
948                
949                $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-next').unbind('click');
950                $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-next').bind('click', function(){
951                    var $this = $(this),
952                    id = $this.parent().attr('id').split('DOPBSPSearch-locations-navigation-')[1],
953                    $li = $('#DOPBSPSearch-locations-'+id+' li:first-child'),
954                    locations = methods_map.vars.locations;
955                    
956                    if (!$this.hasClass('dopbsp-disabled')){
957                        $('#DOPBSPSearch-locations-navigation-'+ID+'-'+i+' .dopbsp-prev').removeClass('dopbsp-disabled');
958                        $li.css('margin-top', parseInt($li.css('margin-top'))-($li.height()+parseInt($li.css('margin-bottom'))));
959                        
960                        setTimeout(function(){
961                            if (-1*parseInt($li.css('margin-top')) >= ($li.height()+parseInt($li.css('margin-bottom')))*(locations.length-1)){
962                                $this.addClass('dopbsp-disabled');
963                            }
964                        }, 150);
965                    }
966                });
967            }
968        },
969
970// ***************************************************************************** Prototypes
971        
972// 14. Prototypes
973
974        prototypes = {
975// Actions                  
976            doHiddenBuster:function(item){
977            /*
978             * Make all parents & current item visible.
979             * 
980             * @param item (element): item for which all parens are going to be made visible
981             * 
982             * @return list of parents
983             */
984                var parent = item.parent(),
985                items = new Array();
986
987                if (item.prop('tagName') !== undefined 
988                        && item.prop('tagName').toLowerCase() !== 'body'){
989                    items = prototypes.doHiddenBuster(parent);
990                }
991
992                if (item.css('display') === 'none'){
993                    item.css('display', 'block');
994                    items.push(item);
995                }
996
997                return items;
998            },
999            undoHiddenBuster:function(items){
1000            /*
1001             * Hide all items from list. The list is returned by function doHiddenBuster().
1002             * 
1003             * @param items (Array): list of items to be hidden
1004             */    
1005                var i;
1006
1007                for (i=0; i<items.length; i++){
1008                    items[i].css('display', 'none');
1009                }
1010            },
1011            openLink:function(url,
1012                              target){
1013            /*
1014             * Open a link.
1015             * 
1016             * @param url (String): link URL
1017             * @param target (String): link target (_blank, _parent, _self, _top)
1018             */
1019                switch (target.toLowerCase()){
1020                    case '_blank':
1021                        window.open(url);
1022                        break;
1023                    case '_parent':
1024                        parent.location.href = url;
1025                        break;
1026                    case '_top':
1027                        top.location.href = url;
1028                        break;
1029                    default:    
1030                        window.location = url;
1031                }
1032            },
1033            randomizeArray:function(theArray){
1034            /*
1035             * Randomize the items of an array.
1036             * 
1037             * @param theArray (Array): the array to be mixed
1038             * 
1039             * return array with mixed items
1040             */
1041                theArray.sort(function(){
1042                    return 0.5-Math.random();
1043                });
1044                return theArray;
1045            },
1046            scrollToY:function(position,
1047                               speed){
1048            /*
1049             * Scroll vertically to position.
1050             * 
1051             * @param position (Number): position to scroll to
1052             * @param speed (Number): scroll speed 
1053             */  
1054                speed = speed !== undefined ? speed: 300;
1055
1056                $('html').stop(true, true)
1057                         .animate({'scrollTop': position}, 
1058                                  speed);
1059                $('body').stop(true, true)
1060                         .animate({'scrollTop': position}, 
1061                                  speed);
1062            },
1063            touchNavigation:function(parent,
1064                                     child){
1065            /*
1066             * One finger navigation for touchscreen devices.
1067             * 
1068             * @param parent (element): parent item
1069             * @param child (element): child item
1070             */
1071                var prevX, 
1072                prevY, 
1073                currX, 
1074                currY, 
1075                touch, 
1076                childX, 
1077                childY;
1078
1079                parent.bind('touchstart', function(e){
1080                    touch = e.originalEvent.touches[0];
1081                    prevX = touch.clientX;
1082                    prevY = touch.clientY;
1083                });
1084
1085                parent.bind('touchmove', function(e){                                
1086                    touch = e.originalEvent.touches[0];
1087                    currX = touch.clientX;
1088                    currY = touch.clientY;
1089                    childX = currX>prevX ? parseInt(child.css('margin-left'))+(currX-prevX):parseInt(child.css('margin-left'))-(prevX-currX);
1090                    childY = currY>prevY ? parseInt(child.css('margin-top'))+(currY-prevY):parseInt(child.css('margin-top'))-(prevY-currY);
1091
1092                    if (childX < (-1)*(child.width()-parent.width())){
1093                        childX = (-1)*(child.width()-parent.width());
1094                    }
1095                    else if (childX > 0){
1096                        childX = 0;
1097                    }
1098                    else{                                    
1099                        e.preventDefault();
1100                    }
1101
1102                    if (childY < (-1)*(child.height()-parent.height())){
1103                        childY = (-1)*(child.height()-parent.height());
1104                    }
1105                    else if (childY > 0){
1106                        childY = 0;
1107                    }
1108                    else{                                    
1109                        e.preventDefault();
1110                    }
1111
1112                    prevX = currX;
1113                    prevY = currY;
1114
1115                    if (parent.width() < child.width()){
1116                        child.css('margin-left', childX);
1117                    }
1118
1119                    if (parent.height() < child.height()){
1120                        child.css('margin-top', childY);
1121                    }
1122                });
1123
1124                parent.bind('touchstart', function(e){
1125                    if (!prototypes.isChromeMobileBrowser()){
1126                        e.preventDefault();
1127                    }
1128                });
1129            },
1130
1131// Browsers & devices
1132            isAndroid:function(){
1133            /*
1134             * Check if operating system is Android.
1135             * 
1136             * @return true/false
1137             */
1138                var isAndroid = false,
1139                agent = navigator.userAgent.toLowerCase();
1140
1141                if (agent.indexOf('android') !== -1){
1142                    isAndroid = true;
1143                }
1144                return isAndroid;
1145            },
1146            isChromeMobileBrowser:function(){
1147            /*
1148             * Check if browser is Chrome on mobile..
1149             * 
1150             * @return true/false
1151             */
1152                var isChromeMobile = false,
1153                agent = navigator.userAgent.toLowerCase();
1154
1155                if ((agent.indexOf('chrome') !== -1 
1156                                || agent.indexOf('crios') !== -1) 
1157                        && prototypes.isTouchDevice()){
1158                    isChromeMobile = true;
1159                }
1160                return isChromeMobile;
1161            },
1162            isIE8Browser:function(){
1163            /*
1164             * Check if browser is IE8.
1165             * 
1166             * @return true/false
1167             */
1168                var isIE8 = false,
1169                agent = navigator.userAgent.toLowerCase();
1170
1171                if (agent.indexOf('msie 8') !== -1){
1172                    isIE8 = true;
1173                }
1174                return isIE8;
1175            },
1176            isIEBrowser:function(){
1177            /*
1178             * Check if browser is IE..
1179             * 
1180             * @return true/false
1181             */
1182                var isIE = false,
1183                agent = navigator.userAgent.toLowerCase();
1184
1185                if (agent.indexOf('msie') !== -1){
1186                    isIE = true;
1187                }
1188                return isIE;
1189            },
1190            isTouchDevice:function(){
1191            /*
1192             * Detect touchscreen devices.
1193             * 
1194             * @return true/false
1195             */
1196                var os = navigator.platform;
1197
1198                if (os.toLowerCase().indexOf('win') !== -1){
1199                    return window.navigator.msMaxTouchPoints;
1200                }
1201                else {
1202                    return 'ontouchstart' in document;
1203                }
1204            },
1205
1206// Cookies
1207            deleteCookie:function(name,
1208                                  path,
1209                                  domain){
1210            /*
1211             * Delete cookie.
1212             * 
1213             * @param name (String): cookie name
1214             * @param path (String): cookie path
1215             * @param domain (String): cookie domain
1216             */
1217                if (prototypes.getCookie(name)){
1218                    document.cookie = name+'='+((path) ? ';path='+path:'')+((domain) ? ';domain='+domain:'')+';expires=Thu, 01-Jan-1970 00:00:01 GMT';
1219                }
1220            },
1221            getCookie:function(name){
1222            /*
1223             * Get cookie.
1224             * 
1225             * @param name (String): cookie name
1226             */    
1227                var namePiece = name+"=",
1228                cookie = document.cookie.split(";"),
1229                i;
1230
1231                for (i=0; i<cookie.length; i++){
1232                    var cookiePiece = cookie[i];
1233
1234                    while (cookiePiece.charAt(0) === ' '){
1235                        cookiePiece = cookiePiece.substring(1, cookiePiece.length);            
1236                    } 
1237
1238                    if (cookiePiece.indexOf(namePiece) === 0){
1239                        return unescape(cookiePiece.substring(namePiece.length, cookiePiece.length));
1240                    } 
1241                }
1242                return null;
1243            },
1244            setCookie:function(name,
1245                               value,
1246                               expire){
1247            /*
1248             * Set cookie.
1249             * 
1250             * @param name (String): cookie name
1251             * @param value (String): cookie value
1252             * @param expire (String): the number of days after which the cookie will expire
1253             */
1254                var expirationDate = new Date();
1255
1256                expirationDate.setDate(expirationDate.getDate()+expire);
1257                document.cookie = name+'='+escape(value)+((expire === null) ? '': ';expires='+expirationDate.toUTCString())+';javahere=yes;path=/';
1258            },
1259
1260// Date & time          
1261            getAMPM:function(time){
1262            /*
1263             * Converts time to AM/PM format.
1264             *
1265             * @param time (String): the time that will be converted (HH:MM)
1266             *
1267             * @return time to AM/PM format
1268             */
1269                var hour = parseInt(time.split(':')[0], 10),
1270                minutes = time.split(':')[1],
1271                result = '';
1272
1273                if (hour === 0){
1274                    result = '12';
1275                }
1276                else if (hour > 12){
1277                    result = prototypes.getLeadingZero(hour-12);
1278                }
1279                else{
1280                    result = prototypes.getLeadingZero(hour);
1281                }
1282
1283                result += ':'+minutes+' '+(hour < 12 ? 'AM':'PM');
1284
1285                return result;
1286            },
1287            getDatesDifference:function(date1,
1288                                        date2,
1289                                        type,
1290                                        valueType,
1291                                        noDecimals){
1292            /*
1293             * Returns difference between 2 dates.
1294             * 
1295             * @param date1 (Date): first date (YYYY-MM-DD)
1296             * @param date2 (Date): second date (YYYY-MM-DD)
1297             * @param type (String): diference type
1298             *                       "seconds"
1299             *                       "minutes"
1300             *                       "hours"
1301             *                       "days"
1302             * @param valueType (String): type of number returned
1303             *                            "float"
1304             *                            "integer"
1305             * @param noDecimals (Number): number of decimals returned with the float value (-1 to display all decimals)
1306             * 
1307             * @return dates diference
1308             */
1309                var y1 = date1.split('-')[0],
1310                m1 = date1.split('-')[1],
1311                d1 = date1.split('-')[2],
1312                y2 = date2.split('-')[0],
1313                m2 = date2.split('-')[1],
1314                d2 = date2.split('-')[2],
1315                time1 = (new Date(y1, m1-1, d1)).getTime(),
1316                time2 = (new Date(y2, m2-1, d2)).getTime(),
1317                diff = Math.abs(time1-time2);
1318        
1319                if (type === undefined){
1320                    type = 'seconds';
1321                }
1322                
1323                if (valueType === undefined){
1324                    valueType = 'float';
1325                }
1326                
1327                if (noDecimals === undefined){
1328                    noDecimals = -1;
1329                }
1330                
1331                switch (type){
1332                    case 'days':
1333                        diff = diff/(1000*60*60*24);
1334                        break;
1335                    case 'hours':
1336                        diff = diff/(1000*60*60);
1337                        break;
1338                    case 'minutes':
1339                        diff = diff/(1000*60);
1340                        break;
1341                    default:
1342                        diff = diff/(1000);
1343                }
1344                
1345                if (valueType === 'float'){
1346                    return noDecimals === -1 ? diff:prototypes.getWithDecimals(diff, noDecimals);
1347                }
1348                else{
1349                    return Math.ceil(diff);
1350                }
1351            },
1352            getHoursDifference:function(hour1,
1353                                        hour2,
1354                                        type,
1355                                        valueType,
1356                                        noDecimals){
1357            /*
1358             * Returns difference between 2 hours.
1359             * 
1360             * @param hour1 (Date): first hour (HH:MM, HH:MM:SS)
1361             * @param hour2 (Date): second hour (HH:MM, HH:MM:SS)
1362             * @param type (String): diference type
1363             *                       "seconds"
1364             *                       "minutes"
1365             *                       "hours"
1366             * @param valueType (String): type of number returned
1367             *                            "float"
1368             *                            "integer"
1369             * @param noDecimals (Number): number of decimals returned with the float value (-1 to display all decimals)
1370             * 
1371             * @return hours difference
1372             */
1373                var hours1 = parseInt(hour1.split(':')[0], 10),
1374                minutes1 = parseInt(hour1.split(':')[1], 10),
1375                seconds1 = hour1.split(':')[2] !== undefined ? parseInt(hour1.split(':')[2], 10):0,
1376                hours2 = parseInt(hour2.split(':')[0], 10),
1377                minutes2 = parseInt(hour2.split(':')[1], 10),
1378                seconds2 = hour2.split(':')[2] !== undefined ? parseInt(hour2.split(':')[2], 10):0,
1379                time1,
1380                time2,
1381                diff;
1382        
1383                if (type === undefined){
1384                    type = 'seconds';
1385                }
1386                
1387                if (valueType === undefined){
1388                    valueType = 'float';
1389                }
1390                
1391                if (noDecimals === undefined){
1392                    noDecimals = -1;
1393                }
1394                
1395                switch (type){
1396                    case 'hours':
1397                        time1 = hours1+minutes1/60+seconds1/60/60;
1398                        time2 = hours2+minutes2/60+seconds2/60/60;
1399                        break;
1400                    case 'minutes':
1401                        time1 = hours1*60+minutes1+seconds1/60;
1402                        time2 = hours2*60+minutes2+seconds2/60;
1403                        break;
1404                    default:
1405                        time1 = hours1*60*60+minutes1*60+seconds1;
1406                        time2 = hours2*60*60+minutes2*60+seconds2;
1407                }
1408                
1409                diff = Math.abs(time1-time2);
1410                
1411                if (valueType === 'float'){
1412                    return noDecimals === -1 ? diff:prototypes.getWithDecimals(diff, noDecimals);
1413                }
1414                else{
1415                    return Math.ceil(diff);
1416                }
1417            },
1418            getNextDay:function(date){
1419            /*
1420             * Returns next day.
1421             * 
1422             * @param date (Date): current date (YYYY-MM-DD)
1423             * 
1424             * @return next day (YYYY-MM-DD)
1425             */
1426                var nextDay = new Date(),
1427                parts = date.split('-');
1428
1429                nextDay.setFullYear(parts[0], parts[1], parts[2]);
1430                nextDay.setTime(nextDay.getTime()+86400000);
1431
1432                return nextDay.getFullYear()+'-'+prototypes.getLeadingZero(nextDay.getMonth())+'-'+prototypes.getLeadingZero(nextDay.getDate());
1433            },
1434            getNoDays:function(date1,
1435                               date2){
1436            /*
1437             * Returns number of days between 2 dates.
1438             * 
1439             * @param date1 (Date): first date (YYYY-MM-DD)
1440             * @param date2 (Date): second date (YYYY-MM-DD)
1441             * 
1442             * @return number of days
1443             */
1444                var y1 = date1.split('-')[0],
1445                m1 = date1.split('-')[1],
1446                d1 = date1.split('-')[2],
1447                y2 = date2.split('-')[0],
1448                m2 = date2.split('-')[1],
1449                d2 = date2.split('-')[2],
1450                time1 = (new Date(y1, m1-1, d1)).getTime(),
1451                time2 = (new Date(y2, m2-1, d2)).getTime(),
1452                diff = Math.abs(time1-time2);
1453        
1454                return Math.round(diff/(1000*60*60*24))+1;
1455            },
1456            getPrevDay:function(date){
1457            /*
1458             * Returns previous day.
1459             * 
1460             * @param date (Date): current date (YYYY-MM-DD)
1461             * 
1462             * @return previous day (YYYY-MM-DD)
1463             */
1464                var previousDay = new Date(),
1465                parts = date.split('-');
1466
1467                previousDay.setFullYear(parts[0],
1468                                        parseInt(parts[1])-1, 
1469                                        parts[2]);
1470                previousDay.setTime(previousDay.getTime()-86400000);
1471
1472                return previousDay.getFullYear()+'-'+prototypes.getLeadingZero(previousDay.getMonth()+1)+'-'+prototypes.getLeadingZero(previousDay.getDate());                        
1473            },
1474            getPrevTime:function(time,
1475                                 diff,
1476                                 diffBy){
1477            /*
1478             * Returns previous time by hours, minutes, seconds.
1479             * 
1480             * @param time (String): time (HH, HH:MM, HH:MM:SS)
1481             * @param diff (Number): diference for previous time
1482             * @param diffBy (Number): diference by 
1483             *                         "hours"
1484             *                         "minutes"
1485             *                         "seconds"
1486             * 
1487             * @return previus hour (HH, HH:MM, HH:MM:SS)
1488             */
1489                var timePieces = time.split(':'),
1490                hours = parseInt(timePieces[0], 10),
1491                minutes = timePieces[1] === undefined ? 0:parseInt(timePieces[1], 10),
1492                seconds = timePieces[2] === undefined ? 0:parseInt(timePieces[2], 10);
1493
1494                switch (diffBy){
1495                    case 'seconds':
1496                        seconds = seconds-diff;
1497
1498                        if (seconds < 0){
1499                            seconds = 60+seconds;
1500                            minutes = minutes-1;
1501
1502                            if (minutes < 0){
1503                                minutes = 60+minutes;
1504                                hours = hours-1 < 0 ? 0:hours-1;
1505                            }
1506                        }
1507                        break;
1508                    case 'minutes':
1509                            minutes = minutes-diff;
1510
1511                            if (minutes < 0){
1512                                minutes = 60+minutes;
1513                                hours = hours-1 < 0 ? 0:hours-1;
1514                            }
1515                        break;
1516                    default:
1517                        hours = hours-diff < 0 ? 0:hours-diff;
1518                }
1519
1520                return prototypes.getLeadingZero(hours)+(timePieces[1] === undefined ? '':':'+prototypes.getLeadingZero(minutes)+(timePieces[2] === undefined ? '':':'+prototypes.getLeadingZero(seconds)));
1521            },
1522            getToday:function(){
1523            /*
1524             * Returns today date.
1525             * 
1526             * @return today (YYYY-MM-DD)
1527             */    
1528                var today = new Date();
1529              
1530                return today.getFullYear()+'-'+prototypes.getLeadingZero(today.getMonth()+1)+'-'+prototypes.getLeadingZero(today.getDate());
1531            },
1532            getWeekDay:function(date){
1533            /*
1534             * Returns week day.
1535             * 
1536             * @param date (String): date for which the function get day of the week (YYYY-MM-DD)
1537             * 
1538             * @return week day index (0 for Sunday)
1539             */    
1540                var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1541                year = date.split('-')[0],
1542                month = date.split('-')[1],
1543                day = date.split('-')[2],
1544                newDate = new Date(eval('"'+day+' '+months[parseInt(month, 10)-1]+', '+year+'"'));
1545
1546                return newDate.getDay();
1547            },
1548
1549// Domains & URLs                        
1550            $_GET:function(name){
1551            /*
1552             * Parse a $_GET variable.
1553             * 
1554             * @param name (String): variable name
1555             * 
1556             * @return variable vaue or "undefined" if it doesn't exist
1557             */
1558                var url = window.location.href.split('?')[1],
1559                variables = url !== undefined ? url.split('&'):[],
1560                i; 
1561
1562                for (i=0; i<variables.length; i++){
1563                    if (variables[i].indexOf(name) !== -1){
1564                        return variables[i].split('=')[1];
1565                        break;
1566                    }
1567                }
1568
1569                return undefined;
1570            },
1571            acaoBuster:function(url){
1572            /*
1573             * Access-Control-Allow-Origin buster. Modifies URL to be the same as browser URL.
1574             * 
1575             * @param url (String): URL
1576             * 
1577             * @return modified URL
1578             */
1579                var browserURL = window.location.href,
1580                pathPiece1 = '', pathPiece2 = '';
1581
1582                if (prototypes.getDomain(browserURL) === prototypes.getDomain(url)){
1583                    if (url.indexOf('https') !== -1 
1584                            || url.indexOf('http') !== -1){
1585                        if (browserURL.indexOf('http://www.') !== -1){
1586                            pathPiece1 = 'http://www.';
1587                        }
1588                        else if (browserURL.indexOf('http://') !== -1){
1589                            pathPiece1 = 'http://';
1590                        }
1591                        else if (browserURL.indexOf('https://www.') !== -1){
1592                            pathPiece1 = 'https://www.';
1593                        }
1594                        else if (browserURL.indexOf('https://') !== -1){
1595                            pathPiece1 = 'https://';
1596                        }
1597
1598                        if (url.indexOf('http://www.') !== -1){
1599                            pathPiece2 = url.split('http://www.')[1];
1600                        }
1601                        else if (url.indexOf('http://') !== -1){
1602                            pathPiece2 = url.split('http://')[1];
1603                        }
1604                        else if (url.indexOf('https://www.') !== -1){
1605                            pathPiece2 = url.split('https://www.')[1];
1606                        }
1607                        else if (url.indexOf('https://') !== -1){
1608                            pathPiece2 = url.split('https://')[1];
1609                        }
1610
1611                        return pathPiece1+pathPiece2;
1612                    }
1613                    else{
1614                        return url;
1615                    }
1616                }
1617                else{
1618                    return url;
1619                }
1620            },
1621            getDomain:function(url){
1622            /*
1623             * Get current domain.
1624             *
1625             * @param url (String): the URL from which the domain will be extracted
1626             *
1627             * @return current domain
1628             */ 
1629                var domain = url;
1630
1631                /*
1632                 * Remove white spaces from the begining of the URL.
1633                 */
1634                domain = domain.replace(new RegExp(/^\s+/),"");
1635
1636                /*
1637                 * Remove white spaces from the end of the URL.
1638                 */
1639                domain = domain.replace(new RegExp(/\s+$/),"");
1640
1641                /*
1642                 * If found , convert back slashes to forward slashes.
1643                 */
1644                domain = domain.replace(new RegExp(/\\/g),"/");
1645
1646                /*
1647                 * If there, removes "http://", "https://" or "ftp://" from the begining.
1648                 */
1649                domain = domain.replace(new RegExp(/^http\:\/\/|^https\:\/\/|^ftp\:\/\//i),"");
1650
1651                /*
1652                 * If there, removes 'www.' from the begining.
1653                 */
1654                domain = domain.replace(new RegExp(/^www\./i),"");
1655
1656                /*
1657                 * Remove complete string from first forward slash on.
1658                 */
1659                domain = domain.replace(new RegExp(/\/(.*)/),"");
1660
1661                return domain;
1662            },
1663            hasSubdomain:function(url){
1664            /*
1665             * Check if current URL has a subdomain.
1666             *
1667             * @param url (String): URL that will be checked
1668             *
1669             * @return true/false
1670             */ 
1671                var subdomain;
1672
1673                /*
1674                 * Remove white spaces from the begining of the URL.
1675                 */
1676                url = url.replace(new RegExp(/^\s+/),"");
1677
1678                /*
1679                 * Remove white spaces from the end of the URL.
1680                 */
1681                url = url.replace(new RegExp(/\s+$/),"");
1682
1683                /*
1684                 * If found , convert back slashes to forward slashes.
1685                 */
1686                url = url.replace(new RegExp(/\\/g),"/");
1687
1688                /*
1689                 * If there, removes 'http://', 'https://' or 'ftp://' from the begining.
1690                 */
1691                url = url.replace(new RegExp(/^http\:\/\/|^https\:\/\/|^ftp\:\/\//i),"");
1692
1693                /*
1694                 * If there, removes 'www.' from the begining.
1695                 */
1696                url = url.replace(new RegExp(/^www\./i),"");
1697
1698                /*
1699                 * Remove complete string from first forward slaash on.
1700                 */
1701                url = url.replace(new RegExp(/\/(.*)/),""); // 
1702
1703                if (url.match(new RegExp(/\.[a-z]{2,3}\.[a-z]{2}$/i))){
1704                    /*
1705                     * Remove ".??.??" or ".???.??" from end - e.g. ".CO.UK", ".COM.AU"
1706                     */
1707                    url = url.replace(new RegExp(/\.[a-z]{2,3}\.[a-z]{2}$/i),"");
1708                }
1709                else if (url.match(new RegExp(/\.[a-z]{2,4}$/i))){
1710                    /*
1711                     * Removes ".??" or ".???" or ".????" from end - e.g. ".US", ".COM", ".INFO"
1712                     */
1713                    url = url.replace(new RegExp(/\.[a-z]{2,4}$/i),"");
1714                }
1715
1716                /*
1717                 * Check to see if there is a dot "." left in the string.
1718                 */
1719                subdomain = (url.match(new RegExp(/\./g))) ? true : false;
1720
1721                return(subdomain);
1722            },
1723
1724// Resize & position                        
1725            rp:function(parent,
1726                        child,
1727                        pw,
1728                        ph,
1729                        cw,
1730                        ch,
1731                        pos,
1732                        type){
1733            /*
1734             * Resize & position an item inside a parent.
1735             * 
1736             * @param parent (element): parent item
1737             * @param child (element): child item
1738             * @param pw (Number): parent width
1739             * @param ph (Number): parent height
1740             * @param cw (Number): child width
1741             * @param ch (Number): child height
1742             * @param pos (String): set child position in parent (bottom, bottom-center, bottom-left, bottom-right, center, left, horizontal-center, middle-left, middle-right, right, top, top-center, top-left, top-right, vertical-center)
1743             * @param type (String): resize type
1744             *                       "fill" fill parent (child will be cropped)
1745             *                       "fit" child resize to fit in parent
1746             */
1747                var newW = 0,
1748                newH = 0;
1749
1750                /*
1751                 * Resize child.
1752                 */
1753                if (cw <= pw 
1754                        && ch <= ph){
1755                    newW = cw;
1756                    newH = ch;
1757                }
1758                else{
1759                    switch (type){
1760                        case 'fill':
1761                            newH = ph;
1762                            newW = (cw*ph)/ch;
1763
1764                            if (newW < pw){
1765                                newW = pw;
1766                                newH = (ch*pw)/cw;
1767                            }
1768                            break;
1769                        default:
1770                            newH = ph;
1771                            newW = (cw*ph)/ch;
1772
1773                            if (newW > pw){
1774                                newW = pw;
1775                                newH = (ch*pw)/cw;
1776                            }
1777                            break;
1778                    }
1779                }
1780
1781                child.width(newW);
1782                child.height(newH);
1783
1784                /*
1785                 * Position child.
1786                 */
1787                switch(pos.toLowerCase()){
1788                    case 'bottom':
1789                        prototypes.rpBottom(parent,
1790                                            child, 
1791                                            ph);
1792                        break;
1793                    case 'bottom-center':
1794                        prototypes.rpBottomCenter(parent, 
1795                                                  child, 
1796                                                  pw, 
1797                                                  ph);
1798                        break;
1799                    case 'bottom-left':
1800                        prototypes.rpBottomLeft(parent, 
1801                                                child, 
1802                                                pw, 
1803                                                ph);
1804                        break;
1805                    case 'bottom-right':
1806                        prototypes.rpBottomRight(parent,
1807                                                 child, 
1808                                                 pw, 
1809                                                 ph);
1810                        break;
1811                    case 'center':
1812                        prototypes.rpCenter(parent, 
1813                                            child, 
1814                                            pw, 
1815                                            ph);
1816                        break;
1817                    case 'left':
1818                        prototypes.rpLeft(parent, 
1819                                          child, 
1820                                          pw);
1821                        break;
1822                    case 'horizontal-center':
1823                        prototypes.rpCenterHorizontally(parent, 
1824                                                        child, 
1825                                                        pw);
1826                        break;
1827                    case 'middle-left':
1828                        prototypes.rpMiddleLeft(parent, 
1829                                                child, 
1830                                                pw, 
1831                                                ph);
1832                        break;
1833                    case 'middle-right':
1834                        prototypes.rpMiddleRight(parent, 
1835                                                 child, 
1836                                                 pw, 
1837                                                 ph);
1838                        break;
1839                    case 'right':
1840                        prototypes.rpRight(parent, 
1841                                           child, 
1842                                           pw);
1843                        break;
1844                    case 'top':
1845                        prototypes.rpTop(parent, 
1846                                         child, 
1847                                         ph);
1848                        break;
1849                    case 'top-center':
1850                        prototypes.rpTopCenter(parent, 
1851                                               child, 
1852                                               pw, 
1853                                               ph);
1854                        break;
1855                    case 'top-left':
1856                        prototypes.rpTopLeft(parent, 
1857                                             child, 
1858                                             pw, 
1859                                             ph);
1860                        break;
1861                    case 'top-right':
1862                        prototypes.rpTopRight(parent, 
1863                                              child,
1864                                              pw, 
1865                                              ph);
1866                        break;
1867                    case 'vertical-center':
1868                        prototypes.rpCenterVertically(parent, 
1869                                                      child, 
1870                                                      ph);
1871                        break;
1872                }
1873            },
1874            rpBottom:function(parent,
1875                              child,
1876                              ph){
1877            /*
1878             * Position item on bottom.
1879             * 
1880             * @param parent (element): parent item
1881             * @param child (element): child item
1882             * @param ph (Number): height to which the parent is going to be set
1883             */
1884                if (ph !== undefined){
1885                    parent.height(ph);
1886                }
1887                child.css('margin-top', parent.height()-child.height());
1888            },
1889            rpBottomCenter:function(parent,
1890                                    child,
1891                                    pw,
1892                                    ph){
1893            /*
1894             * Position item on bottom-left.
1895             * 
1896             * @param parent (element): parent item
1897             * @param child (element): child item
1898             * @param pw (Number): width to which the parent is going to be set
1899             * @param ph (Number): height to which the parent is going to be set
1900             */
1901                prototypes.rpBottom(parent, 
1902                                    child, 
1903                                    ph);
1904                prototypes.rpCenterHorizontally(parent, 
1905                                                child, 
1906                                                pw);
1907            },
1908            rpBottomLeft:function(parent,
1909                                  child,
1910                                  pw,
1911                                  ph){
1912            /*
1913             * Position item on bottom-left.
1914             * 
1915             * @param parent (element): parent item
1916             * @param child (element): child item
1917             * @param pw (Number): width to which the parent is going to be set
1918             * @param ph (Number): height to which the parent is going to be set
1919             */
1920                prototypes.rpBottom(parent, 
1921                                    child, 
1922                                    ph);
1923                prototypes.rpLeft(parent, 
1924                                  child, 
1925                                  pw);
1926            },
1927            rpBottomRight:function(parent,
1928                                   child,
1929                                   pw,
1930                                   ph){
1931            /*
1932             * Position item on bottom-left.
1933             * 
1934             * @param parent (element): parent item
1935             * @param child (element): child item
1936             * @param pw (Number): width to which the parent is going to be set
1937             * @param ph (Number): height to which the parent is going to be set
1938             */
1939                prototypes.rpBottom(parent, 
1940                                    child, 
1941                                    ph);
1942                prototypes.rpRight(parent, 
1943                                   child, 
1944                                   pw);
1945            },
1946            rpCenter:function(parent,
1947                              child,
1948                              pw,
1949                              ph){
1950            /*
1951             * Position item on center.
1952             * 
1953             * @param parent (element): parent item
1954             * @param child (element): child item
1955             * @param pw (Number): width to which the parent is going to be set
1956             * @param ph (Number): height to which the parent is going to be set
1957             */
1958                prototypes.rpCenterHorizontally(parent, 
1959                                                child, 
1960                                                pw);
1961                prototypes.rpCenterVertically(parent, 
1962                                              child, 
1963                                              ph);
1964            },
1965            rpCenterHorizontally:function(parent,
1966                                          child,
1967                                          pw){
1968            /*
1969             * Center item horizontally.
1970             * 
1971             * @param parent (element): parent item
1972             * @param child (element): child item
1973             * @param pw (Number): width to which the parent is going to be set
1974             */
1975                if (pw !== undefined){
1976                    parent.width(pw);
1977                }
1978                child.css('margin-left', (parent.width()-child.width())/2);
1979            },
1980            rpCenterVertically:function(parent,
1981                                        child,
1982                                        ph){
1983            /*
1984             * Center item vertically.
1985             * 
1986             * @param parent (element): parent item
1987             * @param child (element): child item
1988             * @param ph (Number): height to which the parent is going to be set
1989             */
1990                if (ph !== undefined){
1991                    parent.height(ph);
1992                }
1993                child.css('margin-top', (parent.height()-child.height())/2);
1994            },
1995            rpLeft:function(parent,
1996                            child,
1997                            pw){
1998            /*
1999             * Position item on left.
2000             * 
2001             * @param parent (element): parent item
2002             * @param child (element): child item
2003             * @param pw (Number): width to which the parent is going to be set
2004             */
2005                if (pw !== undefined){
2006                    parent.width(pw);
2007                }
2008                child.css('margin-left', 0);
2009            },
2010            rpMiddleLeft:function(parent,
2011                                  child,
2012                                  pw,
2013                                  ph){
2014            /*
2015             * Position item on middle-left.
2016             * 
2017             * @param parent (element): parent item
2018             * @param child (element): child item
2019             * @param pw (Number): width to which the parent is going to be set
2020             * @param ph (Number): height to which the parent is going to be set
2021             */
2022                prototypes.rpCenterVertically(parent,
2023                                              child, 
2024                                              ph);
2025                prototypes.rpLeft(parent,
2026                                  child, 
2027                                  pw);
2028            },
2029            rpMiddleRight:function(parent,
2030                                   child,
2031                                   pw,
2032                                   ph){
2033            /*
2034             * Position item on middle-right.
2035             * 
2036             * @param parent (element): parent item
2037             * @param child (element): child item
2038             * @param pw (Number): width to which the parent is goi
2038ng to be set
2039             * @param ph (Number): height to which the parent is going to be set
2040             */
2041                prototypes.rpCenterVertically(parent,
2042                                              child, 
2043                                              ph);
2044                prototypes.rpRight(parent, 
2045                                   child, 
2046                                   pw);
2047            },
2048            rpRight:function(parent,
2049                             child,
2050                             pw){
2051            /*
2052             * Position item on right.
2053             * 
2054             * @param parent (element): parent item
2055             * @param child (element): child item
2056             * @param pw (Number): width to which the parent is going to be set
2057             */
2058                if (pw !== undefined){
2059                    parent.width(pw);
2060                }
2061                child.css('margin-left', parent.width()-child.width());
2062            },
2063            rpTop:function(parent,
2064                           child,
2065                           ph){
2066            /*
2067             * Position item on top.
2068             * 
2069             * @param parent (element): parent item
2070             * @param child (element): child item
2071             * @param ph (Number): height to which the parent is going to be set
2072             */
2073                if (ph !== undefined){
2074                    parent.height(ph);
2075                }
2076                child.css('margin-top', 0);
2077            },
2078            rpTopCenter:function(parent,
2079                                 child,
2080                                 pw,
2081                                 ph){
2082            /*
2083             * Position item on top-center.
2084             * 
2085             * @param parent (element): parent item
2086             * @param child (element): child item
2087             * @param pw (Number): width to which the parent is going to be set
2088             * @param ph (Number): height to which the parent is going to be set
2089             */
2090                prototypes.rpTop(parent, 
2091                                 child, 
2092                                 ph);
2093                prototypes.rpCenterHorizontally(parent, 
2094                                                child, 
2095                                                pw);
2096            },
2097            rpTopLeft:function(parent,
2098                               child,
2099                               pw,
2100                               ph){
2101            /*
2102             * Position item on top-left.
2103             * 
2104             * @param parent (element): parent item
2105             * @param child (element): child item
2106             * @param pw (Number): width to which the parent is going to be set
2107             * @param ph (Number): height to which the parent is going to be set
2108             */
2109                prototypes.rpTop(parent, 
2110                                 child, 
2111                                 ph);
2112                prototypes.rpLeft(parent, 
2113                                  child, 
2114                                  pw);
2115            },
2116            rpTopRight:function(parent,
2117                                child,
2118                                pw,
2119                                ph){
2120            /*
2121             * Position item on top-right.
2122             * 
2123             * @param parent (element): parent item
2124             * @param child (element): child item
2125             * @param pw (Number): width to which the parent is going to be set
2126             * @param ph (Number): height to which the parent is going to be set
2127             */
2128                prototypes.rpTop(parent, 
2129                                 child, 
2130                                 ph);
2131                prototypes.rpRight(parent, 
2132                                   child, 
2133                                   pw);
2134            },
2135
2136// Strings & numbers
2137            cleanInput:function(input,
2138                                allowedCharacters,
2139                                firstNotAllowed,
2140                                min){
2141            /*
2142             * Clean an input from unwanted characters.
2143             * 
2144             * @param input (element): the input to be checked
2145             * @param allowedCharacters (String): the string of allowed characters
2146             * @param firstNotAllowed (String): the character which can't be on the first position
2147             * @param min (Number/String): the minimum value that is allowed in the input
2148             * 
2149             * @return clean string
2150             */ 
2151                var characters = input.val().split(''),
2152                returnStr = '', 
2153                i, 
2154                startIndex = 0;
2155
2156                /*
2157                 * Check first character.
2158                 */
2159                if (characters.length > 1
2160                        && characters[0] === firstNotAllowed){
2161                    startIndex = 1;
2162                }
2163
2164                /*
2165                 * Check characters.
2166                 */
2167                for (i=startIndex; i<characters.length; i++){
2168                    if (allowedCharacters.indexOf(characters[i]) !== -1){
2169                        returnStr += characters[i];
2170                    }
2171                }
2172
2173                /*
2174                 * Check the minimum value.
2175                 */
2176                if (min > returnStr){
2177                    returnStr = min;
2178                }
2179
2180                input.val(returnStr);
2181            },
2182            getLeadingZero:function(no){
2183            /*
2184             * Adds a leading 0 if number smaller than 10.
2185             * 
2186             * @param no (Number): the number
2187             * 
2188             * @return number with leading 0 if needed
2189             */
2190                if (no < 10){
2191                    return '0'+no;
2192                }
2193                else{
2194                    return no;
2195                }
2196            },
2197            getRandomString:function(stringLength,
2198                                     allowedCharacters){
2199            /*
2200             * Creates a string with random characters.
2201             * 
2202             * @param stringLength (Number): the length of the returned string
2203             * @param allowedCharacters (String): the string of allowed characters
2204             * 
2205             * @return random string
2206             */
2207                var randomString = '',
2208                charactersPosition,
2209                i;
2210
2211                allowedCharacters = allowedCharacters !== undefined ? allowedCharacters:'0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
2212
2213                for (i=0; i<stringLength; i++){
2214                    charactersPosition = Math.floor(Math.random()*allowedCharacters.length);
2215                    randomString += allowedCharacters.substring(charactersPosition, charactersPosition+1);
2216                }
2217                return randomString;
2218            },
2219            getShortString:function(str,
2220                                    size){
2221            /*
2222             * Returns a part of a string followed by 3 dots.
2223             * 
2224             * @param str (String): the string
2225             * @param size (Number): the number of characters that will be displayed minus 3 dots
2226             * 
2227             * @return short string ...
2228             */
2229                var newStr = new Array(),
2230                pieces = str.split(''), i;
2231
2232                if (pieces.length <= size){
2233                    newStr.push(str);
2234                }
2235                else{
2236                    for (i=0; i<size-3; i++){
2237                        newStr.push(pieces[i]);
2238                    }
2239                    newStr.push('...');
2240                }
2241
2242                return newStr.join('');
2243            },
2244            getWithDecimals:function(number,
2245                                     no){
2246            /*
2247             * Returns a number with a predefined number of decimals.
2248             * 
2249             * @param number (Number): the number
2250             * @param no (Number): the number of decimals
2251             * 
2252             * @return string with number and decimals
2253             */
2254                no = no === undefined ? 2:no;
2255                return parseInt(number) === number ? String(number):parseFloat(number).toFixed(no);
2256            },
2257            validateCharacters:function(str,
2258                                        allowedCharacters){
2259            /*
2260             * Verify if a string contains allowed characters.
2261             * 
2262             * @param str (String): string to be checked
2263             * @param allowedCharacters (String): the string of allowed characters
2264             * 
2265             * @return true/false
2266             */
2267                var characters = str.split(''), i;
2268
2269                for (i=0; i<characters.length; i++){
2270                    if (allowedCharacters.indexOf(characters[i]) === -1){
2271                        return false;
2272                    }
2273                }
2274                return true;
2275            },
2276            validEmail:function(email){
2277            /*
2278             * Email validation.
2279             * 
2280             * @param email (String): email to be checked
2281             * 
2282             * @return true/false
2283             */
2284                var filter = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,16}(?:\.[a-z]{2})?)$/i;
2285
2286                if (filter.test(email)){
2287                    return true;
2288                }
2289                return false;
2290            },
2291            stripSlashes:function(str){
2292            /*
2293             * Remove slashes from string.
2294             * 
2295             * @param str (String): the string
2296             * 
2297             * @return string without slashes
2298             */
2299                return (str + '').replace(/\\(.?)/g, function (s, n1){
2300                    switch (n1){
2301                        case '\\':
2302                            return '\\';
2303                        case '0':
2304                            return '\u0000';
2305                        case '':
2306                            return '';
2307                        default:
2308                            return n1;
2309                    }
2310                });
2311            },
2312
2313// Styles
2314            getHEXfromRGB:function(rgb){
2315            /*
2316             * Convert RGB color to HEX.
2317             * 
2318             * @param rgb (String): RGB color
2319             * 
2320             * @return color HEX
2321             */
2322                var hexDigits = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
2323
2324                rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
2325
2326                return (isNaN(rgb[1]) ? '00':hexDigits[(rgb[1]-rgb[1]%16)/16]+hexDigits[rgb[1]%16])+
2327                       (isNaN(rgb[2]) ? '00':hexDigits[(rgb[2]-rgb[2]%16)/16]+hexDigits[rgb[2]%16])+
2328                       (isNaN(rgb[3]) ? '00':hexDigits[(rgb[3]-rgb[3]%16)/16]+hexDigits[rgb[3]%16]);
2329            },
2330            getIdealTextColor:function(bgColor){
2331            /*
2332             * Set text color depending on the background color.
2333             * 
2334             * @param bgColor(String): background color
2335             * 
2336             * return white/black
2337             */
2338                var rgb = /rgb\((\d+).*?(\d+).*?(\d+)\)/.exec(bgColor);
2339
2340                if (rgb !== null){
2341                    return parseInt(rgb[1], 10)+parseInt(rgb[2], 10)+parseInt(rgb[3], 10) < 3*256/2 ? 'white' : 'black';
2342                }
2343                else{
2344                    return parseInt(bgColor.substring(0, 2), 16)+parseInt(bgColor.substring(2, 4), 16)+parseInt(bgColor.substring(4, 6), 16) < 3*256/2 ? 'white' : 'black';
2345                }
2346            }
2347        };
2348        
2349        return methods.init.apply(this);
2350    };
2351})(jQuery);
2352
2353function DOPBSPSearchLoadInfobox(){
2354    var script = document.createElement('script');
2355                    
2356    script.type = 'text/JavaScript';
2357    script.src = 'https://cdn.jsdelivr.net/gh/googlemaps/v3-utility-library@master/archive/infobox/src/infobox_packed.js';
2358    
2359    jQuery('body').append(script);
2360    
2361    return true;
2362}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.