Version Notes
First stable release
Download this release
Release Info
| Developer | IndaBox |
| Extension | indabox |
| Version | 1.0.1.1 |
| Comparing to | |
| See all releases | |
Version 1.0.1.1
- app/code/local/IndaBox/StorePickup/Block/Adminhtml/Configuration/Manual.php +13 -0
- app/code/local/IndaBox/StorePickup/Block/Checkout/Onepage/Payment/Methods.php +39 -0
- app/code/local/IndaBox/StorePickup/Block/Checkout/Onepage/Shipping/Method/Available.php +46 -0
- app/code/local/IndaBox/StorePickup/Block/Map.php +44 -0
- app/code/local/IndaBox/StorePickup/Exception.php +5 -0
- app/code/local/IndaBox/StorePickup/Helper/Config.php +86 -0
- app/code/local/IndaBox/StorePickup/Helper/Data.php +78 -0
- app/code/local/IndaBox/StorePickup/Model/Api.php +152 -0
- app/code/local/IndaBox/StorePickup/Model/Carrier/Storepickup.php +145 -0
- app/code/local/IndaBox/StorePickup/Model/GoogleMaps.php +69 -0
- app/code/local/IndaBox/StorePickup/Model/Observer.php +105 -0
- app/code/local/IndaBox/StorePickup/Model/Order/Point.php +27 -0
- app/code/local/IndaBox/StorePickup/Model/Point.php +135 -0
- app/code/local/IndaBox/StorePickup/Model/Points.php +58 -0
- app/code/local/IndaBox/StorePickup/Model/Resource/Order/Point.php +9 -0
- app/code/local/IndaBox/StorePickup/Model/Resource/Order/Point/Collection.php +10 -0
- app/code/local/IndaBox/StorePickup/Model/Source/Payment.php +21 -0
- app/code/local/IndaBox/StorePickup/Model/Source/Selectorpayment.php +12 -0
- app/code/local/IndaBox/StorePickup/controllers/IndexController.php +79 -0
- app/code/local/IndaBox/StorePickup/etc/config.xml +171 -0
- app/code/local/IndaBox/StorePickup/etc/jstranslator.xml +21 -0
- app/code/local/IndaBox/StorePickup/etc/system.xml +170 -0
- app/code/local/IndaBox/StorePickup/sql/ibstorepickup_setup/install-0.1.0.php +61 -0
- app/design/frontend/base/default/layout/ibstorepickup.xml +29 -0
- app/design/frontend/base/default/template/ibstorepickup/checkout/onepage/billing.phtml +246 -0
- app/design/frontend/base/default/template/ibstorepickup/map.phtml +79 -0
- app/etc/modules/IndaBox_StorePickup.xml +9 -0
- app/locale/en_US/IndaBox_StorePickup.csv +38 -0
- app/locale/it_IT/IndaBox_StorePickup.csv +38 -0
- js/indabox/markerclusterer.js +1310 -0
- js/indabox/storepickup.js +254 -0
- media/indabox/marker_location.png +0 -0
- media/indabox/marker_point.png +0 -0
- package.xml +18 -0
- skin/frontend/base/default/indabox/css/storepickup.css +61 -0
- skin/frontend/base/default/indabox/images/opc-ajax-loader.gif +0 -0
app/code/local/IndaBox/StorePickup/Block/Adminhtml/Configuration/Manual.php
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Block_Adminhtml_Configuration_Manual extends Mage_Adminhtml_Block_System_Config_Form_Field
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
| 7 |
+
{
|
| 8 |
+
$message = $this->__('For all the information on installing and configuring the module and IndaBox Merchant Account, you can refer to <a href="%s" target="_blank">this page</a>', 'https://www.indabox.it/magentomodule.html');
|
| 9 |
+
$html = '<td class="label" colspan="4">' . $message . '</td>';
|
| 10 |
+
return $this->_decorateRowHtml($element, $html);
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
}
|
app/code/local/IndaBox/StorePickup/Block/Checkout/Onepage/Payment/Methods.php
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Block_Checkout_Onepage_Payment_Methods extends Mage_Checkout_Block_Onepage_Payment_Methods
|
| 4 |
+
{
|
| 5 |
+
public function getMethods()
|
| 6 |
+
{
|
| 7 |
+
$methods = $this->getData('methods');
|
| 8 |
+
if (is_null($methods))
|
| 9 |
+
{
|
| 10 |
+
$store = $this->getQuote() ? $this->getQuote()->getStoreId() : null;
|
| 11 |
+
$methods = $this->helper('payment')->getStoreMethods($store, $this->getQuote());
|
| 12 |
+
foreach ($methods as $key => $method) {
|
| 13 |
+
if ($this->_canUseMethod($method)) {
|
| 14 |
+
$this->_assignMethod($method);
|
| 15 |
+
}
|
| 16 |
+
else {
|
| 17 |
+
unset($methods[$key]);
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
if ($this->getQuote()->getShippingAddress()->getShippingMethod() === 'ibstorepickup_ibstorepickup'
|
| 22 |
+
&& Mage::helper('ibstorepickup/config')->getAllowSpecificPayments()
|
| 23 |
+
)
|
| 24 |
+
{
|
| 25 |
+
$allowed = array_flip(Mage::helper('ibstorepickup/config')->getSpecificPayments());
|
| 26 |
+
foreach ($methods as $key => $method)
|
| 27 |
+
{
|
| 28 |
+
if ( ! isset($allowed[$method->getCode()]))
|
| 29 |
+
unset($methods[$key]);
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
$methods = array_values($methods);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
$this->setData('methods', $methods);
|
| 36 |
+
}
|
| 37 |
+
return $methods;
|
| 38 |
+
}
|
| 39 |
+
}
|
app/code/local/IndaBox/StorePickup/Block/Checkout/Onepage/Shipping/Method/Available.php
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Block_Checkout_Onepage_Shipping_Method_Available extends Mage_Checkout_Block_Onepage_Shipping_Method_Available {
|
| 4 |
+
|
| 5 |
+
protected $_storePickupAvailable = false;
|
| 6 |
+
|
| 7 |
+
protected function _filterGroups($groups)
|
| 8 |
+
{
|
| 9 |
+
$useStorePickup = Mage::helper('ibstorepickup')->getUseMethod();
|
| 10 |
+
foreach ($groups as $group => $rates)
|
| 11 |
+
{
|
| 12 |
+
if ($group === 'ibstorepickup' && $useStorePickup)
|
| 13 |
+
$this->_storePickupAvailable = true;
|
| 14 |
+
|
| 15 |
+
if ($group !== 'ibstorepickup' && $useStorePickup
|
| 16 |
+
|| $group === 'ibstorepickup' && ! $useStorePickup
|
| 17 |
+
)
|
| 18 |
+
unset($groups[$group]);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
return $groups;
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
public function getShippingRates()
|
| 25 |
+
{
|
| 26 |
+
if (empty($this->_rates)) {
|
| 27 |
+
$this->getAddress()->collectShippingRates()->save();
|
| 28 |
+
|
| 29 |
+
$groups = $this->getAddress()->getGroupedAllShippingRates();
|
| 30 |
+
|
| 31 |
+
$this->_rates = $this->_filterGroups($groups);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
return $this->_rates;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
protected function _afterToHtml($html)
|
| 38 |
+
{
|
| 39 |
+
if ($this->_storePickupAvailable)
|
| 40 |
+
$html .= $this->getLayout()->createBlock('ibstorepickup/map')->toHtml();
|
| 41 |
+
|
| 42 |
+
return $html;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
}
|
| 46 |
+
|
app/code/local/IndaBox/StorePickup/Block/Map.php
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Block_Map extends Mage_Core_Block_Template
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
public function __construct()
|
| 7 |
+
{
|
| 8 |
+
parent::__construct();
|
| 9 |
+
|
| 10 |
+
$this->setTemplate('ibstorepickup/map.phtml');
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
public function getTosUrl()
|
| 14 |
+
{
|
| 15 |
+
return Mage::helper('ibstorepickup/config')->getTosUrl();
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
public function getGoogleMaps($callback = null)
|
| 19 |
+
{
|
| 20 |
+
$params = array(
|
| 21 |
+
'v' => '3.exp',
|
| 22 |
+
'region' => 'it',
|
| 23 |
+
);
|
| 24 |
+
if ($apiKey = Mage::helper('ibstorepickup/config')->getGMapsKey())
|
| 25 |
+
$params['key'] = $apiKey;
|
| 26 |
+
if ($callback)
|
| 27 |
+
$params['callback'] = $callback;
|
| 28 |
+
return 'https://maps.googleapis.com/maps/api/js?' . http_build_query($params);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
public function getBillingAddress()
|
| 32 |
+
{
|
| 33 |
+
$address = Mage::getSingleton('checkout/session')->getQuote()->getBillingAddress();
|
| 34 |
+
$street = $address->getStreet();
|
| 35 |
+
$parts = array(
|
| 36 |
+
(is_array($street) ? implode(', ', $street) : $street) . ',',
|
| 37 |
+
$address->getPostcode(),
|
| 38 |
+
$address->getCity(),
|
| 39 |
+
);
|
| 40 |
+
|
| 41 |
+
return implode(' ', $parts);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
}
|
app/code/local/IndaBox/StorePickup/Exception.php
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Exception extends Mage_Core_Exception {
|
| 4 |
+
|
| 5 |
+
}
|
app/code/local/IndaBox/StorePickup/Helper/Config.php
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Helper_Config extends Mage_Core_Helper_Abstract
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
const API_VERSION = '0.9.3';
|
| 7 |
+
const API_VERSION_HACK = '0.9';
|
| 8 |
+
|
| 9 |
+
const ENDPOINT_PRODUCTION = 'https://www.indabox.it/api/v:api_version/:api_method.php';
|
| 10 |
+
const ENDPOINT_SANDBOX = 'https://www.indabox.it/sandbox/v:api_version/:api_method.php';
|
| 11 |
+
|
| 12 |
+
const XML_PATH_ACCEPT = 'carriers/ibstorepickup/accept';
|
| 13 |
+
const XML_PATH_COST = 'carriers/ibstorepickup/cost';
|
| 14 |
+
const XML_PATH_SANDBOX = 'carriers/ibstorepickup/sandbox';
|
| 15 |
+
const XML_PATH_DEBUG = 'carriers/ibstorepickup/debug';
|
| 16 |
+
const XML_PATH_MERCHANTID = 'carriers/ibstorepickup/merchant_id';
|
| 17 |
+
const XML_PATH_APIKEY = 'carriers/ibstorepickup/api_key';
|
| 18 |
+
const XML_PATH_TOSURL = 'carriers/ibstorepickup/tos_url';
|
| 19 |
+
const XML_PATH_GMAPSKEY = 'carriers/ibstorepickup/gmaps_key';
|
| 20 |
+
const XML_PATH_ALLOWSPECIFIC = 'carriers/ibstorepickup/allowspecific_payment';
|
| 21 |
+
const XML_PATH_SPECIFICPAYMENTS = 'carriers/ibstorepickup/specificpayment';
|
| 22 |
+
|
| 23 |
+
public function getTosAccepted()
|
| 24 |
+
{
|
| 25 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_ACCEPT);
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
public function getMerchantId()
|
| 29 |
+
{
|
| 30 |
+
return (string) Mage::getStoreConfig(self::XML_PATH_MERCHANTID);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public function getAllowSpecificPayments()
|
| 34 |
+
{
|
| 35 |
+
return Mage::getStoreConfig(self::XML_PATH_ALLOWSPECIFIC);
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public function getSpecificPayments()
|
| 39 |
+
{
|
| 40 |
+
return explode(',', Mage::getStoreConfig(self::XML_PATH_SPECIFICPAYMENTS));
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
public function getApiKey()
|
| 44 |
+
{
|
| 45 |
+
return (string) Mage::getStoreConfig(self::XML_PATH_APIKEY);
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
public function isSandbox()
|
| 49 |
+
{
|
| 50 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_SANDBOX);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
public function isDebug()
|
| 54 |
+
{
|
| 55 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_DEBUG);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
public function getCost()
|
| 59 |
+
{
|
| 60 |
+
return (float) Mage::getStoreConfig(self::XML_PATH_COST);
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
public function getTosUrl()
|
| 64 |
+
{
|
| 65 |
+
return Mage::getStoreConfig(self::XML_PATH_TOSURL);
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
public function getGMapsKey()
|
| 69 |
+
{
|
| 70 |
+
return Mage::getStoreConfig(self::XML_PATH_GMAPSKEY);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
public function getEndpointUrl($method)
|
| 74 |
+
{
|
| 75 |
+
$apiVersion = $method !== 'validMerchant'
|
| 76 |
+
? self::API_VERSION
|
| 77 |
+
: self::API_VERSION_HACK
|
| 78 |
+
;
|
| 79 |
+
|
| 80 |
+
return strtr( ! $this->isSandbox() ? self::ENDPOINT_PRODUCTION : self::ENDPOINT_SANDBOX, array(
|
| 81 |
+
':api_version' => $apiVersion,
|
| 82 |
+
':api_method' => $method,
|
| 83 |
+
));
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
}
|
app/code/local/IndaBox/StorePickup/Helper/Data.php
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Helper_Data extends Mage_Core_Helper_Abstract
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
public function setUseMethod($flag)
|
| 7 |
+
{
|
| 8 |
+
$data = array(
|
| 9 |
+
'use_storepickup' => $flag,
|
| 10 |
+
);
|
| 11 |
+
$session = Mage::getSingleton('checkout/session');
|
| 12 |
+
$session->setData('indabox_storepickup', $data);
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
public function getUseMethod()
|
| 16 |
+
{
|
| 17 |
+
$session = Mage::getSingleton('checkout/session');
|
| 18 |
+
$data = $session->getData('indabox_storepickup');
|
| 19 |
+
return is_array($data) && $data['use_storepickup'];
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
public function setPointId($pointId)
|
| 23 |
+
{
|
| 24 |
+
$this->setUseMethod(true);
|
| 25 |
+
$session = Mage::getSingleton('checkout/session');
|
| 26 |
+
$data = $session->getData('indabox_storepickup');
|
| 27 |
+
$data['point_id'] = $pointId;
|
| 28 |
+
$session->setData('indabox_storepickup', $data);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
public function getPointId()
|
| 32 |
+
{
|
| 33 |
+
$session = Mage::getSingleton('checkout/session');
|
| 34 |
+
$data = $session->getData('indabox_storepickup');
|
| 35 |
+
if ( ! is_array($data) || ! isset($data['point_id']))
|
| 36 |
+
return 0;
|
| 37 |
+
else
|
| 38 |
+
return $data['point_id'];
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
public function getChangeMethodUrl()
|
| 42 |
+
{
|
| 43 |
+
return $this->_getUrl('ibstorepickup/index/changemethod', array('_secure' => true));
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
public function getSearchUrl()
|
| 47 |
+
{
|
| 48 |
+
return $this->_getUrl('ibstorepickup/index/search', array('_secure' => true));
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
public function getLocationUrl()
|
| 52 |
+
{
|
| 53 |
+
return $this->_getUrl('ibstorepickup/index/location', array('_secure' => true));
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
public function getMediaUrl()
|
| 57 |
+
{
|
| 58 |
+
return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA, true) . 'indabox/';
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public function getCustomerAddress()
|
| 62 |
+
{
|
| 63 |
+
$cSession = Mage::getSingleton('customer/session');
|
| 64 |
+
|
| 65 |
+
$attribute = Mage::getModel("eav/entity_attribute")->load("customer_shipping_address_id","attribute_code");
|
| 66 |
+
|
| 67 |
+
if($cSession->isLoggedIn() && $attribute->getId())
|
| 68 |
+
{
|
| 69 |
+
$address = Mage::helper('accountfield')
|
| 70 |
+
->getShippingAddressByCustomerId($cSession->getCustomer()->getId());
|
| 71 |
+
if($address)
|
| 72 |
+
return $address;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
$cart = Mage::getSingleton('checkout/cart');
|
| 76 |
+
return $cart->getQuote()->getShippingAddress();
|
| 77 |
+
}
|
| 78 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Api.php
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Api {
|
| 4 |
+
|
| 5 |
+
protected function _hideApiKey($debugData, $apiKey)
|
| 6 |
+
{
|
| 7 |
+
if (is_array($debugData) && strlen($apiKey)) {
|
| 8 |
+
foreach ($debugData as $key => &$value) {
|
| 9 |
+
if (is_string($value))
|
| 10 |
+
$value = str_replace($apiKey, '******', $value);
|
| 11 |
+
else
|
| 12 |
+
$value = $this->_hideApiKey($value, $apiKey);
|
| 13 |
+
}
|
| 14 |
+
}
|
| 15 |
+
return $debugData;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
protected function _debug($debugData)
|
| 19 |
+
{
|
| 20 |
+
if (Mage::helper('ibstorepickup/config')->isDebug()) {
|
| 21 |
+
$debugData = $this->_hideApiKey($debugData, Mage::helper('ibstorepickup/config')->getApiKey());
|
| 22 |
+
Mage::getModel('core/log_adapter', 'indabox_storepickup.log')
|
| 23 |
+
->log($debugData);
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
protected function _getToken($merchantId, $apiKey, $body)
|
| 28 |
+
{
|
| 29 |
+
return hash_hmac("sha256", $body, $merchantId . $apiKey);
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
public function call($method, $params)
|
| 33 |
+
{
|
| 34 |
+
$config = Mage::helper('ibstorepickup/config');
|
| 35 |
+
$merchantId = $config->getMerchantId();
|
| 36 |
+
if (empty($merchantId))
|
| 37 |
+
throw new IndaBox_StorePickup_Exception(Mage::helper('ibstorepickup')->__('Please specify Merchant ID'));
|
| 38 |
+
$apiKey = $config->getApiKey();
|
| 39 |
+
if (empty($apiKey))
|
| 40 |
+
throw new IndaBox_StorePickup_Exception(Mage::helper('ibstorepickup')->__('Please specify API Key'));
|
| 41 |
+
|
| 42 |
+
$body = json_encode($params);
|
| 43 |
+
$post = array(
|
| 44 |
+
'id_merchant' => $merchantId,
|
| 45 |
+
'msg' => $body,
|
| 46 |
+
'token' => $this->_getToken($merchantId, $apiKey, $body),
|
| 47 |
+
);
|
| 48 |
+
|
| 49 |
+
$this->_debug($post);
|
| 50 |
+
|
| 51 |
+
$client = new Zend_Http_Client($config->getEndpointUrl($method));
|
| 52 |
+
$client->setParameterPost($post);
|
| 53 |
+
$client->setHeaders(array('Accept-encoding: identity'));
|
| 54 |
+
$client->setConfig(array('strictredirects' => true));
|
| 55 |
+
|
| 56 |
+
try {
|
| 57 |
+
$response = $client->request(Zend_Http_Client::POST);
|
| 58 |
+
} catch (Zend_Http_Client_Exception $e) {
|
| 59 |
+
Mage::logException($e);
|
| 60 |
+
throw new IndaBox_StorePickup_Exception(Mage::helper('ibstorepickup')->__('Could not communicate with server'));
|
| 61 |
+
}
|
| 62 |
+
$body = $response->getBody();
|
| 63 |
+
|
| 64 |
+
$json = json_decode($body, true);
|
| 65 |
+
if ($json === null)
|
| 66 |
+
{
|
| 67 |
+
$this->_debug($body);
|
| 68 |
+
throw new IndaBox_StorePickup_Exception(Mage::helper('ibstorepickup')->__('Invalid server reply'));
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
$this->_debug($json);
|
| 72 |
+
|
| 73 |
+
return $json;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
public function validateMerchant()
|
| 77 |
+
{
|
| 78 |
+
$apiKey = Mage::helper('ibstorepickup/config')->getApiKey();
|
| 79 |
+
$result = $this->call('validMerchant', array(
|
| 80 |
+
'api_key' => $apiKey,
|
| 81 |
+
));
|
| 82 |
+
|
| 83 |
+
return $result === 'OK';
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public function getPoints($address, $radius)
|
| 87 |
+
{
|
| 88 |
+
$points = $this->call('getPoints', array(
|
| 89 |
+
'search' => $address,
|
| 90 |
+
'radius' => $radius,
|
| 91 |
+
));
|
| 92 |
+
|
| 93 |
+
if ( ! is_array($points))
|
| 94 |
+
return array();
|
| 95 |
+
|
| 96 |
+
$result = array();
|
| 97 |
+
foreach ($points as $data)
|
| 98 |
+
{
|
| 99 |
+
$point = Mage::getModel('ibstorepickup/point');
|
| 100 |
+
$point->setData($data);
|
| 101 |
+
$result[] = $point;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
return $result;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
public function submitOrder(Mage_Sales_Model_Order $order, IndaBox_StorePickup_Model_Order_Point $orderPoint)
|
| 108 |
+
{
|
| 109 |
+
$billingAddress = $order->getBillingAddress();
|
| 110 |
+
$result = $this->call('submitOrder', array(
|
| 111 |
+
'ref' => $order->getId(),
|
| 112 |
+
'ibp' => array(
|
| 113 |
+
'pointid' => $orderPoint->getPointId(),
|
| 114 |
+
'name' => $orderPoint->getPointName(),
|
| 115 |
+
),
|
| 116 |
+
'rcv' => array(
|
| 117 |
+
'firstName' => $billingAddress->getFirstname(),
|
| 118 |
+
'surname' => $billingAddress->getLastname(),
|
| 119 |
+
'street' => $billingAddress->getStreetFull(),
|
| 120 |
+
'postalCode' => $billingAddress->getPostcode(),
|
| 121 |
+
'city' => $billingAddress->getCity(),
|
| 122 |
+
'country' => $billingAddress->getCountryId(),
|
| 123 |
+
'email' => $order->getCustomerEmail(),
|
| 124 |
+
'mobile' => str_replace('+', '', preg_replace('#\+\.\.#', '', $billingAddress->getTelephone())),
|
| 125 |
+
),
|
| 126 |
+
'pcl' => array(
|
| 127 |
+
'weight' => $order->getWeight(),
|
| 128 |
+
'orderNumber' => $order->getIncrementId(),
|
| 129 |
+
'orderDate' => $order->getCreatedAt(),
|
| 130 |
+
),
|
| 131 |
+
));
|
| 132 |
+
|
| 133 |
+
if ( ! is_array($result) || ! isset($result['codice']))
|
| 134 |
+
throw new IndaBox_StorePickup_Exception(Mage::helper('ibstorepickup')->__('Could not submit order'));
|
| 135 |
+
|
| 136 |
+
return $result['codice'];
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
public function trackShipment($trackNumber)
|
| 140 |
+
{
|
| 141 |
+
$rows = $this->call('getShipmentStatusbyTid', array(
|
| 142 |
+
'transaction_ids' => is_array($trackNumber) ? $trackNumber : array($trackNumber),
|
| 143 |
+
));
|
| 144 |
+
|
| 145 |
+
$result = array();
|
| 146 |
+
foreach ($rows as $row)
|
| 147 |
+
$result[$row['ref']] = $row;
|
| 148 |
+
|
| 149 |
+
return $result;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Carrier/Storepickup.php
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Carrier_Storepickup
|
| 4 |
+
extends Mage_Shipping_Model_Carrier_Abstract
|
| 5 |
+
implements Mage_Shipping_Model_Carrier_Interface
|
| 6 |
+
{
|
| 7 |
+
|
| 8 |
+
protected $_code = 'ibstorepickup';
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
public function getCode()
|
| 12 |
+
{
|
| 13 |
+
return $this->_code;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
|
| 17 |
+
{
|
| 18 |
+
if ( ! $this->getConfigFlag('active'))
|
| 19 |
+
return false;
|
| 20 |
+
|
| 21 |
+
if ( ! Mage::helper('ibstorepickup/config')->getTosAccepted())
|
| 22 |
+
return false;
|
| 23 |
+
|
| 24 |
+
$items = $request->getAllItems();
|
| 25 |
+
if ( ! count($items))
|
| 26 |
+
return false;
|
| 27 |
+
|
| 28 |
+
if ($request->getDestCountryId() !== 'IT')
|
| 29 |
+
return false;
|
| 30 |
+
|
| 31 |
+
if ($request->getPackageWeight() > $this->getConfigData('maximum_weight'))
|
| 32 |
+
return false;
|
| 33 |
+
|
| 34 |
+
if ($request->getBaseSubtotalInclTax() > $this->getConfigData('maximum_subtotal'))
|
| 35 |
+
return false;
|
| 36 |
+
|
| 37 |
+
$api = Mage::getSingleton('ibstorepickup/api');
|
| 38 |
+
try {
|
| 39 |
+
$result = $api->validateMerchant();
|
| 40 |
+
} catch (IndaBox_StorePickup_Exception $e) {
|
| 41 |
+
return false;
|
| 42 |
+
}
|
| 43 |
+
if ( ! $result)
|
| 44 |
+
return false;
|
| 45 |
+
|
| 46 |
+
$cost = Mage::helper('ibstorepickup/config')->getCost();
|
| 47 |
+
|
| 48 |
+
$result = Mage::getModel('shipping/rate_result');
|
| 49 |
+
$method = Mage::getModel('shipping/rate_result_method');
|
| 50 |
+
$method->setCarrier('ibstorepickup');
|
| 51 |
+
$method->setCarrierTitle($this->getConfigData('title'));
|
| 52 |
+
$method->setMethod('ibstorepickup');
|
| 53 |
+
$method->setMethodTitle('');
|
| 54 |
+
$method->setPrice($cost);
|
| 55 |
+
$method->setCost($cost);
|
| 56 |
+
$result->append($method);
|
| 57 |
+
|
| 58 |
+
return $result;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
public function getAllowedMethods()
|
| 62 |
+
{
|
| 63 |
+
return array(
|
| 64 |
+
'ibstorepickup' => 'ibstorepickup',
|
| 65 |
+
);
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
public function getTrackingInfo($tracking)
|
| 69 |
+
{
|
| 70 |
+
$info = array();
|
| 71 |
+
|
| 72 |
+
$result = $this->getTracking($tracking);
|
| 73 |
+
|
| 74 |
+
if($result instanceof Mage_Shipping_Model_Tracking_Result){
|
| 75 |
+
if ($trackings = $result->getAllTrackings()) {
|
| 76 |
+
return $trackings[0];
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
elseif (is_string($result) && !empty($result)) {
|
| 80 |
+
return $result;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
return false;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
public function getTracking($trackings)
|
| 87 |
+
{
|
| 88 |
+
if ( ! is_array($trackings))
|
| 89 |
+
$trackings = array($trackings);
|
| 90 |
+
|
| 91 |
+
$errorTitle = Mage::helper('ibstorepickup')->__('Unable to retrieve tracking');
|
| 92 |
+
|
| 93 |
+
$raw = Mage::getSingleton('ibstorepickup/api')->trackShipment($trackings);
|
| 94 |
+
|
| 95 |
+
$success = array();
|
| 96 |
+
$error = array();
|
| 97 |
+
foreach ($raw as $idx => $row)
|
| 98 |
+
if ($row['esiste'])
|
| 99 |
+
{
|
| 100 |
+
list($date, $time) = explode(' ', $row['data']);
|
| 101 |
+
$success[$idx] = array(
|
| 102 |
+
'deliverydate' => $date,
|
| 103 |
+
'deliverytime' => $time,
|
| 104 |
+
'status' => $row['stato'],
|
| 105 |
+
);
|
| 106 |
+
}
|
| 107 |
+
else
|
| 108 |
+
$error[$idx] = true;
|
| 109 |
+
|
| 110 |
+
$result = Mage::getModel('shipping/tracking_result');
|
| 111 |
+
if ($success || $error) {
|
| 112 |
+
foreach ($error as $t => $r) {
|
| 113 |
+
$error = Mage::getModel('shipping/tracking_result_error');
|
| 114 |
+
$error->setCarrier('ibstorepickup');
|
| 115 |
+
$error->setCarrierTitle($this->getConfigData('title'));
|
| 116 |
+
$error->setTracking($t);
|
| 117 |
+
$error->setErrorMessage($errorTitle);
|
| 118 |
+
$result->append($error);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
foreach ($success as $t => $data) {
|
| 122 |
+
$tracking = Mage::getModel('shipping/tracking_result_status');
|
| 123 |
+
$tracking->setCarrier('ibstorepickup');
|
| 124 |
+
$tracking->setCarrierTitle($this->getConfigData('title'));
|
| 125 |
+
$tracking->setTracking($t);
|
| 126 |
+
$tracking->addData($data);
|
| 127 |
+
|
| 128 |
+
$result->append($tracking);
|
| 129 |
+
}
|
| 130 |
+
} else {
|
| 131 |
+
foreach ($trackings as $t) {
|
| 132 |
+
$error = Mage::getModel('shipping/tracking_result_error');
|
| 133 |
+
$error->setCarrier('ibstorepickup');
|
| 134 |
+
$error->setCarrierTitle($this->getConfigData('title'));
|
| 135 |
+
$error->setTracking($t);
|
| 136 |
+
$error->setErrorMessage($errorTitle);
|
| 137 |
+
$result->append($error);
|
| 138 |
+
|
| 139 |
+
}
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
return $result;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/GoogleMaps.php
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_GoogleMaps
|
| 4 |
+
{
|
| 5 |
+
const GEOCODER_URL = 'http://maps.google.com/maps/api/geocode/json?';
|
| 6 |
+
const STATUS_OK = 'ok';
|
| 7 |
+
|
| 8 |
+
const CACHE_TAG = 'indabox_gmaps';
|
| 9 |
+
const CACHE_KEY = 'indabox_gmaps_location_%s';
|
| 10 |
+
const CACHE_LIFETIME = 604800; // 1 week
|
| 11 |
+
|
| 12 |
+
protected function getLocationFromGoogle($address)
|
| 13 |
+
{
|
| 14 |
+
$params = array(
|
| 15 |
+
'sensor' => 'false',
|
| 16 |
+
'address' => $address,
|
| 17 |
+
);
|
| 18 |
+
if ($apiKey = Mage::helper('ibstorepickup/config')->getGMapsKey())
|
| 19 |
+
$params['key'] = $apiKey;
|
| 20 |
+
|
| 21 |
+
$url = self::GEOCODER_URL . http_build_query($params);
|
| 22 |
+
|
| 23 |
+
$client = new Zend_Http_Client($url);
|
| 24 |
+
$client->setHeaders(array('Accept-encoding: identity'));
|
| 25 |
+
$client->setConfig(array('strictredirects' => true));
|
| 26 |
+
|
| 27 |
+
try {
|
| 28 |
+
$response = $client->request(Zend_Http_Client::POST);
|
| 29 |
+
} catch (Zend_Http_Client_Exception $e) {
|
| 30 |
+
Mage::logException($e);
|
| 31 |
+
return null;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
$body = $response->getBody();
|
| 35 |
+
$json = json_decode($body, true);
|
| 36 |
+
if ($json === null)
|
| 37 |
+
return null;
|
| 38 |
+
|
| 39 |
+
if ( ! isset($json['status']) || strtolower($json['status']) !== self::STATUS_OK)
|
| 40 |
+
return null;
|
| 41 |
+
|
| 42 |
+
if ( ! isset($json['results']) || ! is_array($json['results']) || ! count($json['results']))
|
| 43 |
+
return null;
|
| 44 |
+
|
| 45 |
+
$result = reset($json['results']);
|
| 46 |
+
return array(
|
| 47 |
+
$result['geometry']['location']['lat'],
|
| 48 |
+
$result['geometry']['location']['lng'],
|
| 49 |
+
);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
public function getLocation($address)
|
| 53 |
+
{
|
| 54 |
+
$cacheKey = sprintf(self::CACHE_KEY, md5($address));
|
| 55 |
+
$cache = Mage::app()->getCache();
|
| 56 |
+
$value = unserialize($cache->load($cacheKey));
|
| 57 |
+
if ( ! is_array($value) || $value['address'] != $address)
|
| 58 |
+
{
|
| 59 |
+
$value = array(
|
| 60 |
+
'address' => $address,
|
| 61 |
+
'location' => $this->getLocationFromGoogle($address),
|
| 62 |
+
);
|
| 63 |
+
|
| 64 |
+
$cache->save(serialize($value), $cacheKey, array(self::CACHE_TAG), self::CACHE_LIFETIME);
|
| 65 |
+
}
|
| 66 |
+
return $value['location'];
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Observer.php
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Observer
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
public function onSaveShippingMethod($event)
|
| 7 |
+
{
|
| 8 |
+
$quote = $event->getQuote();
|
| 9 |
+
if ($quote->getShippingAddress()->getShippingMethod() !== 'ibstorepickup_ibstorepickup')
|
| 10 |
+
{
|
| 11 |
+
Mage::helper('ibstorepickup')->setUseMethod(false);
|
| 12 |
+
return;
|
| 13 |
+
}
|
| 14 |
+
$request = $event->getRequest();
|
| 15 |
+
$pointId = $request->getPost('indabox_point_id');
|
| 16 |
+
if ( ! $pointId)
|
| 17 |
+
{
|
| 18 |
+
Mage::helper('ibstorepickup')->setUseMethod(false);
|
| 19 |
+
return;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
Mage::helper('ibstorepickup')->setPointId($pointId);
|
| 23 |
+
$point = Mage::getSingleton('ibstorepickup/points')->getPoint($pointId);
|
| 24 |
+
|
| 25 |
+
if ($point->getLatitude())
|
| 26 |
+
{
|
| 27 |
+
$address = $quote->getShippingAddress();
|
| 28 |
+
$address->addData($point->getAddressData());
|
| 29 |
+
|
| 30 |
+
$address->implodeStreetAddress();
|
| 31 |
+
$address->setCollectShippingRates(true);
|
| 32 |
+
|
| 33 |
+
$quote->collectTotals()->save();
|
| 34 |
+
}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public function onSaveOrderAfter($event)
|
| 38 |
+
{
|
| 39 |
+
$order = $event->getOrder();
|
| 40 |
+
$shippingMethod = $order->getShippingMethod();
|
| 41 |
+
if ($shippingMethod !== 'ibstorepickup_ibstorepickup')
|
| 42 |
+
return;
|
| 43 |
+
|
| 44 |
+
$pointId = Mage::helper('ibstorepickup')->getPointId();
|
| 45 |
+
if ( ! $pointId)
|
| 46 |
+
return;
|
| 47 |
+
|
| 48 |
+
$point = Mage::getSingleton('ibstorepickup/points')->getPoint($pointId);
|
| 49 |
+
$orderPoint = Mage::getModel('ibstorepickup/order_point');
|
| 50 |
+
$orderPoint->createFor($order, $point);
|
| 51 |
+
|
| 52 |
+
Mage::helper('ibstorepickup')->setUseMethod(false);
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
public function onOrderInvoicePay($event)
|
| 56 |
+
{
|
| 57 |
+
$invoice = $event->getInvoice();
|
| 58 |
+
$order = $invoice->getOrder();
|
| 59 |
+
|
| 60 |
+
$orderId = $order->getId();
|
| 61 |
+
$orderPoint = Mage::getModel('ibstorepickup/order_point')->load($orderId, 'order_id');
|
| 62 |
+
if ( ! $orderPoint->getId() || $orderPoint->getIsNotified())
|
| 63 |
+
return;
|
| 64 |
+
|
| 65 |
+
try {
|
| 66 |
+
$trackingNumber = Mage::getSingleton('ibstorepickup/api')->submitOrder($order, $orderPoint);
|
| 67 |
+
} catch (IndaBox_StorePickup_Exception $e) {
|
| 68 |
+
Mage::logException($e);
|
| 69 |
+
return;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
$orderPoint->setIsNotified(true);
|
| 73 |
+
$orderPoint->save();
|
| 74 |
+
|
| 75 |
+
if ( ! $order->canShip())
|
| 76 |
+
return;
|
| 77 |
+
|
| 78 |
+
try {
|
| 79 |
+
$shipment = $order->prepareShipment();
|
| 80 |
+
if ($shipment)
|
| 81 |
+
{
|
| 82 |
+
$shipment->register();
|
| 83 |
+
$shipment->getOrder()->setIsInProcess(true);
|
| 84 |
+
|
| 85 |
+
$track = Mage::getModel('sales/order_shipment_track')
|
| 86 |
+
->setShipment($shipment)
|
| 87 |
+
->setData('title', 'IndaBox')
|
| 88 |
+
->setData('number', $trackingNumber)
|
| 89 |
+
->setData('carrier_code', 'ibstorepickup')
|
| 90 |
+
->setData('order_id', $shipment->getData('order_id'))
|
| 91 |
+
;
|
| 92 |
+
|
| 93 |
+
$transactionSave = Mage::getModel('core/resource_transaction')
|
| 94 |
+
->addObject($shipment)
|
| 95 |
+
->addObject($shipment->getOrder())
|
| 96 |
+
->addObject($track)
|
| 97 |
+
->save()
|
| 98 |
+
;
|
| 99 |
+
}
|
| 100 |
+
} catch (Mage_Core_Exception $e) {
|
| 101 |
+
Mage::logException($e);
|
| 102 |
+
}
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Order/Point.php
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Order_Point extends Mage_Core_Model_Abstract
|
| 4 |
+
{
|
| 5 |
+
public function _construct()
|
| 6 |
+
{
|
| 7 |
+
parent::_construct();
|
| 8 |
+
$this->_init('ibstorepickup/order_point');
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
public function createFor(Mage_Sales_Model_Order $order, IndaBox_StorePickup_Model_Point $point)
|
| 12 |
+
{
|
| 13 |
+
$this->setData('order_id', $order->getId());
|
| 14 |
+
$this->setData('point_id', $point->getId());
|
| 15 |
+
$this->setData('point_name', $point->getName());
|
| 16 |
+
$this->setData('point_address', $point->getFormattedAddress());
|
| 17 |
+
$this->setData('point_data', serialize($point->getData()));
|
| 18 |
+
$this->setData('is_notified', false);
|
| 19 |
+
return $this->save();
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
public function getPoint()
|
| 23 |
+
{
|
| 24 |
+
return Mage::getModel('ibstorepickup/point')->setData(unserialize($this->getPointData()));
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Point.php
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Point extends Varien_Object {
|
| 4 |
+
|
| 5 |
+
public function getId()
|
| 6 |
+
{
|
| 7 |
+
return $this->_getData('pointid');
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
public function getName()
|
| 11 |
+
{
|
| 12 |
+
return $this->_getData('name');
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
public function getStreet()
|
| 16 |
+
{
|
| 17 |
+
$parts = array();
|
| 18 |
+
foreach (array('toponimo', 'indirizzo', 'civico') as $key)
|
| 19 |
+
{
|
| 20 |
+
$value = trim($this->_getData($key));
|
| 21 |
+
if ( ! empty($value))
|
| 22 |
+
{
|
| 23 |
+
if ($key === 'civico')
|
| 24 |
+
$value = ', ' . $value;
|
| 25 |
+
else
|
| 26 |
+
$value = ' ' . $value;
|
| 27 |
+
$parts[] = $value;
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
return trim(implode('', $parts));
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
public function getCity()
|
| 34 |
+
{
|
| 35 |
+
return $this->_getData('comune');
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public function getPostcode()
|
| 39 |
+
{
|
| 40 |
+
return $this->_getData('cap');
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
public function getRegion()
|
| 44 |
+
{
|
| 45 |
+
return $this->_getData('provincia');
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
public function getRegionId()
|
| 49 |
+
{
|
| 50 |
+
$regionModel = Mage::getModel('directory/region')->loadByCode($this->getRegion(), $this->getCountryId());
|
| 51 |
+
return $regionModel->getId();
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
public function getCountryId()
|
| 55 |
+
{
|
| 56 |
+
// hardcoded
|
| 57 |
+
return 'IT';
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
public function getTelephone()
|
| 61 |
+
{
|
| 62 |
+
return $this->_getData('tel');
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
public function getLatitude()
|
| 66 |
+
{
|
| 67 |
+
return $this->_getData('lat');
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public function getLongitude()
|
| 71 |
+
{
|
| 72 |
+
return $this->_getData('lng');
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
public function getDistance()
|
| 76 |
+
{
|
| 77 |
+
return $this->_getData('distance');
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
public function getIndex()
|
| 81 |
+
{
|
| 82 |
+
return $this->_getData('indice');
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
public function getHours()
|
| 86 |
+
{
|
| 87 |
+
return $this->_getData('orari');
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
public function getUri()
|
| 91 |
+
{
|
| 92 |
+
return $this->_getData('uri');
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
public function getAddressData()
|
| 96 |
+
{
|
| 97 |
+
return array(
|
| 98 |
+
'firstname' => Mage::helper('ibstorepickup')->__('IndaBox Point'),
|
| 99 |
+
'lastname' => $this->getName(),
|
| 100 |
+
'street' => $this->getStreet(),
|
| 101 |
+
'city' => $this->getCity(),
|
| 102 |
+
'region' => $this->getRegion(),
|
| 103 |
+
'region_id' => $this->getRegionId(),
|
| 104 |
+
'postcode' => $this->getPostcode(),
|
| 105 |
+
'country_id' => $this->getCountryId(),
|
| 106 |
+
'telephone' => $this->getTelephone(),
|
| 107 |
+
);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
public function getFormattedAddress()
|
| 111 |
+
{
|
| 112 |
+
$address = Mage::getModel('customer/address');
|
| 113 |
+
$address->setData($this->getAddressData());
|
| 114 |
+
|
| 115 |
+
return $address->format('oneline');
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
public function toArray(array $arrAttributes = array())
|
| 119 |
+
{
|
| 120 |
+
$result = array(
|
| 121 |
+
'id' => $this->getId(),
|
| 122 |
+
'name' => $this->getName(),
|
| 123 |
+
);
|
| 124 |
+
$result = array_merge($result, $this->getAddressData());
|
| 125 |
+
$result = array_merge($result, array(
|
| 126 |
+
'latitude' => $this->getLatitude(),
|
| 127 |
+
'longitude' => $this->getLongitude(),
|
| 128 |
+
'distance' => $this->getDistance(),
|
| 129 |
+
'url' => $this->getUri(),
|
| 130 |
+
));
|
| 131 |
+
|
| 132 |
+
return $result;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Points.php
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Points {
|
| 4 |
+
|
| 5 |
+
const CACHE_TAG = 'indabox_points';
|
| 6 |
+
const CACHE_KEY = 'indabox_points_%s_%s';
|
| 7 |
+
const CACHE_LIFETIME = 3600; // 1 hour
|
| 8 |
+
|
| 9 |
+
const POINT_CACHE_KEY = 'indabox_point_%d';
|
| 10 |
+
const POINT_CACHE_LIFETIME = 604800; // 1 week
|
| 11 |
+
|
| 12 |
+
protected function storePoint($point)
|
| 13 |
+
{
|
| 14 |
+
$cacheKey = sprintf(self::POINT_CACHE_KEY, $point->getId());
|
| 15 |
+
$cache = Mage::app()->getCache();
|
| 16 |
+
$cache->save(serialize($point), $cacheKey, array(self::CACHE_TAG), self::POINT_CACHE_LIFETIME);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
public function getPoint($pointId)
|
| 20 |
+
{
|
| 21 |
+
$cacheKey = sprintf(self::POINT_CACHE_KEY, $pointId);
|
| 22 |
+
$cache = Mage::app()->getCache();
|
| 23 |
+
$value = unserialize($cache->load($cacheKey));
|
| 24 |
+
if ( ! $value instanceof IndaBox_StorePickup_Model_Point)
|
| 25 |
+
{
|
| 26 |
+
$value = Mage::getModel('ibstorepickup/point');
|
| 27 |
+
$value->setData(array(
|
| 28 |
+
'pointid' => $pointId,
|
| 29 |
+
'name' => 'Point #' . $pointId,
|
| 30 |
+
));
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
return $value;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
public function getPoints($address, $radius)
|
| 37 |
+
{
|
| 38 |
+
$cacheKey = sprintf(self::CACHE_KEY, md5($address), $radius);
|
| 39 |
+
$cache = Mage::app()->getCache();
|
| 40 |
+
$value = unserialize($cache->load($cacheKey));
|
| 41 |
+
if ( ! is_array($value) || $value['address'] != $address || $value['radius'] != $radius)
|
| 42 |
+
{
|
| 43 |
+
$points = Mage::getSingleton('ibstorepickup/api')->getPoints($address, $radius);
|
| 44 |
+
foreach ($points as $point)
|
| 45 |
+
$this->storePoint($point);
|
| 46 |
+
|
| 47 |
+
$value = array(
|
| 48 |
+
'address' => $address,
|
| 49 |
+
'radius' => $radius,
|
| 50 |
+
'location' => $points,
|
| 51 |
+
);
|
| 52 |
+
|
| 53 |
+
$cache->save(serialize($value), $cacheKey, array(self::CACHE_TAG), self::CACHE_LIFETIME);
|
| 54 |
+
}
|
| 55 |
+
return $value['location'];
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Resource/Order/Point.php
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Resource_Order_Point extends Mage_Core_Model_Resource_Db_Abstract
|
| 4 |
+
{
|
| 5 |
+
public function _construct()
|
| 6 |
+
{
|
| 7 |
+
$this->_init('ibstorepickup/order_point', 'order_point_id');
|
| 8 |
+
}
|
| 9 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Resource/Order/Point/Collection.php
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Resource_Order_Point_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
|
| 4 |
+
{
|
| 5 |
+
public function _construct()
|
| 6 |
+
{
|
| 7 |
+
parent::_construct();
|
| 8 |
+
$this->_init('ibstorepickup/order_point');
|
| 9 |
+
}
|
| 10 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Source/Payment.php
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Source_Payment
|
| 4 |
+
{
|
| 5 |
+
public function toOptionArray()
|
| 6 |
+
{
|
| 7 |
+
$collection = Mage::getModel('payment/config')->getActiveMethods();
|
| 8 |
+
|
| 9 |
+
if ( ! count($collection))
|
| 10 |
+
return;
|
| 11 |
+
|
| 12 |
+
$options = array();
|
| 13 |
+
foreach ($collection as $item)
|
| 14 |
+
{
|
| 15 |
+
$title = $item->getTitle() ? $item->getTitle() : $item->getId();
|
| 16 |
+
$options[] = array('value' => $item->getId(), 'label' => $title);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
return $options;
|
| 20 |
+
}
|
| 21 |
+
}
|
app/code/local/IndaBox/StorePickup/Model/Source/Selectorpayment.php
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_Model_Source_Selectorpayment
|
| 4 |
+
{
|
| 5 |
+
public function toOptionArray()
|
| 6 |
+
{
|
| 7 |
+
return array(
|
| 8 |
+
array('value' => 0, 'label' => Mage::helper('ibstorepickup')->__('All Allowed Payments')),
|
| 9 |
+
array('value' => 1, 'label' => Mage::helper('ibstorepickup')->__('Specific Payments')),
|
| 10 |
+
);
|
| 11 |
+
}
|
| 12 |
+
}
|
app/code/local/IndaBox/StorePickup/controllers/IndexController.php
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
class IndaBox_StorePickup_IndexController extends Mage_Core_Controller_Front_Action
|
| 4 |
+
{
|
| 5 |
+
|
| 6 |
+
public function changemethodAction()
|
| 7 |
+
{
|
| 8 |
+
$flag = (bool) $this->getRequest()->getParam('flag');
|
| 9 |
+
Mage::helper('ibstorepickup')->setUseMethod($flag);
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
public function searchAction()
|
| 13 |
+
{
|
| 14 |
+
$this->getResponse()->setHeader('Content-type', 'application/json');
|
| 15 |
+
|
| 16 |
+
$response = new Varien_Object();
|
| 17 |
+
$response->setError(false);
|
| 18 |
+
|
| 19 |
+
$address = (string) $this->getRequest()->getParam('address', '');
|
| 20 |
+
$radius = (string) $this->getRequest()->getParam('radius', '');
|
| 21 |
+
|
| 22 |
+
if (empty($address) || $radius <= 0)
|
| 23 |
+
{
|
| 24 |
+
$response->setError(true);
|
| 25 |
+
$response->setMessage($this->__('Invalid search parameters.'));
|
| 26 |
+
|
| 27 |
+
$this->getResponse()->setBody($response->toJson());
|
| 28 |
+
return;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
try {
|
| 32 |
+
$points = Mage::getSingleton('ibstorepickup/points')->getPoints($address, $radius);
|
| 33 |
+
$list = array();
|
| 34 |
+
foreach ($points as $point)
|
| 35 |
+
$list[] = $point->toArray();
|
| 36 |
+
$response->setPoints($list);
|
| 37 |
+
} catch (IndaBox_StorePickup_Exception $e) {
|
| 38 |
+
$response->setError(true);
|
| 39 |
+
$response->setMessage($this->__('Error while communicating with IndaBox. Please retry later.'));
|
| 40 |
+
$this->getResponse()->setBody($response->toJson());
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
$this->getResponse()->setBody($response->toJson());
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
public function locationAction()
|
| 47 |
+
{
|
| 48 |
+
$this->getResponse()->setHeader('Content-type', 'application/json');
|
| 49 |
+
|
| 50 |
+
$response = new Varien_Object();
|
| 51 |
+
$response->setError(false);
|
| 52 |
+
|
| 53 |
+
$address = (string) $this->getRequest()->getParam('address', '');
|
| 54 |
+
|
| 55 |
+
if (empty($address))
|
| 56 |
+
{
|
| 57 |
+
$response->setError(true);
|
| 58 |
+
$response->setMessage($this->__('Invalid search parameters.'));
|
| 59 |
+
|
| 60 |
+
$this->getResponse()->setBody($response->toJson());
|
| 61 |
+
return;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
$location = Mage::getSingleton('ibstorepickup/googleMaps')->getLocation($address);
|
| 65 |
+
if ($location !== null)
|
| 66 |
+
{
|
| 67 |
+
$response->setLatitude($location[0]);
|
| 68 |
+
$response->setLongitude($location[1]);
|
| 69 |
+
}
|
| 70 |
+
else
|
| 71 |
+
{
|
| 72 |
+
$response->setError(true);
|
| 73 |
+
$response->setMessage($this->__('Location does not found'));
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
$this->getResponse()->setBody($response->toJson());
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
}
|
app/code/local/IndaBox/StorePickup/etc/config.xml
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<config>
|
| 3 |
+
|
| 4 |
+
<modules>
|
| 5 |
+
<IndaBox_StorePickup>
|
| 6 |
+
<version>0.1.0</version>
|
| 7 |
+
</IndaBox_StorePickup>
|
| 8 |
+
</modules>
|
| 9 |
+
|
| 10 |
+
<global>
|
| 11 |
+
|
| 12 |
+
<models>
|
| 13 |
+
<ibstorepickup>
|
| 14 |
+
<class>IndaBox_StorePickup_Model</class>
|
| 15 |
+
<resourceModel>ibstorepickup_resource</resourceModel>
|
| 16 |
+
</ibstorepickup>
|
| 17 |
+
<ibstorepickup_resource>
|
| 18 |
+
<class>IndaBox_StorePickup_Model_Resource</class>
|
| 19 |
+
<entities>
|
| 20 |
+
<order_point>
|
| 21 |
+
<table>ibsp_order_point</table>
|
| 22 |
+
</order_point>
|
| 23 |
+
</entities>
|
| 24 |
+
</ibstorepickup_resource>
|
| 25 |
+
</models>
|
| 26 |
+
|
| 27 |
+
<blocks>
|
| 28 |
+
<ibstorepickup>
|
| 29 |
+
<class>IndaBox_StorePickup_Block</class>
|
| 30 |
+
</ibstorepickup>
|
| 31 |
+
<checkout>
|
| 32 |
+
<rewrite>
|
| 33 |
+
<onepage_payment_methods>IndaBox_StorePickup_Block_Checkout_Onepage_Payment_Methods</onepage_payment_methods>
|
| 34 |
+
<onepage_shipping_method_available>IndaBox_StorePickup_Block_Checkout_Onepage_Shipping_Method_Available</onepage_shipping_method_available>
|
| 35 |
+
</rewrite>
|
| 36 |
+
</checkout>
|
| 37 |
+
</blocks>
|
| 38 |
+
|
| 39 |
+
<helpers>
|
| 40 |
+
<ibstorepickup>
|
| 41 |
+
<class>IndaBox_StorePickup_Helper</class>
|
| 42 |
+
</ibstorepickup>
|
| 43 |
+
</helpers>
|
| 44 |
+
|
| 45 |
+
<resources>
|
| 46 |
+
<ibstorepickup_setup>
|
| 47 |
+
<setup>
|
| 48 |
+
<module>IndaBox_StorePickup</module>
|
| 49 |
+
</setup>
|
| 50 |
+
<connection>
|
| 51 |
+
<use>core_setup</use>
|
| 52 |
+
</connection>
|
| 53 |
+
</ibstorepickup_setup>
|
| 54 |
+
<ibstorepickup_write>
|
| 55 |
+
<connection>
|
| 56 |
+
<use>core_write</use>
|
| 57 |
+
</connection>
|
| 58 |
+
</ibstorepickup_write>
|
| 59 |
+
<ibstorepickup_read>
|
| 60 |
+
<connection>
|
| 61 |
+
<use>core_read</use>
|
| 62 |
+
</connection>
|
| 63 |
+
</ibstorepickup_read>
|
| 64 |
+
</resources>
|
| 65 |
+
|
| 66 |
+
<events>
|
| 67 |
+
<sales_order_invoice_pay>
|
| 68 |
+
<observers>
|
| 69 |
+
<indabox_storepickup_observer>
|
| 70 |
+
<type>singleton</type>
|
| 71 |
+
<class>ibstorepickup/observer</class>
|
| 72 |
+
<method>onOrderInvoicePay</method>
|
| 73 |
+
</indabox_storepickup_observer>
|
| 74 |
+
</observers>
|
| 75 |
+
</sales_order_invoice_pay>
|
| 76 |
+
</events>
|
| 77 |
+
|
| 78 |
+
</global>
|
| 79 |
+
|
| 80 |
+
<frontend>
|
| 81 |
+
|
| 82 |
+
<translate>
|
| 83 |
+
<modules>
|
| 84 |
+
<IndaBox_StorePickup>
|
| 85 |
+
<files>
|
| 86 |
+
<default>IndaBox_StorePickup.csv</default>
|
| 87 |
+
</files>
|
| 88 |
+
</IndaBox_StorePickup>
|
| 89 |
+
</modules>
|
| 90 |
+
</translate>
|
| 91 |
+
|
| 92 |
+
<routers>
|
| 93 |
+
<ibstorepickup>
|
| 94 |
+
<use>standard</use>
|
| 95 |
+
<args>
|
| 96 |
+
<module>IndaBox_StorePickup</module>
|
| 97 |
+
<frontName>ibstorepickup</frontName>
|
| 98 |
+
</args>
|
| 99 |
+
</ibstorepickup>
|
| 100 |
+
</routers>
|
| 101 |
+
|
| 102 |
+
<layout>
|
| 103 |
+
<updates>
|
| 104 |
+
<ibstorepickup>
|
| 105 |
+
<file>ibstorepickup.xml</file>
|
| 106 |
+
</ibstorepickup>
|
| 107 |
+
</updates>
|
| 108 |
+
</layout>
|
| 109 |
+
|
| 110 |
+
<events>
|
| 111 |
+
<checkout_type_onepage_save_order_after>
|
| 112 |
+
<observers>
|
| 113 |
+
<indabox_storepickup_observer>
|
| 114 |
+
<type>singleton</type>
|
| 115 |
+
<class>ibstorepickup/observer</class>
|
| 116 |
+
<method>onSaveOrderAfter</method>
|
| 117 |
+
</indabox_storepickup_observer>
|
| 118 |
+
</observers>
|
| 119 |
+
</checkout_type_onepage_save_order_after>
|
| 120 |
+
<checkout_controller_onepage_save_shipping_method>
|
| 121 |
+
<observers>
|
| 122 |
+
<indabox_storepickup_observer>
|
| 123 |
+
<type>singleton</type>
|
| 124 |
+
<class>ibstorepickup/observer</class>
|
| 125 |
+
<method>onSaveShippingMethod</method>
|
| 126 |
+
</indabox_storepickup_observer>
|
| 127 |
+
</observers>
|
| 128 |
+
</checkout_controller_onepage_save_shipping_method>
|
| 129 |
+
</events>
|
| 130 |
+
</frontend>
|
| 131 |
+
|
| 132 |
+
<adminhtml>
|
| 133 |
+
|
| 134 |
+
<translate>
|
| 135 |
+
<modules>
|
| 136 |
+
<IndaBox_StorePickup>
|
| 137 |
+
<files>
|
| 138 |
+
<default>IndaBox_StorePickup.csv</default>
|
| 139 |
+
</files>
|
| 140 |
+
</IndaBox_StorePickup>
|
| 141 |
+
</modules>
|
| 142 |
+
</translate>
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
<layout>
|
| 146 |
+
<updates>
|
| 147 |
+
<ibstorepickup>
|
| 148 |
+
<file>ibstorepickup.xml</file>
|
| 149 |
+
</ibstorepickup>
|
| 150 |
+
</updates>
|
| 151 |
+
</layout>
|
| 152 |
+
</adminhtml>
|
| 153 |
+
|
| 154 |
+
<default>
|
| 155 |
+
<carriers>
|
| 156 |
+
<ibstorepickup>
|
| 157 |
+
<accept>0</accept>
|
| 158 |
+
<active>0</active>
|
| 159 |
+
<model>ibstorepickup/carrier_storepickup</model>
|
| 160 |
+
<title>IndaBox StorePickup</title>
|
| 161 |
+
<sandbox>1</sandbox>
|
| 162 |
+
<debug>1</debug>
|
| 163 |
+
<cost>0</cost>
|
| 164 |
+
<maximum_subtotal>500</maximum_subtotal>
|
| 165 |
+
<maximum_weight>15</maximum_weight>
|
| 166 |
+
<tos_url>http://www.indabox.it/condizioni-prestashop/</tos_url>
|
| 167 |
+
</ibstorepickup>
|
| 168 |
+
</carriers>
|
| 169 |
+
</default>
|
| 170 |
+
|
| 171 |
+
</config>
|
app/code/local/IndaBox/StorePickup/etc/jstranslator.xml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<jstranslator>
|
| 3 |
+
<indabox-agreement translate="message" module="ibstorepickup">
|
| 4 |
+
<message>You should accept IndaBox terms and conditions</message>
|
| 5 |
+
</indabox-agreement>
|
| 6 |
+
<indabox-select-point translate="message" module="ibstorepickup">
|
| 7 |
+
<message>You should select one of available pick-up points to continue</message>
|
| 8 |
+
</indabox-select-point>
|
| 9 |
+
<indabox-error translate="message" module="ibstorepickup">
|
| 10 |
+
<message>Error</message>
|
| 11 |
+
</indabox-error>
|
| 12 |
+
<indabox-use-point translate="message" module="ibstorepickup">
|
| 13 |
+
<message>Select this pick-up point</message>
|
| 14 |
+
</indabox-use-point>
|
| 15 |
+
<indabox-distance translate="message" module="ibstorepickup">
|
| 16 |
+
<message>Distance</message>
|
| 17 |
+
</indabox-distance>
|
| 18 |
+
<indabox-telephone translate="message" module="ibstorepickup">
|
| 19 |
+
<message>Telephone</message>
|
| 20 |
+
</indabox-telephone>
|
| 21 |
+
</jstranslator>
|
app/code/local/IndaBox/StorePickup/etc/system.xml
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<config>
|
| 3 |
+
<sections>
|
| 4 |
+
<carriers>
|
| 5 |
+
<groups>
|
| 6 |
+
<ibstorepickup translate="label" module="ibstorepickup">
|
| 7 |
+
<label>IndaBox</label>
|
| 8 |
+
<frontend_type>text</frontend_type>
|
| 9 |
+
<sort_order>12</sort_order>
|
| 10 |
+
<show_in_default>1</show_in_default>
|
| 11 |
+
<show_in_website>1</show_in_website>
|
| 12 |
+
<show_in_store>1</show_in_store>
|
| 13 |
+
<fields>
|
| 14 |
+
<configuration_manual translate="label">
|
| 15 |
+
<label></label>
|
| 16 |
+
<frontend_model>ibstorepickup/adminhtml_configuration_manual</frontend_model>
|
| 17 |
+
<backend_model>adminhtml/system_config_backend_serialized_array</backend_model>
|
| 18 |
+
<sort_order>0</sort_order>
|
| 19 |
+
<show_in_default>1</show_in_default>
|
| 20 |
+
<show_in_website>1</show_in_website>
|
| 21 |
+
<show_in_store>0</show_in_store>
|
| 22 |
+
</configuration_manual>
|
| 23 |
+
<accept translate="label comment">
|
| 24 |
+
<label>Accept TOS</label>
|
| 25 |
+
<comment><![CDATA[I accept <a href="https://www.indabox.it/termini-eco/" target="_blank">IndaBox Terms of Service</a>]]></comment>
|
| 26 |
+
<frontend_type>select</frontend_type>
|
| 27 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 28 |
+
<sort_order>1</sort_order>
|
| 29 |
+
<show_in_default>1</show_in_default>
|
| 30 |
+
<show_in_website>1</show_in_website>
|
| 31 |
+
<show_in_store>0</show_in_store>
|
| 32 |
+
</accept>
|
| 33 |
+
<active translate="label">
|
| 34 |
+
<label>Enabled</label>
|
| 35 |
+
<frontend_type>select</frontend_type>
|
| 36 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 37 |
+
<sort_order>10</sort_order>
|
| 38 |
+
<show_in_default>1</show_in_default>
|
| 39 |
+
<show_in_website>1</show_in_website>
|
| 40 |
+
<show_in_store>0</show_in_store>
|
| 41 |
+
<depends><accept>1</accept></depends>
|
| 42 |
+
</active>
|
| 43 |
+
<title translate="label">
|
| 44 |
+
<label>Title</label>
|
| 45 |
+
<frontend_type>text</frontend_type>
|
| 46 |
+
<sort_order>11</sort_order>
|
| 47 |
+
<show_in_default>1</show_in_default>
|
| 48 |
+
<show_in_website>1</show_in_website>
|
| 49 |
+
<show_in_store>0</show_in_store>
|
| 50 |
+
<depends><accept>1</accept></depends>
|
| 51 |
+
</title>
|
| 52 |
+
|
| 53 |
+
<merchant_id translate="label">
|
| 54 |
+
<label>Merchant ID</label>
|
| 55 |
+
<frontend_type>text</frontend_type>
|
| 56 |
+
<sort_order>20</sort_order>
|
| 57 |
+
<show_in_default>1</show_in_default>
|
| 58 |
+
<show_in_website>1</show_in_website>
|
| 59 |
+
<show_in_store>0</show_in_store>
|
| 60 |
+
<depends><accept>1</accept></depends>
|
| 61 |
+
</merchant_id>
|
| 62 |
+
<api_key translate="label">
|
| 63 |
+
<label>API Key</label>
|
| 64 |
+
<frontend_type>textarea</frontend_type>
|
| 65 |
+
<sort_order>21</sort_order>
|
| 66 |
+
<show_in_default>1</show_in_default>
|
| 67 |
+
<show_in_website>1</show_in_website>
|
| 68 |
+
<show_in_store>0</show_in_store>
|
| 69 |
+
<depends><accept>1</accept></depends>
|
| 70 |
+
</api_key>
|
| 71 |
+
<sandbox translate="label">
|
| 72 |
+
<label>Sandbox</label>
|
| 73 |
+
<frontend_type>select</frontend_type>
|
| 74 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 75 |
+
<sort_order>22</sort_order>
|
| 76 |
+
<show_in_default>1</show_in_default>
|
| 77 |
+
<show_in_website>1</show_in_website>
|
| 78 |
+
<show_in_store>0</show_in_store>
|
| 79 |
+
<depends><accept>1</accept></depends>
|
| 80 |
+
</sandbox>
|
| 81 |
+
<debug translate="label">
|
| 82 |
+
<label>Debug</label>
|
| 83 |
+
<frontend_type>select</frontend_type>
|
| 84 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 85 |
+
<sort_order>23</sort_order>
|
| 86 |
+
<show_in_default>1</show_in_default>
|
| 87 |
+
<show_in_website>1</show_in_website>
|
| 88 |
+
<show_in_store>0</show_in_store>
|
| 89 |
+
<depends><accept>1</accept></depends>
|
| 90 |
+
</debug>
|
| 91 |
+
|
| 92 |
+
<cost translate="label">
|
| 93 |
+
<label>Cost</label>
|
| 94 |
+
<frontend_type>text</frontend_type>
|
| 95 |
+
<sort_order>30</sort_order>
|
| 96 |
+
<validate>validate-number</validate>
|
| 97 |
+
<show_in_default>1</show_in_default>
|
| 98 |
+
<show_in_website>1</show_in_website>
|
| 99 |
+
<show_in_store>0</show_in_store>
|
| 100 |
+
<depends><accept>1</accept></depends>
|
| 101 |
+
</cost>
|
| 102 |
+
<maximum_subtotal translate="label">
|
| 103 |
+
<label>Maximum Subtotal</label>
|
| 104 |
+
<frontend_type>text</frontend_type>
|
| 105 |
+
<sort_order>31</sort_order>
|
| 106 |
+
<validate>validate-number</validate>
|
| 107 |
+
<show_in_default>1</show_in_default>
|
| 108 |
+
<show_in_website>1</show_in_website>
|
| 109 |
+
<show_in_store>0</show_in_store>
|
| 110 |
+
<depends><accept>1</accept></depends>
|
| 111 |
+
</maximum_subtotal>
|
| 112 |
+
<maximum_weight translate="label">
|
| 113 |
+
<label>Maximum Weight</label>
|
| 114 |
+
<frontend_type>text</frontend_type>
|
| 115 |
+
<sort_order>32</sort_order>
|
| 116 |
+
<validate>validate-number</validate>
|
| 117 |
+
<show_in_default>1</show_in_default>
|
| 118 |
+
<show_in_website>1</show_in_website>
|
| 119 |
+
<show_in_store>0</show_in_store>
|
| 120 |
+
<depends><accept>1</accept></depends>
|
| 121 |
+
</maximum_weight>
|
| 122 |
+
|
| 123 |
+
<tos_url translate="label">
|
| 124 |
+
<label>Terms and Conditions Url</label>
|
| 125 |
+
<frontend_type>text</frontend_type>
|
| 126 |
+
<sort_order>40</sort_order>
|
| 127 |
+
<show_in_default>1</show_in_default>
|
| 128 |
+
<show_in_website>1</show_in_website>
|
| 129 |
+
<show_in_store>0</show_in_store>
|
| 130 |
+
<depends><accept>1</accept></depends>
|
| 131 |
+
</tos_url>
|
| 132 |
+
<gmaps_key translate="label comment">
|
| 133 |
+
<label>Google Maps API Key</label>
|
| 134 |
+
<frontend_type>text</frontend_type>
|
| 135 |
+
<sort_order>40</sort_order>
|
| 136 |
+
<show_in_default>1</show_in_default>
|
| 137 |
+
<show_in_website>1</show_in_website>
|
| 138 |
+
<show_in_store>0</show_in_store>
|
| 139 |
+
<comment>Optional, use for high load only</comment>
|
| 140 |
+
<depends><accept>1</accept></depends>
|
| 141 |
+
</gmaps_key>
|
| 142 |
+
|
| 143 |
+
<allowspecific_payment translate="label">
|
| 144 |
+
<label>Applicable payments</label>
|
| 145 |
+
<frontend_type>select</frontend_type>
|
| 146 |
+
<sort_order>100</sort_order>
|
| 147 |
+
<source_model>ibstorepickup/source_selectorpayment</source_model>
|
| 148 |
+
<show_in_default>1</show_in_default>
|
| 149 |
+
<show_in_website>1</show_in_website>
|
| 150 |
+
<show_in_store>0</show_in_store>
|
| 151 |
+
<depends><accept>1</accept></depends>
|
| 152 |
+
</allowspecific_payment>
|
| 153 |
+
|
| 154 |
+
<specificpayment translate="label">
|
| 155 |
+
<label>Specific payments</label>
|
| 156 |
+
<frontend_type>multiselect</frontend_type>
|
| 157 |
+
<sort_order>110</sort_order>
|
| 158 |
+
<source_model>ibstorepickup/source_payment</source_model>
|
| 159 |
+
<show_in_default>1</show_in_default>
|
| 160 |
+
<show_in_website>1</show_in_website>
|
| 161 |
+
<show_in_store>0</show_in_store>
|
| 162 |
+
<depends><allowspecific_payment>1</allowspecific_payment></depends>
|
| 163 |
+
</specificpayment>
|
| 164 |
+
|
| 165 |
+
</fields>
|
| 166 |
+
</ibstorepickup>
|
| 167 |
+
</groups>
|
| 168 |
+
</carriers>
|
| 169 |
+
</sections>
|
| 170 |
+
</config>
|
app/code/local/IndaBox/StorePickup/sql/ibstorepickup_setup/install-0.1.0.php
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
$installer = $this;
|
| 4 |
+
|
| 5 |
+
$installer->startSetup();
|
| 6 |
+
|
| 7 |
+
$table = $installer->getConnection()
|
| 8 |
+
->newTable($installer->getTable('ibstorepickup/order_point'))
|
| 9 |
+
->addColumn('order_point_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
|
| 10 |
+
'identity' => true,
|
| 11 |
+
'unsigned' => true,
|
| 12 |
+
'nullable' => false,
|
| 13 |
+
'primary' => true,
|
| 14 |
+
), 'Order Point ID'
|
| 15 |
+
)
|
| 16 |
+
->addColumn('order_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
|
| 17 |
+
'unsigned' => true,
|
| 18 |
+
'nullable' => false,
|
| 19 |
+
'default' => '0',
|
| 20 |
+
), 'Order ID'
|
| 21 |
+
)
|
| 22 |
+
->addColumn('point_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
|
| 23 |
+
'unsigned' => true,
|
| 24 |
+
'nullable' => false,
|
| 25 |
+
'default' => '0',
|
| 26 |
+
), 'Point ID'
|
| 27 |
+
)
|
| 28 |
+
->addColumn('is_notified', Varien_Db_Ddl_Table::TYPE_BOOLEAN, null, array(
|
| 29 |
+
'nullable' => false,
|
| 30 |
+
'unsigned' => true,
|
| 31 |
+
'default' => '0',
|
| 32 |
+
), 'Is Notified Flag'
|
| 33 |
+
)
|
| 34 |
+
->addColumn('point_name', Varien_Db_Ddl_Table::TYPE_VARCHAR, null, array(
|
| 35 |
+
'nullable' => false,
|
| 36 |
+
'default' => '',
|
| 37 |
+
'length' => 255,
|
| 38 |
+
), 'Point Name'
|
| 39 |
+
)
|
| 40 |
+
->addColumn('point_address', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
|
| 41 |
+
'nullable' => false,
|
| 42 |
+
'default' => '',
|
| 43 |
+
), 'Point Address'
|
| 44 |
+
)
|
| 45 |
+
->addColumn('point_data', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
|
| 46 |
+
'nullable' => false,
|
| 47 |
+
'default' => '',
|
| 48 |
+
), 'Serialized Point Data'
|
| 49 |
+
)
|
| 50 |
+
->addIndex($installer->getIdxName('ibstorepickup/order_point', array('order_id')), array('order_id'))
|
| 51 |
+
->addIndex($installer->getIdxName('ibstorepickup/order_point', array('point_id')), array('point_id'))
|
| 52 |
+
->addForeignKey(
|
| 53 |
+
$installer->getFkName('ibstorepickup/order_point', 'order_id', 'sales/order', 'entity_id'),
|
| 54 |
+
'order_id', $installer->getTable('sales/order'), 'entity_id',
|
| 55 |
+
Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE
|
| 56 |
+
)
|
| 57 |
+
->setComment('Indabox Storepickup Order to Point')
|
| 58 |
+
;
|
| 59 |
+
$installer->getConnection()->createTable($table);
|
| 60 |
+
|
| 61 |
+
$installer->endSetup();
|
app/design/frontend/base/default/layout/ibstorepickup.xml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<layout version="0.1.0">
|
| 3 |
+
<default>
|
| 4 |
+
<reference name="head">
|
| 5 |
+
<action method="addJs"><script>indabox/storepickup.js</script></action>
|
| 6 |
+
<action method="addItem"><type>skin_css</type><name>indabox/css/storepickup.css</name></action>
|
| 7 |
+
</reference>
|
| 8 |
+
</default>
|
| 9 |
+
|
| 10 |
+
<!--checkout_cart_index>
|
| 11 |
+
<reference name="checkout.cart.shipping">
|
| 12 |
+
<action method="setTemplate"><template>storepickup/shippingtax.phtml</template></action>
|
| 13 |
+
<block type="storepickup/storepickup" name="storepickup" as="storepickup" >
|
| 14 |
+
<block type="storepickup/location" name="store_location" as="store_location" template="storepickup/store_location.phtml" />
|
| 15 |
+
<block type="storepickup/storepickup" name="list_store" as="list_store" template="storepickup/store.phtml" />
|
| 16 |
+
</block>
|
| 17 |
+
</reference>
|
| 18 |
+
</checkout_cart_index-->
|
| 19 |
+
|
| 20 |
+
<checkout_onepage_index>
|
| 21 |
+
<reference name="head">
|
| 22 |
+
<action method="addJs"><script>indabox/markerclusterer.js</script></action>
|
| 23 |
+
</reference>
|
| 24 |
+
<reference name="checkout.onepage.billing">
|
| 25 |
+
<action method="setTemplate"><template>ibstorepickup/checkout/onepage/billing.phtml</template></action>
|
| 26 |
+
</reference>
|
| 27 |
+
</checkout_onepage_index>
|
| 28 |
+
|
| 29 |
+
</layout>
|
app/design/frontend/base/default/template/ibstorepickup/checkout/onepage/billing.phtml
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* Magento
|
| 4 |
+
*
|
| 5 |
+
* NOTICE OF LICENSE
|
| 6 |
+
*
|
| 7 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
| 8 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
| 9 |
+
* It is also available through the world-wide-web at this URL:
|
| 10 |
+
* http://opensource.org/licenses/afl-3.0.php
|
| 11 |
+
* If you did not receive a copy of the license and are unable to
|
| 12 |
+
* obtain it through the world-wide-web, please send an email
|
| 13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
| 14 |
+
*
|
| 15 |
+
* DISCLAIMER
|
| 16 |
+
*
|
| 17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
| 18 |
+
* versions in the future. If you wish to customize Magento for your
|
| 19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
| 20 |
+
*
|
| 21 |
+
* @category design
|
| 22 |
+
* @package base_default
|
| 23 |
+
* @copyright Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)
|
| 24 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
| 25 |
+
*/
|
| 26 |
+
?>
|
| 27 |
+
<form id="co-billing-form" action="">
|
| 28 |
+
<fieldset>
|
| 29 |
+
<ul class="form-list">
|
| 30 |
+
<?php if ($this->customerHasAddresses()): ?>
|
| 31 |
+
<li class="wide">
|
| 32 |
+
<label for="billing-address-select"><?php echo $this->__('Select a billing address from your address book or enter a new address.') ?></label>
|
| 33 |
+
<div class="input-box">
|
| 34 |
+
<?php echo $this->getAddressesHtmlSelect('billing') ?>
|
| 35 |
+
</div>
|
| 36 |
+
</li>
|
| 37 |
+
<?php endif; ?>
|
| 38 |
+
<li id="billing-new-address-form"<?php if ($this->customerHasAddresses()): ?> style="display:none;"<?php endif; ?>>
|
| 39 |
+
<fieldset>
|
| 40 |
+
<input type="hidden" name="billing[address_id]" value="<?php echo $this->getAddress()->getId() ?>" id="billing:address_id" />
|
| 41 |
+
<ul>
|
| 42 |
+
<li class="fields"><?php echo $this->getLayout()->createBlock('customer/widget_name')->setObject($this->getAddress()->getFirstname() ? $this->getAddress() : $this->getQuote()->getCustomer())->setForceUseCustomerRequiredAttributes(!$this->isCustomerLoggedIn())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?></li>
|
| 43 |
+
<li class="fields">
|
| 44 |
+
<div class="field">
|
| 45 |
+
<label for="billing:company"><?php echo $this->__('Company') ?></label>
|
| 46 |
+
<div class="input-box">
|
| 47 |
+
<input type="text" id="billing:company" name="billing[company]" value="<?php echo $this->escapeHtml($this->getAddress()->getCompany()) ?>" title="<?php echo $this->__('Company') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('company') ?>" />
|
| 48 |
+
</div>
|
| 49 |
+
</div>
|
| 50 |
+
<?php if(!$this->isCustomerLoggedIn()): ?>
|
| 51 |
+
<div class="field">
|
| 52 |
+
<label for="billing:email" class="required"><em>*</em><?php echo $this->__('Email Address') ?></label>
|
| 53 |
+
<div class="input-box">
|
| 54 |
+
<input type="text" name="billing[email]" id="billing:email" value="<?php echo $this->escapeHtml($this->getAddress()->getEmail()) ?>" title="<?php echo $this->__('Email Address') ?>" class="input-text validate-email required-entry" />
|
| 55 |
+
</div>
|
| 56 |
+
</div>
|
| 57 |
+
<?php endif; ?>
|
| 58 |
+
</li>
|
| 59 |
+
<?php $_streetValidationClass = $this->helper('customer/address')->getAttributeValidationClass('street'); ?>
|
| 60 |
+
<li class="wide">
|
| 61 |
+
<label for="billing:street1" class="required"><em>*</em><?php echo $this->__('Address') ?></label>
|
| 62 |
+
<div class="input-box">
|
| 63 |
+
<input type="text" title="<?php echo $this->__('Street Address') ?>" name="billing[street][]" id="billing:street1" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet(1)) ?>" class="input-text <?php echo $_streetValidationClass ?>" />
|
| 64 |
+
</div>
|
| 65 |
+
</li>
|
| 66 |
+
<?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?>
|
| 67 |
+
<?php for ($_i = 2, $_n = $this->helper('customer/address')->getStreetLines(); $_i <= $_n; $_i++): ?>
|
| 68 |
+
<li class="wide">
|
| 69 |
+
<div class="input-box">
|
| 70 |
+
<input type="text" title="<?php echo $this->__('Street Address %s', $_i) ?>" name="billing[street][]" id="billing:street<?php echo $_i ?>" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet($_i)) ?>" class="input-text <?php echo $_streetValidationClass ?>" />
|
| 71 |
+
</div>
|
| 72 |
+
</li>
|
| 73 |
+
<?php endfor; ?>
|
| 74 |
+
<?php if ($this->helper('customer/address')->isVatAttributeVisible()) : ?>
|
| 75 |
+
<li class="wide">
|
| 76 |
+
<label for="billing:vat_id"><?php echo $this->__('VAT Number') ?></label>
|
| 77 |
+
<div class="input-box">
|
| 78 |
+
<input type="text" id="billing:vat_id" name="billing[vat_id]" value="<?php echo $this->escapeHtml($this->getAddress()->getVatId()) ?>" title="<?php echo $this->__('VAT Number') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('vat_id') ?>" />
|
| 79 |
+
</div>
|
| 80 |
+
</li>
|
| 81 |
+
<?php endif; ?>
|
| 82 |
+
<li class="fields">
|
| 83 |
+
<div class="field">
|
| 84 |
+
<label for="billing:city" class="required"><em>*</em><?php echo $this->__('City') ?></label>
|
| 85 |
+
<div class="input-box">
|
| 86 |
+
<input type="text" title="<?php echo $this->__('City') ?>" name="billing[city]" value="<?php echo $this->escapeHtml($this->getAddress()->getCity()) ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('city') ?>" id="billing:city" />
|
| 87 |
+
</div>
|
| 88 |
+
</div>
|
| 89 |
+
<div class="field">
|
| 90 |
+
<label for="billing:region_id" class="required"><em>*</em><?php echo $this->__('State/Province') ?></label>
|
| 91 |
+
<div class="input-box">
|
| 92 |
+
<select id="billing:region_id" name="billing[region_id]" title="<?php echo $this->__('State/Province') ?>" class="validate-select" style="display:none;">
|
| 93 |
+
<option value=""><?php echo $this->__('Please select region, state or province') ?></option>
|
| 94 |
+
</select>
|
| 95 |
+
<script type="text/javascript">
|
| 96 |
+
//<![CDATA[
|
| 97 |
+
$('billing:region_id').setAttribute('defaultValue', "<?php echo $this->getAddress()->getRegionId() ?>");
|
| 98 |
+
//]]>
|
| 99 |
+
</script>
|
| 100 |
+
<input type="text" id="billing:region" name="billing[region]" value="<?php echo $this->escapeHtml($this->getAddress()->getRegion()) ?>" title="<?php echo $this->__('State/Province') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('region') ?>" style="display:none;" />
|
| 101 |
+
</div>
|
| 102 |
+
</div>
|
| 103 |
+
</li>
|
| 104 |
+
<li class="fields">
|
| 105 |
+
<div class="field">
|
| 106 |
+
<label for="billing:postcode" class="required"><em>*</em><?php echo $this->__('Zip/Postal Code') ?></label>
|
| 107 |
+
<div class="input-box">
|
| 108 |
+
<input type="text" title="<?php echo $this->__('Zip/Postal Code') ?>" name="billing[postcode]" id="billing:postcode" value="<?php echo $this->escapeHtml($this->getAddress()->getPostcode()) ?>" class="input-text validate-zip-international <?php echo $this->helper('customer/address')->getAttributeValidationClass('postcode') ?>" />
|
| 109 |
+
</div>
|
| 110 |
+
</div>
|
| 111 |
+
<div class="field">
|
| 112 |
+
<label for="billing:country_id" class="required"><em>*</em><?php echo $this->__('Country') ?></label>
|
| 113 |
+
<div class="input-box">
|
| 114 |
+
<?php echo $this->getCountryHtmlSelect('billing') ?>
|
| 115 |
+
</div>
|
| 116 |
+
</div>
|
| 117 |
+
</li>
|
| 118 |
+
<li class="fields">
|
| 119 |
+
<div class="field">
|
| 120 |
+
<label for="billing:telephone" class="required"><em>*</em><?php echo $this->__('Telephone') ?></label>
|
| 121 |
+
<div class="input-box">
|
| 122 |
+
<input type="text" name="billing[telephone]" value="<?php echo $this->escapeHtml($this->getAddress()->getTelephone()) ?>" title="<?php echo $this->__('Telephone') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('telephone') ?>" id="billing:telephone" />
|
| 123 |
+
</div>
|
| 124 |
+
</div>
|
| 125 |
+
<div class="field">
|
| 126 |
+
<label for="billing:fax"><?php echo $this->__('Fax') ?></label>
|
| 127 |
+
<div class="input-box">
|
| 128 |
+
<input type="text" name="billing[fax]" value="<?php echo $this->escapeHtml($this->getAddress()->getFax()) ?>" title="<?php echo $this->__('Fax') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('fax') ?>" id="billing:fax" />
|
| 129 |
+
</div>
|
| 130 |
+
</div>
|
| 131 |
+
</li>
|
| 132 |
+
<?php if(!$this->isCustomerLoggedIn()): ?>
|
| 133 |
+
|
| 134 |
+
<?php $_dob = $this->getLayout()->createBlock('customer/widget_dob') ?>
|
| 135 |
+
<?php $_gender = $this->getLayout()->createBlock('customer/widget_gender') ?>
|
| 136 |
+
<?php if ($_dob->isEnabled() || $_gender->isEnabled()): ?>
|
| 137 |
+
<li class="fields">
|
| 138 |
+
<?php if ($_dob->isEnabled()): ?>
|
| 139 |
+
<div class="field">
|
| 140 |
+
<?php echo $_dob->setDate($this->getQuote()->getCustomerDob())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
|
| 141 |
+
</div>
|
| 142 |
+
<?php endif; ?>
|
| 143 |
+
<?php if ($_gender->isEnabled()): ?>
|
| 144 |
+
<div class="field">
|
| 145 |
+
<?php echo $_gender->setGender($this->getQuote()->getCustomerGender())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
|
| 146 |
+
</div>
|
| 147 |
+
<?php endif ?>
|
| 148 |
+
</li>
|
| 149 |
+
<?php endif ?>
|
| 150 |
+
|
| 151 |
+
<?php $_taxvat = $this->getLayout()->createBlock('customer/widget_taxvat') ?>
|
| 152 |
+
<?php if ($_taxvat->isEnabled()): ?>
|
| 153 |
+
<li>
|
| 154 |
+
<?php echo $_taxvat->setTaxvat($this->getQuote()->getCustomerTaxvat())->setFieldIdFormat('billing:%s')->setFieldNameFormat('billing[%s]')->toHtml() ?>
|
| 155 |
+
</li>
|
| 156 |
+
<?php endif ?>
|
| 157 |
+
|
| 158 |
+
<li class="fields" id="register-customer-password">
|
| 159 |
+
<div class="field">
|
| 160 |
+
<label for="billing:customer_password" class="required"><em>*</em><?php echo $this->__('Password') ?></label>
|
| 161 |
+
<div class="input-box">
|
| 162 |
+
<input type="password" name="billing[customer_password]" id="billing:customer_password" title="<?php echo $this->__('Password') ?>" class="input-text required-entry validate-password" />
|
| 163 |
+
</div>
|
| 164 |
+
</div>
|
| 165 |
+
<div class="field">
|
| 166 |
+
<label for="billing:confirm_password" class="required"><em>*</em><?php echo $this->__('Confirm Password') ?></label>
|
| 167 |
+
<div class="input-box">
|
| 168 |
+
<input type="password" name="billing[confirm_password]" title="<?php echo $this->__('Confirm Password') ?>" id="billing:confirm_password" class="input-text required-entry validate-cpassword" />
|
| 169 |
+
</div>
|
| 170 |
+
</div>
|
| 171 |
+
</li>
|
| 172 |
+
<?php endif; ?>
|
| 173 |
+
<?php if ($this->isCustomerLoggedIn() && $this->customerHasAddresses()):?>
|
| 174 |
+
<li class="control">
|
| 175 |
+
<input type="checkbox" name="billing[save_in_address_book]" value="1" title="<?php echo $this->__('Save in address book') ?>" id="billing:save_in_address_book" onchange="if(window.shipping) shipping.setSameAsBilling(false);"<?php if ($this->getAddress()->getSaveInAddressBook()):?> checked="checked"<?php endif;?> class="checkbox" /><label for="billing:save_in_address_book"><?php echo $this->__('Save in address book') ?></label>
|
| 176 |
+
</li>
|
| 177 |
+
<?php else:?>
|
| 178 |
+
<li class="no-display"><input type="hidden" name="billing[save_in_address_book]" value="1" /></li>
|
| 179 |
+
<?php endif; ?>
|
| 180 |
+
<?php echo $this->getChildHtml('form.additional.info'); ?>
|
| 181 |
+
</ul>
|
| 182 |
+
</fieldset>
|
| 183 |
+
</li>
|
| 184 |
+
<?php /* Extensions placeholder */ ?>
|
| 185 |
+
<?php echo $this->getChildHtml('checkout.onepage.billing.extra')?>
|
| 186 |
+
<?php if ($this->canShip()): ?>
|
| 187 |
+
<li class="control">
|
| 188 |
+
<input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_yes" value="1"<?php if ($this->isUseBillingAddressForShipping()) {?> checked="checked"<?php }?> title="<?php echo $this->__('Ship to this address') ?>" onclick="$('shipping:same_as_billing').checked = true;" class="radio" /><label for="billing:use_for_shipping_yes"><?php echo $this->__('Ship to this address') ?></label></li>
|
| 189 |
+
<li class="control">
|
| 190 |
+
<input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_no" value="0"<?php if (!$this->isUseBillingAddressForShipping()) {?> checked="checked"<?php }?> title="<?php echo $this->__('Ship to different address') ?>" onclick="$('shipping:same_as_billing').checked = false;" class="radio" /><label for="billing:use_for_shipping_no"><?php echo $this->__('Ship to different address') ?></label>
|
| 191 |
+
</li>
|
| 192 |
+
<?php if (Mage::getStoreConfig('carriers/ibstorepickup/active') && Mage::getStoreConfig('carriers/ibstorepickup/accept')) : ?>
|
| 193 |
+
<li class="control">
|
| 194 |
+
<input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_point" value="1"<?php if (Mage::helper('ibstorepickup')->getUseMethod()) : ?> checked="checked" <?php endif ?> onclick="$('shipping:same_as_billing').checked = true;" class="radio" />
|
| 195 |
+
<label for="billing:use_for_shipping_point"><?php echo $this->__('IndaBox Store Pickup') ?></label>
|
| 196 |
+
</li>
|
| 197 |
+
<?php endif ?>
|
| 198 |
+
<?php endif; ?>
|
| 199 |
+
</ul>
|
| 200 |
+
<?php if (!$this->canShip()): ?>
|
| 201 |
+
<input type="hidden" name="billing[use_for_shipping]" value="1" />
|
| 202 |
+
<?php endif; ?>
|
| 203 |
+
<div class="buttons-set" id="billing-buttons-container">
|
| 204 |
+
<p class="required"><?php echo $this->__('* Required Fields') ?></p>
|
| 205 |
+
<button type="button" title="<?php echo $this->__('Continue') ?>" class="button" onclick="billing.save()"><span><span><?php echo $this->__('Continue') ?></span></span></button>
|
| 206 |
+
<span class="please-wait" id="billing-please-wait" style="display:none;">
|
| 207 |
+
<img src="<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif') ?>" alt="<?php echo $this->__('Loading next step...') ?>" title="<?php echo $this->__('Loading next step...') ?>" class="v-middle" /> <?php echo $this->__('Loading next step...') ?>
|
| 208 |
+
</span>
|
| 209 |
+
</div>
|
| 210 |
+
</fieldset>
|
| 211 |
+
</form>
|
| 212 |
+
<script type="text/javascript">
|
| 213 |
+
//<![CDATA[
|
| 214 |
+
var billing = new Billing('co-billing-form', '<?php echo $this->getUrl('checkout/onepage/getAddress') ?>address/', '<?php echo $this->getUrl('checkout/onepage/saveBilling') ?>');
|
| 215 |
+
var billingForm = new VarienForm('co-billing-form');
|
| 216 |
+
|
| 217 |
+
//billingForm.setElementsRelation('billing:country_id', 'billing:region', '<?php echo $this->getUrl('directory/json/childRegion') ?>', '<?php echo $this->__('Select State/Province...') ?>');
|
| 218 |
+
$('billing-address-select') && billing.newAddress(!$('billing-address-select').value);
|
| 219 |
+
|
| 220 |
+
var billingRegionUpdater = new RegionUpdater('billing:country_id', 'billing:region', 'billing:region_id', <?php echo $this->helper('directory')->getRegionJson() ?>, undefined, 'billing:postcode');
|
| 221 |
+
//]]>
|
| 222 |
+
</script>
|
| 223 |
+
<?php if ($this->canShip() && Mage::getStoreConfig('carriers/ibstorepickup/active')): ?>
|
| 224 |
+
<script type="text/javascript">
|
| 225 |
+
//<![CDATA[
|
| 226 |
+
var ibStorePickup = new IndaboxStorePickup(
|
| 227 |
+
'<?php echo Mage::helper('ibstorepickup')->getChangeMethodUrl(); ?>',
|
| 228 |
+
'<?php echo Mage::helper('ibstorepickup')->getSearchUrl(); ?>',
|
| 229 |
+
'<?php echo Mage::helper('ibstorepickup')->getLocationUrl(); ?>',
|
| 230 |
+
'<?php echo Mage::helper('ibstorepickup')->getMediaUrl(); ?>'
|
| 231 |
+
);
|
| 232 |
+
|
| 233 |
+
Event.observe('billing:use_for_shipping_point', 'click', function(event){
|
| 234 |
+
ibStorePickup.setUseStorePickup(true);
|
| 235 |
+
});
|
| 236 |
+
|
| 237 |
+
Event.observe('billing:use_for_shipping_yes', 'click', function(event){
|
| 238 |
+
ibStorePickup.setUseStorePickup(false);
|
| 239 |
+
});
|
| 240 |
+
|
| 241 |
+
Event.observe('billing:use_for_shipping_no', 'click', function(event){
|
| 242 |
+
ibStorePickup.setUseStorePickup(false);
|
| 243 |
+
});
|
| 244 |
+
//]]>
|
| 245 |
+
</script>
|
| 246 |
+
<?php endif ?>
|
app/design/frontend/base/default/template/ibstorepickup/map.phtml
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div class="indabox">
|
| 2 |
+
<div id="indabox_conditions">
|
| 3 |
+
<iframe src="<?php echo $this->getTosUrl() ?>">
|
| 4 |
+
<p><?php echo $this->__('Your browser does not support iframes.') ?></p>
|
| 5 |
+
</iframe>
|
| 6 |
+
<div style="clear: both"></div>
|
| 7 |
+
<p class="checkbox">
|
| 8 |
+
<input type="checkbox" name="indabox_accept_terms" id="indabox_accept_terms" value="1" autocomplete="off" class="required" />
|
| 9 |
+
<label for="indabox_accept_terms"><?php echo $this->__('I accept IndaBox terms and conditions') ?></label>
|
| 10 |
+
</p>
|
| 11 |
+
</div>
|
| 12 |
+
<div id="indabox_map" style="display: none;">
|
| 13 |
+
<h3><?php echo $this->__('Search for pick-up points') ?></h3>
|
| 14 |
+
<p><?php echo $this->__('You are viewing the collection points closest to the address below. If you want, you can enter a different address.') ?></p>
|
| 15 |
+
<div class="address">
|
| 16 |
+
<input type="text" id="indabox_search_address" value="<?php echo $this->htmlEscape($this->getBillingAddress()) ?>" size="50" />
|
| 17 |
+
<label for="indabox_search_radius"><?php echo $this->__('Radius') ?></label>
|
| 18 |
+
<select id="indabox_search_radius">
|
| 19 |
+
<option value="1">1 km</option>
|
| 20 |
+
<option value="3" selected="selected">3 km</option>
|
| 21 |
+
<option value="10">10 km</option>
|
| 22 |
+
<option value="30">30 km</option>
|
| 23 |
+
<option value="50">50 km</option>
|
| 24 |
+
</select>
|
| 25 |
+
<button id="indabox_search" class="button"><span><span><?php echo $this->__('Search') ?></span></span></button>
|
| 26 |
+
<img src="<?php echo $this->getSkinUrl('indabox/images/opc-ajax-loader.gif') ?>" alt="<?php echo $this->__('Loading') ?>" />
|
| 27 |
+
</div>
|
| 28 |
+
<div id="indabox_google_map"></div>
|
| 29 |
+
</div>
|
| 30 |
+
<div id="indabox_point" style="display: none;">
|
| 31 |
+
<input type="hidden" name="indabox_point_id" id="indabox_point_id" value="0" />
|
| 32 |
+
<h3><?php echo $this->__('Selected pick-up point') ?></h3>
|
| 33 |
+
<h5 id="indabox_point_name"></h5>
|
| 34 |
+
<p id="indabox_point_address"></p>
|
| 35 |
+
</div>
|
| 36 |
+
</div>
|
| 37 |
+
<script type="text/javascript">
|
| 38 |
+
//<![CDATA[
|
| 39 |
+
|
| 40 |
+
Event.observe('indabox_accept_terms', 'click', function (event) {
|
| 41 |
+
$('indabox_conditions').hide();
|
| 42 |
+
$('indabox_map').show();
|
| 43 |
+
|
| 44 |
+
ibStorePickup.initGoogleMap('<?php echo $this->getGoogleMaps() ?>', 'indabox_google_map');
|
| 45 |
+
ibStorePickup.onInit = function () {
|
| 46 |
+
ibStorePickup.search($('indabox_search_address').value, $('indabox_search_radius').value);
|
| 47 |
+
};
|
| 48 |
+
ibStorePickup.onSearchStart = function () {
|
| 49 |
+
$('indabox_search').addClassName('in-progress').addClassName('disabled');
|
| 50 |
+
};
|
| 51 |
+
ibStorePickup.onSearchEnd = function (points) {
|
| 52 |
+
$('indabox_search').removeClassName('in-progress').removeClassName('disabled');
|
| 53 |
+
if ( ! points.length)
|
| 54 |
+
alert('<?php echo $this->__('No points found around given location') ?>');
|
| 55 |
+
};
|
| 56 |
+
ibStorePickup.onSelectPoint = function (point) {
|
| 57 |
+
$('indabox_point').show();
|
| 58 |
+
$('indabox_point_id').value = point.id;
|
| 59 |
+
$('indabox_point_name').innerHTML = point.name;
|
| 60 |
+
$('indabox_point_address').innerHTML = point.street
|
| 61 |
+
+ '<br />' + point.postcode
|
| 62 |
+
+ ' ' + point.city
|
| 63 |
+
+ ' ' + point.region
|
| 64 |
+
//+ ' ' + point.country_id
|
| 65 |
+
;
|
| 66 |
+
};
|
| 67 |
+
});
|
| 68 |
+
|
| 69 |
+
Event.observe('indabox_search', 'click', function (event) {
|
| 70 |
+
event.preventDefault();
|
| 71 |
+
if ($(this).hasClassName('in-progress')) {
|
| 72 |
+
alert('<?php echo $this->__('Another search is already running') ?>');
|
| 73 |
+
return;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
ibStorePickup.search($('indabox_search_address').value, $('indabox_search_radius').value);
|
| 77 |
+
});
|
| 78 |
+
//]]>
|
| 79 |
+
</script>
|
app/etc/modules/IndaBox_StorePickup.xml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<config>
|
| 3 |
+
<modules>
|
| 4 |
+
<IndaBox_StorePickup>
|
| 5 |
+
<active>true</active>
|
| 6 |
+
<codePool>local</codePool>
|
| 7 |
+
</IndaBox_StorePickup>
|
| 8 |
+
</modules>
|
| 9 |
+
</config>
|
app/locale/en_US/IndaBox_StorePickup.csv
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"IndaBox","IndaBox"
|
| 2 |
+
"Title","Title"
|
| 3 |
+
"Cost","Cost"
|
| 4 |
+
"Maximum Subtotal","Maximum Subtotal"
|
| 5 |
+
"Maximum Weight","Maximum Weight"
|
| 6 |
+
"Terms and Conditions Url","Terms and Conditions Url"
|
| 7 |
+
"Google Maps API Key","Google Maps API Key"
|
| 8 |
+
"Applicable payments","Applicable payments"
|
| 9 |
+
"Specific payments","Specific payments"
|
| 10 |
+
"Point","Point"
|
| 11 |
+
"Please specify Merchant ID","Please specify Merchant ID"
|
| 12 |
+
"Please specify API Key","Please specify API Key"
|
| 13 |
+
"Could not communicate with server","Could not communicate with server"
|
| 14 |
+
"Invalid server reply","Invalid server reply"
|
| 15 |
+
"Could not submit order","Could not submit order"
|
| 16 |
+
"All Allowed Payments","All Allowed Payments"
|
| 17 |
+
"Specific Payments","Specific Payments"
|
| 18 |
+
"Invalid search parameters.","Invalid search parameters."
|
| 19 |
+
"Error while communicating with IndaBox. Please retry later.","Error while communicating with IndaBox. Please retry later."
|
| 20 |
+
"Location does not found","Location does not found"
|
| 21 |
+
"Your browser does not support iframes.","Your browser does not support iframes."
|
| 22 |
+
"I accept IndaBox terms and conditions","I accept IndaBox terms and conditions"
|
| 23 |
+
"Search for pick-up points","Search for pick-up points"
|
| 24 |
+
"You are viewing the collection points closest to the address below. If you want, you can enter a different address.","You are viewing the collection points closest to the address below. If you want, you can enter a different address."
|
| 25 |
+
"Radius","Radius"
|
| 26 |
+
"Loading","Loading"
|
| 27 |
+
"Selected pick-up point","Selected pick-up point"
|
| 28 |
+
"No points found around given location","No points found around given location"
|
| 29 |
+
"Another search is already running","Another search is already running"
|
| 30 |
+
"IndaBox Store Pickup","IndaBox Store Pickup"
|
| 31 |
+
"You should accept IndaBox terms and conditions","You should accept IndaBox terms and conditions"
|
| 32 |
+
"You should select one of available pick-up points to continue","You should select one of available pick-up points to continue"
|
| 33 |
+
"Distance","Distance"
|
| 34 |
+
"Select this pick-up point","Select this pick-up point"
|
| 35 |
+
"I accept <a href=""http://www.indabox.it/termini-eco/"" target=""_blank"">IndaBox Terms of Service</a>","I accept <a href=""http://www.indabox.it/termini-eco/"" target=""_blank"">IndaBox Terms of Service</a>"
|
| 36 |
+
"Accept TOS","Accept TOS"
|
| 37 |
+
"IndaBox Point","IndaBox Point"
|
| 38 |
+
"For all the information on installing and configuring the module and IndaBox Merchant Account, you can refer to <a href=""%s"" target=""_blank"">this page</a>","For all the information on installing and configuring the module and IndaBox Merchant Account, you can refer to <a href=""%s"" target=""_blank"">this page</a>"
|
app/locale/it_IT/IndaBox_StorePickup.csv
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"IndaBox","IndaBox"
|
| 2 |
+
"Title","Titolo"
|
| 3 |
+
"Cost","Costo"
|
| 4 |
+
"Maximum Subtotal","Subtotale Massimo"
|
| 5 |
+
"Maximum Weight","Peso Massimo"
|
| 6 |
+
"Terms and Conditions Url","Url Termini e Condizioni"
|
| 7 |
+
"Google Maps API Key","Chiave API Google Maps"
|
| 8 |
+
"Applicable payments","Pagamenti Applicabili"
|
| 9 |
+
"Point","Punto"
|
| 10 |
+
"Please specify Merchant ID","Specificare il Merchant ID"
|
| 11 |
+
"Please specify API Key","Specificare l´API Key"
|
| 12 |
+
"Could not communicate with server","Impossibile comunicare col server"
|
| 13 |
+
"Invalid server reply","Risposta server non valida"
|
| 14 |
+
"Could not submit order","Non è stato possibile inviare l´ordine."
|
| 15 |
+
"All Allowed Payments","Tutti i Pagamenti Consentiti"
|
| 16 |
+
"Specific Payments","Specifici Pagamenti"
|
| 17 |
+
"Invalid search parameters.","Parametri di ricerca non validi."
|
| 18 |
+
"Error while communicating with IndaBox. Please retry later.","Si è verificato un errore durante la comunicazione con IndaBox. Riprovare a breve."
|
| 19 |
+
"Location does not found","Location non trovata"
|
| 20 |
+
"Your browser does not support iframes.","Il tuo browser non supporta gli iframe."
|
| 21 |
+
"Loading","Caricando"
|
| 22 |
+
"No points found around given location","Non è stato trovato alcun punto IndaBox nelle vicinanze della location inserita."
|
| 23 |
+
"Another search is already running","Vi è già un´altra ricerca in corso."
|
| 24 |
+
"You should accept IndaBox terms and conditions","E´ necessario accettare i termini e condizioni IndaBox"
|
| 25 |
+
"Distance","Distanza"
|
| 26 |
+
"Selected pick-up point","Hai selezionato il seguente punto di ritiro"
|
| 27 |
+
"You should select one of available pick-up points to continue","Selezionare un punto di ritiro dalla mappa prima di continuare"
|
| 28 |
+
"Select this pick-up point","Seleziona questo punto di ritiro"
|
| 29 |
+
"Radius","Raggio"
|
| 30 |
+
"IndaBox Store Pickup","Ricevi il tuo acquisto in uno dei punti di ritiro IndaBox (<a target=""_blank"" href=""http://www.indabox.it"">www.indabox.it</a>)"
|
| 31 |
+
"I accept IndaBox terms and conditions","Accetto i termini di utilizzo del servizio indicati"
|
| 32 |
+
"Search for pick-up points","Cerca un punto di ritiro"
|
| 33 |
+
"You are viewing the collection points closest to the address below. If you want, you can enter a different address.","Stai visualizzando i punti di ritiro vicini al seguente indirizzo. <br/>Se vuoi, puoi inserire un indirizzo differente."
|
| 34 |
+
"I accept <a href=""http://www.indabox.it/termini-eco/"" target=""_blank"">IndaBox Terms of Service</a>","Accetto <a href=""http://www.indabox.it/termini-eco/"" target=""_blank"">IndaBox Termini di Servizio</a>"
|
| 35 |
+
"Accept TOS","Accettare Termini di Servizio"
|
| 36 |
+
"IndaBox Point","IndaBox Point"
|
| 37 |
+
"For all the information on installing and configuring the module and IndaBox Merchant Account, you can refer to <a href=""%s"" target=""_blank"">this page</a>","Per tutte le informazioni sull´installazione e la configurazione del modulo e IndaBox Merchant Account, è possibile fare riferimento a <a href=""%s"" target=""_blank"">questa pagina</a>"
|
| 38 |
+
|
js/indabox/markerclusterer.js
ADDED
|
@@ -0,0 +1,1310 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ==ClosureCompiler==
|
| 2 |
+
// @compilation_level ADVANCED_OPTIMIZATIONS
|
| 3 |
+
// @externs_url http://closure-compiler.googlecode.com/svn/trunk/contrib/externs/maps/google_maps_api_v3_3.js
|
| 4 |
+
// ==/ClosureCompiler==
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* @name MarkerClusterer for Google Maps v3
|
| 8 |
+
* @version version 1.0.1
|
| 9 |
+
* @author Luke Mahe
|
| 10 |
+
* @fileoverview
|
| 11 |
+
* The library creates and manages per-zoom-level clusters for large amounts of
|
| 12 |
+
* markers.
|
| 13 |
+
* <br/>
|
| 14 |
+
* This is a v3 implementation of the
|
| 15 |
+
* <a href="http://gmaps-utility-library-dev.googlecode.com/svn/tags/markerclusterer/"
|
| 16 |
+
* >v2 MarkerClusterer</a>.
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
| 21 |
+
* you may not use this file except in compliance with the License.
|
| 22 |
+
* You may obtain a copy of the License at
|
| 23 |
+
*
|
| 24 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
| 25 |
+
*
|
| 26 |
+
* Unless required by applicable law or agreed to in writing, software
|
| 27 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
| 28 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 29 |
+
* See the License for the specific language governing permissions and
|
| 30 |
+
* limitations under the License.
|
| 31 |
+
*/
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
/**
|
| 35 |
+
* A Marker Clusterer that clusters markers.
|
| 36 |
+
*
|
| 37 |
+
* @param {google.maps.Map} map The Google map to attach to.
|
| 38 |
+
* @param {Array.<google.maps.Marker>=} opt_markers Optional markers to add to
|
| 39 |
+
* the cluster.
|
| 40 |
+
* @param {Object=} opt_options support the following options:
|
| 41 |
+
* 'gridSize': (number) The grid size of a cluster in pixels.
|
| 42 |
+
* 'maxZoom': (number) The maximum zoom level that a marker can be part of a
|
| 43 |
+
* cluster.
|
| 44 |
+
* 'zoomOnClick': (boolean) Whether the default behaviour of clicking on a
|
| 45 |
+
* cluster is to zoom into it.
|
| 46 |
+
* 'averageCenter': (boolean) Wether the center of each cluster should be
|
| 47 |
+
* the average of all markers in the cluster.
|
| 48 |
+
* 'minimumClusterSize': (number) The minimum number of markers to be in a
|
| 49 |
+
* cluster before the markers are hidden and a count
|
| 50 |
+
* is shown.
|
| 51 |
+
* 'styles': (object) An object that has style properties:
|
| 52 |
+
* 'url': (string) The image url.
|
| 53 |
+
* 'height': (number) The image height.
|
| 54 |
+
* 'width': (number) The image width.
|
| 55 |
+
* 'anchor': (Array) The anchor position of the label text.
|
| 56 |
+
* 'textColor': (string) The text color.
|
| 57 |
+
* 'textSize': (number) The text size.
|
| 58 |
+
* 'backgroundPosition': (string) The position of the backgound x, y.
|
| 59 |
+
* @constructor
|
| 60 |
+
* @extends google.maps.OverlayView
|
| 61 |
+
*/
|
| 62 |
+
function MarkerClusterer(map, opt_markers, opt_options) {
|
| 63 |
+
// MarkerClusterer implements google.maps.OverlayView interface. We use the
|
| 64 |
+
// extend function to extend MarkerClusterer with google.maps.OverlayView
|
| 65 |
+
// because it might not always be available when the code is defined so we
|
| 66 |
+
// look for it at the last possible moment. If it doesn't exist now then
|
| 67 |
+
// there is no point going ahead :)
|
| 68 |
+
this.extend(MarkerClusterer, google.maps.OverlayView);
|
| 69 |
+
this.map_ = map;
|
| 70 |
+
|
| 71 |
+
/**
|
| 72 |
+
* @type {Array.<google.maps.Marker>}
|
| 73 |
+
* @private
|
| 74 |
+
*/
|
| 75 |
+
this.markers_ = [];
|
| 76 |
+
|
| 77 |
+
/**
|
| 78 |
+
* @type {Array.<Cluster>}
|
| 79 |
+
*/
|
| 80 |
+
this.clusters_ = [];
|
| 81 |
+
|
| 82 |
+
this.sizes = [53, 56, 66, 78, 90];
|
| 83 |
+
|
| 84 |
+
/**
|
| 85 |
+
* @private
|
| 86 |
+
*/
|
| 87 |
+
this.styles_ = [];
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* @type {boolean}
|
| 91 |
+
* @private
|
| 92 |
+
*/
|
| 93 |
+
this.ready_ = false;
|
| 94 |
+
|
| 95 |
+
var options = opt_options || {};
|
| 96 |
+
|
| 97 |
+
/**
|
| 98 |
+
* @type {number}
|
| 99 |
+
* @private
|
| 100 |
+
*/
|
| 101 |
+
this.gridSize_ = options['gridSize'] || 60;
|
| 102 |
+
|
| 103 |
+
/**
|
| 104 |
+
* @private
|
| 105 |
+
*/
|
| 106 |
+
this.minClusterSize_ = options['minimumClusterSize'] || 2;
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
/**
|
| 110 |
+
* @type {?number}
|
| 111 |
+
* @private
|
| 112 |
+
*/
|
| 113 |
+
this.maxZoom_ = options['maxZoom'] || null;
|
| 114 |
+
|
| 115 |
+
this.styles_ = options['styles'] || [];
|
| 116 |
+
|
| 117 |
+
/**
|
| 118 |
+
* @type {string}
|
| 119 |
+
* @private
|
| 120 |
+
*/
|
| 121 |
+
this.imagePath_ = options['imagePath'] ||
|
| 122 |
+
this.MARKER_CLUSTER_IMAGE_PATH_;
|
| 123 |
+
|
| 124 |
+
/**
|
| 125 |
+
* @type {string}
|
| 126 |
+
* @private
|
| 127 |
+
*/
|
| 128 |
+
this.imageExtension_ = options['imageExtension'] ||
|
| 129 |
+
this.MARKER_CLUSTER_IMAGE_EXTENSION_;
|
| 130 |
+
|
| 131 |
+
/**
|
| 132 |
+
* @type {boolean}
|
| 133 |
+
* @private
|
| 134 |
+
*/
|
| 135 |
+
this.zoomOnClick_ = true;
|
| 136 |
+
|
| 137 |
+
if (options['zoomOnClick'] != undefined) {
|
| 138 |
+
this.zoomOnClick_ = options['zoomOnClick'];
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/**
|
| 142 |
+
* @type {boolean}
|
| 143 |
+
* @private
|
| 144 |
+
*/
|
| 145 |
+
this.averageCenter_ = false;
|
| 146 |
+
|
| 147 |
+
if (options['averageCenter'] != undefined) {
|
| 148 |
+
this.averageCenter_ = options['averageCenter'];
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
this.setupStyles_();
|
| 152 |
+
|
| 153 |
+
this.setMap(map);
|
| 154 |
+
|
| 155 |
+
/**
|
| 156 |
+
* @type {number}
|
| 157 |
+
* @private
|
| 158 |
+
*/
|
| 159 |
+
this.prevZoom_ = this.map_.getZoom();
|
| 160 |
+
|
| 161 |
+
// Add the map event listeners
|
| 162 |
+
var that = this;
|
| 163 |
+
google.maps.event.addListener(this.map_, 'zoom_changed', function() {
|
| 164 |
+
// Determines map type and prevent illegal zoom levels
|
| 165 |
+
var zoom = that.map_.getZoom();
|
| 166 |
+
var minZoom = that.map_.minZoom || 0;
|
| 167 |
+
var maxZoom = Math.min(that.map_.maxZoom || 100,
|
| 168 |
+
that.map_.mapTypes[that.map_.getMapTypeId()].maxZoom);
|
| 169 |
+
zoom = Math.min(Math.max(zoom,minZoom),maxZoom);
|
| 170 |
+
|
| 171 |
+
if (that.prevZoom_ != zoom) {
|
| 172 |
+
that.prevZoom_ = zoom;
|
| 173 |
+
that.resetViewport();
|
| 174 |
+
}
|
| 175 |
+
});
|
| 176 |
+
|
| 177 |
+
google.maps.event.addListener(this.map_, 'idle', function() {
|
| 178 |
+
that.redraw();
|
| 179 |
+
});
|
| 180 |
+
|
| 181 |
+
// Finally, add the markers
|
| 182 |
+
if (opt_markers && (opt_markers.length || Object.keys(opt_markers).length)) {
|
| 183 |
+
this.addMarkers(opt_markers, false);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
/**
|
| 189 |
+
* The marker cluster image path.
|
| 190 |
+
*
|
| 191 |
+
* @type {string}
|
| 192 |
+
* @private
|
| 193 |
+
*/
|
| 194 |
+
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_ =
|
| 195 |
+
'http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/' +
|
| 196 |
+
'images/m';
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
/**
|
| 200 |
+
* The marker cluster image path.
|
| 201 |
+
*
|
| 202 |
+
* @type {string}
|
| 203 |
+
* @private
|
| 204 |
+
*/
|
| 205 |
+
MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_ = 'png';
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
/**
|
| 209 |
+
* Extends a objects prototype by anothers.
|
| 210 |
+
*
|
| 211 |
+
* @param {Object} obj1 The object to be extended.
|
| 212 |
+
* @param {Object} obj2 The object to extend with.
|
| 213 |
+
* @return {Object} The new extended object.
|
| 214 |
+
* @ignore
|
| 215 |
+
*/
|
| 216 |
+
MarkerClusterer.prototype.extend = function(obj1, obj2) {
|
| 217 |
+
return (function(object) {
|
| 218 |
+
for (var property in object.prototype) {
|
| 219 |
+
this.prototype[property] = object.prototype[property];
|
| 220 |
+
}
|
| 221 |
+
return this;
|
| 222 |
+
}).apply(obj1, [obj2]);
|
| 223 |
+
};
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
/**
|
| 227 |
+
* Implementaion of the interface method.
|
| 228 |
+
* @ignore
|
| 229 |
+
*/
|
| 230 |
+
MarkerClusterer.prototype.onAdd = function() {
|
| 231 |
+
this.setReady_(true);
|
| 232 |
+
};
|
| 233 |
+
|
| 234 |
+
/**
|
| 235 |
+
* Implementaion of the interface method.
|
| 236 |
+
* @ignore
|
| 237 |
+
*/
|
| 238 |
+
MarkerClusterer.prototype.draw = function() {};
|
| 239 |
+
|
| 240 |
+
/**
|
| 241 |
+
* Sets up the styles object.
|
| 242 |
+
*
|
| 243 |
+
* @private
|
| 244 |
+
*/
|
| 245 |
+
MarkerClusterer.prototype.setupStyles_ = function() {
|
| 246 |
+
if (this.styles_.length) {
|
| 247 |
+
return;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
for (var i = 0, size; size = this.sizes[i]; i++) {
|
| 251 |
+
this.styles_.push({
|
| 252 |
+
url: this.imagePath_ + (i + 1) + '.' + this.imageExtension_,
|
| 253 |
+
height: size,
|
| 254 |
+
width: size
|
| 255 |
+
});
|
| 256 |
+
}
|
| 257 |
+
};
|
| 258 |
+
|
| 259 |
+
/**
|
| 260 |
+
* Fit the map to the bounds of the markers in the clusterer.
|
| 261 |
+
*/
|
| 262 |
+
MarkerClusterer.prototype.fitMapToMarkers = function() {
|
| 263 |
+
var markers = this.getMarkers();
|
| 264 |
+
var bounds = new google.maps.LatLngBounds();
|
| 265 |
+
for (var i = 0, marker; marker = markers[i]; i++) {
|
| 266 |
+
bounds.extend(marker.getPosition());
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
this.map_.fitBounds(bounds);
|
| 270 |
+
};
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
/**
|
| 274 |
+
* Sets the styles.
|
| 275 |
+
*
|
| 276 |
+
* @param {Object} styles The style to set.
|
| 277 |
+
*/
|
| 278 |
+
MarkerClusterer.prototype.setStyles = function(styles) {
|
| 279 |
+
this.styles_ = styles;
|
| 280 |
+
};
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
/**
|
| 284 |
+
* Gets the styles.
|
| 285 |
+
*
|
| 286 |
+
* @return {Object} The styles object.
|
| 287 |
+
*/
|
| 288 |
+
MarkerClusterer.prototype.getStyles = function() {
|
| 289 |
+
return this.styles_;
|
| 290 |
+
};
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
/**
|
| 294 |
+
* Whether zoom on click is set.
|
| 295 |
+
*
|
| 296 |
+
* @return {boolean} True if zoomOnClick_ is set.
|
| 297 |
+
*/
|
| 298 |
+
MarkerClusterer.prototype.isZoomOnClick = function() {
|
| 299 |
+
return this.zoomOnClick_;
|
| 300 |
+
};
|
| 301 |
+
|
| 302 |
+
/**
|
| 303 |
+
* Whether average center is set.
|
| 304 |
+
*
|
| 305 |
+
* @return {boolean} True if averageCenter_ is set.
|
| 306 |
+
*/
|
| 307 |
+
MarkerClusterer.prototype.isAverageCenter = function() {
|
| 308 |
+
return this.averageCenter_;
|
| 309 |
+
};
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
/**
|
| 313 |
+
* Returns the array of markers in the clusterer.
|
| 314 |
+
*
|
| 315 |
+
* @return {Array.<google.maps.Marker>} The markers.
|
| 316 |
+
*/
|
| 317 |
+
MarkerClusterer.prototype.getMarkers = function() {
|
| 318 |
+
return this.markers_;
|
| 319 |
+
};
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
/**
|
| 323 |
+
* Returns the number of markers in the clusterer
|
| 324 |
+
*
|
| 325 |
+
* @return {Number} The number of markers.
|
| 326 |
+
*/
|
| 327 |
+
MarkerClusterer.prototype.getTotalMarkers = function() {
|
| 328 |
+
return this.markers_.length;
|
| 329 |
+
};
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
/**
|
| 333 |
+
* Sets the max zoom for the clusterer.
|
| 334 |
+
*
|
| 335 |
+
* @param {number} maxZoom The max zoom level.
|
| 336 |
+
*/
|
| 337 |
+
MarkerClusterer.prototype.setMaxZoom = function(maxZoom) {
|
| 338 |
+
this.maxZoom_ = maxZoom;
|
| 339 |
+
};
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
/**
|
| 343 |
+
* Gets the max zoom for the clusterer.
|
| 344 |
+
*
|
| 345 |
+
* @return {number} The max zoom level.
|
| 346 |
+
*/
|
| 347 |
+
MarkerClusterer.prototype.getMaxZoom = function() {
|
| 348 |
+
return this.maxZoom_;
|
| 349 |
+
};
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
/**
|
| 353 |
+
* The function for calculating the cluster icon image.
|
| 354 |
+
*
|
| 355 |
+
* @param {Array.<google.maps.Marker>} markers The markers in the clusterer.
|
| 356 |
+
* @param {number} numStyles The number of styles available.
|
| 357 |
+
* @return {Object} A object properties: 'text' (string) and 'index' (number).
|
| 358 |
+
* @private
|
| 359 |
+
*/
|
| 360 |
+
MarkerClusterer.prototype.calculator_ = function(markers, numStyles) {
|
| 361 |
+
var index = 0;
|
| 362 |
+
var count = markers.length;
|
| 363 |
+
var dv = count;
|
| 364 |
+
while (dv !== 0) {
|
| 365 |
+
dv = parseInt(dv / 10, 10);
|
| 366 |
+
index++;
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
index = Math.min(index, numStyles);
|
| 370 |
+
return {
|
| 371 |
+
text: count,
|
| 372 |
+
index: index
|
| 373 |
+
};
|
| 374 |
+
};
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
/**
|
| 378 |
+
* Set the calculator function.
|
| 379 |
+
*
|
| 380 |
+
* @param {function(Array, number)} calculator The function to set as the
|
| 381 |
+
* calculator. The function should return a object properties:
|
| 382 |
+
* 'text' (string) and 'index' (number).
|
| 383 |
+
*
|
| 384 |
+
*/
|
| 385 |
+
MarkerClusterer.prototype.setCalculator = function(calculator) {
|
| 386 |
+
this.calculator_ = calculator;
|
| 387 |
+
};
|
| 388 |
+
|
| 389 |
+
|
| 390 |
+
/**
|
| 391 |
+
* Get the calculator function.
|
| 392 |
+
*
|
| 393 |
+
* @return {function(Array, number)} the calculator function.
|
| 394 |
+
*/
|
| 395 |
+
MarkerClusterer.prototype.getCalculator = function() {
|
| 396 |
+
return this.calculator_;
|
| 397 |
+
};
|
| 398 |
+
|
| 399 |
+
|
| 400 |
+
/**
|
| 401 |
+
* Add an array of markers to the clusterer.
|
| 402 |
+
*
|
| 403 |
+
* @param {Array.<google.maps.Marker>} markers The markers to add.
|
| 404 |
+
* @param {boolean=} opt_nodraw Whether to redraw the clusters.
|
| 405 |
+
*/
|
| 406 |
+
MarkerClusterer.prototype.addMarkers = function(markers, opt_nodraw) {
|
| 407 |
+
if (markers.length) {
|
| 408 |
+
for (var i = 0, marker; marker = markers[i]; i++) {
|
| 409 |
+
this.pushMarkerTo_(marker);
|
| 410 |
+
}
|
| 411 |
+
} else if (Object.keys(markers).length) {
|
| 412 |
+
for (var marker in markers) {
|
| 413 |
+
this.pushMarkerTo_(markers[marker]);
|
| 414 |
+
}
|
| 415 |
+
}
|
| 416 |
+
if (!opt_nodraw) {
|
| 417 |
+
this.redraw();
|
| 418 |
+
}
|
| 419 |
+
};
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
/**
|
| 423 |
+
* Pushes a marker to the clusterer.
|
| 424 |
+
*
|
| 425 |
+
* @param {google.maps.Marker} marker The marker to add.
|
| 426 |
+
* @private
|
| 427 |
+
*/
|
| 428 |
+
MarkerClusterer.prototype.pushMarkerTo_ = function(marker) {
|
| 429 |
+
marker.isAdded = false;
|
| 430 |
+
if (marker['draggable']) {
|
| 431 |
+
// If the marker is draggable add a listener so we update the clusters on
|
| 432 |
+
// the drag end.
|
| 433 |
+
var that = this;
|
| 434 |
+
google.maps.event.addListener(marker, 'dragend', function() {
|
| 435 |
+
marker.isAdded = false;
|
| 436 |
+
that.repaint();
|
| 437 |
+
});
|
| 438 |
+
}
|
| 439 |
+
this.markers_.push(marker);
|
| 440 |
+
};
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
/**
|
| 444 |
+
* Adds a marker to the clusterer and redraws if needed.
|
| 445 |
+
*
|
| 446 |
+
* @param {google.maps.Marker} marker The marker to add.
|
| 447 |
+
* @param {boolean=} opt_nodraw Whether to redraw the clusters.
|
| 448 |
+
*/
|
| 449 |
+
MarkerClusterer.prototype.addMarker = function(marker, opt_nodraw) {
|
| 450 |
+
this.pushMarkerTo_(marker);
|
| 451 |
+
if (!opt_nodraw) {
|
| 452 |
+
this.redraw();
|
| 453 |
+
}
|
| 454 |
+
};
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
/**
|
| 458 |
+
* Removes a marker and returns true if removed, false if not
|
| 459 |
+
*
|
| 460 |
+
* @param {google.maps.Marker} marker The marker to remove
|
| 461 |
+
* @return {boolean} Whether the marker was removed or not
|
| 462 |
+
* @private
|
| 463 |
+
*/
|
| 464 |
+
MarkerClusterer.prototype.removeMarker_ = function(marker) {
|
| 465 |
+
var index = -1;
|
| 466 |
+
if (this.markers_.indexOf) {
|
| 467 |
+
index = this.markers_.indexOf(marker);
|
| 468 |
+
} else {
|
| 469 |
+
for (var i = 0, m; m = this.markers_[i]; i++) {
|
| 470 |
+
if (m == marker) {
|
| 471 |
+
index = i;
|
| 472 |
+
break;
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
if (index == -1) {
|
| 478 |
+
// Marker is not in our list of markers.
|
| 479 |
+
return false;
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
marker.setMap(null);
|
| 483 |
+
|
| 484 |
+
this.markers_.splice(index, 1);
|
| 485 |
+
|
| 486 |
+
return true;
|
| 487 |
+
};
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
/**
|
| 491 |
+
* Remove a marker from the cluster.
|
| 492 |
+
*
|
| 493 |
+
* @param {google.maps.Marker} marker The marker to remove.
|
| 494 |
+
* @param {boolean=} opt_nodraw Optional boolean to force no redraw.
|
| 495 |
+
* @return {boolean} True if the marker was removed.
|
| 496 |
+
*/
|
| 497 |
+
MarkerClusterer.prototype.removeMarker = function(marker, opt_nodraw) {
|
| 498 |
+
var removed = this.removeMarker_(marker);
|
| 499 |
+
|
| 500 |
+
if (!opt_nodraw && removed) {
|
| 501 |
+
this.resetViewport();
|
| 502 |
+
this.redraw();
|
| 503 |
+
return true;
|
| 504 |
+
} else {
|
| 505 |
+
return false;
|
| 506 |
+
}
|
| 507 |
+
};
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
/**
|
| 511 |
+
* Removes an array of markers from the cluster.
|
| 512 |
+
*
|
| 513 |
+
* @param {Array.<google.maps.Marker>} markers The markers to remove.
|
| 514 |
+
* @param {boolean=} opt_nodraw Optional boolean to force no redraw.
|
| 515 |
+
*/
|
| 516 |
+
MarkerClusterer.prototype.removeMarkers = function(markers, opt_nodraw) {
|
| 517 |
+
var removed = false;
|
| 518 |
+
|
| 519 |
+
for (var i = 0, marker; marker = markers[i]; i++) {
|
| 520 |
+
var r = this.removeMarker_(marker);
|
| 521 |
+
removed = removed || r;
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
if (!opt_nodraw && removed) {
|
| 525 |
+
this.resetViewport();
|
| 526 |
+
this.redraw();
|
| 527 |
+
return true;
|
| 528 |
+
}
|
| 529 |
+
};
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
/**
|
| 533 |
+
* Sets the clusterer's ready state.
|
| 534 |
+
*
|
| 535 |
+
* @param {boolean} ready The state.
|
| 536 |
+
* @private
|
| 537 |
+
*/
|
| 538 |
+
MarkerClusterer.prototype.setReady_ = function(ready) {
|
| 539 |
+
if (!this.ready_) {
|
| 540 |
+
this.ready_ = ready;
|
| 541 |
+
this.createClusters_();
|
| 542 |
+
}
|
| 543 |
+
};
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
/**
|
| 547 |
+
* Returns the number of clusters in the clusterer.
|
| 548 |
+
*
|
| 549 |
+
* @return {number} The number of clusters.
|
| 550 |
+
*/
|
| 551 |
+
MarkerClusterer.prototype.getTotalClusters = function() {
|
| 552 |
+
return this.clusters_.length;
|
| 553 |
+
};
|
| 554 |
+
|
| 555 |
+
|
| 556 |
+
/**
|
| 557 |
+
* Returns the google map that the clusterer is associated with.
|
| 558 |
+
*
|
| 559 |
+
* @return {google.maps.Map} The map.
|
| 560 |
+
*/
|
| 561 |
+
MarkerClusterer.prototype.getMap = function() {
|
| 562 |
+
return this.map_;
|
| 563 |
+
};
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
/**
|
| 567 |
+
* Sets the google map that the clusterer is associated with.
|
| 568 |
+
*
|
| 569 |
+
* @param {google.maps.Map} map The map.
|
| 570 |
+
*/
|
| 571 |
+
MarkerClusterer.prototype.setMap = function(map) {
|
| 572 |
+
this.map_ = map;
|
| 573 |
+
};
|
| 574 |
+
|
| 575 |
+
|
| 576 |
+
/**
|
| 577 |
+
* Returns the size of the grid.
|
| 578 |
+
*
|
| 579 |
+
* @return {number} The grid size.
|
| 580 |
+
*/
|
| 581 |
+
MarkerClusterer.prototype.getGridSize = function() {
|
| 582 |
+
return this.gridSize_;
|
| 583 |
+
};
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
/**
|
| 587 |
+
* Sets the size of the grid.
|
| 588 |
+
*
|
| 589 |
+
* @param {number} size The grid size.
|
| 590 |
+
*/
|
| 591 |
+
MarkerClusterer.prototype.setGridSize = function(size) {
|
| 592 |
+
this.gridSize_ = size;
|
| 593 |
+
};
|
| 594 |
+
|
| 595 |
+
|
| 596 |
+
/**
|
| 597 |
+
* Returns the min cluster size.
|
| 598 |
+
*
|
| 599 |
+
* @return {number} The grid size.
|
| 600 |
+
*/
|
| 601 |
+
MarkerClusterer.prototype.getMinClusterSize = function() {
|
| 602 |
+
return this.minClusterSize_;
|
| 603 |
+
};
|
| 604 |
+
|
| 605 |
+
/**
|
| 606 |
+
* Sets the min cluster size.
|
| 607 |
+
*
|
| 608 |
+
* @param {number} size The grid size.
|
| 609 |
+
*/
|
| 610 |
+
MarkerClusterer.prototype.setMinClusterSize = function(size) {
|
| 611 |
+
this.minClusterSize_ = size;
|
| 612 |
+
};
|
| 613 |
+
|
| 614 |
+
|
| 615 |
+
/**
|
| 616 |
+
* Extends a bounds object by the grid size.
|
| 617 |
+
*
|
| 618 |
+
* @param {google.maps.LatLngBounds} bounds The bounds to extend.
|
| 619 |
+
* @return {google.maps.LatLngBounds} The extended bounds.
|
| 620 |
+
*/
|
| 621 |
+
MarkerClusterer.prototype.getExtendedBounds = function(bounds) {
|
| 622 |
+
var projection = this.getProjection();
|
| 623 |
+
|
| 624 |
+
// Turn the bounds into latlng.
|
| 625 |
+
var tr = new google.maps.LatLng(bounds.getNorthEast().lat(),
|
| 626 |
+
bounds.getNorthEast().lng());
|
| 627 |
+
var bl = new google.maps.LatLng(bounds.getSouthWest().lat(),
|
| 628 |
+
bounds.getSouthWest().lng());
|
| 629 |
+
|
| 630 |
+
// Convert the points to pixels and the extend out by the grid size.
|
| 631 |
+
var trPix = projection.fromLatLngToDivPixel(tr);
|
| 632 |
+
trPix.x += this.gridSize_;
|
| 633 |
+
trPix.y -= this.gridSize_;
|
| 634 |
+
|
| 635 |
+
var blPix = projection.fromLatLngToDivPixel(bl);
|
| 636 |
+
blPix.x -= this.gridSize_;
|
| 637 |
+
blPix.y += this.gridSize_;
|
| 638 |
+
|
| 639 |
+
// Convert the pixel points back to LatLng
|
| 640 |
+
var ne = projection.fromDivPixelToLatLng(trPix);
|
| 641 |
+
var sw = projection.fromDivPixelToLatLng(blPix);
|
| 642 |
+
|
| 643 |
+
// Extend the bounds to contain the new bounds.
|
| 644 |
+
bounds.extend(ne);
|
| 645 |
+
bounds.extend(sw);
|
| 646 |
+
|
| 647 |
+
return bounds;
|
| 648 |
+
};
|
| 649 |
+
|
| 650 |
+
|
| 651 |
+
/**
|
| 652 |
+
* Determins if a marker is contained in a bounds.
|
| 653 |
+
*
|
| 654 |
+
* @param {google.maps.Marker} marker The marker to check.
|
| 655 |
+
* @param {google.maps.LatLngBounds} bounds The bounds to check against.
|
| 656 |
+
* @return {boolean} True if the marker is in the bounds.
|
| 657 |
+
* @private
|
| 658 |
+
*/
|
| 659 |
+
MarkerClusterer.prototype.isMarkerInBounds_ = function(marker, bounds) {
|
| 660 |
+
return bounds.contains(marker.getPosition());
|
| 661 |
+
};
|
| 662 |
+
|
| 663 |
+
|
| 664 |
+
/**
|
| 665 |
+
* Clears all clusters and markers from the clusterer.
|
| 666 |
+
*/
|
| 667 |
+
MarkerClusterer.prototype.clearMarkers = function() {
|
| 668 |
+
this.resetViewport(true);
|
| 669 |
+
|
| 670 |
+
// Set the markers a empty array.
|
| 671 |
+
this.markers_ = [];
|
| 672 |
+
};
|
| 673 |
+
|
| 674 |
+
|
| 675 |
+
/**
|
| 676 |
+
* Clears all existing clusters and recreates them.
|
| 677 |
+
* @param {boolean} opt_hide To also hide the marker.
|
| 678 |
+
*/
|
| 679 |
+
MarkerClusterer.prototype.resetViewport = function(opt_hide) {
|
| 680 |
+
// Remove all the clusters
|
| 681 |
+
for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
|
| 682 |
+
cluster.remove();
|
| 683 |
+
}
|
| 684 |
+
|
| 685 |
+
// Reset the markers to not be added and to be invisible.
|
| 686 |
+
for (var i = 0, marker; marker = this.markers_[i]; i++) {
|
| 687 |
+
marker.isAdded = false;
|
| 688 |
+
if (opt_hide) {
|
| 689 |
+
marker.setMap(null);
|
| 690 |
+
}
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
+
this.clusters_ = [];
|
| 694 |
+
};
|
| 695 |
+
|
| 696 |
+
/**
|
| 697 |
+
*
|
| 698 |
+
*/
|
| 699 |
+
MarkerClusterer.prototype.repaint = function() {
|
| 700 |
+
var oldClusters = this.clusters_.slice();
|
| 701 |
+
this.clusters_.length = 0;
|
| 702 |
+
this.resetViewport();
|
| 703 |
+
this.redraw();
|
| 704 |
+
|
| 705 |
+
// Remove the old clusters.
|
| 706 |
+
// Do it in a timeout so the other clusters have been drawn first.
|
| 707 |
+
window.setTimeout(function() {
|
| 708 |
+
for (var i = 0, cluster; cluster = oldClusters[i]; i++) {
|
| 709 |
+
cluster.remove();
|
| 710 |
+
}
|
| 711 |
+
}, 0);
|
| 712 |
+
};
|
| 713 |
+
|
| 714 |
+
|
| 715 |
+
/**
|
| 716 |
+
* Redraws the clusters.
|
| 717 |
+
*/
|
| 718 |
+
MarkerClusterer.prototype.redraw = function() {
|
| 719 |
+
this.createClusters_();
|
| 720 |
+
};
|
| 721 |
+
|
| 722 |
+
|
| 723 |
+
/**
|
| 724 |
+
* Calculates the distance between two latlng locations in km.
|
| 725 |
+
* @see http://www.movable-type.co.uk/scripts/latlong.html
|
| 726 |
+
*
|
| 727 |
+
* @param {google.maps.LatLng} p1 The first lat lng point.
|
| 728 |
+
* @param {google.maps.LatLng} p2 The second lat lng point.
|
| 729 |
+
* @return {number} The distance between the two points in km.
|
| 730 |
+
* @private
|
| 731 |
+
*/
|
| 732 |
+
MarkerClusterer.prototype.distanceBetweenPoints_ = function(p1, p2) {
|
| 733 |
+
if (!p1 || !p2) {
|
| 734 |
+
return 0;
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
var R = 6371; // Radius of the Earth in km
|
| 738 |
+
var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
|
| 739 |
+
var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
|
| 740 |
+
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
| 741 |
+
Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
|
| 742 |
+
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
| 743 |
+
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
| 744 |
+
var d = R * c;
|
| 745 |
+
return d;
|
| 746 |
+
};
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
/**
|
| 750 |
+
* Add a marker to a cluster, or creates a new cluster.
|
| 751 |
+
*
|
| 752 |
+
* @param {google.maps.Marker} marker The marker to add.
|
| 753 |
+
* @private
|
| 754 |
+
*/
|
| 755 |
+
MarkerClusterer.prototype.addToClosestCluster_ = function(marker) {
|
| 756 |
+
var distance = 40000; // Some large number
|
| 757 |
+
var clusterToAddTo = null;
|
| 758 |
+
var pos = marker.getPosition();
|
| 759 |
+
for (var i = 0, cluster; cluster = this.clusters_[i]; i++) {
|
| 760 |
+
var center = cluster.getCenter();
|
| 761 |
+
if (center) {
|
| 762 |
+
var d = this.distanceBetweenPoints_(center, marker.getPosition());
|
| 763 |
+
if (d < distance) {
|
| 764 |
+
distance = d;
|
| 765 |
+
clusterToAddTo = cluster;
|
| 766 |
+
}
|
| 767 |
+
}
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
+
if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
|
| 771 |
+
clusterToAddTo.addMarker(marker);
|
| 772 |
+
} else {
|
| 773 |
+
var cluster = new Cluster(this);
|
| 774 |
+
cluster.addMarker(marker);
|
| 775 |
+
this.clusters_.push(cluster);
|
| 776 |
+
}
|
| 777 |
+
};
|
| 778 |
+
|
| 779 |
+
|
| 780 |
+
/**
|
| 781 |
+
* Creates the clusters.
|
| 782 |
+
*
|
| 783 |
+
* @private
|
| 784 |
+
*/
|
| 785 |
+
MarkerClusterer.prototype.createClusters_ = function() {
|
| 786 |
+
if (!this.ready_) {
|
| 787 |
+
return;
|
| 788 |
+
}
|
| 789 |
+
|
| 790 |
+
// Get our current map view bounds.
|
| 791 |
+
// Create a new bounds object so we don't affect the map.
|
| 792 |
+
var mapBounds = new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(),
|
| 793 |
+
this.map_.getBounds().getNorthEast());
|
| 794 |
+
var bounds = this.getExtendedBounds(mapBounds);
|
| 795 |
+
|
| 796 |
+
for (var i = 0, marker; marker = this.markers_[i]; i++) {
|
| 797 |
+
if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {
|
| 798 |
+
this.addToClosestCluster_(marker);
|
| 799 |
+
}
|
| 800 |
+
}
|
| 801 |
+
};
|
| 802 |
+
|
| 803 |
+
|
| 804 |
+
/**
|
| 805 |
+
* A cluster that contains markers.
|
| 806 |
+
*
|
| 807 |
+
* @param {MarkerClusterer} markerClusterer The markerclusterer that this
|
| 808 |
+
* cluster is associated with.
|
| 809 |
+
* @constructor
|
| 810 |
+
* @ignore
|
| 811 |
+
*/
|
| 812 |
+
function Cluster(markerClusterer) {
|
| 813 |
+
this.markerClusterer_ = markerClusterer;
|
| 814 |
+
this.map_ = markerClusterer.getMap();
|
| 815 |
+
this.gridSize_ = markerClusterer.getGridSize();
|
| 816 |
+
this.minClusterSize_ = markerClusterer.getMinClusterSize();
|
| 817 |
+
this.averageCenter_ = markerClusterer.isAverageCenter();
|
| 818 |
+
this.center_ = null;
|
| 819 |
+
this.markers_ = [];
|
| 820 |
+
this.bounds_ = null;
|
| 821 |
+
this.clusterIcon_ = new ClusterIcon(this, markerClusterer.getStyles(),
|
| 822 |
+
markerClusterer.getGridSize());
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
/**
|
| 826 |
+
* Determins if a marker is already added to the cluster.
|
| 827 |
+
*
|
| 828 |
+
* @param {google.maps.Marker} marker The marker to check.
|
| 829 |
+
* @return {boolean} True if the marker is already added.
|
| 830 |
+
*/
|
| 831 |
+
Cluster.prototype.isMarkerAlreadyAdded = function(marker) {
|
| 832 |
+
if (this.markers_.indexOf) {
|
| 833 |
+
return this.markers_.indexOf(marker) != -1;
|
| 834 |
+
} else {
|
| 835 |
+
for (var i = 0, m; m = this.markers_[i]; i++) {
|
| 836 |
+
if (m == marker) {
|
| 837 |
+
return true;
|
| 838 |
+
}
|
| 839 |
+
}
|
| 840 |
+
}
|
| 841 |
+
return false;
|
| 842 |
+
};
|
| 843 |
+
|
| 844 |
+
|
| 845 |
+
/**
|
| 846 |
+
* Add a marker the cluster.
|
| 847 |
+
*
|
| 848 |
+
* @param {google.maps.Marker} marker The marker to add.
|
| 849 |
+
* @return {boolean} True if the marker was added.
|
| 850 |
+
*/
|
| 851 |
+
Cluster.prototype.addMarker = function(marker) {
|
| 852 |
+
if (this.isMarkerAlreadyAdded(marker)) {
|
| 853 |
+
return false;
|
| 854 |
+
}
|
| 855 |
+
|
| 856 |
+
if (!this.center_) {
|
| 857 |
+
this.center_ = marker.getPosition();
|
| 858 |
+
this.calculateBounds_();
|
| 859 |
+
} else {
|
| 860 |
+
if (this.averageCenter_) {
|
| 861 |
+
var l = this.markers_.length + 1;
|
| 862 |
+
var lat = (this.center_.lat() * (l-1) + marker.getPosition().lat()) / l;
|
| 863 |
+
var lng = (this.center_.lng() * (l-1) + marker.getPosition().lng()) / l;
|
| 864 |
+
this.center_ = new google.maps.LatLng(lat, lng);
|
| 865 |
+
this.calculateBounds_();
|
| 866 |
+
}
|
| 867 |
+
}
|
| 868 |
+
|
| 869 |
+
marker.isAdded = true;
|
| 870 |
+
this.markers_.push(marker);
|
| 871 |
+
|
| 872 |
+
var len = this.markers_.length;
|
| 873 |
+
if (len < this.minClusterSize_ && marker.getMap() != this.map_) {
|
| 874 |
+
// Min cluster size not reached so show the marker.
|
| 875 |
+
marker.setMap(this.map_);
|
| 876 |
+
}
|
| 877 |
+
|
| 878 |
+
if (len == this.minClusterSize_) {
|
| 879 |
+
// Hide the markers that were showing.
|
| 880 |
+
for (var i = 0; i < len; i++) {
|
| 881 |
+
this.markers_[i].setMap(null);
|
| 882 |
+
}
|
| 883 |
+
}
|
| 884 |
+
|
| 885 |
+
if (len >= this.minClusterSize_) {
|
| 886 |
+
marker.setMap(null);
|
| 887 |
+
}
|
| 888 |
+
|
| 889 |
+
this.updateIcon();
|
| 890 |
+
return true;
|
| 891 |
+
};
|
| 892 |
+
|
| 893 |
+
|
| 894 |
+
/**
|
| 895 |
+
* Returns the marker clusterer that the cluster is associated with.
|
| 896 |
+
*
|
| 897 |
+
* @return {MarkerClusterer} The associated marker clusterer.
|
| 898 |
+
*/
|
| 899 |
+
Cluster.prototype.getMarkerClusterer = function() {
|
| 900 |
+
return this.markerClusterer_;
|
| 901 |
+
};
|
| 902 |
+
|
| 903 |
+
|
| 904 |
+
/**
|
| 905 |
+
* Returns the bounds of the cluster.
|
| 906 |
+
*
|
| 907 |
+
* @return {google.maps.LatLngBounds} the cluster bounds.
|
| 908 |
+
*/
|
| 909 |
+
Cluster.prototype.getBounds = function() {
|
| 910 |
+
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
|
| 911 |
+
var markers = this.getMarkers();
|
| 912 |
+
for (var i = 0, marker; marker = markers[i]; i++) {
|
| 913 |
+
bounds.extend(marker.getPosition());
|
| 914 |
+
}
|
| 915 |
+
return bounds;
|
| 916 |
+
};
|
| 917 |
+
|
| 918 |
+
|
| 919 |
+
/**
|
| 920 |
+
* Removes the cluster
|
| 921 |
+
*/
|
| 922 |
+
Cluster.prototype.remove = function() {
|
| 923 |
+
this.clusterIcon_.remove();
|
| 924 |
+
this.markers_.length = 0;
|
| 925 |
+
delete this.markers_;
|
| 926 |
+
};
|
| 927 |
+
|
| 928 |
+
|
| 929 |
+
/**
|
| 930 |
+
* Returns the center of the cluster.
|
| 931 |
+
*
|
| 932 |
+
* @return {number} The cluster center.
|
| 933 |
+
*/
|
| 934 |
+
Cluster.prototype.getSize = function() {
|
| 935 |
+
return this.markers_.length;
|
| 936 |
+
};
|
| 937 |
+
|
| 938 |
+
|
| 939 |
+
/**
|
| 940 |
+
* Returns the center of the cluster.
|
| 941 |
+
*
|
| 942 |
+
* @return {Array.<google.maps.Marker>} The cluster center.
|
| 943 |
+
*/
|
| 944 |
+
Cluster.prototype.getMarkers = function() {
|
| 945 |
+
return this.markers_;
|
| 946 |
+
};
|
| 947 |
+
|
| 948 |
+
|
| 949 |
+
/**
|
| 950 |
+
* Returns the center of the cluster.
|
| 951 |
+
*
|
| 952 |
+
* @return {google.maps.LatLng} The cluster center.
|
| 953 |
+
*/
|
| 954 |
+
Cluster.prototype.getCenter = function() {
|
| 955 |
+
return this.center_;
|
| 956 |
+
};
|
| 957 |
+
|
| 958 |
+
|
| 959 |
+
/**
|
| 960 |
+
* Calculated the extended bounds of the cluster with the grid.
|
| 961 |
+
*
|
| 962 |
+
* @private
|
| 963 |
+
*/
|
| 964 |
+
Cluster.prototype.calculateBounds_ = function() {
|
| 965 |
+
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
|
| 966 |
+
this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);
|
| 967 |
+
};
|
| 968 |
+
|
| 969 |
+
|
| 970 |
+
/**
|
| 971 |
+
* Determines if a marker lies in the clusters bounds.
|
| 972 |
+
*
|
| 973 |
+
* @param {google.maps.Marker} marker The marker to check.
|
| 974 |
+
* @return {boolean} True if the marker lies in the bounds.
|
| 975 |
+
*/
|
| 976 |
+
Cluster.prototype.isMarkerInClusterBounds = function(marker) {
|
| 977 |
+
return this.bounds_.contains(marker.getPosition());
|
| 978 |
+
};
|
| 979 |
+
|
| 980 |
+
|
| 981 |
+
/**
|
| 982 |
+
* Returns the map that the cluster is associated with.
|
| 983 |
+
*
|
| 984 |
+
* @return {google.maps.Map} The map.
|
| 985 |
+
*/
|
| 986 |
+
Cluster.prototype.getMap = function() {
|
| 987 |
+
return this.map_;
|
| 988 |
+
};
|
| 989 |
+
|
| 990 |
+
|
| 991 |
+
/**
|
| 992 |
+
* Updates the cluster icon
|
| 993 |
+
*/
|
| 994 |
+
Cluster.prototype.updateIcon = function() {
|
| 995 |
+
var zoom = this.map_.getZoom();
|
| 996 |
+
var mz = this.markerClusterer_.getMaxZoom();
|
| 997 |
+
|
| 998 |
+
if (mz && zoom > mz) {
|
| 999 |
+
// The zoom is greater than our max zoom so show all the markers in cluster.
|
| 1000 |
+
for (var i = 0, marker; marker = this.markers_[i]; i++) {
|
| 1001 |
+
marker.setMap(this.map_);
|
| 1002 |
+
}
|
| 1003 |
+
return;
|
| 1004 |
+
}
|
| 1005 |
+
|
| 1006 |
+
if (this.markers_.length < this.minClusterSize_) {
|
| 1007 |
+
// Min cluster size not yet reached.
|
| 1008 |
+
this.clusterIcon_.hide();
|
| 1009 |
+
return;
|
| 1010 |
+
}
|
| 1011 |
+
|
| 1012 |
+
var numStyles = this.markerClusterer_.getStyles().length;
|
| 1013 |
+
var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);
|
| 1014 |
+
this.clusterIcon_.setCenter(this.center_);
|
| 1015 |
+
this.clusterIcon_.setSums(sums);
|
| 1016 |
+
this.clusterIcon_.show();
|
| 1017 |
+
};
|
| 1018 |
+
|
| 1019 |
+
|
| 1020 |
+
/**
|
| 1021 |
+
* A cluster icon
|
| 1022 |
+
*
|
| 1023 |
+
* @param {Cluster} cluster The cluster to be associated with.
|
| 1024 |
+
* @param {Object} styles An object that has style properties:
|
| 1025 |
+
* 'url': (string) The image url.
|
| 1026 |
+
* 'height': (number) The image height.
|
| 1027 |
+
* 'width': (number) The image width.
|
| 1028 |
+
* 'anchor': (Array) The anchor position of the label text.
|
| 1029 |
+
* 'textColor': (string) The text color.
|
| 1030 |
+
* 'textSize': (number) The text size.
|
| 1031 |
+
* 'backgroundPosition: (string) The background postition x, y.
|
| 1032 |
+
* @param {number=} opt_padding Optional padding to apply to the cluster icon.
|
| 1033 |
+
* @constructor
|
| 1034 |
+
* @extends google.maps.OverlayView
|
| 1035 |
+
* @ignore
|
| 1036 |
+
*/
|
| 1037 |
+
function ClusterIcon(cluster, styles, opt_padding) {
|
| 1038 |
+
cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);
|
| 1039 |
+
|
| 1040 |
+
this.styles_ = styles;
|
| 1041 |
+
this.padding_ = opt_padding || 0;
|
| 1042 |
+
this.cluster_ = cluster;
|
| 1043 |
+
this.center_ = null;
|
| 1044 |
+
this.map_ = cluster.getMap();
|
| 1045 |
+
this.div_ = null;
|
| 1046 |
+
this.sums_ = null;
|
| 1047 |
+
this.visible_ = false;
|
| 1048 |
+
|
| 1049 |
+
this.setMap(this.map_);
|
| 1050 |
+
}
|
| 1051 |
+
|
| 1052 |
+
|
| 1053 |
+
/**
|
| 1054 |
+
* Triggers the clusterclick event and zoom's if the option is set.
|
| 1055 |
+
*/
|
| 1056 |
+
ClusterIcon.prototype.triggerClusterClick = function() {
|
| 1057 |
+
var markerClusterer = this.cluster_.getMarkerClusterer();
|
| 1058 |
+
|
| 1059 |
+
// Trigger the clusterclick event.
|
| 1060 |
+
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
|
| 1061 |
+
|
| 1062 |
+
if (markerClusterer.isZoomOnClick()) {
|
| 1063 |
+
// Zoom into the cluster.
|
| 1064 |
+
this.map_.fitBounds(this.cluster_.getBounds());
|
| 1065 |
+
}
|
| 1066 |
+
};
|
| 1067 |
+
|
| 1068 |
+
|
| 1069 |
+
/**
|
| 1070 |
+
* Adding the cluster icon to the dom.
|
| 1071 |
+
* @ignore
|
| 1072 |
+
*/
|
| 1073 |
+
ClusterIcon.prototype.onAdd = function() {
|
| 1074 |
+
this.div_ = document.createElement('DIV');
|
| 1075 |
+
if (this.visible_) {
|
| 1076 |
+
var pos = this.getPosFromLatLng_(this.center_);
|
| 1077 |
+
this.div_.style.cssText = this.createCss(pos);
|
| 1078 |
+
this.div_.innerHTML = this.sums_.text;
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
var panes = this.getPanes();
|
| 1082 |
+
panes.overlayMouseTarget.appendChild(this.div_);
|
| 1083 |
+
|
| 1084 |
+
var that = this;
|
| 1085 |
+
google.maps.event.addDomListener(this.div_, 'click', function() {
|
| 1086 |
+
that.triggerClusterClick();
|
| 1087 |
+
});
|
| 1088 |
+
};
|
| 1089 |
+
|
| 1090 |
+
|
| 1091 |
+
/**
|
| 1092 |
+
* Returns the position to place the div dending on the latlng.
|
| 1093 |
+
*
|
| 1094 |
+
* @param {google.maps.LatLng} latlng The position in latlng.
|
| 1095 |
+
* @return {google.maps.Point} The position in pixels.
|
| 1096 |
+
* @private
|
| 1097 |
+
*/
|
| 1098 |
+
ClusterIcon.prototype.getPosFromLatLng_ = function(latlng) {
|
| 1099 |
+
var pos = this.getProjection().fromLatLngToDivPixel(latlng);
|
| 1100 |
+
pos.x -= parseInt(this.width_ / 2, 10);
|
| 1101 |
+
pos.y -= parseInt(this.height_ / 2, 10);
|
| 1102 |
+
return pos;
|
| 1103 |
+
};
|
| 1104 |
+
|
| 1105 |
+
|
| 1106 |
+
/**
|
| 1107 |
+
* Draw the icon.
|
| 1108 |
+
* @ignore
|
| 1109 |
+
*/
|
| 1110 |
+
ClusterIcon.prototype.draw = function() {
|
| 1111 |
+
if (this.visible_) {
|
| 1112 |
+
var pos = this.getPosFromLatLng_(this.center_);
|
| 1113 |
+
this.div_.style.top = pos.y + 'px';
|
| 1114 |
+
this.div_.style.left = pos.x + 'px';
|
| 1115 |
+
}
|
| 1116 |
+
};
|
| 1117 |
+
|
| 1118 |
+
|
| 1119 |
+
/**
|
| 1120 |
+
* Hide the icon.
|
| 1121 |
+
*/
|
| 1122 |
+
ClusterIcon.prototype.hide = function() {
|
| 1123 |
+
if (this.div_) {
|
| 1124 |
+
this.div_.style.display = 'none';
|
| 1125 |
+
}
|
| 1126 |
+
this.visible_ = false;
|
| 1127 |
+
};
|
| 1128 |
+
|
| 1129 |
+
|
| 1130 |
+
/**
|
| 1131 |
+
* Position and show the icon.
|
| 1132 |
+
*/
|
| 1133 |
+
ClusterIcon.prototype.show = function() {
|
| 1134 |
+
if (this.div_) {
|
| 1135 |
+
var pos = this.getPosFromLatLng_(this.center_);
|
| 1136 |
+
this.div_.style.cssText = this.createCss(pos);
|
| 1137 |
+
this.div_.style.display = '';
|
| 1138 |
+
}
|
| 1139 |
+
this.visible_ = true;
|
| 1140 |
+
};
|
| 1141 |
+
|
| 1142 |
+
|
| 1143 |
+
/**
|
| 1144 |
+
* Remove the icon from the map
|
| 1145 |
+
*/
|
| 1146 |
+
ClusterIcon.prototype.remove = function() {
|
| 1147 |
+
this.setMap(null);
|
| 1148 |
+
};
|
| 1149 |
+
|
| 1150 |
+
|
| 1151 |
+
/**
|
| 1152 |
+
* Implementation of the onRemove interface.
|
| 1153 |
+
* @ignore
|
| 1154 |
+
*/
|
| 1155 |
+
ClusterIcon.prototype.onRemove = function() {
|
| 1156 |
+
if (this.div_ && this.div_.parentNode) {
|
| 1157 |
+
this.hide();
|
| 1158 |
+
this.div_.parentNode.removeChild(this.div_);
|
| 1159 |
+
this.div_ = null;
|
| 1160 |
+
}
|
| 1161 |
+
};
|
| 1162 |
+
|
| 1163 |
+
|
| 1164 |
+
/**
|
| 1165 |
+
* Set the sums of the icon.
|
| 1166 |
+
*
|
| 1167 |
+
* @param {Object} sums The sums containing:
|
| 1168 |
+
* 'text': (string) The text to display in the icon.
|
| 1169 |
+
* 'index': (number) The style index of the icon.
|
| 1170 |
+
*/
|
| 1171 |
+
ClusterIcon.prototype.setSums = function(sums) {
|
| 1172 |
+
this.sums_ = sums;
|
| 1173 |
+
this.text_ = sums.text;
|
| 1174 |
+
this.index_ = sums.index;
|
| 1175 |
+
if (this.div_) {
|
| 1176 |
+
this.div_.innerHTML = sums.text;
|
| 1177 |
+
}
|
| 1178 |
+
|
| 1179 |
+
this.useStyle();
|
| 1180 |
+
};
|
| 1181 |
+
|
| 1182 |
+
|
| 1183 |
+
/**
|
| 1184 |
+
* Sets the icon to the the styles.
|
| 1185 |
+
*/
|
| 1186 |
+
ClusterIcon.prototype.useStyle = function() {
|
| 1187 |
+
var index = Math.max(0, this.sums_.index - 1);
|
| 1188 |
+
index = Math.min(this.styles_.length - 1, index);
|
| 1189 |
+
var style = this.styles_[index];
|
| 1190 |
+
this.url_ = style['url'];
|
| 1191 |
+
this.height_ = style['height'];
|
| 1192 |
+
this.width_ = style['width'];
|
| 1193 |
+
this.textColor_ = style['textColor'];
|
| 1194 |
+
this.anchor_ = style['anchor'];
|
| 1195 |
+
this.textSize_ = style['textSize'];
|
| 1196 |
+
this.backgroundPosition_ = style['backgroundPosition'];
|
| 1197 |
+
};
|
| 1198 |
+
|
| 1199 |
+
|
| 1200 |
+
/**
|
| 1201 |
+
* Sets the center of the icon.
|
| 1202 |
+
*
|
| 1203 |
+
* @param {google.maps.LatLng} center The latlng to set as the center.
|
| 1204 |
+
*/
|
| 1205 |
+
ClusterIcon.prototype.setCenter = function(center) {
|
| 1206 |
+
this.center_ = center;
|
| 1207 |
+
};
|
| 1208 |
+
|
| 1209 |
+
|
| 1210 |
+
/**
|
| 1211 |
+
* Create the css text based on the position of the icon.
|
| 1212 |
+
*
|
| 1213 |
+
* @param {google.maps.Point} pos The position.
|
| 1214 |
+
* @return {string} The css style text.
|
| 1215 |
+
*/
|
| 1216 |
+
ClusterIcon.prototype.createCss = function(pos) {
|
| 1217 |
+
var style = [];
|
| 1218 |
+
style.push('background-image:url(' + this.url_ + ');');
|
| 1219 |
+
var backgroundPosition = this.backgroundPosition_ ? this.backgroundPosition_ : '0 0';
|
| 1220 |
+
style.push('background-position:' + backgroundPosition + ';');
|
| 1221 |
+
|
| 1222 |
+
if (typeof this.anchor_ === 'object') {
|
| 1223 |
+
if (typeof this.anchor_[0] === 'number' && this.anchor_[0] > 0 &&
|
| 1224 |
+
this.anchor_[0] < this.height_) {
|
| 1225 |
+
style.push('height:' + (this.height_ - this.anchor_[0]) +
|
| 1226 |
+
'px; padding-top:' + this.anchor_[0] + 'px;');
|
| 1227 |
+
} else {
|
| 1228 |
+
style.push('height:' + this.height_ + 'px; line-height:' + this.height_ +
|
| 1229 |
+
'px;');
|
| 1230 |
+
}
|
| 1231 |
+
if (typeof this.anchor_[1] === 'number' && this.anchor_[1] > 0 &&
|
| 1232 |
+
this.anchor_[1] < this.width_) {
|
| 1233 |
+
style.push('width:' + (this.width_ - this.anchor_[1]) +
|
| 1234 |
+
'px; padding-left:' + this.anchor_[1] + 'px;');
|
| 1235 |
+
} else {
|
| 1236 |
+
style.push('width:' + this.width_ + 'px; text-align:center;');
|
| 1237 |
+
}
|
| 1238 |
+
} else {
|
| 1239 |
+
style.push('height:' + this.height_ + 'px; line-height:' +
|
| 1240 |
+
this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;');
|
| 1241 |
+
}
|
| 1242 |
+
|
| 1243 |
+
var txtColor = this.textColor_ ? this.textColor_ : 'black';
|
| 1244 |
+
var txtSize = this.textSize_ ? this.textSize_ : 11;
|
| 1245 |
+
|
| 1246 |
+
style.push('cursor:pointer; top:' + pos.y + 'px; left:' +
|
| 1247 |
+
pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' +
|
| 1248 |
+
txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
|
| 1249 |
+
return style.join('');
|
| 1250 |
+
};
|
| 1251 |
+
|
| 1252 |
+
|
| 1253 |
+
// Export Symbols for Closure
|
| 1254 |
+
// If you are not going to compile with closure then you can remove the
|
| 1255 |
+
// code below.
|
| 1256 |
+
window['MarkerClusterer'] = MarkerClusterer;
|
| 1257 |
+
MarkerClusterer.prototype['addMarker'] = MarkerClusterer.prototype.addMarker;
|
| 1258 |
+
MarkerClusterer.prototype['addMarkers'] = MarkerClusterer.prototype.addMarkers;
|
| 1259 |
+
MarkerClusterer.prototype['clearMarkers'] =
|
| 1260 |
+
MarkerClusterer.prototype.clearMarkers;
|
| 1261 |
+
MarkerClusterer.prototype['fitMapToMarkers'] =
|
| 1262 |
+
MarkerClusterer.prototype.fitMapToMarkers;
|
| 1263 |
+
MarkerClusterer.prototype['getCalculator'] =
|
| 1264 |
+
MarkerClusterer.prototype.getCalculator;
|
| 1265 |
+
MarkerClusterer.prototype['getGridSize'] =
|
| 1266 |
+
MarkerClusterer.prototype.getGridSize;
|
| 1267 |
+
MarkerClusterer.prototype['getExtendedBounds'] =
|
| 1268 |
+
MarkerClusterer.prototype.getExtendedBounds;
|
| 1269 |
+
MarkerClusterer.prototype['getMap'] = MarkerClusterer.prototype.getMap;
|
| 1270 |
+
MarkerClusterer.prototype['getMarkers'] = MarkerClusterer.prototype.getMarkers;
|
| 1271 |
+
MarkerClusterer.prototype['getMaxZoom'] = MarkerClusterer.prototype.getMaxZoom;
|
| 1272 |
+
MarkerClusterer.prototype['getStyles'] = MarkerClusterer.prototype.getStyles;
|
| 1273 |
+
MarkerClusterer.prototype['getTotalClusters'] =
|
| 1274 |
+
MarkerClusterer.prototype.getTotalClusters;
|
| 1275 |
+
MarkerClusterer.prototype['getTotalMarkers'] =
|
| 1276 |
+
MarkerClusterer.prototype.getTotalMarkers;
|
| 1277 |
+
MarkerClusterer.prototype['redraw'] = MarkerClusterer.prototype.redraw;
|
| 1278 |
+
MarkerClusterer.prototype['removeMarker'] =
|
| 1279 |
+
MarkerClusterer.prototype.removeMarker;
|
| 1280 |
+
MarkerClusterer.prototype['removeMarkers'] =
|
| 1281 |
+
MarkerClusterer.prototype.removeMarkers;
|
| 1282 |
+
MarkerClusterer.prototype['resetViewport'] =
|
| 1283 |
+
MarkerClusterer.prototype.resetViewport;
|
| 1284 |
+
MarkerClusterer.prototype['repaint'] =
|
| 1285 |
+
MarkerClusterer.prototype.repaint;
|
| 1286 |
+
MarkerClusterer.prototype['setCalculator'] =
|
| 1287 |
+
MarkerClusterer.prototype.setCalculator;
|
| 1288 |
+
MarkerClusterer.prototype['setGridSize'] =
|
| 1289 |
+
MarkerClusterer.prototype.setGridSize;
|
| 1290 |
+
MarkerClusterer.prototype['setMaxZoom'] =
|
| 1291 |
+
MarkerClusterer.prototype.setMaxZoom;
|
| 1292 |
+
MarkerClusterer.prototype['onAdd'] = MarkerClusterer.prototype.onAdd;
|
| 1293 |
+
MarkerClusterer.prototype['draw'] = MarkerClusterer.prototype.draw;
|
| 1294 |
+
|
| 1295 |
+
Cluster.prototype['getCenter'] = Cluster.prototype.getCenter;
|
| 1296 |
+
Cluster.prototype['getSize'] = Cluster.prototype.getSize;
|
| 1297 |
+
Cluster.prototype['getMarkers'] = Cluster.prototype.getMarkers;
|
| 1298 |
+
|
| 1299 |
+
ClusterIcon.prototype['onAdd'] = ClusterIcon.prototype.onAdd;
|
| 1300 |
+
ClusterIcon.prototype['draw'] = ClusterIcon.prototype.draw;
|
| 1301 |
+
ClusterIcon.prototype['onRemove'] = ClusterIcon.prototype.onRemove;
|
| 1302 |
+
|
| 1303 |
+
Object.keys = Object.keys || function(o) {
|
| 1304 |
+
var result = [];
|
| 1305 |
+
for(var name in o) {
|
| 1306 |
+
if (o.hasOwnProperty(name))
|
| 1307 |
+
result.push(name);
|
| 1308 |
+
}
|
| 1309 |
+
return result;
|
| 1310 |
+
};
|
js/indabox/storepickup.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
var IndaboxStorePickup = Class.create();
|
| 2 |
+
IndaboxStorePickup.prototype = {
|
| 3 |
+
|
| 4 |
+
initialize: function(changeMethodUrl, searchUrl, locationUrl, mediaUrl) {
|
| 5 |
+
this.changeMethodUrl = changeMethodUrl;
|
| 6 |
+
this.searchUrl = searchUrl;
|
| 7 |
+
this.locationUrl = locationUrl;
|
| 8 |
+
this.mediaUrl = mediaUrl;
|
| 9 |
+
|
| 10 |
+
this.points = [];
|
| 11 |
+
this.markers = [];
|
| 12 |
+
this.location = null;
|
| 13 |
+
this.map = null;
|
| 14 |
+
this.clusterer = null;
|
| 15 |
+
this.infoWindow = null;
|
| 16 |
+
|
| 17 |
+
this.onInit = null;
|
| 18 |
+
this.onSearchStart = null;
|
| 19 |
+
this.onSearchEnd = null;
|
| 20 |
+
this.onSelectPoint = null;
|
| 21 |
+
|
| 22 |
+
this.setUpHook();
|
| 23 |
+
},
|
| 24 |
+
|
| 25 |
+
setUpHook: function () {
|
| 26 |
+
var fallbackValidate = ShippingMethod.prototype.validate,
|
| 27 |
+
fallbackNextStep = ShippingMethod.prototype.nextStep;
|
| 28 |
+
ShippingMethod.prototype.validate = function () {
|
| 29 |
+
var result,
|
| 30 |
+
pointId,
|
| 31 |
+
methods;
|
| 32 |
+
|
| 33 |
+
result = fallbackValidate.call(this);
|
| 34 |
+
if ( ! result)
|
| 35 |
+
return false;
|
| 36 |
+
|
| 37 |
+
methods = document.getElementsByName('shipping_method');
|
| 38 |
+
for (var i=0; i<methods.length; i++) {
|
| 39 |
+
if (methods[i].checked && methods[i].value !== 'ibstorepickup_ibstorepickup') {
|
| 40 |
+
return true;
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
if ( ! $('indabox_accept_terms').checked) {
|
| 45 |
+
alert(Translator.translate('You should accept IndaBox terms and conditions').stripTags());
|
| 46 |
+
return false;
|
| 47 |
+
}
|
| 48 |
+
pointId = parseInt($('indabox_point_id').value, 10);
|
| 49 |
+
if (pointId <= 0) {
|
| 50 |
+
alert(Translator.translate('You should select one of available pick-up points to continue').stripTags());
|
| 51 |
+
return false;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
return true;
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
ShippingMethod.prototype.nextStep = function (transport) {
|
| 58 |
+
fallbackNextStep.call(this, transport);
|
| 59 |
+
checkout.reloadProgressBlock('shipping');
|
| 60 |
+
};
|
| 61 |
+
},
|
| 62 |
+
|
| 63 |
+
rebound: function () {
|
| 64 |
+
var i,
|
| 65 |
+
bounds;
|
| 66 |
+
|
| 67 |
+
if ( ! this.markers.length)
|
| 68 |
+
return;
|
| 69 |
+
|
| 70 |
+
bounds = new google.maps.LatLngBounds();
|
| 71 |
+
|
| 72 |
+
if (this.location)
|
| 73 |
+
bounds.extend(this.location.getPosition());
|
| 74 |
+
|
| 75 |
+
for (i = 0; i < this.markers.length; i++)
|
| 76 |
+
bounds.extend(this.markers[i].getPosition());
|
| 77 |
+
|
| 78 |
+
this.map.fitBounds(bounds);
|
| 79 |
+
},
|
| 80 |
+
|
| 81 |
+
showPointInfo: function (marker, idx) {
|
| 82 |
+
var point = this.points[idx];
|
| 83 |
+
this.infoWindow.setContent(
|
| 84 |
+
'<div class="indabox-info-window">' +
|
| 85 |
+
'<div class="row title">' + point.name + '</div>' +
|
| 86 |
+
'<div class="row"></div>' +
|
| 87 |
+
'<div class="row distance"><strong>' + Translator.translate('Distance') + ': </strong>' + point.distance + ' km </div>' +
|
| 88 |
+
'<div class="row telephone"><strong>' + Translator.translate('Telephone') + ': </strong>' + point.telephone + '</div>'+
|
| 89 |
+
'<div class="row select"><a class="indabox-select-me" rel="' + idx + '" href="#">' + Translator.translate('Select this pick-up point') + '</a></div>'
|
| 90 |
+
);
|
| 91 |
+
this.infoWindow.open(this.map, marker);
|
| 92 |
+
},
|
| 93 |
+
|
| 94 |
+
setPoints: function (points) {
|
| 95 |
+
var i, marker, point, caller = this;
|
| 96 |
+
for (i = 0; i < this.markers.length; i++)
|
| 97 |
+
this.markers[i].setMap(null);
|
| 98 |
+
|
| 99 |
+
this.clusterer.clearMarkers();
|
| 100 |
+
this.markers.length = 0;
|
| 101 |
+
|
| 102 |
+
this.points = points;
|
| 103 |
+
if ( ! this.points.length)
|
| 104 |
+
return;
|
| 105 |
+
|
| 106 |
+
for (i = 0; i < this.points.length; i++) {
|
| 107 |
+
point = this.points[i];
|
| 108 |
+
marker = new google.maps.Marker({
|
| 109 |
+
position: new google.maps.LatLng(point.latitude, point.longitude),
|
| 110 |
+
map: this.map,
|
| 111 |
+
icon: this.mediaUrl + 'marker_point.png',
|
| 112 |
+
shadow: 'https://chart.googleapis.com/chart?chst=d_map_pin_shadow'
|
| 113 |
+
});
|
| 114 |
+
google.maps.event.addListener(marker, 'click', (function(marker, i) {
|
| 115 |
+
return function () {
|
| 116 |
+
caller.showPointInfo(marker, i);
|
| 117 |
+
}
|
| 118 |
+
})(marker, i));
|
| 119 |
+
this.markers.push(marker);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
this.clusterer.addMarkers(this.markers);
|
| 123 |
+
|
| 124 |
+
this.rebound();
|
| 125 |
+
},
|
| 126 |
+
|
| 127 |
+
choosePoint: function (idx) {
|
| 128 |
+
this.infoWindow.close();
|
| 129 |
+
if (typeof(this.onSelectPoint) === 'function')
|
| 130 |
+
this.onSelectPoint.call(this, this.points[idx]);
|
| 131 |
+
},
|
| 132 |
+
|
| 133 |
+
initMap: function (container) {
|
| 134 |
+
var mapOptions = {
|
| 135 |
+
zoom: 5,
|
| 136 |
+
center: new google.maps.LatLng(41.9000, 12.4833)
|
| 137 |
+
},
|
| 138 |
+
caller = this;
|
| 139 |
+
|
| 140 |
+
Event.observe(container, 'click', function (event) {
|
| 141 |
+
var target = Event.findElement(event);
|
| 142 |
+
|
| 143 |
+
if (target.hasClassName('indabox-select-me')) {
|
| 144 |
+
Event.stop(event);
|
| 145 |
+
caller.choosePoint(parseInt(target.rel), 10);
|
| 146 |
+
}
|
| 147 |
+
});
|
| 148 |
+
|
| 149 |
+
this.infoWindow = new google.maps.InfoWindow();
|
| 150 |
+
this.map = new google.maps.Map(document.getElementById(container), mapOptions);
|
| 151 |
+
this.clusterer = new MarkerClusterer(this.map, this.markers);
|
| 152 |
+
|
| 153 |
+
if (typeof(this.onInit) === 'function')
|
| 154 |
+
this.onInit.call(this);
|
| 155 |
+
},
|
| 156 |
+
|
| 157 |
+
setLocation: function (lat, lng) {
|
| 158 |
+
this.location = new google.maps.Marker({
|
| 159 |
+
position: new google.maps.LatLng(lat, lng),
|
| 160 |
+
map: this.map,
|
| 161 |
+
icon: this.mediaUrl + 'marker_location.png',
|
| 162 |
+
shadow: 'https://chart.googleapis.com/chart?chst=d_map_pin_shadow'
|
| 163 |
+
});
|
| 164 |
+
|
| 165 |
+
this.rebound();
|
| 166 |
+
},
|
| 167 |
+
|
| 168 |
+
locate: function (address) {
|
| 169 |
+
var url = this.locationUrl,
|
| 170 |
+
caller = this;
|
| 171 |
+
|
| 172 |
+
if (this.location) {
|
| 173 |
+
this.location.setMap(null);
|
| 174 |
+
this.location = null;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
url = url + 'address/' + address;
|
| 178 |
+
|
| 179 |
+
new Ajax.Request(url, {
|
| 180 |
+
onSuccess: function(transport) {
|
| 181 |
+
var json = transport.responseText.evalJSON();
|
| 182 |
+
|
| 183 |
+
if (json.error) {
|
| 184 |
+
return;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
caller.setLocation(json.latitude, json.longitude);
|
| 188 |
+
}
|
| 189 |
+
});
|
| 190 |
+
},
|
| 191 |
+
|
| 192 |
+
search: function (address, radius) {
|
| 193 |
+
var url = this.searchUrl,
|
| 194 |
+
caller = this;
|
| 195 |
+
|
| 196 |
+
if (typeof(this.onSearchStart) === 'function')
|
| 197 |
+
this.onSearchStart.call(this);
|
| 198 |
+
|
| 199 |
+
this.locate(address);
|
| 200 |
+
|
| 201 |
+
url = url + 'address/' + address + '/radius/' + radius;
|
| 202 |
+
|
| 203 |
+
new Ajax.Request(url, {
|
| 204 |
+
onComplete: function () {
|
| 205 |
+
if (typeof(caller.onSearchEnd) === 'function')
|
| 206 |
+
caller.onSearchEnd.call(caller, caller.points);
|
| 207 |
+
},
|
| 208 |
+
onSuccess: function(transport) {
|
| 209 |
+
var json = transport.responseText.evalJSON();
|
| 210 |
+
|
| 211 |
+
if (json.error) {
|
| 212 |
+
alert(json.message ? json.message : Translator.translate('Error'));
|
| 213 |
+
return;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
caller.setPoints(json.points);
|
| 217 |
+
}
|
| 218 |
+
});
|
| 219 |
+
},
|
| 220 |
+
|
| 221 |
+
initGoogleMap: function (scriptUrl, container) {
|
| 222 |
+
if ( ! window.google || ! google.maps)
|
| 223 |
+
this.loadGoogleMap(scriptUrl, container);
|
| 224 |
+
else
|
| 225 |
+
this.initMap(container);
|
| 226 |
+
},
|
| 227 |
+
|
| 228 |
+
loadGoogleMap: function (scriptUrl, container) {
|
| 229 |
+
var script = document.createElement('script'),
|
| 230 |
+
functionName = 'initMap' + Math.floor(Math.random() * 1000001),
|
| 231 |
+
caller = this;
|
| 232 |
+
|
| 233 |
+
window[functionName] = function () {
|
| 234 |
+
caller.initMap(container);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
script.type = 'text/javascript';
|
| 238 |
+
script.src = scriptUrl + '&callback=' + functionName;
|
| 239 |
+
document.body.appendChild(script);
|
| 240 |
+
},
|
| 241 |
+
|
| 242 |
+
setUseStorePickup: function(flag)
|
| 243 |
+
{
|
| 244 |
+
var url = this.changeMethodUrl;
|
| 245 |
+
|
| 246 |
+
if (flag)
|
| 247 |
+
url += 'flag/1';
|
| 248 |
+
else
|
| 249 |
+
url += 'flag/0';
|
| 250 |
+
|
| 251 |
+
var request = new Ajax.Request(url, {method: 'get', onFailure: ""});
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
}
|
media/indabox/marker_location.png
ADDED
|
Binary file
|
media/indabox/marker_point.png
ADDED
|
Binary file
|
package.xml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0"?>
|
| 2 |
+
<package>
|
| 3 |
+
<name>indabox</name>
|
| 4 |
+
<version>1.0.1.1</version>
|
| 5 |
+
<stability>stable</stability>
|
| 6 |
+
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
| 7 |
+
<channel>community</channel>
|
| 8 |
+
<extends/>
|
| 9 |
+
<summary>IndaBox Shipping Method Extension</summary>
|
| 10 |
+
<description>Allow to use shipping with IndaBox</description>
|
| 11 |
+
<notes>First stable release</notes>
|
| 12 |
+
<authors><author><name>IndaBox</name><user>indabox</user><email>info@indabox.it</email></author><author><name>Advanced Logic</name><user>alogic</user><email>advancedlogiceu@gmail.com</email></author></authors>
|
| 13 |
+
<date>2014-06-11</date>
|
| 14 |
+
<time>12:16:35</time>
|
| 15 |
+
<contents><target name="magelocal"><dir name="IndaBox"><dir name="StorePickup"><dir name="Block"><dir name="Adminhtml"><dir name="Configuration"><file name="Manual.php" hash="1ea9346d7e7d04bb4dc4f4f8dfb9be82"/></dir></dir><dir name="Checkout"><dir name="Onepage"><dir name="Payment"><file name="Methods.php" hash="340a0a40207e30252a4fc08671be8a46"/></dir><dir name="Shipping"><dir name="Method"><file name="Available.php" hash="967c98f5c0bcd57ca8c793e1f8de2498"/></dir></dir></dir></dir><file name="Map.php" hash="2c644a416a2ffa7b23a19ed6ef701690"/></dir><file name="Exception.php" hash="a7e958b8282d8bd49d658edfad5df19e"/><dir name="Helper"><file name="Config.php" hash="31dba4d9d880082528218bbcd843db2c"/><file name="Data.php" hash="40a1bb55faa368ea74ac3b8cbf5a430f"/></dir><dir name="Model"><file name="Api.php" hash="585755e2c2658c18f5192ad619a339d4"/><dir name="Carrier"><file name="Storepickup.php" hash="04c74ad0e3390b6f1f5d7d3f66cb4b98"/></dir><file name="GoogleMaps.php" hash="c2eb3bceb545b0e10b689f7de0866778"/><file name="Observer.php" hash="68789fa99acefc675193032da3f720bd"/><dir name="Order"><file name="Point.php" hash="657eda40931dd6feb86b974bb36f5d96"/></dir><file name="Point.php" hash="cedd47800610db090a8937cbe8066571"/><file name="Points.php" hash="784d98055d815e48f20a4c302304d817"/><dir name="Resource"><dir name="Order"><dir name="Point"><file name="Collection.php" hash="7b4e48ec040ed1f4e44abe5a9a964daa"/></dir><file name="Point.php" hash="31a9898dbbe274afe18d6bf30f5eeb9e"/></dir></dir><dir name="Source"><file name="Payment.php" hash="f223a5951a18f2b293656fb696d4ac57"/><file name="Selectorpayment.php" hash="82f18db0f8be393a01d234d4f9c4fbc4"/></dir></dir><dir name="controllers"><file name="IndexController.php" hash="8891642df2404ab74d5804a8a74ffe5d"/></dir><dir name="etc"><file name="config.xml" hash="af7f36e74ec99ce89efd810141c04df2"/><file name="jstranslator.xml" hash="8ec2ada62b1484f3c6141006a3c4d184"/><file name="system.xml" hash="68c44ba242835e97869be4f578885b61"/></dir><dir name="sql"><dir name="ibstorepickup_setup"><file name="install-0.1.0.php" hash="32c4475a704617e53a92dad17a91000e"/></dir></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="indabox"><file name="markerclusterer.js" hash="6c3ce8c9377f8edf520c3cee2272bc29"/><file name="storepickup.js" hash="efe49a4d3b914bc8d79eb0cb33ff8680"/></dir></dir><dir name="app"><dir name="etc"><dir name="modules"><file name="IndaBox_StorePickup.xml" hash="bc600feadf12b176c134158ca2f12726"/></dir></dir></dir></target><target name="magemedia"><dir name="indabox"><file name="marker_location.png" hash="000a6513abbe2c9683b19f49873710c5"/><file name="marker_point.png" hash="ea488afc95fd4713c3ecbfcb7a0cfb38"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="ibstorepickup"><dir name="checkout"><dir name="onepage"><file name="billing.phtml" hash="9e2ec2ee9e469037af8ba3d70a718d2c"/></dir></dir><file name="map.phtml" hash="d60d7afa71cdbf48a9c7c5577849e21f"/></dir></dir><dir name="layout"><file name="ibstorepickup.xml" hash="a8fd146391dc8ece400893e4034344ec"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="indabox"><dir><dir name="css"><file name="storepickup.css" hash="30f63f16089efea263bb247e9e8888bd"/></dir><dir name="images"><file name="opc-ajax-loader.gif" hash="e805ea7eca1f34c75ba0f93780d32d38"/></dir></dir></dir></dir></dir></dir></target><target name="magelocale"><dir name="it_IT"><file name="IndaBox_StorePickup.csv" hash="11bf579e01afd50d5207ddda8f9d56f4"/></dir><dir name="en_US"><file name="IndaBox_StorePickup.csv" hash="86bdcd9e56711b3f98461a5e1ef2e41a"/></dir></target></contents>
|
| 16 |
+
<compatible/>
|
| 17 |
+
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
| 18 |
+
</package>
|
skin/frontend/base/default/indabox/css/storepickup.css
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#indabox_conditions iframe {
|
| 2 |
+
border: 0px;
|
| 3 |
+
margin: 20px 0;
|
| 4 |
+
height: 360px;
|
| 5 |
+
width: 100%;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
#indabox_search+img{
|
| 9 |
+
display: none;
|
| 10 |
+
margin: 2px 0 0 10px;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
#indabox_map {
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
#indabox_google_map {
|
| 17 |
+
width: 100%;
|
| 18 |
+
height: 360px;
|
| 19 |
+
margin-top: 20px;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
#indabox_point {
|
| 23 |
+
margin-top: 20px;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
#indabox_search.in-progress+img{
|
| 27 |
+
display: inline-block;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
.indabox-info-window {
|
| 31 |
+
padding: 5px;
|
| 32 |
+
font-size: 13px;
|
| 33 |
+
color: #555;
|
| 34 |
+
line-height: 18px;
|
| 35 |
+
font-family: arial;
|
| 36 |
+
min-width: 300px;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.indabox-info-window .row {
|
| 40 |
+
margin: 5px 0;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.indabox-info-window .row.title {
|
| 44 |
+
color: #457085;
|
| 45 |
+
text-transform: capitalize;
|
| 46 |
+
font-size: 16px;
|
| 47 |
+
margin-bottom: 15px;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
.indabox-info-window .row strong {
|
| 51 |
+
color: grey !important;
|
| 52 |
+
font-weight: 400 !important;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.indabox-info-window .row a {
|
| 56 |
+
margin-top: 7px;
|
| 57 |
+
float: left;
|
| 58 |
+
color: #9bae1d;
|
| 59 |
+
font-size: 14px;
|
| 60 |
+
text-decoration: none;
|
| 61 |
+
}
|
skin/frontend/base/default/indabox/images/opc-ajax-loader.gif
ADDED
|
Binary file
|
