Version Description
- Initial release
Download this release
Release Info
Developer | tijmensmit |
Plugin | WP Store Locator |
Version | 1.0 |
Comparing to | |
See all releases |
Version 1.0
- admin/class-admin.php +1156 -0
- admin/class-store-overview.php +411 -0
- admin/css/style-3.8.css +29 -0
- admin/css/style.css +229 -0
- admin/font/fontello.eot +0 -0
- admin/font/fontello.svg +12 -0
- admin/font/fontello.ttf +0 -0
- admin/font/fontello.woff +0 -0
- admin/js/ajax-queue.js +54 -0
- admin/js/retina-1.1.0.js +152 -0
- admin/js/wpsl-admin.js +375 -0
- admin/templates/add-store.php +109 -0
- admin/templates/edit-store.php +135 -0
- admin/templates/faq.php +10 -0
- admin/templates/map-settings.php +234 -0
- admin/templates/stores-overview.php +24 -0
- css/styles.css +598 -0
- frontend/class-frontend.php +179 -0
- frontend/templates/default.php +45 -0
- frontend/wpsl-ajax-functions.php +114 -0
- img/ajax-loader.gif +0 -0
- img/markers/blue.png +0 -0
- img/markers/blue@2x.png +0 -0
- img/markers/dark-blue.png +0 -0
- img/markers/dark-blue@2x.png +0 -0
- img/markers/dark-green.png +0 -0
- img/markers/dark-green@2x.png +0 -0
- img/markers/dark-orange.png +0 -0
- img/markers/dark-orange@2x.png +0 -0
- img/markers/green.png +0 -0
- img/markers/green@2x.png +0 -0
- img/markers/orange.png +0 -0
- img/markers/orange@2x.png +0 -0
- img/markers/pink.png +0 -0
- img/markers/pink@2x.png +0 -0
- img/markers/purple.png +0 -0
- img/markers/purple@2x.png +0 -0
- img/markers/red.png +0 -0
- img/markers/red@2x.png +0 -0
- img/store-locator-icon.png +0 -0
- js/jquery.easydropdown.js +469 -0
- js/jquery.easydropdown.min.js +24 -0
- js/wpsl-gmap.js +555 -0
- readme.txt +59 -0
- screenshot-1.jpg +0 -0
- screenshot-2.jpg +0 -0
- screenshot-3.jpg +0 -0
- screenshot-4.jpg +0 -0
- screenshot-5.jpg +0 -0
- uninstall.php +19 -0
- wp-store-locator.php +234 -0
admin/class-admin.php
ADDED
@@ -0,0 +1,1156 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Admin class
|
4 |
+
*
|
5 |
+
* @package WP_Store_locator
|
6 |
+
* @subpackage Classes/Admin
|
7 |
+
* @copyright Copyright (c) 2013, Tijmen Smit
|
8 |
+
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
9 |
+
* @since 1.0
|
10 |
+
*/
|
11 |
+
|
12 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
13 |
+
|
14 |
+
if ( !class_exists( 'WPSL_Admin' ) ) {
|
15 |
+
/**
|
16 |
+
* Handle the backend of the store locator
|
17 |
+
*
|
18 |
+
* @since 1.0
|
19 |
+
*/
|
20 |
+
class WPSL_Admin extends WP_Store_locator {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Holds the store data
|
24 |
+
*
|
25 |
+
* @var array
|
26 |
+
* @since 1.0
|
27 |
+
*/
|
28 |
+
public $store_data;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Class constructor
|
32 |
+
*/
|
33 |
+
function __construct() {
|
34 |
+
add_action( 'init', array( $this, 'output_buffer' ) );
|
35 |
+
add_action( 'admin_init', array( $this, 'admin_init' ) );
|
36 |
+
add_action( 'wp_loaded', array( $this, 'init' ) );
|
37 |
+
add_action( 'wp_ajax_delete_store', array( $this, 'delete_store_ajax' ) );
|
38 |
+
|
39 |
+
$this->settings = $this->get_settings();
|
40 |
+
}
|
41 |
+
|
42 |
+
public function output_buffer() {
|
43 |
+
ob_start();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Register a callback function for the settings page
|
48 |
+
*
|
49 |
+
* @since 1.0
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
+
public function admin_init() {
|
53 |
+
register_setting( 'wpsl_settings', 'wpsl_settings', array( $this, 'sanitize_settings' ) );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Add the admin menu and enqueue the admin scripts
|
58 |
+
*
|
59 |
+
* @since 1.0
|
60 |
+
* @return void
|
61 |
+
*/
|
62 |
+
public function init() {
|
63 |
+
add_action( 'admin_menu', array( $this, 'create_admin_menu' ) );
|
64 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Add the menu pages
|
69 |
+
*
|
70 |
+
* @since 1.0
|
71 |
+
* @return void
|
72 |
+
*/
|
73 |
+
public function create_admin_menu() {
|
74 |
+
add_menu_page( 'Store Locator', __( 'Store Locator', 'wpsl' ), __( 'manage_options', 'wpsl' ), 'wpsl_store_editor', array( $this, 'manage_stores' ), plugins_url( 'img/store-locator-icon.png', dirname( __FILE__ ) ) );
|
75 |
+
add_submenu_page( 'wpsl_store_editor', __( 'Manage Stores', 'wpsl' ), __( 'Manage Stores', 'wpsl' ), 'manage_options', 'wpsl_store_editor', array( $this, 'manage_stores' ) );
|
76 |
+
add_submenu_page( 'wpsl_store_editor', __( 'Add Store', 'wpsl' ), __( 'Add Store', 'wpsl' ), 'manage_options', 'wpsl_add_store', array( $this, 'add_store' ) );
|
77 |
+
add_submenu_page( 'wpsl_store_editor', __( 'Settings', 'wpsl' ), __( 'Settings', 'wpsl' ), 'manage_options', 'wpsl_settings', array( $this, 'show_settings' ) );
|
78 |
+
add_submenu_page( 'wpsl_store_editor', __( 'FAQ', 'wpsl' ), __( 'FAQ', 'wpsl' ), 'manage_options', 'wpsl_faq', array( $this, 'show_faq' ) );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Load the add store template
|
83 |
+
*
|
84 |
+
* @since 1.0
|
85 |
+
* @return void
|
86 |
+
*/
|
87 |
+
public function add_store() {
|
88 |
+
$this->store_actions();
|
89 |
+
require_once( WPSL_PLUGIN_DIR . 'admin/templates/add-store.php' );
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* If a store form is submitted, process the store data
|
94 |
+
*
|
95 |
+
* @since 1.0
|
96 |
+
* @return void
|
97 |
+
*/
|
98 |
+
public function store_actions() {
|
99 |
+
if ( isset( $_REQUEST['wpsl_actions'] ) ) {
|
100 |
+
$this->handle_store_data();
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Handle the different actions for the store.
|
106 |
+
*
|
107 |
+
* Based on the action value, either show the store overview list or the edit store template
|
108 |
+
*
|
109 |
+
* @since 1.0
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
+
public function manage_stores() {
|
113 |
+
|
114 |
+
$this->store_actions();
|
115 |
+
|
116 |
+
/* Check which store template to show */
|
117 |
+
switch ( $_GET['action'] ) {
|
118 |
+
case 'edit_store':
|
119 |
+
require_once( WPSL_PLUGIN_DIR . 'admin/templates/edit-store.php' );
|
120 |
+
break;
|
121 |
+
default:
|
122 |
+
require_once( WPSL_PLUGIN_DIR . 'admin/templates/stores-overview.php' );
|
123 |
+
break;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Process new store data
|
129 |
+
*
|
130 |
+
* @since 1.0
|
131 |
+
* @return void
|
132 |
+
*/
|
133 |
+
public function handle_store_data() {
|
134 |
+
|
135 |
+
global $wpdb;
|
136 |
+
|
137 |
+
if ( !current_user_can( 'manage_options' ) )
|
138 |
+
die( '-1' );
|
139 |
+
|
140 |
+
check_admin_referer( 'wpsl_' . $_POST['wpsl_actions'] );
|
141 |
+
|
142 |
+
$this->store_data = $this->validate_store_data();
|
143 |
+
|
144 |
+
if ( $this->store_data ) {
|
145 |
+
$latlng = $this->validate_latlng( $this->store_data['lat'], $this->store_data['lng'] );
|
146 |
+
|
147 |
+
/* If we don't have a valid latlng value, we geocode the supplied address to get one */
|
148 |
+
if ( !$latlng ) {
|
149 |
+
$reponse = $this->geocode_location();
|
150 |
+
$this->store_data['country'] = $reponse['country']['long_name'];
|
151 |
+
$this->store_data['country-iso'] = $reponse['country']['short_name'];
|
152 |
+
$this->store_data['latlng'] = $reponse['latlng'];
|
153 |
+
} else {
|
154 |
+
$this->store_data['country-iso'] = $_POST['wpsl']['country-iso'];
|
155 |
+
$this->store_data['latlng'] = $latlng;
|
156 |
+
}
|
157 |
+
|
158 |
+
if ( $_POST['wpsl_actions'] == 'add_new_store' )
|
159 |
+
$this->add_new_store();
|
160 |
+
|
161 |
+
if ( $_POST['wpsl_actions'] == 'update_store' )
|
162 |
+
$this->update_store();
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Delete a single store
|
168 |
+
*
|
169 |
+
* This is called from the store overview page when a user clicks the delete button
|
170 |
+
*
|
171 |
+
* @since 1.0
|
172 |
+
* @return json Either fail or success
|
173 |
+
*/
|
174 |
+
public function delete_store_ajax() {
|
175 |
+
|
176 |
+
global $wpdb;
|
177 |
+
|
178 |
+
$store_id = absint( $_POST['store_id'] );
|
179 |
+
|
180 |
+
if ( !current_user_can( 'manage_options' ) )
|
181 |
+
die( '-1' );
|
182 |
+
|
183 |
+
check_ajax_referer( 'wpsl_delete_nonce_'.$store_id );
|
184 |
+
|
185 |
+
$result = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->wpsl_stores WHERE wpsl_id = %d", $store_id ) );
|
186 |
+
|
187 |
+
if ( $result === false ) {
|
188 |
+
wp_send_json_error();
|
189 |
+
} else {
|
190 |
+
wp_send_json_success();
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Update store details
|
196 |
+
*
|
197 |
+
* @since 1.0
|
198 |
+
* @param array $store_data The updated store data
|
199 |
+
* @return void
|
200 |
+
*/
|
201 |
+
public function update_store() {
|
202 |
+
|
203 |
+
global $wpdb;
|
204 |
+
|
205 |
+
$result = $wpdb->query(
|
206 |
+
$wpdb->prepare(
|
207 |
+
"
|
208 |
+
UPDATE $wpdb->wpsl_stores
|
209 |
+
SET store = %s, street = %s, city = %s, state = %s, zip = %s, country = %s, country_iso = %s, lat = %s, lng = %s, description = %s, phone = %s, fax = %s, url = %s, email = %s, hours = %s, thumb_id = %d, active = %d
|
210 |
+
WHERE wpsl_id = %d",
|
211 |
+
$this->store_data['store'],
|
212 |
+
$this->store_data['street'],
|
213 |
+
$this->store_data['city'],
|
214 |
+
$this->store_data['state'],
|
215 |
+
strtoupper ( $this->store_data['zip'] ),
|
216 |
+
$this->store_data['country'],
|
217 |
+
$this->store_data['country-iso'],
|
218 |
+
$this->store_data['latlng']['lat'],
|
219 |
+
$this->store_data['latlng']['lng'],
|
220 |
+
$this->store_data['desc'],
|
221 |
+
$this->store_data['phone'],
|
222 |
+
$this->store_data['fax'],
|
223 |
+
$this->store_data['url'],
|
224 |
+
$this->store_data['email'],
|
225 |
+
$this->store_data['hours'],
|
226 |
+
$this->store_data['thumb-id'],
|
227 |
+
$this->store_data['active'],
|
228 |
+
$_GET['store_id']
|
229 |
+
)
|
230 |
+
);
|
231 |
+
|
232 |
+
if ( $result === false ) {
|
233 |
+
$state = 'error';
|
234 |
+
$msg = __( 'There was a problem updating the store details, please try again.', 'wpsl' );
|
235 |
+
} else {
|
236 |
+
$_POST = array();
|
237 |
+
$state = 'updated';
|
238 |
+
$msg = __( 'Store details updated.', 'wpsl' );
|
239 |
+
}
|
240 |
+
|
241 |
+
add_settings_error ( 'update-store', esc_attr( 'update-store' ), $msg, $state );
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Add a new store to the db
|
246 |
+
*
|
247 |
+
* @since 1.0
|
248 |
+
* @param array $store_data The submitted store data
|
249 |
+
* @return void
|
250 |
+
*/
|
251 |
+
public function add_new_store() {
|
252 |
+
|
253 |
+
global $wpdb;
|
254 |
+
|
255 |
+
$result = $wpdb->query(
|
256 |
+
$wpdb->prepare(
|
257 |
+
"
|
258 |
+
INSERT INTO $wpdb->wpsl_stores
|
259 |
+
(store, street, city, state, zip, country, country_iso, lat, lng, description, phone, fax, url, email, hours, thumb_id)
|
260 |
+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d)
|
261 |
+
",
|
262 |
+
$this->store_data['store'],
|
263 |
+
$this->store_data['street'],
|
264 |
+
$this->store_data['city'],
|
265 |
+
$this->store_data['state'],
|
266 |
+
strtoupper ( $this->store_data['zip'] ),
|
267 |
+
$this->store_data['country'],
|
268 |
+
$this->store_data['country-iso'],
|
269 |
+
$this->store_data['latlng']['lat'],
|
270 |
+
$this->store_data['latlng']['lng'],
|
271 |
+
$this->store_data['desc'],
|
272 |
+
$this->store_data['phone'],
|
273 |
+
$this->store_data['fax'],
|
274 |
+
$this->store_data['url'],
|
275 |
+
$this->store_data['email'],
|
276 |
+
$this->store_data['hours'],
|
277 |
+
$this->store_data['thumb-id']
|
278 |
+
)
|
279 |
+
);
|
280 |
+
|
281 |
+
if ( $result === false ) {
|
282 |
+
$state = 'error';
|
283 |
+
$msg = __( 'There was a problem saving the new store details, please try again.', 'wpsl' );
|
284 |
+
} else {
|
285 |
+
$_POST = array();
|
286 |
+
$state = 'updated';
|
287 |
+
$msg = __( 'Store succesfully added.', 'wpsl' );
|
288 |
+
}
|
289 |
+
|
290 |
+
add_settings_error ( 'add-store', esc_attr( 'add-store' ), $msg, $state );
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Get a single value from the default settings
|
295 |
+
*
|
296 |
+
* @since 1.0
|
297 |
+
* @param string $setting The value that should be restored
|
298 |
+
* @return string the default setting value
|
299 |
+
*/
|
300 |
+
public function get_default_setting( $setting ) {
|
301 |
+
return $this->default_settings[$setting];
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Validate the submitted store data
|
306 |
+
*
|
307 |
+
* @since 1.0
|
308 |
+
* @return mixed array|void $store_data the submitted store data if not empty, otherwise nothing
|
309 |
+
*/
|
310 |
+
public function validate_store_data() {
|
311 |
+
|
312 |
+
$store_data = $_POST['wpsl'];
|
313 |
+
|
314 |
+
if ( empty( $store_data['store'] ) || ( empty( $store_data['street'] ) ) || ( empty( $store_data['city'] ) ) || ( empty( $store_data['zip'] ) ) || ( empty( $store_data['country'] ) ) ) {
|
315 |
+
add_settings_error ( 'validate-store', esc_attr( 'validate-store' ), __( 'Please fill in all the required fields.', 'wpsl' ), 'error' );
|
316 |
+
} else {
|
317 |
+
return $store_data;
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Get the data for a single store
|
323 |
+
*
|
324 |
+
* @since 1.0
|
325 |
+
* @param string $store_id The id for a single store
|
326 |
+
* @return array $result The store details
|
327 |
+
*/
|
328 |
+
public function get_store_data( $store_id ) {
|
329 |
+
|
330 |
+
global $wpdb;
|
331 |
+
|
332 |
+
$result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->wpsl_stores WHERE wpsl_id = %d", $store_id ), ARRAY_A );
|
333 |
+
|
334 |
+
return $result;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Show the settings template
|
339 |
+
*
|
340 |
+
* @since 1.0
|
341 |
+
* @return void
|
342 |
+
*/
|
343 |
+
public function show_settings() {
|
344 |
+
require 'templates/map-settings.php';
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Show the faq template
|
349 |
+
*
|
350 |
+
* @since 1.0
|
351 |
+
* @return void
|
352 |
+
*/
|
353 |
+
public function show_faq() {
|
354 |
+
require 'templates/faq.php';
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Handle the different validation errors for the plugin settings
|
359 |
+
*
|
360 |
+
* @since 1.0
|
361 |
+
* @param string $error_type Contains the type of validation error that occured
|
362 |
+
* @return void
|
363 |
+
*/
|
364 |
+
private function settings_error( $error_type ) {
|
365 |
+
|
366 |
+
switch ( $error_type ) {
|
367 |
+
case 'max_results':
|
368 |
+
$error_msg = __( 'The max results field cannot be empty, the default value has been restored.', 'wpsl' );
|
369 |
+
break;
|
370 |
+
case 'search_radius':
|
371 |
+
$error_msg = __( 'The search radius field cannot be empty, the default value has been restored.', 'wpsl' );
|
372 |
+
break;
|
373 |
+
case 'label_missing':
|
374 |
+
$error_msg = __( 'One of the label fields was left empty, the default value for that field has been restored.', 'wpsl' );
|
375 |
+
break;
|
376 |
+
}
|
377 |
+
|
378 |
+
add_settings_error ( 'setting-errors', esc_attr( 'settings_fail' ), $error_msg, 'error' );
|
379 |
+
}
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Sanitize the submitted plugin settings
|
383 |
+
*
|
384 |
+
* @since 1.0
|
385 |
+
* @return array $output The setting values
|
386 |
+
*/
|
387 |
+
public function sanitize_settings() {
|
388 |
+
|
389 |
+
$map_types = array(
|
390 |
+
'roadmap',
|
391 |
+
'satellite',
|
392 |
+
'hybrid',
|
393 |
+
'terrain'
|
394 |
+
);
|
395 |
+
$unit_values = array(
|
396 |
+
'px',
|
397 |
+
'%'
|
398 |
+
);
|
399 |
+
$distance_units = array(
|
400 |
+
'km',
|
401 |
+
'mi'
|
402 |
+
);
|
403 |
+
|
404 |
+
$output['api_key'] = sanitize_text_field( $_POST['wpsl_api']['key'] );
|
405 |
+
$output['api_language'] = wp_filter_nohtml_kses( $_POST['wpsl_api']['language'] );
|
406 |
+
$output['api_region'] = wp_filter_nohtml_kses( $_POST['wpsl_api']['region'] );
|
407 |
+
|
408 |
+
if ( in_array( $_POST['wpsl_search']['distance_unit'], $distance_units ) ) {
|
409 |
+
$output['distance_unit'] = $_POST['wpsl_search']['distance_unit'];
|
410 |
+
} else {
|
411 |
+
$output['distance_unit'] = $this->get_default_setting( 'distance_unit' );
|
412 |
+
}
|
413 |
+
|
414 |
+
/* Check for a valid max results value, otherwise we use the default */
|
415 |
+
if ( !empty( $_POST['wpsl_search']['max_results'] ) ) {
|
416 |
+
$output['max_results'] = sanitize_text_field( $_POST['wpsl_search']['max_results'] );
|
417 |
+
} else {
|
418 |
+
$this->settings_error( 'max_results' );
|
419 |
+
$output['max_results'] = $this->get_default_setting( 'max_results' );
|
420 |
+
}
|
421 |
+
|
422 |
+
/* See if a search radius value exist, otherwise we use the default */
|
423 |
+
if ( !empty( $_POST['wpsl_search']['radius'] ) ) {
|
424 |
+
$output['search_radius'] = sanitize_text_field( $_POST['wpsl_search']['radius'] );
|
425 |
+
} else {
|
426 |
+
$this->settings_error( 'search_radius' );
|
427 |
+
$output['search_radius'] = $this->get_default_setting( 'search_radius' );
|
428 |
+
}
|
429 |
+
|
430 |
+
$output['marker_bounce'] = isset( $_POST['wpsl_map']['marker_bounce'] ) ? 1 : 0;
|
431 |
+
|
432 |
+
/* Check if we have a valid zoom level, it has to be between 1 or 12. If not set it to the default of 3 */
|
433 |
+
if ( $_POST['wpsl_map']['zoom_level'] >= 1 || $_POST['wpsl_map']['zoom_level'] <= 12 ) {
|
434 |
+
$output['zoom_level'] = $_POST['wpsl_map']['zoom_level'];
|
435 |
+
} else {
|
436 |
+
$output['zoom_level'] = $this->get_default_setting( 'zoom_level' );
|
437 |
+
}
|
438 |
+
|
439 |
+
$output['zoom_name'] = sanitize_text_field( $_POST['wpsl_map']['zoom_name'] );
|
440 |
+
|
441 |
+
/* If no location name is set to zoom to we also empty the latlng values from the hidden input field */
|
442 |
+
if ( empty( $output['zoom_name'] ) ) {
|
443 |
+
$output['zoom_latlng'] = '';
|
444 |
+
} else {
|
445 |
+
$output['zoom_latlng'] = sanitize_text_field( $_POST['wpsl_map']['zoom_latlng'] );
|
446 |
+
}
|
447 |
+
|
448 |
+
/* Check if we have a valid map type */
|
449 |
+
if ( in_array( $_POST['wpsl_map']['type'], $map_types ) ) {
|
450 |
+
$output['map_type'] = $_POST['wpsl_map']['type'];
|
451 |
+
} else {
|
452 |
+
$output['map_type'] = $this->get_default_setting( 'map_type' );
|
453 |
+
}
|
454 |
+
|
455 |
+
$output['streetview'] = isset( $_POST['wpsl_map']['streetview'] ) ? 1 : 0;
|
456 |
+
$output['pan_controls'] = isset( $_POST['wpsl_map']['pan_controls'] ) ? 1 : 0;
|
457 |
+
$output['control_position'] = ( $_POST['wpsl_map']['control_position'] == 'left' ) ? 'left' : 'right';
|
458 |
+
$output['control_style'] = ( $_POST['wpsl_map']['control_style'] == 'small' ) ? 'small' : 'large';
|
459 |
+
$output['auto_locate'] = isset( $_POST['wpsl_map']['auto_locate'] ) ? 1 : 0;
|
460 |
+
|
461 |
+
/* Check the height value of the map */
|
462 |
+
if ( absint( $_POST['wpsl_design']['height_value'] ) ) {
|
463 |
+
$output['height'] = $_POST['wpsl_design']['height_value'];
|
464 |
+
} else {
|
465 |
+
$output['height'] = $this->get_default_setting( 'height' );
|
466 |
+
}
|
467 |
+
|
468 |
+
/* Check the max-width of the infowindow */
|
469 |
+
if ( absint( $_POST['wpsl_design']['infowindow_width'] ) ) {
|
470 |
+
$output['infowindow_width'] = $_POST['wpsl_design']['infowindow_width'];
|
471 |
+
} else {
|
472 |
+
$output['infowindow_width'] = $this->get_default_setting( 'infowindow_width' );
|
473 |
+
}
|
474 |
+
|
475 |
+
/* Check the width for the search field */
|
476 |
+
if ( absint( $_POST['wpsl_design']['search_width'] ) ) {
|
477 |
+
$output['search_width'] = $_POST['wpsl_design']['search_width'];
|
478 |
+
} else {
|
479 |
+
$output['search_width'] = $this->get_default_setting( 'search_width' );
|
480 |
+
}
|
481 |
+
|
482 |
+
/* Check the width for labels */
|
483 |
+
if ( absint( $_POST['wpsl_design']['label_width'] ) ) {
|
484 |
+
$output['label_width'] = $_POST['wpsl_design']['label_width'];
|
485 |
+
} else {
|
486 |
+
$output['label_width'] = $this->get_default_setting( 'label_width' );
|
487 |
+
}
|
488 |
+
|
489 |
+
$output['results_dropdown'] = isset( $_POST['wpsl_design']['design_results'] ) ? 1 : 0;
|
490 |
+
|
491 |
+
$output['start_marker'] = wp_filter_nohtml_kses( $_POST['wpsl_map']['start_marker'] );
|
492 |
+
$output['store_marker'] = wp_filter_nohtml_kses( $_POST['wpsl_map']['store_marker'] );
|
493 |
+
|
494 |
+
$missing_labels = false;
|
495 |
+
$required_labels = array(
|
496 |
+
'search',
|
497 |
+
'search_btn',
|
498 |
+
'preloader',
|
499 |
+
'radius',
|
500 |
+
'no_results',
|
501 |
+
'results',
|
502 |
+
'directions',
|
503 |
+
'error',
|
504 |
+
'phone',
|
505 |
+
'fax',
|
506 |
+
'hours',
|
507 |
+
'start',
|
508 |
+
'limit'
|
509 |
+
);
|
510 |
+
|
511 |
+
/**
|
512 |
+
* Labels can never be empty, so we make sure they always contain data.
|
513 |
+
* If they are empty, we use the default value
|
514 |
+
*/
|
515 |
+
foreach ( $required_labels as $k => $label ) {
|
516 |
+
if ( !empty( $_POST['wpsl_label'][$label] ) ) {
|
517 |
+
$output[$label.'_label'] = sanitize_text_field( $_POST['wpsl_label'][$label] );
|
518 |
+
} else {
|
519 |
+
$output[$label.'_label'] = $this->get_default_setting( $label.'_label' );
|
520 |
+
$missing_labels = true;
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
if ( $missing_labels ) {
|
525 |
+
$this->settings_error( 'label_missing' );
|
526 |
+
}
|
527 |
+
|
528 |
+
return $output;
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Validate the latlng values
|
533 |
+
*
|
534 |
+
* @since 1.0
|
535 |
+
* @param string $lat The latitude value
|
536 |
+
* @param string $lng The longitude value
|
537 |
+
* @return array|boolean $latlng The validated latlng values or false if it fails
|
538 |
+
*/
|
539 |
+
public function validate_latlng( $lat, $lng ) {
|
540 |
+
|
541 |
+
if ( is_numeric( $lat ) || ( is_numeric( $lng ) ) ) {
|
542 |
+
$latlng = array(
|
543 |
+
"lat" => $lat,
|
544 |
+
"lng" => $lng
|
545 |
+
);
|
546 |
+
|
547 |
+
return $latlng;
|
548 |
+
} else {
|
549 |
+
return false;
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* Geocode the store location
|
555 |
+
*
|
556 |
+
* @since 1.0
|
557 |
+
* @return array|void $response Contains the country name in the selected language, and the latlng values
|
558 |
+
*/
|
559 |
+
public function geocode_location() {
|
560 |
+
|
561 |
+
$geocode_response = $this->get_latlng();
|
562 |
+
|
563 |
+
switch ( $geocode_response['status'] ) {
|
564 |
+
case 'OK':
|
565 |
+
$response = array (
|
566 |
+
"country" => $this->filter_country_name( $geocode_response ),
|
567 |
+
"latlng" => $geocode_response['results'][0]['geometry']['location']
|
568 |
+
);
|
569 |
+
|
570 |
+
return $response;
|
571 |
+
break;
|
572 |
+
case 'ZERO_RESULTS':
|
573 |
+
$msg = __( 'The Google Geocoding API returned no results for the store location. Please change the location and try again.', 'wpsl' );
|
574 |
+
break;
|
575 |
+
case 'OVER_QUERY_LIMIT':
|
576 |
+
$msg = __( 'You have reached the daily allowed geocoding limit, you can read more <a href="https://developers.google.com/maps/documentation/geocoding/#Limits">here</a>.', 'wpsl' );
|
577 |
+
break;
|
578 |
+
default:
|
579 |
+
$msg = __( 'The Google Geocoding API failed to return valid data, please try again later.', 'wpsl' );
|
580 |
+
break;
|
581 |
+
}
|
582 |
+
|
583 |
+
if ( !empty( $msg ) ) {
|
584 |
+
add_settings_error ( 'geocode', esc_attr( 'geocode' ), $msg, 'error' );
|
585 |
+
}
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* Make the API call to Google to geocode the address
|
590 |
+
*
|
591 |
+
* @since 1.0
|
592 |
+
* @return array $response The geocode response
|
593 |
+
*/
|
594 |
+
public function get_latlng() {
|
595 |
+
|
596 |
+
$address = $this->store_data["street"].','.$this->store_data["city"].','.$this->store_data["zip"].','.$this->store_data["country"];
|
597 |
+
$url = "http://maps.googleapis.com/maps/api/geocode/json?address=".urlencode( $address )."&sensor=false&language=".$this->settings['api_language'];
|
598 |
+
|
599 |
+
if ( extension_loaded( "curl" ) && function_exists( "curl_init" ) ) {
|
600 |
+
$ch = curl_init();
|
601 |
+
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
602 |
+
curl_setopt( $ch, CURLOPT_URL, $url ) ;
|
603 |
+
$result = curl_exec( $ch );
|
604 |
+
curl_close( $ch );
|
605 |
+
} else {
|
606 |
+
$result = file_get_contents( $url );
|
607 |
+
}
|
608 |
+
|
609 |
+
$response = json_decode( $result, true );
|
610 |
+
|
611 |
+
return $response;
|
612 |
+
}
|
613 |
+
|
614 |
+
/**
|
615 |
+
* Filter out the country names from the geocode response
|
616 |
+
*
|
617 |
+
* Take out both the full country name, and the short country code (2 letters)
|
618 |
+
*
|
619 |
+
* @since 1.0
|
620 |
+
* @param array $response The fulle API geocode response
|
621 |
+
* @return array $country_name Both the full and short country names
|
622 |
+
*/
|
623 |
+
public function filter_country_name( $response ) {
|
624 |
+
|
625 |
+
$length = count( $response[results][0][address_components] );
|
626 |
+
|
627 |
+
/* Loop over the address components untill we find the country,political part */
|
628 |
+
for ( $i = 0; $i < $length; $i++ ) {
|
629 |
+
$address_component = $response[results][0][address_components][$i][types];
|
630 |
+
|
631 |
+
if ( $address_component[0] == 'country' && $address_component[1] == 'political' ) {
|
632 |
+
$country_name['long_name'] = $response[results][0][address_components][$i][long_name];
|
633 |
+
$country_name['short_name'] = $response[results][0][address_components][$i][short_name];
|
634 |
+
|
635 |
+
break;
|
636 |
+
}
|
637 |
+
}
|
638 |
+
|
639 |
+
return $country_name;
|
640 |
+
}
|
641 |
+
|
642 |
+
/**
|
643 |
+
* Show the options of the start and store markers
|
644 |
+
*
|
645 |
+
* @since 1.0
|
646 |
+
* @return string $marker_list The complete list of available and selected markers
|
647 |
+
*/
|
648 |
+
public function show_marker_options() {
|
649 |
+
|
650 |
+
$marker_list;
|
651 |
+
$marker_images = $this->get_available_markers();
|
652 |
+
$marker_locations = array(
|
653 |
+
"start",
|
654 |
+
"store"
|
655 |
+
);
|
656 |
+
|
657 |
+
foreach ( $marker_locations as $location ) {
|
658 |
+
if ( $location == 'start' ) {
|
659 |
+
$marker_list .= __( 'Start location marker:', 'wpsl' );
|
660 |
+
} else {
|
661 |
+
$marker_list .= __( 'Store location marker:', 'wpsl' );
|
662 |
+
}
|
663 |
+
|
664 |
+
if ( !empty( $marker_images ) ) {
|
665 |
+
$marker_list .= '<ul class="wpsl-marker-list">';
|
666 |
+
|
667 |
+
foreach ( $marker_images as $marker_img ) {
|
668 |
+
$marker_list .= $this->create_marker_html( $marker_img, $location );
|
669 |
+
}
|
670 |
+
|
671 |
+
$marker_list .= '</ul>';
|
672 |
+
}
|
673 |
+
}
|
674 |
+
|
675 |
+
return $marker_list;
|
676 |
+
}
|
677 |
+
|
678 |
+
/**
|
679 |
+
* Load the markers that can be used on the map
|
680 |
+
*
|
681 |
+
* @since 1.0
|
682 |
+
* @return array $marker_images A list of all the available markers
|
683 |
+
*/
|
684 |
+
public function get_available_markers() {
|
685 |
+
|
686 |
+
$dir = WPSL_PLUGIN_DIR . 'img/markers/';
|
687 |
+
|
688 |
+
if ( is_dir( $dir ) ) {
|
689 |
+
if ( $dh = opendir( $dir ) ) {
|
690 |
+
while ( false !== ( $file = readdir( $dh ) ) ) {
|
691 |
+
if ( $file == '.' || $file == '..' || ( strpos( $file, '@2x' ) !== false ) ) continue;
|
692 |
+
$marker_images[] = $file;
|
693 |
+
}
|
694 |
+
|
695 |
+
closedir( $dh );
|
696 |
+
}
|
697 |
+
}
|
698 |
+
|
699 |
+
return $marker_images;
|
700 |
+
}
|
701 |
+
|
702 |
+
/**
|
703 |
+
* Create the html output for the marker list that is shown on the settings page
|
704 |
+
*
|
705 |
+
* There are two markers lists, one where the user can set the marker for the start point
|
706 |
+
* and one where a marker can be set for the store. We also check if the marker img is identical
|
707 |
+
* to the name in the option field. If so we set it to checked
|
708 |
+
*
|
709 |
+
* @since 1.0
|
710 |
+
* @param string $marker_img The filename of the marker
|
711 |
+
* @param string $location Eiter contains "start" or "store"
|
712 |
+
* @return string $marker_list A list of all the available markers
|
713 |
+
*/
|
714 |
+
public function create_marker_html( $marker_img, $location ) {
|
715 |
+
|
716 |
+
$marker_list = '';
|
717 |
+
|
718 |
+
if ( $this->settings[$location.'_marker'] == $marker_img ) {
|
719 |
+
$checked = 'checked="checked"';
|
720 |
+
$css_class = 'class="wpsl-active-marker"';
|
721 |
+
} else {
|
722 |
+
$checked = '';
|
723 |
+
$css_class = '';
|
724 |
+
}
|
725 |
+
|
726 |
+
$marker_list .= '<li ' . $css_class . '>';
|
727 |
+
$marker_list .= '<img src="' . WPSL_URL . 'img/markers/' . $marker_img . '" />';
|
728 |
+
$marker_list .= '<input ' . $checked . ' type="radio" name="wpsl_map[' . $location . '_marker]" value="' . $marker_img . '" />';
|
729 |
+
$marker_list .= '</li>';
|
730 |
+
|
731 |
+
return $marker_list;
|
732 |
+
}
|
733 |
+
|
734 |
+
/**
|
735 |
+
* Create a dropdown where users can select the distance unit (km or miles),
|
736 |
+
* and set the active value to selected.
|
737 |
+
*
|
738 |
+
* @since 1.0
|
739 |
+
* @return string $dropdown The html for the distance option list
|
740 |
+
*/
|
741 |
+
public function show_distance_units() {
|
742 |
+
|
743 |
+
$items = array( 'km', 'mi' );
|
744 |
+
$dropdown = '<select id="wpsl-distance-unit" name="wpsl_search[distance_unit]">';
|
745 |
+
|
746 |
+
foreach ( $items as $item => $value ) {
|
747 |
+
$selected = ( $this->settings['distance_unit'] == $value ) ? 'selected="selected"' : '';
|
748 |
+
$dropdown .= "<option value='$value' $selected>" . $value . "</option>";
|
749 |
+
}
|
750 |
+
|
751 |
+
$dropdown .= "</select>";
|
752 |
+
|
753 |
+
return $dropdown;
|
754 |
+
}
|
755 |
+
|
756 |
+
/**
|
757 |
+
* Create a dropdown where users can select the used map type
|
758 |
+
*
|
759 |
+
* @since 1.0
|
760 |
+
* @return string $dropdown The html for the map option list
|
761 |
+
*/
|
762 |
+
public function show_map_types() {
|
763 |
+
|
764 |
+
$items = array(
|
765 |
+
'roadmap',
|
766 |
+
'satellite',
|
767 |
+
'hybrid',
|
768 |
+
'terrain'
|
769 |
+
);
|
770 |
+
$dropdown = '<select id="wpsl-map-type" name="wpsl_map[type]">';
|
771 |
+
|
772 |
+
foreach ( $items as $item => $value ) {
|
773 |
+
$selected = ( $this->settings['map_type'] == $value ) ? 'selected="selected"' : '';
|
774 |
+
$dropdown .= "<option value='$value' $selected>" . ucfirst( $value ) . "</option>";
|
775 |
+
}
|
776 |
+
|
777 |
+
$dropdown .= "</select>";
|
778 |
+
|
779 |
+
return $dropdown;
|
780 |
+
}
|
781 |
+
|
782 |
+
/**
|
783 |
+
* Create the dropdown to select the zoom level
|
784 |
+
*
|
785 |
+
* @since 1.0
|
786 |
+
* @return string $dropdown The html for the zoom level list
|
787 |
+
*/
|
788 |
+
public function show_zoom_levels() {
|
789 |
+
|
790 |
+
$dropdown = '<select id="wpsl-zoom-level" name="wpsl_map[zoom_level]">';
|
791 |
+
|
792 |
+
for ( $i = 1; $i < 13; $i++ ) {
|
793 |
+
$selected = ( $this->settings['zoom_level'] == $i ) ? 'selected="selected"' : '';
|
794 |
+
|
795 |
+
switch ( $i ) {
|
796 |
+
case '1':
|
797 |
+
$zoom_desc = '- World view';
|
798 |
+
break;
|
799 |
+
case '3':
|
800 |
+
$zoom_desc = '- Default';
|
801 |
+
break;
|
802 |
+
case '12':
|
803 |
+
$zoom_desc = '- Roadmap view';
|
804 |
+
break;
|
805 |
+
default:
|
806 |
+
$zoom_desc = '';
|
807 |
+
}
|
808 |
+
|
809 |
+
$dropdown .= "<option value='$i' $selected>$i $zoom_desc</option>";
|
810 |
+
}
|
811 |
+
|
812 |
+
$dropdown .= "</select>";
|
813 |
+
|
814 |
+
return $dropdown;
|
815 |
+
}
|
816 |
+
|
817 |
+
/**
|
818 |
+
* Options for the language and region list
|
819 |
+
*
|
820 |
+
* @since 1.0
|
821 |
+
* @param string $list The request list type
|
822 |
+
* @return string|void $option_list The html for the selected list, or nothing if the $list contains invalud values
|
823 |
+
*/
|
824 |
+
public function get_api_option_list( $list ) {
|
825 |
+
|
826 |
+
switch ( $list ) {
|
827 |
+
case 'language':
|
828 |
+
$api_option_list = array (
|
829 |
+
__('Select your language', 'wpsl') => '',
|
830 |
+
__('English', 'wpsl') => 'en',
|
831 |
+
__('Arabic', 'wpsl') => 'ar',
|
832 |
+
__('Basque', 'wpsl') => 'eu',
|
833 |
+
__('Bulgarian', 'wpsl') => 'bg',
|
834 |
+
__('Bengali', 'wpsl') => 'bn',
|
835 |
+
__('Catalan', 'wpsl') => 'ca',
|
836 |
+
__('Czech', 'wpsl') => 'cs',
|
837 |
+
__('Danish', 'wpsl') => 'da',
|
838 |
+
__('German', 'wpsl') => 'de',
|
839 |
+
__('Greek', 'wpsl') => 'el',
|
840 |
+
__('English (Australian)', 'wpsl') => 'en-AU',
|
841 |
+
__('English (Great Britain)', 'wpsl') => 'en-GB',
|
842 |
+
__('Spanish', 'wpsl') => 'es',
|
843 |
+
__('Farsi', 'wpsl') => 'fa',
|
844 |
+
__('Finnish', 'wpsl') => 'fi',
|
845 |
+
__('Filipino', 'wpsl') => 'fil',
|
846 |
+
__('French', 'wpsl') => 'fr',
|
847 |
+
__('Galician', 'wpsl') => 'gl',
|
848 |
+
__('Gujarati', 'wpsl') => 'gu',
|
849 |
+
__('Hindi', 'wpsl') => 'hi',
|
850 |
+
__('Croatian', 'wpsl') => 'hr',
|
851 |
+
__('Hungarian', 'wpsl') => 'hu',
|
852 |
+
__('Indonesian', 'wpsl') => 'id',
|
853 |
+
__('Italian', 'wpsl') => 'it',
|
854 |
+
__('Hebrew', 'wpsl') => 'iw',
|
855 |
+
__('Japanese', 'wpsl') => 'ja',
|
856 |
+
__('Kannada', 'wpsl') => 'kn',
|
857 |
+
__('Korean', 'wpsl') => 'ko',
|
858 |
+
__('Lithuanian', 'wpsl') => 'lt',
|
859 |
+
__('Latvian', 'wpsl') => 'lv',
|
860 |
+
__('Malayalam', 'wpsl') => 'ml',
|
861 |
+
__('Marathi', 'wpsl') => 'mr',
|
862 |
+
__('Dutch', 'wpsl') => 'nl',
|
863 |
+
__('Norwegian', 'wpsl') => 'no',
|
864 |
+
__('Norwegian Nynorsk', 'wpsl') => 'nn',
|
865 |
+
__('Polish', 'wpsl') => 'pl',
|
866 |
+
__('Portuguese', 'wpsl') => 'pt',
|
867 |
+
__('Portuguese (Brazil)', 'wpsl') => 'pt-BR',
|
868 |
+
__('Portuguese (Portugal)', 'wpsl') => 'pt-PT',
|
869 |
+
__('Romanian', 'wpsl') => 'ro',
|
870 |
+
__('Russian', 'wpsl') => 'ru',
|
871 |
+
__('Slovak', 'wpsl') => 'sk',
|
872 |
+
__('Slovenian', 'wpsl') => 'sl',
|
873 |
+
__('Serbian', 'wpsl') => 'sr',
|
874 |
+
__('Swedish', 'wpsl') => 'sv',
|
875 |
+
__('Tagalog', 'wpsl') => 'tl',
|
876 |
+
__('Tamil', 'wpsl') => 'ta',
|
877 |
+
__('Telugu', 'wpsl') => 'te',
|
878 |
+
__('Thai', 'wpsl') => 'th',
|
879 |
+
__('Turkish', 'wpsl') => 'tr',
|
880 |
+
__('Ukrainian', 'wpsl') => 'uk',
|
881 |
+
__('Vietnamese', 'wpsl') => 'vi',
|
882 |
+
__('Chinese (Simplified)', 'wpsl') => 'zh-CN',
|
883 |
+
__('Chinese (Traditional)' ,'wpsl') => 'zh-TW'
|
884 |
+
);
|
885 |
+
break;
|
886 |
+
case 'region':
|
887 |
+
$api_option_list = array (
|
888 |
+
__('Select your region', '') => '',
|
889 |
+
__('Afghanistan', 'wpsl') => 'af',
|
890 |
+
__('Albania', 'wpsl') => 'al',
|
891 |
+
__('Algeria', 'wpsl') => 'dz',
|
892 |
+
__('American Samoa', 'wpsl') => 'as',
|
893 |
+
__('Andorra', 'wpsl') => 'ad',
|
894 |
+
__('Anguilla', 'wpsl') => 'ai',
|
895 |
+
__('Angola', 'wpsl') => 'ao',
|
896 |
+
__('Antigua and Barbuda', 'wpsl') => 'ag',
|
897 |
+
__('Argentina', 'wpsl') => 'ar',
|
898 |
+
__('Armenia', 'wpsl') => 'am',
|
899 |
+
__('Aruba', 'wpsl') => 'aw',
|
900 |
+
__('Australia', 'wpsl') => 'au',
|
901 |
+
__('Austria', 'wpsl') => 'at',
|
902 |
+
__('Azerbaijan', 'wpsl') => 'az',
|
903 |
+
__('Bahamas', 'wpsl') => 'bs',
|
904 |
+
__('Bahrain', 'wpsl') => 'bh',
|
905 |
+
__('Bangladesh', 'wpsl') => 'bd',
|
906 |
+
__('Barbados', 'wpsl') => 'bb',
|
907 |
+
__('Belarus', 'wpsl') => 'by',
|
908 |
+
__('Belgium', 'wpsl') => 'be',
|
909 |
+
__('Belize', 'wpsl') => 'bz',
|
910 |
+
__('Benin', 'wpsl') => 'bj',
|
911 |
+
__('Bermuda', 'wpsl') => 'bm',
|
912 |
+
__('Bhutan', 'wpsl') => 'bt',
|
913 |
+
__('Bolivia', 'wpsl') => 'bo',
|
914 |
+
__('Bosnia and Herzegovina', 'wpsl') => 'ba',
|
915 |
+
__('Botswana', 'wpsl') => 'bw',
|
916 |
+
__('Brazil', 'wpsl') => 'br',
|
917 |
+
__('British Indian Ocean Territory', 'wpsl') => 'io',
|
918 |
+
__('Brunei', 'wpsl') => 'bn',
|
919 |
+
__('Bulgaria', 'wpsl') => 'bg',
|
920 |
+
__('Burkina Faso', 'wpsl') => 'bf',
|
921 |
+
__('Burundi', 'wpsl') => 'bi',
|
922 |
+
__('Cambodia', 'wpsl') => 'kh',
|
923 |
+
__('Cameroon', 'wpsl') => 'cm',
|
924 |
+
__('Canada', 'wpsl') => 'ca',
|
925 |
+
__('Cape Verde', 'wpsl') => 'cv',
|
926 |
+
__('Cayman Islands', 'wpsl') => 'ky',
|
927 |
+
__('Central African Republic', 'wpsl') => 'cf',
|
928 |
+
__('Chad', 'wpsl') => 'td',
|
929 |
+
__('Chile', 'wpsl') => 'cl',
|
930 |
+
__('China', 'wpsl') => 'cn',
|
931 |
+
__('Christmas Island', 'wpsl') => 'cx',
|
932 |
+
__('Cocos Islands', 'wpsl') => 'cc',
|
933 |
+
__('Colombia', 'wpsl') => 'co',
|
934 |
+
__('Comoros', 'wpsl') => 'km',
|
935 |
+
__('Congo', 'wpsl') => 'cg',
|
936 |
+
__('Costa Rica', 'wpsl') => 'cr',
|
937 |
+
__('Côte d\'Ivoire', 'wpsl') => 'ci',
|
938 |
+
__('Croatia', 'wpsl') => 'hr',
|
939 |
+
__('Cuba', 'wpsl') => 'cu',
|
940 |
+
__('Czech Republic', 'wpsl') => 'cz',
|
941 |
+
__('Denmark', 'wpsl') => 'dk',
|
942 |
+
__('Djibouti', 'wpsl') => 'dj',
|
943 |
+
__('Democratic Republic of the Congo', 'wpsl') => 'cd',
|
944 |
+
__('Dominica', 'wpsl') => 'dm',
|
945 |
+
__('Dominican Republic', 'wpsl') => 'do',
|
946 |
+
__('Ecuador', 'wpsl') => 'ec',
|
947 |
+
__('Egypt', 'wpsl') => 'eg',
|
948 |
+
__('El Salvador', 'wpsl') => 'sv',
|
949 |
+
__('Equatorial Guinea', 'wpsl') => 'gq',
|
950 |
+
__('Eritrea', 'wpsl') => 'er',
|
951 |
+
__('Estonia', 'wpsl') => 'ee',
|
952 |
+
__('Ethiopia', 'wpsl') => 'et',
|
953 |
+
__('Fiji', 'wpsl') => 'fj',
|
954 |
+
__('Finland', 'wpsl') => 'fi',
|
955 |
+
__('France', 'wpsl') => 'fr',
|
956 |
+
__('French Guiana', 'wpsl') => 'gf',
|
957 |
+
__('Gabon', 'wpsl') => 'ga',
|
958 |
+
__('Gambia', 'wpsl') => 'gm',
|
959 |
+
__('Germany', 'wpsl') => 'de',
|
960 |
+
__('Ghana', 'wpsl') => 'gh',
|
961 |
+
__('Greenland', 'wpsl') => 'gl',
|
962 |
+
__('Greece', 'wpsl') => 'gr',
|
963 |
+
__('Grenada', 'wpsl') => 'gd',
|
964 |
+
__('Guam', 'wpsl') => 'gu',
|
965 |
+
__('Guadeloupe', 'wpsl') => 'gp',
|
966 |
+
__('Guatemala', 'wpsl') => 'gt',
|
967 |
+
__('Guinea', 'wpsl') => 'gn',
|
968 |
+
__('Guinea-Bissau', 'wpsl') => 'gw',
|
969 |
+
__('Haiti', 'wpsl') => 'ht',
|
970 |
+
__('Honduras', 'wpsl') => 'hn',
|
971 |
+
__('Hong Kong', 'wpsl') => 'hk',
|
972 |
+
__('Hungary', 'wpsl') => 'hu',
|
973 |
+
__('Iceland', 'wpsl') => 'is',
|
974 |
+
__('India', 'wpsl') => 'in',
|
975 |
+
__('Indonesia', 'wpsl') => 'id',
|
976 |
+
__('Iran', 'wpsl') => 'ir',
|
977 |
+
__('Iraq', 'wpsl') => 'iq',
|
978 |
+
__('Ireland', 'wpsl') => 'ie',
|
979 |
+
__('Israel', 'wpsl') => 'il',
|
980 |
+
__('Italy', 'wpsl') => 'it',
|
981 |
+
__('Jamaica', 'wpsl') => 'jm',
|
982 |
+
__('Japan', 'wpsl') => 'jp',
|
983 |
+
__('Jordan', 'wpsl') => 'jo',
|
984 |
+
__('Kazakhstan', 'wpsl') => 'kz',
|
985 |
+
__('Kenya', 'wpsl') => 'ke',
|
986 |
+
__('Kuwait', 'wpsl') => 'kw',
|
987 |
+
__('Kyrgyzstan', 'wpsl') => 'kg',
|
988 |
+
__('Laos', 'wpsl') => 'la',
|
989 |
+
__('Latvia', 'wpsl') => 'lv',
|
990 |
+
__('Lebanon', 'wpsl') => 'lb',
|
991 |
+
__('Lesotho', 'wpsl') => 'ls',
|
992 |
+
__('Liberia', 'wpsl') => 'lr',
|
993 |
+
__('Libya', 'wpsl') => 'ly',
|
994 |
+
__('Liechtenstein', 'wpsl') => 'li',
|
995 |
+
__('Lithuania', 'wpsl') => 'lt',
|
996 |
+
__('Luxembourg', 'wpsl') => 'lu',
|
997 |
+
__('Macau', 'wpsl') => 'mo',
|
998 |
+
__('Macedonia', 'wpsl') => 'mk',
|
999 |
+
__('Madagascar', 'wpsl') => 'mg',
|
1000 |
+
__('Malawi', 'wpsl') => 'mw',
|
1001 |
+
__('Malaysia ', 'wpsl') => 'my',
|
1002 |
+
__('Mali', 'wpsl') => 'ml',
|
1003 |
+
__('Marshall Islands', 'wpsl') => 'mh',
|
1004 |
+
__('Martinique', 'wpsl') => 'il',
|
1005 |
+
__('Mauritania', 'wpsl') => 'mr',
|
1006 |
+
__('Mauritius', 'wpsl') => 'mu',
|
1007 |
+
__('Mexico', 'wpsl') => 'mx',
|
1008 |
+
__('Micronesia', 'wpsl') => 'fm',
|
1009 |
+
__('Moldova', 'wpsl') => 'md',
|
1010 |
+
__('Monaco' ,'wpsl') => 'mc',
|
1011 |
+
__('Mongolia', 'wpsl') => 'mn',
|
1012 |
+
__('Montenegro', 'wpsl') => 'me',
|
1013 |
+
__('Montserrat', 'wpsl') => 'ms',
|
1014 |
+
__('Morocco', 'wpsl') => 'ma',
|
1015 |
+
__('Mozambique', 'wpsl') => 'mz',
|
1016 |
+
__('Myanmar', 'wpsl') => 'mm',
|
1017 |
+
__('Namibia', 'wpsl') => 'na',
|
1018 |
+
__('Nauru', 'wpsl') => 'nr',
|
1019 |
+
__('Nepal', 'wpsl') => 'np',
|
1020 |
+
__('Netherlands', 'wpsl') => 'nl',
|
1021 |
+
__('Netherlands Antilles', 'wpsl') => 'an',
|
1022 |
+
__('New Zealand', 'wpsl') => 'nz',
|
1023 |
+
__('Nicaragua', 'wpsl') => 'ni',
|
1024 |
+
__('Niger', 'wpsl') => 'ne',
|
1025 |
+
__('Nigeria', 'wpsl') => 'ng',
|
1026 |
+
__('Niue', 'wpsl') => 'nu',
|
1027 |
+
__('Northern Mariana Islands', 'wpsl') => 'mp',
|
1028 |
+
__('Norway', 'wpsl') => 'no',
|
1029 |
+
__('Oman', 'wpsl') => 'om',
|
1030 |
+
__('Pakistan', 'wpsl') => 'pk',
|
1031 |
+
__('Panama' ,'wpsl') => 'pa',
|
1032 |
+
__('Papua New Guinea', 'wpsl') => 'pg',
|
1033 |
+
__('Paraguay' ,'wpsl') => 'py',
|
1034 |
+
__('Peru', 'wpsl') => 'pe',
|
1035 |
+
__('Philippines', 'wpsl') => 'ph',
|
1036 |
+
__('Pitcairn Islands', 'wpsl') => 'pn',
|
1037 |
+
__('Poland', 'wpsl') => 'pl',
|
1038 |
+
__('Portugal', 'wpsl') => 'pt',
|
1039 |
+
__('Qatar', 'wpsl') => 'qa',
|
1040 |
+
__('Reunion', 'wpsl') => 're',
|
1041 |
+
__('Romania', 'wpsl') => 'ro',
|
1042 |
+
__('Russia', 'wpsl') => 'ru',
|
1043 |
+
__('Rwanda', 'wpsl') => 'rw',
|
1044 |
+
__('Saint Helena', 'wpsl') => 'sh',
|
1045 |
+
__('Saint Kitts and Nevis', 'wpsl') => 'kn',
|
1046 |
+
__('Saint Vincent and the Grenadines', 'wpsl') => 'vc',
|
1047 |
+
__('Saint Lucia', 'wpsl') => 'lc',
|
1048 |
+
__('Samoa', 'wpsl') => 'ws',
|
1049 |
+
__('San Marino', 'wpsl') => 'sm',
|
1050 |
+
__('São Tomé and PrÃncipe', 'wpsl') => 'st',
|
1051 |
+
__('Saudi Arabia', 'wpsl') => 'sa',
|
1052 |
+
__('Senegal', 'wpsl') => 'sn',
|
1053 |
+
__('Serbia', 'wpsl') => 'rs',
|
1054 |
+
__('Seychelles', 'wpsl') => 'sc',
|
1055 |
+
__('Sierra Leone', 'wpsl') => 'sl',
|
1056 |
+
__('Singapore', 'wpsl') => 'sg',
|
1057 |
+
__('Slovakia', 'wpsl') => 'si',
|
1058 |
+
__('Solomon Islands', 'wpsl') => 'sb',
|
1059 |
+
__('Somalia', 'wpsl') => 'so',
|
1060 |
+
__('South Africa', 'wpsl') => 'za',
|
1061 |
+
__('South Korea', 'wpsl') => 'kr',
|
1062 |
+
__('Spain', 'wpsl') => 'es',
|
1063 |
+
__('Sri Lanka', 'wpsl') => 'lk',
|
1064 |
+
__('Sudan', 'wpsl') => 'sd',
|
1065 |
+
__('Swaziland', 'wpsl') => 'sz',
|
1066 |
+
__('Sweden', 'wpsl') => 'se',
|
1067 |
+
__('Switzerland', 'wpsl') => 'ch',
|
1068 |
+
__('Syria', 'wpsl') => 'sy',
|
1069 |
+
__('Taiwan', 'wpsl') => 'tw',
|
1070 |
+
__('Tajikistan', 'wpsl') => 'tj',
|
1071 |
+
__('Tanzania', 'wpsl') => 'tz',
|
1072 |
+
__('Thailand', 'wpsl') => 'th',
|
1073 |
+
__('Timor-Leste', 'wpsl') => 'tl',
|
1074 |
+
__('Tokelau' ,'wpsl') => 'tk',
|
1075 |
+
__('Togo', 'wpsl') => 'tg',
|
1076 |
+
__('Tonga', 'wpsl') => 'to',
|
1077 |
+
__('Trinidad and Tobago', 'wpsl') => 'tt',
|
1078 |
+
__('Tunisia', 'wpsl') => 'tn',
|
1079 |
+
__('Turkey', 'wpsl') => 'tr',
|
1080 |
+
__('Turkmenistan', 'wpsl') => 'tm',
|
1081 |
+
__('Tuvalu', 'wpsl') => 'tv',
|
1082 |
+
__('Uganda', 'wpsl') => 'ug',
|
1083 |
+
__('Ukraine', 'wpsl') => 'ua',
|
1084 |
+
__('United Arab Emirates', 'wpsl') => 'ae',
|
1085 |
+
__('United Kingdom', 'wpsl') => 'gb',
|
1086 |
+
__('United States', 'wpsl') => 'us',
|
1087 |
+
__('Uruguay', 'wpsl') => 'uy',
|
1088 |
+
__('Uzbekistan', 'wpsl') => 'uz',
|
1089 |
+
__('Wallis Futuna', 'wpsl') => 'wf',
|
1090 |
+
__('Venezuela', 'wpsl') => 've',
|
1091 |
+
__('Vietnam', 'wpsl') => 'vn',
|
1092 |
+
__('Yemen', 'wpsl') => 'ye',
|
1093 |
+
__('Zambia' ,'wpsl') => 'zm',
|
1094 |
+
__('Zimbabwe', 'wpsl') => 'zw'
|
1095 |
+
);
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
/* Make sure we have a array with a value */
|
1099 |
+
if ( !empty( $api_option_list ) && ( is_array( $api_option_list ) ) ) {
|
1100 |
+
$i = 0;
|
1101 |
+
|
1102 |
+
foreach ( $api_option_list as $api_option_key => $api_option_value ) {
|
1103 |
+
|
1104 |
+
/* If no option value exist, set the first one as the selected */
|
1105 |
+
if ( ( $i == 0 ) && ( empty( $this->settings['api_'.$list] ) ) ) {
|
1106 |
+
$selected = 'selected="selected"';
|
1107 |
+
} else {
|
1108 |
+
$selected = ( $this->settings['api_'.$list] == $api_option_value ) ? 'selected="selected"' : '';
|
1109 |
+
}
|
1110 |
+
|
1111 |
+
$option_list .= '<option value="' . esc_attr( $api_option_value ) . '"' . $selected . '> ' . esc_html( $api_option_key ) . '</option>';
|
1112 |
+
$i++;
|
1113 |
+
}
|
1114 |
+
|
1115 |
+
return $option_list;
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
/**
|
1121 |
+
* Check if we can use a font for the plugin icon
|
1122 |
+
*
|
1123 |
+
* @since 1.0
|
1124 |
+
* @param $location The location
|
1125 |
+
* @return void
|
1126 |
+
*/
|
1127 |
+
private function check_icon_font_usage( $location ) {
|
1128 |
+
|
1129 |
+
global $wp_version;
|
1130 |
+
|
1131 |
+
if ( ( version_compare( $wp_version, '3.8', '>=' ) == TRUE ) ) {
|
1132 |
+
wp_enqueue_style( 'wpsl-admin-css-38', plugins_url( '/css/style-3.8.css', __FILE__ ), false );
|
1133 |
+
}
|
1134 |
+
}
|
1135 |
+
|
1136 |
+
/**
|
1137 |
+
* Add the required admin script
|
1138 |
+
*
|
1139 |
+
* @since 1.0
|
1140 |
+
* @return void
|
1141 |
+
*/
|
1142 |
+
public function admin_scripts() {
|
1143 |
+
wp_enqueue_media();
|
1144 |
+
wp_enqueue_script( 'jquery-ui-dialog' );
|
1145 |
+
wp_enqueue_style( 'jquery-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/smoothness/jquery-ui.css' );
|
1146 |
+
wp_enqueue_style( 'wpsl-admin-css', plugins_url( '/css/style.css', __FILE__ ), false );
|
1147 |
+
$this->check_icon_font_usage( 'footer' );
|
1148 |
+
wp_enqueue_script( 'wpsl-gmap', ( "//maps.google.com/maps/api/js?sensor=false&libraries=places&language=" . $this->settings['api_language'] ), false ); // we set the language here to make sure the geocode response returns the country name in the correct language
|
1149 |
+
wp_enqueue_script( 'wpsl-admin-js', plugins_url( '/js/wpsl-admin.js', __FILE__ ), array( 'jquery' ), false );
|
1150 |
+
wp_enqueue_script( 'wpsl-queue', plugins_url( '/js/ajax-queue.js', __FILE__ ), array( 'jquery' ), false );
|
1151 |
+
wp_enqueue_script( 'wpsl-retina', plugins_url( '/js/retina-1.1.0.js', __FILE__ ), array( 'jquery' ), false );
|
1152 |
+
}
|
1153 |
+
}
|
1154 |
+
|
1155 |
+
new WPSL_Admin;
|
1156 |
+
}
|
admin/class-store-overview.php
ADDED
@@ -0,0 +1,411 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
if ( !class_exists( 'WP_List_Table' ) ) {
|
3 |
+
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
4 |
+
}
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class to create the table layout
|
8 |
+
*
|
9 |
+
* @package WordPress
|
10 |
+
* @subpackage List_Table
|
11 |
+
* @since 1.0
|
12 |
+
*/
|
13 |
+
class WPSL_Store_Overview extends WP_List_Table {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Set the amount of stores that are shown on each page
|
17 |
+
* @since 1.0
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
private $_per_page = 10;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Class constructor
|
24 |
+
*/
|
25 |
+
function __construct() {
|
26 |
+
|
27 |
+
global $status, $page;
|
28 |
+
|
29 |
+
parent::__construct( array(
|
30 |
+
'singular' => __( 'Store', 'wpsl' ),
|
31 |
+
'plural' => __( 'Stores', 'wpsl' ),
|
32 |
+
'ajax' => true
|
33 |
+
) );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* The default message that is shown when no store data exists
|
38 |
+
*
|
39 |
+
* @since 1.0
|
40 |
+
* @return string The default message
|
41 |
+
*/
|
42 |
+
function no_items() {
|
43 |
+
_e( 'No stores found', 'wpsl' );
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Set the default values for each column
|
48 |
+
*
|
49 |
+
* @since 1.0
|
50 |
+
* @param array $item Data for a single column row
|
51 |
+
* @param array $column_name The name of the column
|
52 |
+
* @return mixed The value for each column
|
53 |
+
*/
|
54 |
+
function column_default( $item, $column_name ) {
|
55 |
+
|
56 |
+
switch( $column_name ) {
|
57 |
+
case 'wpsl_id':
|
58 |
+
case 'store':
|
59 |
+
case 'street':
|
60 |
+
case 'city':
|
61 |
+
case 'state':
|
62 |
+
case 'zip':
|
63 |
+
return $item[$column_name];
|
64 |
+
case 'thumb':
|
65 |
+
if ( $item['thumb'] !== '0' ) {
|
66 |
+
$thumb = '<img src="' . $item['thumb'] . '" width="36" height="36" />';
|
67 |
+
} else {
|
68 |
+
$thumb = '';
|
69 |
+
}
|
70 |
+
|
71 |
+
return $thumb;
|
72 |
+
case 'active':
|
73 |
+
return ( $item['active'] ) ? __( 'Active', 'wpsl' ) : __( 'Inactive', 'wpsl' );
|
74 |
+
case 'action':
|
75 |
+
return '<a class="button" href="' . admin_url( 'admin.php?page=wpsl_store_editor&action=edit_store&store_id=' . $item['wpsl_id'] ) . '">'. __( 'Edit', 'wpsl' ) . '</a><input type="button" class="button wpsl-delete-store-btn" name="text" value="Delete"><input name="wpsl_store_id" type="hidden" value="' . $item['wpsl_id'] . '" /><input name="wpsl_delete_nonce" type="hidden" value="' . wp_create_nonce( 'wpsl_delete_nonce_'.$item['wpsl_id'] ) . '" />';
|
76 |
+
default:
|
77 |
+
return 'wpsl_id';
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Define which columns should be sortable
|
83 |
+
*
|
84 |
+
* @since 1.0
|
85 |
+
* @return array $sortable_columns The list of sortable scolumns
|
86 |
+
*/
|
87 |
+
function get_sortable_columns() {
|
88 |
+
|
89 |
+
$sortable_columns = array(
|
90 |
+
'wpsl_id' => array( 'wpsl_id', true ), //true = already sorted ( default )
|
91 |
+
'thumb' => array( 'thumb', false ),
|
92 |
+
'store' => array( 'store', false ),
|
93 |
+
'street' => array( 'street', false ),
|
94 |
+
'city' => array( 'city', false ),
|
95 |
+
'state' => array( 'state', false ),
|
96 |
+
'zip' => array( 'zip', false ),
|
97 |
+
'active' => array( 'active', false )
|
98 |
+
);
|
99 |
+
|
100 |
+
return $sortable_columns;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Get the list of columns
|
105 |
+
*
|
106 |
+
* @since 1.0
|
107 |
+
* @return array $columns The list of columns
|
108 |
+
*/
|
109 |
+
function get_columns() {
|
110 |
+
|
111 |
+
$columns = array(
|
112 |
+
'cb' => '<input type="checkbox" />',
|
113 |
+
'wpsl_id' => __( 'ID', 'wpsl' ),
|
114 |
+
'thumb' => __( 'Thumbnail', 'wpsl' ),
|
115 |
+
'store' => __( 'Name', 'wpsl' ),
|
116 |
+
'street' => __( 'Address', 'wpsl' ),
|
117 |
+
'city' => __( 'City', 'wpsl' ),
|
118 |
+
'state' => __( 'State', 'wpsl' ),
|
119 |
+
'zip' => __( 'Zip', 'wpsl' ),
|
120 |
+
'active' => __( 'Status', 'wpsl' ),
|
121 |
+
'action' => __( 'Actions', 'wpsl' ),
|
122 |
+
);
|
123 |
+
|
124 |
+
return $columns;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Set the data for a checkbox column
|
129 |
+
*
|
130 |
+
* @since 1.0
|
131 |
+
* @param array $item The store data for this table row
|
132 |
+
* @return string The html for the checkbox with the correct value set
|
133 |
+
*/
|
134 |
+
function column_cb( $item ) {
|
135 |
+
return sprintf(
|
136 |
+
'<input type="checkbox" name="store[]" value="%s" />', $item['wpsl_id']
|
137 |
+
);
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Get the list of available bulk actions
|
142 |
+
*
|
143 |
+
* @since 1.0
|
144 |
+
* @return array $actions The list of bulk actions
|
145 |
+
*/
|
146 |
+
function get_bulk_actions() {
|
147 |
+
|
148 |
+
$actions = array(
|
149 |
+
'delete' => 'Delete',
|
150 |
+
'activate' => 'Activate',
|
151 |
+
'deactivate' => 'Deactivate'
|
152 |
+
);
|
153 |
+
|
154 |
+
return $actions;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Change the store status into either active or inactive
|
159 |
+
*
|
160 |
+
* @since 1.0
|
161 |
+
* @param string $store_ids The list of store ids
|
162 |
+
* @param string $status Is set to either activate or deactivate
|
163 |
+
* @return void
|
164 |
+
*/
|
165 |
+
function update_store_status( $store_ids, $status ) {
|
166 |
+
|
167 |
+
global $wpdb;
|
168 |
+
|
169 |
+
if ( $status === 'deactivate' ) {
|
170 |
+
$active_status = 0;
|
171 |
+
$success_action_desc = __( 'deactivated', 'wpsl' );
|
172 |
+
$fail_action_desc = __( 'deactivating', 'wpsl' );
|
173 |
+
} else {
|
174 |
+
$active_status = 1;
|
175 |
+
$success_action_desc = __( 'activated', 'wpsl' );
|
176 |
+
$fail_action_desc = __( 'activating', 'wpsl' );
|
177 |
+
}
|
178 |
+
|
179 |
+
$result = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->wpsl_stores SET active = %d WHERE wpsl_id IN ( $store_ids )", $active_status ) );
|
180 |
+
|
181 |
+
if ( $result === false ) {
|
182 |
+
$state = 'error';
|
183 |
+
$msg = __( 'There was a problem ' . $fail_action_desc . ' the store(s), please try again.', 'wpsl' );
|
184 |
+
} else {
|
185 |
+
$state = 'updated';
|
186 |
+
$msg = __( 'Store(s) successfully ' . $success_action_desc , 'wpsl' );
|
187 |
+
}
|
188 |
+
|
189 |
+
add_settings_error ( 'bulk-state', esc_attr( 'bulk-state' ), $msg, $state );
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Remove the selected stores from the db
|
194 |
+
*
|
195 |
+
* @since 1.0
|
196 |
+
* @param string $store_ids The list of store ids that should be deleted.
|
197 |
+
* @return void
|
198 |
+
*/
|
199 |
+
function remove_stores( $store_ids ) {
|
200 |
+
|
201 |
+
global $wpdb;
|
202 |
+
|
203 |
+
$result = $wpdb->query( "DELETE FROM $wpdb->wpsl_stores WHERE wpsl_id IN ( $store_ids )" );
|
204 |
+
|
205 |
+
if ( $result === false ) {
|
206 |
+
$state = 'error';
|
207 |
+
$msg = __( 'There was a problem removing the store(s), please try again.', 'wpsl' );
|
208 |
+
} else {
|
209 |
+
$state = 'updated';
|
210 |
+
$msg = __( 'Store(s) successfully removed.' , 'wpsl' );
|
211 |
+
}
|
212 |
+
|
213 |
+
add_settings_error ( 'bulk-remove', esc_attr( 'bulk-remove' ), $msg, $state );
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Process the bulk actions
|
218 |
+
*
|
219 |
+
* @since 1.0
|
220 |
+
* @return void
|
221 |
+
*/
|
222 |
+
function process_bulk_action() {
|
223 |
+
|
224 |
+
if ( !current_user_can( 'manage_options' ) )
|
225 |
+
die( '-1' );
|
226 |
+
|
227 |
+
if ( isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ) {
|
228 |
+
$nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
|
229 |
+
$action = 'bulk-' . $this->_args['plural'];
|
230 |
+
|
231 |
+
if ( !wp_verify_nonce( $nonce, $action ) )
|
232 |
+
wp_die( 'Nope! Security check failed!' );
|
233 |
+
|
234 |
+
$action = $this->current_action();
|
235 |
+
|
236 |
+
if ( !empty ( $action ) ) {
|
237 |
+
$id_list = array();
|
238 |
+
|
239 |
+
foreach ( $_POST['store'] as $store_id ) {
|
240 |
+
$id_list[] = $store_id;
|
241 |
+
}
|
242 |
+
|
243 |
+
/* Before checking which type of bulk action to run, we make sure we actually have some ids to process */
|
244 |
+
if ( !empty( $id_list ) ) {
|
245 |
+
$store_ids = esc_sql( implode( ',', wp_parse_id_list( $id_list ) ) );
|
246 |
+
|
247 |
+
switch ( $action ) {
|
248 |
+
case 'activate':
|
249 |
+
$this->update_store_status( $store_ids, 'activate' );
|
250 |
+
break;
|
251 |
+
case 'deactivate':
|
252 |
+
$this->update_store_status( $store_ids, 'deactivate' );
|
253 |
+
break;
|
254 |
+
case 'delete':
|
255 |
+
$this->remove_stores( $store_ids );
|
256 |
+
break;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
}
|
260 |
+
}
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Get the required store data for the table list
|
265 |
+
*
|
266 |
+
* @since 1.0
|
267 |
+
* @return array $response The required store data
|
268 |
+
*/
|
269 |
+
function get_store_list() {
|
270 |
+
|
271 |
+
global $wpdb;
|
272 |
+
|
273 |
+
/* Check if we need to run the search query or just show all the data */
|
274 |
+
if ( isset( $_POST['s'] ) ){
|
275 |
+
$search = trim( $_POST['s'] );
|
276 |
+
$result = $wpdb->get_results(
|
277 |
+
$wpdb->prepare( "SELECT wpsl_id, store, street, city, state, zip, thumb_id AS thumb, active
|
278 |
+
FROM $wpdb->wpsl_stores
|
279 |
+
WHERE store LIKE %s OR street LIKE %s OR city LIKE %s OR state LIKE %s OR zip LIKE %s",
|
280 |
+
'%' . like_escape( $search ). '%', '%' . like_escape( $search ). '%', '%' . like_escape( $search ). '%', '%' . like_escape( $search ). '%', '%' . like_escape( $search ). '%'
|
281 |
+
), ARRAY_A
|
282 |
+
);
|
283 |
+
} else {
|
284 |
+
/* Order params */
|
285 |
+
$orderby = !empty ( $_GET["orderby"] ) ? mysql_real_escape_string ( $_GET["orderby"] ) : 'wpsl_id';
|
286 |
+
$order = !empty ( $_GET["order"] ) ? mysql_real_escape_string ( $_GET["order"] ) : 'ASC';
|
287 |
+
$order_sql = $orderby.' '.$order;
|
288 |
+
|
289 |
+
/* Pagination parameters */
|
290 |
+
$total_items = $wpdb->get_var( "SELECT COUNT(*) AS count FROM $wpdb->wpsl_stores" );
|
291 |
+
$paged = !empty ( $_GET["paged"] ) ? mysql_real_escape_string ( $_GET["paged"] ) : '';
|
292 |
+
|
293 |
+
if ( empty( $paged ) || !is_numeric( $paged ) || $paged <= 0 ) {
|
294 |
+
$paged = 1;
|
295 |
+
}
|
296 |
+
|
297 |
+
$totalpages = ceil( $total_items / $this->_per_page );
|
298 |
+
|
299 |
+
if ( !empty( $paged ) && !empty( $this->_per_page ) ){
|
300 |
+
$offset = ( $paged - 1 ) * $this->_per_page;
|
301 |
+
$limit_sql = (int)$offset.',' . (int)$this->_per_page;
|
302 |
+
}
|
303 |
+
|
304 |
+
$result = $wpdb->get_results( "SELECT wpsl_id, store, street, city, state, zip, thumb_id AS thumb, active FROM $wpdb->wpsl_stores ORDER BY $order_sql LIMIT $limit_sql", ARRAY_A );
|
305 |
+
}
|
306 |
+
|
307 |
+
$i = 0;
|
308 |
+
foreach ( $result as $k => $store_details ) {
|
309 |
+
|
310 |
+
/* Check for thumbnails */
|
311 |
+
if ( absint ( $store_details["thumb"] ) ) {
|
312 |
+
$thumb_src = wp_get_attachment_image_src( $store_details["thumb"] );
|
313 |
+
$result[$i]["thumb"] = $thumb_src[0];
|
314 |
+
}
|
315 |
+
|
316 |
+
$i++;
|
317 |
+
}
|
318 |
+
|
319 |
+
$response = array(
|
320 |
+
"data" => $result,
|
321 |
+
"count" => $total_items
|
322 |
+
);
|
323 |
+
|
324 |
+
return $response;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Prepares the list of items for displaying.
|
329 |
+
*
|
330 |
+
* @since 1.0
|
331 |
+
* @uses WP_List_Table::set_pagination_args()
|
332 |
+
* @return void
|
333 |
+
*/
|
334 |
+
function prepare_items() {
|
335 |
+
|
336 |
+
$columns = $this->get_columns();
|
337 |
+
$hidden = array();
|
338 |
+
$sortable = $this->get_sortable_columns();
|
339 |
+
|
340 |
+
$this->process_bulk_action();
|
341 |
+
$response = $this->get_store_list();
|
342 |
+
|
343 |
+
$current_page = $this->get_pagenum();
|
344 |
+
$total_items = $response['count'];
|
345 |
+
|
346 |
+
$this->set_pagination_args( array(
|
347 |
+
'total_items' => $total_items,
|
348 |
+
'per_page' => $this->_per_page,
|
349 |
+
'total_pages' => ceil( $total_items / $this->_per_page )
|
350 |
+
) );
|
351 |
+
|
352 |
+
$this->items = $response['data'];
|
353 |
+
$this->_column_headers = array( $columns, $hidden, $sortable );
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Display the table with the store list
|
358 |
+
*
|
359 |
+
* @since 1.0
|
360 |
+
* @uses WP_List_Table::display_tablenav()
|
361 |
+
* @uses WP_List_Table::get_table_classes()
|
362 |
+
* @uses WP_List_Table::print_column_headers()
|
363 |
+
* @uses WP_List_Table::display_rows_or_placeholder()
|
364 |
+
* @return void
|
365 |
+
*/
|
366 |
+
function display() {
|
367 |
+
extract( $this->_args );
|
368 |
+
|
369 |
+
$this->display_tablenav( 'top' );
|
370 |
+
?>
|
371 |
+
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
|
372 |
+
<thead>
|
373 |
+
<tr>
|
374 |
+
<?php $this->print_column_headers(); ?>
|
375 |
+
</tr>
|
376 |
+
</thead>
|
377 |
+
|
378 |
+
<tfoot>
|
379 |
+
<tr>
|
380 |
+
<?php $this->print_column_headers( false ); ?>
|
381 |
+
</tr>
|
382 |
+
</tfoot>
|
383 |
+
|
384 |
+
<tbody id="the-list"<?php if ( $singular ) echo " data-wp-lists='list:$singular'"; ?>>
|
385 |
+
<?php $this->display_rows_or_placeholder(); ?>
|
386 |
+
</tbody>
|
387 |
+
</table>
|
388 |
+
<div id="wpsl-delete-confirmation">
|
389 |
+
<p><?php _e( 'Are you sure you want to delete this store?', 'wpsl' ); ?></p>
|
390 |
+
<p>
|
391 |
+
<input class="button-primary" type="submit" name="delete" value="<?php _e( 'Delete', 'wpsl' ); ?>" />
|
392 |
+
<input class="button-secondary dialog-cancel" type="reset" value="<?php _e( 'Cancel', 'wpsl' ); ?>" />
|
393 |
+
</p>
|
394 |
+
</div>
|
395 |
+
<?php
|
396 |
+
$this->display_tablenav( 'bottom' );
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Send required variables to JavaScript land
|
401 |
+
*/
|
402 |
+
function _js_vars() {
|
403 |
+
|
404 |
+
$args = array(
|
405 |
+
'url' => WPSL_URL
|
406 |
+
);
|
407 |
+
|
408 |
+
printf( "<script type='text/javascript'>var wpsl_data = %s;</script>\n", json_encode( $args ) );
|
409 |
+
}
|
410 |
+
|
411 |
+
}
|
admin/css/style-3.8.css
ADDED
@@ -0,0 +1,29 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@font-face {
|
2 |
+
font-family: 'fontello';
|
3 |
+
src: url('../font/fontello.eot?92013519');
|
4 |
+
src: url('../font/fontello.eot?92013519#iefix') format('embedded-opentype'),
|
5 |
+
url('../font/fontello.woff?92013519') format('woff'),
|
6 |
+
url('../font/fontello.ttf?92013519') format('truetype'),
|
7 |
+
url('../font/fontello.svg?92013519#fontello') format('svg');
|
8 |
+
font-weight: normal;
|
9 |
+
font-style: normal;
|
10 |
+
}
|
11 |
+
|
12 |
+
#adminmenu #toplevel_page_wpsl_store_editor .wp-menu-image:before {
|
13 |
+
content: '\e800';
|
14 |
+
display: inline-block;
|
15 |
+
font-family: "fontello" !important;
|
16 |
+
font-style: normal;
|
17 |
+
font-variant: normal;
|
18 |
+
font-weight: 400;
|
19 |
+
line-height: 1em;
|
20 |
+
text-align: center;
|
21 |
+
text-decoration: inherit;
|
22 |
+
text-transform: none;
|
23 |
+
width: 1em;
|
24 |
+
}
|
25 |
+
|
26 |
+
/* Hide the pre 3.8 menu icon */
|
27 |
+
#adminmenu #toplevel_page_wpsl_store_editor .wp-menu-image img {
|
28 |
+
display:none;
|
29 |
+
}
|
admin/css/style.css
ADDED
@@ -0,0 +1,229 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
#wpsl-store-overview .widefat td,
|
2 |
+
#wpsl-wrap .widefat td {
|
3 |
+
padding:12px 7px;
|
4 |
+
}
|
5 |
+
|
6 |
+
#wpsl-store-overview .column-action a {
|
7 |
+
float:left;
|
8 |
+
margin-right:5px;
|
9 |
+
}
|
10 |
+
|
11 |
+
#wpsl-store-overview .widefat td.thumb {
|
12 |
+
padding:6px 0 0 8px;
|
13 |
+
}
|
14 |
+
|
15 |
+
#wpsl-store-overview .thumb img {
|
16 |
+
border-radius:3px;
|
17 |
+
}
|
18 |
+
|
19 |
+
#wpsl-store-overview p.search-box {
|
20 |
+
margin:0 0 1em 0;
|
21 |
+
}
|
22 |
+
|
23 |
+
.column-action {
|
24 |
+
width:130px;
|
25 |
+
}
|
26 |
+
#wpsl-delete-confirmation {
|
27 |
+
display:none;
|
28 |
+
}
|
29 |
+
.wpsl-preloader {
|
30 |
+
float:right;
|
31 |
+
margin:4px 0 0 4px;
|
32 |
+
}
|
33 |
+
|
34 |
+
/* Plugin nav */
|
35 |
+
#wpsl-mainnav {
|
36 |
+
border-bottom: 1px solid #CCCCCC;
|
37 |
+
float: left;
|
38 |
+
margin-bottom: 15px;
|
39 |
+
padding-left: 7px;
|
40 |
+
width: 99.4%;
|
41 |
+
}
|
42 |
+
#wpsl-mainnav li a {
|
43 |
+
display: block;
|
44 |
+
padding: 9px 12px;
|
45 |
+
text-decoration: none;
|
46 |
+
}
|
47 |
+
|
48 |
+
#wpsl-mainnav li {
|
49 |
+
float: left;
|
50 |
+
margin: 0;
|
51 |
+
}
|
52 |
+
|
53 |
+
#wpsl-wrap.wpsl-add-stores label,
|
54 |
+
#wpsl-wrap label {
|
55 |
+
width:85px;
|
56 |
+
margin-top:6px;
|
57 |
+
}
|
58 |
+
|
59 |
+
.wpsl-radioboxes {
|
60 |
+
float:left;
|
61 |
+
margin:5px 0 6px 1px;
|
62 |
+
}
|
63 |
+
#wpsl-wrap.wpsl-add-stores label {
|
64 |
+
float:left;
|
65 |
+
}
|
66 |
+
#wpsl-wrap.wpsl-add-stores p {
|
67 |
+
overflow:hidden;
|
68 |
+
}
|
69 |
+
#wpsl-wrap.wpsl-add-stores .wpsl-radioboxes label {
|
70 |
+
float:none;
|
71 |
+
margin-right:10px;
|
72 |
+
}
|
73 |
+
|
74 |
+
#wpsl-wrap em {
|
75 |
+
display:block;
|
76 |
+
}
|
77 |
+
#wpsl-wrap textarea {
|
78 |
+
width:340px;
|
79 |
+
resize:none;
|
80 |
+
}
|
81 |
+
|
82 |
+
.wpsl-curve {
|
83 |
+
border-radius:3px;
|
84 |
+
}
|
85 |
+
|
86 |
+
#wpsl-wrap .wpsl-error {
|
87 |
+
border:1px solid #c01313;
|
88 |
+
}
|
89 |
+
|
90 |
+
.wpsl-submit-wrap,
|
91 |
+
#wpsl-thumb-wrap div {
|
92 |
+
margin-left:85px;
|
93 |
+
}
|
94 |
+
#wpsl-lookup-location {
|
95 |
+
margin-bottom:2px;
|
96 |
+
}
|
97 |
+
|
98 |
+
#wpsl-wrap input[type=text],
|
99 |
+
#wpsl-wrap input[type=email],
|
100 |
+
#wpsl-wrap input[type=url] {
|
101 |
+
width:340px;
|
102 |
+
}
|
103 |
+
|
104 |
+
#wpsl-wrap.wpsl-settings input[type=text].textinput {
|
105 |
+
width:255px;
|
106 |
+
}
|
107 |
+
|
108 |
+
.wpsl-add-store {
|
109 |
+
float:left;
|
110 |
+
width:100%;
|
111 |
+
clear:both;
|
112 |
+
}
|
113 |
+
|
114 |
+
#wpsl-wrap .metabox-holder {
|
115 |
+
float:left;
|
116 |
+
margin-right:20px;
|
117 |
+
}
|
118 |
+
#wpsl-wrap .metabox-holder.wpsl-wide {
|
119 |
+
width:100%;
|
120 |
+
padding-top:0;
|
121 |
+
}
|
122 |
+
|
123 |
+
#wpsl-wrap .wpsl-edit-header {
|
124 |
+
margin-bottom:12px;
|
125 |
+
}
|
126 |
+
|
127 |
+
#wpsl-thumb-wrap {
|
128 |
+
width:100%;
|
129 |
+
overflow:hidden;
|
130 |
+
}
|
131 |
+
|
132 |
+
#wpsl-thumb-wrap p {
|
133 |
+
margin-top:0;
|
134 |
+
}
|
135 |
+
|
136 |
+
#wpsl-thumb-wrap div {
|
137 |
+
float:left;
|
138 |
+
clear:both;
|
139 |
+
}
|
140 |
+
.wpsl-thumb-placeholder {
|
141 |
+
background: none repeat scroll 0 0 #FFFFFF;
|
142 |
+
border: 1px dashed #CCCCCC;
|
143 |
+
border-radius: 3px 3px 3px 3px;
|
144 |
+
float: left;
|
145 |
+
height: 85px;
|
146 |
+
width: 85px;
|
147 |
+
margin-bottom:10px;
|
148 |
+
}
|
149 |
+
|
150 |
+
#wpsl-wrap.wpsl-settings .metabox-holder {
|
151 |
+
width:100%;
|
152 |
+
}
|
153 |
+
#wpsl-wrap.wpsl-settings .metabox-holder h3:hover {
|
154 |
+
cursor: auto;
|
155 |
+
}
|
156 |
+
#wpsl-gmap-wrap {
|
157 |
+
float:left;
|
158 |
+
width:451px;
|
159 |
+
height:250px;
|
160 |
+
border-radius:3px;
|
161 |
+
margin-top:0;
|
162 |
+
margin-bottom:20px;
|
163 |
+
clear:both;
|
164 |
+
}
|
165 |
+
|
166 |
+
/* Markers */
|
167 |
+
.wpsl-marker-list {
|
168 |
+
overflow:hidden;
|
169 |
+
}
|
170 |
+
.wpsl-marker-list li {
|
171 |
+
float:left;
|
172 |
+
padding:10px;
|
173 |
+
margin-right:5px;
|
174 |
+
text-align:center;
|
175 |
+
}
|
176 |
+
.wpsl-marker-list li input[type="radio"] {
|
177 |
+
margin-right:0;
|
178 |
+
}
|
179 |
+
.wpsl-marker-list img {
|
180 |
+
display:block;
|
181 |
+
margin-bottom:7px;
|
182 |
+
}
|
183 |
+
.wpsl-marker-list li:hover,
|
184 |
+
.wpsl-active-marker {
|
185 |
+
background:#E4E4E4;
|
186 |
+
border-radius:5px;
|
187 |
+
cursor: pointer;
|
188 |
+
}
|
189 |
+
|
190 |
+
/* Settings page */
|
191 |
+
#wpsl-settings-form .postbox-container {
|
192 |
+
width:535px;
|
193 |
+
clear:both;
|
194 |
+
}
|
195 |
+
#wpsl-wrap .metabox-holder {
|
196 |
+
padding-top:0;
|
197 |
+
}
|
198 |
+
|
199 |
+
#wpsl-settings-form label {
|
200 |
+
position:relative;
|
201 |
+
display: inline-block;
|
202 |
+
font-weight: normal;
|
203 |
+
margin: 0 10px 0 0;
|
204 |
+
width: 220px;
|
205 |
+
}
|
206 |
+
|
207 |
+
#wpsl-save-settings {
|
208 |
+
float:left;
|
209 |
+
clear:both;
|
210 |
+
}
|
211 |
+
#wpsl-settings-form .wpsl_radioboxes label {
|
212 |
+
float:none;
|
213 |
+
margin-right: 10px;
|
214 |
+
width: auto;
|
215 |
+
}
|
216 |
+
|
217 |
+
#wpsl-faq dt {
|
218 |
+
margin-bottom:4px;
|
219 |
+
font-weight:bold;
|
220 |
+
font-size:110%;
|
221 |
+
}
|
222 |
+
|
223 |
+
#wpsl-faq dd {
|
224 |
+
margin-left: 0;
|
225 |
+
}
|
226 |
+
|
227 |
+
#wpsl-faq dl {
|
228 |
+
margin-bottom: 17px;
|
229 |
+
}
|
admin/font/fontello.eot
ADDED
Binary file
|
admin/font/fontello.svg
ADDED
@@ -0,0 +1,12 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0" standalone="no"?>
|
2 |
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
3 |
+
<svg xmlns="http://www.w3.org/2000/svg">
|
4 |
+
<metadata>Copyright (C) 2013 by original authors @ fontello.com</metadata>
|
5 |
+
<defs>
|
6 |
+
<font id="fontello" horiz-adv-x="1000" >
|
7 |
+
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
|
8 |
+
<missing-glyph horiz-adv-x="1000" />
|
9 |
+
<glyph glyph-name="location" unicode="" d="m429 493q0 59-42 101t-101 42t-101-42t-42-101t42-101t101-42t101 42t42 101z m142 0q0-61-18-100l-203-432q-9-18-27-29t-37-11t-38 11t-26 29l-204 432q-18 39-18 100q0 118 84 202t202 84t202-84t83-202z" horiz-adv-x="571.4" />
|
10 |
+
</font>
|
11 |
+
</defs>
|
12 |
+
</svg>
|
admin/font/fontello.ttf
ADDED
Binary file
|
admin/font/fontello.woff
ADDED
Binary file
|
admin/js/ajax-queue.js
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* jQuery.ajaxQueue - A queue for ajax requests
|
3 |
+
*
|
4 |
+
* (c) 2011 Corey Frang
|
5 |
+
* Dual licensed under the MIT and GPL licenses.
|
6 |
+
*
|
7 |
+
* Requires jQuery 1.5+
|
8 |
+
*/
|
9 |
+
(function($) {
|
10 |
+
|
11 |
+
// jQuery on an empty object, we are going to use this as our Queue
|
12 |
+
var ajaxQueue = $({});
|
13 |
+
|
14 |
+
$.ajaxQueue = function( ajaxOpts ) {
|
15 |
+
var jqXHR,
|
16 |
+
dfd = $.Deferred(),
|
17 |
+
promise = dfd.promise();
|
18 |
+
|
19 |
+
// run the actual query
|
20 |
+
function doRequest( next ) {
|
21 |
+
jqXHR = $.ajax( ajaxOpts );
|
22 |
+
jqXHR.done( dfd.resolve )
|
23 |
+
.fail( dfd.reject )
|
24 |
+
.then( next, next );
|
25 |
+
}
|
26 |
+
|
27 |
+
// queue our ajax request
|
28 |
+
ajaxQueue.queue( doRequest );
|
29 |
+
|
30 |
+
// add the abort method
|
31 |
+
promise.abort = function( statusText ) {
|
32 |
+
|
33 |
+
// proxy abort to the jqXHR if it is active
|
34 |
+
if ( jqXHR ) {
|
35 |
+
return jqXHR.abort( statusText );
|
36 |
+
}
|
37 |
+
|
38 |
+
// if there wasn't already a jqXHR we need to remove from queue
|
39 |
+
var queue = ajaxQueue.queue(),
|
40 |
+
index = $.inArray( doRequest, queue );
|
41 |
+
|
42 |
+
if ( index > -1 ) {
|
43 |
+
queue.splice( index, 1 );
|
44 |
+
}
|
45 |
+
|
46 |
+
// and then reject the deferred
|
47 |
+
dfd.rejectWith( ajaxOpts.context || ajaxOpts, [ promise, statusText, "" ] );
|
48 |
+
return promise;
|
49 |
+
};
|
50 |
+
|
51 |
+
return promise;
|
52 |
+
};
|
53 |
+
|
54 |
+
})(jQuery);
|
admin/js/retina-1.1.0.js
ADDED
@@ -0,0 +1,152 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*!
|
2 |
+
* Retina.js v1.1.0
|
3 |
+
*
|
4 |
+
* Copyright 2013 Imulus, LLC
|
5 |
+
* Released under the MIT license
|
6 |
+
*
|
7 |
+
* Retina.js is an open source script that makes it easy to serve
|
8 |
+
* high-resolution images to devices with retina displays.
|
9 |
+
*/
|
10 |
+
(function() {
|
11 |
+
|
12 |
+
var root = (typeof exports == 'undefined' ? window : exports);
|
13 |
+
|
14 |
+
var config = {
|
15 |
+
// Ensure Content-Type is an image before trying to load @2x image
|
16 |
+
// https://github.com/imulus/retinajs/pull/45)
|
17 |
+
check_mime_type: true
|
18 |
+
};
|
19 |
+
|
20 |
+
|
21 |
+
|
22 |
+
root.Retina = Retina;
|
23 |
+
|
24 |
+
function Retina() {}
|
25 |
+
|
26 |
+
Retina.configure = function(options) {
|
27 |
+
if (options == null) options = {};
|
28 |
+
for (var prop in options) config[prop] = options[prop];
|
29 |
+
};
|
30 |
+
|
31 |
+
Retina.init = function(context) {
|
32 |
+
if (context == null) context = root;
|
33 |
+
|
34 |
+
var existing_onload = context.onload || new Function;
|
35 |
+
|
36 |
+
context.onload = function() {
|
37 |
+
var images = document.getElementsByTagName("img"), retinaImages = [], i, image;
|
38 |
+
for (i = 0; i < images.length; i++) {
|
39 |
+
image = images[i];
|
40 |
+
retinaImages.push(new RetinaImage(image));
|
41 |
+
}
|
42 |
+
existing_onload();
|
43 |
+
}
|
44 |
+
};
|
45 |
+
|
46 |
+
Retina.isRetina = function(){
|
47 |
+
var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
|
48 |
+
(min--moz-device-pixel-ratio: 1.5),\
|
49 |
+
(-o-min-device-pixel-ratio: 3/2),\
|
50 |
+
(min-resolution: 1.5dppx)";
|
51 |
+
|
52 |
+
if (root.devicePixelRatio > 1)
|
53 |
+
return true;
|
54 |
+
|
55 |
+
if (root.matchMedia && root.matchMedia(mediaQuery).matches)
|
56 |
+
return true;
|
57 |
+
|
58 |
+
return false;
|
59 |
+
};
|
60 |
+
|
61 |
+
|
62 |
+
root.RetinaImagePath = RetinaImagePath;
|
63 |
+
|
64 |
+
function RetinaImagePath(path, at_2x_path) {
|
65 |
+
this.path = path;
|
66 |
+
if (typeof at_2x_path !== "undefined" && at_2x_path !== null) {
|
67 |
+
this.at_2x_path = at_2x_path;
|
68 |
+
this.perform_check = false;
|
69 |
+
} else {
|
70 |
+
this.at_2x_path = path.replace(/\.\w+$/, function(match) { return "@2x" + match; });
|
71 |
+
this.perform_check = true;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
RetinaImagePath.confirmed_paths = [];
|
76 |
+
|
77 |
+
RetinaImagePath.prototype.is_external = function() {
|
78 |
+
return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) )
|
79 |
+
}
|
80 |
+
|
81 |
+
RetinaImagePath.prototype.check_2x_variant = function(callback) {
|
82 |
+
var http, that = this;
|
83 |
+
if (this.is_external()) {
|
84 |
+
return callback(false);
|
85 |
+
} else if (!this.perform_check && typeof this.at_2x_path !== "undefined" && this.at_2x_path !== null) {
|
86 |
+
return callback(true);
|
87 |
+
} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
|
88 |
+
return callback(true);
|
89 |
+
} else {
|
90 |
+
http = new XMLHttpRequest;
|
91 |
+
http.open('HEAD', this.at_2x_path);
|
92 |
+
http.onreadystatechange = function() {
|
93 |
+
if (http.readyState != 4) {
|
94 |
+
return callback(false);
|
95 |
+
}
|
96 |
+
|
97 |
+
if (http.status >= 200 && http.status <= 399) {
|
98 |
+
if (config.check_mime_type) {
|
99 |
+
var type = http.getResponseHeader('Content-Type');
|
100 |
+
if (type == null || !type.match(/^image/i)) {
|
101 |
+
return callback(false);
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
RetinaImagePath.confirmed_paths.push(that.at_2x_path);
|
106 |
+
return callback(true);
|
107 |
+
} else {
|
108 |
+
return callback(false);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
http.send();
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
|
116 |
+
|
117 |
+
function RetinaImage(el) {
|
118 |
+
this.el = el;
|
119 |
+
this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
|
120 |
+
var that = this;
|
121 |
+
this.path.check_2x_variant(function(hasVariant) {
|
122 |
+
if (hasVariant) that.swap();
|
123 |
+
});
|
124 |
+
}
|
125 |
+
|
126 |
+
root.RetinaImage = RetinaImage;
|
127 |
+
|
128 |
+
RetinaImage.prototype.swap = function(path) {
|
129 |
+
if (typeof path == 'undefined') path = this.path.at_2x_path;
|
130 |
+
|
131 |
+
var that = this;
|
132 |
+
function load() {
|
133 |
+
if (! that.el.complete) {
|
134 |
+
setTimeout(load, 5);
|
135 |
+
} else {
|
136 |
+
that.el.setAttribute('width', that.el.offsetWidth);
|
137 |
+
that.el.setAttribute('height', that.el.offsetHeight);
|
138 |
+
that.el.setAttribute('src', path);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
load();
|
142 |
+
}
|
143 |
+
|
144 |
+
|
145 |
+
|
146 |
+
|
147 |
+
if (Retina.isRetina()) {
|
148 |
+
Retina.init(root);
|
149 |
+
}
|
150 |
+
|
151 |
+
})();
|
152 |
+
|
admin/js/wpsl-admin.js
ADDED
@@ -0,0 +1,375 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
jQuery( document ).ready( function( $ ) {
|
2 |
+
var map, geocoder, uploadFrame,
|
3 |
+
markersArray = [];
|
4 |
+
|
5 |
+
/* Load the Google Maps */
|
6 |
+
function initializeGmap() {
|
7 |
+
var draggable, alt,
|
8 |
+
myOptions = {
|
9 |
+
zoom: 2,
|
10 |
+
center: new google.maps.LatLng( "52.378153", "4.899363" ),
|
11 |
+
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
12 |
+
streetViewControl: false
|
13 |
+
};
|
14 |
+
|
15 |
+
geocoder = new google.maps.Geocoder();
|
16 |
+
map = new google.maps.Map( document.getElementById( "wpsl-gmap-wrap" ), myOptions );
|
17 |
+
|
18 |
+
checkEditStoreMarker();
|
19 |
+
}
|
20 |
+
|
21 |
+
/* If we have an existing latln value, add a marker to the map. This can only happen on the edit store page */
|
22 |
+
function checkEditStoreMarker() {
|
23 |
+
var location,
|
24 |
+
lat = $( "#wpsl-store-lat" ).val(),
|
25 |
+
lng = $( "#wpsl-store-lng" ).val();
|
26 |
+
|
27 |
+
if ( ( lat ) && ( lng ) ) {
|
28 |
+
location = new google.maps.LatLng( lat, lng );
|
29 |
+
|
30 |
+
map.setCenter( location );
|
31 |
+
map.setZoom( 16 );
|
32 |
+
addMarker( location );
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/* If we have a city/country input field enable the autocomplete */
|
37 |
+
if ( $( "#wpsl-zoom-name" ).length ) {
|
38 |
+
activateAutoComplete();
|
39 |
+
}
|
40 |
+
|
41 |
+
/* Activate the autocomplete function for the city/country field */
|
42 |
+
function activateAutoComplete() {
|
43 |
+
var latlng,
|
44 |
+
input = document.getElementById( "wpsl-zoom-name" ),
|
45 |
+
options = {
|
46 |
+
types: ['geocode']
|
47 |
+
},
|
48 |
+
autocomplete = new google.maps.places.Autocomplete( input, options );
|
49 |
+
|
50 |
+
google.maps.event.addListener( autocomplete, "place_changed", function() {
|
51 |
+
latlng = autocomplete.getPlace().geometry.location;
|
52 |
+
setLatlng( latlng, "zoom" );
|
53 |
+
});
|
54 |
+
}
|
55 |
+
|
56 |
+
/* Add a new marker to the map based on the provided location (latlng) */
|
57 |
+
function addMarker( location ) {
|
58 |
+
var marker = new google.maps.Marker({
|
59 |
+
position: location,
|
60 |
+
map: map,
|
61 |
+
draggable: true
|
62 |
+
});
|
63 |
+
|
64 |
+
markersArray.push( marker );
|
65 |
+
|
66 |
+
google.maps.event.addListener( marker, "dragend", function() {
|
67 |
+
geocodeDraggedPosition( marker.getPosition() );
|
68 |
+
});
|
69 |
+
}
|
70 |
+
|
71 |
+
/* Lookup the location where the marker is dropped */
|
72 |
+
function geocodeDraggedPosition( pos ) {
|
73 |
+
geocoder.geocode({
|
74 |
+
latLng: pos
|
75 |
+
}, function ( response ) {
|
76 |
+
if ( response && response.length > 0 ) {
|
77 |
+
setLatlng( response[0].geometry.location, "store" );
|
78 |
+
|
79 |
+
/* Set the zip code, but only if no existing value exists */
|
80 |
+
setZipCode( response );
|
81 |
+
} else {
|
82 |
+
alert( "Cannot determine address at this location." );
|
83 |
+
}
|
84 |
+
});
|
85 |
+
}
|
86 |
+
|
87 |
+
/* Only update the zipcode if there is no existing value */
|
88 |
+
function setZipCode( response ) {
|
89 |
+
if ( !$( "#wpsl-store-zip" ).val() ) {
|
90 |
+
var filteredResponse = filterApiResponse( response );
|
91 |
+
$( "#wpsl-store-zip" ).val( filteredResponse.zip );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/* Lookup the provided location name with the Google Maps API */
|
96 |
+
$( "#wpsl-lookup-location" ).on( "click", function() {
|
97 |
+
codeAddress();
|
98 |
+
return false;
|
99 |
+
});
|
100 |
+
|
101 |
+
/* Geocode the user input */
|
102 |
+
function codeAddress() {
|
103 |
+
var filteredResponse,
|
104 |
+
street = $( "#wpsl-store-street" ).val(),
|
105 |
+
city = $( "#wpsl-store-city" ).val(),
|
106 |
+
zip = $( "#wpsl-store-zip" ).val(),
|
107 |
+
country = $( "#wpsl-store-country" ).val(),
|
108 |
+
address = street + ',' + city + ',' + zip + ',' + country;
|
109 |
+
|
110 |
+
/* Check we have all the requird data before attempting to geocode the address */
|
111 |
+
if ( !validatePreviewFields( street, city, zip, country ) ) {
|
112 |
+
geocoder.geocode( { 'address': address }, function( response, status ) {
|
113 |
+
if ( status === google.maps.GeocoderStatus.OK ) {
|
114 |
+
|
115 |
+
/* If we have a previous marker on the map remove it */
|
116 |
+
if ( typeof( markersArray[0] ) !== "undefined" ) {
|
117 |
+
if ( markersArray[0].draggable ) {
|
118 |
+
markersArray[0].setMap( null );
|
119 |
+
markersArray.splice(0, 1);
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
/* Center and zoom to the searched location */
|
124 |
+
map.setCenter( response[0].geometry.location );
|
125 |
+
map.setZoom( 16 );
|
126 |
+
addMarker( response[0].geometry.location );
|
127 |
+
setLatlng( response[0].geometry.location, "store" );
|
128 |
+
|
129 |
+
filteredResponse = filterApiResponse( response );
|
130 |
+
$( "#wpsl-store-zip" ).val( filteredResponse.zip );
|
131 |
+
$( "#wpsl-store-country" ).val( filteredResponse.country.long_name );
|
132 |
+
$( "#wpsl-country-iso" ).val( filteredResponse.country.short_name );
|
133 |
+
} else {
|
134 |
+
alert( "Geocode was not successful for the following reason: " + status );
|
135 |
+
}
|
136 |
+
});
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
/* Check that all required fields for the preview to work are there */
|
141 |
+
function validatePreviewFields( street, city, zip, country ) {
|
142 |
+
var error = false;
|
143 |
+
|
144 |
+
$( "#wpsl-wrap input" ).removeClass( "wpsl-error" );
|
145 |
+
|
146 |
+
if ( !street ) {
|
147 |
+
$( "#wpsl-store-street" ).addClass( "wpsl-error" );
|
148 |
+
error = true;
|
149 |
+
}
|
150 |
+
|
151 |
+
if ( !city ) {
|
152 |
+
$( "#wpsl-store-city" ).addClass( "wpsl-error" );
|
153 |
+
error = true;
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( !zip ) {
|
157 |
+
$( "#wpsl-store-zip" ).addClass( "wpsl-error" );
|
158 |
+
error = true;
|
159 |
+
}
|
160 |
+
|
161 |
+
if ( !country ) {
|
162 |
+
$( "#wpsl-store-country" ).addClass( "wpsl-error" );
|
163 |
+
error = true;
|
164 |
+
}
|
165 |
+
|
166 |
+
return error;
|
167 |
+
}
|
168 |
+
|
169 |
+
/* Filter out the zipcode from the Google Maps API response */
|
170 |
+
function filterApiResponse( response ) {
|
171 |
+
var zipcode, responseType,
|
172 |
+
country = {},
|
173 |
+
collectedData = {},
|
174 |
+
addressLength = response[0].address_components.length;
|
175 |
+
|
176 |
+
/* Loop over the API response */
|
177 |
+
for ( i = 0; i < addressLength; i++ ){
|
178 |
+
responseType = response[0].address_components[i].types;
|
179 |
+
|
180 |
+
/* filter out the country name */
|
181 |
+
if ( /^country,political$/.test( responseType ) ) {
|
182 |
+
country = {
|
183 |
+
long_name : response[0].address_components[i].long_name,
|
184 |
+
short_name : response[0].address_components[i].short_name
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
/* filter out the postal code */
|
189 |
+
if ( ( /^postal_code$/.test( responseType ) ) || ( /^postal_code_prefix,postal_code$/.test( responseType ) ) ) {
|
190 |
+
zipcode = response[0].address_components[i].long_name;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
collectedData = {
|
195 |
+
zip : zipcode,
|
196 |
+
country : country
|
197 |
+
};
|
198 |
+
|
199 |
+
return collectedData;
|
200 |
+
}
|
201 |
+
|
202 |
+
/* Update the hidden input field with the current lat/long values. */
|
203 |
+
function setLatlng( latlng, target ) {
|
204 |
+
var coordinates = stripCoordinates( latlng ),
|
205 |
+
lat = roundLatlng( coordinates[0], 6 ),
|
206 |
+
lng = roundLatlng( coordinates[1], 6 );
|
207 |
+
|
208 |
+
if ( target == "store" ) {
|
209 |
+
$( "#wpsl-store-lat" ).val( lat );
|
210 |
+
$( "#wpsl-store-lng" ).val( lng );
|
211 |
+
} else if ( target == "zoom" ) {
|
212 |
+
$( "#wpsl-latlng" ).val( lat + ',' + lng);
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
/* Round the latlng to 6 digits after the comma */
|
217 |
+
function roundLatlng( num, decimals ) {
|
218 |
+
return Math.round( num * Math.pow( 10, decimals ) ) / Math.pow( 10, decimals );
|
219 |
+
}
|
220 |
+
|
221 |
+
/* strip the '(' and ')' from the captured coordinates, and split them */
|
222 |
+
function stripCoordinates( coordinates ) {
|
223 |
+
var latlng = [],
|
224 |
+
selected = coordinates.toString(),
|
225 |
+
latlngStr = selected.split( ",",2 );
|
226 |
+
|
227 |
+
latlng[0] = latlngStr[0].replace( '(', '' );
|
228 |
+
latlng[1] = latlngStr[1].replace( ')', '' );
|
229 |
+
|
230 |
+
return latlng;
|
231 |
+
}
|
232 |
+
|
233 |
+
/* Handle the selection of custom thumbnails */
|
234 |
+
$( "#wpsl-thumb-wrap" ).on( "click", "#wpsl-media-upload", function( e ) {
|
235 |
+
e.preventDefault();
|
236 |
+
|
237 |
+
if ( uploadFrame ) {
|
238 |
+
uploadFrame.open();
|
239 |
+
return;
|
240 |
+
}
|
241 |
+
|
242 |
+
uploadFrame = wp.media.frames.uploadFrame = wp.media({
|
243 |
+
title: "Set store image",
|
244 |
+
frame: "select",
|
245 |
+
multiple: false,
|
246 |
+
library: {
|
247 |
+
type: "image"
|
248 |
+
},
|
249 |
+
button: {
|
250 |
+
text: "upload"
|
251 |
+
}
|
252 |
+
});
|
253 |
+
|
254 |
+
uploadFrame.on( "select", function() {
|
255 |
+
var media_attachment = uploadFrame.state().get( "selection" ).first().toJSON();
|
256 |
+
setLocationThumb( media_attachment.sizes.thumbnail.url, media_attachment.id );
|
257 |
+
});
|
258 |
+
|
259 |
+
uploadFrame.open();
|
260 |
+
});
|
261 |
+
|
262 |
+
/* Replace the thumnail with the placeholder */
|
263 |
+
$( "#wpsl-thumb-wrap" ).on( "click", "#wpsl-remove-thumb", function( e ) {
|
264 |
+
e.preventDefault();
|
265 |
+
|
266 |
+
$( "#wpsl-thumb-wrap img" ).replaceWith( "<span class='wpsl-thumb-placeholder'></span>" );
|
267 |
+
$( "#wpsl-thumb-id" ).val('');
|
268 |
+
});
|
269 |
+
|
270 |
+
/* Show the selected thumb */
|
271 |
+
function setLocationThumb( thumbUrl, thumbId ) {
|
272 |
+
var img;
|
273 |
+
|
274 |
+
if ( $( "#wpsl-thumb-wrap img" ).length ) {
|
275 |
+
$( "#wpsl-thumb-wrap img" ).attr({ 'src' : thumbUrl, 'data-img-id' : thumbId });
|
276 |
+
$( "#wpsl-thumb-id" ).val( thumbId );
|
277 |
+
} else {
|
278 |
+
img = "<img class='wpsl-curve' src='" + thumbUrl + "' width='85' height='85' />";
|
279 |
+
$( "#wpsl-thumb-wrap span" ).replaceWith( img );
|
280 |
+
$( "#wpsl-thumb-id" ).val( thumbId );
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
$( ".wpsl-delete-store-btn" ).removeAttr( "disabled" );
|
285 |
+
|
286 |
+
$( "#wpsl-store-overview" ).on( "click", ".wpsl-delete-store-btn", function() {
|
287 |
+
var elem = $(this),
|
288 |
+
dialogBox = $( "#wpsl-delete-confirmation" ),
|
289 |
+
cancelBtn = dialogBox.find( ".button-secondary" ),
|
290 |
+
submitBtn = dialogBox.find( ".button-primary" ),
|
291 |
+
storeId = $(this).next( "input[name='wpsl_store_id']" ).val();
|
292 |
+
|
293 |
+
dialogBox.dialog({
|
294 |
+
width: 325,
|
295 |
+
resizable : false,
|
296 |
+
modal: true,
|
297 |
+
minHeight: 0
|
298 |
+
});
|
299 |
+
|
300 |
+
$( ".ui-dialog-titlebar" ).remove();
|
301 |
+
cancelBtn.on( "click", function() {
|
302 |
+
dialogBox.dialog( "close" );
|
303 |
+
submitBtn.unbind( "click" );
|
304 |
+
dialogBox.unbind( "click" );
|
305 |
+
});
|
306 |
+
|
307 |
+
submitBtn.on( "click", function() {
|
308 |
+
dialogBox.dialog( "close" );
|
309 |
+
deleteStore( elem );
|
310 |
+
submitBtn.unbind( "click" );
|
311 |
+
dialogBox.unbind( "click" );
|
312 |
+
|
313 |
+
return false;
|
314 |
+
});
|
315 |
+
|
316 |
+
return false;
|
317 |
+
});
|
318 |
+
|
319 |
+
function deleteStore( elem ) {
|
320 |
+
var ajaxData = {},
|
321 |
+
$parentTr = elem.parents( "tr" );
|
322 |
+
|
323 |
+
showPreloader( elem );
|
324 |
+
elem.attr( "disabled", "disabled" );
|
325 |
+
|
326 |
+
ajaxData = {
|
327 |
+
action: "delete_store",
|
328 |
+
store_id: elem.parent( ".column-action" ).find( "input[name='wpsl_store_id']" ).val(),
|
329 |
+
_ajax_nonce: elem.parent( ".column-action" ).find( "input[name='wpsl_delete_nonce']" ).val()
|
330 |
+
};
|
331 |
+
|
332 |
+
jQuery.ajaxQueue({
|
333 |
+
url: ajaxurl,
|
334 |
+
data: ajaxData,
|
335 |
+
type: "POST"
|
336 |
+
}).done( function( response ) {
|
337 |
+
if ( response === -1 ) {
|
338 |
+
elem.removeAttr( "disabled" );
|
339 |
+
$( ".wpsl-preloader" ).remove();
|
340 |
+
alert( "Security check failed, reload the page and try again." );
|
341 |
+
} else if ( response.success ) {
|
342 |
+
setTimeout( function() {
|
343 |
+
$parentTr.fadeOut( "200", function() {
|
344 |
+
$parentTr.remove();
|
345 |
+
});
|
346 |
+
}, 2000);
|
347 |
+
}
|
348 |
+
});
|
349 |
+
}
|
350 |
+
|
351 |
+
$( ".wpsl-marker-list input[type=radio]" ).click( function(){
|
352 |
+
$(this).parents( ".wpsl-marker-list" ).find( "li" ).removeClass();
|
353 |
+
$(this).parent( "li" ).addClass( "wpsl-active-marker" );
|
354 |
+
});
|
355 |
+
|
356 |
+
$( ".wpsl-marker-list li" ).click( function(){
|
357 |
+
$(this).parents( ".wpsl-marker-list" ).find( "input" ).prop( "checked", false );
|
358 |
+
$(this).find( "input" ).prop( "checked", true );
|
359 |
+
$(this).siblings().removeClass();
|
360 |
+
$(this).addClass( "wpsl-active-marker" );
|
361 |
+
});
|
362 |
+
|
363 |
+
/* Insert the preloader after the button */
|
364 |
+
function showPreloader( elem ) {
|
365 |
+
if ( !elem.parent().find( ".wpsl-preloader" ).length ) {
|
366 |
+
elem.after( "<img class='wpsl-preloader' src='" + wpsl_data.url + "img/ajax-loader.gif' />" );
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
/* Load the map */
|
371 |
+
if ( $( "#wpsl-gmap-wrap" ).length ) {
|
372 |
+
google.maps.event.addDomListener( window, "load", initializeGmap );
|
373 |
+
}
|
374 |
+
|
375 |
+
});
|
admin/templates/add-store.php
ADDED
@@ -0,0 +1,109 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div id="wpsl-wrap" class="wrap wpsl-add-stores">
|
2 |
+
<h2>WP Store Locator</h2>
|
3 |
+
<?php settings_errors(); ?>
|
4 |
+
|
5 |
+
<ul id="wpsl-mainnav" class="nav-tab-wrapper">
|
6 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_store_editor' ); ?>"><?php _e('Current Stores', 'wpsl'); ?></a></li>
|
7 |
+
<li><a class="nav-tab nav-tab-active" href="<?php echo admin_url( 'admin.php?page=wpsl_add_store' ); ?>"><?php _e('Add Store', 'wpsl'); ?></a></li>
|
8 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_settings' ); ?>"><?php _e( 'Settings', 'wpsl' ); ?></a></li>
|
9 |
+
</ul>
|
10 |
+
|
11 |
+
<form method="post" action="" accept-charset="utf-8">
|
12 |
+
<input type="hidden" name="wpsl_actions" value="add_new_store" />
|
13 |
+
<?php wp_nonce_field( 'wpsl_add_new_store' ); ?>
|
14 |
+
<div class="wpsl-add-store">
|
15 |
+
<div class="metabox-holder">
|
16 |
+
<div class="postbox">
|
17 |
+
<h3><span><?php _e( 'Store details', 'wpsl' ); ?></span></h3>
|
18 |
+
<div class="inside">
|
19 |
+
<p>
|
20 |
+
<label for="wpsl-store-name"><?php _e( 'Store Name:', 'wpsl' ); ?></label>
|
21 |
+
<input id="wpsl-store-name" name="wpsl[store]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['store'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['store'] ) ) { echo esc_attr( $_POST['wpsl']['store'] ); } ?>" />
|
22 |
+
</p>
|
23 |
+
<p>
|
24 |
+
<label for="wpsl-store-street"><?php _e( 'Street:', 'wpsl' ); ?></label>
|
25 |
+
<input id="wpsl-store-street" name="wpsl[street]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['street'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['street'] ) ) { echo esc_attr( $_POST['wpsl']['street'] ); } ?>" />
|
26 |
+
</p>
|
27 |
+
<p>
|
28 |
+
<label for="wpsl-store-city"><?php _e( 'City:', 'wpsl' ); ?></label>
|
29 |
+
<input id="wpsl-store-city" name="wpsl[city]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['city'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['city'] ) ) { echo esc_attr( $_POST['wpsl']['city'] ); } ?>" />
|
30 |
+
</p>
|
31 |
+
<p>
|
32 |
+
<label for="wpsl-store-state"><?php _e( 'State / Province:', 'wpsl' ); ?></label>
|
33 |
+
<input id="wpsl-store-state" name="wpsl[state]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['state'] ) ) { echo esc_attr( $_POST['wpsl']['state'] ); } ?>" />
|
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 ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( $_POST['wpsl']['zip'] ); } ?>" />
|
38 |
+
</p>
|
39 |
+
<p>
|
40 |
+
<label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
|
41 |
+
<input id="wpsl-store-country" name="wpsl[country]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['country'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( !empty( $_POST['wpsl']['country'] ) ) { echo esc_attr( $_POST['wpsl']['country'] ); } ?>" />
|
42 |
+
<input id="wpsl-country-iso" type="hidden" name="wpsl[country-iso]" value="<?php if ( !empty( $_POST['wpsl']['country-iso'] ) ) { echo esc_attr( $_POST['wpsl']['country-iso'] ); } ?>" />
|
43 |
+
</p>
|
44 |
+
<p>
|
45 |
+
<label for="wpsl-store-lat"><?php _e( 'Latitude:', 'wpsl' ); ?></label>
|
46 |
+
<input id="wpsl-store-lat" name="wpsl[lat]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['lat'] ) ) { echo esc_attr( $_POST['wpsl']['lat'] ); } ?>" />
|
47 |
+
</p>
|
48 |
+
<p>
|
49 |
+
<label for="wpsl-store-lng"><?php _e( 'Longitude:', 'wpsl' ); ?></label>
|
50 |
+
<input id="wpsl-store-lng" name="wpsl[lng]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['lng'] ) ) { echo esc_attr( $_POST['wpsl']['lng'] ); } ?>" />
|
51 |
+
</p>
|
52 |
+
<p class="wpsl-submit-wrap">
|
53 |
+
<input id="wpsl-lookup-location" type="submit" name="wpsl-lookup-location" class="button-primary" value="<?php _e( 'Preview location on the map', 'wpsl' ); ?>" />
|
54 |
+
<em class="nwm-desc"><?php _e( 'You can adjust the location by dragging the marker around', 'nwm' ); ?></em>
|
55 |
+
</p>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
|
60 |
+
<div id="wpsl-gmap-wrap"></div>
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<div class="metabox-holder">
|
64 |
+
<div class="postbox">
|
65 |
+
<h3><span><?php _e( 'Extra details', 'wpsl' ); ?></span></h3>
|
66 |
+
<div class="inside">
|
67 |
+
<p>
|
68 |
+
<label for="wpsl-store-phone"><?php _e( 'Phone:', 'wpsl' ); ?></label>
|
69 |
+
<input id="wpsl-store-phone" name="wpsl[phone]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['phone'] ) ) { echo esc_attr( $_POST['wpsl']['phone'] ); } ?>">
|
70 |
+
</p>
|
71 |
+
<p>
|
72 |
+
<label for="wpsl-store-fax"><?php _e( 'Fax:', 'wpsl' ); ?></label>
|
73 |
+
<input id="wpsl-store-fax" name="wpsl[fax]" type="text" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['fax'] ) ) { echo esc_attr( $_POST['wpsl']['fax'] ); } ?>">
|
74 |
+
</p>
|
75 |
+
<p>
|
76 |
+
<label for="wpsl-store-email"><?php _e( 'Email:', 'wpsl' ); ?></label>
|
77 |
+
<input id="wpsl-store-email" name="wpsl[email]" type="email" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['email'] ) ) { echo esc_attr( $_POST['wpsl']['email'] ); } ?>">
|
78 |
+
</p>
|
79 |
+
<p>
|
80 |
+
<label for="wpsl-store-url"><?php _e( 'Url:', 'wpsl' ); ?></label>
|
81 |
+
<input id="wpsl-store-url" name="wpsl[url]" type="url" class="textinput" value="<?php if ( !empty( $_POST['wpsl']['url'] ) ) { echo esc_attr( $_POST['wpsl']['url'] ); } ?>">
|
82 |
+
</p>
|
83 |
+
<p>
|
84 |
+
<label for="wpsl-store-desc"><?php _e( 'Description:', 'wpsl' ); ?></label>
|
85 |
+
<textarea id="wpsl-store-desc" name="wpsl[desc]" cols="5" rows="5"></textarea>
|
86 |
+
</p>
|
87 |
+
<p>
|
88 |
+
<label for="wpsl-store-hours"><?php _e( 'Operation Hours:', 'wpsl' ); ?></label>
|
89 |
+
<textarea id="wpsl-store-hours" name="wpsl[hours]" cols="5" rows="5"><?php if ( !empty( $_POST['wpsl']['hours'] ) ) { echo esc_textarea( $_POST['wpsl']['hours'] ); } ?></textarea>
|
90 |
+
</p>
|
91 |
+
<div id="wpsl-thumb-wrap">
|
92 |
+
<p>
|
93 |
+
<label><?php _e( 'Thumbnail:', 'wpsl' ); ?></label>
|
94 |
+
<span class="wpsl-thumb-placeholder"></span>
|
95 |
+
</p>
|
96 |
+
<div>
|
97 |
+
<input id="wpsl-media-upload" class="button-primary" type="button" name="text" value="<?php _e( 'Change thumbnail', 'wpsl' ); ?>" />
|
98 |
+
<input id="wpsl-remove-thumb" class="button-primary" type="button" name="text" value="<?php _e( 'Remove', 'wpsl' ); ?>" />
|
99 |
+
<input type="hidden" id="wpsl-thumb-id" name="wpsl[thumb-id]" value="" />
|
100 |
+
</div>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
</div>
|
104 |
+
|
105 |
+
<p><input id="wpsl-add-store" type="submit" name="wpsl-add-store" class="button-primary" value="<?php _e( 'Add Store', 'wpsl' ); ?>" /></p>
|
106 |
+
</div>
|
107 |
+
</form>
|
108 |
+
|
109 |
+
</div>
|
admin/templates/edit-store.php
ADDED
@@ -0,0 +1,135 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$store_id = absint( $_GET['store_id'] );
|
3 |
+
$thumb = '';
|
4 |
+
|
5 |
+
if ( $store_id ) {
|
6 |
+
$store_details = $this->get_store_data( $store_id );
|
7 |
+
|
8 |
+
if ( $store_details['thumb_id'] ) {
|
9 |
+
$thumb = wp_get_attachment_image_src( $store_details['thumb_id'], 'thumbnail' );
|
10 |
+
}
|
11 |
+
}
|
12 |
+
?>
|
13 |
+
<div id="wpsl-wrap" class="wrap wpsl-add-stores">
|
14 |
+
<h2 class="wpsl-edit-header">Edit <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['store'] ) ) { echo esc_attr( $_POST['wpsl']['store'] ); } else { echo esc_attr( $store_details['store'] ); } ?></h2>
|
15 |
+
<?php settings_errors(); ?>
|
16 |
+
|
17 |
+
<form method="post" action="" accept-charset="utf-8">
|
18 |
+
<input type="hidden" name="wpsl_actions" value="update_store" />
|
19 |
+
<?php wp_nonce_field( 'wpsl_update_store' ); ?>
|
20 |
+
<div class="wpsl-add-store">
|
21 |
+
<div class="metabox-holder">
|
22 |
+
<div class="postbox">
|
23 |
+
<h3><span><?php _e( 'Store details', 'wpsl' ); ?></span></h3>
|
24 |
+
<div class="inside">
|
25 |
+
<p>
|
26 |
+
<label for="wpsl-store-status"><?php _e( 'Status:', 'wpsl' ); ?></label>
|
27 |
+
<span class="wpsl-radioboxes">
|
28 |
+
<input id="wpsl-store-active" type="radio" name="wpsl[active]" <?php checked( '1', $store_details['active'], true ); ?> value="1" />
|
29 |
+
<label for="wpsl-store-active"><?php _e( 'active', 'wpsl' ); ?></label>
|
30 |
+
<input id="wpsl-store-inactive" type="radio" name="wpsl[active]" <?php checked( '0', $store_details['active'], true ); ?> value="0" />
|
31 |
+
<label for="wpsl-store-inactive"><?php _e( 'inactive', 'wpsl' ); ?></label>
|
32 |
+
</span>
|
33 |
+
</p>
|
34 |
+
<p>
|
35 |
+
<label for="wpsl-store-name"><?php _e( 'Store Name:', 'wpsl' ); ?></label>
|
36 |
+
<input id="wpsl-store-name" name="wpsl[store]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['store'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['store'] ) ) { echo esc_attr( $_POST['wpsl']['store'] ); } else { echo esc_attr( $store_details['store'] ); } ?>" />
|
37 |
+
</p>
|
38 |
+
<p>
|
39 |
+
<label for="wpsl-store-street"><?php _e( 'Street:', 'wpsl' ); ?></label>
|
40 |
+
<input id="wpsl-store-street" name="wpsl[street]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['street'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['street'] ) ) { echo esc_attr( $_POST['wpsl']['street'] ); } else { echo esc_attr( $store_details['street'] ); } ?>" />
|
41 |
+
</p>
|
42 |
+
<p>
|
43 |
+
<label for="wpsl-store-city"><?php _e( 'City:', 'wpsl' ); ?></label>
|
44 |
+
<input id="wpsl-store-city" name="wpsl[city]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['city'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['city'] ) ) { echo esc_attr( $_POST['wpsl']['city'] ); } else { echo esc_attr( $store_details['city'] ); } ?>" />
|
45 |
+
</p>
|
46 |
+
<p>
|
47 |
+
<label for="wpsl-store-state"><?php _e( 'State / Province:', 'wpsl' ); ?></label>
|
48 |
+
<input id="wpsl-store-state" name="wpsl[state]" type="text" class="textinput" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['state'] ) ) { echo esc_attr( $_POST['wpsl']['state'] ); } else { echo esc_attr( $store_details['state'] ); } ?>" />
|
49 |
+
</p>
|
50 |
+
<p>
|
51 |
+
<label for="wpsl-store-zip"><?php _e( 'Zip Code:', 'wpsl' ); ?></label>
|
52 |
+
<input id="wpsl-store-zip" name="wpsl[zip]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['zip'] ) ) { echo esc_attr( $_POST['wpsl']['zip'] ); } else { echo esc_attr( $store_details['zip'] ); } ?>" />
|
53 |
+
</p>
|
54 |
+
<p>
|
55 |
+
<label for="wpsl-store-country"><?php _e( 'Country:', 'wpsl' ); ?></label>
|
56 |
+
<input id="wpsl-store-country" name="wpsl[country]" type="text" class="textinput <?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['country'] ) ) { echo 'wpsl-error'; } ?>" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['country'] ) ) { echo esc_attr( $_POST['wpsl']['country'] ); } else { echo esc_attr( $store_details['country'] ); } ?>" />
|
57 |
+
<input id="wpsl-country-iso" type="hidden" name="wpsl[country-iso]" value="<?php echo esc_attr( $store_details['country_iso'] ); ?>" />
|
58 |
+
</p>
|
59 |
+
<p>
|
60 |
+
<label for="wpsl-store-lat"><?php _e( 'Latitude:', 'wpsl' ); ?></label>
|
61 |
+
<input id="wpsl-store-lat" name="wpsl[lat]" type="text" class="textinput" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['lat'] ) ) { echo esc_attr( $_POST['wpsl']['lat'] ); } else { echo esc_attr( $store_details['lat'] ); } ?>" />
|
62 |
+
</p>
|
63 |
+
<p>
|
64 |
+
<label for="wpsl-store-lng"><?php _e( 'Longitude:', 'wpsl' ); ?></label>
|
65 |
+
<input id="wpsl-store-lng" name="wpsl[lng]" type="text" class="textinput" value="<?php if ( ( $_POST['wpsl'] ) && empty( $_POST['wpsl']['lng'] ) ) { echo esc_attr( $_POST['wpsl']['lng'] ); } else { echo esc_attr( $store_details['lng'] ); } ?>" />
|
66 |
+
</p>
|
67 |
+
<p class="wpsl-submit-wrap">
|
68 |
+
<input id="wpsl-lookup-location" type="submit" name="wpsl-lookup-location" class="button-primary" value="<?php _e( 'Preview location on the map', 'wpsl' ); ?>" />
|
69 |
+
<em class="nwm-desc"><?php _e( 'You can adjust the location by dragging the marker around', 'nwm' ); ?></em>
|
70 |
+
</p>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
|
75 |
+
<div id="wpsl-gmap-wrap"></div>
|
76 |
+
</div>
|
77 |
+
|
78 |
+
<div class="metabox-holder">
|
79 |
+
<div class="postbox">
|
80 |
+
<h3><span><?php _e( 'Extra details', 'wpsl' ); ?></span></h3>
|
81 |
+
<div class="inside">
|
82 |
+
<p>
|
83 |
+
<label for="wpsl-store-phone"><?php _e( 'Phone:', 'wpsl' ); ?></label>
|
84 |
+
<input id="wpsl-store-phone" name="wpsl[phone]" type="text" class="textinput" value="<?php if ( $_POST['wpsl']['phone'] ) { echo esc_attr( $_POST['wpsl']['phone'] ); } else { echo esc_attr( $store_details['phone'] ); } ?>">
|
85 |
+
</p>
|
86 |
+
<p>
|
87 |
+
<label for="wpsl-store-fax"><?php _e( 'Fax:', 'wpsl' ); ?></label>
|
88 |
+
<input id="wpsl-store-fax" name="wpsl[fax]" type="text" class="textinput" value="<?php if ( $_POST['wpsl']['fax'] ) { echo esc_attr( $_POST['wpsl']['fax'] ); } else { echo esc_attr( $store_details['fax'] ); } ?>">
|
89 |
+
</p>
|
90 |
+
<p>
|
91 |
+
<label for="wpsl-store-email"><?php _e( 'Email:', 'wpsl' ); ?></label>
|
92 |
+
<input id="wpsl-store-email" name="wpsl[email]" type="email" class="textinput" value="<?php if ( $_POST['wpsl']['email'] ) { echo esc_attr( $_POST['wpsl']['email'] ); } else { echo esc_attr( $store_details['email'] ); } ?>">
|
93 |
+
</p>
|
94 |
+
<p>
|
95 |
+
<label for="wpsl-store-url"><?php _e( 'Url:', 'wpsl' ); ?></label>
|
96 |
+
<input id="wpsl-store-url" name="wpsl[url]" type="url" class="textinput" value="<?php if ( $_POST['wpsl']['url'] ) { echo esc_attr( $_POST['wpsl']['url'] ); } else { echo esc_attr( $store_details['url'] ); } ?>">
|
97 |
+
</p>
|
98 |
+
<p>
|
99 |
+
<label for="wpsl-store-desc"><?php _e( 'Description:', 'wpsl' ); ?></label>
|
100 |
+
<textarea id="wpsl-store-desc" name="wpsl[desc]" cols="5" rows="5"><?php if ( $_POST['wpsl']['desc'] ) { echo esc_textarea( $_POST['wpsl']['desc'] ); } else { echo esc_textarea( $store_details['description'] ); } ?></textarea>
|
101 |
+
</p>
|
102 |
+
<p>
|
103 |
+
<label for="wpsl-store-hours"><?php _e( 'Operation Hours:', 'wpsl' ); ?></label>
|
104 |
+
<textarea id="wpsl-store-hours" name="wpsl[hours]" cols="5" rows="5"><?php if ( $_POST['wpsl']['hours'] ) { echo esc_textarea( $_POST['wpsl']['hours'] ); } else { echo esc_textarea( $store_details['hours'] ); } ?></textarea>
|
105 |
+
</p>
|
106 |
+
<div id="wpsl-thumb-wrap">
|
107 |
+
<p>
|
108 |
+
<label><?php _e( 'Thumbnail:', 'wpsl' ); ?></label>
|
109 |
+
<?php
|
110 |
+
if ( !empty( $thumb ) ) {
|
111 |
+
echo '<img class="wpsl-curve" src=" ' . esc_url ( $thumb[0] ) . '" width="85" height="85">';
|
112 |
+
} else {
|
113 |
+
?>
|
114 |
+
<span class="wpsl-thumb-placeholder"></span>
|
115 |
+
<?php
|
116 |
+
}
|
117 |
+
?>
|
118 |
+
</p>
|
119 |
+
<div>
|
120 |
+
<input id="wpsl-media-upload" class="button-primary" type="button" name="text" value="<?php _e( 'Change thumbnail', 'wpsl' ); ?>" />
|
121 |
+
<input id="wpsl-remove-thumb" class="button-primary" type="button" name="text" value="<?php _e( 'Remove', 'wpsl' ); ?>" />
|
122 |
+
<input type="hidden" id="wpsl-thumb-id" name="wpsl[thumb-id]" value="<?php echo esc_attr( $store_details['thumb_id'] ); ?>" />
|
123 |
+
</div>
|
124 |
+
</div>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
+
|
128 |
+
<p>
|
129 |
+
<input id="wpsl-update-store" type="submit" name="wpsl-update-store" class="button-primary" value="<?php _e( 'Update Store', 'wpsl' ); ?>" />
|
130 |
+
<input id="wpsl-delete-store" type="submit" name="wpsl-delete-store" class="button-primary" value="<?php _e( 'Delete Store', 'wpsl' ); ?>" />
|
131 |
+
</p>
|
132 |
+
</div>
|
133 |
+
</form>
|
134 |
+
|
135 |
+
</div>
|
admin/templates/faq.php
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div id="wpsl-wrap" class="wrap wpsl-settings">
|
2 |
+
<h2>WP Store Locator: <?php _e( 'FAQ', 'wpsl' ); ?></h2>
|
3 |
+
|
4 |
+
<div id="wpsl-faq">
|
5 |
+
<dl>
|
6 |
+
<dt>How do I show the store locator on my page?</dt>
|
7 |
+
<dd>Add this shortcode <code>[wpsl]</code> to the page where you want to show the store locator.</dd>
|
8 |
+
</dl>
|
9 |
+
</div>
|
10 |
+
</div>
|
admin/templates/map-settings.php
ADDED
@@ -0,0 +1,234 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div id="wpsl-wrap" class="wrap wpsl-settings">
|
2 |
+
<h2>WP Store Locator: <?php _e( 'Settings', 'wpsl' ); ?></h2>
|
3 |
+
|
4 |
+
<?php global $wpdb; ?>
|
5 |
+
|
6 |
+
<?php settings_errors(); ?>
|
7 |
+
<ul id="wpsl-mainnav" class="nav-tab-wrapper">
|
8 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_store_editor' ); ?>"><?php _e( 'Current Stores', 'wpsl' ); ?></a></li>
|
9 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_add_store' ); ?>"><?php _e( 'Add Store', 'wpsl' ); ?></a></li>
|
10 |
+
<li><a class="nav-tab nav-tab-active" href="<?php echo admin_url( 'admin.php?page=wpsl_settings' ); ?>"><?php _e( 'Settings', 'wpsl' ); ?></a></li>
|
11 |
+
</ul>
|
12 |
+
|
13 |
+
<form id="wpsl-settings-form" method="post" action="options.php" accept-charset="utf-8">
|
14 |
+
<div class="postbox-container">
|
15 |
+
<div class="metabox-holder">
|
16 |
+
<div class="postbox">
|
17 |
+
<h3><span><?php _e( 'API Settings', 'wpsl' ); ?></span></h3>
|
18 |
+
<div class="inside">
|
19 |
+
<p>
|
20 |
+
<label for="wpsl-api-key"><?php _e( 'API key:', 'wpsl' ); ?> *</label>
|
21 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['api_key'] ); ?>" name="wpsl_api[key]" placeholder="<?php _e( 'Optional', 'wpsl' ) ?>" class="textinput" id="wpsl-api-key">
|
22 |
+
</p>
|
23 |
+
<p>
|
24 |
+
<label for="wpsl-api-language"><?php _e( 'Map language:', 'wpsl' ); ?></label>
|
25 |
+
<select id="wpsl-api-language" name="wpsl_api[language]">
|
26 |
+
<?php
|
27 |
+
echo $this->get_api_option_list( 'language' );
|
28 |
+
?>
|
29 |
+
</select>
|
30 |
+
</p>
|
31 |
+
<p>
|
32 |
+
<label for="wpsl-api-region"><?php _e( 'Map region:', 'wpsl' ); ?></label>
|
33 |
+
<select id="wpsl-api-region" name="wpsl_api[region]">
|
34 |
+
<?php
|
35 |
+
echo $this->get_api_option_list( 'region' );
|
36 |
+
?>
|
37 |
+
</select>
|
38 |
+
</p>
|
39 |
+
<em><?php _e( '* A valid <a href="https://developers.google.com/maps/documentation/javascript/tutorial#api_key">API key</a> allows you to monitor the API usage <br> and is required if you need to purchase additional quota.', 'wpsl' ); ?></em>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
|
45 |
+
<div class="postbox-container">
|
46 |
+
<div class="metabox-holder">
|
47 |
+
<div class="postbox">
|
48 |
+
<h3><span><?php _e( 'Search Settings', 'wpsl' ); ?></span></h3>
|
49 |
+
<div class="inside">
|
50 |
+
<p>
|
51 |
+
<label for="wpsl-distance-unit"><?php _e( 'Distance unit:', 'wpsl' ); ?></label>
|
52 |
+
<?php echo $this->show_distance_units(); ?>
|
53 |
+
</p>
|
54 |
+
<p>
|
55 |
+
<label for="wpsl-max-results"><?php _e( 'Max search results:', 'wpsl' ); ?> *</label>
|
56 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['max_results'] ); ?>" name="wpsl_search[max_results]" class="textinput" id="wpsl-max-results">
|
57 |
+
</p>
|
58 |
+
<p>
|
59 |
+
<label for="wpsl-search-radius"><?php _e( 'Search radius options:', 'wpsl' ); ?> *</label>
|
60 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['search_radius'] ); ?>" name="wpsl_search[radius]" class="textinput" id="wpsl-search-radius">
|
61 |
+
</p>
|
62 |
+
<p>
|
63 |
+
<label for="wpsl-bounce"><?php _e( 'If a user hovers over the search results, the corresponding marker will bounce?', 'wpsl' ); ?></label>
|
64 |
+
<input type="checkbox" value="" <?php checked( $this->settings['marker_bounce'] == '1', true ); ?> name="wpsl_map[marker_bounce]" id="wpsl-bounce">
|
65 |
+
</p>
|
66 |
+
<em><?php _e( '* The default value is set between the ( )', 'wpsl' ); ?></em>
|
67 |
+
</div>
|
68 |
+
</div>
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<div class="postbox-container">
|
73 |
+
<div class="metabox-holder">
|
74 |
+
<div class="postbox">
|
75 |
+
<h3><span><?php _e( 'Map Settings', 'wpsl' ); ?></span></h3>
|
76 |
+
<div class="inside">
|
77 |
+
<p>
|
78 |
+
<label for="wpsl-auto-locate"><?php _e( 'Attempt to auto-locate the user:', 'wpsl' ); ?></label>
|
79 |
+
<input type="checkbox" value="" <?php checked( $this->settings['auto_locate'] == '1', true ); ?> name="wpsl_map[auto_locate]" id="wpsl-auto-locate">
|
80 |
+
</p>
|
81 |
+
<p>
|
82 |
+
<label for="wpsl-zoom-level"><?php _e( 'Zoom level:', 'wpsl' ); ?></label>
|
83 |
+
<?php echo $this->show_zoom_levels(); ?>
|
84 |
+
</p>
|
85 |
+
<p>
|
86 |
+
<label for="wpsl-zoom-name"><?php _e( 'Default location to focus on:', 'wpsl' ); ?></label>
|
87 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['zoom_name'] ); ?>" name="wpsl_map[zoom_name]" class="textinput" id="wpsl-zoom-name">
|
88 |
+
<input type="hidden" value="<?php echo esc_attr( $this->settings['zoom_latlng'] ); ?>" name="wpsl_map[zoom_latlng]" id="wpsl-latlng" />
|
89 |
+
</p>
|
90 |
+
<p>
|
91 |
+
<label for="wpsl-map-type"><?php _e( 'Map type:', 'wpsl' ); ?></label>
|
92 |
+
<?php echo $this->show_map_types(); ?>
|
93 |
+
</p>
|
94 |
+
<p>
|
95 |
+
<label for="wpsl-streetview"><?php _e( 'Show the street view controls?', 'wpsl' ); ?></label>
|
96 |
+
<input type="checkbox" value="" <?php checked( $this->settings['streetview'] == '1', true ); ?> name="wpsl_map[streetview]" id="wpsl-streetview">
|
97 |
+
</p>
|
98 |
+
<p>
|
99 |
+
<label for="wpsl-pan-controls"><?php _e( 'Show the pan controls?', 'wpsl' ); ?></label>
|
100 |
+
<input type="checkbox" value="" <?php checked( $this->settings['pan_controls'] == '1', true ); ?> name="wpsl_map[pan_controls]" id="wpsl-pan-controls">
|
101 |
+
</p>
|
102 |
+
<p>
|
103 |
+
<label><?php _e( 'Position of the map controls:', 'wpsl' ); ?></label>
|
104 |
+
<span class="wpsl_radioboxes">
|
105 |
+
<input type="radio" value="left" <?php checked( 'left', $this->settings['control_position'], true ); ?> name="wpsl_map[control_position]" id="wpsl-control-left">
|
106 |
+
<label for="wpsl-control-left"><?php _e( 'Left', 'wpsl' ); ?></label>
|
107 |
+
<input type="radio" value="right" <?php checked( 'right', $this->settings['control_position'], true ); ?> name="wpsl_map[control_position]" id="wpsl-control-right">
|
108 |
+
<label for="wpsl-control-right"><?php _e( 'Right', 'wpsl' ); ?></label>
|
109 |
+
</span>
|
110 |
+
</p>
|
111 |
+
<p>
|
112 |
+
<label><?php _e( 'Zoom control style:', 'wpsl' ); ?></label>
|
113 |
+
<span class="wpsl_radioboxes">
|
114 |
+
<input type="radio" value="small" <?php checked( 'small', $this->settings['control_style'], true ); ?> name="wpsl_map[control_style]" id="wpsl-small-style">
|
115 |
+
<label for="wpsl-small-style"><?php _e( 'Small', 'wpsl' ); ?></label>
|
116 |
+
<input type="radio" value="large" <?php checked( 'large', $this->settings['control_style'], true ); ?> name="wpsl_map[control_style]" id="wpsl-large-style">
|
117 |
+
<label for="wpsl-large-style"><?php _e( 'Large', 'wpsl' ); ?></label>
|
118 |
+
</span>
|
119 |
+
</p>
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
|
125 |
+
<div class="postbox-container">
|
126 |
+
<div class="metabox-holder">
|
127 |
+
<div class="postbox">
|
128 |
+
<h3><span><?php _e( 'Design Settings', 'wpsl' ); ?></span></h3>
|
129 |
+
<div class="inside">
|
130 |
+
<p>
|
131 |
+
<label for="wpsl-design-height"><?php _e( 'Store Locator height', 'wpsl' ); ?></label>
|
132 |
+
<input size="3" value="<?php echo esc_attr( $this->settings['height'] ); ?>" id="wpsl-design-height" name="wpsl_design[height_value]"> px
|
133 |
+
</p>
|
134 |
+
<p>
|
135 |
+
<label for="wpsl-infowindow-width"><?php _e( 'Max width for the infowindow', 'wpsl' ); ?></label>
|
136 |
+
<input size="3" value="<?php echo esc_attr( $this->settings['infowindow_width'] ); ?>" id="wpsl-infowindow-width" name="wpsl_design[infowindow_width]"> px
|
137 |
+
</p>
|
138 |
+
<p>
|
139 |
+
<label for="wpsl-search-width"><?php _e( 'Search field width', 'wpsl' ); ?></label>
|
140 |
+
<input size="3" value="<?php echo esc_attr( $this->settings['search_width'] ); ?>" id="wpsl-search-width" name="wpsl_design[search_width]"> px
|
141 |
+
</p>
|
142 |
+
<p>
|
143 |
+
<label for="wpsl-label-width"><?php _e( 'Search and radius label width *', 'wpsl' ); ?></label>
|
144 |
+
<input size="3" value="<?php echo esc_attr( $this->settings['label_width'] ); ?>" id="wpsl-label-width" name="wpsl_design[label_width]"> px
|
145 |
+
</p>
|
146 |
+
<p>
|
147 |
+
<label for="wpsl-design-results"><?php _e( 'Show the limit results dropdown?', 'wpsl' ); ?></label>
|
148 |
+
<input type="checkbox" value="" <?php checked( $this->settings['results_dropdown'] == '1', true ); ?> name="wpsl_design[design_results]">
|
149 |
+
</p>
|
150 |
+
<em><?php _e( '* This is the text that is placed before the search input and radius dropdown', 'wpsl' ); ?></em>
|
151 |
+
</div>
|
152 |
+
</div>
|
153 |
+
</div>
|
154 |
+
</div>
|
155 |
+
|
156 |
+
<div class="postbox-container">
|
157 |
+
<div class="metabox-holder">
|
158 |
+
<div class="postbox">
|
159 |
+
<h3><span><?php _e( 'Markers', 'wpsl' ); ?></span></h3>
|
160 |
+
<div class="inside">
|
161 |
+
<?php echo $this->show_marker_options(); ?>
|
162 |
+
</div>
|
163 |
+
</div>
|
164 |
+
</div>
|
165 |
+
</div>
|
166 |
+
|
167 |
+
<div class="postbox-container">
|
168 |
+
<div class="metabox-holder">
|
169 |
+
<div class="postbox">
|
170 |
+
<h3><span><?php _e( 'Labels', 'wpsl' ); ?></span></h3>
|
171 |
+
<div class="inside">
|
172 |
+
<p>
|
173 |
+
<label for="wpsl-search"><?php _e( 'Your location:', 'wpsl' ); ?></label>
|
174 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['search_label'] ); ?>" name="wpsl_label[search]" class="textinput" id="wpsl-search">
|
175 |
+
</p>
|
176 |
+
<p>
|
177 |
+
<label for="wpsl-search-radius"><?php _e( 'Search radius:', 'wpsl' ); ?></label>
|
178 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['radius_label'] ); ?>" name="wpsl_label[radius]" class="textinput" id="wpsl-search-radius">
|
179 |
+
</p>
|
180 |
+
<p>
|
181 |
+
<label for="wpsl-no-results"><?php _e( 'No results found:', 'wpsl' ); ?></label>
|
182 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['no_results_label'] ); ?>" name="wpsl_label[no_results]" class="textinput" id="wpsl-no-results">
|
183 |
+
</p>
|
184 |
+
<p>
|
185 |
+
<label for="wpsl-search-btn"><?php _e( 'Search:', 'wpsl' ); ?></label>
|
186 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['search_btn_label'] ); ?>" name="wpsl_label[search_btn]" class="textinput" id="wpsl-search-btn">
|
187 |
+
</p>
|
188 |
+
<p>
|
189 |
+
<label for="wpsl-preloader"><?php _e( 'Searching (preloader text):', 'wpsl' ); ?></label>
|
190 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['preloader_label'] ); ?>" name="wpsl_label[preloader]" class="textinput" id="wpsl-preloader">
|
191 |
+
</p>
|
192 |
+
<p>
|
193 |
+
<label for="wpsl-results"><?php _e( 'Results:', 'wpsl' ); ?></label>
|
194 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['results_label'] ); ?>" name="wpsl_label[results]" class="textinput" id="wpsl-results">
|
195 |
+
</p>
|
196 |
+
<p>
|
197 |
+
<label for="wpsl-phone"><?php _e( 'Phone:', 'wpsl' ); ?></label>
|
198 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['phone_label'] ); ?>" name="wpsl_label[phone]" class="textinput" id="wpsl-phone">
|
199 |
+
</p>
|
200 |
+
<p>
|
201 |
+
<label for="wpsl-fax"><?php _e( 'Fax:', 'wpsl' ); ?></label>
|
202 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['fax_label'] ); ?>" name="wpsl_label[fax]" class="textinput" id="wpsl-fax">
|
203 |
+
</p>
|
204 |
+
<p>
|
205 |
+
<label for="wpsl-hours"><?php _e( 'Hours:', 'wpsl' ); ?></label>
|
206 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['hours_label'] ); ?>" name="wpsl_label[hours]" class="textinput" id="wpsl-hours">
|
207 |
+
</p>
|
208 |
+
<p>
|
209 |
+
<label for="wpsl-start"><?php _e( 'Start location:', 'wpsl' ); ?></label>
|
210 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['start_label'] ); ?>" name="wpsl_label[start]" class="textinput" id="wpsl-start">
|
211 |
+
</p>
|
212 |
+
<p>
|
213 |
+
<label for="wpsl-directions"><?php _e( 'Get directions:', 'wpsl' ); ?></label>
|
214 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['directions_label'] ); ?>" name="wpsl_label[directions]" class="textinput" id="wpsl-directions">
|
215 |
+
</p>
|
216 |
+
<p>
|
217 |
+
<label for="wpsl-error"><?php _e( 'General error:', 'wpsl' ); ?></label>
|
218 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['error_label'] ); ?>" name="wpsl_label[error]" class="textinput" id="wpsl-error">
|
219 |
+
</p>
|
220 |
+
<p>
|
221 |
+
<label for="wpsl-limit"><?php _e( 'Query limit error:', 'wpsl' ); ?> *</label>
|
222 |
+
<input type="text" value="<?php echo esc_attr( $this->settings['limit_label'] ); ?>" name="wpsl_label[limit]" class="textinput" id="wpsl-limit">
|
223 |
+
</p>
|
224 |
+
<em><?php _e( '* You can raise the <a href="https://developers.google.com/maps/documentation/javascript/usage#usage_limits">usage limit</a> by obtaining an API <a href="https://developers.google.com/maps/documentation/javascript/tutorial#api_key">key</a>, <br> and fill in the "API key" field at the top of this page.', 'wpsl' ); ?></em>
|
225 |
+
</div>
|
226 |
+
</div>
|
227 |
+
</div>
|
228 |
+
</div>
|
229 |
+
|
230 |
+
<input type="submit" value="<?php _e( 'Update Settings', 'wpsl' ); ?>" class="button-primary" name="wpsl-save-settings" id="wpsl-save-settings">
|
231 |
+
<?php settings_fields( 'wpsl_settings' ); ?>
|
232 |
+
</form>
|
233 |
+
|
234 |
+
</div>
|
admin/templates/stores-overview.php
ADDED
@@ -0,0 +1,24 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
require_once WPSL_PLUGIN_DIR . 'admin/class-store-overview.php';
|
3 |
+
|
4 |
+
$store_overview = new WPSL_Store_Overview();
|
5 |
+
$store_overview->prepare_items();
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div id="wpsl-store-overview" class="wrap">
|
9 |
+
<h2>WP Store Locator</h2>
|
10 |
+
<?php settings_errors(); ?>
|
11 |
+
|
12 |
+
<ul id="wpsl-mainnav">
|
13 |
+
<li><a class="nav-tab nav-tab-active" href="<?php echo admin_url( 'admin.php?page=wpsl_store_editor' ); ?>"><?php _e( 'Current Stores', 'wpsl' ); ?></a></li>
|
14 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_add_store' ); ?>"><?php _e( 'Add Store', 'wpsl' ); ?></a></li>
|
15 |
+
<li><a class="nav-tab" href="<?php echo admin_url( 'admin.php?page=wpsl_settings' ); ?>"><?php _e( 'Settings', 'wpsl' ); ?></a></li>
|
16 |
+
</ul>
|
17 |
+
|
18 |
+
<form method="post">
|
19 |
+
<?php
|
20 |
+
$store_overview->search_box( 'search', 'search_id' );
|
21 |
+
$store_overview->display();
|
22 |
+
?>
|
23 |
+
</form>
|
24 |
+
</div>
|
css/styles.css
ADDED
@@ -0,0 +1,598 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/* The map container */
|
2 |
+
#wpsl-gmap {
|
3 |
+
float:left;
|
4 |
+
width:66.5%;
|
5 |
+
height:350px;
|
6 |
+
}
|
7 |
+
|
8 |
+
/*
|
9 |
+
Some themes set a box-shadow or max-width for all image /
|
10 |
+
div elements, we disable it to prevent it from messing up the map
|
11 |
+
*/
|
12 |
+
#wpsl-gmap div,
|
13 |
+
#wpsl-gmap img {
|
14 |
+
box-shadow:none;
|
15 |
+
max-width:none;
|
16 |
+
background:none;
|
17 |
+
}
|
18 |
+
|
19 |
+
#wpsl-wrap {
|
20 |
+
width:100%;
|
21 |
+
overflow:hidden;
|
22 |
+
clear:both;
|
23 |
+
}
|
24 |
+
#wpsl-search-wrap {
|
25 |
+
float:left;
|
26 |
+
}
|
27 |
+
#wpsl-search-input {
|
28 |
+
width:179px;
|
29 |
+
padding: 7px 12px;
|
30 |
+
font-size: 100%;
|
31 |
+
/* padding: 3% 12px;*/
|
32 |
+
}
|
33 |
+
#wpsl-search-wrap input,
|
34 |
+
#wpsl-search-btn {
|
35 |
+
border: 1px solid #d2d2d2;
|
36 |
+
border-radius: 3px;
|
37 |
+
}
|
38 |
+
|
39 |
+
#wpsl-search-btn {
|
40 |
+
padding: 7px 10px;
|
41 |
+
line-height: 1.428571429;
|
42 |
+
font-weight: normal;
|
43 |
+
color: #7c7c7c;
|
44 |
+
background-color: #e6e6e6;
|
45 |
+
background-repeat: repeat-x;
|
46 |
+
background-image: -moz-linear-gradient(top, #f4f4f4, #e6e6e6);
|
47 |
+
background-image: -ms-linear-gradient(top, #f4f4f4, #e6e6e6);
|
48 |
+
background-image: -webkit-linear-gradient(top, #f4f4f4, #e6e6e6);
|
49 |
+
background-image: -o-linear-gradient(top, #f4f4f4, #e6e6e6);
|
50 |
+
background-image: linear-gradient(top, #f4f4f4, #e6e6e6);
|
51 |
+
box-shadow: 0 1px 2px rgba(64, 64, 64, 0.1);
|
52 |
+
text-transform: none !important;
|
53 |
+
}
|
54 |
+
|
55 |
+
.wpsl-search {
|
56 |
+
margin-bottom:12px;
|
57 |
+
padding:12px 12px 0 12px;
|
58 |
+
background:#f4f3f3;
|
59 |
+
}
|
60 |
+
|
61 |
+
/* Result list */
|
62 |
+
#wpsl-result-list {
|
63 |
+
float:left;
|
64 |
+
width:33%;
|
65 |
+
margin-right:0.5%;
|
66 |
+
}
|
67 |
+
|
68 |
+
#wpsl-stores,
|
69 |
+
#wpsl-direction-details {
|
70 |
+
height:350px;
|
71 |
+
overflow-y:auto;
|
72 |
+
}
|
73 |
+
#wpsl-direction-details {display:none;}
|
74 |
+
|
75 |
+
#wpsl-result-list p {
|
76 |
+
padding-left:10px;
|
77 |
+
}
|
78 |
+
#wpsl-result-list p a {
|
79 |
+
display:block;
|
80 |
+
margin-bottom:10px;
|
81 |
+
}
|
82 |
+
|
83 |
+
#wpsl-result-list li {
|
84 |
+
padding: 10px;
|
85 |
+
border-bottom: 1px dotted #ccc;
|
86 |
+
margin-left: 0;
|
87 |
+
overflow: hidden;
|
88 |
+
list-style: none outside none !important
|
89 |
+
}
|
90 |
+
#wpsl-result-list li p {
|
91 |
+
padding-left:0;
|
92 |
+
margin-bottom:20px;
|
93 |
+
}
|
94 |
+
#wpsl-stores .wpsl-store-thumb {
|
95 |
+
float:right;
|
96 |
+
border-radius:3px;
|
97 |
+
margin:7px 0 0 10px;
|
98 |
+
width:48px;
|
99 |
+
height:48px;
|
100 |
+
padding:0;
|
101 |
+
border:none;
|
102 |
+
}
|
103 |
+
.wpsl-direction-index {
|
104 |
+
float:left;
|
105 |
+
width:8%;
|
106 |
+
margin:0 5% 0 0;
|
107 |
+
}
|
108 |
+
.wpsl-direction-txt {
|
109 |
+
float:left;
|
110 |
+
width:62%;
|
111 |
+
}
|
112 |
+
.wpsl-direction-distance {
|
113 |
+
float:left;
|
114 |
+
width:20%;
|
115 |
+
margin:0 0 0 5%;
|
116 |
+
}
|
117 |
+
.wpsl-direction-txt span {
|
118 |
+
display:block;
|
119 |
+
margin-top:10px;
|
120 |
+
}
|
121 |
+
|
122 |
+
.wpsl-street,
|
123 |
+
.wpsl-country,
|
124 |
+
.wpsl-directions {
|
125 |
+
display:block;
|
126 |
+
border-bottom:none !important;
|
127 |
+
}
|
128 |
+
|
129 |
+
/* Preloader */
|
130 |
+
#wpsl-result-list li.wpsl-preloader {
|
131 |
+
border-bottom:none;
|
132 |
+
}
|
133 |
+
.wpsl-preloader img {
|
134 |
+
float:left;
|
135 |
+
box-shadow:none !important;
|
136 |
+
border:none !important;
|
137 |
+
}
|
138 |
+
|
139 |
+
.wpsl-preloader span {
|
140 |
+
float:left;
|
141 |
+
margin:-5px 0 0 11px;
|
142 |
+
}
|
143 |
+
|
144 |
+
#wpsl-search-wrap div,
|
145 |
+
#wpsl-search-btn {
|
146 |
+
margin-right:10px;
|
147 |
+
float:left;
|
148 |
+
/* height:32px;*/
|
149 |
+
}
|
150 |
+
|
151 |
+
#wpsl-radius {margin-right:10px;}
|
152 |
+
/*#wpsl-search-wrap #wpsl-results {
|
153 |
+
margin-right: 0;
|
154 |
+
}*/
|
155 |
+
#wpsl-search-btn:hover {
|
156 |
+
cursor: pointer;
|
157 |
+
}
|
158 |
+
|
159 |
+
#wpsl-search-wrap select,
|
160 |
+
#wpsl-search select {
|
161 |
+
display:none;
|
162 |
+
}
|
163 |
+
|
164 |
+
#wpsl-search-wrap div label {
|
165 |
+
float:left;
|
166 |
+
margin-right:10px;
|
167 |
+
/* margin-top: 4px;*/
|
168 |
+
line-height: 32px;
|
169 |
+
}
|
170 |
+
|
171 |
+
#wpsl-result-list ul {
|
172 |
+
list-style: none;
|
173 |
+
margin: 0;
|
174 |
+
padding: 0;
|
175 |
+
}
|
176 |
+
.wpsl-direction-details {
|
177 |
+
display: none;
|
178 |
+
}
|
179 |
+
|
180 |
+
/* Infowindow */
|
181 |
+
#wpsl-gmap .wpsl-info-window {
|
182 |
+
max-width:225px;
|
183 |
+
}
|
184 |
+
.wpsl-info-window span {
|
185 |
+
display:block;
|
186 |
+
}
|
187 |
+
.wpsl-info-window p {
|
188 |
+
margin-bottom:10px;
|
189 |
+
}
|
190 |
+
.wpsl-store-hours {
|
191 |
+
margin-top:10px;
|
192 |
+
}
|
193 |
+
.wpsl-store-hours strong {
|
194 |
+
display:block;
|
195 |
+
}
|
196 |
+
.wpsl-info-window .wpsl-directions {
|
197 |
+
margin:10px 0;
|
198 |
+
}
|
199 |
+
|
200 |
+
/* --- EASYDROPDOWN DEFAULT THEME --- */
|
201 |
+
.wpsl-dropdown,
|
202 |
+
.wpsl-dropdown div,
|
203 |
+
.wpsl-dropdown li,
|
204 |
+
.wpsl-dropdown div::after{
|
205 |
+
-webkit-transition: all 150ms ease-in-out;
|
206 |
+
-moz-transition: all 150ms ease-in-out;
|
207 |
+
-ms-transition: all 150ms ease-in-out;
|
208 |
+
transition: all 150ms ease-in-out;
|
209 |
+
}
|
210 |
+
|
211 |
+
.wpsl-dropdown .selected::after,
|
212 |
+
.wpsl-dropdown.scrollable div::after{
|
213 |
+
-webkit-pointer-events: none;
|
214 |
+
-moz-pointer-events: none;
|
215 |
+
-ms-pointer-events: none;
|
216 |
+
pointer-events: none;
|
217 |
+
}
|
218 |
+
|
219 |
+
/* WRAPPER */
|
220 |
+
.wpsl-dropdown {
|
221 |
+
position: relative;
|
222 |
+
width: 90px;
|
223 |
+
border: 1px solid #ccc;
|
224 |
+
cursor: pointer;
|
225 |
+
background: #fff;
|
226 |
+
border-radius: 3px;
|
227 |
+
-webkit-user-select: none;
|
228 |
+
-moz-user-select: none;
|
229 |
+
user-select: none;
|
230 |
+
margin-right: 0 !important;
|
231 |
+
}
|
232 |
+
|
233 |
+
.wpsl-no-results .wpsl-dropdown {
|
234 |
+
width: 114px;
|
235 |
+
}
|
236 |
+
|
237 |
+
.wpsl-dropdown.open{
|
238 |
+
z-index: 2;
|
239 |
+
}
|
240 |
+
#wpsl-search-input:hover,
|
241 |
+
.wpsl-dropdown:hover{
|
242 |
+
box-shadow: 0 0 5px rgba(0,0,0,.15);
|
243 |
+
}
|
244 |
+
wpsl-search-input.focus,
|
245 |
+
.wpsl-dropdown.focus{
|
246 |
+
box-shadow: 0 0 5px rgba(51,102,248,.4);
|
247 |
+
}
|
248 |
+
|
249 |
+
/* CARAT */
|
250 |
+
.wpsl-dropdown .carat{
|
251 |
+
position: absolute;
|
252 |
+
right: 12px;
|
253 |
+
top: 50%;
|
254 |
+
margin-top: -4px;
|
255 |
+
border: 6px solid transparent;
|
256 |
+
border-top: 8px solid #000;
|
257 |
+
}
|
258 |
+
|
259 |
+
.wpsl-dropdown.open .carat{
|
260 |
+
margin-top: -10px;
|
261 |
+
border-top: 6px solid transparent;
|
262 |
+
border-bottom: 8px solid #000;
|
263 |
+
}
|
264 |
+
|
265 |
+
.wpsl-dropdown.disabled .carat{
|
266 |
+
border-top-color: #999;
|
267 |
+
}
|
268 |
+
|
269 |
+
/* OLD SELECT (HIDDEN) */
|
270 |
+
.wpsl-dropdown .old{
|
271 |
+
position: absolute;
|
272 |
+
left: 0;
|
273 |
+
top: 0;
|
274 |
+
height: 0;
|
275 |
+
width: 0;
|
276 |
+
overflow: hidden;
|
277 |
+
}
|
278 |
+
|
279 |
+
.wpsl-dropdown select{
|
280 |
+
position: absolute;
|
281 |
+
left: 0px;
|
282 |
+
top: 0px;
|
283 |
+
}
|
284 |
+
|
285 |
+
.wpsl-dropdown.touch .old{
|
286 |
+
width: 100%;
|
287 |
+
height: 100%;
|
288 |
+
}
|
289 |
+
|
290 |
+
.wpsl-dropdown.touch select{
|
291 |
+
width: 100%;
|
292 |
+
height: 100%;
|
293 |
+
opacity: 0;
|
294 |
+
}
|
295 |
+
|
296 |
+
/* SELECTED FEEDBACK ITEM */
|
297 |
+
|
298 |
+
/*select.wpsl-dropdown {display:none;}*/
|
299 |
+
#wpsl-search-wrap .wpsl-dropdown div {
|
300 |
+
margin-right: 0;
|
301 |
+
}
|
302 |
+
.wpsl-dropdown .selected,
|
303 |
+
.wpsl-dropdown li{
|
304 |
+
display: block;
|
305 |
+
line-height: 1;
|
306 |
+
color: #000;
|
307 |
+
padding: 9px 12px;
|
308 |
+
overflow: hidden;
|
309 |
+
white-space: nowrap;
|
310 |
+
}
|
311 |
+
|
312 |
+
.wpsl-dropdown.disabled .selected{
|
313 |
+
color: #999;
|
314 |
+
}
|
315 |
+
|
316 |
+
.wpsl-dropdown .selected::after{
|
317 |
+
content: '';
|
318 |
+
position: absolute;
|
319 |
+
right: 0;
|
320 |
+
top: 0;
|
321 |
+
bottom: 0;
|
322 |
+
width: 60px;
|
323 |
+
border-radius: 0 2px 2px 0;
|
324 |
+
}
|
325 |
+
|
326 |
+
/* DROP DOWN WRAPPER */
|
327 |
+
.wpsl-dropdown div{
|
328 |
+
position: absolute;
|
329 |
+
height: 0;
|
330 |
+
left: -1px;
|
331 |
+
right: -1px;
|
332 |
+
top: 100%;
|
333 |
+
margin-top: -1px;
|
334 |
+
background: #fff;
|
335 |
+
border: 1px solid #ccc;
|
336 |
+
border-top: 1px solid #eee;
|
337 |
+
border-radius: 0 0 3px 3px;
|
338 |
+
overflow: hidden;
|
339 |
+
opacity: 0;
|
340 |
+
}
|
341 |
+
|
342 |
+
/* Height is adjusted by JS on open */
|
343 |
+
|
344 |
+
.wpsl-dropdown.open div{
|
345 |
+
opacity: 1;
|
346 |
+
z-index: 2;
|
347 |
+
}
|
348 |
+
|
349 |
+
/* FADE OVERLAY FOR SCROLLING LISTS */
|
350 |
+
|
351 |
+
.wpsl-dropdown.scrollable div::after{
|
352 |
+
content: '';
|
353 |
+
position: absolute;
|
354 |
+
left: 0;
|
355 |
+
right: 0;
|
356 |
+
bottom: 0;
|
357 |
+
height: 50px;
|
358 |
+
box-shadow: inset 0 -50px 30px -35px #fff;
|
359 |
+
}
|
360 |
+
|
361 |
+
.wpsl-dropdown.scrollable.bottom div::after{
|
362 |
+
opacity: 0;
|
363 |
+
}
|
364 |
+
|
365 |
+
/* DROP DOWN LIST */
|
366 |
+
|
367 |
+
.wpsl-dropdown ul{
|
368 |
+
position: absolute;
|
369 |
+
left: 0;
|
370 |
+
top: 0;
|
371 |
+
height: 100%;
|
372 |
+
width: 100%;
|
373 |
+
list-style: none;
|
374 |
+
overflow: hidden;
|
375 |
+
padding:0;
|
376 |
+
margin:0;
|
377 |
+
}
|
378 |
+
|
379 |
+
.wpsl-dropdown.scrollable.open ul{
|
380 |
+
overflow-y: auto;
|
381 |
+
}
|
382 |
+
|
383 |
+
/* DROP DOWN LIST ITEMS */
|
384 |
+
.wpsl-dropdown li{
|
385 |
+
list-style: none;
|
386 |
+
padding: 8px 12px !important;
|
387 |
+
margin:0 !important;
|
388 |
+
}
|
389 |
+
|
390 |
+
/* .focus class is also added on hover */
|
391 |
+
|
392 |
+
.wpsl-dropdown li.focus{
|
393 |
+
background: #f8f9f8;
|
394 |
+
position: relative;
|
395 |
+
z-index: 3;
|
396 |
+
color: #000;
|
397 |
+
}
|
398 |
+
|
399 |
+
.wpsl-dropdown li.active{
|
400 |
+
font-weight: 700;
|
401 |
+
}
|
402 |
+
|
403 |
+
.clearfix:before,
|
404 |
+
.clearfix:after {
|
405 |
+
content: " ";
|
406 |
+
display: table;
|
407 |
+
}
|
408 |
+
.clearfix:after {
|
409 |
+
clear: both;
|
410 |
+
}
|
411 |
+
|
412 |
+
#wpsl-results .wpsl-dropdown {
|
413 |
+
width:70px;
|
414 |
+
}
|
415 |
+
|
416 |
+
.wpsl-input, .wpsl-select-wrap {
|
417 |
+
margin-bottom:10px;
|
418 |
+
}
|
419 |
+
|
420 |
+
@media (max-width: 825px) {
|
421 |
+
#wpsl-search-input {
|
422 |
+
width: 348px;
|
423 |
+
}
|
424 |
+
|
425 |
+
#wpsl-search-wrap .wpsl-dropdown {
|
426 |
+
width:114px;
|
427 |
+
}
|
428 |
+
|
429 |
+
#wpsl-search-wrap .wpsl-input {
|
430 |
+
width: 100%;
|
431 |
+
margin-bottom:10px;
|
432 |
+
}
|
433 |
+
|
434 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-input,
|
435 |
+
.wpsl-no-results #wpsl-search-input,
|
436 |
+
.wpsl-no-results .wpsl-input label,
|
437 |
+
.wpsl-no-results #wpsl-radius label {
|
438 |
+
width: auto;
|
439 |
+
}
|
440 |
+
|
441 |
+
.wpsl-input label,
|
442 |
+
#wpsl-radius label {
|
443 |
+
min-width: 100px;
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
@media (max-width: 720px) {
|
448 |
+
.wpsl-no-results .wpsl-dropdown {
|
449 |
+
width: 100px;
|
450 |
+
}
|
451 |
+
|
452 |
+
#wpsl-search-wrap .wpsl-dropdown {
|
453 |
+
width: 114px;
|
454 |
+
}
|
455 |
+
|
456 |
+
.wpsl-no-results #wpsl-search-input {
|
457 |
+
width: 150px !important;
|
458 |
+
}
|
459 |
+
}
|
460 |
+
|
461 |
+
@media (max-width: 700px) {
|
462 |
+
.wpsl-no-results #wpsl-search-input {
|
463 |
+
width: 250px !important;
|
464 |
+
}
|
465 |
+
|
466 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-input {
|
467 |
+
margin-bottom:10px;
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
@media (max-width: 675px) {
|
472 |
+
#wpsl-search-wrap #wpsl-search-btn {
|
473 |
+
float:left;
|
474 |
+
margin:0 5px 5px 0;
|
475 |
+
}
|
476 |
+
|
477 |
+
.wpsl-dropdown {
|
478 |
+
width: 100%;
|
479 |
+
}
|
480 |
+
.wpsl-search {
|
481 |
+
width: 96%;
|
482 |
+
padding: 2%;
|
483 |
+
}
|
484 |
+
.wpsl-input {
|
485 |
+
margin-right:0;
|
486 |
+
}
|
487 |
+
|
488 |
+
#wpsl-result-list,
|
489 |
+
#wpsl-gmap {
|
490 |
+
width:49.75%;
|
491 |
+
}
|
492 |
+
#wpsl-result-list,
|
493 |
+
#wpsl-gmap {
|
494 |
+
width:100%;
|
495 |
+
}
|
496 |
+
#wpsl-gmap {
|
497 |
+
margin-top:10px;
|
498 |
+
}
|
499 |
+
|
500 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-input {
|
501 |
+
width:100%;
|
502 |
+
}
|
503 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-dropdown {
|
504 |
+
width: 201px;
|
505 |
+
}
|
506 |
+
|
507 |
+
.wpsl-input, .wpsl-select-wrap, #wpsl-search-btn {
|
508 |
+
margin-bottom:0;
|
509 |
+
}
|
510 |
+
}
|
511 |
+
|
512 |
+
@media (max-width: 570px) {
|
513 |
+
#wpsl-search-input {
|
514 |
+
width: 277px;
|
515 |
+
}
|
516 |
+
#wpsl-search-wrap #wpsl-search-btn {
|
517 |
+
margin-top:15px;
|
518 |
+
}
|
519 |
+
|
520 |
+
.wpsl-no-results #wpsl-search-wrap #wpsl-search-btn {
|
521 |
+
margin-top:0;
|
522 |
+
}
|
523 |
+
}
|
524 |
+
|
525 |
+
@media (max-width: 520px) {
|
526 |
+
.wpsl-search {
|
527 |
+
width: 94%;
|
528 |
+
padding: 3%;
|
529 |
+
}
|
530 |
+
#wpsl-search-input {
|
531 |
+
width:91%;
|
532 |
+
}
|
533 |
+
#wpsl-search-wrap div,
|
534 |
+
#wpsl-search-btn {
|
535 |
+
margin-right: 0;
|
536 |
+
}
|
537 |
+
|
538 |
+
#wpsl-search-wrap div label {
|
539 |
+
display:block;
|
540 |
+
width:100%;
|
541 |
+
}
|
542 |
+
|
543 |
+
.wpsl-no-results #wpsl-search-wrap div label {
|
544 |
+
display:inline;
|
545 |
+
width: auto;
|
546 |
+
}
|
547 |
+
.wpsl-no-results #wpsl-search-input,
|
548 |
+
.wpsl-no-results #wpsl-radius,
|
549 |
+
#wpsl-results {
|
550 |
+
width:auto;
|
551 |
+
}
|
552 |
+
|
553 |
+
.wpsl-select-wrap {
|
554 |
+
width:100%;
|
555 |
+
}
|
556 |
+
|
557 |
+
#wpsl-radius, #wpsl-results {
|
558 |
+
width:50%;
|
559 |
+
}
|
560 |
+
#wpsl-radius {
|
561 |
+
margin-right: 4%;
|
562 |
+
}
|
563 |
+
#wpsl-search-wrap .wpsl-dropdown {
|
564 |
+
width: 96%;
|
565 |
+
}
|
566 |
+
|
567 |
+
.wpsl-no-results #wpsl-search-wrap #wpsl-search-btn {
|
568 |
+
margin-top:15px;
|
569 |
+
}
|
570 |
+
|
571 |
+
#wpsl-search-btn {
|
572 |
+
clear: both;
|
573 |
+
}
|
574 |
+
}
|
575 |
+
|
576 |
+
@media (max-width: 460px) {
|
577 |
+
#wpsl-search-input {
|
578 |
+
width:90%;
|
579 |
+
}
|
580 |
+
.wpsl-no-results #wpsl-search-wrap div label {
|
581 |
+
display:block;
|
582 |
+
}
|
583 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-dropdown {
|
584 |
+
width: 274px;
|
585 |
+
}
|
586 |
+
}
|
587 |
+
|
588 |
+
@media (max-width: 375px) {
|
589 |
+
#wpsl-search-input {
|
590 |
+
width:88%;
|
591 |
+
}
|
592 |
+
.wpsl-no-results #wpsl-search-input {
|
593 |
+
width:200px !important;
|
594 |
+
}
|
595 |
+
.wpsl-no-results #wpsl-search-wrap .wpsl-dropdown {
|
596 |
+
width:223px !important;
|
597 |
+
}
|
598 |
+
}
|
frontend/class-frontend.php
ADDED
@@ -0,0 +1,179 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Frontend class
|
4 |
+
*
|
5 |
+
* @package WP_Store_locator
|
6 |
+
* @subpackage Classes/Frontend
|
7 |
+
* @copyright Copyright (c) 2013, Tijmen Smit
|
8 |
+
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
9 |
+
* @since 1.0
|
10 |
+
*/
|
11 |
+
|
12 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
13 |
+
|
14 |
+
if ( !class_exists( 'WPSL_Frontend' ) ) {
|
15 |
+
/**
|
16 |
+
* Handle the frontend of the store locator
|
17 |
+
*
|
18 |
+
* @since 1.0
|
19 |
+
*/
|
20 |
+
class WPSL_Frontend extends WP_Store_locator {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Class constructor
|
24 |
+
*/
|
25 |
+
public function __construct() {
|
26 |
+
add_shortcode( 'wpsl', array( $this, 'render_store_locator' ) );
|
27 |
+
$this->settings = $this->get_settings();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Load the required front-end template and scripts
|
32 |
+
*
|
33 |
+
* @since 1.0
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
+
public function render_store_locator() {
|
37 |
+
require_once( WPSL_PLUGIN_DIR . 'frontend/templates/default.php' );
|
38 |
+
$this->add_frontend_scripts();
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Create the css rules based on the height / max-width that is set on the settings page
|
43 |
+
*
|
44 |
+
* @since 1.0
|
45 |
+
* @return string $css The custom css rules
|
46 |
+
*/
|
47 |
+
public function get_custom_css() {
|
48 |
+
$css = '<style>' . "\r\n";
|
49 |
+
$css .= "#wpsl-stores, #wpsl-direction-details, #wpsl-gmap {height:" . esc_attr( $this->settings['height'] ) . "px !important;}" . "\r\n";
|
50 |
+
$css .= "#wpsl-gmap .wpsl-info-window {max-width:" . esc_attr( $this->settings['infowindow_width'] ) . "px !important;}" . "\r\n";
|
51 |
+
$css .= ".wpsl-input label, #wpsl-radius label {width:" . esc_attr( $this->settings['label_width'] ) . "px;}" . "\r\n";
|
52 |
+
$css .= "#wpsl-search-input {width:" . esc_attr( $this->settings['search_width'] ) . "px !important;}" . "\r\n";
|
53 |
+
$css .= '</style>' . "\r\n";
|
54 |
+
|
55 |
+
return $css;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Collect all the attributes (language, key, region)
|
60 |
+
* we need before making a request to the Google Maps API
|
61 |
+
*
|
62 |
+
* @since 1.0
|
63 |
+
* @param string The name of the list we need to load data for
|
64 |
+
* @return string $dropdown_list A list with the available options for the dropdown list
|
65 |
+
*/
|
66 |
+
public function get_dropdown_list( $list_type ) {
|
67 |
+
|
68 |
+
$settings = explode( ',', $this->settings[$list_type] );
|
69 |
+
|
70 |
+
/* Only show the distance unit when we are dealing with the search radius */
|
71 |
+
if ( $list_type == 'search_radius' ) {
|
72 |
+
$distance_unit = ' '. esc_attr( $this->settings['distance_unit'] );
|
73 |
+
} else {
|
74 |
+
$distance_unit = '';
|
75 |
+
}
|
76 |
+
|
77 |
+
foreach ( $settings as $k => $setting_value ) {
|
78 |
+
|
79 |
+
/* The default radius has a () wrapped around it, so we check for that and filter out the () */
|
80 |
+
if ( strpos( $setting_value, '(' ) !== false ) {
|
81 |
+
$setting_value = filter_var( $setting_value, FILTER_SANITIZE_NUMBER_INT );
|
82 |
+
$selected = 'selected="selected"';
|
83 |
+
} else {
|
84 |
+
$selected = '';
|
85 |
+
}
|
86 |
+
|
87 |
+
$dropdown_list .= '<option ' . $selected . ' value="'. absint( $setting_value ) .'">'. absint( $setting_value ) . $distance_unit .'</option>';
|
88 |
+
}
|
89 |
+
|
90 |
+
return $dropdown_list;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Collect all the attributes (language, key, region)
|
95 |
+
* we need before making a request to the Google Maps API
|
96 |
+
*
|
97 |
+
* @since 1.0
|
98 |
+
* @return string $api_data The collected api attributes
|
99 |
+
*/
|
100 |
+
public function get_gmap_api_attributes() {
|
101 |
+
|
102 |
+
$api_attributes = array( 'language', 'key', 'region' );
|
103 |
+
|
104 |
+
foreach ( $api_attributes as $api_key ) {
|
105 |
+
if ( !empty( $this->settings['api_'.$api_key] ) ) {
|
106 |
+
$api_data .= '&'.$api_key.'=' . $this->settings['api_'.$api_key];
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
return $api_data;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Create a filename with @2x in it for the selected marker color.
|
115 |
+
* So when a user selected green.png in the admin panel. The js on the front-end will end up
|
116 |
+
* loading green@2x.png to provide support for retina compatible devices.
|
117 |
+
*
|
118 |
+
* @since 1.0
|
119 |
+
* @param string $filename The name of the seleted marker
|
120 |
+
* @return string $filename The filename with @2x added to the end
|
121 |
+
*/
|
122 |
+
public function create_retina_filename( $filename ) {
|
123 |
+
|
124 |
+
$filename = explode( '.', $filename );
|
125 |
+
$filename = $filename[0] . '@2x.' . $filename[1];
|
126 |
+
|
127 |
+
return $filename;
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Load the front-end scripts and localize the required js data
|
132 |
+
*
|
133 |
+
* @since 1.0
|
134 |
+
* @return void
|
135 |
+
*/
|
136 |
+
public function add_frontend_scripts( ) {
|
137 |
+
wp_enqueue_style( 'wpsl-css', WPSL_URL . 'css/styles.css', false );
|
138 |
+
wp_enqueue_script( 'wpsl-dropdown', WPSL_URL.'js/jquery.easydropdown.min.js', array( 'jquery' ) ); //not minified version is in the js folder
|
139 |
+
wp_enqueue_script( 'wpsl-gmap', ( "//maps.google.com/maps/api/js?sensor=false".$this->get_gmap_api_attributes() ),'' ,'' ,true );
|
140 |
+
wp_enqueue_script( 'wpsl-js', WPSL_URL.'js/wpsl-gmap.js', array( 'jquery' ) );
|
141 |
+
|
142 |
+
$settings = array(
|
143 |
+
'startMarker' => $this->create_retina_filename( $this->settings['start_marker'] ),
|
144 |
+
'storeMarker' => $this->create_retina_filename( $this->settings['store_marker'] ),
|
145 |
+
'autoLocate' => $this->settings['auto_locate'],
|
146 |
+
'mapType' => $this->settings['map_type'],
|
147 |
+
'zoomLevel' => $this->settings['zoom_level'],
|
148 |
+
'zoomLatlng' => $this->settings['zoom_latlng'],
|
149 |
+
'streetView' => $this->settings['streetview'],
|
150 |
+
'panControls' => $this->settings['pan_controls'],
|
151 |
+
'controlPosition' => $this->settings['control_position'],
|
152 |
+
'controlStyle' => $this->settings['control_style'],
|
153 |
+
'markerBounce' => $this->settings['marker_bounce'],
|
154 |
+
'distanceUnit' => ucfirst( $this->settings['distance_unit'] ),
|
155 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
156 |
+
'path' => WPSL_URL,
|
157 |
+
);
|
158 |
+
|
159 |
+
$labels = array(
|
160 |
+
'preloader' => $this->settings['preloader_label'],
|
161 |
+
'noResults' => $this->settings['no_results_label'],
|
162 |
+
'generalError' => $this->settings['error_label'],
|
163 |
+
'queryLimit' => $this->settings['limit_label'],
|
164 |
+
'directions' => $this->settings['directions_label'],
|
165 |
+
'phone' => $this->settings['phone_label'],
|
166 |
+
'fax' => $this->settings['fax_label'],
|
167 |
+
'hours' => $this->settings['hours_label'],
|
168 |
+
'startPoint' => $this->settings['start_label']
|
169 |
+
);
|
170 |
+
|
171 |
+
wp_localize_script( 'wpsl-js', 'wpslSettings', $settings );
|
172 |
+
wp_localize_script( 'wpsl-js', 'wpslLabels', $labels );
|
173 |
+
}
|
174 |
+
|
175 |
+
}
|
176 |
+
|
177 |
+
new WPSL_Frontend;
|
178 |
+
|
179 |
+
}
|
frontend/templates/default.php
ADDED
@@ -0,0 +1,45 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
echo $this->get_custom_css();
|
3 |
+
|
4 |
+
$show_results_filter = $this->settings['results_dropdown'];
|
5 |
+
$results_filter_class = ( $show_results_filter ) ? '' : 'wpsl-no-results';
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div id="wpsl-wrap">
|
9 |
+
<div class="wpsl-search clearfix <?php echo $results_filter_class; ?>">
|
10 |
+
<div id="wpsl-search-wrap">
|
11 |
+
<div class="wpsl-input">
|
12 |
+
<label for="wpsl-search-input"><?php echo esc_attr( $this->settings['search_label'] ); ?></label>
|
13 |
+
<input autocomplete="off" id="wpsl-search-input" type="text" value="" name="wpsl-search-input" />
|
14 |
+
</div>
|
15 |
+
<div class="wpsl-select-wrap">
|
16 |
+
<div id="wpsl-radius">
|
17 |
+
<label for="wpsl-radius"><?php echo esc_attr( $this->settings['radius_label'] ); ?></label>
|
18 |
+
<select autocomplete="off" class="wpsl-dropdown" name="wpsl-radius">
|
19 |
+
<?php echo $this->get_dropdown_list( 'search_radius' ); ?>
|
20 |
+
</select>
|
21 |
+
</div>
|
22 |
+
<?php if ( $show_results_filter ) { ?>
|
23 |
+
<div id="wpsl-results">
|
24 |
+
<label for="wpsl-results"><?php echo esc_attr( $this->settings['results_label'] ); ?></label>
|
25 |
+
<select autocomplete="off" class="wpsl-dropdown" name="wpsl-results">
|
26 |
+
<?php echo $this->get_dropdown_list( 'max_results' ); ?>
|
27 |
+
</select>
|
28 |
+
</div>
|
29 |
+
<?php } ?>
|
30 |
+
<input id="wpsl-search-btn" type="submit" value="<?php echo esc_attr( $this->settings['search_btn_label'] ); ?>" />
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
<div id="wpsl-result-list">
|
36 |
+
<div id="wpsl-stores">
|
37 |
+
<ul></ul>
|
38 |
+
</div>
|
39 |
+
<div id="wpsl-direction-details">
|
40 |
+
<ul></ul>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
|
44 |
+
<div id="wpsl-gmap"></div>
|
45 |
+
</div>
|
frontend/wpsl-ajax-functions.php
ADDED
@@ -0,0 +1,114 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
add_action( 'wp_ajax_store_search', 'wpsl_store_search' );
|
3 |
+
add_action( 'wp_ajax_nopriv_store_search', 'wpsl_store_search' );
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Handle the ajax store search on the frontend.
|
7 |
+
*
|
8 |
+
* Search for stores that fall within the selected distance range.
|
9 |
+
* This happens by calculating the distance between the latlng of the starting point
|
10 |
+
* and the latlng from the stores.
|
11 |
+
*
|
12 |
+
* @since 1.0
|
13 |
+
* @return json The list of stores in $store_results that matches with the request or false if the query returns no results
|
14 |
+
*/
|
15 |
+
function wpsl_store_search() {
|
16 |
+
|
17 |
+
global $wpdb;
|
18 |
+
|
19 |
+
$options = get_option( 'wpsl_settings' );
|
20 |
+
$distance_unit = ( $options['distance_unit'] == 'km' ) ? '6371' : '3959';
|
21 |
+
$allowed_html = '';
|
22 |
+
|
23 |
+
/* If no max results is set, we get the default value from the settings.
|
24 |
+
* The only situation when it can be empty, is when the "Show the limit results dropdown"
|
25 |
+
* checkbox is unchecked on the settings page.
|
26 |
+
*/
|
27 |
+
if ( !$_GET['max_results'] ) {
|
28 |
+
$max_results = get_default_list_value( $type = 'max_results' );
|
29 |
+
} else {
|
30 |
+
$max_results = $_GET['max_results'];
|
31 |
+
}
|
32 |
+
|
33 |
+
$result = $wpdb->get_results(
|
34 |
+
$wpdb->prepare(
|
35 |
+
"
|
36 |
+
SELECT *, ( $distance_unit * acos( cos( radians( %s ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians( %s ) ) + sin( radians( %s ) ) * sin( radians( lat ) ) ) )
|
37 |
+
AS distance FROM $wpdb->wpsl_stores
|
38 |
+
WHERE active = 1
|
39 |
+
HAVING distance < %d
|
40 |
+
ORDER BY distance LIMIT 0 ,%d
|
41 |
+
",
|
42 |
+
$_GET['lat'],
|
43 |
+
$_GET['lng'],
|
44 |
+
$_GET['lat'],
|
45 |
+
$_GET['radius'],
|
46 |
+
$max_results
|
47 |
+
)
|
48 |
+
);
|
49 |
+
|
50 |
+
if ( $result === false ) {
|
51 |
+
wp_send_json_error();
|
52 |
+
} else {
|
53 |
+
$store_results = array();
|
54 |
+
|
55 |
+
foreach ( $result as $k => $v ) {
|
56 |
+
/* If we have a valid thumb id, get the src */
|
57 |
+
if ( absint ( $result[$k]->thumb_id ) ) {
|
58 |
+
$thumb_src = wp_get_attachment_image_src( $result[$k]->thumb_id );
|
59 |
+
$result[$k]->thumb_src = $thumb_src[0];
|
60 |
+
} else {
|
61 |
+
$result[$k]->thumb_src = '';
|
62 |
+
}
|
63 |
+
|
64 |
+
/* Sanitize the results before they are returned */
|
65 |
+
$store_results[] = array (
|
66 |
+
'id' => wp_kses( $result[$k]->wpsl_id, $allowed_html ),
|
67 |
+
'store' => wp_kses( $result[$k]->store, $allowed_html ),
|
68 |
+
'street' => wp_kses( $result[$k]->street, $allowed_html ),
|
69 |
+
'city' => wp_kses( $result[$k]->city, $allowed_html ),
|
70 |
+
'state' => wp_kses( $result[$k]->state, $allowed_html ),
|
71 |
+
'zip' => wp_kses( $result[$k]->zip, $allowed_html ),
|
72 |
+
'country' => wp_kses( $result[$k]->country, $allowed_html ),
|
73 |
+
'distance' => wp_kses( $result[$k]->distance, $allowed_html ),
|
74 |
+
'lat' => wp_kses( $result[$k]->lat, $allowed_html ),
|
75 |
+
'lng' => wp_kses( $result[$k]->lng, $allowed_html ),
|
76 |
+
'description' => wpautop( wp_kses( $result[$k]->description, $allowed_html ) ),
|
77 |
+
'phone' => wp_kses( $result[$k]->phone, $allowed_html ),
|
78 |
+
'fax' => wp_kses( $result[$k]->fax, $allowed_html ),
|
79 |
+
'email' => wp_kses( $result[$k]->email, $allowed_html ),
|
80 |
+
'hours' => wpautop( wp_kses( $result[$k]->hours, $allowed_html ) ),
|
81 |
+
'url' => esc_url( $result[$k]->url, $allowed_html ),
|
82 |
+
'thumb' => esc_url( $result[$k]->thumb_src, $allowed_html )
|
83 |
+
);
|
84 |
+
}
|
85 |
+
|
86 |
+
wp_send_json( $store_results );
|
87 |
+
}
|
88 |
+
|
89 |
+
die();
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Get the default selected value for a dropdown
|
94 |
+
*
|
95 |
+
* @since 1.0
|
96 |
+
* @param string $type The request list type
|
97 |
+
* @return string $response The default list value
|
98 |
+
*/
|
99 |
+
function get_default_list_value( $type ) {
|
100 |
+
|
101 |
+
$settings = get_option( 'wpsl_settings' );
|
102 |
+
$list_values = explode( ',', $settings[$type] );
|
103 |
+
|
104 |
+
foreach ( $list_values as $k => $list_value ) {
|
105 |
+
|
106 |
+
/* The default radius has a () wrapped around it, so we check for that and filter out the () */
|
107 |
+
if ( strpos( $list_value, '(' ) !== false ) {
|
108 |
+
$response = filter_var( $list_value, FILTER_SANITIZE_NUMBER_INT );
|
109 |
+
break;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
return $response;
|
114 |
+
}
|
img/ajax-loader.gif
ADDED
Binary file
|
img/markers/blue.png
ADDED
Binary file
|
img/markers/blue@2x.png
ADDED
Binary file
|
img/markers/dark-blue.png
ADDED
Binary file
|
img/markers/dark-blue@2x.png
ADDED
Binary file
|
img/markers/dark-green.png
ADDED
Binary file
|
img/markers/dark-green@2x.png
ADDED
Binary file
|
img/markers/dark-orange.png
ADDED
Binary file
|
img/markers/dark-orange@2x.png
ADDED
Binary file
|
img/markers/green.png
ADDED
Binary file
|
img/markers/green@2x.png
ADDED
Binary file
|
img/markers/orange.png
ADDED
Binary file
|
img/markers/orange@2x.png
ADDED
Binary file
|
img/markers/pink.png
ADDED
Binary file
|
img/markers/pink@2x.png
ADDED
Binary file
|
img/markers/purple.png
ADDED
Binary file
|
img/markers/purple@2x.png
ADDED
Binary file
|
img/markers/red.png
ADDED
Binary file
|
img/markers/red@2x.png
ADDED
Binary file
|
img/store-locator-icon.png
ADDED
Binary file
|
js/jquery.easydropdown.js
ADDED
@@ -0,0 +1,469 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* EASYDROPDOWN - A Drop-down Builder for Styleable Inputs and Menus
|
3 |
+
* Version: 2.1.3
|
4 |
+
* License: Creative Commons Attribution 3.0 Unported - CC BY 3.0
|
5 |
+
* http://creativecommons.org/licenses/by/3.0/
|
6 |
+
* This software may be used freely on commercial and non-commercial projects with attribution to the author/copyright holder.
|
7 |
+
* Author: Patrick Kunka
|
8 |
+
* Copyright 2013 Patrick Kunka, All Rights Reserved
|
9 |
+
*/
|
10 |
+
|
11 |
+
|
12 |
+
(function($){
|
13 |
+
|
14 |
+
function EasyDropDown(){
|
15 |
+
this.isField = true,
|
16 |
+
this.down = false,
|
17 |
+
this.inFocus = false,
|
18 |
+
this.disabled = false,
|
19 |
+
this.cutOff = false,
|
20 |
+
this.hasLabel = false,
|
21 |
+
this.keyboardMode = false,
|
22 |
+
this.nativeTouch = true,
|
23 |
+
this.wrapperClass = 'dropdown',
|
24 |
+
this.onChange = null;
|
25 |
+
};
|
26 |
+
|
27 |
+
EasyDropDown.prototype = {
|
28 |
+
constructor: EasyDropDown,
|
29 |
+
instances: [],
|
30 |
+
init: function(domNode, settings){
|
31 |
+
var self = this;
|
32 |
+
|
33 |
+
$.extend(self, settings);
|
34 |
+
self.$select = $(domNode);
|
35 |
+
self.id = domNode.id;
|
36 |
+
self.options = [];
|
37 |
+
self.$options = self.$select.find('option');
|
38 |
+
self.isTouch = 'ontouchend' in document;
|
39 |
+
self.$select.removeClass(self.wrapperClass+' dropdown');
|
40 |
+
if(self.$select.is(':disabled')){
|
41 |
+
self.disabled = true;
|
42 |
+
};
|
43 |
+
if(self.$options.length){
|
44 |
+
self.$options.each(function(i){
|
45 |
+
var $option = $(this);
|
46 |
+
if($option.is(':selected')){
|
47 |
+
self.selected = {
|
48 |
+
index: i,
|
49 |
+
title: $option.text()
|
50 |
+
}
|
51 |
+
self.focusIndex = i;
|
52 |
+
};
|
53 |
+
if($option.hasClass('label') && i == 0){
|
54 |
+
self.hasLabel = true;
|
55 |
+
self.label = $option.text();
|
56 |
+
$option.attr('value','');
|
57 |
+
} else {
|
58 |
+
self.options.push({
|
59 |
+
domNode: $option[0],
|
60 |
+
title: $option.text(),
|
61 |
+
value: $option.val(),
|
62 |
+
selected: $option.is(':selected')
|
63 |
+
});
|
64 |
+
};
|
65 |
+
});
|
66 |
+
if(!self.selected){
|
67 |
+
self.selected = {
|
68 |
+
index: 0,
|
69 |
+
title: self.$options.eq(0).text()
|
70 |
+
}
|
71 |
+
self.focusIndex = 0;
|
72 |
+
};
|
73 |
+
self.render();
|
74 |
+
};
|
75 |
+
},
|
76 |
+
|
77 |
+
render: function(){
|
78 |
+
var self = this,
|
79 |
+
touchClass = self.isTouch && self.nativeTouch ? ' touch' : '',
|
80 |
+
disabledClass = self.disabled ? ' disabled' : '';
|
81 |
+
|
82 |
+
self.$container = self.$select.wrap('<div class="'+self.wrapperClass+touchClass+disabledClass+'"><span class="old"/></div>').parent().parent();
|
83 |
+
self.$active = $('<span class="selected">'+self.selected.title+'</span>').appendTo(self.$container);
|
84 |
+
self.$carat = $('<span class="carat"/>').appendTo(self.$container);
|
85 |
+
self.$scrollWrapper = $('<div><ul/></div>').appendTo(self.$container);
|
86 |
+
self.$dropDown = self.$scrollWrapper.find('ul');
|
87 |
+
self.$form = self.$container.closest('form');
|
88 |
+
$.each(self.options, function(){
|
89 |
+
var option = this,
|
90 |
+
active = option.selected ? ' class="active"':'';
|
91 |
+
self.$dropDown.append('<li'+active+'>'+option.title+'</li>');
|
92 |
+
});
|
93 |
+
self.$items = self.$dropDown.find('li');
|
94 |
+
self.maxHeight = 0;
|
95 |
+
if(self.cutOff && self.$items.length > self.cutOff)self.$container.addClass('scrollable');
|
96 |
+
for(i = 0; i < self.$items.length; i++){
|
97 |
+
var $item = self.$items.eq(i);
|
98 |
+
self.maxHeight += $item.outerHeight();
|
99 |
+
if(self.cutOff == i+1){
|
100 |
+
break;
|
101 |
+
};
|
102 |
+
};
|
103 |
+
|
104 |
+
if(self.isTouch && self.nativeTouch){
|
105 |
+
self.bindTouchHandlers();
|
106 |
+
} else {
|
107 |
+
self.bindHandlers();
|
108 |
+
};
|
109 |
+
},
|
110 |
+
|
111 |
+
bindTouchHandlers: function(){
|
112 |
+
var self = this;
|
113 |
+
self.$container.on('click.easyDropDown',function(){
|
114 |
+
self.$select.focus();
|
115 |
+
});
|
116 |
+
self.$select.on({
|
117 |
+
change: function(){
|
118 |
+
var $selected = $(this).find('option:selected'),
|
119 |
+
title = $selected.text(),
|
120 |
+
value = $selected.val();
|
121 |
+
|
122 |
+
self.$active.text(title);
|
123 |
+
if(typeof self.onChange === 'function'){
|
124 |
+
self.onChange.call(self.$select[0],{
|
125 |
+
title: title,
|
126 |
+
value: value
|
127 |
+
});
|
128 |
+
};
|
129 |
+
},
|
130 |
+
focus: function(){
|
131 |
+
self.$container.addClass('focus');
|
132 |
+
},
|
133 |
+
blur: function(){
|
134 |
+
self.$container.removeClass('focus');
|
135 |
+
}
|
136 |
+
});
|
137 |
+
},
|
138 |
+
|
139 |
+
bindHandlers: function(){
|
140 |
+
var self = this;
|
141 |
+
self.query = '';
|
142 |
+
self.$container.on({
|
143 |
+
'click.easyDropDown': function(){
|
144 |
+
if(!self.down && !self.disabled){
|
145 |
+
self.open();
|
146 |
+
} else {
|
147 |
+
self.close();
|
148 |
+
};
|
149 |
+
},
|
150 |
+
'mousemove.easyDropDown': function(){
|
151 |
+
if(self.keyboardMode){
|
152 |
+
self.keyboardMode = false;
|
153 |
+
};
|
154 |
+
}
|
155 |
+
});
|
156 |
+
|
157 |
+
$('body').on('click.easyDropDown.'+self.id,function(e){
|
158 |
+
var $target = $(e.target),
|
159 |
+
classNames = self.wrapperClass.split(' ').join('.');
|
160 |
+
|
161 |
+
if(!$target.closest('.'+classNames).length && self.down){
|
162 |
+
self.close();
|
163 |
+
};
|
164 |
+
});
|
165 |
+
|
166 |
+
self.$items.on({
|
167 |
+
'click.easyDropDown': function(){
|
168 |
+
var index = $(this).index();
|
169 |
+
self.select(index);
|
170 |
+
self.$select.focus();
|
171 |
+
},
|
172 |
+
'mouseover.easyDropDown': function(){
|
173 |
+
if(!self.keyboardMode){
|
174 |
+
var $t = $(this);
|
175 |
+
$t.addClass('focus').siblings().removeClass('focus');
|
176 |
+
self.focusIndex = $t.index();
|
177 |
+
};
|
178 |
+
},
|
179 |
+
'mouseout.easyDropDown': function(){
|
180 |
+
if(!self.keyboardMode){
|
181 |
+
$(this).removeClass('focus');
|
182 |
+
};
|
183 |
+
}
|
184 |
+
});
|
185 |
+
|
186 |
+
self.$select.on({
|
187 |
+
'focus.easyDropDown': function(){
|
188 |
+
self.$container.addClass('focus');
|
189 |
+
self.inFocus = true;
|
190 |
+
},
|
191 |
+
'blur.easyDropDown': function(){
|
192 |
+
self.$container.removeClass('focus');
|
193 |
+
self.inFocus = false;
|
194 |
+
},
|
195 |
+
'keydown.easyDropDown': function(e){
|
196 |
+
if(self.inFocus){
|
197 |
+
self.keyboardMode = true;
|
198 |
+
var key = e.keyCode;
|
199 |
+
|
200 |
+
if(key == 38 || key == 40 || key == 32){
|
201 |
+
e.preventDefault();
|
202 |
+
if(key == 38){
|
203 |
+
self.focusIndex--
|
204 |
+
self.focusIndex = self.focusIndex < 0 ? self.$items.length - 1 : self.focusIndex;
|
205 |
+
} else if(key == 40){
|
206 |
+
self.focusIndex++
|
207 |
+
self.focusIndex = self.focusIndex > self.$items.length - 1 ? 0 : self.focusIndex;
|
208 |
+
};
|
209 |
+
if(!self.down){
|
210 |
+
self.open();
|
211 |
+
};
|
212 |
+
self.$items.removeClass('focus').eq(self.focusIndex).addClass('focus');
|
213 |
+
if(self.cutOff){
|
214 |
+
self.scrollToView();
|
215 |
+
};
|
216 |
+
self.query = '';
|
217 |
+
};
|
218 |
+
if(self.down){
|
219 |
+
if(key == 9 || key == 27){
|
220 |
+
self.close();
|
221 |
+
} else if(key == 13){
|
222 |
+
e.preventDefault();
|
223 |
+
self.select(self.focusIndex);
|
224 |
+
self.close();
|
225 |
+
return false;
|
226 |
+
} else if(key == 8){
|
227 |
+
e.preventDefault();
|
228 |
+
self.query = self.query.slice(0,-1);
|
229 |
+
self.search();
|
230 |
+
clearTimeout(self.resetQuery);
|
231 |
+
return false;
|
232 |
+
} else if(key != 38 && key != 40){
|
233 |
+
var letter = String.fromCharCode(key);
|
234 |
+
self.query += letter;
|
235 |
+
self.search();
|
236 |
+
clearTimeout(self.resetQuery);
|
237 |
+
};
|
238 |
+
};
|
239 |
+
};
|
240 |
+
},
|
241 |
+
'keyup.easyDropDown': function(){
|
242 |
+
self.resetQuery = setTimeout(function(){
|
243 |
+
self.query = '';
|
244 |
+
},1200);
|
245 |
+
}
|
246 |
+
});
|
247 |
+
|
248 |
+
self.$dropDown.on('scroll.easyDropDown',function(e){
|
249 |
+
if(self.$dropDown[0].scrollTop >= self.$dropDown[0].scrollHeight - self.maxHeight){
|
250 |
+
self.$container.addClass('bottom');
|
251 |
+
} else {
|
252 |
+
self.$container.removeClass('bottom');
|
253 |
+
};
|
254 |
+
});
|
255 |
+
|
256 |
+
if(self.$form.length){
|
257 |
+
self.$form.on('reset.easyDropDown', function(){
|
258 |
+
var active = self.hasLabel ? self.label : self.options[0].title;
|
259 |
+
self.$active.text(active);
|
260 |
+
});
|
261 |
+
};
|
262 |
+
},
|
263 |
+
|
264 |
+
unbindHandlers: function(){
|
265 |
+
var self = this;
|
266 |
+
|
267 |
+
self.$container
|
268 |
+
.add(self.$select)
|
269 |
+
.add(self.$items)
|
270 |
+
.add(self.$form)
|
271 |
+
.add(self.$dropDown)
|
272 |
+
.off('.easyDropDown');
|
273 |
+
$('body').off('.'+self.id);
|
274 |
+
},
|
275 |
+
|
276 |
+
open: function(){
|
277 |
+
var self = this,
|
278 |
+
scrollTop = window.scrollY || document.documentElement.scrollTop,
|
279 |
+
scrollLeft = window.scrollX || document.documentElement.scrollLeft,
|
280 |
+
scrollOffset = self.notInViewport(scrollTop);
|
281 |
+
|
282 |
+
self.closeAll();
|
283 |
+
self.$select.focus();
|
284 |
+
window.scrollTo(scrollLeft, scrollTop+scrollOffset);
|
285 |
+
self.$container.addClass('open');
|
286 |
+
self.$scrollWrapper.css('height',self.maxHeight+'px');
|
287 |
+
self.down = true;
|
288 |
+
},
|
289 |
+
|
290 |
+
close: function(){
|
291 |
+
var self = this;
|
292 |
+
self.$container.removeClass('open');
|
293 |
+
self.$scrollWrapper.css('height','0px');
|
294 |
+
self.focusIndex = self.selected.index;
|
295 |
+
self.query = '';
|
296 |
+
self.down = false;
|
297 |
+
},
|
298 |
+
|
299 |
+
closeAll: function(){
|
300 |
+
var self = this,
|
301 |
+
instances = Object.getPrototypeOf(self).instances;
|
302 |
+
for(var key in instances){
|
303 |
+
var instance = instances[key];
|
304 |
+
instance.close();
|
305 |
+
};
|
306 |
+
},
|
307 |
+
|
308 |
+
select: function(index){
|
309 |
+
var self = this;
|
310 |
+
|
311 |
+
if(typeof index === 'string'){
|
312 |
+
index = self.$select.find('option[value='+index+']').index() - 1;
|
313 |
+
};
|
314 |
+
|
315 |
+
var option = self.options[index],
|
316 |
+
selectIndex = self.hasLabel ? index + 1 : index;
|
317 |
+
self.$items.removeClass('active').eq(index).addClass('active');
|
318 |
+
self.$active.text(option.title);
|
319 |
+
self.$select
|
320 |
+
.find('option')
|
321 |
+
.removeAttr('selected')
|
322 |
+
.eq(selectIndex)
|
323 |
+
.prop('selected',true)
|
324 |
+
.parent()
|
325 |
+
.trigger('change');
|
326 |
+
|
327 |
+
self.selected = {
|
328 |
+
index: index,
|
329 |
+
title: option.title
|
330 |
+
};
|
331 |
+
self.focusIndex = i;
|
332 |
+
if(typeof self.onChange === 'function'){
|
333 |
+
self.onChange.call(self.$select[0],{
|
334 |
+
title: option.title,
|
335 |
+
value: option.value
|
336 |
+
});
|
337 |
+
};
|
338 |
+
},
|
339 |
+
|
340 |
+
search: function(){
|
341 |
+
var self = this,
|
342 |
+
lock = function(i){
|
343 |
+
self.focusIndex = i;
|
344 |
+
self.$items.removeClass('focus').eq(self.focusIndex).addClass('focus');
|
345 |
+
self.scrollToView();
|
346 |
+
},
|
347 |
+
getTitle = function(i){
|
348 |
+
return self.options[i].title.toUpperCase();
|
349 |
+
};
|
350 |
+
|
351 |
+
for(i = 0; i < self.options.length; i++){
|
352 |
+
var title = getTitle(i);
|
353 |
+
if(title.indexOf(self.query) == 0){
|
354 |
+
lock(i);
|
355 |
+
return;
|
356 |
+
};
|
357 |
+
};
|
358 |
+
|
359 |
+
for(i = 0; i < self.options.length; i++){
|
360 |
+
var title = getTitle(i);
|
361 |
+
if(title.indexOf(self.query) > -1){
|
362 |
+
lock(i);
|
363 |
+
break;
|
364 |
+
};
|
365 |
+
};
|
366 |
+
},
|
367 |
+
|
368 |
+
scrollToView: function(){
|
369 |
+
var self = this;
|
370 |
+
if(self.focusIndex >= self.cutOff){
|
371 |
+
var $focusItem = self.$items.eq(self.focusIndex),
|
372 |
+
scroll = ($focusItem.outerHeight() * (self.focusIndex + 1)) - self.maxHeight;
|
373 |
+
|
374 |
+
self.$dropDown.scrollTop(scroll);
|
375 |
+
};
|
376 |
+
},
|
377 |
+
|
378 |
+
notInViewport: function(scrollTop){
|
379 |
+
var self = this,
|
380 |
+
range = {
|
381 |
+
min: scrollTop,
|
382 |
+
max: scrollTop + (window.innerHeight || document.documentElement.clientHeight)
|
383 |
+
},
|
384 |
+
menuBottom = self.$dropDown.offset().top + self.maxHeight;
|
385 |
+
|
386 |
+
if(menuBottom >= range.min && menuBottom <= range.max){
|
387 |
+
return 0;
|
388 |
+
} else {
|
389 |
+
return (menuBottom - range.max) + 5;
|
390 |
+
};
|
391 |
+
},
|
392 |
+
|
393 |
+
destroy: function(){
|
394 |
+
var self = this;
|
395 |
+
self.unbindHandlers();
|
396 |
+
self.$select.unwrap().siblings().remove();
|
397 |
+
self.$select.unwrap();
|
398 |
+
delete Object.getPrototypeOf(self).instances[self.$select[0].id];
|
399 |
+
},
|
400 |
+
|
401 |
+
disable: function(){
|
402 |
+
var self = this;
|
403 |
+
self.disabled = true;
|
404 |
+
self.$container.addClass('disabled');
|
405 |
+
self.$select.attr('disabled',true);
|
406 |
+
if(!self.down)self.close();
|
407 |
+
},
|
408 |
+
|
409 |
+
enable: function(){
|
410 |
+
var self = this;
|
411 |
+
self.disabled = false;
|
412 |
+
self.$container.removeClass('disabled');
|
413 |
+
self.$select.attr('disabled',false);
|
414 |
+
}
|
415 |
+
};
|
416 |
+
|
417 |
+
var instantiate = function(domNode, settings){
|
418 |
+
domNode.id = !domNode.id ? 'EasyDropDown'+rand() : domNode.id;
|
419 |
+
var instance = new EasyDropDown();
|
420 |
+
if(!instance.instances[domNode.id]){
|
421 |
+
instance.instances[domNode.id] = instance;
|
422 |
+
instance.init(domNode, settings);
|
423 |
+
};
|
424 |
+
},
|
425 |
+
rand = function(){
|
426 |
+
return ('00000'+(Math.random()*16777216<<0).toString(16)).substr(-6).toUpperCase();
|
427 |
+
};
|
428 |
+
|
429 |
+
$.fn.easyDropDown = function(){
|
430 |
+
var args = arguments,
|
431 |
+
dataReturn = [],
|
432 |
+
eachReturn;
|
433 |
+
|
434 |
+
eachReturn = this.each(function(){
|
435 |
+
if(args && typeof args[0] === 'string'){
|
436 |
+
var data = EasyDropDown.prototype.instances[this.id][args[0]](args[1], args[2]);
|
437 |
+
if(data)dataReturn.push(data);
|
438 |
+
} else {
|
439 |
+
instantiate(this, args[0]);
|
440 |
+
};
|
441 |
+
});
|
442 |
+
|
443 |
+
if(dataReturn.length){
|
444 |
+
return dataReturn.length > 1 ? dataReturn : dataReturn[0];
|
445 |
+
} else {
|
446 |
+
return eachReturn;
|
447 |
+
};
|
448 |
+
};
|
449 |
+
|
450 |
+
$(function(){
|
451 |
+
if(typeof Object.getPrototypeOf !== 'function'){
|
452 |
+
if(typeof 'test'.__proto__ === 'object'){
|
453 |
+
Object.getPrototypeOf = function(object){
|
454 |
+
return object.__proto__;
|
455 |
+
};
|
456 |
+
} else {
|
457 |
+
Object.getPrototypeOf = function(object){
|
458 |
+
return object.constructor.prototype;
|
459 |
+
};
|
460 |
+
};
|
461 |
+
};
|
462 |
+
|
463 |
+
$('select.dropdown').each(function(){
|
464 |
+
var json = $(this).attr('data-settings');
|
465 |
+
settings = json ? $.parseJSON(json) : {};
|
466 |
+
instantiate(this, settings);
|
467 |
+
});
|
468 |
+
});
|
469 |
+
})(jQuery);
|
js/jquery.easydropdown.min.js
ADDED
@@ -0,0 +1,24 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* EASYDROPDOWN - A Drop-down Builder for Styleable Inputs and Menus
|
3 |
+
* Version: 2.1.3
|
4 |
+
* License: Creative Commons Attribution 3.0 Unported - CC BY 3.0
|
5 |
+
* http://creativecommons.org/licenses/by/3.0/
|
6 |
+
* This software may be used freely on commercial and non-commercial projects with attribution to the author/copyright holder.
|
7 |
+
* Author: Patrick Kunka
|
8 |
+
* Copyright 2013 Patrick Kunka, All Rights Reserved
|
9 |
+
*/
|
10 |
+
|
11 |
+
(function(d){function e(){this.isField=!0;this.keyboardMode=this.hasLabel=this.cutOff=this.disabled=this.inFocus=this.down=!1;this.nativeTouch=!0;this.wrapperClass="dropdown";this.onChange=null}e.prototype={constructor:e,instances:[],init:function(a,c){var b=this;d.extend(b,c);b.$select=d(a);b.id=a.id;b.options=[];b.$options=b.$select.find("option");b.isTouch="ontouchend"in document;b.$select.removeClass(b.wrapperClass+" dropdown");b.$select.is(":disabled")&&(b.disabled=!0);b.$options.length&&(b.$options.each(function(a){var c=
|
12 |
+
d(this);c.is(":selected")&&(b.selected={index:a,title:c.text()},b.focusIndex=a);c.hasClass("label")&&0==a?(b.hasLabel=!0,b.label=c.text(),c.attr("value","")):b.options.push({domNode:c[0],title:c.text(),value:c.val(),selected:c.is(":selected")})}),b.selected||(b.selected={index:0,title:b.$options.eq(0).text()},b.focusIndex=0),b.render())},render:function(){var a=this;a.$container=a.$select.wrap('<div class="'+a.wrapperClass+(a.isTouch&&a.nativeTouch?" touch":"")+(a.disabled?" disabled":"")+'"><span class="old"/></div>').parent().parent();
|
13 |
+
a.$active=d('<span class="selected">'+a.selected.title+"</span>").appendTo(a.$container);a.$carat=d('<span class="carat"/>').appendTo(a.$container);a.$scrollWrapper=d("<div><ul/></div>").appendTo(a.$container);a.$dropDown=a.$scrollWrapper.find("ul");a.$form=a.$container.closest("form");d.each(a.options,function(){a.$dropDown.append("<li"+(this.selected?' class="active"':"")+">"+this.title+"</li>")});a.$items=a.$dropDown.find("li");a.maxHeight=0;a.cutOff&&a.$items.length>a.cutOff&&a.$container.addClass("scrollable");
|
14 |
+
for(i=0;i<a.$items.length;i++){var c=a.$items.eq(i);a.maxHeight+=c.outerHeight();if(a.cutOff==i+1)break}a.isTouch&&a.nativeTouch?a.bindTouchHandlers():a.bindHandlers()},bindTouchHandlers:function(){var a=this;a.$container.on("click.easyDropDown",function(){a.$select.focus()});a.$select.on({change:function(){var c=d(this).find("option:selected"),b=c.text(),c=c.val();a.$active.text(b);"function"===typeof a.onChange&&a.onChange.call(a.$select[0],{title:b,value:c})},focus:function(){a.$container.addClass("focus")},
|
15 |
+
blur:function(){a.$container.removeClass("focus")}})},bindHandlers:function(){var a=this;a.query="";a.$container.on({"click.easyDropDown":function(){a.down||a.disabled?a.close():a.open()},"mousemove.easyDropDown":function(){a.keyboardMode&&(a.keyboardMode=!1)}});d("body").on("click.easyDropDown."+a.id,function(c){c=d(c.target);var b=a.wrapperClass.split(" ").join(".");!c.closest("."+b).length&&a.down&&a.close()});a.$items.on({"click.easyDropDown":function(){var c=d(this).index();a.select(c);a.$select.focus()},
|
16 |
+
"mouseover.easyDropDown":function(){if(!a.keyboardMode){var c=d(this);c.addClass("focus").siblings().removeClass("focus");a.focusIndex=c.index()}},"mouseout.easyDropDown":function(){a.keyboardMode||d(this).removeClass("focus")}});a.$select.on({"focus.easyDropDown":function(){a.$container.addClass("focus");a.inFocus=!0},"blur.easyDropDown":function(){a.$container.removeClass("focus");a.inFocus=!1},"keydown.easyDropDown":function(c){if(a.inFocus){a.keyboardMode=!0;var b=c.keyCode;if(38==b||40==b||32==
|
17 |
+
b)c.preventDefault(),38==b?(a.focusIndex--,a.focusIndex=0>a.focusIndex?a.$items.length-1:a.focusIndex):40==b&&(a.focusIndex++,a.focusIndex=a.focusIndex>a.$items.length-1?0:a.focusIndex),a.down||a.open(),a.$items.removeClass("focus").eq(a.focusIndex).addClass("focus"),a.cutOff&&a.scrollToView(),a.query="";if(a.down)if(9==b||27==b)a.close();else{if(13==b)return c.preventDefault(),a.select(a.focusIndex),a.close(),!1;if(8==b)return c.preventDefault(),a.query=a.query.slice(0,-1),a.search(),clearTimeout(a.resetQuery),
|
18 |
+
!1;38!=b&&40!=b&&(c=String.fromCharCode(b),a.query+=c,a.search(),clearTimeout(a.resetQuery))}}},"keyup.easyDropDown":function(){a.resetQuery=setTimeout(function(){a.query=""},1200)}});a.$dropDown.on("scroll.easyDropDown",function(c){a.$dropDown[0].scrollTop>=a.$dropDown[0].scrollHeight-a.maxHeight?a.$container.addClass("bottom"):a.$container.removeClass("bottom")});if(a.$form.length)a.$form.on("reset.easyDropDown",function(){a.$active.text(a.hasLabel?a.label:a.options[0].title)})},unbindHandlers:function(){this.$container.add(this.$select).add(this.$items).add(this.$form).add(this.$dropDown).off(".easyDropDown");
|
19 |
+
d("body").off("."+this.id)},open:function(){var a=window.scrollY||document.documentElement.scrollTop,c=window.scrollX||document.documentElement.scrollLeft,b=this.notInViewport(a);this.closeAll();this.$select.focus();window.scrollTo(c,a+b);this.$container.addClass("open");this.$scrollWrapper.css("height",this.maxHeight+"px");this.down=!0},close:function(){this.$container.removeClass("open");this.$scrollWrapper.css("height","0px");this.focusIndex=this.selected.index;this.query="";this.down=!1},closeAll:function(){var a=
|
20 |
+
Object.getPrototypeOf(this).instances,c;for(c in a)a[c].close()},select:function(a){"string"===typeof a&&(a=this.$select.find("option[value="+a+"]").index()-1);var c=this.options[a],b=this.hasLabel?a+1:a;this.$items.removeClass("active").eq(a).addClass("active");this.$active.text(c.title);this.$select.find("option").removeAttr("selected").eq(b).prop("selected",!0).parent().trigger("change");this.selected={index:a,title:c.title};this.focusIndex=i;"function"===typeof this.onChange&&this.onChange.call(this.$select[0],
|
21 |
+
{title:c.title,value:c.value})},search:function(){var a=this,c=function(b){a.focusIndex=b;a.$items.removeClass("focus").eq(a.focusIndex).addClass("focus");a.scrollToView()};for(i=0;i<a.options.length;i++){var b=a.options[i].title.toUpperCase();if(0==b.indexOf(a.query)){c(i);return}}for(i=0;i<a.options.length;i++)if(b=a.options[i].title.toUpperCase(),-1<b.indexOf(a.query)){c(i);break}},scrollToView:function(){if(this.focusIndex>=this.cutOff){var a=this.$items.eq(this.focusIndex).outerHeight()*(this.focusIndex+
|
22 |
+
1)-this.maxHeight;this.$dropDown.scrollTop(a)}},notInViewport:function(a){var c=a+(window.innerHeight||document.documentElement.clientHeight),b=this.$dropDown.offset().top+this.maxHeight;return b>=a&&b<=c?0:b-c+5},destroy:function(){this.unbindHandlers();this.$select.unwrap().siblings().remove();this.$select.unwrap();delete Object.getPrototypeOf(this).instances[this.$select[0].id]},disable:function(){this.disabled=!0;this.$container.addClass("disabled");this.$select.attr("disabled",!0);this.down||
|
23 |
+
this.close()},enable:function(){this.disabled=!1;this.$container.removeClass("disabled");this.$select.attr("disabled",!1)}};var f=function(a,c){a.id=a.id?a.id:"EasyDropDown"+("00000"+(16777216*Math.random()<<0).toString(16)).substr(-6).toUpperCase();var b=new e;b.instances[a.id]||(b.instances[a.id]=b,b.init(a,c))};d.fn.easyDropDown=function(){var a=arguments,c=[],b;b=this.each(function(){if(a&&"string"===typeof a[0]){var b=e.prototype.instances[this.id][a[0]](a[1],a[2]);b&&c.push(b)}else f(this,a[0])});
|
24 |
+
return c.length?1<c.length?c:c[0]:b};d(function(){"function"!==typeof Object.getPrototypeOf&&(Object.getPrototypeOf="object"===typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});d("select.dropdown").each(function(){var a=d(this).attr("data-settings");settings=a?d.parseJSON(a):{};f(this,settings)})})})(jQuery);
|
js/wpsl-gmap.js
ADDED
@@ -0,0 +1,555 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
jQuery( document ).ready( function( $ ) {
|
2 |
+
var geocoder, map, infowindow, directionsDisplay, directionsService,
|
3 |
+
markersArray = [],
|
4 |
+
$selects = $( "select" );
|
5 |
+
|
6 |
+
/* Load Google Maps */
|
7 |
+
function initializeGmap() {
|
8 |
+
var myOptions, zoomControlPosition, zoomControlStyle,
|
9 |
+
latLng, zoomTo, zoomLevel, mapType,
|
10 |
+
streetViewVisible = ( wpslSettings.streetView == 1 ) ? true : false;
|
11 |
+
|
12 |
+
/* If no zoom location is defined, we show the entire world */
|
13 |
+
if ( wpslSettings.zoomLatlng !== '' ) {
|
14 |
+
latLng = wpslSettings.zoomLatlng.split( ',' );
|
15 |
+
zoomTo = new google.maps.LatLng( latLng[0], latLng[1] );
|
16 |
+
zoomLevel = parseInt( wpslSettings.zoomLevel );
|
17 |
+
} else {
|
18 |
+
zoomTo = new google.maps.LatLng( 0,0 );
|
19 |
+
zoomLevel = 1;
|
20 |
+
}
|
21 |
+
|
22 |
+
geocoder = new google.maps.Geocoder();
|
23 |
+
infowindow = new google.maps.InfoWindow({
|
24 |
+
pixelOffset: new google.maps.Size( -12,0 ) //make the offset equal to the marker anchor, line 387
|
25 |
+
});
|
26 |
+
directionsDisplay = new google.maps.DirectionsRenderer();
|
27 |
+
directionsService = new google.maps.DirectionsService();
|
28 |
+
|
29 |
+
/* Set correct the position of the controls */
|
30 |
+
if ( wpslSettings.controlPosition == "right" ) {
|
31 |
+
zoomControlPosition = google.maps.ControlPosition.RIGHT_TOP
|
32 |
+
} else {
|
33 |
+
zoomControlPosition = google.maps.ControlPosition.LEFT_TOP
|
34 |
+
}
|
35 |
+
|
36 |
+
/* Set correct control style */
|
37 |
+
if ( wpslSettings.controlStyle == "small" ) {
|
38 |
+
zoomControlStyle = google.maps.ZoomControlStyle.SMALL
|
39 |
+
} else {
|
40 |
+
zoomControlStyle = google.maps.ZoomControlStyle.LARGE
|
41 |
+
}
|
42 |
+
|
43 |
+
/* Set the selected map type */
|
44 |
+
switch ( wpslSettings.mapType ) {
|
45 |
+
case "roadmap":
|
46 |
+
mapType = google.maps.MapTypeId.ROADMAP
|
47 |
+
break;
|
48 |
+
case "satellite":
|
49 |
+
mapType = google.maps.MapTypeId.SATELLITE
|
50 |
+
break;
|
51 |
+
case "hybrid":
|
52 |
+
mapType = google.maps.MapTypeId.HYBRID
|
53 |
+
break;
|
54 |
+
case "terrain":
|
55 |
+
mapType = google.maps.MapTypeId.TERRAIN
|
56 |
+
break;
|
57 |
+
default:
|
58 |
+
mapType = google.maps.MapTypeId.ROADMAP
|
59 |
+
}
|
60 |
+
|
61 |
+
myOptions = {
|
62 |
+
zoom: zoomLevel,
|
63 |
+
center: zoomTo,
|
64 |
+
mapTypeId: mapType,
|
65 |
+
panControl: false,
|
66 |
+
streetViewControl: streetViewVisible,
|
67 |
+
zoomControlOptions: {
|
68 |
+
style: zoomControlStyle,
|
69 |
+
position: zoomControlPosition
|
70 |
+
}
|
71 |
+
};
|
72 |
+
|
73 |
+
map = new google.maps.Map( document.getElementById( "wpsl-gmap" ), myOptions );
|
74 |
+
|
75 |
+
/* Check if we need to try and autolocate the user */
|
76 |
+
if ( wpslSettings.autoLocate == 1 ) {
|
77 |
+
checkGeolocation();
|
78 |
+
}
|
79 |
+
|
80 |
+
/* Style the dropdown menu */
|
81 |
+
$selects.easyDropDown({
|
82 |
+
cutOff: 10,
|
83 |
+
wrapperClass: "wpsl-dropdown"
|
84 |
+
});
|
85 |
+
}
|
86 |
+
|
87 |
+
/* Check if Geolocation is supported */
|
88 |
+
function checkGeolocation() {
|
89 |
+
if ( navigator.geolocation ) {
|
90 |
+
navigator.geolocation.getCurrentPosition( handleGeolocationQuery );
|
91 |
+
}
|
92 |
+
};
|
93 |
+
|
94 |
+
function handleGeolocationQuery( position ) {
|
95 |
+
var storeId = 0,
|
96 |
+
storeName = "",
|
97 |
+
draggable = true,
|
98 |
+
latLng = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
|
99 |
+
|
100 |
+
reverseGeocode( latLng ); //set the zipcode that belongs to the latlng in the input field
|
101 |
+
map.setCenter( latLng );
|
102 |
+
addMarker( latLng, storeId, storeName, draggable );
|
103 |
+
findStoreLocations( latLng );
|
104 |
+
};
|
105 |
+
|
106 |
+
/* Handle clicks on the search button */
|
107 |
+
$( "#wpsl-search-btn" ).on( "click", function() {
|
108 |
+
$( "#wpsl-result-list ul" ).empty();
|
109 |
+
$( "#wpsl-stores" ).show();
|
110 |
+
$( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
|
111 |
+
$( "#wpsl-direction-details" ).hide();
|
112 |
+
|
113 |
+
deleteOverlays();
|
114 |
+
codeAddress();
|
115 |
+
});
|
116 |
+
|
117 |
+
/* Handle the click on the back button when the route directions are displayed */
|
118 |
+
$( "#wpsl-result-list" ).on( "click", ".wpsl-back", function() {
|
119 |
+
var i, len;
|
120 |
+
|
121 |
+
/* Remove the directions from the map */
|
122 |
+
directionsDisplay.setMap( null );
|
123 |
+
|
124 |
+
/* Restore all markers on the map */
|
125 |
+
for ( i = 0, len = markersArray.length; i < len; i++ ) {
|
126 |
+
markersArray[i].setMap( map );
|
127 |
+
}
|
128 |
+
|
129 |
+
fitBounds();
|
130 |
+
|
131 |
+
/* After the markers are restored, the direction link has lost it's click handler. So we reinstate it. */
|
132 |
+
$( ".wpsl-info-window" ).on( "click", ".wpsl-directions", function() {
|
133 |
+
renderDirections( $(this) );
|
134 |
+
return false;
|
135 |
+
});
|
136 |
+
|
137 |
+
$( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
|
138 |
+
$( "#wpsl-stores" ).show();
|
139 |
+
$( "#wpsl-direction-details" ).hide();
|
140 |
+
|
141 |
+
return false;
|
142 |
+
});
|
143 |
+
|
144 |
+
function renderDirections( e ) {
|
145 |
+
var i, start, end, len, storeId;
|
146 |
+
|
147 |
+
/*
|
148 |
+
The storeId is placed on the li in the results list,
|
149 |
+
but in the marker it will be on the wrapper div. So we check which one we need to target
|
150 |
+
*/
|
151 |
+
if ( e.parent( "li" ).length > 0 ) {
|
152 |
+
storeId = e.parent( "li" ).data( "store-id" );
|
153 |
+
} else {
|
154 |
+
storeId = e.parent( ".wpsl-info-window" ).data( "store-id" );
|
155 |
+
}
|
156 |
+
|
157 |
+
/* Find the latlng that belongs to the start and end point */
|
158 |
+
for ( i = 0, len = markersArray.length; i < len; i++ ) {
|
159 |
+
if ( markersArray[i].storeId == 0 ) {
|
160 |
+
start = markersArray[i].getPosition();
|
161 |
+
} else if ( markersArray[i].storeId == storeId ) {
|
162 |
+
end = markersArray[i].getPosition();
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
if ( start && end ) {
|
167 |
+
$( "#wpsl-direction-details ul" ).empty();
|
168 |
+
$( ".wpsl-direction-before, .wpsl-direction-after" ).remove();
|
169 |
+
calcRoute( start, end );
|
170 |
+
} else {
|
171 |
+
alert( wpslLabels.generalError );
|
172 |
+
}
|
173 |
+
}
|
174 |
+
|
175 |
+
/* Check if we need to enable the bouncing of markers when the user hovers over the result list */
|
176 |
+
if ( wpslSettings.markerBounce == 1 ) {
|
177 |
+
$( "#wpsl-stores" ).on( "mouseenter", "li", function() {
|
178 |
+
letsBounce( $(this).data( "store-id" ), "start" );
|
179 |
+
});
|
180 |
+
|
181 |
+
$( "#wpsl-stores" ).on( "mouseleave", "li", function() {
|
182 |
+
letsBounce( $(this).data( "store-id" ), "stop" );
|
183 |
+
});
|
184 |
+
}
|
185 |
+
|
186 |
+
/* Let a single marker bounce */
|
187 |
+
function letsBounce( storeId, status ) {
|
188 |
+
var storeId, status, i, len, animation = '';
|
189 |
+
|
190 |
+
if ( status == "start" ) {
|
191 |
+
animation = google.maps.Animation.BOUNCE
|
192 |
+
} else {
|
193 |
+
animation = null;
|
194 |
+
}
|
195 |
+
|
196 |
+
/* Find the correct marker to bounce based on the storeId */
|
197 |
+
for ( i = 0, len = markersArray.length; i < len; i++ ) {
|
198 |
+
if ( markersArray[i].storeId == storeId ) {
|
199 |
+
marker = markersArray[i];
|
200 |
+
marker.setAnimation( animation );
|
201 |
+
}
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
/* Show the directions on the map */
|
206 |
+
function calcRoute( start, end ) {
|
207 |
+
var legs, len, step, index, direction, i, j,
|
208 |
+
directionStops = "",
|
209 |
+
request = {
|
210 |
+
origin: start,
|
211 |
+
destination: end,
|
212 |
+
travelMode: google.maps.DirectionsTravelMode.DRIVING
|
213 |
+
};
|
214 |
+
|
215 |
+
directionsService.route( request, function( response, status ) {
|
216 |
+
if ( status == google.maps.DirectionsStatus.OK ) {
|
217 |
+
directionsDisplay.setMap( map );
|
218 |
+
directionsDisplay.setDirections( response );
|
219 |
+
|
220 |
+
if ( response.routes.length > 0 ) {
|
221 |
+
direction = response.routes[0];
|
222 |
+
|
223 |
+
/* Loop over the legs and steps of the directions */
|
224 |
+
for ( i = 0; i < direction.legs.length; i++ ) {
|
225 |
+
legs = direction.legs[i];
|
226 |
+
|
227 |
+
for ( j = 0, len = legs.steps.length; j < len; j++ ) {
|
228 |
+
step = legs.steps[j];
|
229 |
+
index = j+1;
|
230 |
+
directionStops = directionStops + "<li><div class='wpsl-direction-index'>" + index + "</div><div class='wpsl-direction-txt'>" + step.instructions + "</div><div class='wpsl-direction-distance'>" + step.distance.text + "</div></li>";
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
$( "#wpsl-direction-details ul" ).append( directionStops ).before( "<p class='wpsl-direction-before'><a class='wpsl-back' href='#'>Back</a>" + direction.legs[0].distance.text + " - " + direction.legs[0].duration.text + "</p>" ).after( "<p class='wpsl-direction-after'>" + response.routes[0].copyrights + "</p>" );
|
235 |
+
$( "#wpsl-direction-details" ).show();
|
236 |
+
|
237 |
+
/* Remove all other markers from the map */
|
238 |
+
for ( i = 0, len = markersArray.length; i < len; i++ ) {
|
239 |
+
markersArray[i].setMap( null );
|
240 |
+
}
|
241 |
+
|
242 |
+
$( "#wpsl-stores" ).hide();
|
243 |
+
}
|
244 |
+
}
|
245 |
+
});
|
246 |
+
}
|
247 |
+
|
248 |
+
/* Geocode the user input */
|
249 |
+
function codeAddress() {
|
250 |
+
var latLng, storeId, storeName,
|
251 |
+
address = $( "#wpsl-search-input" ).val();
|
252 |
+
|
253 |
+
geocoder.geocode( { 'address': address}, function( response, status ) {
|
254 |
+
if ( status == google.maps.GeocoderStatus.OK ) {
|
255 |
+
latLng = response[0].geometry.location;
|
256 |
+
|
257 |
+
/* Remove any previous markers and add a new one */
|
258 |
+
deleteOverlays();
|
259 |
+
addMarker( latLng, storeId = 0, storeName = "", draggable = true );
|
260 |
+
|
261 |
+
/* Try to find stores that match the radius, location criteria */
|
262 |
+
findStoreLocations( latLng );
|
263 |
+
} else {
|
264 |
+
geocodeNotification( status );
|
265 |
+
}
|
266 |
+
}
|
267 |
+
)};
|
268 |
+
|
269 |
+
/* Geocode the user input and set the returned zipcode in the input field */
|
270 |
+
function reverseGeocode( latLng ) {
|
271 |
+
var latLng, zipCode;
|
272 |
+
|
273 |
+
geocoder.geocode( {'latLng': latLng}, function( response, status ) {
|
274 |
+
if ( status == google.maps.GeocoderStatus.OK ) {
|
275 |
+
zipCode = filterApiResponse( response );
|
276 |
+
|
277 |
+
if ( zipCode !== "" ) {
|
278 |
+
$( "#wpsl-search-input" ).val( zipCode );
|
279 |
+
}
|
280 |
+
} else {
|
281 |
+
geocodeNotification( status );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
)};
|
285 |
+
|
286 |
+
/* Filter out the zipcode from the response */
|
287 |
+
function filterApiResponse( response ) {
|
288 |
+
var zipcode, responseType,
|
289 |
+
addressLength = response[0].address_components.length;
|
290 |
+
|
291 |
+
/* Loop over the API response */
|
292 |
+
for ( i = 0; i < addressLength; i++ ){
|
293 |
+
responseType = response[0].address_components[i].types;
|
294 |
+
|
295 |
+
/* filter out the postcode */
|
296 |
+
if ( ( /^postal_code$/.test( responseType ) ) || ( /^postal_code_prefix,postal_code$/.test( responseType ) ) ) {
|
297 |
+
zipcode = response[0].address_components[i].long_name;
|
298 |
+
}
|
299 |
+
}
|
300 |
+
|
301 |
+
return zipcode;
|
302 |
+
}
|
303 |
+
|
304 |
+
function findStoreLocations( startLatLng ) {
|
305 |
+
var location,
|
306 |
+
center = map.getCenter(),
|
307 |
+
infoWindowData = {},
|
308 |
+
storeData = "",
|
309 |
+
draggable = false,
|
310 |
+
$storeList = $( "#wpsl-stores ul" ),
|
311 |
+
preloader = wpslSettings.path + "img/ajax-loader.gif",
|
312 |
+
ajaxData = {
|
313 |
+
action: "store_search",
|
314 |
+
lat: startLatLng.lat(),
|
315 |
+
lng: startLatLng.lng(),
|
316 |
+
max_results: $( "#wpsl-results select" ).val(),
|
317 |
+
radius: $( "#wpsl-radius select" ).val()
|
318 |
+
};
|
319 |
+
|
320 |
+
/* Add the preloader */
|
321 |
+
$storeList.empty().append( "<li class='wpsl-preloader'><img src='" + preloader + "'/><span>" + wpslLabels.preloader + "</span></li>" );
|
322 |
+
|
323 |
+
$.get( wpslSettings.ajaxurl, ajaxData, function( response ) {
|
324 |
+
|
325 |
+
/* Remove the preloaders and no results msg */
|
326 |
+
$( ".wpsl-preloader, .no-results" ).remove();
|
327 |
+
|
328 |
+
if ( response.success !== false ) {
|
329 |
+
if ( response.length > 0 ) {
|
330 |
+
$.each( response, function( index ) {
|
331 |
+
infoWindowData = {
|
332 |
+
store: response[index].store,
|
333 |
+
street: response[index].street,
|
334 |
+
city: response[index].city,
|
335 |
+
state: response[index].state,
|
336 |
+
zip: response[index].zip,
|
337 |
+
description: response[index].description,
|
338 |
+
phone: response[index].phone,
|
339 |
+
fax: response[index].fax,
|
340 |
+
url: response[index].url,
|
341 |
+
email: response[index].email,
|
342 |
+
hours: response[index].hours,
|
343 |
+
thumb: response[index].thumb
|
344 |
+
};
|
345 |
+
|
346 |
+
location = new google.maps.LatLng( response[index].lat, response[index].lng );
|
347 |
+
addMarker( location, response[index].id, infoWindowData, draggable );
|
348 |
+
storeData = storeData + storeHtml( response[index] );
|
349 |
+
});
|
350 |
+
|
351 |
+
$( "#wpsl-result-list" ).off( "click", ".wpsl-directions" );
|
352 |
+
$storeList.append( storeData );
|
353 |
+
|
354 |
+
$( "#wpsl-result-list" ).on( "click", ".wpsl-directions", function() {
|
355 |
+
renderDirections( $(this) );
|
356 |
+
return false;
|
357 |
+
});
|
358 |
+
|
359 |
+
} else {
|
360 |
+
$storeList.html( "<li class='no-results'>" + wpslLabels.noResults + "</li>" );
|
361 |
+
}
|
362 |
+
|
363 |
+
fitBounds();
|
364 |
+
} else {
|
365 |
+
alert( wpslLabels.generalError );
|
366 |
+
}
|
367 |
+
});
|
368 |
+
}
|
369 |
+
|
370 |
+
/* Add a new marker to the map based on the provided location (latlng) */
|
371 |
+
function addMarker( location, storeId, infoWindowData, draggable ) {
|
372 |
+
var markerPath, mapIcon;
|
373 |
+
|
374 |
+
if ( storeId === 0 ) {
|
375 |
+
markerPath = wpslSettings.path + "img/markers/" + wpslSettings.startMarker;
|
376 |
+
} else {
|
377 |
+
markerPath = wpslSettings.path + "img/markers/" + wpslSettings.storeMarker;
|
378 |
+
}
|
379 |
+
|
380 |
+
var mapIcon = {
|
381 |
+
url: markerPath,
|
382 |
+
size: new google.maps.Size( 48,70 ), //original format
|
383 |
+
scaledSize: new google.maps.Size( 24,35 ), //retina format
|
384 |
+
origin: new google.maps.Point( 0,0 ),
|
385 |
+
anchor: new google.maps.Point( 12,35 )
|
386 |
+
};
|
387 |
+
|
388 |
+
var infoWindowContent,
|
389 |
+
marker = new google.maps.Marker({
|
390 |
+
position: location,
|
391 |
+
map: map,
|
392 |
+
optimized: false, //fixes markers flashing while bouncing
|
393 |
+
title: infoWindowData.store,
|
394 |
+
draggable: draggable,
|
395 |
+
storeId: storeId,
|
396 |
+
icon: mapIcon
|
397 |
+
});
|
398 |
+
|
399 |
+
google.maps.event.addListener( marker, "click", function() {
|
400 |
+
if ( storeId != 0 ) {
|
401 |
+
infoWindowContent = createInfoWindowHtml( infoWindowData, storeId );
|
402 |
+
infowindow.setContent( infoWindowContent );
|
403 |
+
} else {
|
404 |
+
infowindow.setContent( wpslLabels.startPoint ); //setting van maken
|
405 |
+
}
|
406 |
+
infowindow.open( map, marker );
|
407 |
+
|
408 |
+
//pixelOffset: new google.maps.Size(0, 60)
|
409 |
+
|
410 |
+
$( ".wpsl-info-window" ).on( "click", ".wpsl-directions", function() {
|
411 |
+
renderDirections( $(this) );
|
412 |
+
return false;
|
413 |
+
});
|
414 |
+
});
|
415 |
+
|
416 |
+
/* Store the marker for later use */
|
417 |
+
markersArray.push( marker );
|
418 |
+
|
419 |
+
if ( draggable ) {
|
420 |
+
google.maps.event.addListener( marker, "dragend", function( event ) {
|
421 |
+
map.setCenter( event.latLng );
|
422 |
+
reverseGeocode( event.latLng );
|
423 |
+
findStoreLocations( event.latLng );
|
424 |
+
});
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
/* Create the data for the infowindows on Google Maps */
|
429 |
+
function createInfoWindowHtml( infoWindowData, storeId ) {
|
430 |
+
var storeHeader,
|
431 |
+
windowContent = "<div data-store-id='" + storeId + "' class='wpsl-info-window'>";
|
432 |
+
|
433 |
+
/* Check if we need to turn the store name into a link or not */
|
434 |
+
if ( ( typeof( infoWindowData.url ) !== "undefined" ) && ( infoWindowData.url !== "" ) ) {
|
435 |
+
storeHeader = "<a href='" + infoWindowData.url + "'><strong>" + infoWindowData.store + "</strong></a>";
|
436 |
+
} else {
|
437 |
+
storeHeader = "<strong>" + infoWindowData.store + "</strong>";
|
438 |
+
}
|
439 |
+
|
440 |
+
windowContent += "<p>" + storeHeader + "<span>" + infoWindowData.street + "</span><span>" + infoWindowData.city + "</span></p>";
|
441 |
+
|
442 |
+
if ( ( typeof( infoWindowData.description ) !== "undefined" ) && ( infoWindowData.description !== "" ) ) {
|
443 |
+
windowContent += "<p>" + infoWindowData.description + "</p>";
|
444 |
+
}
|
445 |
+
|
446 |
+
/* If no data exist for either the phone / fax / email then just don't show them */
|
447 |
+
if ( ( typeof( infoWindowData.phone ) !== "undefined" ) && ( infoWindowData.phone !== "" ) ) {
|
448 |
+
windowContent += "<span><strong>" + wpslLabels.phone + "</strong>: " + infoWindowData.phone + "</span>";
|
449 |
+
}
|
450 |
+
|
451 |
+
if ( ( typeof( infoWindowData.fax ) !== "undefined" ) && ( infoWindowData.fax !== "" ) ) {
|
452 |
+
windowContent += "<span><strong>" + wpslLabels.fax + "</strong>: " + infoWindowData.fax + "</span>";
|
453 |
+
}
|
454 |
+
|
455 |
+
if ( ( typeof( infoWindowData.email ) !== "undefined" ) && ( infoWindowData.email !== "" ) ) {
|
456 |
+
windowContent += "<span><strong>Email</strong>: " + infoWindowData.email + "</span>";
|
457 |
+
}
|
458 |
+
|
459 |
+
if ( ( typeof( infoWindowData.hours ) !== "undefined" ) && ( infoWindowData.hours !== "" ) ) {
|
460 |
+
windowContent += "<div class='wpsl-store-hours'><strong>" + wpslLabels.hours + "</strong> " + infoWindowData.hours + "</div>";
|
461 |
+
}
|
462 |
+
|
463 |
+
windowContent += "<a class='wpsl-directions' href='#'>" + wpslLabels.directions + "</a>";
|
464 |
+
windowContent += "</div>";
|
465 |
+
|
466 |
+
return windowContent;
|
467 |
+
}
|
468 |
+
|
469 |
+
function storeHtml( response ) {
|
470 |
+
var html, storeImg = "",
|
471 |
+
id = response.id,
|
472 |
+
store = response.store,
|
473 |
+
street = response.street,
|
474 |
+
city = response.city,
|
475 |
+
state = response.state,
|
476 |
+
zip = response.zip,
|
477 |
+
thumb = response.thumb,
|
478 |
+
country = response.country,
|
479 |
+
distance = parseFloat( response.distance ).toFixed(1) + " " + wpslSettings.distanceUnit;
|
480 |
+
|
481 |
+
if ( ( typeof( thumb ) !== "undefined" ) && ( thumb !== "" ) ) {
|
482 |
+
storeImg = "<img class='wpsl-store-thumb' src='" + thumb + "' width='48' height='48' alt='" + store + "' />";
|
483 |
+
}
|
484 |
+
|
485 |
+
html = "<li data-store-id='" + id + "'><div><p>" + storeImg + "<strong>" + store + "</strong><span class='wpsl-street'>" + street + "</span>" + city + " " + state + " " + zip + "<span class='wpsl-country'>" + country + "</p></div>" + distance + "<a class='wpsl-directions' href='#'>" + wpslLabels.directions + "</a></li>";
|
486 |
+
|
487 |
+
return html;
|
488 |
+
}
|
489 |
+
|
490 |
+
/* Zoom the map so that all markers fit in the window */
|
491 |
+
function fitBounds() {
|
492 |
+
var i, markerLen,
|
493 |
+
maxZoom = 12,
|
494 |
+
bounds = new google.maps.LatLngBounds();
|
495 |
+
|
496 |
+
/* Make sure we don't zoom to far */
|
497 |
+
google.maps.event.addListenerOnce( map, "bounds_changed", function( event ) {
|
498 |
+
if ( this.getZoom() > maxZoom ) {
|
499 |
+
this.setZoom( maxZoom );
|
500 |
+
}
|
501 |
+
});
|
502 |
+
|
503 |
+
for ( i = 0, markerLen = markersArray.length; i < markerLen; i++ ) {
|
504 |
+
bounds.extend ( markersArray[i].position );
|
505 |
+
}
|
506 |
+
|
507 |
+
map.fitBounds( bounds );
|
508 |
+
}
|
509 |
+
|
510 |
+
/* Remove all existing markers and route lines from the map */
|
511 |
+
function deleteOverlays() {
|
512 |
+
directionsDisplay.setMap( null );
|
513 |
+
|
514 |
+
/* Remove all the markers from the map, and empty the array */
|
515 |
+
if ( markersArray ) {
|
516 |
+
for ( i = 0, markerLen = markersArray.length; i < markerLen; i++ ) {
|
517 |
+
markersArray[i].setMap( null );
|
518 |
+
}
|
519 |
+
|
520 |
+
markersArray.length = 0;
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
+
/* Handle the geocode errors */
|
525 |
+
function geocodeNotification( status ) {
|
526 |
+
var msg;
|
527 |
+
|
528 |
+
switch ( status ) {
|
529 |
+
case "ZERO_RESULTS":
|
530 |
+
msg = wpslLabels.noResults;
|
531 |
+
break;
|
532 |
+
case "OVER_QUERY_LIMIT":
|
533 |
+
msg = wpslLabels.queryLimit;
|
534 |
+
break;
|
535 |
+
default:
|
536 |
+
msg = wpslLabels.generalError;
|
537 |
+
break;
|
538 |
+
}
|
539 |
+
|
540 |
+
alert( msg );
|
541 |
+
}
|
542 |
+
|
543 |
+
/* Trigger the search when the user presses "enter" on the keyboard */
|
544 |
+
$( "#wpsl-search-input" ).keydown( function ( event ) {
|
545 |
+
var keypressed = event.keyCode || event.which;
|
546 |
+
if ( keypressed == 13 ) {
|
547 |
+
$( "#wpsl-search-btn" ).trigger( "click" );
|
548 |
+
}
|
549 |
+
});
|
550 |
+
|
551 |
+
if ( $("#wpsl-gmap").length ) {
|
552 |
+
google.maps.event.addDomListener( window, "load", initializeGmap );
|
553 |
+
}
|
554 |
+
|
555 |
+
});
|
readme.txt
ADDED
@@ -0,0 +1,59 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
=== WP Store Locator ===
|
2 |
+
Contributors: tijmensmit
|
3 |
+
Tags: google maps, store locator, business locations, geocoding, stores, geo
|
4 |
+
Requires at least: 3.5
|
5 |
+
Tested up to: 3.8
|
6 |
+
Stable tag: 1.0
|
7 |
+
License: GPLv3
|
8 |
+
License URI: http://www.gnu.org/licenses/gpl.html
|
9 |
+
|
10 |
+
An easy to use location management system that enables users to search for nearby physical stores
|
11 |
+
|
12 |
+
== Description ==
|
13 |
+
|
14 |
+
WP Store Locator is a powerful and easy to use location management system.
|
15 |
+
You can customize the appearance of the map and provide custom labels for entry fields.
|
16 |
+
Users can filter the results by radius and see driving directions to the nearby stores in
|
17 |
+
the language that is set in the admin panel.
|
18 |
+
|
19 |
+
= Features include: =
|
20 |
+
|
21 |
+
* Manage an unlimited numbers of stores
|
22 |
+
* Set an unique thumbnail for each store
|
23 |
+
* Provide extra details for stores like the phone, fax, email, url, description and opening hours
|
24 |
+
* You can drag the marker to the exact spot on the 'Add Store' page
|
25 |
+
* Show the driving distances in either km or miles
|
26 |
+
* Choose from nine retina ready marker icons
|
27 |
+
* Show Google Maps in different languages, this also influences the language for the driving directions
|
28 |
+
* Show the driving directions to the stores
|
29 |
+
* Users can filter the returned results by radius or max results
|
30 |
+
* Customize the max results and search radius values that users can select
|
31 |
+
* Customize map settings like the terrain type, location of the map controls and the default zoom level
|
32 |
+
* Auto-locate the location of the user and show nearby stores
|
33 |
+
* Labels can be translated in any language through the settings panel
|
34 |
+
|
35 |
+
== Installation ==
|
36 |
+
|
37 |
+
1. Upload the `wp-store-locator` folder to the `/wp-content/plugins/` directory
|
38 |
+
1. Activate the plugin through the 'Plugins' menu in WordPress
|
39 |
+
1. Add your stores under 'Store Locator' -> Add Store
|
40 |
+
1. Add the map to a page with this shortcode: [wpsl]
|
41 |
+
|
42 |
+
== Frequently Asked Questions ==
|
43 |
+
|
44 |
+
= How do I add the store locator to a page? =
|
45 |
+
|
46 |
+
Add this shortcode [wpsl] to the page where you want to display the store locator.
|
47 |
+
|
48 |
+
== Screenshots ==
|
49 |
+
|
50 |
+
1. Front-end of the plugin
|
51 |
+
2. The driving directions from the user location to the selected store
|
52 |
+
3. The 'Add Store' screen
|
53 |
+
4. The plugin settings
|
54 |
+
5. Overview from the current stores
|
55 |
+
|
56 |
+
== Changelog ==
|
57 |
+
|
58 |
+
= 1.0 =
|
59 |
+
* Initial release
|
screenshot-1.jpg
ADDED
Binary file
|
screenshot-2.jpg
ADDED
Binary file
|
screenshot-3.jpg
ADDED
Binary file
|
screenshot-4.jpg
ADDED
Binary file
|
screenshot-5.jpg
ADDED
Binary file
|
uninstall.php
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) && !defined( 'WP_UNINSTALL_PLUGIN ') ) {
|
3 |
+
exit;
|
4 |
+
}
|
5 |
+
|
6 |
+
function wpsl_uninstall() {
|
7 |
+
|
8 |
+
global $wpdb;
|
9 |
+
|
10 |
+
$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'wpsl_stores' );
|
11 |
+
|
12 |
+
delete_option( 'wpsl_version' );
|
13 |
+
delete_option( 'wpsl_settings' );
|
14 |
+
|
15 |
+
}
|
16 |
+
|
17 |
+
/* Delete the tables and options from the db */
|
18 |
+
wpsl_uninstall();
|
19 |
+
?>
|
wp-store-locator.php
ADDED
@@ -0,0 +1,234 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: WP Store Locator
|
4 |
+
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.0
|
9 |
+
Text Domain: wpsl
|
10 |
+
Domain Path: /languages/
|
11 |
+
License: GPLv3
|
12 |
+
|
13 |
+
WP Store Locator
|
14 |
+
Copyright (C)2013, Tijmen Smit - info@tijmensmit.com
|
15 |
+
|
16 |
+
This program is free software: you can redistribute it and/or modify
|
17 |
+
it under the terms of the GNU General Public License as published by
|
18 |
+
the Free Software Foundation, either version 3 of the License, or
|
19 |
+
(at your option) any later version.
|
20 |
+
|
21 |
+
This program is distributed in the hope that it will be useful,
|
22 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
23 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
24 |
+
GNU General Public License for more details.
|
25 |
+
|
26 |
+
You should have received a copy of the GNU General Public License
|
27 |
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
28 |
+
|
29 |
+
@package WP_Store_locator
|
30 |
+
@category Core
|
31 |
+
@author Tijmen Smit
|
32 |
+
@version 1.0
|
33 |
+
*/
|
34 |
+
|
35 |
+
if ( !class_exists( 'WP_Store_locator' ) ) {
|
36 |
+
|
37 |
+
class WP_Store_locator {
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Stores the current plugin settings
|
41 |
+
* @since 1.0
|
42 |
+
* @var array
|
43 |
+
*/
|
44 |
+
public $settings = array();
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Stores the default plugin settings
|
48 |
+
* @since 1.0
|
49 |
+
* @var array
|
50 |
+
*/
|
51 |
+
public $default_settings = array(
|
52 |
+
'api_key' => '',
|
53 |
+
'api_language' => 'en',
|
54 |
+
'api_region' => '',
|
55 |
+
'distance_unit' => 'km',
|
56 |
+
'max_results' => '(25),50,75,100',
|
57 |
+
'search_radius' => '10,25,(50),100,200,500',
|
58 |
+
'marker_bounce' => '1',
|
59 |
+
'auto_locate' => '1',
|
60 |
+
'zoom_level' => '3',
|
61 |
+
'zoom_name' => '',
|
62 |
+
'zoom_latlng' => '',
|
63 |
+
'height' => '350',
|
64 |
+
'map_type' => 'roadmap',
|
65 |
+
'pan_controls' => '0',
|
66 |
+
'streetview' => '0',
|
67 |
+
'results_dropdown' => '1',
|
68 |
+
'infowindow_width' => '225',
|
69 |
+
'search_width' => '179',
|
70 |
+
'label_width' => '95',
|
71 |
+
'control_position' => 'left',
|
72 |
+
'control_style' => 'small',
|
73 |
+
'start_marker' => 'red.png',
|
74 |
+
'store_marker' => 'blue.png',
|
75 |
+
'start_label' => 'Start location',
|
76 |
+
'search_label' => 'Your location',
|
77 |
+
'search_btn_label' => 'Search',
|
78 |
+
'preloader_label' => 'Searching...',
|
79 |
+
'radius_label' => 'Search radius',
|
80 |
+
'no_results_label' => 'No results found',
|
81 |
+
'results_label' => 'Results',
|
82 |
+
'directions_label' => 'Directions',
|
83 |
+
'error_label' => 'Something went wrong, please try again!',
|
84 |
+
'limit_label' => 'API usage limit reached',
|
85 |
+
'phone_label' => 'Phone',
|
86 |
+
'fax_label' => 'Fax',
|
87 |
+
'hours_label' => 'Hours'
|
88 |
+
);
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Class constructor
|
92 |
+
*/
|
93 |
+
function __construct() {
|
94 |
+
|
95 |
+
$this->define_constants();
|
96 |
+
$this->define_tables();
|
97 |
+
|
98 |
+
if ( is_admin() ) {
|
99 |
+
require_once( WPSL_PLUGIN_DIR . 'admin/class-admin.php' );
|
100 |
+
|
101 |
+
load_plugin_textdomain( 'wpsl', false, basename( dirname( __FILE__ ) ) . '/languages' );
|
102 |
+
|
103 |
+
register_activation_hook( __FILE__, array( $this, 'install' ) );
|
104 |
+
} else {
|
105 |
+
require_once( WPSL_PLUGIN_DIR . 'frontend/class-frontend.php' );
|
106 |
+
}
|
107 |
+
|
108 |
+
//if placed in the if else together with the class-frontend, the ajax hook always fails?
|
109 |
+
require_once( WPSL_PLUGIN_DIR . 'frontend/wpsl-ajax-functions.php' );
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Setup plugin constants
|
114 |
+
*
|
115 |
+
* @since 1.0
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
+
public function define_constants() {
|
119 |
+
|
120 |
+
if ( !defined( 'WPSL_VERSION_NUM' ) )
|
121 |
+
define( 'WPSL_VERSION_NUM', '1.0' );
|
122 |
+
|
123 |
+
if ( !defined( 'WPSL_URL' ) )
|
124 |
+
define( 'WPSL_URL', plugin_dir_url( __FILE__ ) );
|
125 |
+
|
126 |
+
if ( !defined( 'WPSL_BASENAME' ) )
|
127 |
+
define( 'WPSL_BASENAME', plugin_basename( __FILE__ ) );
|
128 |
+
|
129 |
+
if ( ! defined( 'WPSL_PLUGIN_DIR' ) )
|
130 |
+
define( 'WPSL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
131 |
+
}
|
132 |
+
|
133 |
+
private function define_tables() {
|
134 |
+
|
135 |
+
global $wpdb;
|
136 |
+
|
137 |
+
$wpdb->wpsl_stores = $wpdb->prefix . 'wpsl_stores';
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Run the install functions
|
142 |
+
*
|
143 |
+
* @since 1.0
|
144 |
+
* @return void
|
145 |
+
*/
|
146 |
+
public function install() {
|
147 |
+
$this->create_tables();
|
148 |
+
$this->set_default_settings();
|
149 |
+
|
150 |
+
update_option( 'wpsl_version', WPSL_VERSION_NUM );
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Create the required tables
|
155 |
+
*
|
156 |
+
* @since 1.0
|
157 |
+
* @return void
|
158 |
+
*/
|
159 |
+
public function create_tables() {
|
160 |
+
|
161 |
+
global $wpdb;
|
162 |
+
|
163 |
+
$charset_collate = '';
|
164 |
+
|
165 |
+
if ( !empty( $wpdb->charset ) )
|
166 |
+
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
167 |
+
if ( !empty( $wpdb->collate ) )
|
168 |
+
$charset_collate .= " COLLATE $wpdb->collate";
|
169 |
+
|
170 |
+
if ( $wpdb->get_var( "SHOW TABLES LIKE '$wpdb->wpsl_stores'" ) != $wpdb->wpsl_stores ) {
|
171 |
+
$sql = "CREATE TABLE " . $wpdb->wpsl_stores . " (
|
172 |
+
wpsl_id int(10) unsigned NOT NULL auto_increment,
|
173 |
+
store varchar(255) NULL,
|
174 |
+
street varchar(255) NULL,
|
175 |
+
city varchar(255) NULL,
|
176 |
+
state varchar(255) NULL,
|
177 |
+
zip varchar(100) NULL,
|
178 |
+
country varchar(255) NULL,
|
179 |
+
country_iso tinytext NOT NULL,
|
180 |
+
lat float(10,6) NOT NULL,
|
181 |
+
lng float(10,6) NOT NULL,
|
182 |
+
description text NULL,
|
183 |
+
phone varchar(100) NULL,
|
184 |
+
fax varchar(100) NULL,
|
185 |
+
url varchar(255) NULL,
|
186 |
+
email varchar(255) NULL,
|
187 |
+
hours varchar(255) NULL,
|
188 |
+
thumb_id bigint(20) unsigned NOT NULL,
|
189 |
+
active tinyint(1) NULL default 1,
|
190 |
+
PRIMARY KEY (wpsl_id)
|
191 |
+
) $charset_collate;";
|
192 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
193 |
+
dbDelta( $sql );
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Set the default pluging settings
|
199 |
+
*
|
200 |
+
* @since 1.0
|
201 |
+
* @return void
|
202 |
+
*/
|
203 |
+
public function set_default_settings() {
|
204 |
+
|
205 |
+
$settings = get_option( 'wpsl_settings' );
|
206 |
+
|
207 |
+
if ( !$settings ) {
|
208 |
+
update_option( 'wpsl_settings', $this->default_settings );
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Get the current plugin settings
|
214 |
+
*
|
215 |
+
* @since 1.0
|
216 |
+
* @return array $setting The current plugin settings
|
217 |
+
*/
|
218 |
+
public function get_settings() {
|
219 |
+
|
220 |
+
$settings = get_option( 'wpsl_settings' );
|
221 |
+
|
222 |
+
if ( !$settings ) {
|
223 |
+
update_option( 'wpsl_settings', $this->default_settings );
|
224 |
+
$settings = $this->default_settings;
|
225 |
+
}
|
226 |
+
|
227 |
+
return $settings;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
$wpsl = new WP_Store_locator();
|
232 |
+
}
|
233 |
+
|
234 |
+
?>
|