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
|