WP Store Locator - Version 1.2.22

Version Description

  • Fixed compatibility issues with the Google Maps field in the Advanced Custom Fields plugin
  • Fixed the store urls in the store listings sometimes breaking
  • Removed the requirement for a zipcode on the add/edit store page
  • Improved the documentation in the js files
Download this release

Release Info

Developer tijmensmit
Plugin Icon 128x128 WP Store Locator
Version 1.2.22
Comparing to
See all releases

Code changes from version 1.2.21 to 1.2.22

admin/class-admin.php CHANGED
@@ -521,7 +521,7 @@ if ( !class_exists( 'WPSL_Admin' ) ) {
521
 
522
  $store_data = $_POST['wpsl'];
523
 
524
- if ( empty( $store_data['store'] ) || ( empty( $store_data['address'] ) ) || ( empty( $store_data['city'] ) ) || ( empty( $store_data['zip'] ) ) || ( empty( $store_data['country'] ) ) ) {
525
  add_settings_error ( 'validate-store', esc_attr( 'validate-store' ), __( 'Please fill in all the required fields.', 'wpsl' ), 'error' );
526
  } else {
527
  return $store_data;
@@ -667,7 +667,6 @@ if ( !class_exists( 'WPSL_Admin' ) ) {
667
  public function sanitize_settings() {
668
 
669
  $map_types = array( 'roadmap', 'satellite', 'hybrid', 'terrain' );
670
- $unit_values = array( 'px', '%' );
671
  $distance_units = array( 'km', 'mi' );
672
  $more_info_locations = array( 'store listings', 'info window' );
673
 
@@ -1623,18 +1622,23 @@ if ( !class_exists( 'WPSL_Admin' ) ) {
1623
  * @return void
1624
  */
1625
  public function admin_scripts() {
1626
- wp_enqueue_media();
1627
- wp_enqueue_script( 'jquery-ui-dialog' );
1628
- wp_enqueue_style( 'jquery-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css' );
1629
- wp_enqueue_style( 'wpsl-admin-css', plugins_url( '/css/style.css', __FILE__ ), false );
1630
- $this->check_icon_font_usage();
1631
- wp_enqueue_script( 'wpsl-gmap', ( "//maps.google.com/maps/api/js?sensor=false&libraries=places&language=" . $this->settings['api_language'] ), false, '', true ); // we set the language here to make sure the geocode response returns the country name in the correct language
1632
- wp_enqueue_script( 'wpsl-admin-js', plugins_url( '/js/wpsl-admin.js', __FILE__ ), array( 'jquery' ), false );
1633
- wp_enqueue_script( 'wpsl-queue', plugins_url( '/js/ajax-queue.js', __FILE__ ), array( 'jquery' ), false );
1634
- wp_enqueue_script( 'wpsl-retina', plugins_url( '/js/retina-1.1.0.js', __FILE__ ), array( 'jquery' ), false );
1635
-
1636
- wp_localize_script( 'wpsl-admin-js', 'wpslL10n', $this->admin_js_l10n() );
1637
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1638
  }
1639
  }
1640
 
521
 
522
  $store_data = $_POST['wpsl'];
523
 
524
+ if ( empty( $store_data['store'] ) || ( empty( $store_data['address'] ) ) || ( empty( $store_data['city'] ) ) || ( empty( $store_data['country'] ) ) ) {
525
  add_settings_error ( 'validate-store', esc_attr( 'validate-store' ), __( 'Please fill in all the required fields.', 'wpsl' ), 'error' );
526
  } else {
527
  return $store_data;
667
  public function sanitize_settings() {
668
 
669
  $map_types = array( 'roadmap', 'satellite', 'hybrid', 'terrain' );
 
670
  $distance_units = array( 'km', 'mi' );
671
  $more_info_locations = array( 'store listings', 'info window' );
672
 
1622
  * @return void
1623
  */
1624
  public function admin_scripts() {
 
 
 
 
 
 
 
 
 
 
 
1625
 
1626
+ $screen = get_current_screen();
1627
+
1628
+ /* Only enqueue the styles and scripts if we are on a page that belongs to the store locator */
1629
+ if ( strpos( $screen->id, 'wpsl_' ) !== false ) {
1630
+ wp_enqueue_media();
1631
+ wp_enqueue_script( 'jquery-ui-dialog' );
1632
+ wp_enqueue_style( 'jquery-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css' );
1633
+ wp_enqueue_style( 'wpsl-admin-css', plugins_url( '/css/style.css', __FILE__ ), false );
1634
+ wp_enqueue_script( 'wpsl-gmap', ( "//maps.google.com/maps/api/js?sensor=false&libraries=places&language=" . $this->settings['api_language'] ), false, '', true ); // we set the language here to make sure the geocode response returns the country name in the correct language
1635
+ wp_enqueue_script( 'wpsl-admin-js', plugins_url( '/js/wpsl-admin.js', __FILE__ ), array( 'jquery' ), false );
1636
+ wp_enqueue_script( 'wpsl-queue', plugins_url( '/js/ajax-queue.js', __FILE__ ), array( 'jquery' ), false );
1637
+ wp_enqueue_script( 'wpsl-retina', plugins_url( '/js/retina-1.1.0.js', __FILE__ ), array( 'jquery' ), false );
1638
+ wp_localize_script( 'wpsl-admin-js', 'wpslL10n', $this->admin_js_l10n() );
1639
+ }
1640
+
1641
+ $this->check_icon_font_usage();
1642
  }
1643
  }
1644
 
admin/js/wpsl-admin.js CHANGED
@@ -2,7 +2,12 @@ jQuery( document ).ready( function( $ ) {
2
  var map, geocoder, uploadFrame,
3
  markersArray = [];
4
 
5
- /* Load the Google Maps */
 
 
 
 
 
6
  function initializeGmap() {
7
  var myOptions = {
8
  zoom: 2,
@@ -17,7 +22,12 @@ function initializeGmap() {
17
  checkEditStoreMarker();
18
  }
19
 
20
- /* If we have an existing latln value, add a marker to the map. This can only happen on the edit store page */
 
 
 
 
 
21
  function checkEditStoreMarker() {
22
  var location,
23
  lat = $( "#wpsl-store-lat" ).val(),
@@ -37,7 +47,12 @@ if ( $( "#wpsl-zoom-name" ).length ) {
37
  activateAutoComplete();
38
  }
39
 
40
- /* Activate the autocomplete function for the city/country field */
 
 
 
 
 
41
  function activateAutoComplete() {
42
  var latlng,
43
  input = document.getElementById( "wpsl-zoom-name" ),
@@ -52,7 +67,13 @@ function activateAutoComplete() {
52
  });
53
  }
54
 
55
- /* Add a new marker to the map based on the provided location (latlng) */
 
 
 
 
 
 
56
  function addMarker( location ) {
57
  var marker = new google.maps.Marker({
58
  position: location,
@@ -67,7 +88,13 @@ function addMarker( location ) {
67
  });
68
  }
69
 
70
- /* Lookup the location where the marker is dropped */
 
 
 
 
 
 
71
  function geocodeDraggedPosition( pos ) {
72
  geocoder.geocode({
73
  latLng: pos
@@ -86,17 +113,21 @@ $( "#wpsl-lookup-location" ).on( "click", function() {
86
  return false;
87
  });
88
 
89
- /* Geocode the user input */
 
 
 
 
 
90
  function codeAddress() {
91
  var filteredResponse,
92
- address = $( "#wpsl-store-address" ).val(),
93
- city = $( "#wpsl-store-city" ).val(),
94
- zip = $( "#wpsl-store-zip" ).val(),
95
- country = $( "#wpsl-store-country" ).val(),
96
- fullAddress = address + ',' + city + ',' + zip + ',' + country;
97
 
98
  /* Check we have all the requird data before attempting to geocode the address */
99
- if ( !validatePreviewFields( address, city, zip, country ) ) {
100
  geocoder.geocode( { 'address': fullAddress }, function( response, status ) {
101
  if ( status === google.maps.GeocoderStatus.OK ) {
102
 
@@ -124,8 +155,16 @@ function codeAddress() {
124
  }
125
  }
126
 
127
- /* Check that all required fields for the preview to work are there */
128
- function validatePreviewFields( address, city, zip, country ) {
 
 
 
 
 
 
 
 
129
  var error = false;
130
 
131
  $( "#wpsl-wrap input" ).removeClass( "wpsl-error" );
@@ -139,12 +178,7 @@ function validatePreviewFields( address, city, zip, country ) {
139
  $( "#wpsl-store-city" ).addClass( "wpsl-error" );
140
  error = true;
141
  }
142
-
143
- if ( !zip ) {
144
- $( "#wpsl-store-zip" ).addClass( "wpsl-error" );
145
- error = true;
146
- }
147
-
148
  if ( !country ) {
149
  $( "#wpsl-store-country" ).addClass( "wpsl-error" );
150
  error = true;
2
  var map, geocoder, uploadFrame,
3
  markersArray = [];
4
 
5
+ /**
6
+ * Initialize the map with the correct settings
7
+ *
8
+ * @since 1.0
9
+ * @returns {void}
10
+ */
11
  function initializeGmap() {
12
  var myOptions = {
13
  zoom: 2,
22
  checkEditStoreMarker();
23
  }
24
 
25
+ /**
26
+ * If we have an existing latlng value, add a marker to the map. This can only happen on the edit store page
27
+ *
28
+ * @since 1.0
29
+ * @returns {void}
30
+ */
31
  function checkEditStoreMarker() {
32
  var location,
33
  lat = $( "#wpsl-store-lat" ).val(),
47
  activateAutoComplete();
48
  }
49
 
50
+ /**
51
+ * Activate the autocomplete function for the city/country field
52
+ *
53
+ * @since 1.0
54
+ * @returns {void}
55
+ */
56
  function activateAutoComplete() {
57
  var latlng,
58
  input = document.getElementById( "wpsl-zoom-name" ),
67
  });
68
  }
69
 
70
+ /**
71
+ * Add a new marker to the map based on the provided location (latlng)
72
+ *
73
+ * @since 1.0
74
+ * @param {object} location The latlng value
75
+ * @returns {void}
76
+ */
77
  function addMarker( location ) {
78
  var marker = new google.maps.Marker({
79
  position: location,
88
  });
89
  }
90
 
91
+ /**
92
+ * Lookup the location where the marker is dropped
93
+ *
94
+ * @since 1.0
95
+ * @param {object} pos The latlng value
96
+ * @returns {void}
97
+ */
98
  function geocodeDraggedPosition( pos ) {
99
  geocoder.geocode({
100
  latLng: pos
113
  return false;
114
  });
115
 
116
+ /**
117
+ * Geocode the user input
118
+ *
119
+ * @since 1.0
120
+ * @returns {void}
121
+ */
122
  function codeAddress() {
123
  var filteredResponse,
124
+ address = $( "#wpsl-store-address" ).val(),
125
+ city = $( "#wpsl-store-city" ).val(),
126
+ country = $( "#wpsl-store-country" ).val(),
127
+ fullAddress = address + ',' + city + ',' + country;
 
128
 
129
  /* Check we have all the requird data before attempting to geocode the address */
130
+ if ( !validatePreviewFields( address, city, country ) ) {
131
  geocoder.geocode( { 'address': fullAddress }, function( response, status ) {
132
  if ( status === google.maps.GeocoderStatus.OK ) {
133
 
155
  }
156
  }
157
 
158
+ /**
159
+ * Check that all required fields for the preview to work are there
160
+ *
161
+ * @since 1.0
162
+ * @param {string} address The store address
163
+ * @param {string} city The store city
164
+ * @param {string} country The store country
165
+ * @returns {boolean} error Whether a field validated or not
166
+ */
167
+ function validatePreviewFields( address, city, country ) {
168
  var error = false;
169
 
170
  $( "#wpsl-wrap input" ).removeClass( "wpsl-error" );
178
  $( "#wpsl-store-city" ).addClass( "wpsl-error" );
179
  error = true;
180
  }
181
+
 
 
 
 
 
182
  if ( !country ) {
183
  $( "#wpsl-store-country" ).addClass( "wpsl-error" );
184
  error = true;
admin/templates/add-store.php CHANGED
@@ -34,7 +34,7 @@
34
  </p>
35
  <p>
36
  <label for="wpsl-store-zip"><?php _e( 'Zip Code:', 'wpsl' ); ?></label>
37
- <input id="wpsl-store-zip" name="wpsl[zip]" type="text" class="textinput <?php if ( isset( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( stripslashes( $_POST['wpsl']['zip'] ) ); } ?>" />
38
  </p>
39
  <p>
40
  <label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
34
  </p>
35
  <p>
36
  <label for="wpsl-store-zip"><?php _e( 'Zip Code:', 'wpsl' ); ?></label>
37
+ <input id="wpsl-store-zip" name="wpsl[zip]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( stripslashes( $_POST['wpsl']['zip'] ) ); } ?>" />
38
  </p>
39
  <p>
40
  <label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
admin/templates/edit-store.php CHANGED
@@ -53,7 +53,7 @@ if ( $store_id ) {
53
  </p>
54
  <p>
55
  <label for="wpsl-store-zip"><?php _e( 'Zip Code:', 'wpsl' ); ?></label>
56
- <input id="wpsl-store-zip" name="wpsl[zip]" type="text" class="textinput <?php if ( isset( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( isset( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( stripslashes( $_POST['wpsl']['zip'] ) ); } else { echo esc_attr( stripslashes( $store_details['zip'] ) ); } ?>" />
57
  </p>
58
  <p>
59
  <label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
53
  </p>
54
  <p>
55
  <label for="wpsl-store-zip"><?php _e( 'Zip Code:', 'wpsl' ); ?></label>
56
+ <input id="wpsl-store-zip" name="wpsl[zip]" type="text" class="textinput" value="<?php if ( isset( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( stripslashes( $_POST['wpsl']['zip'] ) ); } else { echo esc_attr( stripslashes( $store_details['zip'] ) ); } ?>" />
57
  </p>
58
  <p>
59
  <label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
js/wpsl-gmap.js CHANGED
@@ -11,14 +11,18 @@ var geocoder, map, infoWindow, directionsDisplay, directionsService, geolocation
11
  autoLoad = wpslSettings.autoLoad,
12
  $selects = $( "#wpsl-search-wrap select" );
13
 
14
- /* Initialize the map with the correct settings */
 
 
 
 
 
15
  function initializeGmap() {
16
- var myOptions, zoomControlPosition, zoomControlStyle,
17
- latLng, zoomLevel, mapType,
18
  streetViewVisible = ( wpslSettings.streetView == 1 ) ? true : false;
19
 
20
  /* If no zoom location is defined, we show the entire world */
21
- if ( wpslSettings.zoomLatlng !== '' ) {
22
  latLng = wpslSettings.zoomLatlng.split( ',' );
23
  startLatLng = new google.maps.LatLng( latLng[0], latLng[1] );
24
  zoomLevel = parseInt( wpslSettings.zoomLevel );
@@ -90,7 +94,7 @@ function initializeGmap() {
90
  });
91
  } else {
92
  $( "#wpsl-search-wrap select").show();
93
- $( "#wpsl-wrap" ).addClass( 'wpsl-mobile' );
94
  }
95
 
96
  /* Check if we need to try and autolocate the user */
@@ -108,6 +112,12 @@ function initializeGmap() {
108
  }
109
  }
110
 
 
 
 
 
 
 
111
  function showStores() {
112
  var startMarker = {
113
  store: wpslLabels.startPoint
@@ -127,8 +137,13 @@ function checkMobileUserAgent() {
127
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent );
128
  }
129
 
130
- /* Check if Geolocation detection is supported. If there is an error / timeout with determining the users
 
 
131
  * location we use the 'start point' value from the settings as the start location through the showStores function.
 
 
 
132
  */
133
  function checkGeolocation() {
134
  if ( navigator.geolocation ) {
@@ -152,7 +167,18 @@ function checkGeolocation() {
152
  }
153
  };
154
 
 
 
 
 
 
 
 
 
 
 
155
  function handleGeolocationQuery( position, resetMap ) {
 
156
  if ( typeof( position ) === "undefined" ) {
157
  showStores();
158
  } else {
@@ -176,7 +202,7 @@ $( "#wpsl-search-btn" ).on( "click", function() {
176
  $( "#wpsl-search-input" ).removeClass();
177
 
178
  if ( !$( "#wpsl-search-input" ).val() ) {
179
- $( "#wpsl-search-input" ).addClass( 'wpsl-error' ).focus();
180
  } else {
181
  $( "#wpsl-result-list ul" ).empty();
182
  $( "#wpsl-stores" ).show();
@@ -189,7 +215,7 @@ $( "#wpsl-search-btn" ).on( "click", function() {
189
  }
190
  });
191
 
192
- /* Reset the map */
193
  $( "#wpsl-reset-map" ).on( "click", function() {
194
  var keepStartMarker = false,
195
  resetMap = true;
@@ -204,7 +230,7 @@ $( "#wpsl-reset-map" ).on( "click", function() {
204
  /* Check if the latlng or zoom has changed since pageload, if so there is something to reset */
205
  if ( ( ( ( map.getCenter().lat() !== mapDefaults.centerLatlng.lat() ) || ( map.getCenter().lng() !== mapDefaults.centerLatlng.lng() ) || ( map.getZoom() !== mapDefaults.zoomLevel ) ) ) ) {
206
  deleteOverlays( keepStartMarker );
207
- $( "#wpsl-search-input" ).val('').removeClass();
208
 
209
  /* If marker clusters exist, remove them from the map */
210
  if ( markerClusterer ) {
@@ -224,19 +250,28 @@ $( "#wpsl-reset-map" ).on( "click", function() {
224
  }
225
  }
226
 
 
227
  $( "#wpsl-stores" ).show();
228
  $( "#wpsl-direction-details" ).hide();
229
  });
230
 
231
- /* Remove the start marker from the map and empty the var */
 
 
 
 
232
  function deleteStartMarker() {
233
- if ( ( typeof( startMarkerData ) !== "undefined" ) && ( startMarkerData !== "" ) ) {
234
  startMarkerData.setMap( null );
235
- startMarkerData = '';
236
  }
237
  }
238
 
239
- /* Reset the dropdown values after the "reset" button is triggerd */
 
 
 
 
240
  function resetDropdowns() {
241
  var i, arrayLength,
242
  defaultValues = [wpslSettings.searchRadius + ' ' + wpslSettings.distanceUnit, wpslSettings.maxResults],
@@ -248,7 +283,7 @@ function resetDropdowns() {
248
 
249
  $( "#" + dropdowns[i] + " li" ).each( function () {
250
  if ( $( this ).text() === defaultValues[i] ) {
251
- $( this ).addClass('active');
252
  }
253
  });
254
  }
@@ -286,9 +321,15 @@ $( "#wpsl-result-list" ).on( "click", ".wpsl-back", function() {
286
  return false;
287
  });
288
 
 
 
 
 
 
 
289
  function renderDirections( e ) {
290
  var i, start, end, len, storeId;
291
-
292
  /*
293
  The storeId is placed on the li in the results list,
294
  but in the marker it will be on the wrapper div. So we check which one we need to target.
@@ -341,9 +382,15 @@ if ( wpslSettings.markerBounce == 1 ) {
341
  });
342
  }
343
 
344
- /* Let a single marker bounce */
 
 
 
 
 
 
345
  function letsBounce( storeId, status ) {
346
- var i, len, animation = '';
347
 
348
  if ( status == "start" ) {
349
  animation = google.maps.Animation.BOUNCE
@@ -360,13 +407,19 @@ function letsBounce( storeId, status ) {
360
  }
361
  }
362
 
363
- /* Show the directions on the map */
 
 
 
 
 
 
364
  function calcRoute( start, end ) {
365
  var legs, len, step, index, direction, i, j, distanceUnit, directionOffset,
366
  directionStops = "",
367
  request = {};
368
 
369
- if ( wpslSettings.distanceUnit == 'km' ) {
370
  distanceUnit = google.maps.UnitSystem.METRIC
371
  } else {
372
  distanceUnit = google.maps.UnitSystem.IMPERIAL
@@ -430,7 +483,11 @@ function calcRoute( start, end ) {
430
  });
431
  }
432
 
433
- /* Geocode the user input */
 
 
 
 
434
  function codeAddress() {
435
  var latLng,
436
  autoLoad = false,
@@ -450,13 +507,18 @@ function codeAddress() {
450
  } else {
451
  geocodeErrors( status );
452
  }
453
- }
454
- )};
455
 
456
- /* Geocode the user input and set the returned zipcode in the input field */
 
 
 
 
 
457
  function reverseGeocode( latLng ) {
458
  var zipCode;
459
-
460
  geocoder.geocode( {'latLng': latLng}, function( response, status ) {
461
  if ( status == google.maps.GeocoderStatus.OK ) {
462
  zipCode = filterApiResponse( response );
@@ -470,7 +532,12 @@ function reverseGeocode( latLng ) {
470
  });
471
  }
472
 
473
- /* Filter out the zipcode from the response */
 
 
 
 
 
474
  function filterApiResponse( response ) {
475
  var zipcode, responseType, i,
476
  addressLength = response[0].address_components.length;
@@ -488,8 +555,16 @@ function filterApiResponse( response ) {
488
  return zipcode;
489
  }
490
 
 
 
 
 
 
 
 
 
 
491
  function findStoreLocations( startLatLng, resetMap, autoLoad ) {
492
-
493
  /* Check if we need to open a new window and show the route on the Google Maps site itself. */
494
  if ( wpslSettings.directionRedirect == 1 ) {
495
  findFormattedAddress( startLatLng, function() {
@@ -500,7 +575,12 @@ function findStoreLocations( startLatLng, resetMap, autoLoad ) {
500
  }
501
  }
502
 
503
- /* The formatted address is used to build the url for the driving direction and send the user to maps.google.com */
 
 
 
 
 
504
  function findFormattedAddress( latLng, callback ) {
505
  geocoder.geocode( {'latLng': latLng}, function( response, status ) {
506
  if ( status == google.maps.GeocoderStatus.OK ) {
@@ -512,6 +592,14 @@ function findFormattedAddress( latLng, callback ) {
512
  });
513
  }
514
 
 
 
 
 
 
 
 
 
515
  function makeAjaxRequest( startLatLng, resetMap, autoLoad ) {
516
  var latLng,
517
  infoWindowData = {},
@@ -655,7 +743,16 @@ function checkMarkerClusters() {
655
  }
656
  }
657
 
658
- /* Add a new marker to the map based on the provided location (latlng) */
 
 
 
 
 
 
 
 
 
659
  function addMarker( latLng, storeId, infoWindowData, draggable ) {
660
  var markerPath, mapIcon, marker,
661
  keepStartMarker = true;
@@ -791,7 +888,7 @@ function activateStreetView( marker ) {
791
  * info at tijmensmit.com
792
  *
793
  * @since 1.2.20
794
- * @param {object} marker The current marker
795
  * @returns {void}
796
  */
797
  function StreetViewListener( panorama ) {
@@ -824,7 +921,15 @@ function checkStreetViewStatus( latLng, callback ) {
824
  });
825
  }
826
 
827
- /* Create the data for the infowindows on Google Maps */
 
 
 
 
 
 
 
 
828
  function createInfoWindowHtml( infoWindowData, storeId, streetViewAvailable ) {
829
  var storeHeader, url,
830
  address2 = "",
@@ -925,6 +1030,13 @@ function formatClickablePhoneNumber( phoneNumber ) {
925
  return phoneNumber.replace( /(-| |\(|\)|\.|)/g, '' );
926
  }
927
 
 
 
 
 
 
 
 
928
  function createMoreInfoListing( storeData ) {
929
  var newWindow = "",
930
  moreInfoContent = "<div id='wpsl-id-" + storeData.id + "' class='wpsl-more-info-listings'>";
@@ -953,7 +1065,7 @@ function createMoreInfoListing( storeData ) {
953
  newWindow = "target='_blank'";
954
  }
955
 
956
- moreInfoContent += "<span><strong>Url</strong>: <a " + newWindow + " href=" + storeData.url + ">" + storeData.url + "</a></span>";
957
  }
958
 
959
  moreInfoContent += "</p>";
@@ -1009,6 +1121,14 @@ function rfc3986EncodeURIComponent( str ) {
1009
  return encodeURIComponent( str ).replace( /[!'()*]/g, escape );
1010
  }
1011
 
 
 
 
 
 
 
 
 
1012
  function storeHtml( response, url ) {
1013
  var html = "",
1014
  moreInfoData,
@@ -1027,68 +1147,73 @@ function storeHtml( response, url ) {
1027
  country = response.country,
1028
  distance = parseFloat( response.distance ).toFixed(1) + " " + wpslSettings.distanceUnit;
1029
 
1030
- if ( ( typeof( thumb ) !== "undefined" ) && ( thumb !== "" ) ) {
1031
- storeImg = "<img class='wpsl-store-thumb' src='" + thumb + "' width='48' height='48' alt='" + store + "' />";
1032
- }
1033
-
1034
- /* Check if we need to create an url that sends the user to maps.google.com for driving directions */
1035
- if ( wpslSettings.directionRedirect == 1 ) {
1036
- url = createDirectionUrl( address, city, zip, country );
 
 
 
 
 
 
 
 
 
 
1037
  }
1038
-
1039
- /* Check if we need to show the 'more info' link in the store listings */
1040
- if ( wpslSettings.moreInfo == 1 ) {
1041
-
1042
- /* If we show the store listings under the map, we do want to jump to the
1043
- * top of the map to focus on the opened infowindow
1044
- */
1045
- if ( ( wpslSettings.templateId == 1 ) && ( wpslSettings.moreInfoLocation == 'info window' ) ) {
1046
- moreInfoUrl = '#wpsl-search-wrap';
1047
- }
1048
-
1049
- /* Do we need to show the 'more info' data under the store details,
1050
- * or should we only add a link which will trigger the infowindow?
1051
- */
1052
- if ( wpslSettings.moreInfoLocation == "store listings" ) {
1053
-
1054
- /* Only create the 'more info' link if there is data to show */
1055
- if ( ( ( typeof( response.description ) !== "undefined" ) && ( response.description !== "" ) ) ||
1056
- ( ( typeof( response.phone ) !== "undefined" ) && ( response.phone !== "" ) ) ||
1057
- ( ( typeof( response.fax ) !== "undefined" ) && ( response.fax !== "" ) ) ||
1058
- ( ( typeof( response.email ) !== "undefined" ) && ( response.email !== "" ) ) ||
1059
- ( ( typeof( response.hours ) !== "undefined" ) && ( response.hours !== "" ) ) ) {
1060
- moreInfoData = createMoreInfoListing( response );
1061
- moreInfo = "<p><a class='wpsl-store-details wpsl-store-listing' href=" + moreInfoUrl + "wpsl-id-" + id + ">" + wpslLabels.moreInfo + "</a>" + moreInfoData + "</p>";
1062
- }
1063
- } else {
1064
- moreInfo = "<p><a class='wpsl-store-details' href=" + moreInfoUrl + ">" + wpslLabels.moreInfo + "</a></p>";
1065
  }
 
 
1066
  }
1067
-
1068
- /* Check if we need to make the store name clickable */
1069
- if ( wpslSettings.storeUrl == 1) {
1070
- if ( ( typeof( response.url ) !== "undefined" ) && ( response.url !== "" ) ) {
1071
-
1072
- /* Do we need to open the url in a new window? */
1073
- if ( wpslSettings.newWindow == 1 ) {
1074
- storeUrlTarget = "target='_blank'";
1075
- }
1076
-
1077
- store = "<a " + storeUrlTarget + " href=" + response.url + ">" + store + "</a>";
1078
  }
 
 
1079
  }
1080
-
1081
- /* If we have a second address line, we add it */
1082
- if ( ( typeof( response.address2 ) !== "undefined" ) && ( response.address2 !== "" ) ) {
1083
- address2 = "<span class='wpsl-street'>" + response.address2 + "</span>";
1084
- }
 
1085
 
1086
- html = "<li data-store-id='" + id + "'><div><p>" + storeImg + "<strong>" + store + "</strong><span class='wpsl-street'>" + address + "</span>" + address2 + city + " " + state + " " + zip + "<span class='wpsl-country'>" + country + "</p>" + moreInfo + "</div>" + distance + "<a class='wpsl-directions' " + url.target + " href='" + url.src + "'>" + wpslLabels.directions + "</a></li>";
1087
 
1088
  return html;
1089
  }
1090
 
1091
- /* Zoom the map so that all markers fit in the window */
 
 
 
 
 
1092
  function fitBounds() {
1093
  var i, markerLen,
1094
  maxZoom = 12,
@@ -1108,7 +1233,13 @@ function fitBounds() {
1108
  map.fitBounds( bounds );
1109
  }
1110
 
1111
- /* Remove all existing markers and route lines from the map */
 
 
 
 
 
 
1112
  function deleteOverlays( keepStartMarker ) {
1113
  var markerLen, i;
1114
  directionsDisplay.setMap( null );
11
  autoLoad = wpslSettings.autoLoad,
12
  $selects = $( "#wpsl-search-wrap select" );
13
 
14
+ /**
15
+ * Initialize the map with the correct settings
16
+ *
17
+ * @since 1.0
18
+ * @returns {void}
19
+ */
20
  function initializeGmap() {
21
+ var myOptions, zoomControlPosition, zoomControlStyle, latLng, zoomLevel, mapType,
 
22
  streetViewVisible = ( wpslSettings.streetView == 1 ) ? true : false;
23
 
24
  /* If no zoom location is defined, we show the entire world */
25
+ if ( wpslSettings.zoomLatlng !== "" ) {
26
  latLng = wpslSettings.zoomLatlng.split( ',' );
27
  startLatLng = new google.maps.LatLng( latLng[0], latLng[1] );
28
  zoomLevel = parseInt( wpslSettings.zoomLevel );
94
  });
95
  } else {
96
  $( "#wpsl-search-wrap select").show();
97
+ $( "#wpsl-wrap" ).addClass( "wpsl-mobile" );
98
  }
99
 
100
  /* Check if we need to try and autolocate the user */
112
  }
113
  }
114
 
115
+ /**
116
+ * Add the start marker and call the function that inits the store search
117
+ *
118
+ * @since 1.1
119
+ * @returns {void}
120
+ */
121
  function showStores() {
122
  var startMarker = {
123
  store: wpslLabels.startPoint
137
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent );
138
  }
139
 
140
+ /* Check if Geolocation detection is supported.
141
+ *
142
+ * If there is an error / timeout with determining the users
143
  * location we use the 'start point' value from the settings as the start location through the showStores function.
144
+ *
145
+ * @since 1.0
146
+ * @returns {void}
147
  */
148
  function checkGeolocation() {
149
  if ( navigator.geolocation ) {
167
  }
168
  };
169
 
170
+ /* Check if Geolocation detection is supported.
171
+ *
172
+ * If there is an error / timeout determining the users location,
173
+ * then we use the 'start point' value from the settings as the start location through the showStores function.
174
+ *
175
+ * @since 1.0
176
+ * @param {object} position The latlng coordinates
177
+ * @param {boolean} resetMap Whether we should reset the map or not
178
+ * @returns {void}
179
+ */
180
  function handleGeolocationQuery( position, resetMap ) {
181
+
182
  if ( typeof( position ) === "undefined" ) {
183
  showStores();
184
  } else {
202
  $( "#wpsl-search-input" ).removeClass();
203
 
204
  if ( !$( "#wpsl-search-input" ).val() ) {
205
+ $( "#wpsl-search-input" ).addClass( "wpsl-error" ).focus();
206
  } else {
207
  $( "#wpsl-result-list ul" ).empty();
208
  $( "#wpsl-stores" ).show();
215
  }
216
  });
217
 
218
+ /* Handle clicks on the "Reset" button */
219
  $( "#wpsl-reset-map" ).on( "click", function() {
220
  var keepStartMarker = false,
221
  resetMap = true;
230
  /* Check if the latlng or zoom has changed since pageload, if so there is something to reset */
231
  if ( ( ( ( map.getCenter().lat() !== mapDefaults.centerLatlng.lat() ) || ( map.getCenter().lng() !== mapDefaults.centerLatlng.lng() ) || ( map.getZoom() !== mapDefaults.zoomLevel ) ) ) ) {
232
  deleteOverlays( keepStartMarker );
233
+ $( "#wpsl-search-input" ).val("").removeClass();
234
 
235
  /* If marker clusters exist, remove them from the map */
236
  if ( markerClusterer ) {
250
  }
251
  }
252
 
253
+ /* Make sure the stores are shown and the direction details are hidden */
254
  $( "#wpsl-stores" ).show();
255
  $( "#wpsl-direction-details" ).hide();
256
  });
257
 
258
+ /* Remove the start marker from the map
259
+ *
260
+ * @since 1.2.12
261
+ * @returns {void}
262
+ */
263
  function deleteStartMarker() {
264
+ if ( ( typeof( startMarkerData ) !== "undefined" ) && ( startMarkerData !== "" ) ) {
265
  startMarkerData.setMap( null );
266
+ startMarkerData = "";
267
  }
268
  }
269
 
270
+ /* Reset the dropdown values after the "reset" button is triggerd
271
+ *
272
+ * @since 1.1
273
+ * @returns {void}
274
+ */
275
  function resetDropdowns() {
276
  var i, arrayLength,
277
  defaultValues = [wpslSettings.searchRadius + ' ' + wpslSettings.distanceUnit, wpslSettings.maxResults],
283
 
284
  $( "#" + dropdowns[i] + " li" ).each( function () {
285
  if ( $( this ).text() === defaultValues[i] ) {
286
+ $( this ).addClass( "active" );
287
  }
288
  });
289
  }
321
  return false;
322
  });
323
 
324
+ /* Show the driving directions
325
+ *
326
+ * @since 1.1
327
+ * @param {object} e The clicked elemennt
328
+ * @returns {void}
329
+ */
330
  function renderDirections( e ) {
331
  var i, start, end, len, storeId;
332
+
333
  /*
334
  The storeId is placed on the li in the results list,
335
  but in the marker it will be on the wrapper div. So we check which one we need to target.
382
  });
383
  }
384
 
385
+ /* Let a single marker bounce
386
+ *
387
+ * @since 1.0
388
+ * @param {number} storeId The storeId of the marker that we need to bounce on the map
389
+ * @param {string} status Indicates whether we should stop or start the bouncing
390
+ * @returns {void}
391
+ */
392
  function letsBounce( storeId, status ) {
393
+ var i, len, animation = "";
394
 
395
  if ( status == "start" ) {
396
  animation = google.maps.Animation.BOUNCE
407
  }
408
  }
409
 
410
+ /* Calculate the route from the start to the end
411
+ *
412
+ * @since 1.0
413
+ * @param {object} start The latlng from the start point
414
+ * @param {object} end The latlng from the end point
415
+ * @returns {void}
416
+ */
417
  function calcRoute( start, end ) {
418
  var legs, len, step, index, direction, i, j, distanceUnit, directionOffset,
419
  directionStops = "",
420
  request = {};
421
 
422
+ if ( wpslSettings.distanceUnit == "km" ) {
423
  distanceUnit = google.maps.UnitSystem.METRIC
424
  } else {
425
  distanceUnit = google.maps.UnitSystem.IMPERIAL
483
  });
484
  }
485
 
486
+ /* Geocode the user input
487
+ *
488
+ * @since 1.0
489
+ * @returns {void}
490
+ */
491
  function codeAddress() {
492
  var latLng,
493
  autoLoad = false,
507
  } else {
508
  geocodeErrors( status );
509
  }
510
+ });
511
+ }
512
 
513
+ /* Geocode the user input and set the returned zipcode in the input field
514
+ *
515
+ * @since 1.0
516
+ * @param {object} latlng The coordinates of the location that should be reverse geocoded
517
+ * @returns {void}
518
+ */
519
  function reverseGeocode( latLng ) {
520
  var zipCode;
521
+
522
  geocoder.geocode( {'latLng': latLng}, function( response, status ) {
523
  if ( status == google.maps.GeocoderStatus.OK ) {
524
  zipCode = filterApiResponse( response );
532
  });
533
  }
534
 
535
+ /* Filter out the zipcode from the response
536
+ *
537
+ * @since 1.0
538
+ * @param {object} response The complete Google API response
539
+ * @returns {string} zipcode The zipcode
540
+ */
541
  function filterApiResponse( response ) {
542
  var zipcode, responseType, i,
543
  addressLength = response[0].address_components.length;
555
  return zipcode;
556
  }
557
 
558
+ /* Call the function to make the ajax request. But if we need to show the driving directions
559
+ * on maps.google.com itself, we first need to geocode the start latlng into a formatted address.
560
+ *
561
+ * @since 1.0
562
+ * @param {object} startLatLng The latlng used as the starting point
563
+ * @param {boolean} resetMap Whether we should reset the map or not
564
+ * @param {string} autoLoad Check if we need to autoload all the stores
565
+ * @returns {void}
566
+ */
567
  function findStoreLocations( startLatLng, resetMap, autoLoad ) {
 
568
  /* Check if we need to open a new window and show the route on the Google Maps site itself. */
569
  if ( wpslSettings.directionRedirect == 1 ) {
570
  findFormattedAddress( startLatLng, function() {
575
  }
576
  }
577
 
578
+ /* Convert the latlng into a formatted address
579
+ *
580
+ * @since 1.0
581
+ * @param {object} latlng The latlng to geocode
582
+ * @returns {void}
583
+ */
584
  function findFormattedAddress( latLng, callback ) {
585
  geocoder.geocode( {'latLng': latLng}, function( response, status ) {
586
  if ( status == google.maps.GeocoderStatus.OK ) {
592
  });
593
  }
594
 
595
+ /* Make the Ajax request to load the store data
596
+ *
597
+ * @since 1.2
598
+ * @param {object} startLatLng The latlng used as the starting point
599
+ * @param {boolean} resetMap Whether we should reset the map or not
600
+ * @param {string} autoLoad Check if we need to autoload all the stores
601
+ * @returns {void}
602
+ */
603
  function makeAjaxRequest( startLatLng, resetMap, autoLoad ) {
604
  var latLng,
605
  infoWindowData = {},
743
  }
744
  }
745
 
746
+ /**
747
+ * Add a new marker to the map based on the provided location (latlng)
748
+ *
749
+ * @since 1.0
750
+ * @param {object} latLng
751
+ * @param {number} storeId
752
+ * @param {object} infoWindowData
753
+ * @param {boolean} draggable
754
+ * @return {void}
755
+ */
756
  function addMarker( latLng, storeId, infoWindowData, draggable ) {
757
  var markerPath, mapIcon, marker,
758
  keepStartMarker = true;
888
  * info at tijmensmit.com
889
  *
890
  * @since 1.2.20
891
+ * @param {object} panorama The streetview object
892
  * @returns {void}
893
  */
894
  function StreetViewListener( panorama ) {
921
  });
922
  }
923
 
924
+ /**
925
+ * Create the data for the infowindows on Google Maps
926
+ *
927
+ * @since 1.0
928
+ * @param {object} infoWindowData The data that is shown in the infowindow (address, url, phone etc)
929
+ * @param {number} storeId The ID of the store
930
+ * @param {boolean} streetViewAvailable Indicates whether or not we should show the streetview link
931
+ * @returns {string} windowContent The html content that is placed in the infowindow
932
+ */
933
  function createInfoWindowHtml( infoWindowData, storeId, streetViewAvailable ) {
934
  var storeHeader, url,
935
  address2 = "",
1030
  return phoneNumber.replace( /(-| |\(|\)|\.|)/g, '' );
1031
  }
1032
 
1033
+ /**
1034
+ * Create the html for the more info data
1035
+ *
1036
+ * @since 1.2.12
1037
+ * @param {object} storeData The store details shown in the more info section
1038
+ * @returns {string} moreInfoContent The html that is used to show the more info content
1039
+ */
1040
  function createMoreInfoListing( storeData ) {
1041
  var newWindow = "",
1042
  moreInfoContent = "<div id='wpsl-id-" + storeData.id + "' class='wpsl-more-info-listings'>";
1065
  newWindow = "target='_blank'";
1066
  }
1067
 
1068
+ moreInfoContent += "<span><strong>Url</strong>: <a " + newWindow + " href='" + storeData.url + "'>" + storeData.url + "</a></span>";
1069
  }
1070
 
1071
  moreInfoContent += "</p>";
1121
  return encodeURIComponent( str ).replace( /[!'()*]/g, escape );
1122
  }
1123
 
1124
+ /**
1125
+ * Create the html for the <li> elem in the store listing
1126
+ *
1127
+ * @since 1.0
1128
+ * @param {object} response The store details shown in the more info section
1129
+ * @param {object} url The directions url
1130
+ * @returns {string} html The html with the store details
1131
+ */
1132
  function storeHtml( response, url ) {
1133
  var html = "",
1134
  moreInfoData,
1147
  country = response.country,
1148
  distance = parseFloat( response.distance ).toFixed(1) + " " + wpslSettings.distanceUnit;
1149
 
1150
+ if ( ( typeof( thumb ) !== "undefined" ) && ( thumb !== "" ) ) {
1151
+ storeImg = "<img class='wpsl-store-thumb' src='" + thumb + "' width='48' height='48' alt='" + store + "' />";
1152
+ }
1153
+
1154
+ /* Check if we need to create an url that sends the user to maps.google.com for driving directions */
1155
+ if ( wpslSettings.directionRedirect == 1 ) {
1156
+ url = createDirectionUrl( address, city, zip, country );
1157
+ }
1158
+
1159
+ /* Check if we need to show the 'more info' link in the store listings */
1160
+ if ( wpslSettings.moreInfo == 1 ) {
1161
+
1162
+ /* If we show the store listings under the map, we do want to jump to the
1163
+ * top of the map to focus on the opened infowindow
1164
+ */
1165
+ if ( ( wpslSettings.templateId == 1 ) && ( wpslSettings.moreInfoLocation == 'info window' ) ) {
1166
+ moreInfoUrl = '#wpsl-search-wrap';
1167
  }
1168
+
1169
+ /* Do we need to show the 'more info' data under the store details,
1170
+ * or should we only add a link which will trigger the infowindow?
1171
+ */
1172
+ if ( wpslSettings.moreInfoLocation == "store listings" ) {
1173
+
1174
+ /* Only create the 'more info' link if there is data to show */
1175
+ if ( ( ( typeof( response.description ) !== "undefined" ) && ( response.description !== "" ) ) ||
1176
+ ( ( typeof( response.phone ) !== "undefined" ) && ( response.phone !== "" ) ) ||
1177
+ ( ( typeof( response.fax ) !== "undefined" ) && ( response.fax !== "" ) ) ||
1178
+ ( ( typeof( response.email ) !== "undefined" ) && ( response.email !== "" ) ) ||
1179
+ ( ( typeof( response.hours ) !== "undefined" ) && ( response.hours !== "" ) ) ) {
1180
+ moreInfoData = createMoreInfoListing( response );
1181
+ moreInfo = "<p><a class='wpsl-store-details wpsl-store-listing' href=" + moreInfoUrl + "wpsl-id-" + id + ">" + wpslLabels.moreInfo + "</a>" + moreInfoData + "</p>";
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
  }
1183
+ } else {
1184
+ moreInfo = "<p><a class='wpsl-store-details' href=" + moreInfoUrl + ">" + wpslLabels.moreInfo + "</a></p>";
1185
  }
1186
+ }
1187
+
1188
+ /* Check if we need to make the store name clickable */
1189
+ if ( wpslSettings.storeUrl == 1) {
1190
+ if ( ( typeof( response.url ) !== "undefined" ) && ( response.url !== "" ) ) {
1191
+
1192
+ /* Do we need to open the url in a new window? */
1193
+ if ( wpslSettings.newWindow == 1 ) {
1194
+ storeUrlTarget = "target='_blank'";
 
 
1195
  }
1196
+
1197
+ store = "<a " + storeUrlTarget + " href='" + response.url + "'>" + store + "</a>";
1198
  }
1199
+ }
1200
+
1201
+ /* If we have a second address line, we add it */
1202
+ if ( ( typeof( response.address2 ) !== "undefined" ) && ( response.address2 !== "" ) ) {
1203
+ address2 = "<span class='wpsl-street'>" + response.address2 + "</span>";
1204
+ }
1205
 
1206
+ html = "<li data-store-id='" + id + "'><div><p>" + storeImg + "<strong>" + store + "</strong><span class='wpsl-street'>" + address + "</span>" + address2 + city + " " + state + " " + zip + "<span class='wpsl-country'>" + country + "</p>" + moreInfo + "</div>" + distance + "<a class='wpsl-directions' " + url.target + " href='" + url.src + "'>" + wpslLabels.directions + "</a></li>";
1207
 
1208
  return html;
1209
  }
1210
 
1211
+ /**
1212
+ * Zoom the map so that all markers fit in the window
1213
+ *
1214
+ * @since 1.0
1215
+ * @returns {void}
1216
+ */
1217
  function fitBounds() {
1218
  var i, markerLen,
1219
  maxZoom = 12,
1233
  map.fitBounds( bounds );
1234
  }
1235
 
1236
+ /**
1237
+ * Remove all existing markers and route lines from the map
1238
+ *
1239
+ * @since 1.0
1240
+ * @param {boolean} keepStartMarker Whether or not to keep the start marker while removing all the other markers from the map
1241
+ * @returns {void}
1242
+ */
1243
  function deleteOverlays( keepStartMarker ) {
1244
  var markerLen, i;
1245
  directionsDisplay.setMap( null );
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: tijmensmit
3
  Tags: google maps, store locator, business locations, geocoding, stores, geo
4
  Requires at least: 3.5
5
  Tested up to: 3.9.1
6
- Stable tag: 1.2.21
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
 
@@ -78,6 +78,12 @@ If you find a plugin or theme that causes a conflict, please report it on the [s
78
 
79
  == Changelog ==
80
 
 
 
 
 
 
 
81
  = 1.2.21 =
82
  * Fixed an js error breaking the store locator
83
 
3
  Tags: google maps, store locator, business locations, geocoding, stores, geo
4
  Requires at least: 3.5
5
  Tested up to: 3.9.1
6
+ Stable tag: 1.2.22
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
 
78
 
79
  == Changelog ==
80
 
81
+ = 1.2.22 =
82
+ * Fixed compatibility issues with the Google Maps field in the Advanced Custom Fields plugin
83
+ * Fixed the store urls in the store listings sometimes breaking
84
+ * Removed the requirement for a zipcode on the add/edit store page
85
+ * Improved the documentation in the js files
86
+
87
  = 1.2.21 =
88
  * Fixed an js error breaking the store locator
89
 
wp-store-locator.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI:
5
  Description: An easy to use location management system that enables users to search for nearby physical stores
6
  Author: Tijmen Smit
7
  Author URI: http://tijmensmit.com/
8
- Version: 1.2.21
9
  Text Domain: wpsl
10
  Domain Path: /languages/
11
  License: GPLv3
@@ -83,7 +83,7 @@ if ( !class_exists( 'WP_Store_locator' ) ) {
83
  public function define_constants() {
84
 
85
  if ( !defined( 'WPSL_VERSION_NUM' ) )
86
- define( 'WPSL_VERSION_NUM', '1.2.21' );
87
 
88
  if ( !defined( 'WPSL_URL' ) )
89
  define( 'WPSL_URL', plugin_dir_url( __FILE__ ) );
5
  Description: An easy to use location management system that enables users to search for nearby physical stores
6
  Author: Tijmen Smit
7
  Author URI: http://tijmensmit.com/
8
+ Version: 1.2.22
9
  Text Domain: wpsl
10
  Domain Path: /languages/
11
  License: GPLv3
83
  public function define_constants() {
84
 
85
  if ( !defined( 'WPSL_VERSION_NUM' ) )
86
+ define( 'WPSL_VERSION_NUM', '1.2.22' );
87
 
88
  if ( !defined( 'WPSL_URL' ) )
89
  define( 'WPSL_URL', plugin_dir_url( __FILE__ ) );