PageSourceSearch

https://nnyln.org/wp-content/plugins/booking-system/assets/js/jque…p.frontend.BSPSearchWidget.js?ver=2.9.9.6.9

js nnyln.org collected 2026-10-02 10:51:31 UTC 102,370 bytes, 2,410 lines download raw bytes

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

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.