PageSourceSearch

https://kovatera.com/wp-content/plugins/agile-store-locator/public/js/site_script.js?ver=1.5.4

js kovatera.com collected 2026-10-08 01:33:39 UTC 198,827 bytes, 5,942 lines download raw bytes

1/**
2 * Copyright Agile Logix 
3 * License: GNU General Public License v2 or later
4 * 
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
6 * and associated documentation files (the "Software"), to use, copy, modify, merge, publish, 
7 * distribute, sublicense, and/or sell copies of the Software, subject to the following conditions:
8 * 
9 * 1. Redistributions of the Software must retain the above copyright notice, 
10 *    this list of conditions, and the following disclaimer.
11 * 
12 * 2. No resale of the Software or its derivatives is permitted, whether for profit or otherwise, 
13 *    without express written permission from the Author.
14 * 
15 * The Software is provided "AS IS", without warranty of any kind, express or implied, 
16 * including but not limited to the warranties of merchantability, fitness for a particular purpose 
17 * and noninfringement. In no event shall the authors or copyright holders be liable for any claim, 
18 * damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of 
19 * or in connection with the software or the use or other dealings in the software.
20 */
21
22
23
24/**
25 * [asl_gdpr Enable the GDPR for the Store Locator]
26 * @return {[type]} [description]
27 */
28var asl_gdpr = function(_accepted) {
29
30    window['asl_async_callback'] = function(){
31      asl_store_locator();
32    };
33  
34    /**
35     * [load_google_maps Load the Google Maps Async]
36     * @return {[type]} [description]
37     */
38    function load_google_maps() {
39  
40      var script  = document.createElement('script');
41      script.type = 'text/javascript';
42      script.src  = 'https://maps.googleapis.com/maps/api/js?libraries=places,drawing&callback=asl_async_callback&key=' + asl_configuration.api_key;
43      document.body.appendChild(script);
44    };
45  
46  
47    /**
48     * [gdpr_accepted Once user approve it]
49     * @return {[type]} [description]
50     */
51    function gdpr_accepted() {
52  
53      window.localStorage && window.localStorage.setItem('asl-gdpr', 1);
54        
55      //  disable it once accepted
56      asl_configuration.gdpr = false;
57  
58      load_google_maps();
59  
60      //  remove the GDPR box
61      jQuery('.asl-cont #sl-btn-gdpr').parent().parent().parent().remove();
62    };
63  
64    //  Accepted by the Borlabs Cookies
65    if(_accepted) {
66      load_google_maps();
67      return;
68    }
69  
70    //  Accept the GDPR :: Simple
71    jQuery('.asl-cont #sl-btn-gdpr').bind('click', gdpr_accepted);
72    
73    //  Check if already approved
74    if(window.localStorage && window.localStorage.getItem('asl-gdpr') == '1') {
75      gdpr_accepted();
76    }
77  };
78  
79  //  Call the GDPR
80  if(asl_configuration.gdpr == '1') {
81    asl_configuration.gdpr_enabled = true;
82    asl_gdpr();
83  }
84  
85  
86  
87  /**
88   * [asl_store_locator Store Locator Main Function]
89   * @return {[type]} [description]
90   */
91  function asl_store_locator() {
92    
93    //  when GDPR is enabled
94    if(asl_configuration.gdpr == '1')return;
95  
96    //  Make sure the Google Maps is loaded
97    if (!window['google'] || !google.maps) {
98  
99      if(!asl_configuration.gdpr_enabled)
100        console.warn('Store Locator Error! Google Maps library is not loaded, check your cache plugin');
101  
102      return;
103    }
104  
105    //  Multiple instance not allowed
106    if(jQuery('.storelocator-main').length >= 2) {
107      console.warn('Store Locator Error! Multiple instances of store locator loaded on the page.');
108    }
109  
110    if (!window['_asl_map_customize']) {
111      window['_asl_map_customize'] = null;
112    }
113  
114    
115    //  Don't allow to load twice
116    if(asl_configuration.is_loaded) {
117      return;
118    }
119  
120    asl_configuration.is_loaded = true;
121  
122    //  the Locator instance
123    var asl_locator = function() {};
124  
125  
126  
127    //info box library
128    function InfoBox(e){e=e||{};google.maps.OverlayView.apply(this,arguments);this.content_=e.content||"";this.disableAutoPan_=e.disableAutoPan||false;this.maxWidth_=e.maxWidth||0;this.pixelOffset_=e.pixelOffset||new google.maps.Size(0,0);this.position_=e.position||new google.maps.LatLng(0,0);this.zIndex_=e.zIndex||null;this.boxClass_=e.boxClass||"infoBox";this.boxStyle_=e.boxStyle||{};this.closeBoxMargin_=e.closeBoxMargin||"2px";this.closeBoxURL_=e.closeBoxURL||"https://www.google.com/intl/en_us/mapfiles/close.gif";if(e.closeBoxURL===""){this.closeBoxURL_=""}this.infoBoxClearance_=e.infoBoxClearance||new google.maps.Size(1,1);if(typeof e.visible==="undefined"){if(typeof e.isHidden==="undefined"){e.visible=true}else{e.visible=!e.isHidden}}this.isHidden_=!e.visible;this.alignBottom_=e.alignBottom||false;this.pane_=e.pane||"floatPane";this.enableEventPropagation_=e.enableEventPropagation||false;this.div_=null;this.closeListener_=null;this.moveListener_=null;this.contextListener_=null;this.eventListeners_=null;this.fixedWidthSet_=null}InfoBox.prototype=new google.maps.OverlayView;InfoBox.prototype.createInfoBoxDiv_=function(){var e;var t;var n;var r=this;var i=function(e){e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation()}};var s=function(e){e.returnValue=false;if(e.preventDefault){e.preventDefault()}if(!r.enableEventPropagation_){i(e)}};if(!this.div_){this.div_=document.createElement("div");this.setBoxStyle_();if(typeof this.content_.nodeType==="undefined"){this.div_.innerHTML=this.getCloseBoxImg_()+this.content_}else{this.div_.innerHTML=this.getCloseBoxImg_();this.div_.appendChild(this.content_)}this.getPanes()[this.pane_].appendChild(this.div_);this.addClickHandler_();if(this.div_.style.width){this.fixedWidthSet_=true}else{if(this.maxWidth_!==0&&this.div_.offsetWidth>this.maxWidth_){this.div_.style.width=this.maxWidth_;this.div_.style.overflow="auto";this.fixedWidthSet_=true}else{n=this.getBoxWidths_();
128this.div_.style.width=this.div_.offsetWidth-n.left-n.right+"px";this.fixedWidthSet_=false}}this.panBox_(this.disableAutoPan_);if(!this.enableEventPropagation_){this.eventListeners_=[];t=["mousedown","mouseover","mouseout","mouseup","click","dblclick","touchstart","touchend","touchmove"];for(e=0;e<t.length;e++){this.eventListeners_.push(this.div_.addEventListener(t[e],i))}this.eventListeners_.push(this.div_.addEventListener("mouseover",function(e){this.style.cursor="default"}))}this.contextListener_=this.div_.addEventListener("contextmenu",s);google.maps.event.trigger(this,"domready")}};InfoBox.prototype.getCloseBoxImg_=function(){var e="";if(this.closeBoxURL_!==""){e="<img";e+=" src='"+this.closeBoxURL_+"'";e+=" align=right";e+=" style='";e+=" position: relative;";e+=" cursor: pointer;";e+=" margin: "+this.closeBoxMargin_+";";e+="'>"}return e};InfoBox.prototype.addClickHandler_=function(){var e;if(this.closeBoxURL_!==""){e=this.div_.firstChild;this.closeListener_=e.addEventListener("click",this.getCloseClickHandler_())}else{this.closeListener_=null}};InfoBox.prototype.getCloseClickHandler_=function(){var e=this;return function(t){t.cancelBubble=true;if(t.stopPropagation){t.stopPropagation()}google.maps.event.trigger(e,"closeclick");e.close()}};InfoBox.prototype.panBox_=function(e){var t;var n;var r=0,i=0;if(!e){t=this.getMap();if(t instanceof google.maps.Map){if(!t.getBounds().contains(this.position_)){t.setCenter(this.position_)}n=t.getBounds();var s=t.getDiv();var o=s.offsetWidth;var u=s.offsetHeight;var a=this.pixelOffset_.width;var f=this.pixelOffset_.height;var l=this.div_.offsetWidth;var c=this.div_.offsetHeight;var h=this.infoBoxClearance_.width;var p=this.infoBoxClearance_.height;var d=this.getProjection().fromLatLngToContainerPixel(this.position_);if(d.x<-a+h){r=d.x+a-h}else if(d.x+l+a+h>o){r=d.x+l+a+h-o}if(this.alignBottom_){if(d.y<-f+p+c){i=d.y+f-p-c}else if(d.y+f+p>u){i=d.y+f+p-u}}else{if(d.y<-f+p){i=d.y+f-p}else if(d.y+c+f+p>u){i=d.y+c+f+p-u}}if(!(r===0&&i===0)){var v=t.getCenter();t.panBy(r,i)}}}};InfoBox.prototype.setBoxStyle_=function(){var e,t;if(this.div_){this.div_.className=this.boxClass_;this.div_.style.cssText="";t=this.boxStyle_;for(e in t){if(t.hasOwnProperty(e)){this.div_.style[e]=t[e]}}this.div_.style.WebkitTransform="translateZ(0)";if(typeof this.div_.style.opacity!=="undefined"&&this.div_.style.opacity!==""){this.div_.style.MsFilter='"progid:DXImageTransform.Microsoft.Alpha(Opacity='+this.div_.style.opacity*100+')"';this.div_.style.filter="alpha(opacity="+this.div_.style.opacity*100+")"}this.div_.style.position="absolute";this.div_.style.visibility="hidden";if(this.zIndex_!==null){this.div_.style.zIndex=this.zIndex_}}};InfoBox.prototype.getBoxWidths_=function(){var e;var t={top:0,bottom:0,left:0,right:0};var n=this.div_;if(document.defaultView&&document.defaultView.getComputedStyle){e=n.ownerDocument.defaultView.getComputedStyle(n,"");if(e){t.top=parseInt(e.borderTopWidth,10)||0;t.bottom=parseInt(e.borderBottomWidth,10)||0;t.left=parseInt(e.borderLeftWidth,10)||0;t.right=parseInt(e.borderRightWidth,10)||0}}else if(document.documentElement.currentStyle){if(n.currentStyle){t.top=parseInt(n.currentStyle.borderTopWidth,10)||0;t.bottom=parseInt(n.currentStyle.borderBottomWidth,10)||0;t.left=parseInt(n.currentStyle.borderLeftWidth,10)||0;t.right=parseInt(n.currentStyle.borderRightWidth,10)||0}}return t};InfoBox.prototype.onRemove=function(){if(this.div_){this.div_.parentNode.removeChild(this.div_);this.div_=null}};InfoBox.prototype.draw=function(){this.createInfoBoxDiv_();var e=this.getProjection().fromLatLngToDivPixel(this.position_);this.div_.style.left=e.x+this.pixelOffset_.width+"px";if(this.alignBottom_){this.div_.style.bottom=-(e.y+this.pixelOffset_.height)+"px"}else{this.div_.style.top=e.y+this.pixelOffset_.height+"px"}if(this.isHidden_){this.div_.style.visibility="hidden"}else{this.div_.style.visibility="visible"}};InfoBox.prototype.setOptions=function(e){if(typeof e.boxClass!=="undefined"){this.boxClass_=e.boxClass;this.setBoxStyle_()}if(typeof e.boxStyle!=="undefined"){this.boxStyle_=e.boxStyle;this.setBoxStyle_()}if(typeof e.content!=="undefined"){this.setContent(e.content)}if(typeof e.disableAutoPan!=="undefined"){this.disableAutoPan_=e.disableAutoPan}if(typeof e.maxWidth!=="undefined"){this.maxWidth_=e.maxWidth}if(typeof e.pixelOffset!=="undefined"){this.pixelOffset_=e.pixelOffset}if(typeof e.alignBottom!=="undefined"){this.alignBottom_=e.alignBottom}if(typeof e.position!=="undefined"){this.setPosition(e.position)}if(typeof e.zIndex!=="undefined"){this.setZIndex(e.zIndex)}if(typeof e.closeBoxMargin!=="undefined"){this.closeBoxMargin_=e.closeBoxMargin}if(typeof e.closeBoxURL!=="undefined"){this.closeBoxURL_=e.closeBoxURL}if(typeof e.infoBoxClearance!=="undefined"){this.infoBoxClearance_=e.infoBoxClearance}if(typeof e.isHidden!=="undefined"){this.isHidden_=e.isHidden}if(typeof e.visible!=="undefined"){this.isHidden_=!e.visible}if(typeof e.enableEventPropagation!=="undefined"){this.enableEventPropagation_=e.enableEventPropagation}if(this.div_){this.draw()}};InfoBox.prototype.setContent=function(e){this.content_=e;if(this.div_){if(this.closeListener_){google.maps.event.removeListener(this.closeListener_);this.closeListener_=null}if(!this.fixedWidthSet_){this.div_.style.width=""}if(typeof e.nodeType==="undefined"){this.div_.innerHTML=this.getCloseBoxImg_()+e}else{this.div_.innerHTML=this.getCloseBoxImg_();this.div_.appendChild(e)}if(!this.fixedWidthSet_){this.div_.style.width=this.div_.offsetWidth+"px";if(typeof e.nodeType==="undefined"){this.div_.innerHTML=this.getCloseBoxImg_()+e}else{this.div_.innerHTML=this.getCloseBoxImg_();this.div_.appendChild(e)}}this.addClickHandler_()}google.maps.event.trigger(this,"content_changed")};InfoBox.prototype.setPosition=function(e){this.position_=e;if(this.div_){this.draw()}google.maps.event.trigger(this,"position_changed")};InfoBox.prototype.setZIndex=function(e){this.zIndex_=e;if(this.div_){this.div_.style.zIndex=e}google.maps.event.trigger(this,"zindex_changed")};InfoBox.prototype.setVisible=function(e){this.isHidden_=!e;if(this.div_){this.div_.style.visibility=this.isHidden_?"hidden":"visible"}};InfoBox.prototype.getContent=function(){return this.content_};InfoBox.prototype.getPosition=function(){return this.position_};InfoBox.prototype.getZIndex=function(){return this.zIndex_};InfoBox.prototype.getVisible=function(){var e;if(typeof this.getMap()==="undefined"||this.getMap()===null){e=false}else{e=!this.isHidden_}return e};InfoBox.prototype.show=function(){this.isHidden_=false;if(this.div_){this.div_.style.visibility="visible"}};InfoBox.prototype.hide=function(){this.isHidden_=true;if(this.div_){this.div_.style.visibility="hidden"}};InfoBox.prototype.open=function(e,t){var n=this;if(t){this.position_=t.getPosition();this.moveListener_=google.maps.event.addListener(t,"position_changed",function(){n.setPosition(this.getPosition())})}this.setMap(e);if(this.div_){this.panBox_()}};InfoBox.prototype.close=function(){var e;if(this.closeListener_){google.maps.event.removeListener(this.closeListener_);this.closeListener_=null}if(this.eventListeners_){for(e=0;e<this.eventListeners_.length;e++){google.maps.event.removeListener(this.eventListeners_[e])}this.eventListeners_=null}if(this.moveListener_){google.maps.event.removeListener(this.moveListener_);this.moveListener_=null}if(this.contextListener_){google.maps.event.removeListener(this.contextListener_);this.contextListener_=null}this.setMap(null)};
129  
130  
131    //mobile test
132    function _isMobileDevice() {
133      var check = (window.innerWidth < 768)? true: false;
134      (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
135      return check;
136    };
137  
138  
139    /**
140     * [addHours Add the hours to the Date]
141     * @param {[type]} h [description]
142     */
143    Date.prototype.addHours = function(h) {
144      this.setTime(this.getTime() + (h*60*60*1000));
145      return this;
146    };
147  
148    /**
149     * [subDays description]
150     * @param  {[type]} h [description]
151     * @return {[type]}   [description]
152     */
153    Date.prototype.subDays = function(h) {
154      this.setTime(this.getTime() - (h*60*60*1000 * 24));
155      return this;
156    };
157  
158  
159    /**
160     * [getDecimal Get the decimal of the number]
161     * @return {[type]} [description]
162     */
163    function getDecimal(_value) {
164  
165        return Math.ceil((_value - Math.floor(_value)) * 100)
166    };
167  
168    //  Remove the Roboto when GDPR enabled
169    if(asl_configuration.gdpr_enabled) {
170  
171      var head = document.getElementsByTagName('head')[0];
172  
173      // Save the original method
174      var insertBefore = head.insertBefore;
175  
176      // Replace it!
177      head.insertBefore = function (newElement, referenceElement) {
178  
179        if (newElement.href && newElement.href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0) {
180            return;
181        }
182  
183        insertBefore.call(head, newElement, referenceElement);
184      };
185    }
186  
187    /**
188     * [asl_drawing Code for ASL Drawing]
189     * @type {Object}
190     */
191    var asl_drawing  = {
192      shapes: [],
193      shapes_index: 0,
194      current_map: null,
195      loadData: function(saved, _map) {
196  
197        var that = this;
198        that.current_map = _map;
199  
200        for (var i in saved.shapes) {
201          if (!saved.shapes[i]) continue;
202  
203          if (saved.shapes[i].type == 'polygon') {
204            that.shapes.push(
205              that.create_polygon.call(that, saved.shapes[i].coord, _map, saved.shapes[i])
206            );
207          } 
208          else if (saved.shapes[i].type == 'polyline') {
209  
210            that.shapes.push(
211              that.create_polyline.call(that, saved.shapes[i].coord, _map, saved.shapes[i])
212            );
213          }
214          else if (saved.shapes[i].type == 'circle') {
215            that.shapes.push(
216              that.create_circle.call(that, saved.shapes[i], _map)
217            );
218          } else if (saved.shapes[i].type == 'rectangle') {
219            that.shapes.push(
220              that.create_rectangle.call(that, saved.shapes[i], _map)
221            );
222          }
223        }
224      },
225      create_rectangle: function(_data) {
226  
227        var _map = this.current_map;
228  
229        return new google.maps.Rectangle({
230          strokeColor: _data.strokeColor,
231          fillColor: _data.color,
232          strokeWeight: 1,
233          type: 'rectangle',
234          editable: (asl_drawing.allow_edit) ? asl_drawing.allow_edit : false,
235          map: _map,
236          bounds: new google.maps.LatLngBounds(
237            new google.maps.LatLng(_data.sw[0], _data.sw[1]),
238            new google.maps.LatLng(_data.ne[0], _data.ne[1]))
239        });
240      },
241      create_circle: function(_data, _map) {
242  
243        var _map = this.current_map;
244  
245        return new google.maps.Circle({
246          strokeColor: _data.strokeColor,
247          fillColor: _data.color,
248          type: 'circle',
249          strokeWeight: 1,
250          map: _map,
251          editable: (asl_drawing.allow_edit) ? asl_drawing.allow_edit : false,
252          center: new google.maps.LatLng(_data.center[0], _data.center[1]),
253          radius: _data.radius
254        });
255  
256      },
257      create_polyline: function(_points, _map, _shape) {
258  
259        var _map = this.current_map;
260  
261        var coords = [];
262  
263        for (var i in _points) {
264  
265          coords.push({ lat: _points[i][0], lng: _points[i][1] });
266        }
267  
268        return new google.maps.Polyline({
269          path: coords,
270          strokeColor: _shape.strokeColor || '#000000',
271          strokeWeight: 3,
272          editable: false, // Editable geometry off by default
273          type: 'polyline',
274          map: _map
275        });
276      },
277      create_polygon: function(_points, _map, _shape) {
278  
279        var _map = this.current_map;
280  
281        var coords = [];
282  
283        for (var i in _points) {
284  
285          coords.push({ lat: _points[i][0], lng: _points[i][1] });
286        }
287  
288        return new google.maps.Polygon({
289          paths: coords,
290          fillColor: _shape.color,
291          strokeColor: _shape.strokeColor,
292          strokeWeight: 1,
293          editable: (asl_drawing.allow_edit) ? true : false, // Editable geometry off by default
294          type: 'polygon',
295          map: _map
296        });
297      }
298    },
299    ASL_CLOSE_BUTTON = '<button class="asl-search-clr asl-clear-btn hide" type="button"><svg width="12" height="12" viewBox="0 0 12 12" xmlns="https://www.w3.org/2000/svg"><path d="M.566 1.698L0 1.13 1.132 0l.565.566L6 4.868 10.302.566 10.868 0 12 1.132l-.566.565L7.132 6l4.302 4.3.566.568L10.868 12l-.565-.566L6 7.132l-4.3 4.302L1.13 12 0 10.868l.566-.565L4.868 6 .566 1.698z"></path></svg></button>',
300    ASL_PICKUP_ROW   = (asl_configuration.pickup || asl_configuration.ship_from)? '<div class="sl-row mt-2 sl-pickup-row"><div class="pol"><a class="btn btn-block btn-asl sl-pickup">'+ ((asl_configuration.ship_from)? asl_configuration.words.ship_from: asl_configuration.words.pickup) +'</a></div></div>': null;
301  
302    /*ASL Script*/
303    (function($) {
304  
305      //  Hack for the Template
306      if (!$.templates) {
307        $.templates = jQuery.templates;
308      }
309  
310      
311      if (!$.views) {
312        $.templates = jQuery.views;
313      }
314  
315  
316      //  Enable Stars
317      if($.views && $.views.tags) {
318        
319        $.views.tags("stars", function(rating) {
320          if(!isNaN(rating)) {
321            rating = (Math.round(parseFloat(rating) * 4) / 4);
322            var starPercentage        = (rating / 5) * 100;
323            var starPercentageRounded = (Math.round(starPercentage / 5) * 5) + '%';
324            return '<span class="sl-stars"><div class="sl-stars-out icon-star"><div style="width:' + starPercentageRounded+'" class="sl-stars-in icon-star"></div></div></span>';
325          }
326        });
327      }
328  
329    
330      /**
331       * [ASLConsole Take Over the Console]
332       * @return {[type]} [description]
333       */
334      if(asl_configuration.debug == '1') {
335        
336        (function ASLConsole() {
337          var console = window.console
338          if (!console) return
339  
340          function intercept(method) {
341              var original = console[method]
342  
343              console[method] = function() {
344                 
345                 // check message
346                 if(arguments[0] && arguments[0].indexOf('Google') !== -1) {
347  
348                    var $err_msg = $('<div class="alert alert-danger asl-geo-err"></div>');
349                    $err_msg.html(arguments[0]);
350                    $err_msg.appendTo('.asl-cont .asl-map');
351                    window.setTimeout(function() {
352                      $err_msg.remove();
353                    }, 5000);
354                 }
355                 
356                  if (original.apply) {
357                      // Do this for normal browsers
358                      original.apply(console, arguments)
359                  } else {
360                      // Do this for IE
361                      var message = Array.prototype.slice.apply(arguments).join(' ')
362                      original(message)
363                  }
364              }
365          }
366          var methods = ['error'];
367          for (var i = 0; i < methods.length; i++)
368              intercept(methods[i])
369        }());
370      }
371      
372  
373      /**
374       * [hook_event Event HOOK]
375       * @param  {[type]} _event_type [description]
376       * @param  {[type]} _data       [description]
377       * @return {[type]}             [description]
378       */
379      asl_locator.hook_event = function(_event) {
380  
381        //  bind the hook, init
382        if(window['asl_event_hook'] && typeof window['asl_event_hook']  == 'function') {
383          asl_event_hook.call(this, _event);
384        }
385      };
386  
387      /**
388       * [add_clear_search Add the clear search]
389       * @param {[type]} _input [description]
390       */
391      asl_locator.add_clear_button = function(_input) {
392  
393        var _clear_btn = $(ASL_CLOSE_BUTTON);
394  
395        _input.after(_clear_btn);
396        
397        //  Clear button Event
398        _clear_btn.bind('click', function() {
399  
400          asl_view.search_text = asl_view._location = null;
401  
402          asl_view.clear_search(_input);
403          _clear_btn.addClass('hide');
404        });
405  
406        return _clear_btn;
407      };
408  
409  
410      /**
411       * [save_analytics Save Analytics]
412       * @param  {[type]} _store_or_loc [description]
413       * @param  {[type]} _viewed       [description]
414       * @return {[type]}               [description]
415       */
416      asl_locator.save_analytics = function(_store_or_loc, _viewed) {
417  
418      };
419  
420      asl_locator.toRad_ = function(degrees) {
421        return degrees * Math.PI / 180;
422      };
423  
424      asl_locator.Store = function(id, location, categories, props) {
425        this.id_        = id;
426        this.location_  = location;
427        this.categories_ = categories /* || asl_locator.FeatureSet.NONE*/ ;
428        this.props_ = props || {};
429        this.v_id   = props.vendor_id;
430      };
431  
432  
433      asl_locator.Store.prototype.setMarker = function(marker) {
434        this.marker_ = marker;
435        google.maps.event.trigger(this, 'marker_changed', marker);
436      };
437  
438      /**
439       * Gets this store's Marker
440       * @return {google.maps.Marker} the store's marker.
441       */
442      asl_locator.Store.prototype.getMarker = function() {
443        return this.marker_;
444      };
445  
446      /**
447       * Gets this store's ID.
448       * @return {string} this store's ID.
449       */
450      asl_locator.Store.prototype.getId = function() {
451        return this.id_;
452      };
453  
454      /**
455       * Gets this store's location.
456       * @return {google.maps.LatLng} this store's location.
457       */
458      asl_locator.Store.prototype.getLocation = function() {
459        return this.location_;
460      };
461  
462      /**
463       * Gets this store's features.
464       * @return {asl_locator.FeatureSet} this store's features.
465       */
466      /*
467      //Not used
468      asl_locator.Store.prototype.getStoreFeatures = function() {
469      return this.categories_;
470      };
471      */
472  
473      /**
474       * Checks whether this store has a particular feature.
475       * @param {!asl_locator.Feature} feature the feature to check for.
476       * @return {boolean} true if the store has the feature, false otherwise.
477       */
478      asl_locator.Store.prototype.hasCategory = function(featureID) {
479  
480        return this.categories_.indexOf(featureID) != -1;
481      };
482  
483      /**
484       * Checks whether this store has all the given features.
485       * @param {asl_locator.FeatureSet} features the features to check for.
486       * @return {boolean} true if the store has all features, false otherwise.
487       */
488      asl_locator.Store.prototype.hasAnyCategory = function(active_features) {
489  
490        if (!active_features.array_.length) {
491          return asl_configuration.on_select;
492        }
493  
494  
495        var featureList = active_features.asList();
496  
497        for (var i = 0, ii = featureList.length; i < ii; i++) {
498  
499          if (this.categories_.indexOf(featureList[i].id_) != -1)
500            return true;
501  
502          /*
503            if (this.hasCategory(featureList[i].id_)) {
504              return true;
505            }
506            */
507        }
508  
509        return false;
510      };
511  
512      /**
513       * [hasAllCategory Checks whether this store has all the given features.]
514       * @param  {[type]}  active_features [description]
515       * @return {Boolean}                 [description]
516       */
517      asl_locator.Store.prototype.hasAllCategory = function(active_features) {
518  
519        if (!active_features.array_.length) {
520          return asl_configuration.on_select;
521        }
522  
523        var featureList = active_features.asList();
524  
525        for (var i = 0, ii = featureList.length; i < ii; i++) {
526          
527          if (this.categories_.indexOf(featureList[i].id_) == -1) {
528            return false;
529          }
530        }
531  
532        return true;
533      };
534  
535  
536      /**
537       * Gets additional details about this store.
538       * @return {Object} additional properties of this store.
539       */
540      asl_locator.Store.prototype.getDetails = function() {
541        return this.props_;
542      };
543  
544      /**
545       * Generates HTML for additional details about this store.
546       * @private
547       * @param {Array.<string>} fields the optional fields of this store to output.
548       * @return {string} html version of additional fields of this store.
549       */
550      asl_locator.Store.prototype.generateFieldsHTML_ = function(fields) {
551  
552        var html = [];
553  
554        for (var i = 0, ii = fields.length; i < ii; i++) {
555          var prop = fields[i];
556  
557          if (this.props_[prop]) {
558            html.push('<div class="');
559            html.push(prop);
560            html.push('">');
561            html.push(prop + ': ');
562            html.push((isNaN(this.props_[prop])) ? this.props_[prop] : numberWithCommas(this.props_[prop]));
563            html.push('</div>');
564          }
565        }
566        return html.join('');
567      };
568  
569      /**
570       * Generates a HTML list of this store's features.
571       * @private
572       * @return {string} html list of this store's features.
573       */
574      asl_locator.Store.prototype.generateFeaturesHTML_ = function() {
575  
576        var html = [];
577        html.push('<ul class="features">');
578        var featureList = this.categories_.asList();
579        for (var i = 0, feature; feature = featureList[i]; i++) {
580          html.push('<li>');
581          html.push(feature.getDisplayName());
582          html.push('</li>');
583        }
584        html.push('</ul>');
585        return html.join('');
586      };
587  
588      /**
589       * [getStoreContent description]
590       * @return {[type]} [description]
591       */
592      asl_locator.Store.prototype.getStoreContent = function() {
593  
594        if (!this.content_) {
595          // TODO(cbro): make this a setting?
596  
597          var tmpl = (window['asl_tmpl_list_item']) ? window['asl_tmpl_list_item'] : $.templates((window['asl_tmpls'] && window['asl_tmpls']['list'] || '#tmpl_list_item'));
598          window['asl_tmpl_list_item'] = tmpl;
599  
600          this.props_.target = asl_configuration.target_blank;
601  
602          this.content_ = $(tmpl.render(this.props_));
603  
604  
605          // When we have a pickup row
606          if(asl_configuration.pickup || asl_configuration.ship_from) {
607            this.content_.append(ASL_PICKUP_ROW);
608          }
609        }
610  
611        return this.content_;
612      };
613  
614      /**
615       * [advMkrContent Generate the content of the advanced marker]
616       * @return {[type]} [description]
617       */
618      asl_locator.Store.prototype.advMkrContent = function() {
619  
620        var tmpl = (window['asl_tmpl_adv_mkr']) ? window['asl_tmpl_adv_mkr'] : $.templates((window['asl_tmpls'] && window['asl_tmpls']['adv_mkr'] || '#asl_tmpl_adv_mkr'));
621  
622        window['asl_tmpl_adv_mkr'] = tmpl;
623  
624        this.props_.target = asl_configuration.target_blank;
625  
626        //  Create the node
627        const content     = document.createElement('div');
628        content.className = 'adv-mkr-cont';
629        
630        //  Add the HTML
631        content.innerHTML = tmpl.render(this.props_);
632        
633        return content;
634      };
635  
636      /**
637       * Gets the HTML content for this Store, suitable for use in an InfoWindow.
638       * @return {string} a HTML version of this store.
639       */
640      asl_locator.Store.prototype.getcontent_ = function(store) {
641  
642        var tmpl = (window['asl_too_tip_tmpl']) ? window['asl_too_tip_tmpl'] : $.templates((window['asl_tmpls'] && window['asl_tmpls']['infobox'] || '#asl_too_tip'));
643        window['asl_too_tip_tmpl'] = tmpl;
644  
645        store.props_.show_categories = asl_configuration.show_categories;
646  
647        var html_tip     = tmpl.render(store.props_);
648        
649        return html_tip;
650      };
651  
652      /**
653       * [getInfoWindowContent description]
654       * @param  {[type]} stores [description]
655       * @return {[type]}        [description]
656       */
657      asl_locator.Store.prototype.getInfoWindowContent = function(stores) {
658  
659        var html = '<div class="infoWindow" id="style_' + ((asl_configuration.infobox_layout) ? asl_configuration.infobox_layout : '1') + '">';
660  
661        html += this.getcontent_(this);
662  
663        html += '</div>';
664  
665        this.content_ = html;
666  
667        return this.content_;
668      };
669  
670  
671      /**
672       * Keep a cache of InfoPanel items (DOM Node), keyed by the store ID.
673       * @private
674       * @type {Object}
675       */
676      asl_locator.Store.infoPanelCache_ = {};
677  
678      /**
679       * Gets a HTML element suitable for use in the InfoPanel.
680       * @return {Node} a HTML element.
681       */
682      asl_locator.Store.prototype.getInfoPanelItem = function() {
683  
684        var store = this;
685        var cache = asl_locator.Store.infoPanelCache_;
686        var key = store.id_;
687  
688  
689  
690        if (!cache[key]) {
691          var content = store.getStoreContent();
692          cache[key] = content[0];
693  
694        }
695  
696        return cache[key];
697      };
698  
699      /**
700       * Gets the distance between this Store and a certain location.
701       * @param {google.maps.LatLng} point the point to calculate distance to/from.
702       * @return {number} the distance from this store to a given point.
703       * @license
704       *  Latitude/longitude spherical geodesy formulae & scripts
705       *  (c) Chris Veness 2002-2010
706       *  www.movable-type.co.uk/scripts/latlong.html
707       */
708      asl_locator.Store.prototype.distanceTo = function(point) {
709  
710        var R = 6371; // mean radius of earth
711        var location = this.getLocation();
712        var lat1 = asl_locator.toRad_(location.lat());
713        var lon1 = asl_locator.toRad_(location.lng());
714        var lat2 = asl_locator.toRad_(point.lat());
715        var lon2 = asl_locator.toRad_(point.lng());
716        var dLat = lat2 - lat1;
717        var dLon = lon2 - lon1;
718  
719        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
720          Math.cos(lat1) * Math.cos(lat2) *
721          Math.sin(dLon / 2) * Math.sin(dLon / 2);
722        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
723        var _val = R * c;
724  
725        return (asl_configuration.distance_unit == 'Miles') ? _val * 0.621371 : _val;
726      };
727  
728  
729      ///////////////////////////////STORES END HERE///////////////////////////////
730      asl_locator.View = function(map, data, opt_options) {
731  
732        this.map_ = map;
733        this.data_ = data;
734  
735  
736        this.settings_ = $.extend({
737          'updateOnPan': true,
738          'geolocation': false,
739          'features': new asl_locator.FeatureSet
740        }, opt_options);
741  
742        this.init_();
743  
744        google.maps.event.trigger(this, 'load');
745        this.set('featureFilter', new asl_locator.FeatureSet);
746  
747        //  Active Marker
748        if (asl_configuration.active_marker)
749          this.active_marker = { m: null, picon: null, icon: new google.maps.MarkerImage(asl_configuration.PLUGIN_URL + "public/icon/active.png", null, null) };
750  
751        //  Icon Sizing & Label Origin
752        if(asl_configuration.icon_size) {
753  
754          var sizes       = asl_configuration.icon_size.split('x'),
755              size_width  = parseInt(sizes[0]), 
756              size_height = parseInt(sizes[1]); 
757  
758  
759          var label_origin = null;
760  
761          //  Label Origin
762          if(asl_configuration.label_origin) {
763  
764            label_origin = asl_configuration.label_origin.split('x');
765  
766            label_origin[0] = parseInt(label_origin[0]);
767            label_origin[1] = parseInt(label_origin[1]);
768          }
769          else
770            label_origin = [size_width/2, ((size_height) / 2) - 10];
771  
772  
773          var anchor = null;
774  
775          //  Anchor Position
776          if(asl_configuration.infowin_anchor) {
777  
778            anchor = asl_configuration.infowin_anchor.split('x');
779  
780            anchor[0] = parseInt(anchor[0]);
781            anchor[1] = parseInt(anchor[1]);
782          }
783          else
784            anchor = [size_width/2, ((size_height) / 2) + 8];
785  
786  
787          this.icon = {
788            scaledSize: new google.maps.Size(size_width, size_height),
789            origin: new google.maps.Point(0, 0),
790            anchor: new google.maps.Point(anchor[0], anchor[1] ),
791            labelOrigin:  new google.maps.Point(label_origin[0], label_origin[1])
792          };
793        }
794  
795  
796        //  Content of the tooltip
797        this.cat_in_tooltip = (asl_configuration.title_only == '1')? false: true;
798      };
799  
800      asl_locator['View'] = asl_locator.View;
801  
802  
803      asl_locator.View.prototype = new google.maps.MVCObject;
804  
805  
806  
807      /**
808       * [clear_search Clear the search on Close_BUTTON]
809       * @param  {[type]} _input_control [description]
810       * @return {[type]}                [description]
811       */
812      asl_locator.View.prototype.clear_search = function(_input_control) {
813  
814  
815        // dont fetch as it is clear search
816        //this.halt_fetch = true;
817  
818        //  Search by the Name
819        if(asl_configuration.search_type == '1') {
820          this.filter_text = null;
821        }
822  
823        this.prop_filter  = this._location = null;
824        this.reset_measure(_input_control);
825  
826        //  Reset Map to same location where it was initially
827        this.getMap().panTo(new google.maps.LatLng(asl_configuration.default_lat, asl_configuration.default_lng));
828        this.getMap().setZoom(parseInt(asl_configuration.zoom));
829  
830        //  When Category accordion, reset the list as well
831        if(asl_configuration.category_accordion) {
832          
833          var colapse_li = $('.asl-cont #asl-list li.item-state > a:not(.colisiond)');
834          
835          if(colapse_li[0]) {
836  
837            colapse_li.addClass('colisiond');
838            colapse_li.next().removeClass('in');measure_dista
839          }
840        }
841  
842      };
843  
844      /*
845        _no_refresh only works when user_center = 1
846      */
847      asl_locator.View.prototype.measure_distance = function(_latlng, _nearest, _no_refresh, _place_api) {
848  
849        var that = this;
850  
851        //  Clear the infobox
852        this.clear_infobox();
853  
854        //  Delete Marker Cache, when Advanced markers are enabled clear the markers template as well
855        if(asl_configuration.adv_mkr) {
856  
857          that.clearMarkers();
858  
859          delete that.markerCache_;
860          that.markerCache_ = {};
861        }
862  
863        var loc = new google.maps.LatLng(_latlng.lat(), _latlng.lng());
864        that._panel.dest_coords = that.dest_coords = loc;
865  
866        //  disable the sort random
867        if(asl_configuration.sort_random)
868          asl_configuration.sort_random = false;
869  
870        //  First Load
871        if (asl_configuration.first_load == '5') {
872  
873          if (!that.display_list) {
874  
875            $('.asl-cont.storelocator-main').removeClass('sl-search-only');
876  
877            that.display_list = true;
878          }
879        }
880        else if (asl_configuration.first_load == '3') {
881  
882          if (!that.display_list) {
883  
884            $('.asl-cont.storelocator-main').removeClass('map-full');
885  
886            that.display_list = true;
887          }
888        }
889        else if (asl_configuration.first_load == '4') {
890  
891          if (!that.list_shown && that.display_list) {
892            $('.asl-cont.storelocator-main').removeClass('map-full');
893            that.list_shown = true;
894          }
895  
896          if (!that.display_list) {
897            that.display_list = true;
898          }
899        }
900  
901  
902        //var max_distance = asl_configuration.radius_range,
903        var max_distance = 100,
904          min_distance   = 1000,
905          nearest_pin    = null;
906  
907        var unit_translation = (asl_configuration.distance_unit == 'KM') ? asl_configuration.words.Km : asl_configuration.words.Miles;
908  
909        //get distance from current
910        for (var s in that.data_.stores_) {
911  
912          if (!that.data_.stores_.hasOwnProperty(s)) continue;
913  
914          var _distance = that.data_.stores_[s].distanceTo(that.dest_coords);
915          that.data_.stores_[s].content_ = null;
916  
917  
918          //change KM TO Miles
919          that.data_.stores_[s].props_.distance = _distance;
920          that.data_.stores_[s].props_.dist_str = asl_engine.helper.format_count(_distance) + ' ' + unit_translation;
921  
922  
923          //console.log(that.data_.stores_[s].props_.city,'     ',that.data_.stores_[s].props_.state,'   ',that.data_.stores_[s].props_.postal_code);
924  
925          if (_distance > max_distance)
926            max_distance = _distance;
927  
928          if (_distance < min_distance) {
929  
930            nearest_pin = that.data_.stores_[s];
931            min_distance = _distance;
932          }
933        }
934  
935  
936        asl_configuration.radius_range = (asl_configuration.fixed_radius) ? parseInt(asl_configuration.fixed_radius) : Math.ceil(max_distance);
937  
938  
939        $('.asl-cont #asl-radius-input').html(asl_configuration.radius_range);
940  
941        delete asl_locator.Store.infoPanelCache_;
942        asl_locator.Store.infoPanelCache_ = {};
943  
944        //my marker
945        if (!that.my_marker) {
946  
947          that.my_marker = new google.maps.Marker({
948            title: asl_configuration.words.your_cur_loc,
949            position: loc,
950            zIndex: 0,
951            animation: google.maps.Animation.DROP,
952            draggable: true,
953            map: (asl_configuration.geo_marker == '0')? null: that.getMap()
954          });
955  
956          //  Apply the Geo-Marker Image
957          var geo_marker_image = asl_configuration.PLUGIN_URL + "public/icon/me-pin.png";
958  
959          if(asl_configuration.geo_marker_id && asl_markers[asl_configuration.geo_marker_id]) {
960            geo_marker_image = asl_configuration.URL + 'icon/' + asl_markers[asl_configuration.geo_marker_id].icon;
961          }
962  
963  
964          var marker_icon = new google.maps.MarkerImage(geo_marker_image, null, null, null /*, new google.maps.Size(24,46)*/ );
965          that.my_marker.setIcon(marker_icon);
966  
967          that.my_marker.addListener('dragend', function(_event) {
968  
969            that.measure_distance(_event.latLng);
970          });
971        } else
972          that.my_marker.setPosition(loc);
973  
974  
975  
976        //Show the Nearest Store
977        if (_nearest && asl_configuration.search_destin == '1' && nearest_pin) {
978  
979          loc = nearest_pin.getLocation();
980        }
981  
982        /**
983         * [radius_circle Create a Circle]
984         * @param  {[type]} _location [description]
985         * @return {[type]}           [description]
986         */
987        function radius_circle(_location) {
988  
989          var _radius = null;
990  
991          _radius = ((!asl_configuration.distance_slider || !asl_configuration.advance_filter) && !asl_configuration.fixed_radius) ? 100 : parseInt(asl_configuration.radius_range);
992  
993          //Change to KM
994          _radius = _radius * 1000;
995  
996          //  Change Miles to KM Unit
997          if (asl_configuration.distance_unit != 'KM') {
998  
999            _radius = _radius * 1.60934;
1000          }
1001  
1002          if (!that.$circle) {
1003  
1004            //  Create the Circle Control
1005            function circleStatus(controlDiv, map) {
1006  
1007              // Set CSS for the control border.
1008              $reset_btn = $('<div class="asl-radius-cnt"><div class="checkbox"><label for="asl-rad-circ"><input id="asl-rad-circ" checked type="checkbox">' + asl_configuration.words.radius_circle + '</label></div></div>');
1009              controlDiv.appendChild($reset_btn[0]);
1010  
1011              // Setup the click event listeners: simply set the map to Chicago.
1012              $reset_btn.find('#asl-rad-circ')[0].addEventListener('click', function() {
1013  
1014                that.$circle.setMap((this.checked) ? that.getMap() : null);
1015              });
1016            };
1017  
1018            //  Add the Circle Overlay
1019            that.$circle = new google.maps.Circle({
1020              strokeColor: asl_configuration.radius_color || '#FFFF00',
1021              strokeOpacity: 0.7,
1022              strokeWeight: 2,
1023              fillColor: asl_configuration.radius_color || '#FFFF00',
1024              fillOpacity: 0.20,
1025              map: that.getMap(),
1026              radius: _radius,
1027              center: _location
1028            });
1029          } 
1030          else {
1031  
1032            //  Change it
1033            that.$circle.setOptions({ radius: _radius, center: _location });
1034          }
1035  
1036          //  Make the Circle Radius
1037          that.getMap().fitBounds(that.$circle.getBounds());
1038        };
1039  
1040        //  For the Boundary Box
1041        if(asl_configuration.boundary_box) {
1042  
1043          //  no control needed
1044        }
1045        //For Dropdwon
1046        else if (asl_configuration.distance_slider & asl_configuration.advance_filter && asl_configuration.distance_control == '1') {
1047  
1048          var unit_translation = (asl_configuration.distance_unit == 'KM') ? asl_configuration.words.Km : asl_configuration.words.Miles;
1049          //Intialize Distance Dropdown
1050          if (!that.$dist_control) {
1051  
1052            var dropdown_opts = asl_configuration.dropdown_range.split(','),
1053              dropdown_html = '';
1054  
1055            for (var d = 0; d < dropdown_opts.length; d++) {
1056  
1057              var opt_val = dropdown_opts[d],
1058                selecti = (opt_val && opt_val[0] == '*') ? true : false;
1059  
1060              // Remove *
1061              if (selecti) {
1062  
1063                opt_val = opt_val.replace('*', '');
1064                dropdown_html += '<option selected="selected" value="' + opt_val + '">' + opt_val + ' ' + unit_translation + '</option>';
1065              } else
1066                dropdown_html += '<option value="' + opt_val + '">' + opt_val + ' ' + unit_translation + '</option>';
1067            }
1068  
1069  
1070            $('.asl-cont .range_filter').html('<div class="asl-filter-cntrl"><label class="asl-cntrl-lbl">' + asl_configuration.words.distance + '</label><div class="sl-dropdown-cont">\
1071              <select class="asl-dist-ddl">' + dropdown_html + '</select></div></div>')
1072              .removeClass('hide');
1073  
1074  
1075            // Template 1
1076            if(asl_configuration.template == '1') {
1077              $('.asl-cont .range_filter').prepend('<label>'+asl_configuration.words.in+'</label>');
1078            }
1079  
1080            that.$dist_control = $('.asl-cont .asl-dist-ddl');
1081  
1082            that.$dist_control.multiselect({
1083              enableFiltering: false,
1084              nonSelectedText: asl_configuration.words.select_distance,
1085              numberDisplayed: 1,
1086              maxHeight: (asl_configuration.ddl_max_height)?parseInt(asl_configuration.ddl_max_height): 250,
1087              /*onSelectAll: function(event) {
1088              },*/
1089              onChange: function(option, checked) {
1090  
1091                var rad_val = parseInt(option.val());
1092  
1093                if (isNaN(rad_val)) {
1094  
1095                  rad_val = 1000;
1096                  //rad_val = (asl_configuration.fixed_radius)?parseInt(asl_configuration.fixed_radius):1000;
1097                }
1098  
1099                asl_configuration.radius_range = rad_val;
1100                that.refreshView();
1101  
1102                // Change the Circle
1103                if (that.$circle) {
1104  
1105                  radius_circle(that.dest_coords);
1106                }
1107              }
1108            });
1109  
1110            asl_configuration.radius_range = that.$dist_control.val();
1111          } 
1112          else {
1113  
1114            asl_configuration.radius_range = that.$dist_control.val();
1115  
1116          }
1117        }
1118        //For Slider
1119        else if (asl_configuration.distance_slider & asl_configuration.advance_filter && asl_configuration.distance_control == '0') {
1120  
1121          $('.asl-cont .range_filter').removeClass('hide');
1122  
1123          //  Either Slider or Dropdown
1124          if (!that.$dist_control) {
1125  
1126            var slider_current_value = (asl_configuration.slider_val_radius)? parseInt(asl_configuration.slider_val_radius): asl_configuration.radius_range;
1127  
1128  
1129            that.$dist_control = jQuery(".asl-cont #asl-radius-slide")
1130              .aslSlider({
1131                value: slider_current_value,
1132                min: asl_configuration.slider_min_radius? parseInt(asl_configuration.slider_min_radius): 1,
1133                max: asl_configuration.radius_range
1134              })
1135              .on("slide", function(e) {
1136  
1137                $('#asl-radius-input').html(e.value);
1138                asl_configuration.radius_range = e.value;
1139              })
1140              .on("slideStop", function(value) {
1141  
1142                that.refreshView();
1143  
1144                // Change the Circle
1145                if (that.$circle) {
1146  
1147                  radius_circle(that.dest_coords);
1148                }
1149              });
1150  
1151              //  Current value of the slider
1152              asl_configuration.radius_range = slider_current_value;
1153          }
1154          //Set Max value
1155          else {
1156  
1157            that.$dist_control.aslSlider('setAttribute', 'max', asl_configuration.radius_range);
1158            that.$dist_control.aslSlider('setValue', asl_configuration.radius_range);
1159            $('#asl-radius-input').html(asl_configuration.radius_range);
1160          }
1161        }
1162  
1163        //  Radius Circle
1164        if (asl_configuration.radius_circle) {
1165  
1166          radius_circle(that.dest_coords);
1167          that.refreshView();
1168        }
1169        else if (!_no_refresh) {
1170  
1171          //  Bounding Box Search
1172          if(asl_configuration.search_zoom == '0' && that.bbox) {
1173  
1174            if(!that.bbox.isEmpty()) {
1175              that.getMap().fitBounds(that.bbox);
1176            }
1177          }
1178          else {
1179  
1180            that.getMap().setCenter(loc);
1181            that.getMap().setZoom((asl_configuration.search_zoom) ? parseInt(asl_configuration.search_zoom) : parseInt(asl_configuration.zoom));
1182            google.maps.event.trigger(that, 'load');
1183          }
1184  
1185          that.refreshView();
1186        }
1187  
1188  
1189        //  Hide the geoModal
1190        if(that._panel.geo_modal) {
1191          that._panel.hideGeoModal();        
1192        }
1193  
1194        return;
1195      };
1196  
1197  
1198      /**
1199       * [reset_measure Reset the Measure]
1200       * @param  {[type]} _input [description]
1201       * @return {[type]}        [description]
1202       */
1203      asl_locator.View.prototype.reset_measure = function(_input) {
1204  
1205        var that  = this;
1206  
1207        //  Clear the infobox
1208        this.clear_infobox();
1209  
1210        //  Delete Marker Cache, when Advanced markers are enabled clear the markers template as well
1211        if(asl_configuration.adv_mkr) {
1212  
1213          that.clearMarkers();
1214  
1215          delete that.markerCache_;
1216          that.markerCache_ = {};
1217        }
1218  
1219        that.bbox = that._panel.dest_coords = that.dest_coords = null;
1220  
1221        var max_distance  = asl_configuration.radius_range,
1222          min_distance    = 1000,
1223          nearest_pin     = null;
1224  
1225  
1226        //  Get distance from current
1227        for (var s in that.data_.stores_) {
1228  
1229          if (!that.data_.stores_.hasOwnProperty(s)) continue;
1230  
1231          that.data_.stores_[s].content_ = null;
1232  
1233          // Change KM TO Miles
1234          that.data_.stores_[s].props_.dist_str = that.data_.stores_[s].props_.distance = null;
1235        }
1236  
1237        //disable it in case of radius_range fixed
1238        //asl_configuration.radius_range = Math.round(max_distance);
1239        asl_configuration.radius_range = (asl_configuration.fixed_radius) ? parseInt(asl_configuration.fixed_radius) : Math.round(max_distance);
1240  
1241  
1242        $('.asl-cont #asl-radius-input').html(asl_configuration.radius_range);
1243  
1244        delete asl_locator.Store.infoPanelCache_;
1245  
1246  
1247        asl_locator.Store.infoPanelCache_ = {};
1248  
1249        //  Clear the Marker
1250        if (that.my_marker) {
1251  
1252          that.my_marker.setMap(null);
1253          delete that.my_marker;
1254          that.my_marker = null;
1255        }
1256  
1257        //  Clear the Circle
1258        if(that.$circle) {
1259  
1260          that.$circle.setMap(null);
1261          delete that.$circle;
1262          that.$circle = null;
1263        }
1264  
1265        //For Dropdwon
1266        if (asl_configuration.distance_slider & asl_configuration.advance_filter && asl_configuration.distance_control == '1') {
1267  
1268          //Destroy
1269          if (that.$dist_control) {
1270  
1271            that.$dist_control.multiselect('destroy');
1272            that.$dist_control = null;
1273          }
1274  
1275          $('.asl-cont .range_filter').addClass('hide');
1276  
1277        }
1278        //For Slider
1279        else if (asl_configuration.distance_slider & asl_configuration.advance_filter && asl_configuration.distance_control == '0') {
1280  
1281          $('.asl-cont .range_filter').addClass('hide');
1282  
1283          //Either Slider or Dropdown
1284          if (that.$dist_control) {
1285  
1286            that.$dist_control.aslSlider('destroy');
1287            that.$dist_control.removeData('aslSlider');
1288            that.$dist_control = null;
1289          }
1290        }
1291  
1292  
1293        that.refreshView();
1294  
1295        $(_input).val('');
1296      };
1297  
1298  
1299      /**
1300       * [add_search_text add text to search control]
1301       * @param  {[type]} _text [description]
1302       * @return {[type]}       [description]
1303       */
1304      asl_locator.View.prototype.add_search_text = function(_text) {
1305  
1306        var that = this;
1307  
1308        //  when we have a control, add text to it
1309        if(that._panel.search_control) {
1310  
1311          that._panel.search_control.value = _text;
1312  
1313          //  Show the close button
1314          $(that._panel.search_control).next().removeClass('hide');
1315        }
1316      };
1317  
1318  
1319      /**
1320       * [geolocate_ GeoLocate]
1321       * @return {[type]} [description]
1322       */
1323      asl_locator.View.prototype.geolocate_ = function() {
1324  
1325        var that = this;
1326  
1327        if (window.navigator && navigator.geolocation) {
1328  
1329          //  todo remove it
1330          //that.measure_distance(new google.maps.LatLng(51.6262, 1.080647));return;
1331  
1332          /**
1333           * [geo_error Geo-Location Error]
1334           * @param  {[type]} error [description]
1335           * @return {[type]}       [description]
1336           */
1337          function geo_error(error) {
1338  
1339            var $err_msg = $('<div class="alert alert-danger asl-geo-err"></div>');
1340            
1341            switch (error.code) {
1342  
1343              case 'http':
1344                $err_msg.html("Error! site is loading with HTTP connection");
1345              break;
1346              case error.PERMISSION_DENIED:
1347                $err_msg.html((asl_configuration.words.geo_location_error || error.message) || "User denied the request for Geolocation.");
1348                break;
1349              case error.POSITION_UNAVAILABLE:
1350                $err_msg.html("Location information is unavailable.");
1351                break;
1352              case error.TIMEOUT:
1353                $err_msg.html("The request to get user location timed out.");
1354                break;
1355              case error.UNKNOWN_ERROR:
1356                $err_msg.html("An unknown error occurred.");
1357                break;
1358              default:
1359                $err_msg.html(error.message);
1360            }
1361  
1362            $err_msg.appendTo('.asl-cont .asl-map');
1363            window.setTimeout(function() {
1364              $err_msg.remove();
1365            }, 5000);
1366          };
1367  
1368          //  Add the Error
1369          if(window.location.protocol == "http:") {
1370            geo_error({code: 'http'});return;
1371          }
1372  
1373          navigator.geolocation.getCurrentPosition(function(pos) {
1374  
1375              that.measure_distance(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
1376  
1377              //  bind the hook, geolocation
1378              asl_locator.hook_event({type: 'geolocation', data: pos.coords});
1379  
1380              //  Add the text to it
1381              that.add_search_text(asl_configuration.words.current_location);
1382  
1383            },
1384            geo_error, ({
1385              maximumAge: 60 * 1000,
1386              timeout: 10 * 1000
1387            })
1388          );
1389        }
1390      };
1391  
1392  
1393      /**
1394       * [geo_service GEO JS IP Free]
1395       * @return {[type]} [description]
1396       */
1397      asl_locator.View.prototype.geo_service = function() {
1398  
1399        var that = this;
1400  
1401        var ip_geoservice = "https://get.geojs.io/v1/ip/geo.json";
1402  
1403        $.ajax({
1404          url: ip_geoservice,
1405          type: 'GET',
1406          dataType: 'json',
1407          success: function(geo_resp) {
1408  
1409            if(geo_resp && geo_resp.latitude && geo_resp.longitude) {
1410              
1411              var geo_lat   = parseFloat(geo_resp.latitude),
1412                  geo_lng   = parseFloat(geo_resp.longitude),
1413                  geo_coord = new google.maps.LatLng(geo_lat, geo_lng);
1414  
1415              that.measure_distance(geo_coord);
1416              
1417              //  bind the hook, geolocation
1418              asl_locator.hook_event({type: 'geolocation', data: geo_coord});
1419            }
1420          },
1421          error: function(e) {
1422  
1423            console.warn('Error Store Locator! GeoJS API: ', e);
1424          }
1425        });
1426      };
1427  
1428  
1429      /**
1430       * [clear_infobox Remove the infobox if visible]
1431       * @return {[type]} [description]
1432       */
1433      asl_locator.View.prototype.clear_infobox = function() {
1434  
1435        // Clear the previous infobox if exist
1436        if(this.get('selectedStore')) {
1437          this.highlight(null);
1438        }
1439      };
1440  
1441      /**
1442       * [fitBound Fit Bound to the Stores, asl_configuration.category_bound]
1443       * @return {[type]} [description]
1444       */
1445      asl_locator.View.prototype.fitBound = function(_stores) {
1446  
1447        var stores = _stores || this.get('stores');
1448  
1449        if(stores.length) {
1450  
1451          var bounds = new google.maps.LatLngBounds();
1452  
1453          for (var s in stores) {
1454  
1455            if (!stores.hasOwnProperty(s)) continue;
1456  
1457            bounds.extend(stores[s].getLocation());
1458  
1459          }
1460  
1461          //  Set a max bound zoom to avoid zoom in
1462          var bound_zoom = asl_configuration.max_bound_zoom;
1463  
1464          if(bound_zoom) {
1465            google.maps.event.addListenerOnce(this.getMap(), 'bounds_changed', function() { 
1466              this.setZoom(Math.min(bound_zoom, this.getZoom())); 
1467            });
1468          }
1469  
1470          //  Fit bound to those stores
1471          this.getMap().fitBounds(bounds);
1472        }
1473      };
1474  
1475  
1476  
1477  
1478      /**
1479       * [init_ View Init]
1480       * @return {[type]} [description]
1481       */
1482      asl_locator.View.prototype.init_ = function() {
1483  
1484        //If geolocation is enabled show distance
1485        if (this.settings_['geolocation']) {
1486          this.geolocate_();
1487        }
1488  
1489        this.markerCache_ = {};
1490  
1491        var infobox_width = asl_configuration.infobox_width || 320;
1492  
1493  
1494        //var closeURL        = 'https://www.google.com/intl/en_us/mapfiles/close.gif',
1495        var closeURL        = asl_configuration.PLUGIN_URL + ((asl_configuration.close_white)? "public/img/cross-white.png": "public/img/cross.png"),
1496            closeBoxMargin  = "11px 10px -27px 0px";
1497  
1498        //  For Template 0
1499        if(asl_configuration.infobox_layout == '2' || (asl_configuration.template == '1' && asl_configuration.infobox_layout == '0')) {
1500          closeURL = asl_configuration.PLUGIN_URL + "public/img/close-white.svg";
1501        }
1502        
1503  
1504  
1505        //closeURL = 'https://www.google.com/intl/en_us/mapfiles/close.gif';
1506  
1507        this.infoWindow_ = new InfoBox({
1508          //disableAutoPan: false,
1509          //pixelOffset: new google.maps.Size(-65, -140),
1510          boxStyle: {
1511            //width: "250px",
1512            //margin:'0 0 33px -120px'
1513            width: infobox_width + "px",
1514            margin: '0 0 '+asl_configuration.marker_height+'px -' + ((infobox_width / 2)) + 'px'
1515          },
1516          alignBottom: true,
1517          pane: false,
1518          disableAutoPan: true,
1519          closeBoxMargin: closeBoxMargin,
1520          closeBoxURL: closeURL,
1521          infoBoxClearance: new google.maps.Size(1, 1)
1522        });
1523  
1524        //infoBox,0 0 15px 27px
1525        var that = this;
1526        var map = this.getMap();
1527  
1528        this.set('updateOnPan', this.settings_['updateOnPan']); // true or false
1529  
1530        google.maps.event.addListener(this.infoWindow_, 'closeclick', function() {
1531          that.highlight(null);
1532        });
1533  
1534        google.maps.event.addListener(map, 'click', function() {
1535          that.highlight(null);
1536          that.infoWindow_.close();
1537        });
1538  
1539        //  Advanced Markers are enabled!
1540        if(asl_configuration.adv_mkr) {
1541  
1542          //  Cluster not supported
1543          asl_configuration.marker_label = asl_configuration.do_bounce = asl_configuration.active_marker = asl_configuration.cluster  = false;
1544          that.active_marker = '';
1545  
1546          /**
1547           * [createMarker Override the create marker function for Advanced Markers]
1548           * @param  {[type]} store [description]
1549           * @return {[type]}       [description]
1550           */
1551          this.createMarker = function(store) {
1552            
1553  
1554            var adv_marker = new google.maps.marker.AdvancedMarkerElement({
1555              content: store.advMkrContent(),
1556              position: store.getLocation(),
1557              title: store.props_.title
1558            });
1559            
1560            return adv_marker;
1561          };
1562  
1563          //  Missing methods
1564          google.maps.marker.AdvancedMarkerElement.prototype.getPosition = function() {return this.position;};
1565          google.maps.marker.AdvancedMarkerElement.prototype.getMap      = function() {return this.map;};
1566        }
1567      };
1568  
1569  
1570      /**
1571       * Adds/remove hooks as appropriate.
1572       */
1573      asl_locator.View.prototype.updateOnPan_changed = function() {
1574  
1575  
1576        if (this.updateOnPanListener_) {
1577          google.maps.event.removeListener(this.updateOnPanListener_);
1578        }
1579  
1580        var that = this;
1581        //validate the view
1582  
1583        if (this.get('updateOnPan') && this.getMap()) {
1584          var that = this,
1585            map = this.getMap(),
1586            updateOnPan_method = function(e) {
1587  
1588              if (asl_configuration.reset_button && $('.asl-reset-map')[0]) {
1589  
1590                if ($('.asl-reset-map')[0].style != 'block')
1591                  $('.asl-reset-map')[0].style.display = 'block';
1592              }
1593  
1594              //if(that.showing_direction || asl_configuration.load_all != '1')return;
1595              //closing this refreshview for testing :: 4-22-2017 :: majin
1596              
1597              if(asl_configuration.sort_by_bound) {
1598  
1599                that.refreshView();
1600              }
1601            };
1602          this.updateOnPanListener_ = google.maps.event.addListener(map, 'dragend', //idle
1603            updateOnPan_method
1604          );
1605        }
1606      };
1607  
1608      /**
1609       * Add a store to the map.
1610       * @param {asl_locator.Store} store the store to add.
1611       */
1612      asl_locator.View.prototype.addStoreToMap = function(store) {
1613  
1614        var marker = this.getMarker(store);
1615        store.setMarker(marker);
1616        var that = this;
1617  
1618        //Marker Click or mouse over event
1619  
1620        marker.clickListener_ = google.maps.event.addListener(marker, (asl_configuration.mouseover) ? 'mouseover' : 'click',
1621          function() {
1622  
1623            //  Redirect to the website URL instead of showing popup
1624            if(asl_configuration.click_redirect) {
1625  
1626              //  the link
1627              var link = store.props_[asl_configuration.click_redirect];
1628  
1629              //  redirect to that given link
1630              if(link) {
1631                window.location.href = link;
1632              }
1633              
1634              return;
1635            }
1636  
1637            //  Marker is clicked
1638            that.marker_clicked = true;
1639  
1640            that.halt_fetch     = true;
1641            that.marker_center  = marker.getPosition();
1642            that.highlight(store, false);
1643  
1644            if (_asl_map_customize && _asl_map_customize.marker_animations == 1)
1645              marker.setAnimation(google.maps.Animation.Xp);
1646          });
1647  
1648        if (marker.getMap() != this.getMap()) {
1649          marker.setMap(this.getMap());
1650  
1651          if (_asl_map_customize && _asl_map_customize.marker_animations == 1)
1652            marker.setAnimation(google.maps.Animation.Xp);
1653        }
1654      };
1655  
1656      /**
1657       * Create a marker for a store.
1658       * @param {asl_locator.Store} store the store to produce a marker for.
1659       * @this asl_locator.View
1660       * @return {google.maps.Marker} a new marker.
1661       * @export
1662       */
1663      asl_locator.View.prototype.createMarker = function(store) {
1664  
1665        var url             = asl_configuration.PLUGIN_URL + 'public/icon/',
1666            marker_category = asl_categories[store.categories_[0]];
1667  
1668        var marker_index    = 0;
1669  
1670        url += 'default.png';
1671  
1672        //  Marker title
1673        var marker_title = (asl_configuration.marker_title)? ((this.cat_in_tooltip && marker_category && marker_category['name'])?  marker_category['name'] + ' | ' + store.props_.title: store.props_.title): null;
1674  
1675        //http://image.flaticon.com/icons/svg/252/252025.svg
1676        //new google.maps.MarkerImage(url, null, null, null, markerSize);
1677        var marker_param = {
1678          title: asl_engine.helper.html_entites(marker_title),
1679          position: store.getLocation(),
1680          zIndex: asl_configuration.marker_index? marker_index: null,
1681          animation: (_asl_map_customize && _asl_map_customize.marker_animations == 1) ? google.maps.Animation.BOUNCE : null,
1682          icon: {
1683            url: url
1684          }
1685        };
1686  
1687        //  When we have icon
1688        if(this.icon) {
1689  
1690          //  copy the icon
1691          marker_param['icon']        = Object.assign({}, this.icon);
1692  
1693          //  add the url
1694          marker_param['icon']['url'] = url;
1695        }
1696  
1697        //  When you have Marker Label
1698        if(asl_configuration.marker_label && store.props_.label) {
1699  
1700          marker_param['label'] = {text: store.props_.label, color: asl_configuration.label_color || "#eb3a44",fontSize: "16px",fontWeight: "bold"};
1701         
1702        }
1703  
1704        return new google.maps.Marker(marker_param);
1705      };
1706  
1707      /**
1708       * Get a marker for a store. By default, this caches the value from
1709       * createMarker(store)
1710       * @param {asl_locator.Store} store the store to get the marker from.
1711       * @return {google.maps.Marker} the marker.
1712       */
1713      asl_locator.View.prototype.getMarker = function(store) {
1714  
1715        var cache = this.markerCache_;
1716        var key = store.id_;
1717  
1718        if (!cache[key]) {
1719  
1720          cache[key] = this['createMarker'](store);
1721        }
1722  
1723  
1724        return cache[key];
1725      };
1726  
1727      /**
1728       * Get a InfoWindow for a particular store.
1729       * @param {asl_locator.Store} store the store.
1730       * @return {google.maps.InfoWindow} the store's InfoWindow.
1731       */
1732      asl_locator.View.prototype.getInfoWindow = function(store, stores) {
1733  
1734        if (!store) {
1735          return this.infoWindow_;
1736        }
1737  
1738        var div = $(store.getInfoWindowContent(stores));
1739  
1740        this.infoWindow_.setContent(div[0]);
1741        return this.infoWindow_;
1742      };
1743  
1744      /**
1745       * Gets all possible features for this View.
1746       * @return {asl_locator.FeatureSet} All possible features.
1747       */
1748      asl_locator.View.prototype.getViewFeatures = function() {
1749  
1750        return this.settings_['features'];
1751      };
1752  
1753      /**
1754       * Gets a feature by its id. Convenience method.
1755       * @param {string} id the feature's id.
1756       * @return {asl_locator.Feature|undefined} The feature, if the id is valid.
1757       * undefined if not.
1758       */
1759      asl_locator.View.prototype.getFeatureById = function(id) {
1760  
1761        if (!this.featureById_) {
1762          this.featureById_ = {};
1763          var feature_list  = this.getViewFeatures().asList();
1764          
1765          for (var i = 0, feature; feature = feature_list[i]; i++) {
1766            this.featureById_[feature.id_] = feature;
1767          }
1768        }
1769        return this.featureById_[id];
1770      };
1771  
1772      /**
1773       * featureFilter_changed event handler.
1774       */
1775      asl_locator.View.prototype.featureFilter_changed = function() {
1776  
1777        google.maps.event.trigger(this, 'featureFilter_changed',
1778          this.get('featureFilter'));
1779  
1780        if (this.get('stores')) {
1781          this.clearMarkers();
1782        }
1783      };
1784  
1785      /**
1786       * Clears the visible markers on the map.
1787       */
1788      asl_locator.View.prototype.clearMarkers = function() {
1789  
1790        for (var marker in this.markerCache_) {
1791          this.markerCache_[marker].setMap(null);
1792          var listener = this.markerCache_[marker].clickListener_;
1793          if (listener) {
1794            google.maps.event.removeListener(listener);
1795          }
1796        }
1797      };
1798  
1799  
1800      /**
1801       * [storesWithCategory Get the Stores with the Category ID]
1802       * @param  {[type]} _category_id [description]
1803       * @return {[type]}              [description]
1804       */
1805      asl_locator.View.prototype.storesWithCategory = function(_category_id) {
1806  
1807        var stores = this.get('stores');
1808  
1809        var filtered = [];
1810  
1811        if (stores) {
1812  
1813          for (var i = 0, ii = stores.length; i < ii; i++) {
1814            
1815            if(stores[i].hasCategory(_category_id)) {
1816  
1817              filtered.push(stores[i]);
1818            }
1819          }
1820        }
1821  
1822        return filtered;
1823      };
1824  
1825  
1826      /**
1827       * [categoryClearAll Remove all the categories]
1828       * @return {[type]} [description]
1829       */
1830      asl_locator.View.prototype.categoryClearAll = function() {
1831  
1832        //  Get all the Stores with the Category ID li_cat_id
1833        //var stores = view.storesWithCategory(_category_id);
1834        var featureFilter_inst = this.get('featureFilter');
1835  
1836        for (var f in featureFilter_inst.array_) {
1837          featureFilter_inst.array_.pop();
1838        }
1839  
1840      };
1841  
1842      /**
1843       * [categoryAccFilter Category accordion filter, filter the stores]
1844       * @param  {[type]} _category_id [description]
1845       * @return {[type]}              [description]
1846       */
1847      asl_locator.View.prototype.categoryAccFilter = function(_category_id, _state) {
1848  
1849        //  Get all the Stores with the Category ID li_cat_id
1850        //var stores = view.storesWithCategory(_category_id);
1851        var featureFilter_inst = this.get('featureFilter');
1852  
1853        //  add the feature
1854        var feature = (_category_id && _state)? this.getFeatureById(_category_id): null;
1855  
1856        if(feature) {
1857          
1858          featureFilter_inst.add(feature);
1859        }
1860  
1861        this.set('featureFilter', featureFilter_inst);
1862        this.refreshView();
1863        this.fitBound();
1864      };
1865  
1866  
1867      /**
1868       * [bounce Bounce the Store Marker]
1869       * @param  {[type]} store   [description]
1870       * @param  {[type]} _status [description]
1871       * @return {[type]}         [description]
1872       */
1873      asl_locator.View.prototype.doBounce = function(store, _status) {
1874  
1875        //  No bounce with marker label
1876        if(asl_configuration.marker_label)return;
1877  
1878        var _marker = store.getMarker();
1879  
1880        _marker.setAnimation(null);
1881  
1882        if (_status) {
1883          //_marker.setZIndex(100);
1884          _marker.setAnimation(google.maps.Animation.BOUNCE);
1885        } else {
1886          //_marker.setZIndex(store.props_.ordr || 0);
1887        }
1888  
1889      };
1890  
1891  
1892      /**
1893       * [reloadLocator Reload the Store Locator based on the Parameters]
1894       * @param  {[type]} _params [description]
1895       * @return {[type]}         [description]
1896       */
1897      asl_locator.View.prototype.reloadLocator = function(_params, _callback) {
1898  
1899        //  Must be load all
1900        asl_configuration.load_all = '1';
1901  
1902        //   Remove all the markers
1903        this.clearMarkers();
1904  
1905            //  Cluster
1906        if (asl_configuration.cluster) {
1907  
1908          asl_locator.marker_clusters.clearMarkers();
1909        }
1910  
1911        // Reset Stores Immediately
1912        this.data_.stores_ = [];
1913  
1914        //  Clean current ones
1915        this.refreshView();
1916  
1917        delete asl_locator.Store.infoPanelCache_;
1918        asl_locator.Store.infoPanelCache_ = {};
1919  
1920        this.data_.fetch_remote_data(null, _params, _callback);
1921      };
1922  
1923      /**
1924       * Refresh the map's view. This will fetch new data based on the map's bounds.
1925       */
1926      asl_locator.View.prototype.refreshView = function() {
1927  
1928        var that = this,
1929          bounds = this.getMap().getBounds();
1930  
1931        console.log('CALLING REFRESH VIEW');
1932  
1933        //  1- brand-attr
1934        var attr_fields = {};
1935  
1936        //  When First Load is enabled, there must be distance or search address active
1937        if (!asl_configuration.first_load || asl_configuration.first_load != '1') {
1938            
1939          if(!that.dest_coords && !that.prop_filter) {
1940  
1941            //  No search is perform as coordinates are not there
1942            that.search_performed = false;
1943  
1944            that.set('stores', []);
1945            return;
1946          }
1947        }
1948  
1949        //  Yes, search is perform with coordinates
1950        that.search_performed = true;
1951  
1952        this.data_.getStores(bounds, (this.get('featureFilter')), function(stores) {
1953  
1954          var oldStores = that.get('stores');
1955  
1956          //  Remove all old Stores Markers
1957          if (oldStores) {
1958  
1959            for (var i = 0, ii = oldStores.length; i < ii; i++) {
1960              google.maps.event.removeListener(
1961                oldStores[i].getMarker().clickListener_);
1962            }
1963          }
1964  
1965          //  When Range slider is enabled
1966          var stores_in_range = [],
1967              priority_stores = [],
1968              filter_text     = null,
1969              has_distance    = (stores && stores[0] && stores[0].props_.dist_str)? true: false,
1970              check_distance  = false,
1971              bbox_check      = (asl_configuration.boundary_box && that.bbox)? true: false;
1972  
1973          //  When Store Radius is Enabled!
1974          var by_store_radius = false;
1975  
1976  
1977          //Refresh Category Stores Counts
1978          var c_keys = Object.keys(asl_categories);
1979  
1980          //  2- brand-attr
1981          var fields = asl_configuration.filter_ddl;
1982  
1983          for (var c in c_keys) {
1984  
1985            if (asl_categories[c_keys[c]])
1986              asl_categories[c_keys[c]].len = 0;
1987          }
1988  
1989  
1990          for (var c in c_keys) {
1991  
1992            if (asl_categories[c_keys[c]])
1993              asl_categories[c_keys[c]].len = 0;
1994          }
1995  
1996  
1997          /////////////////////////
1998          // Loop for the stores //
1999          /////////////////////////
2000          for (var k in stores) {
2001  
2002            if (!stores.hasOwnProperty(k)) continue;
2003  
2004            //  Temp store instance
2005            var _store = stores[k].props_;
2006  
2007  
2008            /////////////////////////
2009            //////Distance Testing //
2010            /////////////////////////
2011  
2012            //  Store Radius validation for each Store
2013            if(bbox_check) {
2014  
2015              if (!that.bbox.contains(stores[k].getLocation())) {
2016                  continue;
2017              }
2018            }
2019            else if (asl_configuration.advance_filter) {
2020  
2021              //If not valid continue
2022              if (check_distance && _store.distance >= asl_configuration.radius_range) {
2023                continue;
2024              }
2025  
2026            }
2027            //When Advance filter is OFF
2028            else if (asl_configuration.fixed_radius && _store.distance) {
2029  
2030              //If in Range
2031              if (_store.distance >= asl_configuration.fixed_radius) {
2032                continue;
2033              }
2034            }
2035  
2036       
2037            //  Else add into array
2038            if (_store.ordr > 0)
2039              priority_stores.push(stores[k]);
2040            else
2041              stores_in_range.push(stores[k]);   
2042          }
2043  
2044  
2045          //  Change the categories count
2046          if (asl_configuration.template == "2" && asl_configuration.advance_filter) {
2047  
2048            var $category_box = $('.asl-cont .asl-categories-list .round-box');
2049  
2050            $category_box.each(function(e) {
2051  
2052              $(this).attr('data-c', (asl_categories[$(this).attr('data-id')].len));
2053              this.children[0].children[1].children[0].children[1].innerHTML = '(' + asl_categories[$(this).attr('data-id')].len + ')';
2054            });
2055          }
2056  
2057          //  IF Priority Stores Exist, Sort them ?
2058          if (priority_stores.length > 0) {
2059  
2060            // Sort by distance first for the Prioirity Stores
2061            if(that.dest_coords)
2062              that.data_.sortDistance(that.dest_coords, priority_stores);
2063  
2064            //  Sort by the number, as second
2065            that.data_.sortByDesc('ordr', priority_stores);
2066          }
2067  
2068          
2069          ///////////////////
2070          /////// Sortings //
2071          ///////////////////
2072          
2073          if(asl_configuration.sort_random) {
2074            
2075            that.data_.sortRandom(stores_in_range);
2076          }
2077          else if (asl_configuration.sort_by) {
2078  
2079            that.data_.sortBy(asl_configuration.sort_by, stores_in_range);
2080          }
2081          //  Sorted by the distance
2082          else if (stores_in_range && that.dest_coords) {
2083  
2084            //  located Position
2085            that.data_.sortDistance(that.dest_coords, stores_in_range);
2086          } 
2087          //  sorted by the bound
2088          else if (bounds && asl_configuration.sort_by_bound)
2089            that.data_.sortDistance(bounds.getCenter(), stores_in_range);
2090  
2091  
2092          //  Merge Priority Stores
2093          if (priority_stores.length > 0) {
2094  
2095            // Merge it
2096            stores_in_range = priority_stores.concat(stores_in_range);
2097          }
2098  
2099  
2100          //  Apply the Limit
2101          if (asl_configuration.stores_limit) {
2102  
2103            stores_in_range = stores_in_range.slice(0, asl_configuration.stores_limit);
2104          }
2105  
2106          //  If has Marker Label OR Advanced Marker
2107          if((asl_configuration.adv_mkr ||  asl_configuration.marker_label) && has_distance) {
2108  
2109            var max_len = stores_in_range.length;
2110            //var max_len = (stores_in_range.length < 100)? stores_in_range.length: 100;
2111  
2112            for(var s = 0; s < max_len; s++) {
2113              stores_in_range[s].props_.label = String(s + 1);
2114            }
2115  
2116            //  Clear the marker cache
2117            delete that.markerCache_;
2118            that.markerCache_ = {};
2119          }
2120          
2121          //  Show a store when there are no stores within the range
2122          if(!stores_in_range.length && asl_configuration.default_store) {
2123  
2124            var default_store = stores.filter(function(x) {
2125              return x.props_.id === parseInt(asl_configuration.default_store);
2126            });
2127  
2128            stores_in_range = default_store;
2129          }
2130          
2131          //  Set new stores          
2132          that.set('stores', stores_in_range);
2133  
2134          //  Set the Stores in Panel
2135          that._panel.set('stores', [true]);
2136  
2137          //  Category bound
2138          if(asl_configuration.select_category && asl_configuration.category_bound) {
2139              
2140            //  When there is no default-addr
2141            if(!asl_configuration['default-addr'])
2142              that.fitBound(null);
2143  
2144            //  remove preselection
2145            asl_configuration.select_category = null;
2146          }
2147        });
2148      };
2149  
2150      /**
2151       * stores_changed event handler.
2152       * This will display all new stores on the map.
2153       * @this asl_locator.View
2154       */
2155      asl_locator.View.prototype.stores_changed = function() {
2156  
2157  
2158        var stores = this.get('stores'),
2159          current_markers = [];
2160  
2161        //  Clear old Markers When Cluster is OFF
2162        if (!asl_configuration.cluster)
2163          this.clearMarkers();
2164  
2165        for (var i = 0, store; store = stores[i]; i++) {
2166  
2167          this.addStoreToMap(store);
2168          current_markers.push(store.marker_);
2169        }
2170  
2171        if (asl_configuration.cluster) {
2172  
2173          asl_locator.marker_clusters.clearMarkers();
2174          asl_locator.marker_clusters.addMarkers(current_markers);
2175        }
2176      };
2177  
2178      /**
2179       * Gets the view's Map.
2180       * @return {google.maps.Map} the view's Map.
2181       */
2182      asl_locator.View.prototype.getMap = function() {
2183        return this.map_;
2184      };
2185  
2186      /**
2187       * [map_recenter Recenter the Map]
2188       * @param  {[type]} latlng  [description]
2189       * @param  {[type]} offsetx [description]
2190       * @param  {[type]} offsety [description]
2191       * @return {[type]}         [description]
2192       */
2193      asl_locator.View.prototype.map_recenter = function(latlng, offsetx, offsety) {
2194  
2195        var map = this.getMap();
2196        var point1 = map.getProjection().fromLatLngToPoint(
2197          (latlng instanceof google.maps.LatLng) ? latlng : map.getCenter()
2198        );
2199        var point2 = new google.maps.Point(
2200          ((typeof(offsetx) == 'number' ? offsetx : 0) / Math.pow(2, map.getZoom())) || 0,
2201          ((typeof(offsety) == 'number' ? offsety : 0) / Math.pow(2, map.getZoom())) || 0
2202        );
2203        map.panTo(map.getProjection().fromPointToLatLng(new google.maps.Point(
2204          point1.x - point2.x,
2205          point1.y + point2.y
2206        )));
2207      };
2208  
2209  
2210      /**
2211       * [highlightAdvMkr Highlight a Advanced Marker]
2212       * @param  {[type]} store         [description]
2213       * @param  {[type]} _item_clicked [description]
2214       * @return {[type]}               [description]
2215       */
2216      asl_locator.View.prototype.highlightAdvMkr = function(store, _item_clicked) {
2217  
2218        var _map       = this.getMap(),
2219            that       = this;
2220  
2221        //  Remove the highlight of previous selection
2222        var prev_selected = this.get('selectedStore');
2223  
2224        if(prev_selected) {
2225  
2226          //  Advance Marker instance
2227          var marker = prev_selected.getMarker();
2228  
2229          //  Set as Active
2230          $(marker.targetElement).removeClass('asl-mkr-actv');
2231  
2232          //  Reset the zIndex
2233          marker.zIndex = null;
2234        }
2235  
2236  
2237        //If valid Store
2238        if (store) {
2239  
2240  
2241          var stores = this.get('stores');
2242  
2243          //  when we have the zoom value
2244          if(asl_configuration.zoom_li)
2245            _map.setZoom(parseInt(asl_configuration.zoom_li));
2246          
2247          this.map_recenter(store.getLocation(), asl_configuration.info_x_offset, asl_configuration.info_y_offset);
2248  
2249          //  bind the hook, store highlight
2250          asl_locator.hook_event({type: 'select', data: store.props_});
2251  
2252          //map.getStreetView().setVisible(true)
2253          if (_map.getStreetView().getVisible()) {
2254            _map.getStreetView().setPosition(store.getLocation());
2255          }
2256  
2257          //  Advance Marker instance
2258          var marker = store.getMarker();
2259  
2260          //  Set as Active
2261          $(marker.targetElement).addClass('asl-mkr-actv');
2262  
2263          //  Set on the top
2264          marker.zIndex = 1;
2265          
2266        }
2267  
2268        this.set('selectedStore', store);
2269  
2270  
2271        
2272        //  Highlight the Store, Add Highlight Class
2273        if (!_item_clicked && store  && !asl_configuration.accordion) {
2274  
2275          window.setTimeout(function() {
2276
2277            //  To avoid the scroll
2278            if(asl_configuration.disable_scroll)return;
2279  
2280            var sl_box = that._panel.mainPanel;
2281            var ele_   = that._panel.storeList_.find('.sl-item[data-id="' + store.id_ + '"]');          
2282            
2283            // Get scroll offset with type safety
2284            var scrollOffset = parseInt(asl_configuration.scroll_offset_y, 10) || 60; // Force to integer, default to 60
2285
2286            var top_offset = ele_.position().top;
2287
2288            top_offset = Math.max(top_offset - scrollOffset, 0);
2289  
2290            if (ele_[0])
2291              sl_box.animate({
2292                //scrollTop: top_offset + sl_box[0].scrollTop
2293                scrollTop: top_offset
2294              }, 'fast');
2295  
2296  
2297          }, 500);
2298        }
2299      };
2300  
2301      /**
2302       * Select a particular store.
2303       * @param {asl_locator.Store} store the store to highlight.
2304       * @param {boolean} pan if panning to the store on the map is desired.
2305       */
2306      asl_locator.View.prototype.highlight = function(store, _item_clicked) {
2307  
2308        var infoWindow = null,
2309            _map       = this.getMap(),
2310            that       = this;
2311  
2312  
2313  
2314        //  For Advanced Markers
2315        if(asl_configuration.adv_mkr) {
2316          return this.highlightAdvMkr(store, _item_clicked);
2317        }
2318  
2319  
2320        //If valid Store
2321        if (store) {
2322  
2323          var stores = this.get('stores');
2324          infoWindow = this.getInfoWindow(store, stores);
2325  
2326  
2327          if (store.getMarker()) {
2328  
2329            var _this = this,
2330              m = store.getMarker();
2331  
2332            infoWindow.open(_map, store.getMarker());
2333  
2334            //Store viewed
2335            if (asl_configuration.analytics) {
2336  
2337              asl_locator.save_analytics(store, 1);
2338            }
2339          }
2340          else {
2341            infoWindow.setPosition(store.getLocation());
2342            infoWindow.open(_map);
2343          }
2344  
2345          
2346          _map.setZoom(parseInt(asl_configuration.zoom_li));
2347          this.map_recenter(store.getLocation(), asl_configuration.info_x_offset, asl_configuration.info_y_offset);
2348  
2349  
2350          //  bind the hook, store highlight
2351          asl_locator.hook_event({type: 'store', data: store.props_});
2352  
2353          //map.getStreetView().setVisible(true)
2354          if (_map.getStreetView().getVisible()) {
2355            _map.getStreetView().setPosition(store.getLocation());
2356          }
2357  
2358        } 
2359        else {
2360          this.getInfoWindow().close();
2361  
2362          //  bind the hook, store highlight
2363          asl_locator.hook_event({type: 'clear', data: null});
2364        }
2365  
2366        this.set('selectedStore', store);
2367  
2368        //  Highlight the Store, Add Highlight Class
2369        if (!_item_clicked && store) {
2370  
2371          window.setTimeout(function() {
2372
2373            //  To avoid the scroll
2374            if(asl_configuration.disable_scroll)return;
2375  
2376            var sl_box = that._panel.mainPanel;
2377            var ele_   = that._panel.storeList_.find('.sl-item[data-id="' + store.id_ + '"]');          
2378            
2379            // Get scroll offset with type safety
2380            var scrollOffset = parseInt(asl_configuration.scroll_offset_y, 10) || 60; // Force to integer, default to 60
2381
2382            var top_offset = ele_.position().top;
2383
2384            top_offset = Math.max(top_offset - scrollOffset, 0);
2385  
2386            if (ele_[0])
2387              sl_box.animate({
2388                //scrollTop: top_offset + sl_box[0].scrollTop
2389                scrollTop: top_offset
2390              }, 'fast');
2391          }, 500);
2392        }
2393  
2394      };
2395  
2396      asl_locator.View.prototype.selectedStore_changed = function() {
2397        google.maps.event.trigger(this, 'selectedStore_changed', this.get('selectedStore'));
2398      };
2399  
2400      asl_locator.ViewOptions = function() {};
2401  
2402      /**
2403       * Whether the map should update stores in the visible area when the visible
2404       * area changes. <code>refreshView()</code> will need to be called
2405       * programatically. Defaults to true.
2406       * @type boolean
2407       */
2408      asl_locator.ViewOptions.prototype.updateOnPan;
2409  
2410      /**
2411       * Whether the store locator should attempt to determine the user's location
2412       * for the initial view. Defaults to true.
2413       * @type boolean
2414       */
2415      asl_locator.ViewOptions.prototype.geolocation;
2416  
2417      /**
2418       * All available store features. Defaults to empty FeatureSet.
2419       * @type asl_locator.FeatureSet
2420       */
2421      asl_locator.ViewOptions.prototype.features;
2422  
2423      /**
2424       * The icon to use for markers representing stores.
2425       * @type string|google.maps.MarkerImage
2426       */
2427      asl_locator.ViewOptions.prototype.markerIcon;
2428  
2429  
2430      /**
2431       * Representation of a feature of a store. (e.g. 24 hours, BYO, etc).
2432       * @example <pre>
2433       * var feature = new asl_locator.Feature('24hour', 'Open 24 Hours');
2434       * </pre>
2435       * @param {string} id unique identifier for this feature.
2436       * @param {string} name display name of this feature.
2437       * @constructor
2438       * @implements asl_locator_Feature
2439       */
2440      asl_locator.Feature = function(id, name, img, _s) {
2441  
2442        this.id_      = id;
2443        this.name_    = name;
2444        this.img_     = img;
2445        this.order    = _s;
2446      };
2447  
2448      asl_locator['Feature'] = asl_locator.Feature;
2449  
2450      /**
2451       * Gets this Feature's ID.
2452       * @return {string} this feature's ID.
2453       */
2454      asl_locator.Feature.prototype.getId = function() {
2455        return this.id_;
2456      };
2457  
2458      /**
2459       * Gets this Feature's display name.
2460       * @return {string} this feature's display name.
2461       */
2462      asl_locator.Feature.prototype.getDisplayName = function() {
2463        return this.name_;
2464      };
2465  
2466      asl_locator.Feature.prototype.toString = function() {
2467        return this.getDisplayName();
2468      };
2469  
2470  
2471  
2472      asl_locator.FeatureSet = function(var_args) {
2473  
2474        /**
2475         * Stores references to the actual Feature.
2476         * @private
2477         * @type {!Array.<asl_locator.Feature>}
2478         */
2479        this.array_ = [];
2480  
2481        /**
2482         * Maps from a Feature's id to its array index.
2483         * @private
2484         * @type {Object.<string, number>}
2485         */
2486        this.hash_ = {};
2487  
2488        for (var i = 0, feature; feature = arguments[i]; i++) {
2489          this.add(feature);
2490        }
2491      };
2492  
2493      asl_locator['FeatureSet'] = asl_locator.FeatureSet;
2494  
2495      /**
2496       * Adds the given feature to the set, if it doesn't exist in the set already.
2497       * Else, removes the feature from the set.
2498       * @param {!asl_locator.Feature} feature the feature to toggle.
2499       */
2500      asl_locator.FeatureSet.prototype.toggle = function(feature) {
2501  
2502        if (this.hash_[feature.id_]) {
2503          this.remove(feature);
2504        } else {
2505  
2506          this.add(feature);
2507        }
2508  
2509      };
2510  
2511      /**
2512       * Adds a feature to the set.
2513       * @param {asl_locator.Feature} feature the feature to add.
2514       */
2515      asl_locator.FeatureSet.prototype.add = function(feature) {
2516  
2517        if (!feature) {
2518          return;
2519        }
2520  
2521        this.array_.push(feature);
2522        this.hash_[feature.id_] = 1;
2523      };
2524  
2525      /**
2526       * Removes a feature from the set, if it already exists in the set. If it does
2527       * not already exist in the set, this function is a no op.
2528       * @param {!asl_locator.Feature} feature the feature to remove.
2529       */
2530      asl_locator.FeatureSet.prototype.remove = function(feature) {
2531  
2532        var _feature_id = feature.id_;
2533  
2534        if (!this.hash_[_feature_id]) {
2535          return;
2536        }
2537  
2538        delete this.hash_[_feature_id];
2539        this.array_ = this.array_.filter(function(e) { return e && e.id_ != _feature_id });
2540      };
2541  
2542      /**
2543       * Get the contents of this set as an Array.
2544       * @return {Array.<!asl_locator.Feature>} the features in the set, in the order
2545       * they were inserted.
2546       */
2547      asl_locator.FeatureSet.prototype.asList = function() {
2548  
2549        var filtered = [];
2550        for (var i = 0, ii = this.array_.length; i < ii; i++) {
2551          var elem = this.array_[i];
2552          if (elem !== null) {
2553            filtered.push(elem);
2554          }
2555        }
2556        return filtered;
2557      };
2558  
2559      /**
2560       * Empty feature set.
2561       * @type asl_locator.FeatureSet
2562       * @const
2563       */
2564      asl_locator.FeatureSet.NONE = new asl_locator.FeatureSet;
2565  
2566  
2567      /**
2568       * An info panel, to complement the map view.
2569       * Provides a list of stores, location search, feature filter, and directions.
2570       * @example <pre>
2571       * var container = document.getElementById('panel');
2572       * var panel = new asl_locator.Panel(container, {
2573       *   view: view,
2574       *   locationSearchLabel: 'Location:'
2575       * });
2576       * google.maps.event.addListener(panel, 'geocode', function(result) {
2577       *   geocodeMarker.setPosition(result.geometry.location);
2578       * });
2579       * </pre>
2580       * @param {!Node} el the element to contain this panel.
2581       * @param {asl_locator.PanelOptions} opt_options
2582       * @constructor
2583       * @implements asl_locator_Panel
2584       */
2585      asl_locator.Panel = function(el, opt_options) {
2586  
2587        
2588        var that = this;
2589  
2590        this.el_ = $(el);
2591  
2592        this.el_.addClass('asl_locator-panel');
2593        this.settings_ = $.extend({
2594          'locationSearch': true,
2595          'locationSearchLabel': 'Enter Location/ZipCode: ',
2596          'featureFilter': true,
2597          'directions': true,
2598          'view': null
2599        }, opt_options);
2600  
2601        this.directionsRenderer_ = new google.maps.DirectionsRenderer({
2602          draggable: true
2603        });
2604        this.directionsService_ = new google.maps.DirectionsService;
2605  
2606  
2607        //lookhere
2608        opt_options.view._panel = this; 
2609  
2610        this.init_();
2611  
2612  
2613        //  Print button event
2614        $('.asl-cont .asl-print-btn').bind('click', function(e) {
2615  
2616          var print_cont_id = "asl-list";
2617  
2618          //  make use of the direction for printing
2619          if($('#asl-list .panel-inner').css('display') == 'none') {
2620            
2621            print_cont_id = 'asl-rendered-dir';
2622            $('#asl-list').find('.rendered-directions').attr('id', print_cont_id);
2623          }
2624  
2625  
2626          var print_params = {
2627            printable: print_cont_id, 
2628            type: "html",
2629            css: asl_configuration.PLUGIN_URL + 'public/css/print.css'
2630          };
2631  
2632          //  Add the Header
2633          if(asl_configuration.print_header) {
2634            print_params['header'] = asl_configuration.print_header;
2635          }
2636  
2637          printJS(print_params);
2638        });
2639      };
2640  
2641      asl_locator['Panel'] = asl_locator.Panel;
2642  
2643      asl_locator.Panel.prototype = new google.maps.MVCObject;
2644  
2645      /**
2646       * Initialise the info panel
2647       * @private
2648       */
2649      asl_locator.Panel.prototype.init_ = function() {
2650  
2651        var that = this;
2652        this.itemCache_ = {};
2653  
2654        if (this.settings_['view']) {
2655          this.set('view', this.settings_['view']);
2656        }
2657  
2658        this.filter_ = $('.asl-cont .header-search');
2659  
2660        // this.el_.parent().prepend(this.filter_);
2661        var view  = that.get('view');
2662        var map   = view.getMap();
2663        
2664        //When Clusters
2665        if (asl_configuration.cluster) {
2666  
2667          asl_locator.marker_clusters = new MarkerClusterer(map, [], {
2668            maxZoom: parseInt(asl_configuration.cluster_max_zoom) || 9,
2669            gridSize: parseInt(asl_configuration.cluster_grid_size) || 90,
2670            styles: [{width: 30,height: 30,className: "asl-cluster-1"},{width: 40,height: 40,className: "asl-cluster-2"},{width: 50,height: 50,className: "asl-cluster-3"}],
2671            clusterClass: "asl-cluster"
2672            //imagePath: asl_configuration.URL + 'icon/m'
2673          });
2674  
2675        }
2676  
2677        if (this.settings_['locationSearch']) {
2678  
2679          this.locationSearch_ = this.filter_;
2680       
2681          if (typeof google.maps.places != 'undefined') {
2682  
2683            var _input_txt = $('.asl-cont #auto-complete-search,.asl-cont .asl-search-address')[0];
2684            //Add search to the stores name
2685            if (asl_configuration.search_type == '0') {
2686              this.initAutocomplete_(_input_txt);
2687            }
2688  
2689            //  Add the Geocoder for the Additional Search
2690            if(asl_configuration.additional_search) {
2691              this.geoCoder(_input_txt);
2692            }
2693          } 
2694          else {
2695            this.filter_.submit(function() {
2696              that.searchPosition($('input', that.locationSearch_).val());
2697            });
2698          }
2699  
2700          this.filter_.submit(function() {
2701            return false;
2702          });
2703  
2704          google.maps.event.addListener(this, 'geocode', function(place) {
2705            //console.log('===> site_script.js ===> GEOCODE IS INVOKED');
2706            if (that.searchPositionTimeout_) {
2707              window.clearTimeout(that.searchPositionTimeout_);
2708            }
2709            if (!place.geometry) {
2710              //console.log('===> site_script.js ===> SEARCHING FOR POSITION');
2711              that.searchPosition(place.name);
2712              return;
2713            }
2714  
2715            this.directionsFrom_ = place.geometry.location;
2716  
2717            if (that.directionsVisible_) {
2718              that.renderDirections_();
2719            }
2720            
2721            var sl = that.get('view');
2722            
2723            sl.highlight(null);
2724            
2725            var map = sl.getMap();
2726            
2727            if (place.geometry.viewport) {
2728              map.fitBounds(place.geometry.viewport);
2729            }
2730            else {
2731              map.setCenter(place.geometry.location);
2732              map.setZoom(parseInt(asl_configuration.zoom_li));
2733            }
2734  
2735            sl.refreshView();
2736  
2737            that.listenForStoresUpdate_();
2738          });
2739        }
2740  
2741  
2742        //Feature Sets
2743        if (this.settings_['featureFilter']) {
2744  
2745          // TODO(cbro): update this on view_changed
2746          var _this = this;
2747          this.featureFilter_ = $('.asl-cont #filter-options');
2748          this.featureFilter_.show();
2749  
2750          //show the filters
2751          if (!asl_configuration.show_categories) {
2752  
2753            $('.asl-cont .sl-category-filter.drop_box_filter').remove();
2754          }
2755  
2756  
2757          if (asl_configuration.advance_filter)
2758            $('.asl-cont .asl-advance-filters').removeClass('hide');
2759  
2760  
2761          if (!asl_configuration.radius_range)
2762            asl_configuration.radius_range = (asl_configuration.fixed_radius) ? parseInt(asl_configuration.fixed_radius) : 1000;
2763  
2764  
2765  
2766          var tswitch = $('#asl-open-close');
2767          //time_switch:: asl open close
2768          if (asl_configuration.time_switch && tswitch[0]) {
2769            
2770            tswitch[0].checked = false;
2771            tswitch.bind('change', function(e) {
2772  
2773              asl_configuration.show_opened = this.checked;
2774              that.get('view').refreshView();
2775            });
2776          }
2777          else
2778            $('.asl-cont .Status_filter').remove();
2779  
2780          
2781          var allFeatures = this.get('view').getViewFeatures().asList();
2782          var $inner      = this.featureFilter_.find('.inner-filter');
2783  
2784  
2785  
2786          this.storeList_ = this.el_.find('.sl-list');
2787          this.SListCont_ = this.el_.find('.asl-panel-inner');
2788          this.mainPanel  = this.el_.find('.sl-main-cont-box');
2789  
2790  
2791          //  IF category is enabled
2792          allFeatures       =  (asl_configuration.cat_sort == 'name_')? asl_engine.helper.sortBy(allFeatures, 'name_', true): asl_engine.helper.sortBy(allFeatures, 'order');
2793        
2794        }
2795  
2796  
2797        this.directionsPanel_ = $('.asl-cont #agile-modal-direction');
2798  
2799        //Distance Slider
2800        var $direction_from = this.directionsPanel_.find('.frm-place');
2801        $direction_from.val('');
2802  
2803        if (that.dest_coords)
2804          that_.directionsFrom_ = that.dest_coords;
2805  
2806        var input_search = this.directionsPanel_.find('.frm-place')[0];
2807        this.input_search = new google.maps.places.Autocomplete(input_search);
2808  
2809        //  Apply the restriction
2810        var fields = ['geometry'];
2811        this.input_search.setFields(fields);
2812  
2813  
2814        var that_ = this;
2815        google.maps.event.addListener(this.input_search, 'place_changed',
2816          function() {
2817            that_.directionsFrom_ = this.getPlace().geometry.location;
2818          });
2819  
2820        this.directionsPanel_.find('.directions-to').attr('readonly', 'readonly');
2821        //this.directionsPanel_.hide();
2822        this.directionsVisible_ = false;
2823  
2824        //Direction Submit button
2825        this.directionsPanel_.find('.btn-submit').click(function(e) {
2826  
2827          if (that.dest_coords && $direction_from.val() == asl_configuration.words.current_location)
2828            that.directionsFrom_ = that.dest_coords || null;
2829  
2830          that.renderDirections_();
2831  
2832          return false;
2833        });
2834  
2835        if (asl_configuration.distance_unit == 'KM') {
2836  
2837          that.distance_type = google.maps.UnitSystem.METRIC;
2838          that.directionsPanel_.find('#rbtn-km')[0].checked = true;
2839        } 
2840        else
2841          that.distance_type = google.maps.UnitSystem.IMPERIAL;
2842  
2843        that.directionsPanel_.find('input[name=dist-type]').change(function() {
2844  
2845          that.distance_type = (this.value == 1) ? google.maps.UnitSystem.IMPERIAL : google.maps.UnitSystem.METRIC;
2846        });
2847  
2848  
2849        // Close button for the Direction panel
2850        this.el_.find('.directions-cont .close').click(function() {
2851          
2852          that.hideDirections();
2853          $('.asl-cont .count-row').removeClass('hide');
2854          $('.asl-cont #filter-options').removeClass('hide');
2855        });
2856  
2857  
2858        //  Close button for the Direction Panel
2859        this.directionsPanel_.find('.close-directions').click(function() {
2860          
2861          that.hideDirections();
2862          $('.asl-cont .count-row').removeClass('hide');
2863          $('.asl-cont #filter-options').removeClass('hide');
2864        });
2865  
2866        
2867        //  bind the hook, init
2868        asl_locator.hook_event({type: 'init', data: view.data_.stores_});
2869      };
2870  
2871  
2872  
2873  
2874  
2875      /**
2876       * Toggles a particular feature on/off in the feature filter.
2877       * @param {asl_locator.Feature} feature The feature to toggle.
2878       * @private
2879       */
2880      asl_locator.Panel.prototype.toggleFeatureFilter_ = function(feature) {
2881  
2882        var featureFilter = this.get('featureFilter');
2883        featureFilter.toggle(feature);
2884        
2885        this.set('featureFilter', featureFilter);
2886      };
2887  
2888      /**
2889       * Global Geocoder instance, for convenience.
2890       * @type {google.maps.Geocoder}
2891       * @private
2892       */
2893      asl_locator.geocoder_ = new google.maps.Geocoder;
2894  
2895      /**
2896       * Triggers an update for the store list in the Panel. Will wait for stores
2897       * to load asynchronously from the data source.
2898       * @private
2899       */
2900      asl_locator.Panel.prototype.listenForStoresUpdate_ = function() {
2901  
2902        var that = this;
2903        var view = (this.get('view'));
2904        if (this.storesChangedListener_) {
2905          google.maps.event.removeListener(this.storesChangedListener_);
2906        }
2907  
2908  
2909        ////console.log('listenForStoresUpdate_');
2910        /*
2911        this.storesChangedListener_ = google.maps.event.addListenerOnce(view,
2912          'stores_changed',
2913          function() {
2914            that.set('stores', view.get('stores'));
2915          });
2916        */
2917      };
2918  
2919      /**
2920       * Search and pan to the specified address.
2921       * @param {string} searchText the address to pan to.
2922       */
2923      asl_locator.Panel.prototype.searchPosition = function(searchText) {
2924  
2925        var that = this;
2926        var request = {
2927          address: searchText,
2928          bounds: this.get('view').getMap().getBounds()
2929        };
2930        asl_locator.geocoder_.geocode(request, function(result, status) {
2931          if (status != google.maps.GeocoderStatus.OK) {
2932            //TODO(cbro): proper error handling
2933            return;
2934          }
2935          google.maps.event.trigger(that, 'geocode', result[0]);
2936        });
2937      };
2938  
2939      /**
2940       * Sets the associated View.
2941       * @param {asl_locator.View} view the view to set.
2942       */
2943      asl_locator.Panel.prototype.setView = function(view) {
2944  
2945        this.set('view', view);
2946      };
2947  
2948      /**
2949       * view_changed handler.
2950       * Sets up additional bindings between the info panel and the map view.
2951       */
2952      asl_locator.Panel.prototype.view_changed = function() {
2953  
2954  
2955        ////console.log('VIEW CHANGED...........###########');
2956        var that = this;
2957        var sl = (this.get('view'));
2958        this.bindTo('selectedStore', sl);
2959  
2960        //window['test_panel'] = that;
2961  
2962        if (this.geolocationListener_) {
2963          google.maps.event.removeListener(this.geolocationListener_);
2964        }
2965  
2966        if (this.zoomListener_) {
2967          google.maps.event.removeListener(this.zoomListener_);
2968        }
2969  
2970        if (this.idleListener_) {
2971          google.maps.event.removeListener(this.idleListener_);
2972        }
2973  
2974        var center = sl.getMap().getCenter();
2975  
2976        var updateList = function() {
2977  
2978          //sl.clearMarkers();
2979          that.listenForStoresUpdate_();
2980        };
2981  
2982        //TODO(cbro): somehow get the geolocated position and populate the 'from' box.
2983  
2984        this.geolocationListener_ = google.maps.event.addListener(sl, 'load', updateList);
2985  
2986        this.zoomListener_ = google.maps.event.addListener(sl.getMap(), 'zoom_changed', updateList);
2987  
2988  
2989        this.idleListener_ = google.maps.event.addListener(sl.getMap(),
2990          'idle',
2991          function() {
2992  
2993            return that.idle_(sl.getMap());
2994          });
2995  
2996        updateList();
2997        
2998        this.bindTo('featureFilter', sl);
2999  
3000        if (this.autoComplete_) {
3001          this.autoComplete_.bindTo('bounds', sl.getMap());
3002        }
3003      };
3004  
3005  
3006      /**
3007       * [geoCoder Geocoder method]
3008       * @param  {[type]} _input    [description]
3009       * @param  {[type]} _callback [description]
3010       * @return {[type]}           [description]
3011       */
3012      asl_locator.Panel.prototype.geoCoder = function(_input, _callback) {
3013  
3014        var that  = this;
3015        var view  = that.get('view');
3016  
3017        var geocoder  = new google.maps.Geocoder(),
3018            _callback = _callback || function(results, status) {
3019  
3020            if (status == 'OK') {
3021              
3022              //  Add the search text
3023              results.search_text = _input.value;
3024  
3025              //  Get the bbox
3026              view.bbox = (results[0].geometry && results[0].geometry.viewport)? results[0].geometry.viewport: null;
3027              
3028              //  bind the hook, place api search
3029              asl_locator.hook_event({type: 'before_search', data: results});
3030  
3031              view.measure_distance(results[0].geometry.location, true, null, results);
3032  
3033              //  bind the hook, geocoder
3034              asl_locator.hook_event({type: 'search', data: results});
3035  
3036              //trigger Click of scan button
3037              if (asl_configuration.load_all == '2') {
3038                $('.asl-reload-map').trigger('click');
3039              }
3040  
3041              //  Show the close button
3042              $(_input).next().removeClass('hide');
3043  
3044            } else {
3045              console.log('Geocode was not successful for the following reason: ' + status);
3046            }
3047          };
3048  
3049  
3050  
3051        /**
3052         * [do_geocoding Do a Geocoding Request]
3053         * @param  {[type]} _addr_value [description]
3054         * @return {[type]}             [description]
3055         */
3056        function do_geocoding(addr_value) {
3057  
3058          if (addr_value){
3059  
3060            //birmingham
3061            var search_param = { 'address': addr_value };
3062  
3063            //  Restrict the search
3064            if (asl_configuration.country_restrict) {
3065            
3066              var country_restricted = asl_configuration.country_restrict.toLowerCase();
3067  
3068              country_restricted = country_restricted.split(',');
3069  
3070              search_param['componentRestrictions'] = {
3071                country: country_restricted[0]
3072              };
3073            }
3074  
3075            geocoder.geocode(search_param, _callback);
3076          }
3077        };
3078  
3079        // Clear to Write
3080        $(_input).bind('click', function(e) {
3081  
3082          //  Select existing text on the click
3083          _input.select();
3084        });
3085  
3086        //Enter Key
3087        $(_input).bind('keyup', function(e) {
3088  
3089          if (e.keyCode == 13) {
3090  
3091            var addr_value = $.trim(this.value);
3092  
3093            do_geocoding(addr_value);
3094          }
3095        });
3096  
3097        //  Pre-address, through Search Widget
3098        if(_input && asl_configuration['default-addr']) {
3099  
3100          window.setTimeout(function(){
3101  
3102          // req_coords
3103          if (asl_configuration.req_coords) {
3104  
3105            do_geocoding(asl_configuration["default-addr"]);
3106          }
3107          else {
3108  
3109            //  Geo-coder callback, trigger through search widget coordinates
3110            that.get('view').measure_distance(new google.maps.LatLng(asl_configuration.default_lat, asl_configuration.default_lng), true, null, null);
3111  
3112            //trigger Click of Scan button
3113            if (asl_configuration.load_all == '2') {
3114              $('.asl-reload-map').trigger('click');
3115            }
3116          }
3117  
3118          //  Show the close button
3119          $(_input).next().removeClass('hide');
3120  
3121          }, 800);
3122        }
3123  
3124  
3125        //Make it Search Button
3126        $('.asl-cont .icon-search').bind('click', function(e) {
3127  
3128          var addr_value = $.trim(_input.value);
3129  
3130          if (addr_value)
3131            geocoder.geocode({ 'address': addr_value }, _callback);
3132        });
3133      };
3134  
3135      /**
3136       * Adds autocomplete to the input box.
3137       * @private
3138       */
3139      asl_locator.Panel.prototype.initAutocomplete_ = function(input) {
3140  
3141        var that = this;
3142  
3143        if (!asl_configuration.geocoding_only) {
3144  
3145          var options = {};
3146  
3147          if (asl_configuration.google_search_type) {
3148  
3149            options['types'] = (asl_configuration.google_search_type == 'cities' || asl_configuration.google_search_type == 'regions') ? ['(' + asl_configuration.google_search_type + ')'] : [asl_configuration.google_search_type];
3150          }
3151  
3152          this.autoComplete_ = new google.maps.places.Autocomplete(input, options);
3153  
3154          if (asl_configuration.country_restrict) {
3155              
3156            var country_restricted = asl_configuration.country_restrict.toLowerCase();
3157  
3158            country_restricted = country_restricted.split(',');
3159  
3160            this.autoComplete_.setComponentRestrictions({country: country_restricted });
3161          }
3162  
3163            
3164          //  Limit the search scope
3165          var fields = ['geometry'];
3166  
3167          if(asl_configuration.filter_address)
3168            fields.push('address_components');
3169  
3170          this.autoComplete_.setFields(fields);
3171  
3172  
3173          if (this.get('view')) {
3174            this.autoComplete_.bindTo('bounds', this.get('view').getMap());
3175          }
3176  
3177  
3178          google.maps.event.addListener(this.autoComplete_, 'place_changed',
3179          function() {
3180            
3181            var p = this.getPlace();
3182  
3183            if (asl_configuration.analytics) {
3184              
3185              //  Add the address when API doesn't provide it
3186              if(!p.formatted_address) {
3187                p.formatted_address = input.value;
3188              }
3189  
3190  
3191              //Send a request and save the log
3192              asl_locator.save_analytics(p);
3193            }
3194           
3195            // lucia
3196            if (p.geometry) {
3197  
3198              var view = that.get('view');
3199              
3200              //  Get the bbox for place api
3201              view.bbox = (p.geometry && p.geometry.viewport)? p.geometry.viewport: null;
3202  
3203              //  bind the hook, place api search
3204              asl_locator.hook_event({type: 'before_search', data:p});
3205  
3206              //  measure the distance
3207              view.measure_distance(p.geometry.location, true, null, p);
3208  
3209              //  bind the hook, place api search
3210              asl_locator.hook_event({type: 'search', data:p});
3211  
3212              //  show the cross button
3213              $(input).next().removeClass('hide');
3214  
3215              //trigger Click of Scan button
3216              if (asl_configuration.load_all == '2') {
3217  
3218                $('.asl-reload-map').trigger('click');
3219              }
3220            }
3221  
3222            //trigger geocode
3223            //google.maps.event.trigger(that, 'geocode', p);
3224          });
3225  
3226        }
3227  
3228        //  The search control
3229        that.search_control = input;
3230        
3231        //  Entery Key
3232        that.geoCoder(input);
3233      };
3234  
3235      /**
3236       * Called on the view's map idle event. Refreshes the store list if the
3237       * user has navigated far away enough.
3238       * @param {google.maps.Map} map the current view's map.
3239       * @private
3240       */
3241      asl_locator.Panel.prototype.idle_ = function(map) {
3242  
3243        if (!this.center_) {
3244          this.center_ = map.getCenter();
3245        } else if (!map.getBounds().contains(this.center_)) {
3246          this.center_ = map.getCenter();
3247          this.listenForStoresUpdate_();
3248        }
3249      };
3250  
3251  
3252  
3253      /**
3254       * [hideGeoModal Hide the Geo Modal]
3255       * @return {[type]} [description]
3256       */
3257      asl_locator.Panel.prototype.hideGeoModal = function() {
3258  
3259        var $agile_modal = $('.asl-cont #asl-geolocation-agile-modal');
3260        
3261        $agile_modal.removeClass('in');
3262        
3263        window.setTimeout(function() {
3264          
3265          $agile_modal.css('display', 'none');
3266  
3267        }, 300);
3268  
3269        //  Visible
3270        this.geo_modal = false;
3271      };
3272  
3273  
3274      /**
3275       * [hideDescModal Hide the description Modal]
3276       * @return {[type]} [description]
3277       */
3278      asl_locator.Panel.prototype.hideDescModal = function() {
3279  
3280        var $desc_modal =  $('.asl-cont #asl-desc-agile-modal');
3281  
3282        $desc_modal.removeClass('in');
3283        
3284        window.setTimeout(function() {
3285          $desc_modal.css('display', 'none');
3286        }, 300);
3287  
3288        //  visibility
3289        this.isDescModal = false;
3290      }
3291  
3292      /**
3293       * [descriptionModal Show a description Modal]
3294       * @param  {[type]} _store [description]
3295       * @return {[type]}        [description]
3296       */
3297      asl_locator.Panel.prototype.descriptionModal = function(_store) {
3298  
3299        var $modal =  $('.asl-cont #asl-desc-agile-modal');
3300  
3301        $modal.find('.sl-title').html(_store.props_.title);
3302  
3303        var desc_text = '<h5>'+asl_configuration.words.desc_title+ '</h5><p>' +_store.props_.description + '</p>';
3304  
3305        if(_store.props_.description_2) {
3306            
3307            desc_text += '<br><h5 class="sl-addit-desc">'+asl_configuration.words.add_desc_title+'</h5><p>' + _store.props_.description_2 + '</p>';
3308        }
3309        
3310        $modal.find('.sl-desc').html(desc_text);
3311  
3312        $modal.css('display', 'block');
3313  
3314        $modal.addClass('in');
3315  
3316  
3317        if (asl_configuration.is_mob) {
3318  
3319          $('html, body')
3320            .stop()
3321            .animate({
3322              'scrollTop': $modal.offset().top
3323            }, 900, 'swing');
3324        }
3325  
3326        //  Modal Visibility
3327        this.isDescModal = true;
3328      };
3329  
3330  
3331      /**
3332       * Handler for stores_changed. Updates the list of stores.
3333       * @this asl_locator.Panel
3334       */
3335      asl_locator.Panel.prototype.stores_changed = function(_store) {
3336  
3337        var that = this;
3338  
3339        //  Hide the desc Modal if Visible
3340        if(that.isDescModal) {
3341          that.hideDescModal();
3342        }
3343  
3344        if (!this.get('stores')) {
3345          return;
3346        }
3347  
3348        var view = this.get('view');
3349  
3350        if (view.showing_direction) return;
3351  
3352        ///////////////////////////
3353        //Once for the Accordion //
3354        ///////////////////////////
3355        if (asl_configuration.accordion) {
3356          if (view.is_updated) return;
3357        }
3358  
3359        view.is_updated = true;
3360  
3361  
3362        var bounds = view && view.getMap().getBounds();
3363        //var stores = this.get('stores');
3364        var stores = view.get('stores');
3365        var selectedStore = this.get('selectedStore');
3366  
3367  
3368        //var stores = this.get('stores');
3369        //var stores = asl_panel.get('view').get('stores');
3370  
3371        //  Highlight the Clicked Element, Make it first
3372        if (asl_configuration.highlight_first && _store) {
3373  
3374          var high_arr = [],
3375            low_arr = [];
3376          for (var s = 0; s < stores.length; s++) {
3377  
3378            if (stores[s].id_ == _store.id_)
3379              high_arr.push(stores[s]);
3380            else
3381              low_arr.push(stores[s]);
3382          }
3383  
3384          stores = high_arr.concat(low_arr);
3385        }
3386  
3387  
3388        if (!asl_configuration.accordion)
3389          this.storeList_.empty();
3390  
3391        if (!stores.length) {
3392  
3393          $('.asl-cont .Num_of_store .count-result').html('0');
3394          that.storeList_.html('<div class="asl-overlay-on-item" id="asl-no-item-found"><div class="white"></div><h1 class="h1">' + ((view.search_performed)? asl_configuration.no_item_text: asl_configuration.words.perform_search) + '</h1></div>');
3395  
3396          //  When no stores are found
3397          asl_locator.hook_event({type: 'no_stores', data: {element: that.storeList_}});
3398        } 
3399        else {
3400  
3401          $('.asl-cont .Num_of_store .count-result').html(stores.length);
3402        }
3403  
3404        /**
3405         * [clickHandler description]
3406         * @param  {[type]} e [description]
3407         * @return {[type]}   [description]
3408         */
3409        var clickHandler = function(e) {
3410  
3411          var $e = $(e.target);
3412  
3413          if ($e.hasClass('s-direction')) {
3414            e.preventDefault();
3415            return;
3416          }
3417  
3418          if ($e.hasClass('sl-link')) {
3419            e.preventDefault();
3420  
3421            that.descriptionModal(this['store']);
3422            return;
3423          }
3424  
3425          if ($e.hasClass('sl-pickup')) {
3426            
3427            e.preventDefault();
3428  
3429            asl_locator.hook_event({type: ((asl_configuration.ship_from)? 'ship_from': 'pickup'), data: this['store']});
3430            return;
3431          }
3432  
3433          //  Hide the desc Modal if Visible
3434          if(that.isDescModal) {
3435            that.hideDescModal();
3436          }
3437          
3438          //  Hide the geoModal
3439          if(that.geo_modal) {
3440            that.hideGeoModal();        
3441          }
3442  
3443          //  Click is disabled
3444          if (e.target.className == 'A' || asl_configuration.disable_list_click) {
3445  
3446            //  bind the hook, store highlight
3447            asl_locator.hook_event({type: 'highlight', data: this['store']});
3448            return;
3449          }
3450  
3451          view.noRefreshList = true;
3452          view.highlight(this['store'], true);
3453  
3454          //  Scroll to the Map if Mobile
3455          if (asl_configuration.is_mob) {
3456  
3457            $('html, body')
3458              .stop()
3459              .animate({
3460                'scrollTop': $(view.getMap().getDiv()).offset().top
3461              }, 900, 'swing');
3462  
3463          }
3464        };
3465        //  End of the Event
3466  
3467  
3468  
3469  
3470        // TODO(cbro): change 10 to a setting/option
3471        //add the stores and the click event    
3472        for (var i = 0, ii = stores.length; i < ii; i++) {
3473  
3474          var storeLi = stores[i].getInfoPanelItem();
3475          storeLi['store'] = stores[i];
3476          var store_inst = stores[i];
3477  
3478  
3479          if (selectedStore && stores[i].id_ == selectedStore.id_) {
3480            $(storeLi).addClass('highlighted');
3481          }
3482  
3483          /*
3484          //  Deprecated
3485          if (!storeLi.clickHandler_) {
3486            storeLi.clickHandler_ = google.maps.event.addDomListener(storeLi, asl_configuration.list_event, clickHandler);
3487          }
3488          */
3489         
3490          storeLi.addEventListener(asl_configuration.list_event, clickHandler);
3491  
3492          if(asl_configuration.do_bounce) {
3493  
3494            storeLi.addEventListener('mouseenter', view.doBounce.bind(view, stores[i], true));
3495            storeLi.addEventListener('mouseleave', view.doBounce.bind(view, stores[i], false));
3496          }
3497          //The direction link on panel
3498          //direction Click Handler
3499          $(storeLi).find('.s-direction').click(function(e) {
3500            var store = $(this).data('_store');
3501            that.directionsTo_ = store;
3502            that.showDirections(store);
3503          })
3504          .data('_store', stores[i]);
3505  
3506          that.storeList_.append(storeLi);
3507        }
3508  
3509  
3510        /// Open the Category Accordion Markers
3511        if(asl_configuration.category_accordion) {
3512  
3513          //  Bind Event for the Category Li-State Click
3514          $('.asl-cont li.item-state').bind('click', function(e) {
3515  
3516            var $li_target = $(e.target).parent();
3517  
3518            //  is it accordion?
3519            if($li_target.hasClass('item-state')) {
3520              
3521              var li_cat_id = $(this).data('id'),
3522                  li_state  = $(this).children(0).hasClass('colisiond');
3523  
3524  
3525              //  Close the other listings
3526              asl_view._panel.storeList_.find('.show').colision('hide');
3527  
3528              //  Remove existing ones
3529              asl_view.categoryClearAll();
3530  
3531              if(li_cat_id) {
3532                
3533                view.categoryAccFilter(String(li_cat_id), li_state);
3534              }
3535            }
3536          });
3537  
3538          //  When it is shown, highlight the store
3539          /*
3540          that.storeList_.on('shown.bs.colision', function () {
3541  
3542          });
3543          */
3544        }
3545  
3546  
3547        //  Make sure the storeList_ has offset 0
3548        if(that.mainPanel.scrollTop() > 0) {
3549  
3550          that.mainPanel
3551              .stop()
3552              .animate({
3553                'scrollTop': 0
3554              }, 100, 'swing');
3555        }
3556      };
3557  
3558      /**
3559       * Handler for selectedStore_changed. Highlights the selected store in the
3560       * store list.
3561       * @this asl_locator.Panel
3562       */
3563      asl_locator.Panel.prototype.selectedStore_changed = function() {
3564  
3565        var that  = this;
3566        var store = this.get('selectedStore');
3567        var view  = that.get('view');
3568  
3569        var $highlighted = $('.highlighted', this.storeList_),
3570            skip_slideUp = false;
3571  
3572        //  is a marker click?
3573        var is_marker_click = view.marker_clicked;
3574  
3575        //  Reset it to false
3576        view.marker_clicked = false;
3577  
3578  
3579  
3580        //  Remove the Highlighted Class
3581        $highlighted.removeClass('highlighted');
3582  
3583  
3584        //  Remove the active_marker active state
3585        if (!asl_configuration.adv_mkr && view.active_marker && view.active_marker.m) {
3586  
3587          view.active_marker.m.setIcon(view.active_marker.picon);
3588          view.active_marker.m = null;
3589        }
3590  
3591        if (!store) {
3592          return;
3593        }
3594  
3595  
3596        // majin icon change here
3597        var store_marker = store.getMarker();
3598  
3599        // Backup Store marker
3600        if (view.active_marker) {
3601  
3602          view.active_marker.picon = store_marker.getIcon();
3603          view.active_marker.m = store_marker;
3604          store_marker.setIcon(view.active_marker.icon);
3605        }
3606  
3607  
3608        this.directionsTo_ = store;
3609        var store_li = this.storeList_.find('li.sl-item[data-id="' + store.id_ + '"]');
3610  
3611        //  Must be single node
3612        if(store_li.length > 1) {
3613          store_li = store_li.eq(0);
3614        }
3615  
3616        //  the selected store
3617        if (store_li) {
3618  
3619  
3620          store_li.addClass('highlighted');
3621        }
3622  
3623        if (this.settings_['directions']) {
3624          this.directionsPanel_.find('.directions-to')
3625            .val(store.getDetails().title);
3626        }
3627  
3628        var node = that.get('view').getInfoWindow().getContent();
3629        var directionsLink = $('<a/>')
3630          .text(asl_configuration.words.direction)
3631          .attr('href', 'javascript:void(0)')
3632          .addClass('action')
3633          .addClass('directions');
3634  
3635        // TODO(cbro): Make these two permanent fixtures in InfoWindow.
3636        // Move out of Panel.
3637        var zoomLink = $('<a/>')
3638          .text(asl_configuration.words.zoom)
3639          .attr('href', 'javascript:void(0)')
3640          .addClass('action')
3641          .addClass('zoomhere');
3642  
3643  
3644        var link = store.props_['link'];
3645  
3646  
3647        directionsLink.click(function() {
3648  
3649          that.showDirections();
3650          return false;
3651        });
3652  
3653        zoomLink.click(function() {
3654  
3655          that.get('view').getMap().setOptions({
3656            center: store.getLocation(),
3657            zoom: (asl_map.getZoom() + 1)
3658          });
3659        });
3660  
3661  
3662        $(node).find('.asl-buttons')
3663          .append(directionsLink)
3664          .append(zoomLink);
3665  
3666        //  Add Pickup Button
3667        if(asl_configuration.pickup || asl_configuration.ship_from) {
3668  
3669          var $pickup_btn = $('<a/>')
3670          .text(((asl_configuration.ship_from)? asl_configuration.words.ship_from: asl_configuration.words.pickup))
3671          .addClass('action')
3672          .addClass('sl-pickup');
3673  
3674          $(node).find('.asl-buttons').append($pickup_btn);
3675  
3676          $pickup_btn.click(function(e) {
3677            asl_locator.hook_event({type: ((asl_configuration.ship_from)? 'ship_from': 'pickup'), data: store});
3678          });
3679        }
3680  
3681  
3682        var streetViewLink = $('<a/>').text(asl_configuration.words.detail).addClass('action').addClass('a-website');
3683        
3684        //  If have an event hook for it
3685        if(window['asl_website_click']) {
3686          streetViewLink.click(function(){
3687            asl_website_click(store.props_, link);
3688          });
3689  
3690          $(node).find('.asl-buttons').append(streetViewLink);
3691        }
3692        //   If have a link for it
3693        else if (link) {
3694  
3695          $(node).find('.asl-buttons').append(streetViewLink);
3696  
3697          streetViewLink.attr('href', link);
3698  
3699          streetViewLink.attr('target', asl_configuration.target_blank);
3700        }
3701  
3702      };
3703  
3704      /**
3705       * Hides the directions panel.
3706       */
3707      asl_locator.Panel.prototype.hideDirections = function() {
3708  
3709        this.directionsVisible_ = false;
3710        this.directionsPanel_.removeClass('in');
3711        this.el_.find('.directions-cont').addClass('hide');
3712        //this.featureFilter_.fadeIn();
3713        this.storeList_.fadeIn();
3714        this.directionsRenderer_.setMap(null);
3715  
3716        var view = this.get('view');
3717        view.showing_direction = false;
3718      };
3719  
3720      /**
3721       * Shows directions to the selected store.
3722       */
3723      asl_locator.Panel.prototype.showDirections = function(_store) {
3724  
3725        var store = _store || this.get('selectedStore');
3726        if (!store) return;
3727  
3728        //  bind the hook, store highlight
3729        asl_locator.hook_event({type: 'direction', data: store.props_});
3730  
3731        //_isMobileDevice()
3732        if ((asl_configuration.is_mob && asl_configuration.direction_redirect == '1') || asl_configuration.direction_redirect == '2') {
3733  
3734          var destin = (asl_configuration.title_in_dir)? [store.props_.title]:[],
3735              source = '';
3736  
3737          destin.push(store.props_.address);
3738          destin = destin.join(', ').replace(/<\/?[^>]+(>|$)/g," ");
3739  
3740          //  Fix the URL for the Direction
3741          destin = encodeURIComponent( destin );
3742  
3743          //  Direction with the Coordinates
3744          if(asl_configuration.coords_direction) {
3745            destin = store.location_.lat() + ',' + store.location_.lng();
3746          }
3747  
3748          //https://developers.google.com/maps/documentation/urls/ios-urlscheme
3749          var _path = "https://www.google.com/maps/dir/?api=1&destination=" + destin;
3750          //var path   = "https://www.google.com/maps/dir/Current+Location/"+destin+"?hl=en";
3751          window.open(_path);
3752          return;
3753        }
3754  
3755        this.directionsPanel_.find('.frm-place').val((this.dest_coords) ? asl_configuration.words.current_location : '');
3756  
3757        
3758        this.directionsPanel_.find('.directions-to').val(store.getDetails().title);
3759        this.directionsPanel_.addClass('in');
3760        this.renderDirections_();
3761  
3762        //  When the direction box is press in the mobile, show the map
3763        if(asl_configuration.is_mob) {
3764  
3765          //  Scroll to the map
3766          $('html, body')
3767              .stop()
3768              .animate({
3769                'scrollTop': $(this.get('view').getMap().getDiv()).offset().top
3770              }, 900, 'swing');
3771        }
3772  
3773        this.directionsVisible_ = true;
3774      };
3775  
3776      /**
3777       * Renders directions from the location in the input box, to the store that is
3778       * pre-filled in the 'to' box.
3779       * @private
3780       */
3781      asl_locator.Panel.prototype.renderDirections_ = function() {
3782  
3783        var that = this;
3784  
3785        if (!this.directionsFrom_ || !this.directionsTo_) {
3786          return;
3787        }
3788  
3789        this.el_.find('#map-loading').show();
3790  
3791        this.el_.find('.directions-cont').removeClass('hide');
3792        this.storeList_.fadeOut();
3793        that.directionsPanel_.removeClass('in');
3794        var rendered = this.el_.find('.rendered-directions').empty();
3795  
3796  
3797        //  Travel Mode
3798        var travel_mode = google.maps['DirectionsTravelMode'].DRIVING;
3799  
3800        //  Override it
3801        if(asl_configuration.direction_mode) {
3802  
3803          var direction_mode = asl_configuration.direction_mode.toUpperCase();
3804  
3805          //  Override when we hav a value
3806          if(google.maps['DirectionsTravelMode'][direction_mode])
3807            travel_mode = direction_mode;
3808        }
3809  
3810  
3811  
3812        this.directionsService_.route({
3813            origin: this.directionsFrom_,
3814            destination: this.directionsTo_.getLocation(),
3815            travelMode: travel_mode,
3816            unitSystem: that.distance_type
3817            //TODO(cbro): region biasing, waypoints, travelmode
3818          },
3819          function(result, status) {
3820            that.el_.find('#map-loading').hide();
3821            if (status != google.maps.DirectionsStatus.OK) {
3822              // TODO(cbro): better error handling
3823              return;
3824            }
3825  
3826            $('.asl-cont .count-row').addClass('hide');
3827            $('.asl-cont #filter-options').addClass('hide');
3828  
3829            var view = that.get('view');
3830            view.showing_direction = true;
3831  
3832            //  Hide the infobox
3833            if(view.infoWindow_.getVisible()) {
3834              view.infoWindow_.close();
3835            }
3836  
3837            var renderer = that.directionsRenderer_;
3838            renderer.setPanel(rendered[0]);
3839            renderer.setMap(that.get('view').getMap());
3840            renderer.setDirections(result);
3841          });
3842  
3843        //make it null again
3844        this.directionsFrom_ = null;
3845      };
3846  
3847      /**
3848       * featureFilter_changed event handler.
3849       */
3850      asl_locator.Panel.prototype.featureFilter_changed = function() {
3851  
3852        this.listenForStoresUpdate_();
3853      };
3854  
3855  
3856  
3857      /**
3858       * @example see asl_locator.Panel
3859       * @interface
3860       */
3861      asl_locator.PanelOptions = function() {};
3862  
3863      /**
3864       * Whether to show the location search box. Default is true.
3865       * @type boolean
3866       */
3867      asl_locator.prototype.locationSearch;
3868  
3869      /**
3870       * The label to show above the location search box. Default is "Where are you
3871       * now?".
3872       * @type string
3873       */
3874      asl_locator.PanelOptions.prototype.locationSearchLabel;
3875  
3876      /**
3877       * Whether to show the feature filter picker. Default is true.
3878       * @type boolean
3879       */
3880      asl_locator.PanelOptions.prototype.featureFilter;
3881  
3882      /**
3883       * Whether to provide directions. Deafult is true.
3884       * @type boolean
3885       */
3886      asl_locator.PanelOptions.prototype.directions;
3887  
3888      /**
3889       * The store locator model to bind to.
3890       * @type asl_locator.View
3891       */
3892      asl_locator.PanelOptions.prototype.view;
3893    })(jQuery);
3894  
3895  
3896    /*Site Script*/
3897    (function($) {
3898  
3899      //  Accent characters normalization
3900      var charMap = {
3901        'a': /[àáâ]/gi,
3902        'c': /[ç]/gi,
3903        'e': /[èéêë]/gi,
3904        'i': /[ï]/gi,
3905        'o': /[ôÓÖ]/gi,
3906        'oe': /[œ]/gi,
3907        'u': /[üÚ]/gi
3908      };
3909  
3910      var normalize = function (str) {
3911        $.each(charMap, function (normalized, regex) {
3912          str = str.replace(regex, normalized);
3913        });
3914        return str;
3915      };
3916  
3917      var queryTokenizer = function (q) {
3918        var normalized = normalize(q);
3919        return Bloodhound.tokenizers.whitespace(normalized);
3920      };
3921  
3922  
3923  
3924      //Main map instance
3925      var map = null;
3926  
3927      var asl_engine = {
3928        config: {},
3929        helper: {}
3930      };
3931      window['asl_engine'] = asl_engine;
3932  
3933  
3934  
3935      if (!window['asl_configuration']) return;
3936      asl_configuration.category_accordion = (asl_configuration.layout == '2')? true: false;
3937      asl_configuration.accordion = (asl_configuration.layout == '1' || asl_configuration.category_accordion) ? true : false;
3938      asl_configuration.analytics = (asl_configuration.analytics == '1') ? true : false;
3939      asl_configuration.sort_by_bound = (asl_configuration.sort_by_bound == '1') ? true : false;
3940      asl_configuration.scroll_wheel = (asl_configuration.scroll_wheel == '1') ? true : false;
3941      asl_configuration.distance_slider = (asl_configuration.distance_slider == '1') ? true : false;
3942      asl_configuration.show_categories = (asl_configuration.show_categories == '0') ? false : true;
3943      asl_configuration.time_switch = (asl_configuration.time_switch == '0') ? false : true;
3944      asl_configuration.category_marker = (asl_configuration.category_marker == '0') ? false : true;
3945      asl_configuration.advance_filter = (asl_configuration.advance_filter == '0') ? false : true;
3946      asl_configuration.time_24 = (asl_configuration.time_format == '1') ? true : false;
3947      //asl_configuration.week_hours = (asl_configuration.week_hours == '1') ? true : false;
3948      asl_configuration.user_center = (asl_configuration.user_center == '1') ? true : false;
3949      asl_configuration.distance_unit  = (asl_configuration.distance_unit == 'KM') ? asl_configuration.distance_unit : 'Miles';
3950      asl_configuration.filter_address = (asl_configuration.filter_address == '1') ? true : false;
3951      asl_configuration.regex = (asl_configuration.no_regex) ? /#|\./ig : /[^a-z0-9\s]/gi;
3952      asl_configuration.info_x_offset = (asl_configuration.info_x_offset && !isNaN(asl_configuration.info_x_offset)) ? parseInt(asl_configuration.info_x_offset) : 0;
3953      asl_configuration.info_y_offset = (asl_configuration.info_y_offset && !isNaN(asl_configuration.info_y_offset)) ? parseInt(asl_configuration.info_y_offset) : 0;
3954      asl_configuration.enter_key     = true;
3955      asl_configuration.category_sort = true;
3956      asl_configuration.stores_limit  = (asl_configuration.stores_limit && !isNaN(asl_configuration.stores_limit)) ? parseInt(asl_configuration.stores_limit) : null;
3957      asl_configuration.radius_circle = (asl_configuration.radius_circle == '1') ? true : false;
3958      asl_configuration.marker_height = (asl_configuration.marker_height)? asl_configuration.marker_height: '43';
3959      asl_configuration.and_filter    = (asl_configuration.and_filter == '1') ? true : false;
3960      asl_configuration.category_bound= (asl_configuration.category_bound == '1') ? true : false;
3961      asl_configuration.fit_bound     = (asl_configuration.fit_bound == '1') ? true : false;
3962      asl_configuration.sort_random   = (asl_configuration.sort_random == '1') ? true : false;
3963      asl_configuration.filter_ddl    = null;
3964      asl_configuration.boundary_box  = (asl_configuration.distance_control == '2')? true: false;
3965      asl_configuration.store_radius  = (asl_configuration.store_radius == '1')? true: false;
3966      asl_configuration.marker_title  = (asl_configuration.marker_title == '0')? false: true;
3967      asl_configuration.hide_logo     = (asl_configuration.hide_logo == '1')? true: false;
3968      asl_configuration.hide_hours    = (asl_configuration.hide_hours == '1')? true: false;
3969      asl_configuration.do_bounce     = (asl_configuration.do_bounce === '0')? false: true;
3970      asl_configuration.list_event    = (asl_configuration.mouseover_list === '1')? 'mouseover': 'click';
3971      asl_configuration.pickup        = (asl_configuration.pickup === '1')? true: false;
3972      asl_configuration.ship_from     = (asl_configuration.ship_from === '1')? true: false;
3973      asl_configuration.address_ddl   = false;
3974      asl_configuration.tabs_layout   = (asl_configuration.tabs_layout === '1')? true: false;
3975      asl_configuration.ddl_search    = asl_configuration.ddl_search? true: false;
3976      asl_configuration.target_blank  = (asl_configuration.target_blank == '1')? '_blank':'_self';
3977      asl_configuration.cluster       = (asl_configuration.cluster == '0')? false: true;
3978      asl_configuration.display_list  = true;
3979      asl_configuration.adv_mkr       = (asl_configuration.advanced_marker)? true: false;
3980  
3981      // Disable the Circle when distance slider is off
3982      if(!asl_configuration.distance_slider) {
3983        asl_configuration.radius_circle = false;
3984      }
3985  
3986      //  Show stores On Category Select 
3987      asl_configuration.on_select     = true;
3988      if(asl_configuration.first_load == '6') {
3989        asl_configuration.first_load = '1';
3990        asl_configuration.on_select  = false;
3991      }
3992  
3993  
3994      //  Default location Address, disable Prompt Location
3995      if(asl_configuration['default-addr'] || asl_configuration['select_category']) {
3996        asl_configuration.prompt_location = '0';
3997      }
3998  
3999      //  Avoid multiple search names
4000      if(asl_configuration.search_type == '1' && asl_configuration.template != '2' && asl_configuration.search_2) {
4001        asl_configuration.search_type = '0';
4002      }
4003  
4004  
4005      if(asl_configuration.sort_random && asl_configuration.user_center) {
4006        asl_configuration.user_center = false;
4007        console.log('Warning! Sort Random disable the default location marker');
4008      }
4009  
4010      if(asl_configuration.search_type == '1' || asl_configuration.search_type == '2') {
4011        asl_configuration.user_center = false;
4012      }
4013  
4014      if(asl_configuration.first_load != '1') {
4015        asl_configuration.user_center = false;      
4016      }
4017  
4018  
4019  
4020      //  Add the offset
4021      if(!asl_configuration.info_y_offset) {
4022  
4023        //  Default
4024        asl_configuration.info_y_offset = -100;
4025  
4026        if(asl_configuration.template == '2')
4027          asl_configuration.info_y_offset = -120;
4028  
4029        if(asl_configuration.infobox_layout == '1') {
4030          asl_configuration.info_y_offset = -150;
4031        }
4032      }
4033  
4034  
4035      asl_configuration.fixed_radius = (asl_configuration.fixed_radius && !isNaN(asl_configuration.fixed_radius)) ? parseInt(asl_configuration.fixed_radius) : null;
4036  
4037      asl_configuration.is_mob = _isMobileDevice();
4038  
4039      //  When the device is a mobile
4040      if(asl_configuration.is_mob) {
4041        
4042        //   Zoom for the mobile device
4043        if(asl_configuration.mobile_zoom)
4044          asl_configuration.zoom = parseInt(asl_configuration.mobile_zoom);
4045  
4046        //   Search Zoom for the mobile device
4047        if(asl_configuration.mobile_search_zoom)
4048          asl_configuration.search_zoom = parseInt(asl_configuration.mobile_search_zoom);
4049  
4050        //   Search Zoom for the mobile device
4051        if(asl_configuration.mobile_click_zoom)
4052          asl_configuration.zoom_li = parseInt(asl_configuration.mobile_click_zoom);
4053  
4054        // For mobile devices, don't let it be mouseover
4055        asl_configuration.list_event = 'click';
4056        asl_configuration.mouseover  = false;
4057      }
4058  
4059      //  Add a max bound zoom
4060      asl_configuration.max_bound_zoom = (asl_configuration.max_bound_zoom)? parseInt(asl_configuration.max_bound_zoom): asl_configuration.search_zoom;
4061      
4062  
4063      //  Geocoding Only
4064      if (asl_configuration.search_type == '3') {
4065  
4066        asl_configuration.search_type = '0';
4067        asl_configuration.geocoding_only = true;
4068      }
4069  
4070      //Fixed
4071      if (asl_configuration.full_height) {
4072        //$('#asl-storelocator .asl-map-canv').css('height', '100vh');
4073        //$('#asl-storelocator .asl-map-canv').css('height', (locator_height) + 'px');
4074      }
4075  
4076      //Only for load all
4077      /*if(asl_configuration.load_all != "1")
4078        asl_configuration.search_type = '0';*/
4079  
4080      //Set Mobile Load on Bound
4081      if (asl_configuration.is_mob && asl_configuration.mobile_load_bound) {
4082  
4083        asl_configuration.load_all = '2';
4084        asl_configuration.search_type = '0';
4085      }
4086  
4087      //  Radius only Works with Google Search
4088      if (asl_configuration.search_type != '0' || asl_configuration.distance_control != '1') {
4089  
4090        console.log('Radius Circle Works with Google Search Only and Distance Control.');
4091        asl_configuration.radius_circle = false;
4092      }
4093  
4094  
4095      //  Enable the Search by Description
4096      if(asl_configuration.additional_search) {
4097  
4098        asl_configuration.search_type = '2';
4099      }
4100  
4101  
4102  
4103  
4104      //  Set Mobile Stores Limit
4105      if (asl_configuration.is_mob && asl_configuration.mobile_stores_limit) {
4106  
4107        asl_configuration.stores_limit = (asl_configuration.mobile_stores_limit && !isNaN(asl_configuration.mobile_stores_limit)) ? parseInt(asl_configuration.mobile_stores_limit) : null;
4108      }
4109  
4110      if (!asl_configuration.advance_filter)
4111        $('.asl-cont').addClass('no-asl-filters');
4112  
4113      
4114      asl_configuration.mobile_stores_limit = (asl_configuration.mobile_stores_limit) ? parseInt(asl_configuration.mobile_stores_limit) : 100;
4115  
4116  
4117      // Disable Radius Circle, if Load all = 0
4118      if(asl_configuration.load_all != '1') {
4119  
4120        asl_configuration.cache = asl_configuration.radius_circle = false;
4121        console.log('Radius Circle Works with load all only');
4122      }
4123  
4124      //NO asl filters
4125      if (asl_configuration.advance_filter && $('#asl-open-close')[0])
4126        $('#asl-open-close')[0].checked = true;
4127  
4128      /*ALL HELPER METHODS*/
4129      var asl_lat = (asl_configuration.default_lat) ? parseFloat(asl_configuration.default_lat) : 39.9217698526,
4130        asl_lng = (asl_configuration.default_lng) ? parseFloat(asl_configuration.default_lng) : -75.5718432,
4131        categories = {},
4132        asl_date = new Date();
4133  
4134      asl_configuration.default_lat = asl_lat;
4135      asl_configuration.default_lng = asl_lng;
4136  
4137  
4138      //HARDCODE MODE
4139      /*
4140      asl_configuration.show_categories = true; 
4141      asl_configuration.advance_filter = true;  
4142      asl_configuration.additional_info = true;
4143      */
4144      /*
4145      asl_configuration.range_slider = true;
4146      asl_configuration.show_distance = true; 
4147      asl_configuration.direction = true; 
4148      asl_configuration.additional_info = true; 
4149      asl_configuration.distance_unit = true; 
4150      asl_configuration.cluster = true; 
4151      */
4152      asl_configuration.show_opened = false;
4153  
4154      $('#asl-dist-unit').html(asl_configuration.distance_unit);
4155  
4156  
4157      var COUNT_FORMATS =
4158      [
4159        { // 0 - 999
4160          letter: '',
4161          limit: 1e3
4162        },
4163        { // 1,000 - 999,999
4164          letter: 'K',
4165          limit: 1e6
4166        }
4167      ];
4168  
4169      /**
4170       * [html_entites Convert the codes into HTML]
4171       * @param  {[type]} _string [description]
4172       * @return {[type]}         [description]
4173       */
4174      asl_engine.helper.html_entites = function(_string) {
4175  
4176        var tempElement = document.createElement("div");
4177        tempElement.innerHTML = _string;
4178        return tempElement.innerText;
4179      };
4180  
4181      /**
4182       * [is_empty Check if it's empty]
4183       * @param  {[type]} _string [description]
4184       * @return {[type]}         [description]
4185       */
4186      asl_engine.helper.is_empty = function(obj) {
4187  
4188        // Check if the object is null or undefined
4189        if (obj === null || obj === undefined) {
4190          return true;
4191        }
4192  
4193        // Check if it's an object and has no own properties
4194        if (typeof obj !== 'object' || Array.isArray(obj)) {
4195          return false;
4196        }
4197  
4198        // Check if all properties are either null or undefined
4199        for (let key in obj) {
4200          if (obj[key] !== null && obj[key] !== undefined) {
4201            return false;
4202          }
4203        }
4204  
4205        return true;
4206      };
4207  
4208      /**
4209       * [format_count Format the count in K]
4210       * @param  {[type]} value [description]
4211       * @return {[type]}       [description]
4212       */
4213      asl_engine.helper.format_count = function(value) {
4214  
4215        var limit  = 1e6;
4216  
4217         if(value < limit && value > 1000) {
4218          value = (1000 * value / limit);
4219          value = Math.round(value * 10) / 10; // keep one decimal number, only if needed
4220          return (value + 'K');
4221        }
4222  
4223        return value.toFixed(2);
4224      };
4225  
4226  
4227      /**
4228       * [uniq Get the array of objects of uniq type]
4229       * @param  {[type]} _list [description]
4230       * @param  {[type]} _type [description]
4231       * @return {[type]}       [description]
4232       */
4233      asl_engine.helper.uniq = function(_list, _type, _normalize) {
4234  
4235        var unique    = [];
4236        var distinct  = [];
4237  
4238        for(var i = 0; i < _list.length; i++) {
4239  
4240          if( !unique[_list[i][_type]]) {
4241  
4242            distinct.push((_normalize)? { type: _type, title: _list[i][_type] }: { type: _type, title: _list[i][_type], value: normalize(_list[i][_type]) });
4243            unique[_list[i][_type]] = 1;
4244          }
4245        }
4246  
4247        return distinct;
4248      };
4249  
4250      /**
4251       * [merge Merge two array]
4252       * @param  {[type]} a [description]
4253       * @param  {[type]} b [description]
4254       * @return {[type]}   [description]
4255       */
4256      asl_engine.helper.merge = function(a, b) {
4257  
4258        var hash = {};
4259        var i;
4260        
4261        for (i = 0; i < a.length; i++) {hash[a[i]] = true;}
4262        for (i = 0; i < b.length; i++) {hash[b[i]] = true;}
4263        
4264        return Object.keys(hash);
4265      };
4266  
4267      /**
4268       * [asl_leadzero description]
4269       * @param  {[type]} n [description]
4270       * @return {[type]}   [description]
4271       */
4272      asl_engine.helper.asl_leadzero = function(n) {
4273        return n > 9 ? "" + n : "0" + n;
4274      };
4275  
4276      /**
4277       * [asl_timeConvert description]
4278       * @param  {[type]} _str [description]
4279       * @return {[type]}      [description]
4280       */
4281      asl_engine.helper.asl_timeConvert = function(_str) {
4282  
4283        if(!_str)return 0;
4284  
4285        var time  = $.trim(_str).toUpperCase();
4286  
4287        if(/(1[012]|[0-9]):[0-5][0-9]$/.test(time)) {
4288  
4289        var hours   = Number(time.match(/^(\d+)/)[1]);
4290        var minutes = Number(time.match(/:(\d+)/)[1]);
4291  
4292        return hours+(minutes / 100);
4293        }
4294        else if(/(1[012]|[1-9]):[0-5][0-9][ ]?(AM|PM)/.test(time)) {
4295          
4296          var hours   = Number(time.match(/^(\d+)/)[1]);
4297          var minutes = Number(time.match(/:(\d+)/)[1]);
4298          var AMPM    = (time.indexOf('PM') != -1)?'PM':'AM';
4299  
4300          if (AMPM == "PM" && hours < 12) hours  = hours + 12;
4301        if (AMPM == "AM" && hours == 12) hours = hours - 12;
4302  
4303          return hours+(minutes / 100);
4304        }
4305        else
4306          return 0;
4307  
4308      };
4309  
4310      /**
4311       * [between description]
4312       * @param  {[type]} number [description]
4313       * @param  {[type]} lower  [description]
4314       * @param  {[type]} upper  [description]
4315       * @return {[type]}        [description]
4316       */
4317      asl_engine.helper.between = function(number, lower, upper) {
4318        return number > lower && number < upper;
4319      };
4320  
4321      /**
4322       * [implode description]
4323       * @param  {[type]} arr [description]
4324       * @param  {[type]} sep [description]
4325       * @return {[type]}     [description]
4326       */
4327      asl_engine.helper.implode = function(arr, sep) {
4328        var parts = [];
4329        for (var i = 0, ii = arr.length; i < ii; i++) {
4330          arr[i] && parts.push(arr[i]);
4331        }
4332        return parts.join(sep);
4333      };
4334  
4335      /**
4336       * [toObject_ description]
4337       * @param  {[type]} headings [description]
4338       * @param  {[type]} row      [description]
4339       * @return {[type]}          [description]
4340       */
4341      asl_engine.helper.toObject_ = function(headings, row) {
4342  
4343        var result = {};
4344        for (var i = 0, ii = row.length; i < ii; i++) {
4345          result[headings[i]] = row[i];
4346        }
4347        return result;
4348      };
4349  
4350  
4351      /**
4352       * [distanceCalc description]
4353       * @param  {[type]} point [description]
4354       * @return {[type]}       [description]
4355       */
4356      asl_engine.helper.distanceCalc = function(point) {
4357  
4358        var R = 6371; // mean radius of earth
4359        var location = this.getLocation();
4360        var lat1 = asl_locator.toRad_(location.lat());
4361        var lon1 = asl_locator.toRad_(location.lng());
4362        var lat2 = asl_locator.toRad_(point.lat());
4363        var lon2 = asl_locator.toRad_(point.lng());
4364        var dLat = lat2 - lat1;
4365        var dLon = lon2 - lon1;
4366  
4367        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
4368          Math.cos(lat1) * Math.cos(lat2) *
4369          Math.sin(dLon / 2) * Math.sin(dLon / 2);
4370        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
4371        return R * c;
4372      };
4373  
4374  
4375      /**
4376       * [multi_sort description]
4377       * @param  {[type]} _items   [description]
4378       * @param  {[type]} _param_1 [description]
4379       * @param  {[type]} _param_2 [description]
4380       * @return {[type]}          [description]
4381       */
4382      asl_engine.helper.multi_sort =  function(_items, _param_1, _param_2) {
4383  
4384        _items.sort(function(a, b) {
4385  
4386          var aVal = a[_param_1];
4387          var bVal = b[_param_1];
4388          var aNum = a[_param_2];
4389          var bNum = b[_param_2];
4390  
4391          if (aVal == bVal) {
4392  
4393            return (aNum < bNum) ? -1 : (aNum > bNum) ? 1 : 0;
4394          } else {
4395            return (aVal < bVal) ? -1 : 1;
4396          }
4397        });
4398      };
4399  
4400  
4401      /**
4402       * [sortBy Sort Method for Integer & Strings]
4403       * @param  {[type]} a [description]
4404       * @param  {[type]} b [description]
4405       * @return {[type]}   [description]
4406       */
4407      asl_engine.helper.sortBy = function(_items, _type, _string) {
4408  
4409  
4410        var sort_method = null;
4411  
4412        //  For Strings
4413        if(_string) {
4414  
4415          if(asl_configuration.sort_order == 'desc') {
4416  
4417            //  For string to with localecompare
4418            sort_method = function(a, b) {
4419              
4420              return (a[_type] && b[_type])? -(a[_type].localeCompare(b[_type])): 0;
4421            };
4422          }
4423          else {
4424  
4425            //  For string to with localecompare
4426            sort_method = function(a, b) {
4427              
4428              return (a[_type] && b[_type])? a[_type].localeCompare(b[_type]): 0;
4429            };
4430          }
4431        }
4432        //  Integers
4433        else {
4434  
4435          if(asl_configuration.sort_order == 'desc') {
4436  
4437            sort_method = function(a, b) {
4438              return parseInt(b[_type]) - parseInt(a[_type]);
4439            };
4440          }
4441          else
4442            sort_method = function(a, b) {
4443              return parseInt(a[_type]) - parseInt(b[_type]);
4444            };  
4445        }
4446  
4447        return _items.sort(sort_method);
4448      };
4449  
4450      /*HELPER ENDS HERE*/
4451  
4452  
4453      /*All the DATAFEED*/
4454      asl_engine.dataSource = function() {
4455  
4456        this.stores_ = [];
4457        this.remote_url = ASL_REMOTE.ajax_url;
4458      };
4459  
4460      /* Accordion STARTS*/
4461      asl_engine.dataSource.prototype.getCountriesStateCities = function(_objects) {
4462  
4463        var countries = {};
4464  
4465        for (var i = 0; i < _objects.length; i++) {
4466  
4467          //country add
4468          if (!countries[_objects[i].props_.country]) {
4469            countries[_objects[i].props_.country] = {};
4470          }
4471  
4472          //state add
4473          if (!countries[_objects[i].props_.country][_objects[i].props_.state]) {
4474            countries[_objects[i].props_.country][_objects[i].props_.state] = [];
4475          }
4476  
4477          //add the suburb if not there
4478          if (countries[_objects[i].props_.country][_objects[i].props_.state].indexOf(_objects[i].props_.city) == -1) {
4479            countries[_objects[i].props_.country][_objects[i].props_.state].push(_objects[i].props_.city);
4480          }
4481        }
4482  
4483        return countries;
4484      };
4485  
4486  
4487      asl_engine.dataSource.prototype.getStateCities = function(_objects) {
4488  
4489        var states_n_cities = {};
4490  
4491        for (var i = 0; i < _objects.length; i++) {
4492  
4493          //state add
4494          if (!states_n_cities[_objects[i].props_.state]) {
4495            states_n_cities[_objects[i].props_.state] = [];
4496          }
4497  
4498          //add the suburb if not there
4499          if (states_n_cities[_objects[i].props_.state].indexOf(_objects[i].props_.city) == -1) {
4500            states_n_cities[_objects[i].props_.state].push(_objects[i].props_.city);
4501          }
4502        }
4503  
4504        return states_n_cities;
4505      };
4506  
4507      /**
4508       * [sortDistance description]
4509       * @param  {[type]} latLng [description]
4510       * @param  {[type]} stores [description]
4511       * @return {[type]}        [description]
4512       */
4513      asl_engine.dataSource.prototype.sortDistance = function(latLng, stores) {
4514  
4515        stores = stores.sort(function(a, b) {
4516          return a.distanceTo(latLng) - b.distanceTo(latLng);
4517        });
4518      };
4519  
4520  
4521      /**
4522       * [sortRandom Sort by random]
4523       * @param  {[type]} stores [description]
4524       * @return {[type]}        [description]
4525       */
4526      asl_engine.dataSource.prototype.sortRandom  = function(stores) {
4527  
4528          stores = stores.sort(function(a, b) {
4529            return Math.random() - 0.5;
4530          });
4531      };
4532  
4533      /**
4534       * [sortBy Sort By Function]
4535       * @param  {[type]} _type  [description]
4536       * @param  {[type]} stores [description]
4537       * @return {[type]}        [description]
4538       */
4539      asl_engine.dataSource.prototype.sortBy = function(_type, stores) {
4540  
4541        var sort_method = null;
4542  
4543  
4544        //  There are no stores
4545        if(!stores || !stores.length) {
4546          return;
4547        }
4548  
4549        //  when search term is integer
4550        var is_integer = (typeof stores[0].props_[_type] == 'number')? true: false;
4551  
4552        if (_type == 'cat') {
4553            
4554          /**
4555           * [sort_method Sort for the categries]
4556           * @param  {[type]} a [description]
4557           * @param  {[type]} b [description]
4558           * @return {[type]}   [description]
4559           */
4560          sort_method = function(a, b) {
4561  
4562            var aVal = a.props_['cat'];
4563            var bVal = b.props_['cat'];
4564            var aDist = a.props_['distance'];
4565            var bDist = b.props_['distance'];
4566  
4567            if (aVal == bVal) {
4568  
4569              return (aDist < bDist) ? -1 : (aDist > bDist) ? 1 : 0;
4570            }
4571            else {
4572              return (aVal < bVal) ? -1 : 1;
4573            }
4574          };
4575        }
4576        //When integer
4577        else if(is_integer) {
4578  
4579          /**
4580           * [sort_method description]
4581           * @param  {[type]} a [description]
4582           * @param  {[type]} b [description]
4583           * @return {[type]}   [description]
4584           */
4585          sort_method = function(a, b) {
4586            return (a.props_[_type] > b.props_[_type]) ? 1 : ((b.props_[_type] > a.props_[_type]) ? -1 : 0);
4587          }
4588        }
4589        else if(asl_configuration.sort_order == 'desc') {
4590          
4591          /**
4592           * [sort_method description]
4593           * @param  {[type]} a [description]
4594           * @param  {[type]} b [description]
4595           * @return {[type]}   [description]
4596           */
4597          sort_method = function(a, b) {
4598            return (a.props_[_type].toLowerCase() < b.props_[_type].toLowerCase()) ? 1 : ((b.props_[_type].toLowerCase() < a.props_[_type].toLowerCase()) ? -1 : 0);
4599          };
4600        }
4601        else {
4602            
4603          /**
4604           * [sort_method description]
4605           * @param  {[type]} a [description]
4606           * @param  {[type]} b [description]
4607           * @return {[type]}   [description]
4608           */
4609          sort_method = function(a, b) {
4610            return (a.props_[_type].toLowerCase() > b.props_[_type].toLowerCase()) ? 1 : ((b.props_[_type].toLowerCase() > a.props_[_type].toLowerCase()) ? -1 : 0);
4611          }
4612        }
4613        
4614        stores.sort(sort_method);
4615      };
4616  
4617  
4618      /**
4619       * [sortByDesc Sort by Desc]
4620       * @param  {[type]} _type  [description]
4621       * @param  {[type]} stores [description]
4622       * @return {[type]}        [description]
4623       */
4624      asl_engine.dataSource.prototype.sortByDesc = function(_type, stores) {
4625  
4626        stores.sort(function(a, b) {
4627  
4628          return (a.props_[_type] < b.props_[_type]) ? 1 : ((b.props_[_type] < a.props_[_type]) ? -1 : 0);
4629        });
4630      };
4631  
4632  
4633  
4634      /**
4635       * [load_kml Load a KML]
4636       * @param  {[type]} _map [description]
4637       */
4638      asl_engine.dataSource.prototype.load_kml = function(_map) {
4639  
4640        //  All the KML files
4641        var kml_files = asl_configuration.kml_files;
4642  
4643        for(var k in kml_files) {
4644  
4645          if (!kml_files.hasOwnProperty(k)) continue;
4646  
4647  
4648          var src_file = asl_configuration.URL + '/kml/' + kml_files[k];
4649  
4650          //  Create a layer
4651          var kmlLayer = new google.maps.KmlLayer(src_file, {
4652              //suppressInfoWindows: false,
4653              preserveViewport: true,
4654              map: _map
4655            });
4656          
4657          /*kmlLayer.addListener('click', function(event) {
4658            var content = event.featureData.infoWindowHtml;
4659            var testimonial = document.getElementById('capture');
4660            testimonial.innerHTML = content;
4661          });*/
4662        }
4663      };
4664  
4665  
4666      var not_initial_load = false,
4667        asl_view = null,
4668        asl_panel = null;
4669  
4670  
4671      /**
4672       * [fetch_remote_data Fetch the remote Data]
4673       * @param  {[type]} _position [description]
4674       * @return {[type]}           [description]
4675       */
4676      asl_engine.dataSource.prototype.fetch_remote_data = function(_position, _params, _fetch_callback) {
4677  
4678        var that = this;
4679  
4680        $('.asl-cont .asl-overlay').show();
4681  
4682        // Old _params for GDPR
4683        if(!_params && asl_configuration.reload_params) {
4684          
4685          //  Give it to _params
4686          _params = asl_configuration.reload_params;
4687  
4688          // reset it to null
4689          asl_configuration.reload_params = null;
4690        }
4691  
4692        var params = {
4693          action: 'asl_load_stores',
4694          nonce: ASL_REMOTE.nonce,
4695          //asl_lang: asl_configuration.lang,
4696          load_all: asl_configuration.load_all,
4697          layout: (asl_configuration.layout) ? 1 : 0
4698        };
4699  
4700        //  Merge with the original parameters
4701        if(_params) {
4702          params = Object.assign(params, _params);
4703        }
4704  
4705  
4706        //limited markers
4707        if (asl_configuration.stores) {
4708          params['stores'] = asl_configuration.stores;
4709        }
4710  
4711        //Not Load all
4712        if (asl_configuration.load_all != '1') {
4713  
4714          var bounds = map.getBounds(),
4715            ne = bounds.getNorthEast(), // LatLng of the north-east corner
4716            sw = bounds.getSouthWest(), // LatLng of the south-west corder
4717            center = bounds.getCenter();
4718  
4719          params['lat'] = center.lat(),
4720            params['lng'] = center.lng(),
4721            params['nw'] = [ne.lat(), sw.lng()],
4722            params['se'] = [sw.lat(), ne.lng()];
4723        }
4724  
4725  
4726        //  specific category
4727        if (asl_configuration.category) {
4728          params['category'] = asl_configuration.category;
4729        }
4730  
4731        //  specific special
4732        if (asl_configuration.special) {
4733          params['special'] = asl_configuration.special;
4734        }
4735  
4736        //  specific brand
4737        if (asl_configuration.brand) {
4738          params['brand'] = asl_configuration.brand;
4739        }
4740  
4741        /*
4742        if(that.on_call)
4743          return;
4744        */
4745        that.on_call = true;
4746  
4747        var the_url = ASL_REMOTE.ajax_url;
4748        
4749        $.ajax({
4750          url: the_url,
4751          data: params,
4752          type: 'GET',
4753          dataType: 'json',
4754          success: function(_data) {
4755  
4756            that.stores_ = that.parseData(_data);
4757  
4758            var _input_txt = $('.asl-cont #auto-complete-search,.asl-cont .asl-search-address');
4759  
4760            //  Remove spinner
4761            if (asl_configuration.load_all == '2') {
4762              $('.asl-reload-map').find('i').removeClass('animate-spin');
4763            }
4764            
4765            
4766            //  Add Clear button for Search Type 0 and 3
4767            if (!not_initial_load) {
4768              asl_locator.add_clear_button(_input_txt);
4769            }
4770  
4771  
4772            //  Add search location end
4773            var all_stores = that.stores_;
4774  
4775            var country = (all_stores[0]) ? all_stores[0].props_.country : null;
4776            that.countries = false;
4777  
4778  
4779            for (var j = 0; j < all_stores.length; j++) {
4780  
4781  
4782              if (country != all_stores[j].props_.country) {
4783                that.countries = true;
4784                break;
4785              }
4786            }
4787  
4788            
4789  
4790            // Only Once loaded
4791            if (!not_initial_load) {
4792  
4793              not_initial_load = true;
4794  
4795              //that.load_locator(all_stores[0],that.countries);
4796              asl_view = new asl_locator.View(map, that, {
4797                geolocation: false,
4798                features: that.getDSFeatures()
4799              });
4800  
4801  
4802              asl_panel = new asl_locator.Panel(document.getElementById('asl-panel'), {
4803                view: asl_view
4804              });
4805  
4806              window['asl_view'] = asl_view;
4807  
4808              
4809              //  when we have the kml files, include them
4810              if(asl_configuration.kml_files) {
4811  
4812                that.load_kml(map);
4813              }
4814  
4815  
4816  
4817              //  Desc Modal Close Event
4818              $('.asl-cont #asl-desc-agile-modal').find('.sl-close').bind('click', asl_panel.hideDescModal.bind(asl_panel));
4819  
4820              //  Geo Modal
4821              var $agile_modal = jQuery('.asl-cont #asl-geolocation-agile-modal');
4822  
4823              //  Close Dailog Event GeoModal
4824              $agile_modal.find('.sl-close').bind('click', asl_panel.hideGeoModal.bind(asl_panel));
4825  
4826               /**
4827               * [_promptLocResRender Will remove the dailog and execute measure_distance]
4828               * @param  {[type]} geo_place [description]
4829               * @return {[type]}           [description]
4830               */
4831              function _promptLocResRender(geo_place) {
4832  
4833                asl_view.measure_distance(geo_place.geometry.location, true, null, geo_place);
4834  
4835                $agile_modal.removeClass('in').css('display', 'none');
4836  
4837                if (asl_configuration.analytics) {
4838                  //asl_locator.save_analytics(p);
4839                }
4840              };
4841  
4842              
4843  
4844              //  Auto Without Prompt
4845              if (asl_configuration.prompt_location == '3') {
4846                asl_view.geolocate_();
4847              }
4848              else if (asl_configuration.prompt_location == '4') {
4849                asl_view.geo_service();
4850              }
4851              //  Prompt using the Dailog
4852              else if (asl_configuration.prompt_location != '0') {
4853  
4854                $agile_modal.css('display', 'block');
4855  
4856                window.setTimeout(function() {
4857  
4858                  $agile_modal.addClass('in');
4859  
4860                }, 300);
4861  
4862                //IF PROMPT is ON
4863                $('.asl-cont #asl-btn-geolocation').bind('click', function() {
4864                  asl_view.geolocate_();
4865                  $agile_modal.removeClass('in').css('display', 'none');
4866                });
4867  
4868                //  Geo Modal is enabled
4869                asl_panel.geo_modal = true;
4870              }
4871  
4872              // For GEO Locate Prompt Dailog
4873              if (asl_configuration.prompt_location == "2") {
4874  
4875                var geo_place = null;
4876  
4877                var geocoder = new google.maps.Geocoder(),
4878                  _callback = _callback || function(results, status) {
4879  
4880                    if (status == 'OK') {
4881  
4882                      _promptLocResRender(results[0]);
4883  
4884                    } else {
4885                      console.log('Geocode was not successful for the following reason: ' + status);
4886                    }
4887                  };
4888  
4889  
4890                // Enter Key
4891                $('#asl-current-loc').bind('keyup', function(e) {
4892  
4893                  if (e.keyCode == 13) {
4894  
4895                    var addr_value = $.trim(this.value);
4896  
4897                    if (addr_value) {
4898  
4899                      //birmingham
4900                      var search_param = { 'address': addr_value };
4901  
4902                      //  Restrict the search
4903                      if (asl_configuration.country_restrict) {
4904                      
4905                        var country_restricted = asl_configuration.country_restrict.toLowerCase();
4906  
4907                        country_restricted = country_restricted.split(',');
4908  
4909                        search_param['componentRestrictions'] = {
4910                          country: country_restricted[0]
4911                        };
4912                      }
4913  
4914                      geocoder.geocode(search_param, _callback);
4915                    }
4916                  }
4917                });
4918  
4919                //Event of geolocate 
4920                $('#asl-btn-locate').click(function(e) {
4921  
4922  
4923                  // When we have it through Place API
4924                  if (geo_place) {
4925                    
4926                    _promptLocResRender(geo_place);
4927                    return;
4928                  }
4929  
4930  
4931                  // For simple button click when no data
4932                  var addr_value = $.trim($('#asl-current-loc').val());
4933  
4934                    if (addr_value)
4935                      geocoder.geocode({ 'address': addr_value }, _callback);
4936                });
4937  
4938  
4939                var input = $('.asl-cont #asl-current-loc')[0];
4940  
4941                var options = {};
4942  
4943                if (asl_configuration.google_search_type) {
4944                  options['types'] = ['(' + asl_configuration.google_search_type + ')'];
4945                }
4946  
4947                /*if (asl_configuration.country_restrict) {
4948                  options['componentRestrictions'] = { country: asl_configuration.country_restrict.toLowerCase() }
4949                }*/
4950  
4951  
4952                var autoComplete_ = new google.maps.places.Autocomplete(input, options);
4953  
4954                //  Restrict the country
4955                if (asl_configuration.country_restrict) {
4956              
4957                  var country_restricted = asl_configuration.country_restrict.toLowerCase();
4958  
4959                  country_restricted = country_restricted.split(',');
4960  
4961                  autoComplete_.setComponentRestrictions({country: country_restricted });
4962                }
4963  
4964                //  Limit the search scope
4965                var fields = ['geometry'];
4966  
4967                if(asl_configuration.filter_address)
4968                  fields.push('address_components');
4969  
4970                autoComplete_.setFields(fields);
4971  
4972                google.maps.event.addListener(autoComplete_, 'place_changed',
4973  
4974                  function() {
4975                    var p = this.getPlace();
4976  
4977                    geo_place = p;
4978                  });
4979              }
4980  
4981              //GEO Locate Current Location
4982              $('.asl-cont .asl-geo.icon-direction-outline').bind('click', function(e) {
4983                asl_view.geolocate_();
4984              });
4985  
4986  
4987              //for users who want fixed lat/lng for home location
4988              if (asl_configuration.user_center)
4989                asl_view.measure_distance(new google.maps.LatLng(asl_configuration.default_lat, asl_configuration.default_lng));
4990            }
4991            // Only loaded once end
4992  
4993            //  Calculate distance for Ajax
4994            if (asl_configuration.load_all != '1' && asl_view.dest_coords) {
4995              asl_view.measure_distance(asl_view.dest_coords, null, true);
4996            }
4997  
4998  
4999            //  First Refresh of the View
5000            asl_view.refreshView();
5001  
5002            $('.asl-cont .asl-overlay').hide();
5003            
5004            //  Pan to a given Position
5005            if (_position) {
5006              map.panTo(_position);
5007            }
5008  
5009  
5010            that.on_call = false;
5011  
5012            //  Call the asl_loaded event
5013            if(window['asl_loaded'] && typeof window['asl_loaded']  == 'function') {
5014              asl_loaded.call(this);
5015            }
5016  
5017  
5018            //  When it is Load All
5019            if(asl_configuration.load_all == '1') {
5020  
5021              //  Highlight a Store supported by Load all
5022              var hash_store_id = window.location.hash.replace('#', '');
5023  
5024              //  Validate, it should be a number
5025              if(hash_store_id && !isNaN(hash_store_id)) {
5026  
5027                //  Timeout for the Hash Method
5028                window.setTimeout(function() {
5029                    
5030                  var searched_store = asl_view.data_.findStore(hash_store_id);
5031  
5032                  asl_view.highlight(searched_store);
5033  
5034                }, 500);
5035              }
5036            }
5037  
5038  
5039            //  All data is loaded
5040            asl_locator.hook_event({type: 'load', data: null});
5041  
5042            //  Add a callback function
5043            if(_fetch_callback && typeof _fetch_callback == 'function') {
5044              _fetch_callback.call(this);
5045            }
5046  
5047          },
5048          error: function() {
5049            that.on_call = false;
5050          },
5051          dataType: 'json'
5052        });
5053  
5054  
5055        /*Save that pos*/
5056        that.pos = center;
5057      };
5058  
5059  
5060  
5061      /**
5062       * [load_locator Load the Locator]
5063       * @return {[type]} [description]
5064       */
5065      asl_engine.dataSource.prototype.load_locator = function() { /* _store,_morecountries */
5066  
5067        var that = this;
5068  
5069        //Only if found
5070        if (!document.getElementById('asl-map-canv'))
5071          return false;
5072  
5073  
5074        var maps_params = {
5075          center: new google.maps.LatLng(asl_lat, asl_lng),
5076          zoom: parseInt(asl_configuration.zoom),
5077          scrollwheel: asl_configuration.scroll_wheel,
5078          gestureHandling: asl_configuration.gesture_handling || 'cooperative', //cooperative,greedy
5079          mapTypeId: asl_configuration.map_type
5080        };
5081  
5082        //  Advanced Marker
5083        if(asl_configuration.advanced_marker) {
5084          maps_params['mapId'] = asl_configuration.map_id || "asl-maps-id-tag";
5085        }
5086  
5087        maps_params.zoomControl     = (asl_configuration.zoomcontrol == 'true')? true: false;
5088        maps_params.mapTypeControl  = (asl_configuration.maptypecontrol == 'true')? true: false;
5089        if (asl_configuration.scalecontrol == 'false') maps_params.scaleControl = false;
5090        if (asl_configuration.rotatecontrol == 'false') maps_params.rotateControl = false;
5091        if (asl_configuration.fullscreencontrol == 'false') maps_params.fullscreenControl = false;
5092        if (asl_configuration.streetviewcontrol == 'false') maps_params.streetViewControl = false;
5093        if (asl_configuration.cameracontrol == 'false') maps_params.cameraControl = false;
5094  
5095        maps_params['fullscreenControlOptions'] = {
5096          position: google.maps.ControlPosition.RIGHT_CENTER
5097        };
5098  
5099  
5100        // Map Type Positions
5101        if(asl_configuration.position_maptype) {
5102          maps_params['mapTypeControlOptions'] = {position: parseInt(asl_configuration.position_maptype)};
5103        }
5104  
5105        // FULL SCREEN Positions
5106        if(asl_configuration.position_fullscreen) {
5107          maps_params['fullscreenControlOptions'] = {position: parseInt(asl_configuration.position_fullscreen)};
5108        }
5109  
5110        // ZOOM Positions
5111        if(asl_configuration.position_zoom) {
5112          maps_params['zoomControlOptions'] = {position: parseInt(asl_configuration.position_zoom)};
5113        }
5114  
5115        // STREETVIEW Positions
5116        if(asl_configuration.position_streetview) {
5117          maps_params['streetViewControlOptions'] = {position: parseInt(asl_configuration.position_streetview)};
5118        }
5119  
5120        if (asl_configuration.maxzoom && !isNaN(asl_configuration.maxzoom)) {
5121          maps_params['maxZoom'] = parseInt(asl_configuration.maxzoom);
5122        }
5123  
5124        if (asl_configuration.minzoom && !isNaN(asl_configuration.minzoom)) {
5125          maps_params['minZoom'] = parseInt(asl_configuration.minzoom);
5126        }
5127  
5128        map = new google.maps.Map(document.getElementById('asl-map-canv'), maps_params);
5129  
5130        window['asl_map'] = map;
5131  
5132  
5133        ///////Add a Map Reset Button////////////
5134        asl_configuration.reset_button = true;
5135  
5136        if (asl_configuration.reset_button) {
5137  
5138          var $reset_btn = null;
5139  
5140          function ASLResetMAP(controlDiv, map) {
5141  
5142            // Set CSS for the control border.
5143            $reset_btn = $('<span class="asl-reset-map" style="display:none">' + asl_configuration.words.reset_map + '</span>');
5144            controlDiv.appendChild($reset_btn[0]);
5145  
5146            // Setup the click event listeners: simply set the map to Chicago.
5147            $reset_btn[0].addEventListener('click', function() {
5148  
5149              map.panTo(new google.maps.LatLng(asl_lat, asl_lng));
5150              map.setZoom(parseInt(asl_configuration.zoom));
5151  
5152              $reset_btn[0].style.display = 'none';
5153  
5154              //Reset the Category
5155              if (asl_view._panel.$category_ddl) {
5156  
5157                var selected_cats = asl_view._panel.$category_ddl.val();
5158                if (selected_cats && selected_cats.length > 0) {
5159                  asl_view._panel.$category_ddl.multiselect('deselect', asl_view._panel.$category_ddl.val(), true);
5160                }
5161              }
5162  
5163              //  When the direction box is press in the mobile, show the map
5164              if(asl_configuration.is_mob) {
5165  
5166                //  Scroll to the Map
5167                $('html, body')
5168                    .stop()
5169                    .animate({
5170                      'scrollTop': $('.asl-cont.storelocator-main').offset().top
5171                    }, 900, 'swing');
5172              }
5173  
5174              asl_view.highlight(null);
5175  
5176            });
5177          }
5178  
5179          var centerControlDiv = document.createElement('div');
5180          var centerControl = new ASLResetMAP(centerControlDiv, map);
5181  
5182          centerControlDiv.index = 1;
5183          map.controls[google.maps.ControlPosition.TOP_RIGHT].push(centerControlDiv);
5184        }
5185        /////////////////
5186  
5187  
5188        if (asl_configuration.map_layout) {
5189          var map_style = eval('(' + asl_configuration.map_layout + ')');
5190          map.set('styles', map_style);
5191        }
5192  
5193  
5194        if (window['_asl_map_customize']) {
5195  
5196          _asl_map_customize = JSON.parse(_asl_map_customize);
5197  
5198          //  When Advanced Marker is enabled disable the animations
5199          if(asl_configuration.advanced_marker) {
5200            _asl_map_customize.marker_animations = false;
5201          }
5202  
5203          //ADd trafice layer
5204          if (_asl_map_customize.trafic_layer && _asl_map_customize.trafic_layer == 1) {
5205  
5206            trafic_layer = new google.maps.TrafficLayer();
5207            trafic_layer.setMap(map);
5208          }
5209  
5210          //ADd bike layer
5211          if (_asl_map_customize.bike_layer && _asl_map_customize.bike_layer == 1) {
5212  
5213            bike_layer = new google.maps.BicyclingLayer();
5214            bike_layer.setMap(map);
5215          }
5216  
5217          //ADd transit layer
5218          if (_asl_map_customize.transit_layer && _asl_map_customize.transit_layer == 1) {
5219  
5220            transit_layer = new google.maps.TransitLayer();
5221            transit_layer.setMap(map);
5222          }
5223  
5224  
5225          ///Load the DATA
5226          if (_asl_map_customize.drawing) {
5227  
5228            asl_drawing.loadData(_asl_map_customize.drawing, map);
5229          }
5230        }
5231  
5232        ///////////////////////////////////////////////////////////////////////
5233        var _features = [];
5234  
5235        /*Add all categories*/
5236  
5237        for (var i in asl_categories) {
5238          var cat = asl_categories[i];
5239          that.FEATURES_.add(new asl_locator.Feature(cat.id, cat.name, cat.icon, ((cat.ordr && !isNaN(cat.ordr))? parseInt(cat.ordr): 0)));
5240        }
5241  
5242        if (asl_configuration.load_all == '1') {
5243  
5244          that.fetch_remote_data();
5245        } 
5246        else if (asl_configuration.load_all == '2') {
5247  
5248          var $reload_btn = null,
5249            _set_position = null,
5250            first_loaded = false;
5251  
5252          function ASLReloadMAP(controlDiv, map) {
5253  
5254            // Set CSS for the control border.
5255            $reload_btn = $('<span class="asl-reload-map" display="none"><i class="icon-arrows-cw"></i>' + asl_configuration.words.reload_map + '</span>');
5256            controlDiv.appendChild($reload_btn[0]);
5257  
5258            // Setup the click event listeners: simply set the map to Chicago.
5259            $reload_btn[0].addEventListener('click', function() {
5260  
5261              $reload_btn.find('i').addClass('animate-spin');
5262              that.fetch_remote_data(_set_position);
5263            });
5264          }
5265  
5266          var centerControlDiv = document.createElement('div');
5267          var centerControl = new ASLReloadMAP(centerControlDiv, map);
5268  
5269          centerControlDiv.index = 1;
5270          map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
5271  
5272          //the load event
5273          google.maps.event.addListener(map, 'idle', function() {
5274  
5275            if (asl_view && asl_view.halt_fetch) {
5276  
5277              _set_position = asl_view.marker_center;
5278              asl_view.halt_fetch = false;
5279            }
5280  
5281            $reload_btn[0].style.display = 'block';
5282  
5283            //first load
5284            if (!first_loaded) {
5285              first_loaded = true;
5286              that.fetch_remote_data();
5287            }
5288          });
5289        }
5290        //  load_all == '0'
5291        else
5292          google.maps.event.addListener(map, 'idle', function() {
5293  
5294            //  fix over here
5295            var _set_position = null;
5296  
5297            if (asl_view && asl_view.halt_fetch) {
5298  
5299              _set_position = asl_view.marker_center;
5300              asl_view.halt_fetch = false;
5301              return;
5302            }
5303  
5304  
5305            that.fetch_remote_data(_set_position);
5306          });
5307  
5308      };
5309      /**
5310       * @const
5311       * @type {!asl_locator.FeatureSet}
5312       * @private
5313       */
5314      asl_engine.dataSource.prototype.FEATURES_ = new asl_locator.FeatureSet();
5315  
5316  
5317      /**
5318       * @return {!asl_locator.FeatureSet}
5319       */
5320      asl_engine.dataSource.prototype.getDSFeatures = function() {
5321        return this.FEATURES_;
5322      };
5323  
5324  
5325      /**
5326       * [parseData Parse Data]
5327       * @param  {[type]} rows [description]
5328       * @return {[type]}      [description]
5329       */
5330      asl_engine.dataSource.prototype.parseData = function(rows) {
5331  
5332        var stores = [];
5333  
5334        var current_hr_min = asl_date.getHours() + (asl_date.getMinutes() / 100),
5335          current_day      = asl_date.getDay();
5336  
5337  
5338        var _asl_categories = asl_categories;
5339        asl_categories      = {};
5340        var c_keys = Object.keys(_asl_categories);
5341  
5342  
5343        for (var c in c_keys) {
5344  
5345          if (typeof(_asl_categories[c_keys[c]]) == "object") {
5346  
5347            asl_categories[String(c_keys[c])] = _asl_categories[c_keys[c]];
5348            asl_categories[c_keys[c]].len = 0;
5349          }
5350        }
5351  
5352        //Calculate Open Hours
5353        var days      = { '1': 'mon', '2': 'tue', '3': 'wed', '4': 'thu', '5': 'fri', '6': 'sat', '0': 'sun' },
5354          day_keys    = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'],
5355          current_day = days[current_day];
5356  
5357        var time_now   = new Date;
5358        var days_number  = { 
5359          'sun': 0,
5360          'mon': 1,
5361          'tue': 2,
5362          'wed': 3,
5363          'thu': 4,
5364          'fri': 5,
5365          'sat': 6
5366        };
5367  
5368  
5369        var grouped_hours = (asl_configuration.week_hours == '2')? true: false;
5370  
5371        /*
5372        var cust_lbls = [
5373        asl_configuration.words.carry_out,
5374        asl_configuration.words.dine_in,
5375        asl_configuration.words.delivery
5376        ];
5377        */
5378  
5379        /**
5380         * [sl_slot description]
5381         * @return {[type]} [description]
5382         */
5383        function sl_slot() {
5384  
5385          this.start = null;
5386          this.end   = null;
5387          this.hours = [];
5388        }
5389  
5390        //  Use to Get All Hours
5391        function getAllHours(row) {
5392  
5393          //Close and Open Timing Hourse
5394          if (row.open_hours) {
5395  
5396  
5397            row.open        = false;
5398            row.days        = [];
5399            row.open_hours  = JSON.parse(row.open_hours);
5400            var days_words  = asl_configuration.days;
5401            var all_days_hours = (grouped_hours)? {}: [];
5402  
5403            for (var _kd in day_keys) {
5404  
5405              var k_day   = day_keys[_kd],
5406                hours     = row.open_hours[k_day],
5407                is_today  = (k_day == current_day) ? true : false;
5408  
5409               //Loop and Match Open Hours
5410                if(hours == '1') {
5411                    
5412                    if(is_today)
5413                        row.open =  true;
5414  
5415                    //  Push the open day
5416                    row.days.push(days_words[k_day]);
5417                }
5418                else if(hours == '0') {
5419                    
5420                    if(is_today)
5421                        row.open =  false;
5422                }
5423                else if(hours) {
5424                    
5425                    //  console.log(row.title, '===> ' + k_day + ' ===> ', hours);
5426                    //  Push the open day
5427                    row.days.push(days_words[k_day]);
5428  
5429                    var day_hours   = [];
5430  
5431  
5432                    for(var h in hours) {
5433  
5434                        if(!hours.hasOwnProperty(h))continue;
5435  
5436                        var hr_span = hours[h].split(' - ');
5437  
5438                        //time per day hack
5439                        var start_time = hr_span[0],
5440                            end_time   = hr_span[1];
5441  
5442                        var _start = (start_time != 0)?asl_engine.helper.asl_timeConvert(start_time):0,
5443                            _end   = (end_time != 0)?asl_engine.helper.asl_timeConvert(end_time):24;
5444  
5445                        //hack for end
5446                        if(_end == 0)_end = 24;
5447  
5448  
5449                        /**
5450                         *
5451                         * Timing 
5452                         * "10:00 PM" - "1:00 AM"
5453                         *  22 duration 3
5454                         *
5455                         * "4:00 PM", "2:00 AM"
5456                         *  16 duration
5457                         * 
5458                         */
5459                        
5460                        //  Do all the testing when open is false
5461                        if(!row.open) {
5462  
5463                            //  Simple Checking, Normal timing
5464                            if(_start < _end) {
5465  
5466                                // Is Today is used as only Today timing will be opened and they will be considered only and avoid other days, also once open saved
5467                                if(!row.open && is_today) {
5468  
5469                                    row.open = (_start && _end)? asl_engine.helper.between(current_hr_min, _start, _end): false;
5470                                }
5471                            }
5472                            //  Complex Checking
5473                            else {
5474  
5475                                var duration =  24 - _start  + _end;
5476  
5477                                // Convert the times in the Dates
5478                                var from_date = new Date();
5479                                from_date.setHours(Math.floor(_start));
5480                                from_date.setMinutes(getDecimal(_start));
5481  
5482                                // Validate the Correct day
5483                                if(time_now.getDay() != days_number[k_day]) {
5484                                    from_date.subDays(1);
5485                                }
5486  
5487  
5488                                var to_date = new Date(from_date.getTime());
5489                                to_date.addHours(duration);
5490                                to_date.setMinutes(getDecimal(_end));
5491  
5492                                //  Validate if it is in asl_engine.helper.between the timing, set Open is true
5493                                if(time_now > from_date && time_now < to_date) {
5494                                    row.open = true;
5495                                }
5496  
5497                            }
5498                        }
5499                        
5500                        //  Change the Format if 24 hours setting
5501                        if(asl_configuration.time_24) {
5502  
5503                            
5504                            _start += 0.01;
5505                            _start  = parseFloat(_start).toFixed(2);
5506                            var _s_time = String(_start).split('.');
5507                            
5508                            _s_time[0]  = asl_engine.helper.asl_leadzero(parseInt(_s_time[0]));
5509                            _s_time[1]  = asl_engine.helper.asl_leadzero((parseInt(_s_time[1]) - 1));
5510                            start_time = _s_time.join(':');
5511  
5512  
5513                            _end += 0.01;
5514                            _end = parseFloat(_end).toFixed(2);
5515  
5516                            var _e_time = String(_end).split('.');
5517                            _e_time[0]  = asl_engine.helper.asl_leadzero(parseInt(_e_time[0]));
5518                            _e_time[1]  = asl_engine.helper.asl_leadzero((parseInt(_e_time[1]) - 1));
5519                            end_time    = _e_time.join(':');
5520                        }
5521                        else {
5522  
5523                            var str_s_time = start_time.split(':'),
5524                                str_e_time = end_time.split(':');
5525                            
5526  
5527                            if(str_s_time[0]) {
5528                                str_s_time[0] = asl_engine.helper.asl_leadzero(parseInt(str_s_time[0]));
5529                            } 
5530  
5531                            start_time = str_s_time.join(':');
5532  
5533                            if(str_e_time[0]) {
5534                                str_e_time[0] = asl_engine.helper.asl_leadzero(parseInt(str_e_time[0]));
5535                            }
5536  
5537                            end_time = str_e_time.join(':');
5538                        }
5539  
5540                        day_hours.push(start_time+' - '+end_time);
5541                    }
5542  
5543                    if(grouped_hours)
5544                      all_days_hours[k_day] = day_hours;
5545                    else
5546                      all_days_hours.push('<span><span class="asl-day-lbl">'+days_words[k_day]+':</span><span class="asl-time-hrs">'+ day_hours.map(function(d) { return '<span>' + d + '</span>';}) + '</span></span>');
5547                }
5548            }
5549  
5550            //  Grouped
5551            if(grouped_hours) {
5552  
5553              // End of For loop
5554              var slots        = [],
5555                  tmp_slot     = null;
5556  
5557              // Loop to merge dates
5558              for(var d = 0; d < day_keys.length; d++) {
5559  
5560                //  A new slot for the times
5561                if(!tmp_slot || JSON.stringify(tmp_slot.hours) != JSON.stringify(all_days_hours[day_keys[d]])) {
5562                    
5563                  //  make sure the times exist
5564                  if(all_days_hours[day_keys[d]]) {
5565                    
5566                    tmp_slot = new sl_slot();
5567  
5568                    tmp_slot.start = day_keys[d];
5569                    tmp_slot.hours = all_days_hours[day_keys[d]];
5570  
5571                    //  add the slot
5572                    slots.push(tmp_slot);
5573                  }
5574                }
5575                else {
5576                  tmp_slot.end = day_keys[d];
5577                }
5578              }
5579  
5580              //  If we have the slots
5581              if(slots.length > 0) {
5582  
5583                var slot_html = '';
5584  
5585                //  For each slots
5586                slots.forEach(function(item) {
5587                  slot_html += '<span class="asl-group-slots"><span class="asl-day-lbl">'+days_words[item.start] + ((item.end)? (' - ' + days_words[item.end]): '') +':</span><span class="asl-time-hrs">'+ item.hours.map(function(h) { return '<span>' + h + '</span>'}).join('') + '</span></span>';
5588                });              
5589              }
5590  
5591              row.open_hours = slot_html;
5592            }
5593            //  Simple
5594            else {
5595  
5596              row.open_hours = (all_days_hours.length > 0)?('<span class="asl-week-hrs">'+all_days_hours.join('')+'</span>'):null;            
5597            }
5598  
5599            row.days = row.days.join(', ');
5600  
5601  
5602          }
5603          else row.open =  true;
5604        };
5605  
5606  
5607        // Use to Get Today Hours
5608        function getTodayHours(row) {
5609  
5610  
5611          //Close and Open Timing Hourse
5612          if (row.open_hours) {
5613  
5614            row.open       = false;
5615            
5616            row.open_hours = JSON.parse(row.open_hours);
5617  
5618            // Hours of the current day
5619            var hours = row.open_hours[current_day];
5620  
5621            row.open_hours = null;
5622  
5623            //Loop and Match Open Hours
5624            if(hours == '1') {
5625                
5626                row.open        =  true;
5627                row.open_hours  = null;
5628            }
5629            else if(hours == '0') {
5630                
5631                row.open        =  false;
5632                row.open_hours  = null;
5633            }
5634            else if(hours) {
5635                
5636                row.open_hours = [];
5637  
5638                for(var h in hours) {
5639  
5640                    if(!hours.hasOwnProperty(h))continue;
5641  
5642                    var hr_span = hours[h].split(' - ');
5643  
5644                    //time per day hack
5645                    var start_time = hr_span[0];
5646                    var end_time   = hr_span[1];
5647  
5648  
5649                    
5650                    var _start = (start_time != 0)?asl_engine.helper.asl_timeConvert(start_time):0,
5651                        _end   = (end_time != 0)?asl_engine.helper.asl_timeConvert(end_time):24;
5652  
5653                    //hack for end
5654                    if(_end == 0)_end = 24;
5655                  
5656  
5657                    //  Do all the testing when open is false
5658                    if(!row.open) {
5659  
5660                        //  Simple Checking, Normal timing
5661                        if(_start < _end) {
5662  
5663                            // Is Today is used as only Today timing will be opened and they will be considered only and avoid other days, also once open saved
5664                            if(!row.open) {
5665  
5666                                row.open = (_start && _end)? asl_engine.helper.between(current_hr_min, _start, _end): false;
5667                            }
5668                        }
5669                        //  Complex Checking
5670                        else {
5671  
5672                            var duration =  24 - _start  + _end;
5673  
5674                            // Convert the times in the Dates
5675                            var from_date = new Date();
5676                            from_date.setHours(Math.floor(_start));
5677                            from_date.setMinutes(getDecimal(_start));
5678  
5679                            // Validate the Correct day
5680                            if(time_now.getDay() != days_number[current_day]) {
5681                                from_date.subDays(1);
5682                            }
5683  
5684  
5685                            var to_date = new Date(from_date.getTime());
5686                            to_date.addHours(duration);
5687                            to_date.setMinutes(getDecimal(_end));
5688  
5689                            //  Validate if it is in asl_engine.helper.between the timing, set Open is true
5690                            if(time_now > from_date && time_now < to_date) {
5691                                row.open = true;
5692                            }
5693                        }
5694                    }
5695  
5696                    
5697                    //Change the format if 24 hours setting
5698                    if(asl_configuration.time_24) {
5699  
5700                        
5701                        _start += 0.01;
5702                        _start  = parseFloat(_start).toFixed(2);
5703                        var _s_time = String(_start).split('.');
5704                        
5705                        _s_time[0]  = asl_engine.helper.asl_leadzero(parseInt(_s_time[0]));
5706                        _s_time[1]  = asl_engine.helper.asl_leadzero((parseInt(_s_time[1]) - 1));
5707                        start_time = _s_time.join(':');
5708  
5709  
5710                        _end += 0.01;
5711                        _end = parseFloat(_end).toFixed(2);
5712  
5713                        var _e_time = String(_end).split('.');
5714                        _e_time[0]  = asl_engine.helper.asl_leadzero(parseInt(_e_time[0])
5714);
5715                        _e_time[1]  = asl_engine.helper.asl_leadzero((parseInt(_e_time[1]) - 1));
5716                        end_time = _e_time.join(':');
5717                    }
5718                    else {
5719  
5720                        var str_s_time = start_time.split(':'),
5721                            str_e_time = end_time.split(':');
5722                        
5723  
5724                        if(str_s_time[0]) {
5725                            str_s_time[0] = asl_engine.helper.asl_leadzero(parseInt(str_s_time[0]));
5726                        } 
5727  
5728                        start_time = str_s_time.join(':');
5729  
5730                        if(str_e_time[0]) {
5731                            str_e_time[0] = asl_engine.helper.asl_leadzero(parseInt(str_e_time[0]));
5732                        } 
5733  
5734                        end_time = str_e_time.join(':');
5735                    }
5736  
5737  
5738                    row.open_hours.push(start_time+' - '+end_time);
5739                }
5740  
5741                row.open_hours = (row.open_hours.length > 0)?row.open_hours.join(' <br> '):null;
5742            }
5743  
5744          }
5745          else row.open =  true;
5746        };
5747  
5748        var show_categories = asl_configuration.show_categories || asl_configuration.category_accordion;
5749  
5750        //  Show the link
5751        var have_link       = (asl_configuration.slug_link == '1')? true: false,
5752            slug_url        = asl_configuration.rewrite_slug + '/',
5753            is_slug_url     = (asl_configuration.link_type == '1' && asl_configuration.rewrite_slug)? true: false;
5754        
5755        var has_desc        = (asl_configuration.additional_info == '0')? false: true,
5756            has_desc_link   = (asl_configuration.additional_info == '2')? true: false;
5757  
5758        var no_locality_street = (asl_categories.template != '1')? true: false;
5759  
5760        //  Loop over the stores
5761        for (var i = 0; i < rows.length; i++) {
5762  
5763          var row = rows[i];
5764  
5765          row.id = parseInt(row.id);
5766          row.ordr = (!row.ordr || isNaN(row.ordr)) ? 0 : parseInt(row.ordr);
5767          row.lat = parseFloat(row.lat);
5768          row.lng = parseFloat(row.lng);
5769          row.logo_id = (row.logo_id && !isNaN(row.logo_id)) ? parseInt(row.logo_id) : row.logo_id;
5770  
5771          var position = new google.maps.LatLng(row.lat, row.lng);
5772  
5773          //When Open Hours
5774          row.open_hours = (row.open_hours) ? (row.open_hours) : null;
5775  
5776  
5777          if (!row.state) row.state = '';
5778  
5779          var locality = asl_engine.helper.implode([row.city, row.state, row.postal_code], ', ');
5780          var addr     = [row.street, locality];
5781  
5782          row.address       = asl_engine.helper.implode(addr, '<br>');
5783          var _categories   = row.categories ? row.categories.split(",") : [],
5784            row_categories  = [];
5785  
5786  
5787          //If categories are enabled
5788          if (show_categories) {
5789  
5790            var c_names = [];
5791            var c_ids   = [];
5792  
5793            for (var k in _categories) {
5794  
5795              var _cat_id = _categories[k].toString();
5796  
5797              if (asl_categories[_cat_id]) {
5798  
5799                asl_categories[_cat_id].len++;
5800                //Add the Features
5801                row_categories.push(asl_categories[_cat_id]);
5802                c_names.push(asl_categories[_cat_id].name);
5803                c_ids.push(asl_categories[_cat_id].id);
5804  
5805              } else
5806                delete _categories[k];
5807            }
5808  
5809  
5810            //  Sort by Category
5811            row.cat = (c_names && c_names[0])? c_names[0]: '';
5812            
5813  
5814            row.c_ids   = c_ids;
5815            row.c_names = asl_engine.helper.implode(c_names, ', ');
5816  
5817            //julie category sort by __order
5818            row.categories = row_categories;
5819          }
5820  
5821         
5822  
5823          row.city    = $.trim(row.city) /*.replace(asl_configuration.regex, '')*/ ;
5824          row.country = $.trim(row.country);
5825  
5826          if (!row.state)
5827            row.state = '';
5828  
5829  
5830          row.marker_id = (row.marker_id) ? row.marker_id.toString() : "";
5831  
5832          //  Hide the hours
5833          if(asl_configuration.hide_hours) {
5834            row.open_hours = null;
5835          }
5836          else {
5837            (asl_configuration.week_hours == '0')? getTodayHours(row): getAllHours(row);
5838          }
5839  
5840          //  Show/Hide Logo
5841          if(asl_configuration.hide_logo) {
5842            row.path = null;          
5843          }
5844  
5845          //  Description
5846          if(has_desc) {
5847            row.desc_link = has_desc_link;
5848          }
5849          else
5850            row.description = null;
5851  
5852          //  Link URL
5853          if(have_link) {
5854            row.link = (is_slug_url)? (slug_url + row.slug + '/') : row.website;
5855          }
5856  
5857          //Saving all the stores
5858          var store = new asl_locator.Store(row.id, position, _categories, row);
5859          stores.push(store);
5860        }
5861  
5862        return stores;
5863      };
5864  
5865  
5866      /*INITIALIZE THE Data Source*/
5867      var data_source = new asl_engine.dataSource();
5868  
5869      /**
5870       * [getStores Get Stores on Each Pan]
5871       * @param  {[type]}   bounds          [description]
5872       * @param  {[type]}   active_features [description]
5873       * @param  {Function} callback        [description]
5874       * @return {[type]}                   [description]
5875       */
5876      data_source.getStores = function(bounds, active_features, callback) {
5877  
5878        var that    = this,
5879            stores  = [];
5880  
5881        var func_name = (asl_configuration.and_filter)? 'hasAllCategory': 'hasAnyCategory';
5882  
5883        //  Has any Filter Active
5884        for (var i = 0, store; store = this.stores_[i]; i++) {
5885          if (store[func_name](active_features)) {
5886            stores.push(store);
5887          }
5888        }
5889  
5890        callback(stores);
5891      };
5892  
5893  
5894      /**
5895       * [findStore Find a Store Having ID]
5896       * @param  {[type]} _store_id [description]
5897       * @return {[type]}           [description]
5898       */
5899      data_source.findStore = function(_store_id) {
5900  
5901        _store_id  = parseInt(_store_id);
5902  
5903        for (var i = 0, store; store = this.stores_[i]; i++) {
5904          
5905          if(store.id_ == _store_id)
5906            return store;
5907        }
5908  
5909        return null;
5910      };
5911  
5912      /**
5913       * [getStores Get Stores on Each Pan]
5914       * @param  {[type]}   bounds          [description]
5915       * @param  {[type]}   active_features [description]
5916       * @param  {Function} callback        [description]
5917       * @param  {[type]}   _no_ajax        [description]
5918       * @return {[type]}                   [description]
5919       */
5920      data_source.allStores = function() {
5921  
5922        return this.stores_;
5923      };
5924  
5925  
5926      //  Download the Advanced Marker library first
5927      if(asl_configuration.advanced_marker) {
5928  
5929        google.maps.importLibrary("marker").then(function(){
5930  
5931            data_source.load_locator();
5932        });
5933      }
5934      //  Simple Markers
5935      else
5936        data_source.load_locator();
5937  
5938    })(jQuery);
5939  };
5940  
5941  
5942  jQuery(document).ready(asl_store_locator);

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.