PageSourceSearch

https://naturalezaiberica.com/wp-content/plugins/_dopbsp/assets/js/jquery.dop.frontend.BSPSearch.js?ver=6.9.10

js naturalezaiberica.com collected 2026-10-10 02:05:25 UTC 100,157 bytes, 2,338 lines download raw bytes

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

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.