Version Notes
Initial Release
Download this release
Release Info
Developer | Ilan PARMENTIER |
Extension | Mageho_Sortproducts |
Version | 1.0.1 |
Comparing to | |
See all releases |
Version 1.0.1
- app/code/local/Mageho/All/Block/System/Config/Form/Fieldset/Extensions.php +80 -0
- app/code/local/Mageho/All/Helper/Data.php +9 -0
- app/code/local/Mageho/All/etc/adminhtml.xml +30 -0
- app/code/local/Mageho/All/etc/config.xml +61 -0
- app/code/local/Mageho/All/etc/system.xml +39 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Info.php +63 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Info.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Sortgrid.php +112 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Sortgrid.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Tab.php +28 -0
- app/code/local/Mageho/Sortproducts/Block/Adminhtml/Tab.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Helper/Data.php +56 -0
- app/code/local/Mageho/Sortproducts/Helper/Data.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Model/Observer.php +36 -0
- app/code/local/Mageho/Sortproducts/Model/Observer.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Model/Resource/Position.php +43 -0
- app/code/local/Mageho/Sortproducts/Model/Resource/Position.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/Model/System/Config/Source/Attributes.php +63 -0
- app/code/local/Mageho/Sortproducts/Model/System/Config/Source/Attributes.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/controllers/Adminhtml/Mageho/SortproductsController.php +93 -0
- app/code/local/Mageho/Sortproducts/controllers/Adminhtml/Mageho/SortproductsController.php.LCK +1 -0
- app/code/local/Mageho/Sortproducts/etc/adminhtml.xml +34 -0
- app/code/local/Mageho/Sortproducts/etc/adminhtml.xml.LCK +1 -0
- app/code/local/Mageho/Sortproducts/etc/config.xml +112 -0
- app/code/local/Mageho/Sortproducts/etc/config.xml.LCK +1 -0
- app/code/local/Mageho/Sortproducts/etc/system.xml +70 -0
- app/code/local/Mageho/Sortproducts/etc/system.xml.LCK +1 -0
- app/design/adminhtml/default/default/layout/mageho/sortproducts.xml +73 -0
- app/design/adminhtml/default/default/template/mageho/sortproducts/info.phtml +37 -0
- app/design/adminhtml/default/default/template/mageho/sortproducts/sortgrid.phtml +83 -0
- app/design/adminhtml/default/default/template/mageho/sortproducts/tab.phtml +19 -0
- app/etc/modules/Mageho_All.xml +17 -0
- app/etc/modules/Mageho_Sortproducts.xml +21 -0
- app/locale/fr_FR/Mageho_All.csv +1 -0
- app/locale/fr_FR/Mageho_Sortproducts.csv +14 -0
- js/mageho/sortproducts/builder.js +136 -0
- js/mageho/sortproducts/controls.js +965 -0
- js/mageho/sortproducts/dragdrop.js +974 -0
- js/mageho/sortproducts/effects.js +1123 -0
- js/mageho/sortproducts/excanvas.js +35 -0
- js/mageho/sortproducts/loading.gif +0 -0
- js/mageho/sortproducts/opentip.css +460 -0
- js/mageho/sortproducts/opentip.js +1285 -0
- js/mageho/sortproducts/prototype.js +6081 -0
- js/mageho/sortproducts/scriptaculous.js +68 -0
- js/mageho/sortproducts/slider.js +275 -0
- js/mageho/sortproducts/sound.js +59 -0
- js/mageho/sortproducts/unittest.js +568 -0
- package.xml +64 -0
- skin/adminhtml/default/default/mageho/sortproducts/placeholder.jpg +0 -0
- skin/adminhtml/default/default/mageho/sortproducts/sortproducts.css +6 -0
app/code/local/Mageho/All/Block/System/Config/Form/Fieldset/Extensions.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_All
|
5 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
6 |
+
* @license http://www.mageho.com/license Proprietary License
|
7 |
+
*/
|
8 |
+
|
9 |
+
class Mageho_All_Block_System_Config_Form_Fieldset_Extensions extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
|
10 |
+
{
|
11 |
+
protected $_dummyElement;
|
12 |
+
protected $_fieldRenderer;
|
13 |
+
protected $_values;
|
14 |
+
|
15 |
+
public function render(Varien_Data_Form_Element_Abstract $element)
|
16 |
+
{
|
17 |
+
$html = $this->_getHeaderHtml($element);
|
18 |
+
$modules = array_keys((array)Mage::getConfig()->getNode('modules')->children());
|
19 |
+
sort($modules);
|
20 |
+
|
21 |
+
foreach ($modules as $moduleName) {
|
22 |
+
if (strstr($moduleName,'Mageho_') === false) {
|
23 |
+
continue;
|
24 |
+
}
|
25 |
+
if ($moduleName == 'Mageho_All') {
|
26 |
+
continue;
|
27 |
+
}
|
28 |
+
|
29 |
+
$html.= $this->_getFieldHtml($element, $moduleName);
|
30 |
+
}
|
31 |
+
|
32 |
+
$html .= $this->_getFooterHtml($element);
|
33 |
+
|
34 |
+
return $html;
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function _getDummyElement()
|
38 |
+
{
|
39 |
+
if (empty($this->_dummyElement)) {
|
40 |
+
$this->_dummyElement = new Varien_Object(array('show_in_default' => 1, 'show_in_website' => 1));
|
41 |
+
}
|
42 |
+
return $this->_dummyElement;
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function _getFieldRenderer()
|
46 |
+
{
|
47 |
+
if (empty($this->_fieldRenderer)) {
|
48 |
+
$this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
|
49 |
+
}
|
50 |
+
return $this->_fieldRenderer;
|
51 |
+
}
|
52 |
+
|
53 |
+
protected function _getFieldHtml($fieldset, $moduleName)
|
54 |
+
{
|
55 |
+
$name = strtolower($moduleName);
|
56 |
+
$version = Mage::getConfig()->getModuleConfig($moduleName)->version;
|
57 |
+
|
58 |
+
$field = $fieldset->addField($name, 'label',
|
59 |
+
array(
|
60 |
+
'name' => $name,
|
61 |
+
'label' => $moduleName,
|
62 |
+
'value' => $version
|
63 |
+
))->setRenderer($this->_getFieldRenderer());
|
64 |
+
|
65 |
+
return $field->toHtml();
|
66 |
+
}
|
67 |
+
|
68 |
+
protected function _convertVersion($v)
|
69 |
+
{
|
70 |
+
$digits = @explode('.', $v);
|
71 |
+
$version = 0;
|
72 |
+
|
73 |
+
if (is_array($digits)) {
|
74 |
+
foreach($digits as $k=>$v) {
|
75 |
+
$version += ($v * pow(10, max(0, (3-$k))));
|
76 |
+
}
|
77 |
+
}
|
78 |
+
return $version;
|
79 |
+
}
|
80 |
+
}
|
app/code/local/Mageho/All/Helper/Data.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_All
|
5 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
6 |
+
* @license http://www.mageho.com/license Proprietary License
|
7 |
+
*/
|
8 |
+
|
9 |
+
class Mageho_All_Helper_Data extends Mage_Core_Helper_Abstract {}
|
app/code/local/Mageho/All/etc/adminhtml.xml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_All
|
6 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
-->
|
10 |
+
<config>
|
11 |
+
<acl>
|
12 |
+
<resources>
|
13 |
+
<admin>
|
14 |
+
<children>
|
15 |
+
<system>
|
16 |
+
<children>
|
17 |
+
<config>
|
18 |
+
<children>
|
19 |
+
<magehoall>
|
20 |
+
<title>Mageho</title>
|
21 |
+
</magehoall>
|
22 |
+
</children>
|
23 |
+
</config>
|
24 |
+
</children>
|
25 |
+
</system>
|
26 |
+
</children>
|
27 |
+
</admin>
|
28 |
+
</resources>
|
29 |
+
</acl>
|
30 |
+
</config>
|
app/code/local/Mageho/All/etc/config.xml
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_All
|
6 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
-->
|
10 |
+
<config>
|
11 |
+
<modules>
|
12 |
+
<Mageho_All>
|
13 |
+
<version>1.0.0</version>
|
14 |
+
</Mageho_All>
|
15 |
+
</modules>
|
16 |
+
|
17 |
+
<global>
|
18 |
+
<blocks>
|
19 |
+
<magehoall><class>Mageho_All_Block</class></magehoall>
|
20 |
+
</blocks>
|
21 |
+
|
22 |
+
<models>
|
23 |
+
<magehoall><class>Mageho_All_Model</class></magehoall>
|
24 |
+
</models>
|
25 |
+
|
26 |
+
<helpers>
|
27 |
+
<magehoall><class>Mageho_All_Helper</class></magehoall>
|
28 |
+
</helpers>
|
29 |
+
</global>
|
30 |
+
|
31 |
+
<adminhtml>
|
32 |
+
<acl>
|
33 |
+
<resources>
|
34 |
+
<admin>
|
35 |
+
<children>
|
36 |
+
<system>
|
37 |
+
<children>
|
38 |
+
<config>
|
39 |
+
<children>
|
40 |
+
<magehoall>
|
41 |
+
<title>Mageho</title>
|
42 |
+
</magehoall>
|
43 |
+
</children>
|
44 |
+
</config>
|
45 |
+
</children>
|
46 |
+
</system>
|
47 |
+
</children>
|
48 |
+
</admin>
|
49 |
+
</resources>
|
50 |
+
</acl>
|
51 |
+
<translate>
|
52 |
+
<modules>
|
53 |
+
<Mageho_All>
|
54 |
+
<files>
|
55 |
+
<default>Mageho_All.csv</default>
|
56 |
+
</files>
|
57 |
+
</Mageho_All>
|
58 |
+
</modules>
|
59 |
+
</translate>
|
60 |
+
</adminhtml>
|
61 |
+
</config>
|
app/code/local/Mageho/All/etc/system.xml
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_All
|
6 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
-->
|
10 |
+
<config>
|
11 |
+
<tabs>
|
12 |
+
<mageho translate="label" module="magehoall">
|
13 |
+
<label>Mageho</label>
|
14 |
+
<sort_order>300</sort_order>
|
15 |
+
</mageho>
|
16 |
+
</tabs>
|
17 |
+
<sections>
|
18 |
+
<magehoall translate="label" module="magehoall">
|
19 |
+
<label>Info</label>
|
20 |
+
<tab>mageho</tab>
|
21 |
+
<frontend_type>text</frontend_type>
|
22 |
+
<sort_order>0</sort_order>
|
23 |
+
<show_in_default>1</show_in_default>
|
24 |
+
<show_in_website>1</show_in_website>
|
25 |
+
<show_in_store>1</show_in_store>
|
26 |
+
<groups>
|
27 |
+
<extensions translate="label">
|
28 |
+
<label>Installed Mageho Extensions</label>
|
29 |
+
<frontend_type>text</frontend_type>
|
30 |
+
<frontend_model>magehoall/system_config_form_fieldset_extensions</frontend_model>
|
31 |
+
<sort_order>0</sort_order>
|
32 |
+
<show_in_default>1</show_in_default>
|
33 |
+
<show_in_website>1</show_in_website>
|
34 |
+
<show_in_store>1</show_in_store>
|
35 |
+
</extensions>
|
36 |
+
</groups>
|
37 |
+
</magehoall>
|
38 |
+
</sections>
|
39 |
+
</config>
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Info.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Block_Adminhtml_Info extends Mage_Adminhtml_Block_Template
|
11 |
+
{
|
12 |
+
public function __construct()
|
13 |
+
{
|
14 |
+
parent::__construct();
|
15 |
+
$this->setTemplate('mageho/sortproducts/info.phtml');
|
16 |
+
}
|
17 |
+
|
18 |
+
protected function _prepareLayout()
|
19 |
+
{
|
20 |
+
parent::_prepareLayout();
|
21 |
+
return $this;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getSavePercentage($product)
|
25 |
+
{
|
26 |
+
if ($product->getPrice() == $product->getFinalPrice()) {
|
27 |
+
return false;
|
28 |
+
}
|
29 |
+
|
30 |
+
$save = number_format( (100 - ( $product->getFinalPrice() / $product->getPrice() ) * 100) );
|
31 |
+
return sprintf('-%d%%', $save);
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getAttributesToShow()
|
35 |
+
{
|
36 |
+
$columnSettings = array();
|
37 |
+
$attributes = explode(',', Mage::getStoreConfig('mageho_sortproducts/general/show_attributes'));
|
38 |
+
foreach ($attributes as $attribute) {
|
39 |
+
$columnSettings[] = trim($attribute);
|
40 |
+
}
|
41 |
+
|
42 |
+
if (empty($columnSettings)) {
|
43 |
+
return false;
|
44 |
+
}
|
45 |
+
|
46 |
+
$countColumnSettings = count($columnSettings);
|
47 |
+
|
48 |
+
if ($countColumnSettings < 1) {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
|
52 |
+
if ($countColumnSettings == 1 && current($columnSettings) == '') {
|
53 |
+
return false;
|
54 |
+
}
|
55 |
+
|
56 |
+
return $columnSettings;
|
57 |
+
}
|
58 |
+
|
59 |
+
public function getAttributeFrontendLabel($product, $attribute)
|
60 |
+
{
|
61 |
+
return $product->getResource()->getAttribute($attribute)->getFrontendLabel();
|
62 |
+
}
|
63 |
+
}
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Info.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Sortgrid.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Block_Adminhtml_Sortgrid extends Mage_Adminhtml_Block_Template
|
11 |
+
{
|
12 |
+
public function __construct()
|
13 |
+
{
|
14 |
+
parent::__construct();
|
15 |
+
$this->setTemplate('mageho/sortproducts/sortgrid.phtml');
|
16 |
+
}
|
17 |
+
|
18 |
+
protected function _prepareLayout()
|
19 |
+
{
|
20 |
+
parent::_prepareLayout();
|
21 |
+
return $this;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* ACL validation before html generation
|
26 |
+
*
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
protected function _toHtml()
|
30 |
+
{
|
31 |
+
if (Mage::getSingleton('admin/session')->isAllowed('catalog/categories')) {
|
32 |
+
return parent::_toHtml();
|
33 |
+
}
|
34 |
+
return '';
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getProductsCollection()
|
38 |
+
{
|
39 |
+
if (!$this->_productsCollection)
|
40 |
+
{
|
41 |
+
$store = (int) $this->getRequest()->getParam('store', 0);
|
42 |
+
$category_id = (int) $this->getRequest()->getParam('id', 0);
|
43 |
+
|
44 |
+
$category = Mage::getSingleton('catalog/category')->setStoreId($store)->load($category_id);
|
45 |
+
$products = $category->getProductsPosition();
|
46 |
+
|
47 |
+
$collection = Mage::getModel('catalog/product')->getCollection()
|
48 |
+
#->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
|
49 |
+
->addAttributeToSelect('*')
|
50 |
+
->joinField('position', 'catalog/category_product', 'position', 'product_id=entity_id', '{{table}}.category_id='.$category_id, 'left')
|
51 |
+
#->joinField('qty', 'cataloginventory/stock_item', 'qty', 'product_id=entity_id', '{{table}}.stock_id=1', 'left')
|
52 |
+
#->joinField('rating', 'review/review_aggregate', 'rating_summary', 'entity_pk_value=entity_id', '{{table}}.store_id=1', 'left') // Modifier store_id
|
53 |
+
->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner', $store)
|
54 |
+
->addFieldToFilter('visibility', array('in' => array(Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG, Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH)))
|
55 |
+
->addFieldToFilter('entity_id', array('in' => array_keys($products)))
|
56 |
+
->addStoreFilter($store);
|
57 |
+
|
58 |
+
if (Mage::helper('mageho_sortproducts')->displayOnlyEnabledProducts()) {
|
59 |
+
$collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner', $store)
|
60 |
+
->addFieldToFilter('status', 1);
|
61 |
+
}
|
62 |
+
|
63 |
+
// On cache les produits épuisés
|
64 |
+
if (Mage::helper('mageho_sortproducts')->displayOutStockProducts()) {
|
65 |
+
if ($websiteId = Mage::app()->getWebsite()->getWebsiteId()) {
|
66 |
+
$collection->joinField('stock_status', 'cataloginventory/stock_status', 'stock_status', 'product_id=entity_id', array('stock_status' => Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK, 'website_id' => $websiteId));
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
$collection->setOrder('position', 'asc');
|
71 |
+
|
72 |
+
if ($limit = Mage::helper('mageho_sortproducts')->limitSortProducts()) {
|
73 |
+
$collection->setPageSize($limit);
|
74 |
+
}
|
75 |
+
|
76 |
+
$collection->setCurPage(1);
|
77 |
+
|
78 |
+
$this->_productsCollection = $collection;
|
79 |
+
}
|
80 |
+
return $this->_productsCollection;
|
81 |
+
}
|
82 |
+
|
83 |
+
public function getImageWidth()
|
84 |
+
{
|
85 |
+
return Mage::helper('mageho_sortproducts')->getImageWidth();
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Retrieve Session Form Key
|
90 |
+
*
|
91 |
+
* @return string
|
92 |
+
*/
|
93 |
+
public function getFormKey()
|
94 |
+
{
|
95 |
+
return Mage::getSingleton('core/session')->getFormKey();
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getSaveUrl()
|
99 |
+
{
|
100 |
+
return $this->getUrl('*/*/save', array('_current' => true));
|
101 |
+
}
|
102 |
+
|
103 |
+
public function getProductInfoUrl($product)
|
104 |
+
{
|
105 |
+
return $this->getUrl('*/*/info', array('id' => $product->getId(), '_current' => true));
|
106 |
+
}
|
107 |
+
|
108 |
+
public function isDisabled($product)
|
109 |
+
{
|
110 |
+
return $product->getStatus() && ($product->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
|
111 |
+
}
|
112 |
+
}
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Sortgrid.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Tab.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Block_Adminhtml_Tab extends Mage_Adminhtml_Block_Template
|
11 |
+
{
|
12 |
+
public function __construct()
|
13 |
+
{
|
14 |
+
parent::__construct();
|
15 |
+
$this->setTemplate('mageho/sortproducts/tab.phtml');
|
16 |
+
}
|
17 |
+
|
18 |
+
protected function _prepareLayout()
|
19 |
+
{
|
20 |
+
parent::_prepareLayout();
|
21 |
+
return $this;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getSortProductsUrl()
|
25 |
+
{
|
26 |
+
return $this->getUrl('adminhtml/mageho_sortproducts/index', array('_current' => true));
|
27 |
+
}
|
28 |
+
}
|
app/code/local/Mageho/Sortproducts/Block/Adminhtml/Tab.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Helper/Data.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Helper_Data extends Mage_Core_Helper_Abstract
|
11 |
+
{
|
12 |
+
const SORTPRODUCTS_DISPLAY_OUT_STOCK_PRODUCTS = 'sortproducts/general/display_out_stock_products';
|
13 |
+
const SORTPRODUCTS_DISPLAY_ONLY_ENABLED_PRODUCTS = 'sortproducts/general/display_only_enabled_products';
|
14 |
+
const SORTPRODUCTS_LIMIT_PRODUCTS = 'sortproducts/general/limit_products';
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Translate
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
public function __()
|
22 |
+
{
|
23 |
+
$args = func_get_args();
|
24 |
+
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mageho_Sortproducts');
|
25 |
+
array_unshift($args, $expr);
|
26 |
+
return utf8_encode(Mage::app()->getTranslator()->translate($args));
|
27 |
+
}
|
28 |
+
|
29 |
+
public function displayOutStockProducts()
|
30 |
+
{
|
31 |
+
return Mage::getStoreConfigFlag(self::SORTPRODUCTS_DISPLAY_OUT_STOCK_PRODUCTS);
|
32 |
+
}
|
33 |
+
|
34 |
+
public function displayOnlyEnabledProducts()
|
35 |
+
{
|
36 |
+
return Mage::getStoreConfigFlag(self::SORTPRODUCTS_DISPLAY_ONLY_ENABLED_PRODUCTS);
|
37 |
+
}
|
38 |
+
|
39 |
+
public function limitSortProducts()
|
40 |
+
{
|
41 |
+
$limit = (int) Mage::getStoreConfig(self::SORTPRODUCTS_LIMIT_PRODUCTS, 0);
|
42 |
+
if ($limit > 0) {
|
43 |
+
return $limit;
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getImageWidth()
|
48 |
+
{
|
49 |
+
$width = (int) Mage::getStoreConfig('mageho_sortproducts/general/image_width');
|
50 |
+
if ($width > 0) {
|
51 |
+
return $width;
|
52 |
+
} else {
|
53 |
+
return 60;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
app/code/local/Mageho/Sortproducts/Helper/Data.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Model/Observer.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Model_Observer
|
11 |
+
{
|
12 |
+
public function addTabToCategoryPage($observer)
|
13 |
+
{
|
14 |
+
$event = $observer->getEvent();
|
15 |
+
$tabs = $event->getTabs();
|
16 |
+
$category = $tabs->getCategory();
|
17 |
+
$count = $category->getProductCount();
|
18 |
+
|
19 |
+
if ($category->getId() && ($count > 1))
|
20 |
+
{
|
21 |
+
$tabs->addTab('mageho_sortproducts', array(
|
22 |
+
'label' => Mage::helper('mageho_sortproducts')->__('Sort Category Products'),
|
23 |
+
'content' => $tabs->getLayout()->createBlock('mageho_sortproducts/adminhtml_tab')->setTemplate('mageho/sortproducts/tab.phtml')->toHtml()
|
24 |
+
|
25 |
+
/*
|
26 |
+
* Pour charger le bloc en ajax ajouter ces lignes et enlever la clé content juste au-dessus
|
27 |
+
*/
|
28 |
+
|
29 |
+
#'url' => Mage::getUrl('adminhtml/mageho_sortproducts/tab', array('_current' => true)),
|
30 |
+
#'class' => 'ajax'
|
31 |
+
));
|
32 |
+
}
|
33 |
+
|
34 |
+
return $this;
|
35 |
+
}
|
36 |
+
}
|
app/code/local/Mageho/Sortproducts/Model/Observer.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Model/Resource/Position.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproduct
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
#class Mageho_Sortproducts_Model_Mysql4_Position extends Mage_Catalog_Model_Resource_Eav_Mysql4_Category
|
11 |
+
class Mageho_Sortproducts_Model_Resource_Position extends Mage_Catalog_Model_Resource_Category
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Initialize resource
|
15 |
+
*/
|
16 |
+
public function __construct()
|
17 |
+
{
|
18 |
+
parent::__construct();
|
19 |
+
$resource = Mage::getSingleton('core/resource');
|
20 |
+
$this->setType('catalog_category')
|
21 |
+
->setConnection(
|
22 |
+
$resource->getConnection('catalog_read'),
|
23 |
+
$resource->getConnection('catalog_write')
|
24 |
+
);
|
25 |
+
|
26 |
+
$this->_productCategoryTable = $resource->getTableName('catalog/category_product');
|
27 |
+
$this->_productCategoryIndexTable = $resource->getTableName('catalog/category_product_index');
|
28 |
+
}
|
29 |
+
|
30 |
+
public function save($position, $productId, $categoryId)
|
31 |
+
{
|
32 |
+
$condition = array(
|
33 |
+
$this->_getWriteAdapter()->quoteInto("product_id=?", $productId),
|
34 |
+
$this->_getWriteAdapter()->quoteInto("category_id=?", $categoryId)
|
35 |
+
);
|
36 |
+
|
37 |
+
$db = $this->_getWriteAdapter();
|
38 |
+
$db->update($this->_productCategoryTable, array('position' => $position), $condition);
|
39 |
+
$db->update($this->_productCategoryIndexTable, array('position' => $position), $condition);
|
40 |
+
|
41 |
+
return $this;
|
42 |
+
}
|
43 |
+
}
|
app/code/local/Mageho/Sortproducts/Model/Resource/Position.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/Model/System/Config/Source/Attributes.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Model_System_Config_Source_Attributes
|
11 |
+
{
|
12 |
+
public $doNotDisplayAttributesArray = array('price', 'tier_price', 'group_price', 'special_price', 'name', 'sku',
|
13 |
+
'description', 'tax_class_id', 'url_key', 'options_container', 'price_view', 'gift_message_available',
|
14 |
+
'custom_design', 'custom_design_from', 'custom_design_to', 'custom_layout_update', 'page_layout',
|
15 |
+
'visibility', 'status', 'enable_googlecheckout');
|
16 |
+
|
17 |
+
public function toOptionArray()
|
18 |
+
{
|
19 |
+
$cols = array();
|
20 |
+
$cols[] = array('value' => '', 'label' => Mage::helper('mageho_sortproducts')->__('None'));
|
21 |
+
$cols[] = array('value' => 'type_id', 'label' => Mage::helper('mageho_sortproducts')->__('Product Type (simple, bundle, etc)'));
|
22 |
+
$cols[] = array('value' => 'attribute_set_id', 'label' => Mage::helper('mageho_sortproducts')->__('Attribute Set'));
|
23 |
+
$cols[] = array('value' => 'created_at', 'label' => Mage::helper('mageho_sortproducts')->__('Date Created'));
|
24 |
+
|
25 |
+
foreach ($this->getAttributes() as $attribute) {
|
26 |
+
$label = $attribute->getFrontendLabel() . ' - ' . $attribute->getAttributeCode() . ' #'.$attribute->getAttributeId();
|
27 |
+
|
28 |
+
$cols[] = array('value' => $attribute->getAttributeCode(), 'label' => $label);
|
29 |
+
}
|
30 |
+
|
31 |
+
return $cols;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return Mage_Eav_Model_Mysql4_Entity_Attribute_Collection
|
36 |
+
*/
|
37 |
+
protected function getAttributes()
|
38 |
+
{
|
39 |
+
if (version_compare(Mage::getVersion(), '1.4', '>=')) {
|
40 |
+
$collection = Mage::getResourceModel( 'catalog/product_attribute_collection');
|
41 |
+
} else {
|
42 |
+
$type_id = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId();
|
43 |
+
$collection = Mage::getResourceModel('eav/entity_attribute_collection');
|
44 |
+
$collection->setEntityTypeFilter($type_id);
|
45 |
+
}
|
46 |
+
|
47 |
+
$collection->addFilter('is_visible', 1);
|
48 |
+
|
49 |
+
$allowedAttributes = array();
|
50 |
+
foreach ($collection->getItems() as $attribute) {
|
51 |
+
if ( in_array($attribute->getFrontendInput(), array('media_image', 'gallery')) ) {
|
52 |
+
continue;
|
53 |
+
}
|
54 |
+
if ( in_array($attribute->getAttributeCode(), $this->doNotDisplayAttributesArray) ) {
|
55 |
+
continue;
|
56 |
+
}
|
57 |
+
|
58 |
+
$allowedAttributes[] = $attribute;
|
59 |
+
}
|
60 |
+
|
61 |
+
return $allowedAttributes;
|
62 |
+
}
|
63 |
+
}
|
app/code/local/Mageho/Sortproducts/Model/System/Config/Source/Attributes.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/controllers/Adminhtml/Mageho/SortproductsController.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @version 1.0.0
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
|
10 |
+
class Mageho_Sortproducts_Adminhtml_Mageho_SortproductsController
|
11 |
+
extends Mage_Adminhtml_Controller_Action
|
12 |
+
{
|
13 |
+
public function indexAction()
|
14 |
+
{
|
15 |
+
$this->loadLayout();
|
16 |
+
$this->renderLayout();
|
17 |
+
}
|
18 |
+
|
19 |
+
public function tabAction()
|
20 |
+
{
|
21 |
+
$this->getResponse()->setBody(
|
22 |
+
$this->getLayout()->createBlock('mageho_sortproducts/adminhtml_tab')->toHtml()
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
public function infoAction()
|
27 |
+
{
|
28 |
+
$productId = $this->getRequest()->getParam('id', false);
|
29 |
+
$product = Mage::getModel('catalog/product')
|
30 |
+
->setStoreId($this->getRequest()->getParam('store', 0));
|
31 |
+
|
32 |
+
if ($productId) {
|
33 |
+
$product->load($productId);
|
34 |
+
|
35 |
+
Mage::register('product', $product);
|
36 |
+
Mage::register('current_product', $product);
|
37 |
+
|
38 |
+
$this->getResponse()->setBody(
|
39 |
+
$this->getLayout()->createBlock('mageho_sortproducts/adminhtml_info')->toHtml()
|
40 |
+
);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
public function saveAction()
|
45 |
+
{
|
46 |
+
$data = $this->getRequest()->getPost('data');
|
47 |
+
$categoryId = $this->getRequest()->getParam('id', false);
|
48 |
+
|
49 |
+
try {
|
50 |
+
if (! $data) {
|
51 |
+
throw new Exception('no data post parameters');
|
52 |
+
}
|
53 |
+
|
54 |
+
$category = Mage::getModel('catalog/category')
|
55 |
+
->setStoreId($this->getRequest()->getParam('store', 0));
|
56 |
+
|
57 |
+
if ($categoryId) {
|
58 |
+
$category->load($categoryId);
|
59 |
+
|
60 |
+
if ($category->getId()) {
|
61 |
+
parse_str($data);
|
62 |
+
for ($i = 0; $i < count($sortlist); $i++) {
|
63 |
+
$position = $i;
|
64 |
+
$productId = $sortlist[$i];
|
65 |
+
|
66 |
+
Mage::getResourceModel('mageho_sortproducts/position')->save($position, $productId, $category->getId());
|
67 |
+
}
|
68 |
+
|
69 |
+
Mage::app()->cleanCache(array(Mage_Catalog_Model_Category::CACHE_TAG.'_'.$category->getId()));
|
70 |
+
|
71 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(
|
72 |
+
Mage::helper('mageho_sortproducts')->__('The position of products has been saved with success.')
|
73 |
+
);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
} catch (Exception $e) {
|
77 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
78 |
+
}
|
79 |
+
|
80 |
+
$resetUrl = Mage::helper('adminhtml')->getUrl('adminhtml/catalog_category/edit', array('active_tab_id' => 'category_info_tabs_sortproducts', '_current' => true));
|
81 |
+
$this->getResponse()->setBody("window.top.categoryReset('{$resetUrl}', true);");
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Check if admin has permissions to visit categories pages
|
86 |
+
*
|
87 |
+
* @return boolean
|
88 |
+
*/
|
89 |
+
protected function _isAllowed()
|
90 |
+
{
|
91 |
+
return Mage::getSingleton('admin/session')->isAllowed('catalog/categories');
|
92 |
+
}
|
93 |
+
}
|
app/code/local/Mageho/Sortproducts/controllers/Adminhtml/Mageho/SortproductsController.php.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/etc/adminhtml.xml
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_SortProducts
|
6 |
+
* @version 1.0.0
|
7 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
8 |
+
* @license http://www.mageho.com/license Proprietary License
|
9 |
+
*/
|
10 |
+
-->
|
11 |
+
<config>
|
12 |
+
<acl>
|
13 |
+
<resources>
|
14 |
+
<all translate="title" module="mageho_sortproducts">
|
15 |
+
<title>Allow Everything</title>
|
16 |
+
</all>
|
17 |
+
<admin>
|
18 |
+
<children>
|
19 |
+
<system>
|
20 |
+
<children>
|
21 |
+
<config>
|
22 |
+
<children>
|
23 |
+
<mageho_sortproducts translate="title" module="mageho_sortproducts">
|
24 |
+
<title>Merchandising</title>
|
25 |
+
</mageho_sortproducts>
|
26 |
+
</children>
|
27 |
+
</config>
|
28 |
+
</children>
|
29 |
+
</system>
|
30 |
+
</children>
|
31 |
+
</admin>
|
32 |
+
</resources>
|
33 |
+
</acl>
|
34 |
+
</config>
|
app/code/local/Mageho/Sortproducts/etc/adminhtml.xml.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/etc/config.xml
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_Sortproducts
|
6 |
+
* @version 1.0.0
|
7 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
8 |
+
* @license http://www.mageho.com/license Proprietary License
|
9 |
+
*/
|
10 |
+
-->
|
11 |
+
<config>
|
12 |
+
<modules>
|
13 |
+
<Mageho_Sortproducts>
|
14 |
+
<version>1.0.0</version>
|
15 |
+
</Mageho_Sortproducts>
|
16 |
+
</modules>
|
17 |
+
<global>
|
18 |
+
<blocks>
|
19 |
+
<mageho_sortproducts>
|
20 |
+
<class>Mageho_Sortproducts_Block</class>
|
21 |
+
</mageho_sortproducts>
|
22 |
+
</blocks>
|
23 |
+
<helpers>
|
24 |
+
<mageho_sortproducts>
|
25 |
+
<class>Mageho_Sortproducts_Helper</class>
|
26 |
+
</mageho_sortproducts>
|
27 |
+
</helpers>
|
28 |
+
<models>
|
29 |
+
<mageho_sortproducts>
|
30 |
+
<class>Mageho_Sortproducts_Model</class>
|
31 |
+
<!-- resourceModel>sortproducts_mysql4</resourceModel -->
|
32 |
+
<resourceModel>mageho_sortproducts_resource</resourceModel>
|
33 |
+
</mageho_sortproducts>
|
34 |
+
<!--sortproducts_mysql4>
|
35 |
+
<class>Mageho_Sortproducts_Model_Mysql4</class>
|
36 |
+
</sortproducts_mysql4-->
|
37 |
+
<mageho_sortproducts_resource>
|
38 |
+
<class>Mageho_Sortproducts_Model_Resource</class>
|
39 |
+
</mageho_sortproducts_resource>
|
40 |
+
</models>
|
41 |
+
<resources>
|
42 |
+
<mageho_sortproducts_setup>
|
43 |
+
<setup>
|
44 |
+
<module>Mageho_Sortproducts</module>
|
45 |
+
</setup>
|
46 |
+
<connection>
|
47 |
+
<use>core_setup</use>
|
48 |
+
</connection>
|
49 |
+
</mageho_sortproducts_setup>
|
50 |
+
<mageho_sortproducts_write>
|
51 |
+
<connection>
|
52 |
+
<use>core_write</use>
|
53 |
+
</connection>
|
54 |
+
</mageho_sortproducts_write>
|
55 |
+
<mageho_sortproducts_read>
|
56 |
+
<connection>
|
57 |
+
<use>core_read</use>
|
58 |
+
</connection>
|
59 |
+
</mageho_sortproducts_read>
|
60 |
+
</resources>
|
61 |
+
<events>
|
62 |
+
<adminhtml_catalog_category_tabs>
|
63 |
+
<observers>
|
64 |
+
<mageho_sortproducts>
|
65 |
+
<type>singleton</type>
|
66 |
+
<class>mageho_sortproducts/observer</class>
|
67 |
+
<method>addTabToCategoryPage</method>
|
68 |
+
</mageho_sortproducts>
|
69 |
+
</observers>
|
70 |
+
</adminhtml_catalog_category_tabs>
|
71 |
+
</events>
|
72 |
+
</global>
|
73 |
+
<admin>
|
74 |
+
<routers>
|
75 |
+
<adminhtml>
|
76 |
+
<args>
|
77 |
+
<modules>
|
78 |
+
<Mageho_Sortproducts before="Mage_Adminhtml">Mageho_Sortproducts_Adminhtml</Mageho_Sortproducts>
|
79 |
+
</modules>
|
80 |
+
</args>
|
81 |
+
</adminhtml>
|
82 |
+
</routers>
|
83 |
+
</admin>
|
84 |
+
<adminhtml>
|
85 |
+
<translate>
|
86 |
+
<modules>
|
87 |
+
<Mageho_Sortproducts>
|
88 |
+
<files>
|
89 |
+
<default>Mageho_Sortproducts.csv</default>
|
90 |
+
</files>
|
91 |
+
</Mageho_Sortproducts>
|
92 |
+
</modules>
|
93 |
+
</translate>
|
94 |
+
<layout>
|
95 |
+
<updates>
|
96 |
+
<mageho_sortproducts>
|
97 |
+
<file>mageho/sortproducts.xml</file>
|
98 |
+
</mageho_sortproducts>
|
99 |
+
</updates>
|
100 |
+
</layout>
|
101 |
+
</adminhtml>
|
102 |
+
<default>
|
103 |
+
<mageho_sortproducts>
|
104 |
+
<general>
|
105 |
+
<limit_products>0</limit_products>
|
106 |
+
<image_width>50</image_width>
|
107 |
+
<display_only_enabled_products>0</display_only_enabled_products>
|
108 |
+
<display_out_stock_products>0</display_out_stock_products>
|
109 |
+
</general>
|
110 |
+
</mageho_sortproducts>
|
111 |
+
</default>
|
112 |
+
</config>
|
app/code/local/Mageho/Sortproducts/etc/config.xml.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/code/local/Mageho/Sortproducts/etc/system.xml
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_Sortproducts
|
6 |
+
* @version 1.0.0
|
7 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
8 |
+
* @license http://www.mageho.com/license Proprietary License
|
9 |
+
*/
|
10 |
+
-->
|
11 |
+
<config>
|
12 |
+
<sections>
|
13 |
+
<mageho_sortproducts translate="label" module="mageho_sortproducts">
|
14 |
+
<label>Merchandising</label>
|
15 |
+
<tab>mageho</tab>
|
16 |
+
<frontend_type>text</frontend_type>
|
17 |
+
<sort_order>200</sort_order>
|
18 |
+
<show_in_default>1</show_in_default>
|
19 |
+
<show_in_website>1</show_in_website>
|
20 |
+
<show_in_store>0</show_in_store>
|
21 |
+
<groups>
|
22 |
+
<general translate="label">
|
23 |
+
<label>General</label>
|
24 |
+
<show_in_default>1</show_in_default>
|
25 |
+
<show_in_website>0</show_in_website>
|
26 |
+
<show_in_store>0</show_in_store>
|
27 |
+
<fields>
|
28 |
+
<limit_products translate="label comment">
|
29 |
+
<label>Limit number of products in iframe</label>
|
30 |
+
<comment>Enter 0 for no limit - This parameter can improve performance loading</comment>
|
31 |
+
<frontend_type>text</frontend_type>
|
32 |
+
<sort_order>0</sort_order>
|
33 |
+
<show_in_default>1</show_in_default>
|
34 |
+
<show_in_website>1</show_in_website>
|
35 |
+
</limit_products>
|
36 |
+
<image_width translate="label">
|
37 |
+
<label>Image Width</label>
|
38 |
+
<frontend_type>text</frontend_type>
|
39 |
+
<sort_order>10</sort_order>
|
40 |
+
<show_in_default>1</show_in_default>
|
41 |
+
<show_in_website>1</show_in_website>
|
42 |
+
</image_width>
|
43 |
+
<show_attributes translate="label">
|
44 |
+
<label>Show Attributes</label>
|
45 |
+
<frontend_type>multiselect</frontend_type>
|
46 |
+
<source_model>Mageho_Sortproducts_Model_System_Config_Source_Attributes</source_model>
|
47 |
+
<sort_order>20</sort_order>
|
48 |
+
<show_in_default>1</show_in_default>
|
49 |
+
<show_in_website>1</show_in_website>
|
50 |
+
</show_attributes>
|
51 |
+
<display_only_enabled_products translate="label">
|
52 |
+
<label>Display Only Enabled Products</label>
|
53 |
+
<frontend_type>select</frontend_type>
|
54 |
+
<sort_order>30</sort_order>
|
55 |
+
<show_in_default>1</show_in_default>
|
56 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
57 |
+
</display_only_enabled_products>
|
58 |
+
<display_out_stock_products translate="label">
|
59 |
+
<label>Display Out of Stock Products</label>
|
60 |
+
<frontend_type>select</frontend_type>
|
61 |
+
<sort_order>40</sort_order>
|
62 |
+
<show_in_default>1</show_in_default>
|
63 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
64 |
+
</display_out_stock_products>
|
65 |
+
</fields>
|
66 |
+
</general>
|
67 |
+
</groups>
|
68 |
+
</mageho_sortproducts>
|
69 |
+
</sections>
|
70 |
+
</config>
|
app/code/local/Mageho/Sortproducts/etc/system.xml.LCK
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
Ilan Parmentier||ilan.parmentier@artbambou.com
|
app/design/adminhtml/default/default/layout/mageho/sortproducts.xml
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_Sortproducts
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
* @version 1.0.0
|
9 |
+
*/
|
10 |
+
-->
|
11 |
+
<layout version="0.1.0">
|
12 |
+
<adminhtml_mageho_sortproducts_index>
|
13 |
+
<update handle="popup" />
|
14 |
+
<remove name="head.calendar" />
|
15 |
+
<remove name="notifications" />
|
16 |
+
<remove name="footer" />
|
17 |
+
|
18 |
+
<reference name="head">
|
19 |
+
<action method="removeItem"><type>js</type><name>prototype/prototype.js</name></action>
|
20 |
+
<action method="removeItem"><type>js</type><name>prototype/window.js</name></action>
|
21 |
+
<action method="removeItem"><type>js</type><name>scriptaculous/builder.js</name></action>
|
22 |
+
<action method="removeItem"><type>js</type><name>scriptaculous/effects.js</name></action>
|
23 |
+
<action method="removeItem"><type>js</type><name>scriptaculous/dragdrop.js</name></action>
|
24 |
+
<action method="removeItem"><type>js</type><name>scriptaculous/controls.js</name></action>
|
25 |
+
<action method="removeItem"><type>js</type><name>scriptaculous/slider.js</name></action>
|
26 |
+
<action method="removeItem"><type>js</type><name>lib/ccard.js</name></action>
|
27 |
+
<action method="removeItem"><type>js</type><name>prototype/validation.js</name></action>
|
28 |
+
<action method="removeItem"><type>js</type><name>varien/js.js</name></action>
|
29 |
+
<action method="removeItem"><type>js</type><name>mage/translate.js</name></action>
|
30 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/hash.js</name></action>
|
31 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/events.js</name></action>
|
32 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/loader.js</name></action>
|
33 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/grid.js</name></action>
|
34 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/tabs.js</name></action>
|
35 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/form.js</name></action>
|
36 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/accordion.js</name></action>
|
37 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/tools.js</name></action>
|
38 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/uploader.js</name></action>
|
39 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/product.js</name></action>
|
40 |
+
<action method="removeItem"><type>js</type><name>calendar/calendar.js</name></action>
|
41 |
+
<action method="removeItem"><type>js</type><name>calendar/calendar-setup.js</name></action>
|
42 |
+
<action method="removeItem"><type>js</type><name>mage/adminhtml/rules.js</name></action>
|
43 |
+
|
44 |
+
<!-- Extension EmProductsFilter -->
|
45 |
+
<action method="removeItem"><type>js</type><name>em/productsfilter/productsfilter.js</name></action>
|
46 |
+
|
47 |
+
<!-- Extension Files Download -->
|
48 |
+
<action method="removeItem"><type>js</type><name>mageworx/fileuploader.js</name></action>
|
49 |
+
|
50 |
+
<!-- Extension EnhancedGrid -->
|
51 |
+
<action method="removeItem"><type>js</type><name>tbt/enhancedgrid/enhancedgrid.js</name></action>
|
52 |
+
<action method="removeItem"><type>js</type><name>tbt/enhancedgrid/egsupplemental.js</name></action>
|
53 |
+
<action method="removeItem"><type>js</type><name>tbt/enhancedgrid/customfunctions/catalog_products.js</name></action>
|
54 |
+
|
55 |
+
<action method="addJs"><script>mageho/sortproducts/prototype.js</script></action>
|
56 |
+
|
57 |
+
<!-- Ne fonctionne que si les fichiers javascript ne sont pas fusionnés -->
|
58 |
+
<!-- action method="addJs"><script>mageho/sortproducts/scriptaculous.js</script></action -->
|
59 |
+
|
60 |
+
<action method="addJs"><script>mageho/sortproducts/effects.js</script></action>
|
61 |
+
<action method="addJs"><script>mageho/sortproducts/dragdrop.js</script></action>
|
62 |
+
<action method="addJs"><script>mageho/sortproducts/opentip.js</script></action>
|
63 |
+
<action method="addJs"><script>mageho/sortproducts/excanvas.js</script></action>
|
64 |
+
<action method="addItem"><type>js_css</type><name>mageho/sortproducts/opentip.css</name></action>
|
65 |
+
|
66 |
+
<action method="addCss"><name>mageho/sortproducts/sortproducts.css</name></action>
|
67 |
+
</reference>
|
68 |
+
|
69 |
+
<reference name="content">
|
70 |
+
<block type="mageho_sortproducts/adminhtml_sortgrid" name="mageho.sortgrid" />
|
71 |
+
</reference>
|
72 |
+
</adminhtml_mageho_sortproducts_index>
|
73 |
+
</layout>
|
app/design/adminhtml/default/default/template/mageho/sortproducts/info.phtml
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
6 |
+
* @license http://www.mageho.com/license Proprietary License
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
?>
|
10 |
+
<?php $_product = Mage::registry('current_product'); ?>
|
11 |
+
<div>
|
12 |
+
<ul class="square-list">
|
13 |
+
<li><small><?php echo $this->__('ID'); ?> : <?php echo $_product->getId(); ?></small></li>
|
14 |
+
|
15 |
+
<?php if ($_product->getSku()): ?>
|
16 |
+
<li><small><?php echo $this->__('SKU'); ?> : <?php echo $_product->getSku(); ?></small></li>
|
17 |
+
<?php endif; ?>
|
18 |
+
|
19 |
+
<li>
|
20 |
+
<?php echo $this->__('Price'); ?> :
|
21 |
+
<?php if ($_product->getSpecialPrice()): ?>
|
22 |
+
<del><?php echo $this->helper('core')->currency($_product->getPrice()); ?></del>
|
23 |
+
<ins><?php echo $this->helper('core')->currency($_product->getSpecialPrice()); ?></ins>
|
24 |
+
|
25 |
+
<?php echo $this->getSavePercentage($_product); ?>
|
26 |
+
<?php else: ?>
|
27 |
+
<?php echo $this->helper('core')->currency($_product->getPrice()); ?>
|
28 |
+
<?php endif; ?>
|
29 |
+
</li>
|
30 |
+
|
31 |
+
<?php if ($attributes = $this->getAttributesToShow()): ?>
|
32 |
+
<?php foreach($attributes as $attribute): ?>
|
33 |
+
<li><?php echo $this->getAttributeFrontendLabel($_product, $attribute); ?> : <?php echo ($_product->getData($attribute) ? $_product->getData($attribute) : $this->__('N.C.')); ?></li>
|
34 |
+
<?php endforeach; ?>
|
35 |
+
<?php endif; ?>
|
36 |
+
</ul>
|
37 |
+
</div>
|
app/design/adminhtml/default/default/template/mageho/sortproducts/sortgrid.phtml
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
6 |
+
* @license http://www.mageho.com/license Proprietary License
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
?>
|
10 |
+
<?php if (($_products = $this->getProductsCollection()) && $_products->getSize()): ?>
|
11 |
+
<script type="text/javascript">
|
12 |
+
//<![CDATA[
|
13 |
+
document.observe('dom:loaded', function() {
|
14 |
+
Sortable.create('sortlist', {
|
15 |
+
tag: 'li',
|
16 |
+
only: 'sorting',
|
17 |
+
hoverclass: 'over',
|
18 |
+
overlap: 'horizontal',
|
19 |
+
ghosting: false,
|
20 |
+
constraint: false,
|
21 |
+
scroll: window,
|
22 |
+
scrollSensitivity: 30,
|
23 |
+
scrollSpeed: 25
|
24 |
+
})
|
25 |
+
|
26 |
+
$$('button.button-save-sortable').each(function(el) {
|
27 |
+
el.onclick = function() {
|
28 |
+
new Ajax.Request("<?php echo $this->getSaveUrl(); ?>", {
|
29 |
+
method: "post",
|
30 |
+
evalScripts: true,
|
31 |
+
onLoading: function() { parent.$('loading-mask').show() },
|
32 |
+
onSuccess: function(transport) { parent.$('loading-mask').hide() },
|
33 |
+
onComplete:function(transport) { eval(transport.responseText) },
|
34 |
+
parameters: {
|
35 |
+
data: Sortable.serialize('sortlist'),
|
36 |
+
form_key: '<?php echo $this->getFormKey(); ?>'
|
37 |
+
}
|
38 |
+
})
|
39 |
+
}
|
40 |
+
})
|
41 |
+
})
|
42 |
+
//]]>
|
43 |
+
</script>
|
44 |
+
|
45 |
+
<div id="messages"></div>
|
46 |
+
|
47 |
+
<div class="content-header">
|
48 |
+
<div class="content-buttons-placeholder"><p class="content-buttons form-buttons"><button type="button" class="scalable button-save-sortable"><span><?php echo $this->__('Save Products Position'); ?></span></button></p></div>
|
49 |
+
</div>
|
50 |
+
|
51 |
+
<div id="sortlist-wrapper">
|
52 |
+
<ul id="sortlist">
|
53 |
+
<?php foreach ($_products->getItems() as $_product): ?>
|
54 |
+
<li id="product_<?php echo $_product->getId(); ?>" class="sorting">
|
55 |
+
<div class="product_container">
|
56 |
+
|
57 |
+
<?php
|
58 |
+
# Error message for no products with image
|
59 |
+
# core/Mage/Catalog/Helper/Image.php(163): Mage_Catalog_Model_Product_Image->setBaseFile('no_selection')
|
60 |
+
|
61 |
+
try {
|
62 |
+
$imageUrl = $this->helper('catalog/image')->init($_product, 'thumbnail')->resize($this->getImageWidth());
|
63 |
+
} catch(Exception $e) {
|
64 |
+
$imageUrl = Mage::getDesign()->getSkinUrl('mageho/sortproducts/placeholder.jpg');
|
65 |
+
}
|
66 |
+
?>
|
67 |
+
|
68 |
+
<img src="<?php echo $imageUrl; ?>" width="<?php echo $this->getImageWidth(); ?>" alt="<?php echo $this->htmlEscape($_product->getName()); ?>" class="sorting-image" longdesc="<?php echo $this->getProductInfoUrl($_product); ?>" <?php if ($this->isDisabled($_product)): ?>style="opacity:0.3"<?php endif; ?> />
|
69 |
+
<?php if (!$_product->isSaleable() && !$_product->isConfigurable()): ?><div class="saleable"><?php echo $this->helper('catalog')->__('Out of stock'); ?></div><?php endif; ?>
|
70 |
+
</div>
|
71 |
+
</li>
|
72 |
+
<?php endforeach; ?>
|
73 |
+
</ul>
|
74 |
+
</div>
|
75 |
+
|
76 |
+
<script type="text/javascript">
|
77 |
+
//<![CDATA[
|
78 |
+
$$('.sorting-image').each(function(image) {
|
79 |
+
image.addTip({ title: image.alt, style: 'slick', ajax: { url: image.readAttribute('longdesc'), options: { parameters: { form_key: '<?php echo $this->getFormKey(); ?>'} } } });
|
80 |
+
});
|
81 |
+
//]]>
|
82 |
+
</script>
|
83 |
+
<?php endif; ?>
|
app/design/adminhtml/default/default/template/mageho/sortproducts/tab.phtml
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* @category Mageho
|
4 |
+
* @package Mageho_Sortproducts
|
5 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
6 |
+
* @license http://www.mageho.com/license Proprietary License
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
?>
|
10 |
+
<div class="entry-edit">
|
11 |
+
<div class="entry-edit-head">
|
12 |
+
<h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('Sort Products'); ?></h4>
|
13 |
+
<div class="form-buttons"></div>
|
14 |
+
</div>
|
15 |
+
|
16 |
+
<div class="fieldset">
|
17 |
+
<iframe id="sortproductsdraganddrop" src="<?php echo $this->getSortProductsUrl(); ?>" width="100%" height="500" scrolling="yes" allowtransparency="true" frameborder="0" style="overflow:auto;"></iframe>
|
18 |
+
</div>
|
19 |
+
</div>
|
app/etc/modules/Mageho_All.xml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_All
|
6 |
+
* @copyright Copyright (c) 2012 - 2013 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
-->
|
10 |
+
<config>
|
11 |
+
<modules>
|
12 |
+
<Mageho_All>
|
13 |
+
<active>true</active>
|
14 |
+
<codePool>local</codePool>
|
15 |
+
</Mageho_All>
|
16 |
+
</modules>
|
17 |
+
</config>
|
app/etc/modules/Mageho_Sortproducts.xml
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
/*
|
4 |
+
* @category Mageho
|
5 |
+
* @package Mageho_Sortproducts
|
6 |
+
* @copyright Copyright (c) 2012 Mageho (http://www.mageho.com)
|
7 |
+
* @license http://www.mageho.com/license Proprietary License
|
8 |
+
*/
|
9 |
+
-->
|
10 |
+
<config>
|
11 |
+
<modules>
|
12 |
+
<Mageho_Sortproducts>
|
13 |
+
<active>true</active>
|
14 |
+
<codePool>local</codePool>
|
15 |
+
<depends>
|
16 |
+
<Mage_Adminhtml />
|
17 |
+
<Mage_Catalog />
|
18 |
+
</depends>
|
19 |
+
</Mageho_Sortproducts>
|
20 |
+
</modules>
|
21 |
+
</config>
|
app/locale/fr_FR/Mageho_All.csv
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
"Installed Mageho Extensions","Extensions Mageho installées"
|
app/locale/fr_FR/Mageho_Sortproducts.csv
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"%d position's product have been saved.","%s positions de produit ont �t� sauvegard�es."
|
2 |
+
"Enter 0 for no limit - This parameter can improve performance loading","Entrer 0 pour aucune limitation - Ce param�tre peut am�liorer les performances de chargement."
|
3 |
+
"Display Only Enabled Products","Afficher seulement les produits dont le statut est activ�"
|
4 |
+
"Display Out of Stock Products","Afficher les produits en rupture de stock"
|
5 |
+
"Image Width","Taille d'image"
|
6 |
+
"Limit number of products in iframe","Limiter le nombre de produits"
|
7 |
+
"General","G�n�ral"
|
8 |
+
"None","Aucun"
|
9 |
+
"Product Type (simple, bundle, etc)","Type produit (simple, bundle, etc)"
|
10 |
+
"Save Products Position","Sauvegarder la position des produits"
|
11 |
+
"Show Attributes","Afficher les attributs produits suivants"
|
12 |
+
"Sort Products","Trier les produits"
|
13 |
+
"Sort Category Products","Merchandising produits"
|
14 |
+
"The position of products has been saved with success.","La position des produits a bien �t� sauvegard�e avec succ�s."
|
js/mageho/sortproducts/builder.js
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us builder.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
//
|
5 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
6 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
7 |
+
|
8 |
+
var Builder = {
|
9 |
+
NODEMAP: {
|
10 |
+
AREA: 'map',
|
11 |
+
CAPTION: 'table',
|
12 |
+
COL: 'table',
|
13 |
+
COLGROUP: 'table',
|
14 |
+
LEGEND: 'fieldset',
|
15 |
+
OPTGROUP: 'select',
|
16 |
+
OPTION: 'select',
|
17 |
+
PARAM: 'object',
|
18 |
+
TBODY: 'table',
|
19 |
+
TD: 'table',
|
20 |
+
TFOOT: 'table',
|
21 |
+
TH: 'table',
|
22 |
+
THEAD: 'table',
|
23 |
+
TR: 'table'
|
24 |
+
},
|
25 |
+
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
|
26 |
+
// due to a Firefox bug
|
27 |
+
node: function(elementName) {
|
28 |
+
elementName = elementName.toUpperCase();
|
29 |
+
|
30 |
+
// try innerHTML approach
|
31 |
+
var parentTag = this.NODEMAP[elementName] || 'div';
|
32 |
+
var parentElement = document.createElement(parentTag);
|
33 |
+
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
34 |
+
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
|
35 |
+
} catch(e) {}
|
36 |
+
var element = parentElement.firstChild || null;
|
37 |
+
|
38 |
+
// see if browser added wrapping tags
|
39 |
+
if(element && (element.tagName.toUpperCase() != elementName))
|
40 |
+
element = element.getElementsByTagName(elementName)[0];
|
41 |
+
|
42 |
+
// fallback to createElement approach
|
43 |
+
if(!element) element = document.createElement(elementName);
|
44 |
+
|
45 |
+
// abort if nothing could be created
|
46 |
+
if(!element) return;
|
47 |
+
|
48 |
+
// attributes (or text)
|
49 |
+
if(arguments[1])
|
50 |
+
if(this._isStringOrNumber(arguments[1]) ||
|
51 |
+
(arguments[1] instanceof Array) ||
|
52 |
+
arguments[1].tagName) {
|
53 |
+
this._children(element, arguments[1]);
|
54 |
+
} else {
|
55 |
+
var attrs = this._attributes(arguments[1]);
|
56 |
+
if(attrs.length) {
|
57 |
+
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
58 |
+
parentElement.innerHTML = "<" +elementName + " " +
|
59 |
+
attrs + "></" + elementName + ">";
|
60 |
+
} catch(e) {}
|
61 |
+
element = parentElement.firstChild || null;
|
62 |
+
// workaround firefox 1.0.X bug
|
63 |
+
if(!element) {
|
64 |
+
element = document.createElement(elementName);
|
65 |
+
for(attr in arguments[1])
|
66 |
+
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
|
67 |
+
}
|
68 |
+
if(element.tagName.toUpperCase() != elementName)
|
69 |
+
element = parentElement.getElementsByTagName(elementName)[0];
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
// text, or array of children
|
74 |
+
if(arguments[2])
|
75 |
+
this._children(element, arguments[2]);
|
76 |
+
|
77 |
+
return $(element);
|
78 |
+
},
|
79 |
+
_text: function(text) {
|
80 |
+
return document.createTextNode(text);
|
81 |
+
},
|
82 |
+
|
83 |
+
ATTR_MAP: {
|
84 |
+
'className': 'class',
|
85 |
+
'htmlFor': 'for'
|
86 |
+
},
|
87 |
+
|
88 |
+
_attributes: function(attributes) {
|
89 |
+
var attrs = [];
|
90 |
+
for(attribute in attributes)
|
91 |
+
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
|
92 |
+
'="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"');
|
93 |
+
return attrs.join(" ");
|
94 |
+
},
|
95 |
+
_children: function(element, children) {
|
96 |
+
if(children.tagName) {
|
97 |
+
element.appendChild(children);
|
98 |
+
return;
|
99 |
+
}
|
100 |
+
if(typeof children=='object') { // array can hold nodes and text
|
101 |
+
children.flatten().each( function(e) {
|
102 |
+
if(typeof e=='object')
|
103 |
+
element.appendChild(e);
|
104 |
+
else
|
105 |
+
if(Builder._isStringOrNumber(e))
|
106 |
+
element.appendChild(Builder._text(e));
|
107 |
+
});
|
108 |
+
} else
|
109 |
+
if(Builder._isStringOrNumber(children))
|
110 |
+
element.appendChild(Builder._text(children));
|
111 |
+
},
|
112 |
+
_isStringOrNumber: function(param) {
|
113 |
+
return(typeof param=='string' || typeof param=='number');
|
114 |
+
},
|
115 |
+
build: function(html) {
|
116 |
+
var element = this.node('div');
|
117 |
+
$(element).update(html.strip());
|
118 |
+
return element.down();
|
119 |
+
},
|
120 |
+
dump: function(scope) {
|
121 |
+
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
|
122 |
+
|
123 |
+
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
|
124 |
+
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
|
125 |
+
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
|
126 |
+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
|
127 |
+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
|
128 |
+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
|
129 |
+
|
130 |
+
tags.each( function(tag){
|
131 |
+
scope[tag] = function() {
|
132 |
+
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
|
133 |
+
};
|
134 |
+
});
|
135 |
+
}
|
136 |
+
};
|
js/mageho/sortproducts/controls.js
ADDED
@@ -0,0 +1,965 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us controls.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
// (c) 2005-2010 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
5 |
+
// (c) 2005-2010 Jon Tirsen (http://www.tirsen.com)
|
6 |
+
// Contributors:
|
7 |
+
// Richard Livsey
|
8 |
+
// Rahul Bhargava
|
9 |
+
// Rob Wills
|
10 |
+
//
|
11 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
12 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
13 |
+
|
14 |
+
// Autocompleter.Base handles all the autocompletion functionality
|
15 |
+
// that's independent of the data source for autocompletion. This
|
16 |
+
// includes drawing the autocompletion menu, observing keyboard
|
17 |
+
// and mouse events, and similar.
|
18 |
+
//
|
19 |
+
// Specific autocompleters need to provide, at the very least,
|
20 |
+
// a getUpdatedChoices function that will be invoked every time
|
21 |
+
// the text inside the monitored textbox changes. This method
|
22 |
+
// should get the text for which to provide autocompletion by
|
23 |
+
// invoking this.getToken(), NOT by directly accessing
|
24 |
+
// this.element.value. This is to allow incremental tokenized
|
25 |
+
// autocompletion. Specific auto-completion logic (AJAX, etc)
|
26 |
+
// belongs in getUpdatedChoices.
|
27 |
+
//
|
28 |
+
// Tokenized incremental autocompletion is enabled automatically
|
29 |
+
// when an autocompleter is instantiated with the 'tokens' option
|
30 |
+
// in the options parameter, e.g.:
|
31 |
+
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
|
32 |
+
// will incrementally autocomplete with a comma as the token.
|
33 |
+
// Additionally, ',' in the above example can be replaced with
|
34 |
+
// a token array, e.g. { tokens: [',', '\n'] } which
|
35 |
+
// enables autocompletion on multiple tokens. This is most
|
36 |
+
// useful when one of the tokens is \n (a newline), as it
|
37 |
+
// allows smart autocompletion after linebreaks.
|
38 |
+
|
39 |
+
if(typeof Effect == 'undefined')
|
40 |
+
throw("controls.js requires including script.aculo.us' effects.js library");
|
41 |
+
|
42 |
+
var Autocompleter = { };
|
43 |
+
Autocompleter.Base = Class.create({
|
44 |
+
baseInitialize: function(element, update, options) {
|
45 |
+
element = $(element);
|
46 |
+
this.element = element;
|
47 |
+
this.update = $(update);
|
48 |
+
this.hasFocus = false;
|
49 |
+
this.changed = false;
|
50 |
+
this.active = false;
|
51 |
+
this.index = 0;
|
52 |
+
this.entryCount = 0;
|
53 |
+
this.oldElementValue = this.element.value;
|
54 |
+
|
55 |
+
if(this.setOptions)
|
56 |
+
this.setOptions(options);
|
57 |
+
else
|
58 |
+
this.options = options || { };
|
59 |
+
|
60 |
+
this.options.paramName = this.options.paramName || this.element.name;
|
61 |
+
this.options.tokens = this.options.tokens || [];
|
62 |
+
this.options.frequency = this.options.frequency || 0.4;
|
63 |
+
this.options.minChars = this.options.minChars || 1;
|
64 |
+
this.options.onShow = this.options.onShow ||
|
65 |
+
function(element, update){
|
66 |
+
if(!update.style.position || update.style.position=='absolute') {
|
67 |
+
update.style.position = 'absolute';
|
68 |
+
Position.clone(element, update, {
|
69 |
+
setHeight: false,
|
70 |
+
offsetTop: element.offsetHeight
|
71 |
+
});
|
72 |
+
}
|
73 |
+
Effect.Appear(update,{duration:0.15});
|
74 |
+
};
|
75 |
+
this.options.onHide = this.options.onHide ||
|
76 |
+
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
|
77 |
+
|
78 |
+
if(typeof(this.options.tokens) == 'string')
|
79 |
+
this.options.tokens = new Array(this.options.tokens);
|
80 |
+
// Force carriage returns as token delimiters anyway
|
81 |
+
if (!this.options.tokens.include('\n'))
|
82 |
+
this.options.tokens.push('\n');
|
83 |
+
|
84 |
+
this.observer = null;
|
85 |
+
|
86 |
+
this.element.setAttribute('autocomplete','off');
|
87 |
+
|
88 |
+
Element.hide(this.update);
|
89 |
+
|
90 |
+
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
|
91 |
+
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
|
92 |
+
},
|
93 |
+
|
94 |
+
show: function() {
|
95 |
+
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
|
96 |
+
if(!this.iefix &&
|
97 |
+
(Prototype.Browser.IE) &&
|
98 |
+
(Element.getStyle(this.update, 'position')=='absolute')) {
|
99 |
+
new Insertion.After(this.update,
|
100 |
+
'<iframe id="' + this.update.id + '_iefix" '+
|
101 |
+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
|
102 |
+
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
|
103 |
+
this.iefix = $(this.update.id+'_iefix');
|
104 |
+
}
|
105 |
+
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
|
106 |
+
},
|
107 |
+
|
108 |
+
fixIEOverlapping: function() {
|
109 |
+
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
|
110 |
+
this.iefix.style.zIndex = 1;
|
111 |
+
this.update.style.zIndex = 2;
|
112 |
+
Element.show(this.iefix);
|
113 |
+
},
|
114 |
+
|
115 |
+
hide: function() {
|
116 |
+
this.stopIndicator();
|
117 |
+
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
|
118 |
+
if(this.iefix) Element.hide(this.iefix);
|
119 |
+
},
|
120 |
+
|
121 |
+
startIndicator: function() {
|
122 |
+
if(this.options.indicator) Element.show(this.options.indicator);
|
123 |
+
},
|
124 |
+
|
125 |
+
stopIndicator: function() {
|
126 |
+
if(this.options.indicator) Element.hide(this.options.indicator);
|
127 |
+
},
|
128 |
+
|
129 |
+
onKeyPress: function(event) {
|
130 |
+
if(this.active)
|
131 |
+
switch(event.keyCode) {
|
132 |
+
case Event.KEY_TAB:
|
133 |
+
case Event.KEY_RETURN:
|
134 |
+
this.selectEntry();
|
135 |
+
Event.stop(event);
|
136 |
+
case Event.KEY_ESC:
|
137 |
+
this.hide();
|
138 |
+
this.active = false;
|
139 |
+
Event.stop(event);
|
140 |
+
return;
|
141 |
+
case Event.KEY_LEFT:
|
142 |
+
case Event.KEY_RIGHT:
|
143 |
+
return;
|
144 |
+
case Event.KEY_UP:
|
145 |
+
this.markPrevious();
|
146 |
+
this.render();
|
147 |
+
Event.stop(event);
|
148 |
+
return;
|
149 |
+
case Event.KEY_DOWN:
|
150 |
+
this.markNext();
|
151 |
+
this.render();
|
152 |
+
Event.stop(event);
|
153 |
+
return;
|
154 |
+
}
|
155 |
+
else
|
156 |
+
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
|
157 |
+
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
|
158 |
+
|
159 |
+
this.changed = true;
|
160 |
+
this.hasFocus = true;
|
161 |
+
|
162 |
+
if(this.observer) clearTimeout(this.observer);
|
163 |
+
this.observer =
|
164 |
+
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
|
165 |
+
},
|
166 |
+
|
167 |
+
activate: function() {
|
168 |
+
this.changed = false;
|
169 |
+
this.hasFocus = true;
|
170 |
+
this.getUpdatedChoices();
|
171 |
+
},
|
172 |
+
|
173 |
+
onHover: function(event) {
|
174 |
+
var element = Event.findElement(event, 'LI');
|
175 |
+
if(this.index != element.autocompleteIndex)
|
176 |
+
{
|
177 |
+
this.index = element.autocompleteIndex;
|
178 |
+
this.render();
|
179 |
+
}
|
180 |
+
Event.stop(event);
|
181 |
+
},
|
182 |
+
|
183 |
+
onClick: function(event) {
|
184 |
+
var element = Event.findElement(event, 'LI');
|
185 |
+
this.index = element.autocompleteIndex;
|
186 |
+
this.selectEntry();
|
187 |
+
this.hide();
|
188 |
+
},
|
189 |
+
|
190 |
+
onBlur: function(event) {
|
191 |
+
// needed to make click events working
|
192 |
+
setTimeout(this.hide.bind(this), 250);
|
193 |
+
this.hasFocus = false;
|
194 |
+
this.active = false;
|
195 |
+
},
|
196 |
+
|
197 |
+
render: function() {
|
198 |
+
if(this.entryCount > 0) {
|
199 |
+
for (var i = 0; i < this.entryCount; i++)
|
200 |
+
this.index==i ?
|
201 |
+
Element.addClassName(this.getEntry(i),"selected") :
|
202 |
+
Element.removeClassName(this.getEntry(i),"selected");
|
203 |
+
if(this.hasFocus) {
|
204 |
+
this.show();
|
205 |
+
this.active = true;
|
206 |
+
}
|
207 |
+
} else {
|
208 |
+
this.active = false;
|
209 |
+
this.hide();
|
210 |
+
}
|
211 |
+
},
|
212 |
+
|
213 |
+
markPrevious: function() {
|
214 |
+
if(this.index > 0) this.index--;
|
215 |
+
else this.index = this.entryCount-1;
|
216 |
+
this.getEntry(this.index).scrollIntoView(true);
|
217 |
+
},
|
218 |
+
|
219 |
+
markNext: function() {
|
220 |
+
if(this.index < this.entryCount-1) this.index++;
|
221 |
+
else this.index = 0;
|
222 |
+
this.getEntry(this.index).scrollIntoView(false);
|
223 |
+
},
|
224 |
+
|
225 |
+
getEntry: function(index) {
|
226 |
+
return this.update.firstChild.childNodes[index];
|
227 |
+
},
|
228 |
+
|
229 |
+
getCurrentEntry: function() {
|
230 |
+
return this.getEntry(this.index);
|
231 |
+
},
|
232 |
+
|
233 |
+
selectEntry: function() {
|
234 |
+
this.active = false;
|
235 |
+
this.updateElement(this.getCurrentEntry());
|
236 |
+
},
|
237 |
+
|
238 |
+
updateElement: function(selectedElement) {
|
239 |
+
if (this.options.updateElement) {
|
240 |
+
this.options.updateElement(selectedElement);
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
var value = '';
|
244 |
+
if (this.options.select) {
|
245 |
+
var nodes = $(selectedElement).select('.' + this.options.select) || [];
|
246 |
+
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
|
247 |
+
} else
|
248 |
+
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
|
249 |
+
|
250 |
+
var bounds = this.getTokenBounds();
|
251 |
+
if (bounds[0] != -1) {
|
252 |
+
var newValue = this.element.value.substr(0, bounds[0]);
|
253 |
+
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
|
254 |
+
if (whitespace)
|
255 |
+
newValue += whitespace[0];
|
256 |
+
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
|
257 |
+
} else {
|
258 |
+
this.element.value = value;
|
259 |
+
}
|
260 |
+
this.oldElementValue = this.element.value;
|
261 |
+
this.element.focus();
|
262 |
+
|
263 |
+
if (this.options.afterUpdateElement)
|
264 |
+
this.options.afterUpdateElement(this.element, selectedElement);
|
265 |
+
},
|
266 |
+
|
267 |
+
updateChoices: function(choices) {
|
268 |
+
if(!this.changed && this.hasFocus) {
|
269 |
+
this.update.innerHTML = choices;
|
270 |
+
Element.cleanWhitespace(this.update);
|
271 |
+
Element.cleanWhitespace(this.update.down());
|
272 |
+
|
273 |
+
if(this.update.firstChild && this.update.down().childNodes) {
|
274 |
+
this.entryCount =
|
275 |
+
this.update.down().childNodes.length;
|
276 |
+
for (var i = 0; i < this.entryCount; i++) {
|
277 |
+
var entry = this.getEntry(i);
|
278 |
+
entry.autocompleteIndex = i;
|
279 |
+
this.addObservers(entry);
|
280 |
+
}
|
281 |
+
} else {
|
282 |
+
this.entryCount = 0;
|
283 |
+
}
|
284 |
+
|
285 |
+
this.stopIndicator();
|
286 |
+
this.index = 0;
|
287 |
+
|
288 |
+
if(this.entryCount==1 && this.options.autoSelect) {
|
289 |
+
this.selectEntry();
|
290 |
+
this.hide();
|
291 |
+
} else {
|
292 |
+
this.render();
|
293 |
+
}
|
294 |
+
}
|
295 |
+
},
|
296 |
+
|
297 |
+
addObservers: function(element) {
|
298 |
+
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
|
299 |
+
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
|
300 |
+
},
|
301 |
+
|
302 |
+
onObserverEvent: function() {
|
303 |
+
this.changed = false;
|
304 |
+
this.tokenBounds = null;
|
305 |
+
if(this.getToken().length>=this.options.minChars) {
|
306 |
+
this.getUpdatedChoices();
|
307 |
+
} else {
|
308 |
+
this.active = false;
|
309 |
+
this.hide();
|
310 |
+
}
|
311 |
+
this.oldElementValue = this.element.value;
|
312 |
+
},
|
313 |
+
|
314 |
+
getToken: function() {
|
315 |
+
var bounds = this.getTokenBounds();
|
316 |
+
return this.element.value.substring(bounds[0], bounds[1]).strip();
|
317 |
+
},
|
318 |
+
|
319 |
+
getTokenBounds: function() {
|
320 |
+
if (null != this.tokenBounds) return this.tokenBounds;
|
321 |
+
var value = this.element.value;
|
322 |
+
if (value.strip().empty()) return [-1, 0];
|
323 |
+
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
|
324 |
+
var offset = (diff == this.oldElementValue.length ? 1 : 0);
|
325 |
+
var prevTokenPos = -1, nextTokenPos = value.length;
|
326 |
+
var tp;
|
327 |
+
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
|
328 |
+
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
|
329 |
+
if (tp > prevTokenPos) prevTokenPos = tp;
|
330 |
+
tp = value.indexOf(this.options.tokens[index], diff + offset);
|
331 |
+
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
|
332 |
+
}
|
333 |
+
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
|
334 |
+
}
|
335 |
+
});
|
336 |
+
|
337 |
+
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
|
338 |
+
var boundary = Math.min(newS.length, oldS.length);
|
339 |
+
for (var index = 0; index < boundary; ++index)
|
340 |
+
if (newS[index] != oldS[index])
|
341 |
+
return index;
|
342 |
+
return boundary;
|
343 |
+
};
|
344 |
+
|
345 |
+
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
|
346 |
+
initialize: function(element, update, url, options) {
|
347 |
+
this.baseInitialize(element, update, options);
|
348 |
+
this.options.asynchronous = true;
|
349 |
+
this.options.onComplete = this.onComplete.bind(this);
|
350 |
+
this.options.defaultParams = this.options.parameters || null;
|
351 |
+
this.url = url;
|
352 |
+
},
|
353 |
+
|
354 |
+
getUpdatedChoices: function() {
|
355 |
+
this.startIndicator();
|
356 |
+
|
357 |
+
var entry = encodeURIComponent(this.options.paramName) + '=' +
|
358 |
+
encodeURIComponent(this.getToken());
|
359 |
+
|
360 |
+
this.options.parameters = this.options.callback ?
|
361 |
+
this.options.callback(this.element, entry) : entry;
|
362 |
+
|
363 |
+
if(this.options.defaultParams)
|
364 |
+
this.options.parameters += '&' + this.options.defaultParams;
|
365 |
+
|
366 |
+
new Ajax.Request(this.url, this.options);
|
367 |
+
},
|
368 |
+
|
369 |
+
onComplete: function(request) {
|
370 |
+
this.updateChoices(request.responseText);
|
371 |
+
}
|
372 |
+
});
|
373 |
+
|
374 |
+
// The local array autocompleter. Used when you'd prefer to
|
375 |
+
// inject an array of autocompletion options into the page, rather
|
376 |
+
// than sending out Ajax queries, which can be quite slow sometimes.
|
377 |
+
//
|
378 |
+
// The constructor takes four parameters. The first two are, as usual,
|
379 |
+
// the id of the monitored textbox, and id of the autocompletion menu.
|
380 |
+
// The third is the array you want to autocomplete from, and the fourth
|
381 |
+
// is the options block.
|
382 |
+
//
|
383 |
+
// Extra local autocompletion options:
|
384 |
+
// - choices - How many autocompletion choices to offer
|
385 |
+
//
|
386 |
+
// - partialSearch - If false, the autocompleter will match entered
|
387 |
+
// text only at the beginning of strings in the
|
388 |
+
// autocomplete array. Defaults to true, which will
|
389 |
+
// match text at the beginning of any *word* in the
|
390 |
+
// strings in the autocomplete array. If you want to
|
391 |
+
// search anywhere in the string, additionally set
|
392 |
+
// the option fullSearch to true (default: off).
|
393 |
+
//
|
394 |
+
// - fullSsearch - Search anywhere in autocomplete array strings.
|
395 |
+
//
|
396 |
+
// - partialChars - How many characters to enter before triggering
|
397 |
+
// a partial match (unlike minChars, which defines
|
398 |
+
// how many characters are required to do any match
|
399 |
+
// at all). Defaults to 2.
|
400 |
+
//
|
401 |
+
// - ignoreCase - Whether to ignore case when autocompleting.
|
402 |
+
// Defaults to true.
|
403 |
+
//
|
404 |
+
// It's possible to pass in a custom function as the 'selector'
|
405 |
+
// option, if you prefer to write your own autocompletion logic.
|
406 |
+
// In that case, the other options above will not apply unless
|
407 |
+
// you support them.
|
408 |
+
|
409 |
+
Autocompleter.Local = Class.create(Autocompleter.Base, {
|
410 |
+
initialize: function(element, update, array, options) {
|
411 |
+
this.baseInitialize(element, update, options);
|
412 |
+
this.options.array = array;
|
413 |
+
},
|
414 |
+
|
415 |
+
getUpdatedChoices: function() {
|
416 |
+
this.updateChoices(this.options.selector(this));
|
417 |
+
},
|
418 |
+
|
419 |
+
setOptions: function(options) {
|
420 |
+
this.options = Object.extend({
|
421 |
+
choices: 10,
|
422 |
+
partialSearch: true,
|
423 |
+
partialChars: 2,
|
424 |
+
ignoreCase: true,
|
425 |
+
fullSearch: false,
|
426 |
+
selector: function(instance) {
|
427 |
+
var ret = []; // Beginning matches
|
428 |
+
var partial = []; // Inside matches
|
429 |
+
var entry = instance.getToken();
|
430 |
+
var count = 0;
|
431 |
+
|
432 |
+
for (var i = 0; i < instance.options.array.length &&
|
433 |
+
ret.length < instance.options.choices ; i++) {
|
434 |
+
|
435 |
+
var elem = instance.options.array[i];
|
436 |
+
var foundPos = instance.options.ignoreCase ?
|
437 |
+
elem.toLowerCase().indexOf(entry.toLowerCase()) :
|
438 |
+
elem.indexOf(entry);
|
439 |
+
|
440 |
+
while (foundPos != -1) {
|
441 |
+
if (foundPos == 0 && elem.length != entry.length) {
|
442 |
+
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
|
443 |
+
elem.substr(entry.length) + "</li>");
|
444 |
+
break;
|
445 |
+
} else if (entry.length >= instance.options.partialChars &&
|
446 |
+
instance.options.partialSearch && foundPos != -1) {
|
447 |
+
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
|
448 |
+
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
|
449 |
+
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
|
450 |
+
foundPos + entry.length) + "</li>");
|
451 |
+
break;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
foundPos = instance.options.ignoreCase ?
|
456 |
+
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
|
457 |
+
elem.indexOf(entry, foundPos + 1);
|
458 |
+
|
459 |
+
}
|
460 |
+
}
|
461 |
+
if (partial.length)
|
462 |
+
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
|
463 |
+
return "<ul>" + ret.join('') + "</ul>";
|
464 |
+
}
|
465 |
+
}, options || { });
|
466 |
+
}
|
467 |
+
});
|
468 |
+
|
469 |
+
// AJAX in-place editor and collection editor
|
470 |
+
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
|
471 |
+
|
472 |
+
// Use this if you notice weird scrolling problems on some browsers,
|
473 |
+
// the DOM might be a bit confused when this gets called so do this
|
474 |
+
// waits 1 ms (with setTimeout) until it does the activation
|
475 |
+
Field.scrollFreeActivate = function(field) {
|
476 |
+
setTimeout(function() {
|
477 |
+
Field.activate(field);
|
478 |
+
}, 1);
|
479 |
+
};
|
480 |
+
|
481 |
+
Ajax.InPlaceEditor = Class.create({
|
482 |
+
initialize: function(element, url, options) {
|
483 |
+
this.url = url;
|
484 |
+
this.element = element = $(element);
|
485 |
+
this.prepareOptions();
|
486 |
+
this._controls = { };
|
487 |
+
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
|
488 |
+
Object.extend(this.options, options || { });
|
489 |
+
if (!this.options.formId && this.element.id) {
|
490 |
+
this.options.formId = this.element.id + '-inplaceeditor';
|
491 |
+
if ($(this.options.formId))
|
492 |
+
this.options.formId = '';
|
493 |
+
}
|
494 |
+
if (this.options.externalControl)
|
495 |
+
this.options.externalControl = $(this.options.externalControl);
|
496 |
+
if (!this.options.externalControl)
|
497 |
+
this.options.externalControlOnly = false;
|
498 |
+
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
|
499 |
+
this.element.title = this.options.clickToEditText;
|
500 |
+
this._boundCancelHandler = this.handleFormCancellation.bind(this);
|
501 |
+
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
|
502 |
+
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
|
503 |
+
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
|
504 |
+
this._boundWrapperHandler = this.wrapUp.bind(this);
|
505 |
+
this.registerListeners();
|
506 |
+
},
|
507 |
+
checkForEscapeOrReturn: function(e) {
|
508 |
+
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
|
509 |
+
if (Event.KEY_ESC == e.keyCode)
|
510 |
+
this.handleFormCancellation(e);
|
511 |
+
else if (Event.KEY_RETURN == e.keyCode)
|
512 |
+
this.handleFormSubmission(e);
|
513 |
+
},
|
514 |
+
createControl: function(mode, handler, extraClasses) {
|
515 |
+
var control = this.options[mode + 'Control'];
|
516 |
+
var text = this.options[mode + 'Text'];
|
517 |
+
if ('button' == control) {
|
518 |
+
var btn = document.createElement('input');
|
519 |
+
btn.type = 'submit';
|
520 |
+
btn.value = text;
|
521 |
+
btn.className = 'editor_' + mode + '_button';
|
522 |
+
if ('cancel' == mode)
|
523 |
+
btn.onclick = this._boundCancelHandler;
|
524 |
+
this._form.appendChild(btn);
|
525 |
+
this._controls[mode] = btn;
|
526 |
+
} else if ('link' == control) {
|
527 |
+
var link = document.createElement('a');
|
528 |
+
link.href = '#';
|
529 |
+
link.appendChild(document.createTextNode(text));
|
530 |
+
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
|
531 |
+
link.className = 'editor_' + mode + '_link';
|
532 |
+
if (extraClasses)
|
533 |
+
link.className += ' ' + extraClasses;
|
534 |
+
this._form.appendChild(link);
|
535 |
+
this._controls[mode] = link;
|
536 |
+
}
|
537 |
+
},
|
538 |
+
createEditField: function() {
|
539 |
+
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
|
540 |
+
var fld;
|
541 |
+
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
|
542 |
+
fld = document.createElement('input');
|
543 |
+
fld.type = 'text';
|
544 |
+
var size = this.options.size || this.options.cols || 0;
|
545 |
+
if (0 < size) fld.size = size;
|
546 |
+
} else {
|
547 |
+
fld = document.createElement('textarea');
|
548 |
+
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
|
549 |
+
fld.cols = this.options.cols || 40;
|
550 |
+
}
|
551 |
+
fld.name = this.options.paramName;
|
552 |
+
fld.value = text; // No HTML breaks conversion anymore
|
553 |
+
fld.className = 'editor_field';
|
554 |
+
if (this.options.submitOnBlur)
|
555 |
+
fld.onblur = this._boundSubmitHandler;
|
556 |
+
this._controls.editor = fld;
|
557 |
+
if (this.options.loadTextURL)
|
558 |
+
this.loadExternalText();
|
559 |
+
this._form.appendChild(this._controls.editor);
|
560 |
+
},
|
561 |
+
createForm: function() {
|
562 |
+
var ipe = this;
|
563 |
+
function addText(mode, condition) {
|
564 |
+
var text = ipe.options['text' + mode + 'Controls'];
|
565 |
+
if (!text || condition === false) return;
|
566 |
+
ipe._form.appendChild(document.createTextNode(text));
|
567 |
+
};
|
568 |
+
this._form = $(document.createElement('form'));
|
569 |
+
this._form.id = this.options.formId;
|
570 |
+
this._form.addClassName(this.options.formClassName);
|
571 |
+
this._form.onsubmit = this._boundSubmitHandler;
|
572 |
+
this.createEditField();
|
573 |
+
if ('textarea' == this._controls.editor.tagName.toLowerCase())
|
574 |
+
this._form.appendChild(document.createElement('br'));
|
575 |
+
if (this.options.onFormCustomization)
|
576 |
+
this.options.onFormCustomization(this, this._form);
|
577 |
+
addText('Before', this.options.okControl || this.options.cancelControl);
|
578 |
+
this.createControl('ok', this._boundSubmitHandler);
|
579 |
+
addText('Between', this.options.okControl && this.options.cancelControl);
|
580 |
+
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
|
581 |
+
addText('After', this.options.okControl || this.options.cancelControl);
|
582 |
+
},
|
583 |
+
destroy: function() {
|
584 |
+
if (this._oldInnerHTML)
|
585 |
+
this.element.innerHTML = this._oldInnerHTML;
|
586 |
+
this.leaveEditMode();
|
587 |
+
this.unregisterListeners();
|
588 |
+
},
|
589 |
+
enterEditMode: function(e) {
|
590 |
+
if (this._saving || this._editing) return;
|
591 |
+
this._editing = true;
|
592 |
+
this.triggerCallback('onEnterEditMode');
|
593 |
+
if (this.options.externalControl)
|
594 |
+
this.options.externalControl.hide();
|
595 |
+
this.element.hide();
|
596 |
+
this.createForm();
|
597 |
+
this.element.parentNode.insertBefore(this._form, this.element);
|
598 |
+
if (!this.options.loadTextURL)
|
599 |
+
this.postProcessEditField();
|
600 |
+
if (e) Event.stop(e);
|
601 |
+
},
|
602 |
+
enterHover: function(e) {
|
603 |
+
if (this.options.hoverClassName)
|
604 |
+
this.element.addClassName(this.options.hoverClassName);
|
605 |
+
if (this._saving) return;
|
606 |
+
this.triggerCallback('onEnterHover');
|
607 |
+
},
|
608 |
+
getText: function() {
|
609 |
+
return this.element.innerHTML.unescapeHTML();
|
610 |
+
},
|
611 |
+
handleAJAXFailure: function(transport) {
|
612 |
+
this.triggerCallback('onFailure', transport);
|
613 |
+
if (this._oldInnerHTML) {
|
614 |
+
this.element.innerHTML = this._oldInnerHTML;
|
615 |
+
this._oldInnerHTML = null;
|
616 |
+
}
|
617 |
+
},
|
618 |
+
handleFormCancellation: function(e) {
|
619 |
+
this.wrapUp();
|
620 |
+
if (e) Event.stop(e);
|
621 |
+
},
|
622 |
+
handleFormSubmission: function(e) {
|
623 |
+
var form = this._form;
|
624 |
+
var value = $F(this._controls.editor);
|
625 |
+
this.prepareSubmission();
|
626 |
+
var params = this.options.callback(form, value) || '';
|
627 |
+
if (Object.isString(params))
|
628 |
+
params = params.toQueryParams();
|
629 |
+
params.editorId = this.element.id;
|
630 |
+
if (this.options.htmlResponse) {
|
631 |
+
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
|
632 |
+
Object.extend(options, {
|
633 |
+
parameters: params,
|
634 |
+
onComplete: this._boundWrapperHandler,
|
635 |
+
onFailure: this._boundFailureHandler
|
636 |
+
});
|
637 |
+
new Ajax.Updater({ success: this.element }, this.url, options);
|
638 |
+
} else {
|
639 |
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
640 |
+
Object.extend(options, {
|
641 |
+
parameters: params,
|
642 |
+
onComplete: this._boundWrapperHandler,
|
643 |
+
onFailure: this._boundFailureHandler
|
644 |
+
});
|
645 |
+
new Ajax.Request(this.url, options);
|
646 |
+
}
|
647 |
+
if (e) Event.stop(e);
|
648 |
+
},
|
649 |
+
leaveEditMode: function() {
|
650 |
+
this.element.removeClassName(this.options.savingClassName);
|
651 |
+
this.removeForm();
|
652 |
+
this.leaveHover();
|
653 |
+
this.element.style.backgroundColor = this._originalBackground;
|
654 |
+
this.element.show();
|
655 |
+
if (this.options.externalControl)
|
656 |
+
this.options.externalControl.show();
|
657 |
+
this._saving = false;
|
658 |
+
this._editing = false;
|
659 |
+
this._oldInnerHTML = null;
|
660 |
+
this.triggerCallback('onLeaveEditMode');
|
661 |
+
},
|
662 |
+
leaveHover: function(e) {
|
663 |
+
if (this.options.hoverClassName)
|
664 |
+
this.element.removeClassName(this.options.hoverClassName);
|
665 |
+
if (this._saving) return;
|
666 |
+
this.triggerCallback('onLeaveHover');
|
667 |
+
},
|
668 |
+
loadExternalText: function() {
|
669 |
+
this._form.addClassName(this.options.loadingClassName);
|
670 |
+
this._controls.editor.disabled = true;
|
671 |
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
672 |
+
Object.extend(options, {
|
673 |
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
674 |
+
onComplete: Prototype.emptyFunction,
|
675 |
+
onSuccess: function(transport) {
|
676 |
+
this._form.removeClassName(this.options.loadingClassName);
|
677 |
+
var text = transport.responseText;
|
678 |
+
if (this.options.stripLoadedTextTags)
|
679 |
+
text = text.stripTags();
|
680 |
+
this._controls.editor.value = text;
|
681 |
+
this._controls.editor.disabled = false;
|
682 |
+
this.postProcessEditField();
|
683 |
+
}.bind(this),
|
684 |
+
onFailure: this._boundFailureHandler
|
685 |
+
});
|
686 |
+
new Ajax.Request(this.options.loadTextURL, options);
|
687 |
+
},
|
688 |
+
postProcessEditField: function() {
|
689 |
+
var fpc = this.options.fieldPostCreation;
|
690 |
+
if (fpc)
|
691 |
+
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
|
692 |
+
},
|
693 |
+
prepareOptions: function() {
|
694 |
+
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
|
695 |
+
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
|
696 |
+
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
|
697 |
+
Object.extend(this.options, defs);
|
698 |
+
}.bind(this));
|
699 |
+
},
|
700 |
+
prepareSubmission: function() {
|
701 |
+
this._saving = true;
|
702 |
+
this.removeForm();
|
703 |
+
this.leaveHover();
|
704 |
+
this.showSaving();
|
705 |
+
},
|
706 |
+
registerListeners: function() {
|
707 |
+
this._listeners = { };
|
708 |
+
var listener;
|
709 |
+
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
|
710 |
+
listener = this[pair.value].bind(this);
|
711 |
+
this._listeners[pair.key] = listener;
|
712 |
+
if (!this.options.externalControlOnly)
|
713 |
+
this.element.observe(pair.key, listener);
|
714 |
+
if (this.options.externalControl)
|
715 |
+
this.options.externalControl.observe(pair.key, listener);
|
716 |
+
}.bind(this));
|
717 |
+
},
|
718 |
+
removeForm: function() {
|
719 |
+
if (!this._form) return;
|
720 |
+
this._form.remove();
|
721 |
+
this._form = null;
|
722 |
+
this._controls = { };
|
723 |
+
},
|
724 |
+
showSaving: function() {
|
725 |
+
this._oldInnerHTML = this.element.innerHTML;
|
726 |
+
this.element.innerHTML = this.options.savingText;
|
727 |
+
this.element.addClassName(this.options.savingClassName);
|
728 |
+
this.element.style.backgroundColor = this._originalBackground;
|
729 |
+
this.element.show();
|
730 |
+
},
|
731 |
+
triggerCallback: function(cbName, arg) {
|
732 |
+
if ('function' == typeof this.options[cbName]) {
|
733 |
+
this.options[cbName](this, arg);
|
734 |
+
}
|
735 |
+
},
|
736 |
+
unregisterListeners: function() {
|
737 |
+
$H(this._listeners).each(function(pair) {
|
738 |
+
if (!this.options.externalControlOnly)
|
739 |
+
this.element.stopObserving(pair.key, pair.value);
|
740 |
+
if (this.options.externalControl)
|
741 |
+
this.options.externalControl.stopObserving(pair.key, pair.value);
|
742 |
+
}.bind(this));
|
743 |
+
},
|
744 |
+
wrapUp: function(transport) {
|
745 |
+
this.leaveEditMode();
|
746 |
+
// Can't use triggerCallback due to backward compatibility: requires
|
747 |
+
// binding + direct element
|
748 |
+
this._boundComplete(transport, this.element);
|
749 |
+
}
|
750 |
+
});
|
751 |
+
|
752 |
+
Object.extend(Ajax.InPlaceEditor.prototype, {
|
753 |
+
dispose: Ajax.InPlaceEditor.prototype.destroy
|
754 |
+
});
|
755 |
+
|
756 |
+
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
|
757 |
+
initialize: function($super, element, url, options) {
|
758 |
+
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
|
759 |
+
$super(element, url, options);
|
760 |
+
},
|
761 |
+
|
762 |
+
createEditField: function() {
|
763 |
+
var list = document.createElement('select');
|
764 |
+
list.name = this.options.paramName;
|
765 |
+
list.size = 1;
|
766 |
+
this._controls.editor = list;
|
767 |
+
this._collection = this.options.collection || [];
|
768 |
+
if (this.options.loadCollectionURL)
|
769 |
+
this.loadCollection();
|
770 |
+
else
|
771 |
+
this.checkForExternalText();
|
772 |
+
this._form.appendChild(this._controls.editor);
|
773 |
+
},
|
774 |
+
|
775 |
+
loadCollection: function() {
|
776 |
+
this._form.addClassName(this.options.loadingClassName);
|
777 |
+
this.showLoadingText(this.options.loadingCollectionText);
|
778 |
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
779 |
+
Object.extend(options, {
|
780 |
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
781 |
+
onComplete: Prototype.emptyFunction,
|
782 |
+
onSuccess: function(transport) {
|
783 |
+
var js = transport.responseText.strip();
|
784 |
+
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
|
785 |
+
throw('Server returned an invalid collection representation.');
|
786 |
+
this._collection = eval(js);
|
787 |
+
this.checkForExternalText();
|
788 |
+
}.bind(this),
|
789 |
+
onFailure: this.onFailure
|
790 |
+
});
|
791 |
+
new Ajax.Request(this.options.loadCollectionURL, options);
|
792 |
+
},
|
793 |
+
|
794 |
+
showLoadingText: function(text) {
|
795 |
+
this._controls.editor.disabled = true;
|
796 |
+
var tempOption = this._controls.editor.firstChild;
|
797 |
+
if (!tempOption) {
|
798 |
+
tempOption = document.createElement('option');
|
799 |
+
tempOption.value = '';
|
800 |
+
this._controls.editor.appendChild(tempOption);
|
801 |
+
tempOption.selected = true;
|
802 |
+
}
|
803 |
+
tempOption.update((text || '').stripScripts().stripTags());
|
804 |
+
},
|
805 |
+
|
806 |
+
checkForExternalText: function() {
|
807 |
+
this._text = this.getText();
|
808 |
+
if (this.options.loadTextURL)
|
809 |
+
this.loadExternalText();
|
810 |
+
else
|
811 |
+
this.buildOptionList();
|
812 |
+
},
|
813 |
+
|
814 |
+
loadExternalText: function() {
|
815 |
+
this.showLoadingText(this.options.loadingText);
|
816 |
+
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
|
817 |
+
Object.extend(options, {
|
818 |
+
parameters: 'editorId=' + encodeURIComponent(this.element.id),
|
819 |
+
onComplete: Prototype.emptyFunction,
|
820 |
+
onSuccess: function(transport) {
|
821 |
+
this._text = transport.responseText.strip();
|
822 |
+
this.buildOptionList();
|
823 |
+
}.bind(this),
|
824 |
+
onFailure: this.onFailure
|
825 |
+
});
|
826 |
+
new Ajax.Request(this.options.loadTextURL, options);
|
827 |
+
},
|
828 |
+
|
829 |
+
buildOptionList: function() {
|
830 |
+
this._form.removeClassName(this.options.loadingClassName);
|
831 |
+
this._collection = this._collection.map(function(entry) {
|
832 |
+
return 2 === entry.length ? entry : [entry, entry].flatten();
|
833 |
+
});
|
834 |
+
var marker = ('value' in this.options) ? this.options.value : this._text;
|
835 |
+
var textFound = this._collection.any(function(entry) {
|
836 |
+
return entry[0] == marker;
|
837 |
+
}.bind(this));
|
838 |
+
this._controls.editor.update('');
|
839 |
+
var option;
|
840 |
+
this._collection.each(function(entry, index) {
|
841 |
+
option = document.createElement('option');
|
842 |
+
option.value = entry[0];
|
843 |
+
option.selected = textFound ? entry[0] == marker : 0 == index;
|
844 |
+
option.appendChild(document.createTextNode(entry[1]));
|
845 |
+
this._controls.editor.appendChild(option);
|
846 |
+
}.bind(this));
|
847 |
+
this._controls.editor.disabled = false;
|
848 |
+
Field.scrollFreeActivate(this._controls.editor);
|
849 |
+
}
|
850 |
+
});
|
851 |
+
|
852 |
+
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
|
853 |
+
//**** This only exists for a while, in order to let ****
|
854 |
+
//**** users adapt to the new API. Read up on the new ****
|
855 |
+
//**** API and convert your code to it ASAP! ****
|
856 |
+
|
857 |
+
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
|
858 |
+
if (!options) return;
|
859 |
+
function fallback(name, expr) {
|
860 |
+
if (name in options || expr === undefined) return;
|
861 |
+
options[name] = expr;
|
862 |
+
};
|
863 |
+
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
|
864 |
+
options.cancelLink == options.cancelButton == false ? false : undefined)));
|
865 |
+
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
|
866 |
+
options.okLink == options.okButton == false ? false : undefined)));
|
867 |
+
fallback('highlightColor', options.highlightcolor);
|
868 |
+
fallback('highlightEndColor', options.highlightendcolor);
|
869 |
+
};
|
870 |
+
|
871 |
+
Object.extend(Ajax.InPlaceEditor, {
|
872 |
+
DefaultOptions: {
|
873 |
+
ajaxOptions: { },
|
874 |
+
autoRows: 3, // Use when multi-line w/ rows == 1
|
875 |
+
cancelControl: 'link', // 'link'|'button'|false
|
876 |
+
cancelText: 'cancel',
|
877 |
+
clickToEditText: 'Click to edit',
|
878 |
+
externalControl: null, // id|elt
|
879 |
+
externalControlOnly: false,
|
880 |
+
fieldPostCreation: 'activate', // 'activate'|'focus'|false
|
881 |
+
formClassName: 'inplaceeditor-form',
|
882 |
+
formId: null, // id|elt
|
883 |
+
highlightColor: '#ffff99',
|
884 |
+
highlightEndColor: '#ffffff',
|
885 |
+
hoverClassName: '',
|
886 |
+
htmlResponse: true,
|
887 |
+
loadingClassName: 'inplaceeditor-loading',
|
888 |
+
loadingText: 'Loading...',
|
889 |
+
okControl: 'button', // 'link'|'button'|false
|
890 |
+
okText: 'ok',
|
891 |
+
paramName: 'value',
|
892 |
+
rows: 1, // If 1 and multi-line, uses autoRows
|
893 |
+
savingClassName: 'inplaceeditor-saving',
|
894 |
+
savingText: 'Saving...',
|
895 |
+
size: 0,
|
896 |
+
stripLoadedTextTags: false,
|
897 |
+
submitOnBlur: false,
|
898 |
+
textAfterControls: '',
|
899 |
+
textBeforeControls: '',
|
900 |
+
textBetweenControls: ''
|
901 |
+
},
|
902 |
+
DefaultCallbacks: {
|
903 |
+
callback: function(form) {
|
904 |
+
return Form.serialize(form);
|
905 |
+
},
|
906 |
+
onComplete: function(transport, element) {
|
907 |
+
// For backward compatibility, this one is bound to the IPE, and passes
|
908 |
+
// the element directly. It was too often customized, so we don't break it.
|
909 |
+
new Effect.Highlight(element, {
|
910 |
+
startcolor: this.options.highlightColor, keepBackgroundImage: true });
|
911 |
+
},
|
912 |
+
onEnterEditMode: null,
|
913 |
+
onEnterHover: function(ipe) {
|
914 |
+
ipe.element.style.backgroundColor = ipe.options.highlightColor;
|
915 |
+
if (ipe._effect)
|
916 |
+
ipe._effect.cancel();
|
917 |
+
},
|
918 |
+
onFailure: function(transport, ipe) {
|
919 |
+
alert('Error communication with the server: ' + transport.responseText.stripTags());
|
920 |
+
},
|
921 |
+
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
|
922 |
+
onLeaveEditMode: null,
|
923 |
+
onLeaveHover: function(ipe) {
|
924 |
+
ipe._effect = new Effect.Highlight(ipe.element, {
|
925 |
+
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
|
926 |
+
restorecolor: ipe._originalBackground, keepBackgroundImage: true
|
927 |
+
});
|
928 |
+
}
|
929 |
+
},
|
930 |
+
Listeners: {
|
931 |
+
click: 'enterEditMode',
|
932 |
+
keydown: 'checkForEscapeOrReturn',
|
933 |
+
mouseover: 'enterHover',
|
934 |
+
mouseout: 'leaveHover'
|
935 |
+
}
|
936 |
+
});
|
937 |
+
|
938 |
+
Ajax.InPlaceCollectionEditor.DefaultOptions = {
|
939 |
+
loadingCollectionText: 'Loading options...'
|
940 |
+
};
|
941 |
+
|
942 |
+
// Delayed observer, like Form.Element.Observer,
|
943 |
+
// but waits for delay after last key input
|
944 |
+
// Ideal for live-search fields
|
945 |
+
|
946 |
+
Form.Element.DelayedObserver = Class.create({
|
947 |
+
initialize: function(element, delay, callback) {
|
948 |
+
this.delay = delay || 0.5;
|
949 |
+
this.element = $(element);
|
950 |
+
this.callback = callback;
|
951 |
+
this.timer = null;
|
952 |
+
this.lastValue = $F(this.element);
|
953 |
+
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
|
954 |
+
},
|
955 |
+
delayedListener: function(event) {
|
956 |
+
if(this.lastValue == $F(this.element)) return;
|
957 |
+
if(this.timer) clearTimeout(this.timer);
|
958 |
+
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
|
959 |
+
this.lastValue = $F(this.element);
|
960 |
+
},
|
961 |
+
onTimerEvent: function() {
|
962 |
+
this.timer = null;
|
963 |
+
this.callback(this.element, $F(this.element));
|
964 |
+
}
|
965 |
+
});
|
js/mageho/sortproducts/dragdrop.js
ADDED
@@ -0,0 +1,974 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us dragdrop.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
//
|
5 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
6 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
7 |
+
|
8 |
+
if(Object.isUndefined(Effect))
|
9 |
+
throw("dragdrop.js requires including script.aculo.us' effects.js library");
|
10 |
+
|
11 |
+
var Droppables = {
|
12 |
+
drops: [],
|
13 |
+
|
14 |
+
remove: function(element) {
|
15 |
+
this.drops = this.drops.reject(function(d) { return d.element==$(element) });
|
16 |
+
},
|
17 |
+
|
18 |
+
add: function(element) {
|
19 |
+
element = $(element);
|
20 |
+
var options = Object.extend({
|
21 |
+
greedy: true,
|
22 |
+
hoverclass: null,
|
23 |
+
tree: false
|
24 |
+
}, arguments[1] || { });
|
25 |
+
|
26 |
+
// cache containers
|
27 |
+
if(options.containment) {
|
28 |
+
options._containers = [];
|
29 |
+
var containment = options.containment;
|
30 |
+
if(Object.isArray(containment)) {
|
31 |
+
containment.each( function(c) { options._containers.push($(c)) });
|
32 |
+
} else {
|
33 |
+
options._containers.push($(containment));
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
if(options.accept) options.accept = [options.accept].flatten();
|
38 |
+
|
39 |
+
Element.makePositioned(element); // fix IE
|
40 |
+
options.element = element;
|
41 |
+
|
42 |
+
this.drops.push(options);
|
43 |
+
},
|
44 |
+
|
45 |
+
findDeepestChild: function(drops) {
|
46 |
+
deepest = drops[0];
|
47 |
+
|
48 |
+
for (i = 1; i < drops.length; ++i)
|
49 |
+
if (Element.isParent(drops[i].element, deepest.element))
|
50 |
+
deepest = drops[i];
|
51 |
+
|
52 |
+
return deepest;
|
53 |
+
},
|
54 |
+
|
55 |
+
isContained: function(element, drop) {
|
56 |
+
var containmentNode;
|
57 |
+
if(drop.tree) {
|
58 |
+
containmentNode = element.treeNode;
|
59 |
+
} else {
|
60 |
+
containmentNode = element.parentNode;
|
61 |
+
}
|
62 |
+
return drop._containers.detect(function(c) { return containmentNode == c });
|
63 |
+
},
|
64 |
+
|
65 |
+
isAffected: function(point, element, drop) {
|
66 |
+
return (
|
67 |
+
(drop.element!=element) &&
|
68 |
+
((!drop._containers) ||
|
69 |
+
this.isContained(element, drop)) &&
|
70 |
+
((!drop.accept) ||
|
71 |
+
(Element.classNames(element).detect(
|
72 |
+
function(v) { return drop.accept.include(v) } ) )) &&
|
73 |
+
Position.within(drop.element, point[0], point[1]) );
|
74 |
+
},
|
75 |
+
|
76 |
+
deactivate: function(drop) {
|
77 |
+
if(drop.hoverclass)
|
78 |
+
Element.removeClassName(drop.element, drop.hoverclass);
|
79 |
+
this.last_active = null;
|
80 |
+
},
|
81 |
+
|
82 |
+
activate: function(drop) {
|
83 |
+
if(drop.hoverclass)
|
84 |
+
Element.addClassName(drop.element, drop.hoverclass);
|
85 |
+
this.last_active = drop;
|
86 |
+
},
|
87 |
+
|
88 |
+
show: function(point, element) {
|
89 |
+
if(!this.drops.length) return;
|
90 |
+
var drop, affected = [];
|
91 |
+
|
92 |
+
this.drops.each( function(drop) {
|
93 |
+
if(Droppables.isAffected(point, element, drop))
|
94 |
+
affected.push(drop);
|
95 |
+
});
|
96 |
+
|
97 |
+
if(affected.length>0)
|
98 |
+
drop = Droppables.findDeepestChild(affected);
|
99 |
+
|
100 |
+
if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
|
101 |
+
if (drop) {
|
102 |
+
Position.within(drop.element, point[0], point[1]);
|
103 |
+
if(drop.onHover)
|
104 |
+
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
|
105 |
+
|
106 |
+
if (drop != this.last_active) Droppables.activate(drop);
|
107 |
+
}
|
108 |
+
},
|
109 |
+
|
110 |
+
fire: function(event, element) {
|
111 |
+
if(!this.last_active) return;
|
112 |
+
Position.prepare();
|
113 |
+
|
114 |
+
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
|
115 |
+
if (this.last_active.onDrop) {
|
116 |
+
this.last_active.onDrop(element, this.last_active.element, event);
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
},
|
120 |
+
|
121 |
+
reset: function() {
|
122 |
+
if(this.last_active)
|
123 |
+
this.deactivate(this.last_active);
|
124 |
+
}
|
125 |
+
};
|
126 |
+
|
127 |
+
var Draggables = {
|
128 |
+
drags: [],
|
129 |
+
observers: [],
|
130 |
+
|
131 |
+
register: function(draggable) {
|
132 |
+
if(this.drags.length == 0) {
|
133 |
+
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
|
134 |
+
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
|
135 |
+
this.eventKeypress = this.keyPress.bindAsEventListener(this);
|
136 |
+
|
137 |
+
Event.observe(document, "mouseup", this.eventMouseUp);
|
138 |
+
Event.observe(document, "mousemove", this.eventMouseMove);
|
139 |
+
Event.observe(document, "keypress", this.eventKeypress);
|
140 |
+
}
|
141 |
+
this.drags.push(draggable);
|
142 |
+
},
|
143 |
+
|
144 |
+
unregister: function(draggable) {
|
145 |
+
this.drags = this.drags.reject(function(d) { return d==draggable });
|
146 |
+
if(this.drags.length == 0) {
|
147 |
+
Event.stopObserving(document, "mouseup", this.eventMouseUp);
|
148 |
+
Event.stopObserving(document, "mousemove", this.eventMouseMove);
|
149 |
+
Event.stopObserving(document, "keypress", this.eventKeypress);
|
150 |
+
}
|
151 |
+
},
|
152 |
+
|
153 |
+
activate: function(draggable) {
|
154 |
+
if(draggable.options.delay) {
|
155 |
+
this._timeout = setTimeout(function() {
|
156 |
+
Draggables._timeout = null;
|
157 |
+
window.focus();
|
158 |
+
Draggables.activeDraggable = draggable;
|
159 |
+
}.bind(this), draggable.options.delay);
|
160 |
+
} else {
|
161 |
+
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
|
162 |
+
this.activeDraggable = draggable;
|
163 |
+
}
|
164 |
+
},
|
165 |
+
|
166 |
+
deactivate: function() {
|
167 |
+
this.activeDraggable = null;
|
168 |
+
},
|
169 |
+
|
170 |
+
updateDrag: function(event) {
|
171 |
+
if(!this.activeDraggable) return;
|
172 |
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
173 |
+
// Mozilla-based browsers fire successive mousemove events with
|
174 |
+
// the same coordinates, prevent needless redrawing (moz bug?)
|
175 |
+
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
|
176 |
+
this._lastPointer = pointer;
|
177 |
+
|
178 |
+
this.activeDraggable.updateDrag(event, pointer);
|
179 |
+
},
|
180 |
+
|
181 |
+
endDrag: function(event) {
|
182 |
+
if(this._timeout) {
|
183 |
+
clearTimeout(this._timeout);
|
184 |
+
this._timeout = null;
|
185 |
+
}
|
186 |
+
if(!this.activeDraggable) return;
|
187 |
+
this._lastPointer = null;
|
188 |
+
this.activeDraggable.endDrag(event);
|
189 |
+
this.activeDraggable = null;
|
190 |
+
},
|
191 |
+
|
192 |
+
keyPress: function(event) {
|
193 |
+
if(this.activeDraggable)
|
194 |
+
this.activeDraggable.keyPress(event);
|
195 |
+
},
|
196 |
+
|
197 |
+
addObserver: function(observer) {
|
198 |
+
this.observers.push(observer);
|
199 |
+
this._cacheObserverCallbacks();
|
200 |
+
},
|
201 |
+
|
202 |
+
removeObserver: function(element) { // element instead of observer fixes mem leaks
|
203 |
+
this.observers = this.observers.reject( function(o) { return o.element==element });
|
204 |
+
this._cacheObserverCallbacks();
|
205 |
+
},
|
206 |
+
|
207 |
+
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
|
208 |
+
if(this[eventName+'Count'] > 0)
|
209 |
+
this.observers.each( function(o) {
|
210 |
+
if(o[eventName]) o[eventName](eventName, draggable, event);
|
211 |
+
});
|
212 |
+
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
|
213 |
+
},
|
214 |
+
|
215 |
+
_cacheObserverCallbacks: function() {
|
216 |
+
['onStart','onEnd','onDrag'].each( function(eventName) {
|
217 |
+
Draggables[eventName+'Count'] = Draggables.observers.select(
|
218 |
+
function(o) { return o[eventName]; }
|
219 |
+
).length;
|
220 |
+
});
|
221 |
+
}
|
222 |
+
};
|
223 |
+
|
224 |
+
/*--------------------------------------------------------------------------*/
|
225 |
+
|
226 |
+
var Draggable = Class.create({
|
227 |
+
initialize: function(element) {
|
228 |
+
var defaults = {
|
229 |
+
handle: false,
|
230 |
+
reverteffect: function(element, top_offset, left_offset) {
|
231 |
+
var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
|
232 |
+
new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
|
233 |
+
queue: {scope:'_draggable', position:'end'}
|
234 |
+
});
|
235 |
+
},
|
236 |
+
endeffect: function(element) {
|
237 |
+
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
|
238 |
+
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
|
239 |
+
queue: {scope:'_draggable', position:'end'},
|
240 |
+
afterFinish: function(){
|
241 |
+
Draggable._dragging[element] = false
|
242 |
+
}
|
243 |
+
});
|
244 |
+
},
|
245 |
+
zindex: 1000,
|
246 |
+
revert: false,
|
247 |
+
quiet: false,
|
248 |
+
scroll: false,
|
249 |
+
scrollSensitivity: 20,
|
250 |
+
scrollSpeed: 15,
|
251 |
+
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
|
252 |
+
delay: 0
|
253 |
+
};
|
254 |
+
|
255 |
+
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
|
256 |
+
Object.extend(defaults, {
|
257 |
+
starteffect: function(element) {
|
258 |
+
element._opacity = Element.getOpacity(element);
|
259 |
+
Draggable._dragging[element] = true;
|
260 |
+
new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
|
261 |
+
}
|
262 |
+
});
|
263 |
+
|
264 |
+
var options = Object.extend(defaults, arguments[1] || { });
|
265 |
+
|
266 |
+
this.element = $(element);
|
267 |
+
|
268 |
+
if(options.handle && Object.isString(options.handle))
|
269 |
+
this.handle = this.element.down('.'+options.handle, 0);
|
270 |
+
|
271 |
+
if(!this.handle) this.handle = $(options.handle);
|
272 |
+
if(!this.handle) this.handle = this.element;
|
273 |
+
|
274 |
+
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
|
275 |
+
options.scroll = $(options.scroll);
|
276 |
+
this._isScrollChild = Element.childOf(this.element, options.scroll);
|
277 |
+
}
|
278 |
+
|
279 |
+
Element.makePositioned(this.element); // fix IE
|
280 |
+
|
281 |
+
this.options = options;
|
282 |
+
this.dragging = false;
|
283 |
+
|
284 |
+
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
|
285 |
+
Event.observe(this.handle, "mousedown", this.eventMouseDown);
|
286 |
+
|
287 |
+
Draggables.register(this);
|
288 |
+
},
|
289 |
+
|
290 |
+
destroy: function() {
|
291 |
+
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
|
292 |
+
Draggables.unregister(this);
|
293 |
+
},
|
294 |
+
|
295 |
+
currentDelta: function() {
|
296 |
+
return([
|
297 |
+
parseInt(Element.getStyle(this.element,'left') || '0'),
|
298 |
+
parseInt(Element.getStyle(this.element,'top') || '0')]);
|
299 |
+
},
|
300 |
+
|
301 |
+
initDrag: function(event) {
|
302 |
+
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
|
303 |
+
Draggable._dragging[this.element]) return;
|
304 |
+
if(Event.isLeftClick(event)) {
|
305 |
+
// abort on form elements, fixes a Firefox issue
|
306 |
+
var src = Event.element(event);
|
307 |
+
if((tag_name = src.tagName.toUpperCase()) && (
|
308 |
+
tag_name=='INPUT' ||
|
309 |
+
tag_name=='SELECT' ||
|
310 |
+
tag_name=='OPTION' ||
|
311 |
+
tag_name=='BUTTON' ||
|
312 |
+
tag_name=='TEXTAREA')) return;
|
313 |
+
|
314 |
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
315 |
+
var pos = this.element.cumulativeOffset();
|
316 |
+
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
|
317 |
+
|
318 |
+
Draggables.activate(this);
|
319 |
+
Event.stop(event);
|
320 |
+
}
|
321 |
+
},
|
322 |
+
|
323 |
+
startDrag: function(event) {
|
324 |
+
this.dragging = true;
|
325 |
+
if(!this.delta)
|
326 |
+
this.delta = this.currentDelta();
|
327 |
+
|
328 |
+
if(this.options.zindex) {
|
329 |
+
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
|
330 |
+
this.element.style.zIndex = this.options.zindex;
|
331 |
+
}
|
332 |
+
|
333 |
+
if(this.options.ghosting) {
|
334 |
+
this._clone = this.element.cloneNode(true);
|
335 |
+
this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
|
336 |
+
if (!this._originallyAbsolute)
|
337 |
+
Position.absolutize(this.element);
|
338 |
+
this.element.parentNode.insertBefore(this._clone, this.element);
|
339 |
+
}
|
340 |
+
|
341 |
+
if(this.options.scroll) {
|
342 |
+
if (this.options.scroll == window) {
|
343 |
+
var where = this._getWindowScroll(this.options.scroll);
|
344 |
+
this.originalScrollLeft = where.left;
|
345 |
+
this.originalScrollTop = where.top;
|
346 |
+
} else {
|
347 |
+
this.originalScrollLeft = this.options.scroll.scrollLeft;
|
348 |
+
this.originalScrollTop = this.options.scroll.scrollTop;
|
349 |
+
}
|
350 |
+
}
|
351 |
+
|
352 |
+
Draggables.notify('onStart', this, event);
|
353 |
+
|
354 |
+
if(this.options.starteffect) this.options.starteffect(this.element);
|
355 |
+
},
|
356 |
+
|
357 |
+
updateDrag: function(event, pointer) {
|
358 |
+
if(!this.dragging) this.startDrag(event);
|
359 |
+
|
360 |
+
if(!this.options.quiet){
|
361 |
+
Position.prepare();
|
362 |
+
Droppables.show(pointer, this.element);
|
363 |
+
}
|
364 |
+
|
365 |
+
Draggables.notify('onDrag', this, event);
|
366 |
+
|
367 |
+
this.draw(pointer);
|
368 |
+
if(this.options.change) this.options.change(this);
|
369 |
+
|
370 |
+
if(this.options.scroll) {
|
371 |
+
this.stopScrolling();
|
372 |
+
|
373 |
+
var p;
|
374 |
+
if (this.options.scroll == window) {
|
375 |
+
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
|
376 |
+
} else {
|
377 |
+
p = Position.page(this.options.scroll).toArray();
|
378 |
+
p[0] += this.options.scroll.scrollLeft + Position.deltaX;
|
379 |
+
p[1] += this.options.scroll.scrollTop + Position.deltaY;
|
380 |
+
p.push(p[0]+this.options.scroll.offsetWidth);
|
381 |
+
p.push(p[1]+this.options.scroll.offsetHeight);
|
382 |
+
}
|
383 |
+
var speed = [0,0];
|
384 |
+
if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
|
385 |
+
if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
|
386 |
+
if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
|
387 |
+
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
|
388 |
+
this.startScrolling(speed);
|
389 |
+
}
|
390 |
+
|
391 |
+
// fix AppleWebKit rendering
|
392 |
+
if(Prototype.Browser.WebKit) window.scrollBy(0,0);
|
393 |
+
|
394 |
+
Event.stop(event);
|
395 |
+
},
|
396 |
+
|
397 |
+
finishDrag: function(event, success) {
|
398 |
+
this.dragging = false;
|
399 |
+
|
400 |
+
if(this.options.quiet){
|
401 |
+
Position.prepare();
|
402 |
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
403 |
+
Droppables.show(pointer, this.element);
|
404 |
+
}
|
405 |
+
|
406 |
+
if(this.options.ghosting) {
|
407 |
+
if (!this._originallyAbsolute)
|
408 |
+
Position.relativize(this.element);
|
409 |
+
delete this._originallyAbsolute;
|
410 |
+
Element.remove(this._clone);
|
411 |
+
this._clone = null;
|
412 |
+
}
|
413 |
+
|
414 |
+
var dropped = false;
|
415 |
+
if(success) {
|
416 |
+
dropped = Droppables.fire(event, this.element);
|
417 |
+
if (!dropped) dropped = false;
|
418 |
+
}
|
419 |
+
if(dropped && this.options.onDropped) this.options.onDropped(this.element);
|
420 |
+
Draggables.notify('onEnd', this, event);
|
421 |
+
|
422 |
+
var revert = this.options.revert;
|
423 |
+
if(revert && Object.isFunction(revert)) revert = revert(this.element);
|
424 |
+
|
425 |
+
var d = this.currentDelta();
|
426 |
+
if(revert && this.options.reverteffect) {
|
427 |
+
if (dropped == 0 || revert != 'failure')
|
428 |
+
this.options.reverteffect(this.element,
|
429 |
+
d[1]-this.delta[1], d[0]-this.delta[0]);
|
430 |
+
} else {
|
431 |
+
this.delta = d;
|
432 |
+
}
|
433 |
+
|
434 |
+
if(this.options.zindex)
|
435 |
+
this.element.style.zIndex = this.originalZ;
|
436 |
+
|
437 |
+
if(this.options.endeffect)
|
438 |
+
this.options.endeffect(this.element);
|
439 |
+
|
440 |
+
Draggables.deactivate(this);
|
441 |
+
Droppables.reset();
|
442 |
+
},
|
443 |
+
|
444 |
+
keyPress: function(event) {
|
445 |
+
if(event.keyCode!=Event.KEY_ESC) return;
|
446 |
+
this.finishDrag(event, false);
|
447 |
+
Event.stop(event);
|
448 |
+
},
|
449 |
+
|
450 |
+
endDrag: function(event) {
|
451 |
+
if(!this.dragging) return;
|
452 |
+
this.stopScrolling();
|
453 |
+
this.finishDrag(event, true);
|
454 |
+
Event.stop(event);
|
455 |
+
},
|
456 |
+
|
457 |
+
draw: function(point) {
|
458 |
+
var pos = this.element.cumulativeOffset();
|
459 |
+
if(this.options.ghosting) {
|
460 |
+
var r = Position.realOffset(this.element);
|
461 |
+
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
|
462 |
+
}
|
463 |
+
|
464 |
+
var d = this.currentDelta();
|
465 |
+
pos[0] -= d[0]; pos[1] -= d[1];
|
466 |
+
|
467 |
+
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
|
468 |
+
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
|
469 |
+
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
|
470 |
+
}
|
471 |
+
|
472 |
+
var p = [0,1].map(function(i){
|
473 |
+
return (point[i]-pos[i]-this.offset[i])
|
474 |
+
}.bind(this));
|
475 |
+
|
476 |
+
if(this.options.snap) {
|
477 |
+
if(Object.isFunction(this.options.snap)) {
|
478 |
+
p = this.options.snap(p[0],p[1],this);
|
479 |
+
} else {
|
480 |
+
if(Object.isArray(this.options.snap)) {
|
481 |
+
p = p.map( function(v, i) {
|
482 |
+
return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
|
483 |
+
} else {
|
484 |
+
p = p.map( function(v) {
|
485 |
+
return (v/this.options.snap).round()*this.options.snap }.bind(this));
|
486 |
+
}
|
487 |
+
}}
|
488 |
+
|
489 |
+
var style = this.element.style;
|
490 |
+
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
|
491 |
+
style.left = p[0] + "px";
|
492 |
+
if((!this.options.constraint) || (this.options.constraint=='vertical'))
|
493 |
+
style.top = p[1] + "px";
|
494 |
+
|
495 |
+
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
|
496 |
+
},
|
497 |
+
|
498 |
+
stopScrolling: function() {
|
499 |
+
if(this.scrollInterval) {
|
500 |
+
clearInterval(this.scrollInterval);
|
501 |
+
this.scrollInterval = null;
|
502 |
+
Draggables._lastScrollPointer = null;
|
503 |
+
}
|
504 |
+
},
|
505 |
+
|
506 |
+
startScrolling: function(speed) {
|
507 |
+
if(!(speed[0] || speed[1])) return;
|
508 |
+
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
|
509 |
+
this.lastScrolled = new Date();
|
510 |
+
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
|
511 |
+
},
|
512 |
+
|
513 |
+
scroll: function() {
|
514 |
+
var current = new Date();
|
515 |
+
var delta = current - this.lastScrolled;
|
516 |
+
this.lastScrolled = current;
|
517 |
+
if(this.options.scroll == window) {
|
518 |
+
with (this._getWindowScroll(this.options.scroll)) {
|
519 |
+
if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
|
520 |
+
var d = delta / 1000;
|
521 |
+
this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
|
522 |
+
}
|
523 |
+
}
|
524 |
+
} else {
|
525 |
+
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
|
526 |
+
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
|
527 |
+
}
|
528 |
+
|
529 |
+
Position.prepare();
|
530 |
+
Droppables.show(Draggables._lastPointer, this.element);
|
531 |
+
Draggables.notify('onDrag', this);
|
532 |
+
if (this._isScrollChild) {
|
533 |
+
Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
|
534 |
+
Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
|
535 |
+
Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
|
536 |
+
if (Draggables._lastScrollPointer[0] < 0)
|
537 |
+
Draggables._lastScrollPointer[0] = 0;
|
538 |
+
if (Draggables._lastScrollPointer[1] < 0)
|
539 |
+
Draggables._lastScrollPointer[1] = 0;
|
540 |
+
this.draw(Draggables._lastScrollPointer);
|
541 |
+
}
|
542 |
+
|
543 |
+
if(this.options.change) this.options.change(this);
|
544 |
+
},
|
545 |
+
|
546 |
+
_getWindowScroll: function(w) {
|
547 |
+
var T, L, W, H;
|
548 |
+
with (w.document) {
|
549 |
+
if (w.document.documentElement && documentElement.scrollTop) {
|
550 |
+
T = documentElement.scrollTop;
|
551 |
+
L = documentElement.scrollLeft;
|
552 |
+
} else if (w.document.body) {
|
553 |
+
T = body.scrollTop;
|
554 |
+
L = body.scrollLeft;
|
555 |
+
}
|
556 |
+
if (w.innerWidth) {
|
557 |
+
W = w.innerWidth;
|
558 |
+
H = w.innerHeight;
|
559 |
+
} else if (w.document.documentElement && documentElement.clientWidth) {
|
560 |
+
W = documentElement.clientWidth;
|
561 |
+
H = documentElement.clientHeight;
|
562 |
+
} else {
|
563 |
+
W = body.offsetWidth;
|
564 |
+
H = body.offsetHeight;
|
565 |
+
}
|
566 |
+
}
|
567 |
+
return { top: T, left: L, width: W, height: H };
|
568 |
+
}
|
569 |
+
});
|
570 |
+
|
571 |
+
Draggable._dragging = { };
|
572 |
+
|
573 |
+
/*--------------------------------------------------------------------------*/
|
574 |
+
|
575 |
+
var SortableObserver = Class.create({
|
576 |
+
initialize: function(element, observer) {
|
577 |
+
this.element = $(element);
|
578 |
+
this.observer = observer;
|
579 |
+
this.lastValue = Sortable.serialize(this.element);
|
580 |
+
},
|
581 |
+
|
582 |
+
onStart: function() {
|
583 |
+
this.lastValue = Sortable.serialize(this.element);
|
584 |
+
},
|
585 |
+
|
586 |
+
onEnd: function() {
|
587 |
+
Sortable.unmark();
|
588 |
+
if(this.lastValue != Sortable.serialize(this.element))
|
589 |
+
this.observer(this.element)
|
590 |
+
}
|
591 |
+
});
|
592 |
+
|
593 |
+
var Sortable = {
|
594 |
+
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
|
595 |
+
|
596 |
+
sortables: { },
|
597 |
+
|
598 |
+
_findRootElement: function(element) {
|
599 |
+
while (element.tagName.toUpperCase() != "BODY") {
|
600 |
+
if(element.id && Sortable.sortables[element.id]) return element;
|
601 |
+
element = element.parentNode;
|
602 |
+
}
|
603 |
+
},
|
604 |
+
|
605 |
+
options: function(element) {
|
606 |
+
element = Sortable._findRootElement($(element));
|
607 |
+
if(!element) return;
|
608 |
+
return Sortable.sortables[element.id];
|
609 |
+
},
|
610 |
+
|
611 |
+
destroy: function(element){
|
612 |
+
element = $(element);
|
613 |
+
var s = Sortable.sortables[element.id];
|
614 |
+
|
615 |
+
if(s) {
|
616 |
+
Draggables.removeObserver(s.element);
|
617 |
+
s.droppables.each(function(d){ Droppables.remove(d) });
|
618 |
+
s.draggables.invoke('destroy');
|
619 |
+
|
620 |
+
delete Sortable.sortables[s.element.id];
|
621 |
+
}
|
622 |
+
},
|
623 |
+
|
624 |
+
create: function(element) {
|
625 |
+
element = $(element);
|
626 |
+
var options = Object.extend({
|
627 |
+
element: element,
|
628 |
+
tag: 'li', // assumes li children, override with tag: 'tagname'
|
629 |
+
dropOnEmpty: false,
|
630 |
+
tree: false,
|
631 |
+
treeTag: 'ul',
|
632 |
+
overlap: 'vertical', // one of 'vertical', 'horizontal'
|
633 |
+
constraint: 'vertical', // one of 'vertical', 'horizontal', false
|
634 |
+
containment: element, // also takes array of elements (or id's); or false
|
635 |
+
handle: false, // or a CSS class
|
636 |
+
only: false,
|
637 |
+
delay: 0,
|
638 |
+
hoverclass: null,
|
639 |
+
ghosting: false,
|
640 |
+
quiet: false,
|
641 |
+
scroll: false,
|
642 |
+
scrollSensitivity: 20,
|
643 |
+
scrollSpeed: 15,
|
644 |
+
format: this.SERIALIZE_RULE,
|
645 |
+
|
646 |
+
// these take arrays of elements or ids and can be
|
647 |
+
// used for better initialization performance
|
648 |
+
elements: false,
|
649 |
+
handles: false,
|
650 |
+
|
651 |
+
onChange: Prototype.emptyFunction,
|
652 |
+
onUpdate: Prototype.emptyFunction
|
653 |
+
}, arguments[1] || { });
|
654 |
+
|
655 |
+
// clear any old sortable with same element
|
656 |
+
this.destroy(element);
|
657 |
+
|
658 |
+
// build options for the draggables
|
659 |
+
var options_for_draggable = {
|
660 |
+
revert: true,
|
661 |
+
quiet: options.quiet,
|
662 |
+
scroll: options.scroll,
|
663 |
+
scrollSpeed: options.scrollSpeed,
|
664 |
+
scrollSensitivity: options.scrollSensitivity,
|
665 |
+
delay: options.delay,
|
666 |
+
ghosting: options.ghosting,
|
667 |
+
constraint: options.constraint,
|
668 |
+
handle: options.handle };
|
669 |
+
|
670 |
+
if(options.starteffect)
|
671 |
+
options_for_draggable.starteffect = options.starteffect;
|
672 |
+
|
673 |
+
if(options.reverteffect)
|
674 |
+
options_for_draggable.reverteffect = options.reverteffect;
|
675 |
+
else
|
676 |
+
if(options.ghosting) options_for_draggable.reverteffect = function(element) {
|
677 |
+
element.style.top = 0;
|
678 |
+
element.style.left = 0;
|
679 |
+
};
|
680 |
+
|
681 |
+
if(options.endeffect)
|
682 |
+
options_for_draggable.endeffect = options.endeffect;
|
683 |
+
|
684 |
+
if(options.zindex)
|
685 |
+
options_for_draggable.zindex = options.zindex;
|
686 |
+
|
687 |
+
// build options for the droppables
|
688 |
+
var options_for_droppable = {
|
689 |
+
overlap: options.overlap,
|
690 |
+
containment: options.containment,
|
691 |
+
tree: options.tree,
|
692 |
+
hoverclass: options.hoverclass,
|
693 |
+
onHover: Sortable.onHover
|
694 |
+
};
|
695 |
+
|
696 |
+
var options_for_tree = {
|
697 |
+
onHover: Sortable.onEmptyHover,
|
698 |
+
overlap: options.overlap,
|
699 |
+
containment: options.containment,
|
700 |
+
hoverclass: options.hoverclass
|
701 |
+
};
|
702 |
+
|
703 |
+
// fix for gecko engine
|
704 |
+
Element.cleanWhitespace(element);
|
705 |
+
|
706 |
+
options.draggables = [];
|
707 |
+
options.droppables = [];
|
708 |
+
|
709 |
+
// drop on empty handling
|
710 |
+
if(options.dropOnEmpty || options.tree) {
|
711 |
+
Droppables.add(element, options_for_tree);
|
712 |
+
options.droppables.push(element);
|
713 |
+
}
|
714 |
+
|
715 |
+
(options.elements || this.findElements(element, options) || []).each( function(e,i) {
|
716 |
+
var handle = options.handles ? $(options.handles[i]) :
|
717 |
+
(options.handle ? $(e).select('.' + options.handle)[0] : e);
|
718 |
+
options.draggables.push(
|
719 |
+
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
|
720 |
+
Droppables.add(e, options_for_droppable);
|
721 |
+
if(options.tree) e.treeNode = element;
|
722 |
+
options.droppables.push(e);
|
723 |
+
});
|
724 |
+
|
725 |
+
if(options.tree) {
|
726 |
+
(Sortable.findTreeElements(element, options) || []).each( function(e) {
|
727 |
+
Droppables.add(e, options_for_tree);
|
728 |
+
e.treeNode = element;
|
729 |
+
options.droppables.push(e);
|
730 |
+
});
|
731 |
+
}
|
732 |
+
|
733 |
+
// keep reference
|
734 |
+
this.sortables[element.identify()] = options;
|
735 |
+
|
736 |
+
// for onupdate
|
737 |
+
Draggables.addObserver(new SortableObserver(element, options.onUpdate));
|
738 |
+
|
739 |
+
},
|
740 |
+
|
741 |
+
// return all suitable-for-sortable elements in a guaranteed order
|
742 |
+
findElements: function(element, options) {
|
743 |
+
return Element.findChildren(
|
744 |
+
element, options.only, options.tree ? true : false, options.tag);
|
745 |
+
},
|
746 |
+
|
747 |
+
findTreeElements: function(element, options) {
|
748 |
+
return Element.findChildren(
|
749 |
+
element, options.only, options.tree ? true : false, options.treeTag);
|
750 |
+
},
|
751 |
+
|
752 |
+
onHover: function(element, dropon, overlap) {
|
753 |
+
if(Element.isParent(dropon, element)) return;
|
754 |
+
|
755 |
+
if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
|
756 |
+
return;
|
757 |
+
} else if(overlap>0.5) {
|
758 |
+
Sortable.mark(dropon, 'before');
|
759 |
+
if(dropon.previousSibling != element) {
|
760 |
+
var oldParentNode = element.parentNode;
|
761 |
+
element.style.visibility = "hidden"; // fix gecko rendering
|
762 |
+
dropon.parentNode.insertBefore(element, dropon);
|
763 |
+
if(dropon.parentNode!=oldParentNode)
|
764 |
+
Sortable.options(oldParentNode).onChange(element);
|
765 |
+
Sortable.options(dropon.parentNode).onChange(element);
|
766 |
+
}
|
767 |
+
} else {
|
768 |
+
Sortable.mark(dropon, 'after');
|
769 |
+
var nextElement = dropon.nextSibling || null;
|
770 |
+
if(nextElement != element) {
|
771 |
+
var oldParentNode = element.parentNode;
|
772 |
+
element.style.visibility = "hidden"; // fix gecko rendering
|
773 |
+
dropon.parentNode.insertBefore(element, nextElement);
|
774 |
+
if(dropon.parentNode!=oldParentNode)
|
775 |
+
Sortable.options(oldParentNode).onChange(element);
|
776 |
+
Sortable.options(dropon.parentNode).onChange(element);
|
777 |
+
}
|
778 |
+
}
|
779 |
+
},
|
780 |
+
|
781 |
+
onEmptyHover: function(element, dropon, overlap) {
|
782 |
+
var oldParentNode = element.parentNode;
|
783 |
+
var droponOptions = Sortable.options(dropon);
|
784 |
+
|
785 |
+
if(!Element.isParent(dropon, element)) {
|
786 |
+
var index;
|
787 |
+
|
788 |
+
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
|
789 |
+
var child = null;
|
790 |
+
|
791 |
+
if(children) {
|
792 |
+
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
|
793 |
+
|
794 |
+
for (index = 0; index < children.length; index += 1) {
|
795 |
+
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
|
796 |
+
offset -= Element.offsetSize (children[index], droponOptions.overlap);
|
797 |
+
} else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
|
798 |
+
child = index + 1 < children.length ? children[index + 1] : null;
|
799 |
+
break;
|
800 |
+
} else {
|
801 |
+
child = children[index];
|
802 |
+
break;
|
803 |
+
}
|
804 |
+
}
|
805 |
+
}
|
806 |
+
|
807 |
+
dropon.insertBefore(element, child);
|
808 |
+
|
809 |
+
Sortable.options(oldParentNode).onChange(element);
|
810 |
+
droponOptions.onChange(element);
|
811 |
+
}
|
812 |
+
},
|
813 |
+
|
814 |
+
unmark: function() {
|
815 |
+
if(Sortable._marker) Sortable._marker.hide();
|
816 |
+
},
|
817 |
+
|
818 |
+
mark: function(dropon, position) {
|
819 |
+
// mark on ghosting only
|
820 |
+
var sortable = Sortable.options(dropon.parentNode);
|
821 |
+
if(sortable && !sortable.ghosting) return;
|
822 |
+
|
823 |
+
if(!Sortable._marker) {
|
824 |
+
Sortable._marker =
|
825 |
+
($('dropmarker') || Element.extend(document.createElement('DIV'))).
|
826 |
+
hide().addClassName('dropmarker').setStyle({position:'absolute'});
|
827 |
+
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
|
828 |
+
}
|
829 |
+
var offsets = dropon.cumulativeOffset();
|
830 |
+
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
|
831 |
+
|
832 |
+
if(position=='after')
|
833 |
+
if(sortable.overlap == 'horizontal')
|
834 |
+
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
|
835 |
+
else
|
836 |
+
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
|
837 |
+
|
838 |
+
Sortable._marker.show();
|
839 |
+
},
|
840 |
+
|
841 |
+
_tree: function(element, options, parent) {
|
842 |
+
var children = Sortable.findElements(element, options) || [];
|
843 |
+
|
844 |
+
for (var i = 0; i < children.length; ++i) {
|
845 |
+
var match = children[i].id.match(options.format);
|
846 |
+
|
847 |
+
if (!match) continue;
|
848 |
+
|
849 |
+
var child = {
|
850 |
+
id: encodeURIComponent(match ? match[1] : null),
|
851 |
+
element: element,
|
852 |
+
parent: parent,
|
853 |
+
children: [],
|
854 |
+
position: parent.children.length,
|
855 |
+
container: $(children[i]).down(options.treeTag)
|
856 |
+
};
|
857 |
+
|
858 |
+
/* Get the element containing the children and recurse over it */
|
859 |
+
if (child.container)
|
860 |
+
this._tree(child.container, options, child);
|
861 |
+
|
862 |
+
parent.children.push (child);
|
863 |
+
}
|
864 |
+
|
865 |
+
return parent;
|
866 |
+
},
|
867 |
+
|
868 |
+
tree: function(element) {
|
869 |
+
element = $(element);
|
870 |
+
var sortableOptions = this.options(element);
|
871 |
+
var options = Object.extend({
|
872 |
+
tag: sortableOptions.tag,
|
873 |
+
treeTag: sortableOptions.treeTag,
|
874 |
+
only: sortableOptions.only,
|
875 |
+
name: element.id,
|
876 |
+
format: sortableOptions.format
|
877 |
+
}, arguments[1] || { });
|
878 |
+
|
879 |
+
var root = {
|
880 |
+
id: null,
|
881 |
+
parent: null,
|
882 |
+
children: [],
|
883 |
+
container: element,
|
884 |
+
position: 0
|
885 |
+
};
|
886 |
+
|
887 |
+
return Sortable._tree(element, options, root);
|
888 |
+
},
|
889 |
+
|
890 |
+
/* Construct a [i] index for a particular node */
|
891 |
+
_constructIndex: function(node) {
|
892 |
+
var index = '';
|
893 |
+
do {
|
894 |
+
if (node.id) index = '[' + node.position + ']' + index;
|
895 |
+
} while ((node = node.parent) != null);
|
896 |
+
return index;
|
897 |
+
},
|
898 |
+
|
899 |
+
sequence: function(element) {
|
900 |
+
element = $(element);
|
901 |
+
var options = Object.extend(this.options(element), arguments[1] || { });
|
902 |
+
|
903 |
+
return $(this.findElements(element, options) || []).map( function(item) {
|
904 |
+
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
|
905 |
+
});
|
906 |
+
},
|
907 |
+
|
908 |
+
setSequence: function(element, new_sequence) {
|
909 |
+
element = $(element);
|
910 |
+
var options = Object.extend(this.options(element), arguments[2] || { });
|
911 |
+
|
912 |
+
var nodeMap = { };
|
913 |
+
this.findElements(element, options).each( function(n) {
|
914 |
+
if (n.id.match(options.format))
|
915 |
+
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
|
916 |
+
n.parentNode.removeChild(n);
|
917 |
+
});
|
918 |
+
|
919 |
+
new_sequence.each(function(ident) {
|
920 |
+
var n = nodeMap[ident];
|
921 |
+
if (n) {
|
922 |
+
n[1].appendChild(n[0]);
|
923 |
+
delete nodeMap[ident];
|
924 |
+
}
|
925 |
+
});
|
926 |
+
},
|
927 |
+
|
928 |
+
serialize: function(element) {
|
929 |
+
element = $(element);
|
930 |
+
var options = Object.extend(Sortable.options(element), arguments[1] || { });
|
931 |
+
var name = encodeURIComponent(
|
932 |
+
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
|
933 |
+
|
934 |
+
if (options.tree) {
|
935 |
+
return Sortable.tree(element, arguments[1]).children.map( function (item) {
|
936 |
+
return [name + Sortable._constructIndex(item) + "[id]=" +
|
937 |
+
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
|
938 |
+
}).flatten().join('&');
|
939 |
+
} else {
|
940 |
+
return Sortable.sequence(element, arguments[1]).map( function(item) {
|
941 |
+
return name + "[]=" + encodeURIComponent(item);
|
942 |
+
}).join('&');
|
943 |
+
}
|
944 |
+
}
|
945 |
+
};
|
946 |
+
|
947 |
+
// Returns true if child is contained within element
|
948 |
+
Element.isParent = function(child, element) {
|
949 |
+
if (!child.parentNode || child == element) return false;
|
950 |
+
if (child.parentNode == element) return true;
|
951 |
+
return Element.isParent(child.parentNode, element);
|
952 |
+
};
|
953 |
+
|
954 |
+
Element.findChildren = function(element, only, recursive, tagName) {
|
955 |
+
if(!element.hasChildNodes()) return null;
|
956 |
+
tagName = tagName.toUpperCase();
|
957 |
+
if(only) only = [only].flatten();
|
958 |
+
var elements = [];
|
959 |
+
$A(element.childNodes).each( function(e) {
|
960 |
+
if(e.tagName && e.tagName.toUpperCase()==tagName &&
|
961 |
+
(!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
|
962 |
+
elements.push(e);
|
963 |
+
if(recursive) {
|
964 |
+
var grandchildren = Element.findChildren(e, only, recursive, tagName);
|
965 |
+
if(grandchildren) elements.push(grandchildren);
|
966 |
+
}
|
967 |
+
});
|
968 |
+
|
969 |
+
return (elements.length>0 ? elements.flatten() : []);
|
970 |
+
};
|
971 |
+
|
972 |
+
Element.offsetSize = function (element, type) {
|
973 |
+
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
|
974 |
+
};
|
js/mageho/sortproducts/effects.js
ADDED
@@ -0,0 +1,1123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us effects.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
// Contributors:
|
5 |
+
// Justin Palmer (http://encytemedia.com/)
|
6 |
+
// Mark Pilgrim (http://diveintomark.org/)
|
7 |
+
// Martin Bialasinki
|
8 |
+
//
|
9 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
10 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
11 |
+
|
12 |
+
// converts rgb() and #xxx to #xxxxxx format,
|
13 |
+
// returns self (or first argument) if not convertable
|
14 |
+
String.prototype.parseColor = function() {
|
15 |
+
var color = '#';
|
16 |
+
if (this.slice(0,4) == 'rgb(') {
|
17 |
+
var cols = this.slice(4,this.length-1).split(',');
|
18 |
+
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
|
19 |
+
} else {
|
20 |
+
if (this.slice(0,1) == '#') {
|
21 |
+
if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
|
22 |
+
if (this.length==7) color = this.toLowerCase();
|
23 |
+
}
|
24 |
+
}
|
25 |
+
return (color.length==7 ? color : (arguments[0] || this));
|
26 |
+
};
|
27 |
+
|
28 |
+
/*--------------------------------------------------------------------------*/
|
29 |
+
|
30 |
+
Element.collectTextNodes = function(element) {
|
31 |
+
return $A($(element).childNodes).collect( function(node) {
|
32 |
+
return (node.nodeType==3 ? node.nodeValue :
|
33 |
+
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
|
34 |
+
}).flatten().join('');
|
35 |
+
};
|
36 |
+
|
37 |
+
Element.collectTextNodesIgnoreClass = function(element, className) {
|
38 |
+
return $A($(element).childNodes).collect( function(node) {
|
39 |
+
return (node.nodeType==3 ? node.nodeValue :
|
40 |
+
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
|
41 |
+
Element.collectTextNodesIgnoreClass(node, className) : ''));
|
42 |
+
}).flatten().join('');
|
43 |
+
};
|
44 |
+
|
45 |
+
Element.setContentZoom = function(element, percent) {
|
46 |
+
element = $(element);
|
47 |
+
element.setStyle({fontSize: (percent/100) + 'em'});
|
48 |
+
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
|
49 |
+
return element;
|
50 |
+
};
|
51 |
+
|
52 |
+
Element.getInlineOpacity = function(element){
|
53 |
+
return $(element).style.opacity || '';
|
54 |
+
};
|
55 |
+
|
56 |
+
Element.forceRerendering = function(element) {
|
57 |
+
try {
|
58 |
+
element = $(element);
|
59 |
+
var n = document.createTextNode(' ');
|
60 |
+
element.appendChild(n);
|
61 |
+
element.removeChild(n);
|
62 |
+
} catch(e) { }
|
63 |
+
};
|
64 |
+
|
65 |
+
/*--------------------------------------------------------------------------*/
|
66 |
+
|
67 |
+
var Effect = {
|
68 |
+
_elementDoesNotExistError: {
|
69 |
+
name: 'ElementDoesNotExistError',
|
70 |
+
message: 'The specified DOM element does not exist, but is required for this effect to operate'
|
71 |
+
},
|
72 |
+
Transitions: {
|
73 |
+
linear: Prototype.K,
|
74 |
+
sinoidal: function(pos) {
|
75 |
+
return (-Math.cos(pos*Math.PI)/2) + .5;
|
76 |
+
},
|
77 |
+
reverse: function(pos) {
|
78 |
+
return 1-pos;
|
79 |
+
},
|
80 |
+
flicker: function(pos) {
|
81 |
+
var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
|
82 |
+
return pos > 1 ? 1 : pos;
|
83 |
+
},
|
84 |
+
wobble: function(pos) {
|
85 |
+
return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
|
86 |
+
},
|
87 |
+
pulse: function(pos, pulses) {
|
88 |
+
return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
|
89 |
+
},
|
90 |
+
spring: function(pos) {
|
91 |
+
return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
|
92 |
+
},
|
93 |
+
none: function(pos) {
|
94 |
+
return 0;
|
95 |
+
},
|
96 |
+
full: function(pos) {
|
97 |
+
return 1;
|
98 |
+
}
|
99 |
+
},
|
100 |
+
DefaultOptions: {
|
101 |
+
duration: 1.0, // seconds
|
102 |
+
fps: 100, // 100= assume 66fps max.
|
103 |
+
sync: false, // true for combining
|
104 |
+
from: 0.0,
|
105 |
+
to: 1.0,
|
106 |
+
delay: 0.0,
|
107 |
+
queue: 'parallel'
|
108 |
+
},
|
109 |
+
tagifyText: function(element) {
|
110 |
+
var tagifyStyle = 'position:relative';
|
111 |
+
if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
|
112 |
+
|
113 |
+
element = $(element);
|
114 |
+
$A(element.childNodes).each( function(child) {
|
115 |
+
if (child.nodeType==3) {
|
116 |
+
child.nodeValue.toArray().each( function(character) {
|
117 |
+
element.insertBefore(
|
118 |
+
new Element('span', {style: tagifyStyle}).update(
|
119 |
+
character == ' ' ? String.fromCharCode(160) : character),
|
120 |
+
child);
|
121 |
+
});
|
122 |
+
Element.remove(child);
|
123 |
+
}
|
124 |
+
});
|
125 |
+
},
|
126 |
+
multiple: function(element, effect) {
|
127 |
+
var elements;
|
128 |
+
if (((typeof element == 'object') ||
|
129 |
+
Object.isFunction(element)) &&
|
130 |
+
(element.length))
|
131 |
+
elements = element;
|
132 |
+
else
|
133 |
+
elements = $(element).childNodes;
|
134 |
+
|
135 |
+
var options = Object.extend({
|
136 |
+
speed: 0.1,
|
137 |
+
delay: 0.0
|
138 |
+
}, arguments[2] || { });
|
139 |
+
var masterDelay = options.delay;
|
140 |
+
|
141 |
+
$A(elements).each( function(element, index) {
|
142 |
+
new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
|
143 |
+
});
|
144 |
+
},
|
145 |
+
PAIRS: {
|
146 |
+
'slide': ['SlideDown','SlideUp'],
|
147 |
+
'blind': ['BlindDown','BlindUp'],
|
148 |
+
'appear': ['Appear','Fade']
|
149 |
+
},
|
150 |
+
toggle: function(element, effect, options) {
|
151 |
+
element = $(element);
|
152 |
+
effect = (effect || 'appear').toLowerCase();
|
153 |
+
|
154 |
+
return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({
|
155 |
+
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
|
156 |
+
}, options || {}));
|
157 |
+
}
|
158 |
+
};
|
159 |
+
|
160 |
+
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
|
161 |
+
|
162 |
+
/* ------------- core effects ------------- */
|
163 |
+
|
164 |
+
Effect.ScopedQueue = Class.create(Enumerable, {
|
165 |
+
initialize: function() {
|
166 |
+
this.effects = [];
|
167 |
+
this.interval = null;
|
168 |
+
},
|
169 |
+
_each: function(iterator) {
|
170 |
+
this.effects._each(iterator);
|
171 |
+
},
|
172 |
+
add: function(effect) {
|
173 |
+
var timestamp = new Date().getTime();
|
174 |
+
|
175 |
+
var position = Object.isString(effect.options.queue) ?
|
176 |
+
effect.options.queue : effect.options.queue.position;
|
177 |
+
|
178 |
+
switch(position) {
|
179 |
+
case 'front':
|
180 |
+
// move unstarted effects after this effect
|
181 |
+
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
|
182 |
+
e.startOn += effect.finishOn;
|
183 |
+
e.finishOn += effect.finishOn;
|
184 |
+
});
|
185 |
+
break;
|
186 |
+
case 'with-last':
|
187 |
+
timestamp = this.effects.pluck('startOn').max() || timestamp;
|
188 |
+
break;
|
189 |
+
case 'end':
|
190 |
+
// start effect after last queued effect has finished
|
191 |
+
timestamp = this.effects.pluck('finishOn').max() || timestamp;
|
192 |
+
break;
|
193 |
+
}
|
194 |
+
|
195 |
+
effect.startOn += timestamp;
|
196 |
+
effect.finishOn += timestamp;
|
197 |
+
|
198 |
+
if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
|
199 |
+
this.effects.push(effect);
|
200 |
+
|
201 |
+
if (!this.interval)
|
202 |
+
this.interval = setInterval(this.loop.bind(this), 15);
|
203 |
+
},
|
204 |
+
remove: function(effect) {
|
205 |
+
this.effects = this.effects.reject(function(e) { return e==effect });
|
206 |
+
if (this.effects.length == 0) {
|
207 |
+
clearInterval(this.interval);
|
208 |
+
this.interval = null;
|
209 |
+
}
|
210 |
+
},
|
211 |
+
loop: function() {
|
212 |
+
var timePos = new Date().getTime();
|
213 |
+
for(var i=0, len=this.effects.length;i<len;i++)
|
214 |
+
this.effects[i] && this.effects[i].loop(timePos);
|
215 |
+
}
|
216 |
+
});
|
217 |
+
|
218 |
+
Effect.Queues = {
|
219 |
+
instances: $H(),
|
220 |
+
get: function(queueName) {
|
221 |
+
if (!Object.isString(queueName)) return queueName;
|
222 |
+
|
223 |
+
return this.instances.get(queueName) ||
|
224 |
+
this.instances.set(queueName, new Effect.ScopedQueue());
|
225 |
+
}
|
226 |
+
};
|
227 |
+
Effect.Queue = Effect.Queues.get('global');
|
228 |
+
|
229 |
+
Effect.Base = Class.create({
|
230 |
+
position: null,
|
231 |
+
start: function(options) {
|
232 |
+
if (options && options.transition === false) options.transition = Effect.Transitions.linear;
|
233 |
+
this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
|
234 |
+
this.currentFrame = 0;
|
235 |
+
this.state = 'idle';
|
236 |
+
this.startOn = this.options.delay*1000;
|
237 |
+
this.finishOn = this.startOn+(this.options.duration*1000);
|
238 |
+
this.fromToDelta = this.options.to-this.options.from;
|
239 |
+
this.totalTime = this.finishOn-this.startOn;
|
240 |
+
this.totalFrames = this.options.fps*this.options.duration;
|
241 |
+
|
242 |
+
this.render = (function() {
|
243 |
+
function dispatch(effect, eventName) {
|
244 |
+
if (effect.options[eventName + 'Internal'])
|
245 |
+
effect.options[eventName + 'Internal'](effect);
|
246 |
+
if (effect.options[eventName])
|
247 |
+
effect.options[eventName](effect);
|
248 |
+
}
|
249 |
+
|
250 |
+
return function(pos) {
|
251 |
+
if (this.state === "idle") {
|
252 |
+
this.state = "running";
|
253 |
+
dispatch(this, 'beforeSetup');
|
254 |
+
if (this.setup) this.setup();
|
255 |
+
dispatch(this, 'afterSetup');
|
256 |
+
}
|
257 |
+
if (this.state === "running") {
|
258 |
+
pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
|
259 |
+
this.position = pos;
|
260 |
+
dispatch(this, 'beforeUpdate');
|
261 |
+
if (this.update) this.update(pos);
|
262 |
+
dispatch(this, 'afterUpdate');
|
263 |
+
}
|
264 |
+
};
|
265 |
+
})();
|
266 |
+
|
267 |
+
this.event('beforeStart');
|
268 |
+
if (!this.options.sync)
|
269 |
+
Effect.Queues.get(Object.isString(this.options.queue) ?
|
270 |
+
'global' : this.options.queue.scope).add(this);
|
271 |
+
},
|
272 |
+
loop: function(timePos) {
|
273 |
+
if (timePos >= this.startOn) {
|
274 |
+
if (timePos >= this.finishOn) {
|
275 |
+
this.render(1.0);
|
276 |
+
this.cancel();
|
277 |
+
this.event('beforeFinish');
|
278 |
+
if (this.finish) this.finish();
|
279 |
+
this.event('afterFinish');
|
280 |
+
return;
|
281 |
+
}
|
282 |
+
var pos = (timePos - this.startOn) / this.totalTime,
|
283 |
+
frame = (pos * this.totalFrames).round();
|
284 |
+
if (frame > this.currentFrame) {
|
285 |
+
this.render(pos);
|
286 |
+
this.currentFrame = frame;
|
287 |
+
}
|
288 |
+
}
|
289 |
+
},
|
290 |
+
cancel: function() {
|
291 |
+
if (!this.options.sync)
|
292 |
+
Effect.Queues.get(Object.isString(this.options.queue) ?
|
293 |
+
'global' : this.options.queue.scope).remove(this);
|
294 |
+
this.state = 'finished';
|
295 |
+
},
|
296 |
+
event: function(eventName) {
|
297 |
+
if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
|
298 |
+
if (this.options[eventName]) this.options[eventName](this);
|
299 |
+
},
|
300 |
+
inspect: function() {
|
301 |
+
var data = $H();
|
302 |
+
for(property in this)
|
303 |
+
if (!Object.isFunction(this[property])) data.set(property, this[property]);
|
304 |
+
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
|
305 |
+
}
|
306 |
+
});
|
307 |
+
|
308 |
+
Effect.Parallel = Class.create(Effect.Base, {
|
309 |
+
initialize: function(effects) {
|
310 |
+
this.effects = effects || [];
|
311 |
+
this.start(arguments[1]);
|
312 |
+
},
|
313 |
+
update: function(position) {
|
314 |
+
this.effects.invoke('render', position);
|
315 |
+
},
|
316 |
+
finish: function(position) {
|
317 |
+
this.effects.each( function(effect) {
|
318 |
+
effect.render(1.0);
|
319 |
+
effect.cancel();
|
320 |
+
effect.event('beforeFinish');
|
321 |
+
if (effect.finish) effect.finish(position);
|
322 |
+
effect.event('afterFinish');
|
323 |
+
});
|
324 |
+
}
|
325 |
+
});
|
326 |
+
|
327 |
+
Effect.Tween = Class.create(Effect.Base, {
|
328 |
+
initialize: function(object, from, to) {
|
329 |
+
object = Object.isString(object) ? $(object) : object;
|
330 |
+
var args = $A(arguments), method = args.last(),
|
331 |
+
options = args.length == 5 ? args[3] : null;
|
332 |
+
this.method = Object.isFunction(method) ? method.bind(object) :
|
333 |
+
Object.isFunction(object[method]) ? object[method].bind(object) :
|
334 |
+
function(value) { object[method] = value };
|
335 |
+
this.start(Object.extend({ from: from, to: to }, options || { }));
|
336 |
+
},
|
337 |
+
update: function(position) {
|
338 |
+
this.method(position);
|
339 |
+
}
|
340 |
+
});
|
341 |
+
|
342 |
+
Effect.Event = Class.create(Effect.Base, {
|
343 |
+
initialize: function() {
|
344 |
+
this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
|
345 |
+
},
|
346 |
+
update: Prototype.emptyFunction
|
347 |
+
});
|
348 |
+
|
349 |
+
Effect.Opacity = Class.create(Effect.Base, {
|
350 |
+
initialize: function(element) {
|
351 |
+
this.element = $(element);
|
352 |
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
353 |
+
// make this work on IE on elements without 'layout'
|
354 |
+
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
355 |
+
this.element.setStyle({zoom: 1});
|
356 |
+
var options = Object.extend({
|
357 |
+
from: this.element.getOpacity() || 0.0,
|
358 |
+
to: 1.0
|
359 |
+
}, arguments[1] || { });
|
360 |
+
this.start(options);
|
361 |
+
},
|
362 |
+
update: function(position) {
|
363 |
+
this.element.setOpacity(position);
|
364 |
+
}
|
365 |
+
});
|
366 |
+
|
367 |
+
Effect.Move = Class.create(Effect.Base, {
|
368 |
+
initialize: function(element) {
|
369 |
+
this.element = $(element);
|
370 |
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
371 |
+
var options = Object.extend({
|
372 |
+
x: 0,
|
373 |
+
y: 0,
|
374 |
+
mode: 'relative'
|
375 |
+
}, arguments[1] || { });
|
376 |
+
this.start(options);
|
377 |
+
},
|
378 |
+
setup: function() {
|
379 |
+
this.element.makePositioned();
|
380 |
+
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
|
381 |
+
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
|
382 |
+
if (this.options.mode == 'absolute') {
|
383 |
+
this.options.x = this.options.x - this.originalLeft;
|
384 |
+
this.options.y = this.options.y - this.originalTop;
|
385 |
+
}
|
386 |
+
},
|
387 |
+
update: function(position) {
|
388 |
+
this.element.setStyle({
|
389 |
+
left: (this.options.x * position + this.originalLeft).round() + 'px',
|
390 |
+
top: (this.options.y * position + this.originalTop).round() + 'px'
|
391 |
+
});
|
392 |
+
}
|
393 |
+
});
|
394 |
+
|
395 |
+
// for backwards compatibility
|
396 |
+
Effect.MoveBy = function(element, toTop, toLeft) {
|
397 |
+
return new Effect.Move(element,
|
398 |
+
Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
|
399 |
+
};
|
400 |
+
|
401 |
+
Effect.Scale = Class.create(Effect.Base, {
|
402 |
+
initialize: function(element, percent) {
|
403 |
+
this.element = $(element);
|
404 |
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
405 |
+
var options = Object.extend({
|
406 |
+
scaleX: true,
|
407 |
+
scaleY: true,
|
408 |
+
scaleContent: true,
|
409 |
+
scaleFromCenter: false,
|
410 |
+
scaleMode: 'box', // 'box' or 'contents' or { } with provided values
|
411 |
+
scaleFrom: 100.0,
|
412 |
+
scaleTo: percent
|
413 |
+
}, arguments[2] || { });
|
414 |
+
this.start(options);
|
415 |
+
},
|
416 |
+
setup: function() {
|
417 |
+
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
|
418 |
+
this.elementPositioning = this.element.getStyle('position');
|
419 |
+
|
420 |
+
this.originalStyle = { };
|
421 |
+
['top','left','width','height','fontSize'].each( function(k) {
|
422 |
+
this.originalStyle[k] = this.element.style[k];
|
423 |
+
}.bind(this));
|
424 |
+
|
425 |
+
this.originalTop = this.element.offsetTop;
|
426 |
+
this.originalLeft = this.element.offsetLeft;
|
427 |
+
|
428 |
+
var fontSize = this.element.getStyle('font-size') || '100%';
|
429 |
+
['em','px','%','pt'].each( function(fontSizeType) {
|
430 |
+
if (fontSize.indexOf(fontSizeType)>0) {
|
431 |
+
this.fontSize = parseFloat(fontSize);
|
432 |
+
this.fontSizeType = fontSizeType;
|
433 |
+
}
|
434 |
+
}.bind(this));
|
435 |
+
|
436 |
+
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
|
437 |
+
|
438 |
+
this.dims = null;
|
439 |
+
if (this.options.scaleMode=='box')
|
440 |
+
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
|
441 |
+
if (/^content/.test(this.options.scaleMode))
|
442 |
+
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
|
443 |
+
if (!this.dims)
|
444 |
+
this.dims = [this.options.scaleMode.originalHeight,
|
445 |
+
this.options.scaleMode.originalWidth];
|
446 |
+
},
|
447 |
+
update: function(position) {
|
448 |
+
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
|
449 |
+
if (this.options.scaleContent && this.fontSize)
|
450 |
+
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
|
451 |
+
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
|
452 |
+
},
|
453 |
+
finish: function(position) {
|
454 |
+
if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
|
455 |
+
},
|
456 |
+
setDimensions: function(height, width) {
|
457 |
+
var d = { };
|
458 |
+
if (this.options.scaleX) d.width = width.round() + 'px';
|
459 |
+
if (this.options.scaleY) d.height = height.round() + 'px';
|
460 |
+
if (this.options.scaleFromCenter) {
|
461 |
+
var topd = (height - this.dims[0])/2;
|
462 |
+
var leftd = (width - this.dims[1])/2;
|
463 |
+
if (this.elementPositioning == 'absolute') {
|
464 |
+
if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
|
465 |
+
if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
|
466 |
+
} else {
|
467 |
+
if (this.options.scaleY) d.top = -topd + 'px';
|
468 |
+
if (this.options.scaleX) d.left = -leftd + 'px';
|
469 |
+
}
|
470 |
+
}
|
471 |
+
this.element.setStyle(d);
|
472 |
+
}
|
473 |
+
});
|
474 |
+
|
475 |
+
Effect.Highlight = Class.create(Effect.Base, {
|
476 |
+
initialize: function(element) {
|
477 |
+
this.element = $(element);
|
478 |
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
479 |
+
var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
|
480 |
+
this.start(options);
|
481 |
+
},
|
482 |
+
setup: function() {
|
483 |
+
// Prevent executing on elements not in the layout flow
|
484 |
+
if (this.element.getStyle('display')=='none') { this.cancel(); return; }
|
485 |
+
// Disable background image during the effect
|
486 |
+
this.oldStyle = { };
|
487 |
+
if (!this.options.keepBackgroundImage) {
|
488 |
+
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
|
489 |
+
this.element.setStyle({backgroundImage: 'none'});
|
490 |
+
}
|
491 |
+
if (!this.options.endcolor)
|
492 |
+
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
|
493 |
+
if (!this.options.restorecolor)
|
494 |
+
this.options.restorecolor = this.element.getStyle('background-color');
|
495 |
+
// init color calculations
|
496 |
+
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
|
497 |
+
this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
|
498 |
+
},
|
499 |
+
update: function(position) {
|
500 |
+
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
|
501 |
+
return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
|
502 |
+
},
|
503 |
+
finish: function() {
|
504 |
+
this.element.setStyle(Object.extend(this.oldStyle, {
|
505 |
+
backgroundColor: this.options.restorecolor
|
506 |
+
}));
|
507 |
+
}
|
508 |
+
});
|
509 |
+
|
510 |
+
Effect.ScrollTo = function(element) {
|
511 |
+
var options = arguments[1] || { },
|
512 |
+
scrollOffsets = document.viewport.getScrollOffsets(),
|
513 |
+
elementOffsets = $(element).cumulativeOffset();
|
514 |
+
|
515 |
+
if (options.offset) elementOffsets[1] += options.offset;
|
516 |
+
|
517 |
+
return new Effect.Tween(null,
|
518 |
+
scrollOffsets.top,
|
519 |
+
elementOffsets[1],
|
520 |
+
options,
|
521 |
+
function(p){ scrollTo(scrollOffsets.left, p.round()); }
|
522 |
+
);
|
523 |
+
};
|
524 |
+
|
525 |
+
/* ------------- combination effects ------------- */
|
526 |
+
|
527 |
+
Effect.Fade = function(element) {
|
528 |
+
element = $(element);
|
529 |
+
var oldOpacity = element.getInlineOpacity();
|
530 |
+
var options = Object.extend({
|
531 |
+
from: element.getOpacity() || 1.0,
|
532 |
+
to: 0.0,
|
533 |
+
afterFinishInternal: function(effect) {
|
534 |
+
if (effect.options.to!=0) return;
|
535 |
+
effect.element.hide().setStyle({opacity: oldOpacity});
|
536 |
+
}
|
537 |
+
}, arguments[1] || { });
|
538 |
+
return new Effect.Opacity(element,options);
|
539 |
+
};
|
540 |
+
|
541 |
+
Effect.Appear = function(element) {
|
542 |
+
element = $(element);
|
543 |
+
var options = Object.extend({
|
544 |
+
from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
|
545 |
+
to: 1.0,
|
546 |
+
// force Safari to render floated elements properly
|
547 |
+
afterFinishInternal: function(effect) {
|
548 |
+
effect.element.forceRerendering();
|
549 |
+
},
|
550 |
+
beforeSetup: function(effect) {
|
551 |
+
effect.element.setOpacity(effect.options.from).show();
|
552 |
+
}}, arguments[1] || { });
|
553 |
+
return new Effect.Opacity(element,options);
|
554 |
+
};
|
555 |
+
|
556 |
+
Effect.Puff = function(element) {
|
557 |
+
element = $(element);
|
558 |
+
var oldStyle = {
|
559 |
+
opacity: element.getInlineOpacity(),
|
560 |
+
position: element.getStyle('position'),
|
561 |
+
top: element.style.top,
|
562 |
+
left: element.style.left,
|
563 |
+
width: element.style.width,
|
564 |
+
height: element.style.height
|
565 |
+
};
|
566 |
+
return new Effect.Parallel(
|
567 |
+
[ new Effect.Scale(element, 200,
|
568 |
+
{ sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
|
569 |
+
new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
|
570 |
+
Object.extend({ duration: 1.0,
|
571 |
+
beforeSetupInternal: function(effect) {
|
572 |
+
Position.absolutize(effect.effects[0].element);
|
573 |
+
},
|
574 |
+
afterFinishInternal: function(effect) {
|
575 |
+
effect.effects[0].element.hide().setStyle(oldStyle); }
|
576 |
+
}, arguments[1] || { })
|
577 |
+
);
|
578 |
+
};
|
579 |
+
|
580 |
+
Effect.BlindUp = function(element) {
|
581 |
+
element = $(element);
|
582 |
+
element.makeClipping();
|
583 |
+
return new Effect.Scale(element, 0,
|
584 |
+
Object.extend({ scaleContent: false,
|
585 |
+
scaleX: false,
|
586 |
+
restoreAfterFinish: true,
|
587 |
+
afterFinishInternal: function(effect) {
|
588 |
+
effect.element.hide().undoClipping();
|
589 |
+
}
|
590 |
+
}, arguments[1] || { })
|
591 |
+
);
|
592 |
+
};
|
593 |
+
|
594 |
+
Effect.BlindDown = function(element) {
|
595 |
+
element = $(element);
|
596 |
+
var elementDimensions = element.getDimensions();
|
597 |
+
return new Effect.Scale(element, 100, Object.extend({
|
598 |
+
scaleContent: false,
|
599 |
+
scaleX: false,
|
600 |
+
scaleFrom: 0,
|
601 |
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
602 |
+
restoreAfterFinish: true,
|
603 |
+
afterSetup: function(effect) {
|
604 |
+
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
605 |
+
},
|
606 |
+
afterFinishInternal: function(effect) {
|
607 |
+
effect.element.undoClipping();
|
608 |
+
}
|
609 |
+
}, arguments[1] || { }));
|
610 |
+
};
|
611 |
+
|
612 |
+
Effect.SwitchOff = function(element) {
|
613 |
+
element = $(element);
|
614 |
+
var oldOpacity = element.getInlineOpacity();
|
615 |
+
return new Effect.Appear(element, Object.extend({
|
616 |
+
duration: 0.4,
|
617 |
+
from: 0,
|
618 |
+
transition: Effect.Transitions.flicker,
|
619 |
+
afterFinishInternal: function(effect) {
|
620 |
+
new Effect.Scale(effect.element, 1, {
|
621 |
+
duration: 0.3, scaleFromCenter: true,
|
622 |
+
scaleX: false, scaleContent: false, restoreAfterFinish: true,
|
623 |
+
beforeSetup: function(effect) {
|
624 |
+
effect.element.makePositioned().makeClipping();
|
625 |
+
},
|
626 |
+
afterFinishInternal: function(effect) {
|
627 |
+
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
|
628 |
+
}
|
629 |
+
});
|
630 |
+
}
|
631 |
+
}, arguments[1] || { }));
|
632 |
+
};
|
633 |
+
|
634 |
+
Effect.DropOut = function(element) {
|
635 |
+
element = $(element);
|
636 |
+
var oldStyle = {
|
637 |
+
top: element.getStyle('top'),
|
638 |
+
left: element.getStyle('left'),
|
639 |
+
opacity: element.getInlineOpacity() };
|
640 |
+
return new Effect.Parallel(
|
641 |
+
[ new Effect.Move(element, {x: 0, y: 100, sync: true }),
|
642 |
+
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
|
643 |
+
Object.extend(
|
644 |
+
{ duration: 0.5,
|
645 |
+
beforeSetup: function(effect) {
|
646 |
+
effect.effects[0].element.makePositioned();
|
647 |
+
},
|
648 |
+
afterFinishInternal: function(effect) {
|
649 |
+
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
|
650 |
+
}
|
651 |
+
}, arguments[1] || { }));
|
652 |
+
};
|
653 |
+
|
654 |
+
Effect.Shake = function(element) {
|
655 |
+
element = $(element);
|
656 |
+
var options = Object.extend({
|
657 |
+
distance: 20,
|
658 |
+
duration: 0.5
|
659 |
+
}, arguments[1] || {});
|
660 |
+
var distance = parseFloat(options.distance);
|
661 |
+
var split = parseFloat(options.duration) / 10.0;
|
662 |
+
var oldStyle = {
|
663 |
+
top: element.getStyle('top'),
|
664 |
+
left: element.getStyle('left') };
|
665 |
+
return new Effect.Move(element,
|
666 |
+
{ x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
|
667 |
+
new Effect.Move(effect.element,
|
668 |
+
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
669 |
+
new Effect.Move(effect.element,
|
670 |
+
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
671 |
+
new Effect.Move(effect.element,
|
672 |
+
{ x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
673 |
+
new Effect.Move(effect.element,
|
674 |
+
{ x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
|
675 |
+
new Effect.Move(effect.element,
|
676 |
+
{ x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
|
677 |
+
effect.element.undoPositioned().setStyle(oldStyle);
|
678 |
+
}}); }}); }}); }}); }}); }});
|
679 |
+
};
|
680 |
+
|
681 |
+
Effect.SlideDown = function(element) {
|
682 |
+
element = $(element).cleanWhitespace();
|
683 |
+
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
|
684 |
+
var oldInnerBottom = element.down().getStyle('bottom');
|
685 |
+
var elementDimensions = element.getDimensions();
|
686 |
+
return new Effect.Scale(element, 100, Object.extend({
|
687 |
+
scaleContent: false,
|
688 |
+
scaleX: false,
|
689 |
+
scaleFrom: window.opera ? 0 : 1,
|
690 |
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
691 |
+
restoreAfterFinish: true,
|
692 |
+
afterSetup: function(effect) {
|
693 |
+
effect.element.makePositioned();
|
694 |
+
effect.element.down().makePositioned();
|
695 |
+
if (window.opera) effect.element.setStyle({top: ''});
|
696 |
+
effect.element.makeClipping().setStyle({height: '0px'}).show();
|
697 |
+
},
|
698 |
+
afterUpdateInternal: function(effect) {
|
699 |
+
effect.element.down().setStyle({bottom:
|
700 |
+
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
701 |
+
},
|
702 |
+
afterFinishInternal: function(effect) {
|
703 |
+
effect.element.undoClipping().undoPositioned();
|
704 |
+
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
|
705 |
+
}, arguments[1] || { })
|
706 |
+
);
|
707 |
+
};
|
708 |
+
|
709 |
+
Effect.SlideUp = function(element) {
|
710 |
+
element = $(element).cleanWhitespace();
|
711 |
+
var oldInnerBottom = element.down().getStyle('bottom');
|
712 |
+
var elementDimensions = element.getDimensions();
|
713 |
+
return new Effect.Scale(element, window.opera ? 0 : 1,
|
714 |
+
Object.extend({ scaleContent: false,
|
715 |
+
scaleX: false,
|
716 |
+
scaleMode: 'box',
|
717 |
+
scaleFrom: 100,
|
718 |
+
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
|
719 |
+
restoreAfterFinish: true,
|
720 |
+
afterSetup: function(effect) {
|
721 |
+
effect.element.makePositioned();
|
722 |
+
effect.element.down().makePositioned();
|
723 |
+
if (window.opera) effect.element.setStyle({top: ''});
|
724 |
+
effect.element.makeClipping().show();
|
725 |
+
},
|
726 |
+
afterUpdateInternal: function(effect) {
|
727 |
+
effect.element.down().setStyle({bottom:
|
728 |
+
(effect.dims[0] - effect.element.clientHeight) + 'px' });
|
729 |
+
},
|
730 |
+
afterFinishInternal: function(effect) {
|
731 |
+
effect.element.hide().undoClipping().undoPositioned();
|
732 |
+
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
|
733 |
+
}
|
734 |
+
}, arguments[1] || { })
|
735 |
+
);
|
736 |
+
};
|
737 |
+
|
738 |
+
// Bug in opera makes the TD containing this element expand for a instance after finish
|
739 |
+
Effect.Squish = function(element) {
|
740 |
+
return new Effect.Scale(element, window.opera ? 1 : 0, {
|
741 |
+
restoreAfterFinish: true,
|
742 |
+
beforeSetup: function(effect) {
|
743 |
+
effect.element.makeClipping();
|
744 |
+
},
|
745 |
+
afterFinishInternal: function(effect) {
|
746 |
+
effect.element.hide().undoClipping();
|
747 |
+
}
|
748 |
+
});
|
749 |
+
};
|
750 |
+
|
751 |
+
Effect.Grow = function(element) {
|
752 |
+
element = $(element);
|
753 |
+
var options = Object.extend({
|
754 |
+
direction: 'center',
|
755 |
+
moveTransition: Effect.Transitions.sinoidal,
|
756 |
+
scaleTransition: Effect.Transitions.sinoidal,
|
757 |
+
opacityTransition: Effect.Transitions.full
|
758 |
+
}, arguments[1] || { });
|
759 |
+
var oldStyle = {
|
760 |
+
top: element.style.top,
|
761 |
+
left: element.style.left,
|
762 |
+
height: element.style.height,
|
763 |
+
width: element.style.width,
|
764 |
+
opacity: element.getInlineOpacity() };
|
765 |
+
|
766 |
+
var dims = element.getDimensions();
|
767 |
+
var initialMoveX, initialMoveY;
|
768 |
+
var moveX, moveY;
|
769 |
+
|
770 |
+
switch (options.direction) {
|
771 |
+
case 'top-left':
|
772 |
+
initialMoveX = initialMoveY = moveX = moveY = 0;
|
773 |
+
break;
|
774 |
+
case 'top-right':
|
775 |
+
initialMoveX = dims.width;
|
776 |
+
initialMoveY = moveY = 0;
|
777 |
+
moveX = -dims.width;
|
778 |
+
break;
|
779 |
+
case 'bottom-left':
|
780 |
+
initialMoveX = moveX = 0;
|
781 |
+
initialMoveY = dims.height;
|
782 |
+
moveY = -dims.height;
|
783 |
+
break;
|
784 |
+
case 'bottom-right':
|
785 |
+
initialMoveX = dims.width;
|
786 |
+
initialMoveY = dims.height;
|
787 |
+
moveX = -dims.width;
|
788 |
+
moveY = -dims.height;
|
789 |
+
break;
|
790 |
+
case 'center':
|
791 |
+
initialMoveX = dims.width / 2;
|
792 |
+
initialMoveY = dims.height / 2;
|
793 |
+
moveX = -dims.width / 2;
|
794 |
+
moveY = -dims.height / 2;
|
795 |
+
break;
|
796 |
+
}
|
797 |
+
|
798 |
+
return new Effect.Move(element, {
|
799 |
+
x: initialMoveX,
|
800 |
+
y: initialMoveY,
|
801 |
+
duration: 0.01,
|
802 |
+
beforeSetup: function(effect) {
|
803 |
+
effect.element.hide().makeClipping().makePositioned();
|
804 |
+
},
|
805 |
+
afterFinishInternal: function(effect) {
|
806 |
+
new Effect.Parallel(
|
807 |
+
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
|
808 |
+
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
|
809 |
+
new Effect.Scale(effect.element, 100, {
|
810 |
+
scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
|
811 |
+
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
|
812 |
+
], Object.extend({
|
813 |
+
beforeSetup: function(effect) {
|
814 |
+
effect.effects[0].element.setStyle({height: '0px'}).show();
|
815 |
+
},
|
816 |
+
afterFinishInternal: function(effect) {
|
817 |
+
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
|
818 |
+
}
|
819 |
+
}, options)
|
820 |
+
);
|
821 |
+
}
|
822 |
+
});
|
823 |
+
};
|
824 |
+
|
825 |
+
Effect.Shrink = function(element) {
|
826 |
+
element = $(element);
|
827 |
+
var options = Object.extend({
|
828 |
+
direction: 'center',
|
829 |
+
moveTransition: Effect.Transitions.sinoidal,
|
830 |
+
scaleTransition: Effect.Transitions.sinoidal,
|
831 |
+
opacityTransition: Effect.Transitions.none
|
832 |
+
}, arguments[1] || { });
|
833 |
+
var oldStyle = {
|
834 |
+
top: element.style.top,
|
835 |
+
left: element.style.left,
|
836 |
+
height: element.style.height,
|
837 |
+
width: element.style.width,
|
838 |
+
opacity: element.getInlineOpacity() };
|
839 |
+
|
840 |
+
var dims = element.getDimensions();
|
841 |
+
var moveX, moveY;
|
842 |
+
|
843 |
+
switch (options.direction) {
|
844 |
+
case 'top-left':
|
845 |
+
moveX = moveY = 0;
|
846 |
+
break;
|
847 |
+
case 'top-right':
|
848 |
+
moveX = dims.width;
|
849 |
+
moveY = 0;
|
850 |
+
break;
|
851 |
+
case 'bottom-left':
|
852 |
+
moveX = 0;
|
853 |
+
moveY = dims.height;
|
854 |
+
break;
|
855 |
+
case 'bottom-right':
|
856 |
+
moveX = dims.width;
|
857 |
+
moveY = dims.height;
|
858 |
+
break;
|
859 |
+
case 'center':
|
860 |
+
moveX = dims.width / 2;
|
861 |
+
moveY = dims.height / 2;
|
862 |
+
break;
|
863 |
+
}
|
864 |
+
|
865 |
+
return new Effect.Parallel(
|
866 |
+
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
|
867 |
+
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
|
868 |
+
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
|
869 |
+
], Object.extend({
|
870 |
+
beforeStartInternal: function(effect) {
|
871 |
+
effect.effects[0].element.makePositioned().makeClipping();
|
872 |
+
},
|
873 |
+
afterFinishInternal: function(effect) {
|
874 |
+
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
|
875 |
+
}, options)
|
876 |
+
);
|
877 |
+
};
|
878 |
+
|
879 |
+
Effect.Pulsate = function(element) {
|
880 |
+
element = $(element);
|
881 |
+
var options = arguments[1] || { },
|
882 |
+
oldOpacity = element.getInlineOpacity(),
|
883 |
+
transition = options.transition || Effect.Transitions.linear,
|
884 |
+
reverser = function(pos){
|
885 |
+
return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
|
886 |
+
};
|
887 |
+
|
888 |
+
return new Effect.Opacity(element,
|
889 |
+
Object.extend(Object.extend({ duration: 2.0, from: 0,
|
890 |
+
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
|
891 |
+
}, options), {transition: reverser}));
|
892 |
+
};
|
893 |
+
|
894 |
+
Effect.Fold = function(element) {
|
895 |
+
element = $(element);
|
896 |
+
var oldStyle = {
|
897 |
+
top: element.style.top,
|
898 |
+
left: element.style.left,
|
899 |
+
width: element.style.width,
|
900 |
+
height: element.style.height };
|
901 |
+
element.makeClipping();
|
902 |
+
return new Effect.Scale(element, 5, Object.extend({
|
903 |
+
scaleContent: false,
|
904 |
+
scaleX: false,
|
905 |
+
afterFinishInternal: function(effect) {
|
906 |
+
new Effect.Scale(element, 1, {
|
907 |
+
scaleContent: false,
|
908 |
+
scaleY: false,
|
909 |
+
afterFinishInternal: function(effect) {
|
910 |
+
effect.element.hide().undoClipping().setStyle(oldStyle);
|
911 |
+
} });
|
912 |
+
}}, arguments[1] || { }));
|
913 |
+
};
|
914 |
+
|
915 |
+
Effect.Morph = Class.create(Effect.Base, {
|
916 |
+
initialize: function(element) {
|
917 |
+
this.element = $(element);
|
918 |
+
if (!this.element) throw(Effect._elementDoesNotExistError);
|
919 |
+
var options = Object.extend({
|
920 |
+
style: { }
|
921 |
+
}, arguments[1] || { });
|
922 |
+
|
923 |
+
if (!Object.isString(options.style)) this.style = $H(options.style);
|
924 |
+
else {
|
925 |
+
if (options.style.include(':'))
|
926 |
+
this.style = options.style.parseStyle();
|
927 |
+
else {
|
928 |
+
this.element.addClassName(options.style);
|
929 |
+
this.style = $H(this.element.getStyles());
|
930 |
+
this.element.removeClassName(options.style);
|
931 |
+
var css = this.element.getStyles();
|
932 |
+
this.style = this.style.reject(function(style) {
|
933 |
+
return style.value == css[style.key];
|
934 |
+
});
|
935 |
+
options.afterFinishInternal = function(effect) {
|
936 |
+
effect.element.addClassName(effect.options.style);
|
937 |
+
effect.transforms.each(function(transform) {
|
938 |
+
effect.element.style[transform.style] = '';
|
939 |
+
});
|
940 |
+
};
|
941 |
+
}
|
942 |
+
}
|
943 |
+
this.start(options);
|
944 |
+
},
|
945 |
+
|
946 |
+
setup: function(){
|
947 |
+
function parseColor(color){
|
948 |
+
if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
|
949 |
+
color = color.parseColor();
|
950 |
+
return $R(0,2).map(function(i){
|
951 |
+
return parseInt( color.slice(i*2+1,i*2+3), 16 );
|
952 |
+
});
|
953 |
+
}
|
954 |
+
this.transforms = this.style.map(function(pair){
|
955 |
+
var property = pair[0], value = pair[1], unit = null;
|
956 |
+
|
957 |
+
if (value.parseColor('#zzzzzz') != '#zzzzzz') {
|
958 |
+
value = value.parseColor();
|
959 |
+
unit = 'color';
|
960 |
+
} else if (property == 'opacity') {
|
961 |
+
value = parseFloat(value);
|
962 |
+
if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
|
963 |
+
this.element.setStyle({zoom: 1});
|
964 |
+
} else if (Element.CSS_LENGTH.test(value)) {
|
965 |
+
var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
|
966 |
+
value = parseFloat(components[1]);
|
967 |
+
unit = (components.length == 3) ? components[2] : null;
|
968 |
+
}
|
969 |
+
|
970 |
+
var originalValue = this.element.getStyle(property);
|
971 |
+
return {
|
972 |
+
style: property.camelize(),
|
973 |
+
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
|
974 |
+
targetValue: unit=='color' ? parseColor(value) : value,
|
975 |
+
unit: unit
|
976 |
+
};
|
977 |
+
}.bind(this)).reject(function(transform){
|
978 |
+
return (
|
979 |
+
(transform.originalValue == transform.targetValue) ||
|
980 |
+
(
|
981 |
+
transform.unit != 'color' &&
|
982 |
+
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
|
983 |
+
)
|
984 |
+
);
|
985 |
+
});
|
986 |
+
},
|
987 |
+
update: function(position) {
|
988 |
+
var style = { }, transform, i = this.transforms.length;
|
989 |
+
while(i--)
|
990 |
+
style[(transform = this.transforms[i]).style] =
|
991 |
+
transform.unit=='color' ? '#'+
|
992 |
+
(Math.round(transform.originalValue[0]+
|
993 |
+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
|
994 |
+
(Math.round(transform.originalValue[1]+
|
995 |
+
(transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
|
996 |
+
(Math.round(transform.originalValue[2]+
|
997 |
+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
|
998 |
+
(transform.originalValue +
|
999 |
+
(transform.targetValue - transform.originalValue) * position).toFixed(3) +
|
1000 |
+
(transform.unit === null ? '' : transform.unit);
|
1001 |
+
this.element.setStyle(style, true);
|
1002 |
+
}
|
1003 |
+
});
|
1004 |
+
|
1005 |
+
Effect.Transform = Class.create({
|
1006 |
+
initialize: function(tracks){
|
1007 |
+
this.tracks = [];
|
1008 |
+
this.options = arguments[1] || { };
|
1009 |
+
this.addTracks(tracks);
|
1010 |
+
},
|
1011 |
+
addTracks: function(tracks){
|
1012 |
+
tracks.each(function(track){
|
1013 |
+
track = $H(track);
|
1014 |
+
var data = track.values().first();
|
1015 |
+
this.tracks.push($H({
|
1016 |
+
ids: track.keys().first(),
|
1017 |
+
effect: Effect.Morph,
|
1018 |
+
options: { style: data }
|
1019 |
+
}));
|
1020 |
+
}.bind(this));
|
1021 |
+
return this;
|
1022 |
+
},
|
1023 |
+
play: function(){
|
1024 |
+
return new Effect.Parallel(
|
1025 |
+
this.tracks.map(function(track){
|
1026 |
+
var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
|
1027 |
+
var elements = [$(ids) || $$(ids)].flatten();
|
1028 |
+
return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
|
1029 |
+
}).flatten(),
|
1030 |
+
this.options
|
1031 |
+
);
|
1032 |
+
}
|
1033 |
+
});
|
1034 |
+
|
1035 |
+
Element.CSS_PROPERTIES = $w(
|
1036 |
+
'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
|
1037 |
+
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
|
1038 |
+
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
|
1039 |
+
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
|
1040 |
+
'fontSize fontWeight height left letterSpacing lineHeight ' +
|
1041 |
+
'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
|
1042 |
+
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
|
1043 |
+
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
|
1044 |
+
'right textIndent top width wordSpacing zIndex');
|
1045 |
+
|
1046 |
+
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
|
1047 |
+
|
1048 |
+
String.__parseStyleElement = document.createElement('div');
|
1049 |
+
String.prototype.parseStyle = function(){
|
1050 |
+
var style, styleRules = $H();
|
1051 |
+
if (Prototype.Browser.WebKit)
|
1052 |
+
style = new Element('div',{style:this}).style;
|
1053 |
+
else {
|
1054 |
+
String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
|
1055 |
+
style = String.__parseStyleElement.childNodes[0].style;
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
Element.CSS_PROPERTIES.each(function(property){
|
1059 |
+
if (style[property]) styleRules.set(property, style[property]);
|
1060 |
+
});
|
1061 |
+
|
1062 |
+
if (Prototype.Browser.IE && this.include('opacity'))
|
1063 |
+
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
|
1064 |
+
|
1065 |
+
return styleRules;
|
1066 |
+
};
|
1067 |
+
|
1068 |
+
if (document.defaultView && document.defaultView.getComputedStyle) {
|
1069 |
+
Element.getStyles = function(element) {
|
1070 |
+
var css = document.defaultView.getComputedStyle($(element), null);
|
1071 |
+
return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
|
1072 |
+
styles[property] = css[property];
|
1073 |
+
return styles;
|
1074 |
+
});
|
1075 |
+
};
|
1076 |
+
} else {
|
1077 |
+
Element.getStyles = function(element) {
|
1078 |
+
element = $(element);
|
1079 |
+
var css = element.currentStyle, styles;
|
1080 |
+
styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
|
1081 |
+
results[property] = css[property];
|
1082 |
+
return results;
|
1083 |
+
});
|
1084 |
+
if (!styles.opacity) styles.opacity = element.getOpacity();
|
1085 |
+
return styles;
|
1086 |
+
};
|
1087 |
+
}
|
1088 |
+
|
1089 |
+
Effect.Methods = {
|
1090 |
+
morph: function(element, style) {
|
1091 |
+
element = $(element);
|
1092 |
+
new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
|
1093 |
+
return element;
|
1094 |
+
},
|
1095 |
+
visualEffect: function(element, effect, options) {
|
1096 |
+
element = $(element);
|
1097 |
+
var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
|
1098 |
+
new Effect[klass](element, options);
|
1099 |
+
return element;
|
1100 |
+
},
|
1101 |
+
highlight: function(element, options) {
|
1102 |
+
element = $(element);
|
1103 |
+
new Effect.Highlight(element, options);
|
1104 |
+
return element;
|
1105 |
+
}
|
1106 |
+
};
|
1107 |
+
|
1108 |
+
$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
|
1109 |
+
'pulsate shake puff squish switchOff dropOut').each(
|
1110 |
+
function(effect) {
|
1111 |
+
Effect.Methods[effect] = function(element, options){
|
1112 |
+
element = $(element);
|
1113 |
+
Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
|
1114 |
+
return element;
|
1115 |
+
};
|
1116 |
+
}
|
1117 |
+
);
|
1118 |
+
|
1119 |
+
$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
|
1120 |
+
function(f) { Effect.Methods[f] = Element[f]; }
|
1121 |
+
);
|
1122 |
+
|
1123 |
+
Element.addMethods(Effect.Methods);
|
js/mageho/sortproducts/excanvas.js
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2006 Google Inc.
|
2 |
+
//
|
3 |
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
// you may not use this file except in compliance with the License.
|
5 |
+
// You may obtain a copy of the License at
|
6 |
+
//
|
7 |
+
// http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
//
|
9 |
+
// Unless required by applicable law or agreed to in writing, software
|
10 |
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
// See the License for the specific language governing permissions and
|
13 |
+
// limitations under the License.
|
14 |
+
document.createElement("canvas").getContext||(function(){var s=Math,j=s.round,F=s.sin,G=s.cos,V=s.abs,W=s.sqrt,k=10,v=k/2;function X(){return this.context_||(this.context_=new H(this))}var L=Array.prototype.slice;function Y(b,a){var c=L.call(arguments,2);return function(){return b.apply(a,c.concat(L.call(arguments)))}}var M={init:function(b){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var a=b||document;a.createElement("canvas");a.attachEvent("onreadystatechange",Y(this.init_,this,a))}},init_:function(b){b.namespaces.g_vml_||
|
15 |
+
b.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");b.namespaces.g_o_||b.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");if(!b.styleSheets.ex_canvas_){var a=b.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var c=b.getElementsByTagName("canvas"),d=0;for(;d<c.length;d++)this.initElement(c[d])},
|
16 |
+
initElement:function(b){if(!b.getContext){b.getContext=X;b.innerHTML="";b.attachEvent("onpropertychange",Z);b.attachEvent("onresize",$);var a=b.attributes;if(a.width&&a.width.specified)b.style.width=a.width.nodeValue+"px";else b.width=b.clientWidth;if(a.height&&a.height.specified)b.style.height=a.height.nodeValue+"px";else b.height=b.clientHeight}return b}};function Z(b){var a=b.srcElement;switch(b.propertyName){case "width":a.style.width=a.attributes.width.nodeValue+"px";a.getContext().clearRect();
|
17 |
+
break;case "height":a.style.height=a.attributes.height.nodeValue+"px";a.getContext().clearRect();break}}function $(b){var a=b.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+"px";a.firstChild.style.height=a.clientHeight+"px"}}M.init();var N=[],B=0;for(;B<16;B++){var C=0;for(;C<16;C++)N[B*16+C]=B.toString(16)+C.toString(16)}function I(){return[[1,0,0],[0,1,0],[0,0,1]]}function y(b,a){var c=I(),d=0;for(;d<3;d++){var f=0;for(;f<3;f++){var h=0,g=0;for(;g<3;g++)h+=b[d][g]*a[g][f];c[d][f]=
|
18 |
+
h}}return c}function O(b,a){a.fillStyle=b.fillStyle;a.lineCap=b.lineCap;a.lineJoin=b.lineJoin;a.lineWidth=b.lineWidth;a.miterLimit=b.miterLimit;a.shadowBlur=b.shadowBlur;a.shadowColor=b.shadowColor;a.shadowOffsetX=b.shadowOffsetX;a.shadowOffsetY=b.shadowOffsetY;a.strokeStyle=b.strokeStyle;a.globalAlpha=b.globalAlpha;a.arcScaleX_=b.arcScaleX_;a.arcScaleY_=b.arcScaleY_;a.lineScale_=b.lineScale_}function P(b){var a,c=1;b=String(b);if(b.substring(0,3)=="rgb"){var d=b.indexOf("(",3),f=b.indexOf(")",d+
|
19 |
+
1),h=b.substring(d+1,f).split(",");a="#";var g=0;for(;g<3;g++)a+=N[Number(h[g])];if(h.length==4&&b.substr(3,1)=="a")c=h[3]}else a=b;return{color:a,alpha:c}}function aa(b){switch(b){case "butt":return"flat";case "round":return"round";case "square":default:return"square"}}function H(b){this.m_=I();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=k*1;this.globalAlpha=1;this.canvas=b;
|
20 |
+
var a=b.ownerDocument.createElement("div");a.style.width=b.clientWidth+"px";a.style.height=b.clientHeight+"px";a.style.position="absolute";b.appendChild(a);this.element_=a;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}var i=H.prototype;i.clearRect=function(){this.element_.innerHTML=""};i.beginPath=function(){this.currentPath_=[]};i.moveTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};
|
21 |
+
i.lineTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};i.bezierCurveTo=function(b,a,c,d,f,h){var g=this.getCoords_(f,h),l=this.getCoords_(b,a),e=this.getCoords_(c,d);Q(this,l,e,g)};function Q(b,a,c,d){b.currentPath_.push({type:"bezierCurveTo",cp1x:a.x,cp1y:a.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y});b.currentX_=d.x;b.currentY_=d.y}i.quadraticCurveTo=function(b,a,c,d){var f=this.getCoords_(b,a),h=this.getCoords_(c,d),g={x:this.currentX_+
|
22 |
+
0.6666666666666666*(f.x-this.currentX_),y:this.currentY_+0.6666666666666666*(f.y-this.currentY_)};Q(this,g,{x:g.x+(h.x-this.currentX_)/3,y:g.y+(h.y-this.currentY_)/3},h)};i.arc=function(b,a,c,d,f,h){c*=k;var g=h?"at":"wa",l=b+G(d)*c-v,e=a+F(d)*c-v,m=b+G(f)*c-v,r=a+F(f)*c-v;if(l==m&&!h)l+=0.125;var n=this.getCoords_(b,a),o=this.getCoords_(l,e),q=this.getCoords_(m,r);this.currentPath_.push({type:g,x:n.x,y:n.y,radius:c,xStart:o.x,yStart:o.y,xEnd:q.x,yEnd:q.y})};i.rect=function(b,a,c,d){this.moveTo(b,
|
23 |
+
a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath()};i.strokeRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.stroke();this.currentPath_=f};i.fillRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.fill();this.currentPath_=f};i.createLinearGradient=function(b,
|
24 |
+
a,c,d){var f=new D("gradient");f.x0_=b;f.y0_=a;f.x1_=c;f.y1_=d;return f};i.createRadialGradient=function(b,a,c,d,f,h){var g=new D("gradientradial");g.x0_=b;g.y0_=a;g.r0_=c;g.x1_=d;g.y1_=f;g.r1_=h;return g};i.drawImage=function(b){var a,c,d,f,h,g,l,e,m=b.runtimeStyle.width,r=b.runtimeStyle.height;b.runtimeStyle.width="auto";b.runtimeStyle.height="auto";var n=b.width,o=b.height;b.runtimeStyle.width=m;b.runtimeStyle.height=r;if(arguments.length==3){a=arguments[1];c=arguments[2];h=g=0;l=d=n;e=f=o}else if(arguments.length==
|
25 |
+
5){a=arguments[1];c=arguments[2];d=arguments[3];f=arguments[4];h=g=0;l=n;e=o}else if(arguments.length==9){h=arguments[1];g=arguments[2];l=arguments[3];e=arguments[4];a=arguments[5];c=arguments[6];d=arguments[7];f=arguments[8]}else throw Error("Invalid number of arguments");var q=this.getCoords_(a,c),t=[];t.push(" <g_vml_:group",' coordsize="',k*10,",",k*10,'"',' coordorigin="0,0"',' style="width:',10,"px;height:",10,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]){var E=[];E.push("M11=",
|
26 |
+
this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",j(q.x/k),",","Dy=",j(q.y/k),"");var p=q,z=this.getCoords_(a+d,c),w=this.getCoords_(a,c+f),x=this.getCoords_(a+d,c+f);p.x=s.max(p.x,z.x,w.x,x.x);p.y=s.max(p.y,z.y,w.y,x.y);t.push("padding:0 ",j(p.x/k),"px ",j(p.y/k),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",E.join(""),", sizingmethod='clip');")}else t.push("top:",j(q.y/k),"px;left:",j(q.x/k),"px;");t.push(' ">','<g_vml_:image src="',b.src,
|
27 |
+
'"',' style="width:',k*d,"px;"," height:",k*f,'px;"',' cropleft="',h/n,'"',' croptop="',g/o,'"',' cropright="',(n-h-l)/n,'"',' cropbottom="',(o-g-e)/o,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",t.join(""))};i.stroke=function(b){var a=[],c=P(b?this.fillStyle:this.strokeStyle),d=c.color,f=c.alpha*this.globalAlpha;a.push("<g_vml_:shape",' filled="',!!b,'"',' style="position:absolute;width:',10,"px;height:",10,'px;"',' coordorigin="0 0" coordsize="',k*10," ",k*10,'"',' stroked="',
|
28 |
+
!b,'"',' path="');var h={x:null,y:null},g={x:null,y:null},l=0;for(;l<this.currentPath_.length;l++){var e=this.currentPath_[l];switch(e.type){case "moveTo":a.push(" m ",j(e.x),",",j(e.y));break;case "lineTo":a.push(" l ",j(e.x),",",j(e.y));break;case "close":a.push(" x ");e=null;break;case "bezierCurveTo":a.push(" c ",j(e.cp1x),",",j(e.cp1y),",",j(e.cp2x),",",j(e.cp2y),",",j(e.x),",",j(e.y));break;case "at":case "wa":a.push(" ",e.type," ",j(e.x-this.arcScaleX_*e.radius),",",j(e.y-this.arcScaleY_*e.radius),
|
29 |
+
" ",j(e.x+this.arcScaleX_*e.radius),",",j(e.y+this.arcScaleY_*e.radius)," ",j(e.xStart),",",j(e.yStart)," ",j(e.xEnd),",",j(e.yEnd));break}if(e){if(h.x==null||e.x<h.x)h.x=e.x;if(g.x==null||e.x>g.x)g.x=e.x;if(h.y==null||e.y<h.y)h.y=e.y;if(g.y==null||e.y>g.y)g.y=e.y}}a.push(' ">');if(b)if(typeof this.fillStyle=="object"){var m=this.fillStyle,r=0,n={x:0,y:0},o=0,q=1;if(m.type_=="gradient"){var t=m.x1_/this.arcScaleX_,E=m.y1_/this.arcScaleY_,p=this.getCoords_(m.x0_/this.arcScaleX_,m.y0_/this.arcScaleY_),
|
30 |
+
z=this.getCoords_(t,E);r=Math.atan2(z.x-p.x,z.y-p.y)*180/Math.PI;if(r<0)r+=360;if(r<1.0E-6)r=0}else{var p=this.getCoords_(m.x0_,m.y0_),w=g.x-h.x,x=g.y-h.y;n={x:(p.x-h.x)/w,y:(p.y-h.y)/x};w/=this.arcScaleX_*k;x/=this.arcScaleY_*k;var R=s.max(w,x);o=2*m.r0_/R;q=2*m.r1_/R-o}var u=m.colors_;u.sort(function(ba,ca){return ba.offset-ca.offset});var J=u.length,da=u[0].color,ea=u[J-1].color,fa=u[0].alpha*this.globalAlpha,ga=u[J-1].alpha*this.globalAlpha,S=[],l=0;for(;l<J;l++){var T=u[l];S.push(T.offset*q+
|
31 |
+
o+" "+T.color)}a.push('<g_vml_:fill type="',m.type_,'"',' method="none" focus="100%"',' color="',da,'"',' color2="',ea,'"',' colors="',S.join(","),'"',' opacity="',ga,'"',' g_o_:opacity2="',fa,'"',' angle="',r,'"',' focusposition="',n.x,",",n.y,'" />')}else a.push('<g_vml_:fill color="',d,'" opacity="',f,'" />');else{var K=this.lineScale_*this.lineWidth;if(K<1)f*=K;a.push("<g_vml_:stroke",' opacity="',f,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',aa(this.lineCap),
|
32 |
+
'"',' weight="',K,'px"',' color="',d,'" />')}a.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",a.join(""))};i.fill=function(){this.stroke(true)};i.closePath=function(){this.currentPath_.push({type:"close"})};i.getCoords_=function(b,a){var c=this.m_;return{x:k*(b*c[0][0]+a*c[1][0]+c[2][0])-v,y:k*(b*c[0][1]+a*c[1][1]+c[2][1])-v}};i.save=function(){var b={};O(this,b);this.aStack_.push(b);this.mStack_.push(this.m_);this.m_=y(I(),this.m_)};i.restore=function(){O(this.aStack_.pop(),
|
33 |
+
this);this.m_=this.mStack_.pop()};function ha(b){var a=0;for(;a<3;a++){var c=0;for(;c<2;c++)if(!isFinite(b[a][c])||isNaN(b[a][c]))return false}return true}function A(b,a,c){if(!!ha(a)){b.m_=a;if(c)b.lineScale_=W(V(a[0][0]*a[1][1]-a[0][1]*a[1][0]))}}i.translate=function(b,a){A(this,y([[1,0,0],[0,1,0],[b,a,1]],this.m_),false)};i.rotate=function(b){var a=G(b),c=F(b);A(this,y([[a,c,0],[-c,a,0],[0,0,1]],this.m_),false)};i.scale=function(b,a){this.arcScaleX_*=b;this.arcScaleY_*=a;A(this,y([[b,0,0],[0,a,
|
34 |
+
0],[0,0,1]],this.m_),true)};i.transform=function(b,a,c,d,f,h){A(this,y([[b,a,0],[c,d,0],[f,h,1]],this.m_),true)};i.setTransform=function(b,a,c,d,f,h){A(this,[[b,a,0],[c,d,0],[f,h,1]],true)};i.clip=function(){};i.arcTo=function(){};i.createPattern=function(){return new U};function D(b){this.type_=b;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}D.prototype.addColorStop=function(b,a){a=P(a);this.colors_.push({offset:b,color:a.color,alpha:a.alpha})};function U(){}G_vmlCanvasManager=
|
35 |
+
M;CanvasRenderingContext2D=H;CanvasGradient=D;CanvasPattern=U})();
|
js/mageho/sortproducts/loading.gif
ADDED
Binary file
|
js/mageho/sortproducts/opentip.css
ADDED
@@ -0,0 +1,460 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
** http://www.opentip.org
|
3 |
+
** See opentip.js for the license.
|
4 |
+
**
|
5 |
+
** One word about the different states when showing / hiding opentips.
|
6 |
+
**
|
7 |
+
** An opentip starts with the .ot-completely-hidden class.
|
8 |
+
** When shown, it changes to .ot-becoming-visible, then to .ot-visible (depending
|
9 |
+
** on the length of the transition effect).
|
10 |
+
** When hidden, it changes to .ot-hidden, and then to .ot-completely-hidden (again:
|
11 |
+
** depending on the length of the transition effect).
|
12 |
+
**/
|
13 |
+
.ot-container {
|
14 |
+
position: absolute;
|
15 |
+
max-width: 300px;
|
16 |
+
z-index: 100;
|
17 |
+
}
|
18 |
+
/**
|
19 |
+
* Only using the position transition on fixed opentips, so the tip only moves
|
20 |
+
* smoothly when it changes position due to browser viewport changes.
|
21 |
+
*/
|
22 |
+
.ot-container.ot-fixed {
|
23 |
+
-webkit-transition-property: left, top;
|
24 |
+
-webkit-transition-duration: 0.2s, 0.2s;
|
25 |
+
-moz-transition-property: left, top;
|
26 |
+
-moz-transition-duration: 0.2s, 0.2s;
|
27 |
+
}
|
28 |
+
.ot-container.ot-completely-hidden {
|
29 |
+
display: none;
|
30 |
+
}
|
31 |
+
.opentip {
|
32 |
+
position: relative;
|
33 |
+
font-size: 13px;
|
34 |
+
line-height: 120%;
|
35 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
36 |
+
-moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
37 |
+
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
38 |
+
}
|
39 |
+
.opentip .title { font-weight: bold; }
|
40 |
+
.opentip .content { width: auto !important;}
|
41 |
+
|
42 |
+
|
43 |
+
.opentip .loadingIndication {
|
44 |
+
display: none;
|
45 |
+
padding: 10px 15px;
|
46 |
+
background: url("loading.gif") center center no-repeat;
|
47 |
+
width: 25px;
|
48 |
+
height: 15px;
|
49 |
+
}
|
50 |
+
.opentip .loadingIndication span { display: none; }
|
51 |
+
.ot-loading .opentip .loadingIndication { display: block; }
|
52 |
+
.ot-loading .opentip .content { display: none; }
|
53 |
+
|
54 |
+
.ot-buttons {
|
55 |
+
position: absolute;
|
56 |
+
right: 0;
|
57 |
+
top: 0;
|
58 |
+
}
|
59 |
+
|
60 |
+
.ot-buttons .close {
|
61 |
+
display: block;
|
62 |
+
width: 15px;
|
63 |
+
height: 15px;
|
64 |
+
display: block;
|
65 |
+
text-decoration: none;
|
66 |
+
}
|
67 |
+
.ot-buttons .close .canvas {
|
68 |
+
position: relative;
|
69 |
+
display: block;
|
70 |
+
color: white; /* Read by JS and applied to canvas */
|
71 |
+
background-color: rgba(0, 0, 0, 0.2); /* Read by JS and applied to canvas */
|
72 |
+
}
|
73 |
+
|
74 |
+
.ot-container .stem-container {
|
75 |
+
position: absolute;
|
76 |
+
width: 0;
|
77 |
+
height: 0;
|
78 |
+
}
|
79 |
+
.ot-container .stem {
|
80 |
+
position: absolute;
|
81 |
+
overflow: hidden;
|
82 |
+
color: #cccccc; /* JS will read this property to draw the stem in the right color. */
|
83 |
+
/* background: rgba(255, 0, 0, 0.5);*/
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
.ot-container .left { left: 0; }
|
88 |
+
.ot-container .center { left: 50%; }
|
89 |
+
.ot-container .right { right: 0; }
|
90 |
+
.ot-container .top { top: 0; }
|
91 |
+
.ot-container .middle { top: 50%; }
|
92 |
+
.ot-container .bottom { bottom: 0; }
|
93 |
+
|
94 |
+
|
95 |
+
|
96 |
+
/**
|
97 |
+
|
98 |
+
Styles
|
99 |
+
======
|
100 |
+
|
101 |
+
Those are the different styles available in opentip.
|
102 |
+
|
103 |
+
**/
|
104 |
+
|
105 |
+
.style-standard .opentip {
|
106 |
+
border: 1px solid #f2e37b;
|
107 |
+
background-color: #fff18f;
|
108 |
+
color: black;
|
109 |
+
padding: 6px 10px;
|
110 |
+
box-shadow: 2px 2px 7px rgba(0, 0, 0, 0.1);
|
111 |
+
-moz-box-shadow: 2px 2px 7px rgba(0, 0, 0, 0.1);
|
112 |
+
-webkit-box-shadow: 2px 2px 7px rgba(0, 0, 0, 0.1);
|
113 |
+
}
|
114 |
+
.style-standard .opentip .title {
|
115 |
+
margin-bottom: 1px;
|
116 |
+
}
|
117 |
+
.style-standard .stem {
|
118 |
+
color: #e3ca1b; /* JS will read this property to draw the stem in the right color. */
|
119 |
+
}
|
120 |
+
.style-standard .ot-buttons {
|
121 |
+
top: -6px;
|
122 |
+
right: -6px;
|
123 |
+
}
|
124 |
+
.style-standard .ot-buttons .close {
|
125 |
+
width: 21px;
|
126 |
+
height: 21px;
|
127 |
+
}
|
128 |
+
.style-standard .ot-buttons .close .canvas {
|
129 |
+
background-color: rgba(255, 241, 143, 0.5);
|
130 |
+
color: #a2932B;
|
131 |
+
}
|
132 |
+
|
133 |
+
|
134 |
+
|
135 |
+
|
136 |
+
.style-rounded .opentip {
|
137 |
+
border: 7px solid #81b4da;
|
138 |
+
background-color: #f9fbfc;
|
139 |
+
color: #3f5d73;
|
140 |
+
border-radius: 10px;
|
141 |
+
-moz-border-radius: 10px;
|
142 |
+
-webkit-border-radius: 10px;
|
143 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
|
144 |
+
-moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
|
145 |
+
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
|
146 |
+
}
|
147 |
+
.style-rounded .opentip .title {
|
148 |
+
background: #81b4da;
|
149 |
+
color: #f7fafd;
|
150 |
+
padding: 0px 10px 4px 10px;
|
151 |
+
}
|
152 |
+
.style-rounded .opentip .content {
|
153 |
+
padding: 6px 10px;
|
154 |
+
}
|
155 |
+
.style-rounded .stem {
|
156 |
+
color: #c3ddf0;
|
157 |
+
}
|
158 |
+
.style-rounded .ot-buttons {
|
159 |
+
top: -3px;
|
160 |
+
right: -3px;
|
161 |
+
}
|
162 |
+
.style-rounded .ot-buttons .close {
|
163 |
+
width: 21px;
|
164 |
+
height: 21px;
|
165 |
+
}
|
166 |
+
.style-rounded .ot-buttons .close .canvas {
|
167 |
+
background-color: #81B4DA;
|
168 |
+
}
|
169 |
+
|
170 |
+
.style-slick .opentip {
|
171 |
+
border: 1px solid #eeeeee;
|
172 |
+
background: #f7f7f7;
|
173 |
+
border-radius: 3px;
|
174 |
+
-moz-border-radius: 3px;
|
175 |
+
-webkit-border-radius: 3px;
|
176 |
+
}
|
177 |
+
.style-slick .opentip .title {
|
178 |
+
/* color: #49677e !important; */
|
179 |
+
color:#fff !important;
|
180 |
+
padding: 5px 10px 3px 10px !important;
|
181 |
+
border-bottom: 1px solid #eeeeee !important;
|
182 |
+
}
|
183 |
+
.style-slick .opentip .content {
|
184 |
+
padding: 6px 10px;
|
185 |
+
border-top: 1px solid #fefefe;
|
186 |
+
}
|
187 |
+
.style-slick .stem {
|
188 |
+
color: #cccccc;
|
189 |
+
}
|
190 |
+
.style-slick .ot-buttons {
|
191 |
+
right: -7px;
|
192 |
+
top: -5px;
|
193 |
+
}
|
194 |
+
.style-slick .ot-buttons .close {
|
195 |
+
height: 19px;
|
196 |
+
width: 19px;
|
197 |
+
}
|
198 |
+
.style-slick .ot-buttons .close .canvas {
|
199 |
+
background-color: rgba(0, 0, 0, 0.2);
|
200 |
+
}
|
201 |
+
|
202 |
+
|
203 |
+
.style-glass .opentip {
|
204 |
+
background: white;
|
205 |
+
background: rgba(255, 255, 255, 0.9);
|
206 |
+
border-radius: 5px;
|
207 |
+
-moz-border-radius: 5px;
|
208 |
+
-webkit-border-radius: 5px;
|
209 |
+
box-shadow: 0 0 15px rgba(51, 113, 136, 0.5);
|
210 |
+
-moz-box-shadow: 0 0 15px rgba(51, 113, 136, 0.5);
|
211 |
+
-webkit-box-shadow: 0 0 15px rgba(51, 113, 136, 0.5);
|
212 |
+
padding: 20px 30px;
|
213 |
+
}
|
214 |
+
.style-glass .opentip .title {
|
215 |
+
color: #316F89;
|
216 |
+
font-family: serif;
|
217 |
+
font-style: italic;
|
218 |
+
margin: 0 0 20px 0;
|
219 |
+
font-size: 16px;
|
220 |
+
}
|
221 |
+
.style-glass .opentip .content {
|
222 |
+
color: #333333;
|
223 |
+
}
|
224 |
+
.style-glass .stem {
|
225 |
+
color: #ffffff;
|
226 |
+
}
|
227 |
+
.style-glass .ot-buttons {
|
228 |
+
right: -3px;
|
229 |
+
top: -3px;
|
230 |
+
}
|
231 |
+
.style-glass .ot-buttons .close {
|
232 |
+
width: 25px;
|
233 |
+
height: 25px;
|
234 |
+
}
|
235 |
+
.style-glass .ot-buttons .close .canvas {
|
236 |
+
background-color: #F7BA00;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
|
241 |
+
IE 6 HACKS
|
242 |
+
==========
|
243 |
+
|
244 |
+
**/
|
245 |
+
|
246 |
+
/*\*/
|
247 |
+
.ot-buttons {
|
248 |
+
z-index: 110;
|
249 |
+
}
|
250 |
+
.opentip {
|
251 |
+
z-index: 110;
|
252 |
+
}
|
253 |
+
.opentipIFrame {
|
254 |
+
position: absolute;
|
255 |
+
top: 0;
|
256 |
+
left: 0;
|
257 |
+
border: none;
|
258 |
+
background: none;
|
259 |
+
margin: 0;
|
260 |
+
padding: 0;
|
261 |
+
display:none;
|
262 |
+
/*sorry for IE5*/ display/**/:block;/*sorry for IE5*/
|
263 |
+
z-index:-1;/*must have*/
|
264 |
+
filter:mask();/*must have*/
|
265 |
+
}
|
266 |
+
|
267 |
+
.style-glass .opentip {
|
268 |
+
border: 1px solid #bbbbbb;
|
269 |
+
}
|
270 |
+
/**/
|
271 |
+
|
272 |
+
|
273 |
+
|
274 |
+
|
275 |
+
/**
|
276 |
+
|
277 |
+
CSS3 Transitions
|
278 |
+
================
|
279 |
+
|
280 |
+
The definitions that follow here, are only meant for browsers that support css3
|
281 |
+
transitions.
|
282 |
+
|
283 |
+
So the syntax I'm going to use, is really meant for more modern browsers than
|
284 |
+
IE6.
|
285 |
+
|
286 |
+
|
287 |
+
|
288 |
+
To define a show effect, you have to define the position you want to come from
|
289 |
+
as the .ot-completely-hidden property (in combination with your
|
290 |
+
.ot-show-effectName).
|
291 |
+
|
292 |
+
To define a hide effect, you do the same, but for .ot-hidden (in combination
|
293 |
+
with your .ot-show-effectName).
|
294 |
+
|
295 |
+
**/
|
296 |
+
|
297 |
+
|
298 |
+
.ot-container.ot-css3 {
|
299 |
+
-webkit-transition-duration: 1s; /* Well be reset by JS */
|
300 |
+
-webkit-transition-property: opacity, -webkit-transform;
|
301 |
+
-moz-transition-duration: 1s; /* Well be reset by JS */
|
302 |
+
-moz-transition-property: opacity, -moz-transform;
|
303 |
+
-o-transition-duration: 1s; /* Well be reset by JS */
|
304 |
+
-o-transition-property: opacity, -o-transform;
|
305 |
+
|
306 |
+
opacity: 1;
|
307 |
+
}
|
308 |
+
|
309 |
+
.ot-container.ot-css3.ot-completely-hidden {
|
310 |
+
display: none;
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
|
315 |
+
|
316 |
+
|
317 |
+
/** Appear / Fade**/
|
318 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-appear,
|
319 |
+
.ot-container.ot-css3.ot-hidden.ot-hide-fade {
|
320 |
+
opacity: 0;
|
321 |
+
}
|
322 |
+
|
323 |
+
|
324 |
+
|
325 |
+
/** Grow / Shrink **/
|
326 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-grow,
|
327 |
+
.ot-container.ot-css3.ot-hidden.ot-hide-shrink {
|
328 |
+
-webkit-transform: scale(0);
|
329 |
+
-moz-transform: scale(0);
|
330 |
+
-o-transform: scale(0);
|
331 |
+
}
|
332 |
+
|
333 |
+
|
334 |
+
|
335 |
+
/** Blind/Slide down / Blind up**/
|
336 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-blindDown,
|
337 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-slideDown,
|
338 |
+
.ot-container.ot-css3.ot-hidden.ot-hide-blindUp {
|
339 |
+
-webkit-transform: scaleY(0);
|
340 |
+
-moz-transform: scaleY(0);
|
341 |
+
-o-transform: scaleY(0);
|
342 |
+
opacity: 0;
|
343 |
+
}
|
344 |
+
|
345 |
+
|
346 |
+
/** Condense / Puff **/
|
347 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-condense,
|
348 |
+
.ot-container.ot-css3.ot-hidden.ot-hide-puff {
|
349 |
+
-webkit-transform: scale(5);
|
350 |
+
-moz-transform: scale(5);
|
351 |
+
-o-transform: scale(5);
|
352 |
+
opacity: 0;
|
353 |
+
}
|
354 |
+
|
355 |
+
/** Rotate **/
|
356 |
+
.ot-container.ot-css3.ot-becoming-visible.ot-show-rotate {
|
357 |
+
-webkit-transform: scale(3) rotate(-500deg);
|
358 |
+
-moz-transform: scale(3) rotate(-500deg);
|
359 |
+
-o-transform: scale(3) rotate(-500deg);
|
360 |
+
opacity: 0;
|
361 |
+
}
|
362 |
+
.ot-container.ot-css3.ot-hidden.ot-hide-rotate {
|
363 |
+
-webkit-transform: scale(3) rotate(500deg);
|
364 |
+
-moz-transform: scale(3) rotate(500deg);
|
365 |
+
-o-transform: scale(3) rotate(500deg);
|
366 |
+
opacity: 0;
|
367 |
+
}
|
368 |
+
|
369 |
+
|
370 |
+
|
371 |
+
|
372 |
+
|
373 |
+
|
374 |
+
|
375 |
+
|
376 |
+
|
377 |
+
|
378 |
+
|
379 |
+
|
380 |
+
/**
|
381 |
+
|
382 |
+
Content design
|
383 |
+
==============
|
384 |
+
|
385 |
+
Nicer input fields, etc...
|
386 |
+
|
387 |
+
*/
|
388 |
+
|
389 |
+
|
390 |
+
.opentip label {
|
391 |
+
margin-bottom: 3px;
|
392 |
+
margin-top: 10px;
|
393 |
+
display: block;
|
394 |
+
}
|
395 |
+
.opentip input, .opentip textarea {
|
396 |
+
padding: 5px 6px;
|
397 |
+
border: 1px solid rgba(100, 100, 100, 0.2);
|
398 |
+
background: rgba(255,255,255,0.5);
|
399 |
+
display: block;
|
400 |
+
width: 100%;
|
401 |
+
margin: 3px 0 10px 0;
|
402 |
+
-moz-border-radius: 2px;
|
403 |
+
-webkit-border-radius: 2px;
|
404 |
+
-moz-box-sizing: border-box;
|
405 |
+
-webkit-box-sizing: border-box;
|
406 |
+
}
|
407 |
+
.opentip input:focus, .opentip textarea:focus {
|
408 |
+
border-color: rgba(100, 100, 100, 0.2);
|
409 |
+
-moz-box-shadow: 0 0 10px rgba(0,0,0,0.2);
|
410 |
+
-webkit-box-shadow: 0 0 10px rgba(0,0,0,0.2);
|
411 |
+
}
|
412 |
+
|
413 |
+
.opentip button {
|
414 |
+
margin-top: 20px;
|
415 |
+
display: block;
|
416 |
+
-moz-box-sizing: border-box;
|
417 |
+
-webkit-box-sizing: border-box;
|
418 |
+
box-sizing: border-box;
|
419 |
+
width: 100%;
|
420 |
+
|
421 |
+
|
422 |
+
border: 1px solid rgba(247, 186, 0, 0.8);
|
423 |
+
background: rgba(247, 186, 0, 0.9);
|
424 |
+
font-size: 14px;
|
425 |
+
line-height: 14px;
|
426 |
+
padding: 10px 10px;
|
427 |
+
position: relative;
|
428 |
+
color: rgba(255,255,255, 1);
|
429 |
+
text-shadow: 0 0 10px rgba(255,255,255,0.3);
|
430 |
+
text-align: center;
|
431 |
+
font-weight: bold;
|
432 |
+
font-family: serif;
|
433 |
+
font-style: italic;
|
434 |
+
text-decoration: none;
|
435 |
+
margin: 20px 0 0 0;
|
436 |
+
cursor: pointer;
|
437 |
+
-moz-border-radius: 2px;
|
438 |
+
-webkit-border-radius: 2px;
|
439 |
+
-moz-box-shadow: 0 0 4px rgba(0,0,0,0.2),
|
440 |
+
0 -2px 10px rgba(255, 255, 255, 0.4) inset;
|
441 |
+
-webkit-box-shadow: 0 0 4px rgba(0,0,0,0.2),
|
442 |
+
0 -2px 10px rgba(255, 255, 255, 0.4) inset;
|
443 |
+
}
|
444 |
+
.opentip button {
|
445 |
+
padding: 8px 6px;
|
446 |
+
}
|
447 |
+
.button:hover, button:hover {
|
448 |
+
-moz-box-shadow: 0 0 6px rgba(247, 192, 25, 1),
|
449 |
+
0 -2px 10px rgba(255, 255, 255, 0.6) inset;
|
450 |
+
text-shadow: 0 0 4px rgba(255,255,255,1);
|
451 |
+
}
|
452 |
+
|
453 |
+
|
454 |
+
|
455 |
+
/** IE 6 HACKS **/
|
456 |
+
/*\*/
|
457 |
+
.opentip input, .opentip textarea, .opentip button {
|
458 |
+
width: 200px;
|
459 |
+
}
|
460 |
+
/**/
|
js/mageho/sortproducts/opentip.js
ADDED
@@ -0,0 +1,1285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
** More info at http://www.opentip.org
|
3 |
+
**
|
4 |
+
** Copyright (c) 2009, Matias Meno
|
5 |
+
** Graphics by Tjandra Mayerhold
|
6 |
+
**
|
7 |
+
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 |
+
** of this software and associated documentation files (the "Software"), to deal
|
9 |
+
** in the Software without restriction, including without limitation the rights
|
10 |
+
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 |
+
** copies of the Software, and to permit persons to whom the Software is
|
12 |
+
** furnished to do so, subject to the following conditions:
|
13 |
+
**
|
14 |
+
** The above copyright notice and this permission notice shall be included in
|
15 |
+
** all copies or substantial portions of the Software.
|
16 |
+
**
|
17 |
+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 |
+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 |
+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20 |
+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 |
+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 |
+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 |
+
** THE SOFTWARE.
|
24 |
+
**
|
25 |
+
**/
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
** Usage:
|
30 |
+
**
|
31 |
+
** <div onmouseover="javascript:Tips.add(this, event, 'Content', { options });"></div>
|
32 |
+
**
|
33 |
+
** or externally:
|
34 |
+
**
|
35 |
+
** $('elementId').addTip('Content', { options });
|
36 |
+
**
|
37 |
+
** For a full documentation, please visit http://www.opentip.org/documentation
|
38 |
+
**/
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Namespace and helper functions for opentips.
|
44 |
+
*/
|
45 |
+
var Opentip = {
|
46 |
+
|
47 |
+
Version: '1.4.4',
|
48 |
+
REQUIRED_PROTOTYPE_VERSION: '1.6.0',
|
49 |
+
REQUIRED_SCRIPTACULOUS_VERSION: '1.8.0',
|
50 |
+
STICKS_OUT_TOP: 1,
|
51 |
+
STICKS_OUT_BOTTOM: 2,
|
52 |
+
STICKS_OUT_LEFT: 1,
|
53 |
+
STICKS_OUT_RIGHT: 2,
|
54 |
+
cached: {},
|
55 |
+
debugging: false,
|
56 |
+
load: function() {
|
57 |
+
function getComparableVersion(version) {var v = version.split('.');return parseInt(v[0])*100000 + parseInt(v[1])*1000 + parseInt(v[2]);}
|
58 |
+
if((typeof Prototype === 'undefined') || (typeof Element === 'undefined') || (typeof Element.Methods === 'undefined') || (getComparableVersion(Prototype.Version) < getComparableVersion(Opentip.REQUIRED_PROTOTYPE_VERSION))) {throw("Opentip requires the Prototype JavaScript framework >= " + Opentip.REQUIRED_PROTOTYPE_VERSION);}
|
59 |
+
|
60 |
+
Opentip.useCss3Transitions = Opentip.supports('transition');
|
61 |
+
Opentip.useScriptaculousTransitions = ! Opentip.useCss3Transitions;
|
62 |
+
|
63 |
+
if (Opentip.useCss3Transitions) Opentip.debug('Using CSS3 transitions.');
|
64 |
+
|
65 |
+
if((typeof Scriptaculous === 'undefined') || (typeof Effect === 'undefined') || (getComparableVersion(Scriptaculous.Version) < getComparableVersion(Opentip.REQUIRED_SCRIPTACULOUS_VERSION))) {
|
66 |
+
Opentip.debug('No scriptaculous available. Disabling scriptaculous transitions.');
|
67 |
+
Opentip.useScriptaculousTransitions = false;
|
68 |
+
}
|
69 |
+
},
|
70 |
+
debug: function() {if (this.debugging && typeof console !== 'undefined' && typeof console.debug !== 'undefined') console.debug.apply(console, arguments);},
|
71 |
+
IEVersion: function() {
|
72 |
+
if (typeof Opentip.cached.IEVersion !== 'undefined') return Opentip.cached.IEVersion;
|
73 |
+
if (Prototype.Browser.IE) {
|
74 |
+
var version = navigator.userAgent.match('MSIE ([\\d.]+)');
|
75 |
+
var IEVersion = version ? (parseFloat(version[1])) : false;
|
76 |
+
}
|
77 |
+
else IEVersion = false;
|
78 |
+
Opentip.cached.IEVersion = IEVersion;
|
79 |
+
return IEVersion;
|
80 |
+
},
|
81 |
+
objectIsEvent: function(obj) {
|
82 |
+
// There must be a better way of doing this.
|
83 |
+
return (typeof(obj) == 'object' && obj.type && obj.screenX);
|
84 |
+
},
|
85 |
+
useIFrame: function() {return Opentip.IEVersion() ? (Opentip.IEVersion() <= 6) : false;},
|
86 |
+
lastTipId: 1,
|
87 |
+
lastZIndex: 100,
|
88 |
+
documentIsLoaded: false,
|
89 |
+
postponeCreation: function(createFunction) {
|
90 |
+
if (Opentip.documentIsLoaded || !Opentip.IEVersion()) createFunction();
|
91 |
+
else {
|
92 |
+
Event.observe(window, 'load', createFunction); // Sorry IE users but... well: get another browser!
|
93 |
+
}
|
94 |
+
},
|
95 |
+
|
96 |
+
// Mimics scriptaculous Builder.node behaviour
|
97 |
+
element: function(tagName, attributes, children) {
|
98 |
+
if (Object.isArray(attributes) || Object.isString(attributes) || Object.isElement(attributes)) {
|
99 |
+
children = attributes;
|
100 |
+
attributes = null;
|
101 |
+
}
|
102 |
+
|
103 |
+
var element = new Element(tagName, attributes || {});
|
104 |
+
|
105 |
+
// This is a prototype 1.6 bug, that doesn't apply the className to IE8 elements.
|
106 |
+
// Thanks to Alexander Shakhnovsky for finding the bug, and pinpointing the problem.
|
107 |
+
if(attributes && attributes['className']) {
|
108 |
+
attributes['className'].split(' ').each(function(class_name){element.addClassName(class_name);});
|
109 |
+
}
|
110 |
+
|
111 |
+
if (children) {
|
112 |
+
if (Object.isArray(children)) {
|
113 |
+
children.each(function(child) {
|
114 |
+
element.insert({bottom: child});
|
115 |
+
});
|
116 |
+
}
|
117 |
+
else {
|
118 |
+
element.insert({bottom: children});
|
119 |
+
}
|
120 |
+
}
|
121 |
+
return element;
|
122 |
+
},
|
123 |
+
|
124 |
+
// In the future every position attribute will go through this method.
|
125 |
+
sanitizePosition: function(arrayPosition) {
|
126 |
+
var position;
|
127 |
+
if (Object.isArray(arrayPosition)) {
|
128 |
+
var positionString = '';
|
129 |
+
if (arrayPosition[0] == 'center') {
|
130 |
+
positionString = arrayPosition[1];
|
131 |
+
}
|
132 |
+
else if (arrayPosition[1] == 'middle') {
|
133 |
+
positionString = arrayPosition[0];
|
134 |
+
}
|
135 |
+
else {
|
136 |
+
positionString = arrayPosition[1] + arrayPosition[0].capitalize();
|
137 |
+
}
|
138 |
+
if (Opentip.position[positionString] === undefined) throw 'Unknown position: ' + positionString;
|
139 |
+
position = Opentip.position[positionString];
|
140 |
+
}
|
141 |
+
else if (Object.isString(arrayPosition)) {
|
142 |
+
if (Opentip.position[arrayPosition] === undefined) throw 'Unknown position: ' + arrayPosition;
|
143 |
+
position = Opentip.position[arrayPosition];
|
144 |
+
}
|
145 |
+
return parseInt(position);
|
146 |
+
},
|
147 |
+
|
148 |
+
|
149 |
+
/* Browser support testing */
|
150 |
+
vendors: 'Khtml Ms O Moz Webkit'.split(' '),
|
151 |
+
testDiv: document.createElement('div'),
|
152 |
+
supports: function(prop) {
|
153 |
+
if ( prop in Opentip.testDiv.style ) return true;
|
154 |
+
|
155 |
+
prop = prop.ot_ucfirst();
|
156 |
+
|
157 |
+
return Opentip.vendors.any(function(vendor) {
|
158 |
+
return vendor + prop in Opentip.testDiv.style;
|
159 |
+
});
|
160 |
+
}
|
161 |
+
};
|
162 |
+
|
163 |
+
String.prototype.ot_ucfirst = function() {
|
164 |
+
return this.replace(/^\w/, function(val) {return val.toUpperCase();});
|
165 |
+
};
|
166 |
+
|
167 |
+
Opentip.load();
|
168 |
+
|
169 |
+
|
170 |
+
|
171 |
+
|
172 |
+
|
173 |
+
/**
|
174 |
+
* The standard style.
|
175 |
+
*/
|
176 |
+
|
177 |
+
Opentip.styles = {
|
178 |
+
standard: {
|
179 |
+
// This style contains all default values for other styles.
|
180 |
+
// POSITION : [ 'left|right|center', 'top|bottom|middle' ]
|
181 |
+
// COORDINATE : [ XVALUE, YVALUE ] (integers)
|
182 |
+
title: null,
|
183 |
+
className: 'standard', // The class name to be used in the stylesheet
|
184 |
+
stem: false, // false (no stem) || true (stem at tipJoint position) || POSITION (for stems in other directions)
|
185 |
+
delay: null, // float (in seconds - if null, the default is used: 0.2 for mouseover, 0 for click)
|
186 |
+
hideDelay: 0.1, // --
|
187 |
+
fixed: false, // If target is not null, elements are always fixed.
|
188 |
+
showOn: 'mouseover', // string (the observe string of the trigger element, eg: click, mouseover, etc..) || 'creation' (the tooltip will show when being created) || null if you want to handle it yourself.
|
189 |
+
hideTrigger: 'trigger', // 'trigger' | 'tip' | 'target' | 'closeButton' | ELEMENT | ELEMENT_ID || array containing any of the previous
|
190 |
+
hideOn: null, // string (event eg: click) || array of event strings if multiple hideTriggers || null (let Opentip decide)
|
191 |
+
offset: [ 0, 0 ], // COORDINATE
|
192 |
+
containInViewport: true, // Whether the targetJoint/tipJoint should be changed if the tooltip is not in the viewport anymore.
|
193 |
+
autoOffset: true, // If set to true, offsets are calculated automatically to position the tooltip. (pixels are added if there are stems for example)
|
194 |
+
showEffect: 'appear', // scriptaculous or CSS3 (in opentip.css) effect
|
195 |
+
fallbackShowEffect: 'appear', // At tip creation, this effect will override the showEffect, if useScriptaculousTransitions == true, and the showEffect does not exist.
|
196 |
+
hideEffect: 'fade',
|
197 |
+
fallbackHideEffect: 'appear',
|
198 |
+
showEffectDuration: 0.3,
|
199 |
+
hideEffectDuration: 0.2,
|
200 |
+
stemSize: 8, // integer
|
201 |
+
tipJoint: [ 'left', 'top' ], // POSITION
|
202 |
+
target: null, // null (no target, opentip uses mouse as target) || true (target is the triggerElement) || elementId|element (for another element)
|
203 |
+
targetJoint: null, // POSITION (Ignored if target == null) || null (targetJoint is the opposite of tipJoint)
|
204 |
+
ajax: false, // Ajax options. eg: { url: 'yourUrl.html', options: { ajaxOptions... } } or { options: { ajaxOptions } /* This will use the href of the A element the tooltip is attached to */ }
|
205 |
+
group: null, // You can group opentips together. So when a tooltip shows, it looks if there are others in the same group, and hides them.
|
206 |
+
escapeHtml: false,
|
207 |
+
style: null
|
208 |
+
},
|
209 |
+
slick: {
|
210 |
+
className: 'slick',
|
211 |
+
stem: true
|
212 |
+
},
|
213 |
+
rounded: {
|
214 |
+
className: 'rounded',
|
215 |
+
stem: true
|
216 |
+
},
|
217 |
+
glass: {
|
218 |
+
className: 'glass'
|
219 |
+
}
|
220 |
+
};
|
221 |
+
Opentip.defaultStyle = 'standard'; // Change this to the style name you want your tooltips to have.
|
222 |
+
|
223 |
+
|
224 |
+
|
225 |
+
Opentip.position = {
|
226 |
+
top: 0,
|
227 |
+
topRight: 1,
|
228 |
+
right: 2,
|
229 |
+
bottomRight: 3,
|
230 |
+
bottom: 4,
|
231 |
+
bottomLeft: 5,
|
232 |
+
left: 6,
|
233 |
+
topLeft: 7
|
234 |
+
};
|
235 |
+
|
236 |
+
|
237 |
+
|
238 |
+
/**
|
239 |
+
* On document load
|
240 |
+
*/
|
241 |
+
Event.observe(window, Opentip.IEVersion() ? 'load' : 'dom:loaded', function() {
|
242 |
+
Opentip.documentIsLoaded = true;
|
243 |
+
|
244 |
+
|
245 |
+
var htmlOptionNames = [];
|
246 |
+
for (var i in Opentip.styles.standard) {
|
247 |
+
htmlOptionNames.push(i.underscore().dasherize());
|
248 |
+
}
|
249 |
+
|
250 |
+
// Go through all elements, and look for elements that have inline element
|
251 |
+
// opentip definitions.
|
252 |
+
$$('[data-ot]').each(function(element) {
|
253 |
+
var options = {};
|
254 |
+
element = $(element);
|
255 |
+
|
256 |
+
var content = element.readAttribute('data-ot');
|
257 |
+
|
258 |
+
if (content === '' || content === 'true' || content === 'yes') {
|
259 |
+
content = element.readAttribute('title');
|
260 |
+
element.title = '';
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
content || (content = '');
|
265 |
+
|
266 |
+
htmlOptionNames.each(function(optionName) {
|
267 |
+
var optionValue;
|
268 |
+
if (optionValue = element.readAttribute('data-ot-' + optionName)) {
|
269 |
+
try {
|
270 |
+
// See if it's a JSON string.
|
271 |
+
optionValue = optionValue.gsub("'", '"').evalJSON();
|
272 |
+
}
|
273 |
+
catch (err) {
|
274 |
+
// Well, it's not.
|
275 |
+
}
|
276 |
+
|
277 |
+
options[optionName.camelize()] = optionValue;
|
278 |
+
}
|
279 |
+
});
|
280 |
+
|
281 |
+
element.addTip(content, options);
|
282 |
+
});
|
283 |
+
});
|
284 |
+
|
285 |
+
|
286 |
+
|
287 |
+
|
288 |
+
|
289 |
+
|
290 |
+
var Tips = {
|
291 |
+
list: [],
|
292 |
+
append: function(tip) {this.list.push(tip);},
|
293 |
+
remove: function(element) {
|
294 |
+
if (!element.element) var tip = this.list.find(function(t) {return t.triggerElement === element});
|
295 |
+
else var tip = this.list.find(function(t) {return t === element});
|
296 |
+
if (tip) {
|
297 |
+
tip.deactivate();
|
298 |
+
tip.destroyAllElements();
|
299 |
+
this.list = this.list.without(tip);
|
300 |
+
}
|
301 |
+
},
|
302 |
+
add: function(element) {
|
303 |
+
if (element._opentipAddedTips) {
|
304 |
+
/* TODO: Now it just returns the first found... try to find the correct one. */
|
305 |
+
var tip = this.list.find(function(t) {return (t.triggerElement === element);});
|
306 |
+
if (tip.options.showOn == 'creation') tip.show();
|
307 |
+
tip.debug('Using an existing opentip.');
|
308 |
+
return;
|
309 |
+
} else setTimeout(function() {element._opentipAddedTips = true;}, 1); // I added a timeout, so that tooltips, defined in an onmouseover or onclick event, will show.
|
310 |
+
|
311 |
+
Opentip.debug('Creating new opentip');
|
312 |
+
|
313 |
+
var tipArguments = [];
|
314 |
+
|
315 |
+
$A(arguments).each(function(arg, idx) {
|
316 |
+
if (idx == 1 && !Opentip.objectIsEvent(arg)) tipArguments.push(null);
|
317 |
+
tipArguments.push(arg);
|
318 |
+
});
|
319 |
+
|
320 |
+
|
321 |
+
// Creating the tooltip object, but not yet activating it, or creating the container elements.
|
322 |
+
var tooltip = new TipClass(tipArguments[0], tipArguments[1], tipArguments[2], tipArguments[3], tipArguments[4]);
|
323 |
+
|
324 |
+
this.append(tooltip);
|
325 |
+
|
326 |
+
var self = this;
|
327 |
+
var createTip = function() {
|
328 |
+
tooltip.create(tipArguments[1]); // Passing the event.
|
329 |
+
}
|
330 |
+
|
331 |
+
Opentip.postponeCreation(createTip);
|
332 |
+
|
333 |
+
return tooltip;
|
334 |
+
},
|
335 |
+
hideGroup: function(groupName) {
|
336 |
+
this.list.findAll(function(t) {return (t.options.group == groupName);}).invoke('doHide');
|
337 |
+
},
|
338 |
+
abortShowingGroup: function(groupName) {
|
339 |
+
this.list.findAll(function(t) {return (t.options.group == groupName);}).invoke('abortShowing');
|
340 |
+
}
|
341 |
+
};
|
342 |
+
|
343 |
+
var Tip = function() { return Tips.add.apply(Tips, arguments); };
|
344 |
+
|
345 |
+
Element.addMethods({
|
346 |
+
addTip: function(element) {
|
347 |
+
element = $(element);
|
348 |
+
Tips.add.apply(Tips, arguments);
|
349 |
+
return element;
|
350 |
+
},
|
351 |
+
setCss3Style: function(element) {
|
352 |
+
element = $(element);
|
353 |
+
var style = {};
|
354 |
+
for (var propertyName in arguments[1]) {
|
355 |
+
var css3PropertyName = propertyName.ot_ucfirst();
|
356 |
+
var css3PropertyValue = arguments[1][propertyName];
|
357 |
+
Opentip.vendors.each(function(vendor) {
|
358 |
+
style[vendor + css3PropertyName] = css3PropertyValue;
|
359 |
+
element.setStyle(style);
|
360 |
+
});
|
361 |
+
}
|
362 |
+
return element;
|
363 |
+
}
|
364 |
+
});
|
365 |
+
|
366 |
+
|
367 |
+
var TipClass = Class.create({
|
368 |
+
debug: function() {
|
369 |
+
var newArguments = Array.from(arguments);
|
370 |
+
newArguments.unshift('ID:', this.id, '|');
|
371 |
+
Opentip.debug.apply(Opentip, newArguments);
|
372 |
+
},
|
373 |
+
initialize: function(element, evt) {
|
374 |
+
this.id = Opentip.lastTipId ++;
|
375 |
+
|
376 |
+
element = $(element);
|
377 |
+
|
378 |
+
this.triggerElement = element;
|
379 |
+
|
380 |
+
this.loaded = false; // for ajax
|
381 |
+
this.loading = false; // for ajax
|
382 |
+
|
383 |
+
this.visible = false;
|
384 |
+
this.waitingToShow = false;
|
385 |
+
this.waitingToHide = false;
|
386 |
+
|
387 |
+
this.lastPosition = {left: 0, top: 0};
|
388 |
+
this.dimensions = [ 100, 50 ]; // Just some initial values.
|
389 |
+
|
390 |
+
var options = {};
|
391 |
+
this.content = '';
|
392 |
+
|
393 |
+
if (typeof(arguments[2]) == 'object') {options = Object.clone(arguments[2]);}
|
394 |
+
else if (typeof(arguments[3]) == 'object') {this.setContent(arguments[2]);options = Object.clone(arguments[3]);}
|
395 |
+
else if (typeof(arguments[4]) == 'object') {this.setContent(arguments[2]);options = Object.clone(arguments[4]);options.title = arguments[3];}
|
396 |
+
else {
|
397 |
+
if (Object.isString(arguments[2]) || Object.isFunction(arguments[2])) this.setContent(arguments[2]);
|
398 |
+
if (Object.isString(arguments[3])) options.title = arguments[3];
|
399 |
+
}
|
400 |
+
|
401 |
+
// Use the type of the html event (eg: onclick="") if called in an event.
|
402 |
+
if (!options.showOn && evt) options.showOn = evt.type;
|
403 |
+
|
404 |
+
// If the url of an Ajax request is not set, get it from the link it's attached to.
|
405 |
+
if (options.ajax && !options.ajax.url) {
|
406 |
+
if (this.triggerElement.tagName.toLowerCase() == 'a') {
|
407 |
+
if (typeof(options.ajax) != 'object') options.ajax = { };
|
408 |
+
options.ajax.url = this.triggerElement.href;
|
409 |
+
} else {options.ajax = false;}
|
410 |
+
}
|
411 |
+
|
412 |
+
// If the event is 'click', no point in following a link
|
413 |
+
if (options.showOn == 'click' && this.triggerElement.tagName.toLowerCase() == 'a') {if (evt) {evt.stop();}this.triggerElement.observe('click', function(e) {e.stop();});}
|
414 |
+
|
415 |
+
|
416 |
+
options.style || (options.style = Opentip.defaultStyle);
|
417 |
+
|
418 |
+
var styleOptions = Object.extend({ }, Opentip.styles.standard); // Copy all standard options.
|
419 |
+
if (options.style != 'standard') Object.extend(styleOptions, Opentip.styles[options.style]);
|
420 |
+
|
421 |
+
options = Object.extend(styleOptions, options);
|
422 |
+
|
423 |
+
|
424 |
+
options.target && (options.fixed = true);
|
425 |
+
|
426 |
+
|
427 |
+
if (options.stem === true) options.stem = options.tipJoint;
|
428 |
+
if (options.target === true) options.target = this.triggerElement;
|
429 |
+
else if (options.target) options.target = $(options.target);
|
430 |
+
|
431 |
+
|
432 |
+
this.currentStemPosition = options.stem;
|
433 |
+
|
434 |
+
|
435 |
+
if (options.delay === null) {
|
436 |
+
if (options.showOn == 'mouseover') options.delay = 0.2;
|
437 |
+
else options.delay = 0
|
438 |
+
}
|
439 |
+
|
440 |
+
if (Opentip.useScriptaculousTransitions) {
|
441 |
+
if (options.showEffect && ! Effect[options.showEffect.ot_ucfirst()]) {
|
442 |
+
this.debug('Using fallback show effect "' + options.fallbackShowEffect + '" instead of "' + options.showEffect + '"');
|
443 |
+
options.showEffect = options.fallbackShowEffect;
|
444 |
+
}
|
445 |
+
if (options.hideEffect && ! Effect[options.hideEffect.ot_ucfirst()]) {
|
446 |
+
this.debug('Using fallback hide effect "' + options.fallbackHideEffect + '" instead of "' + options.hideEffect + '"');
|
447 |
+
options.hideEffect = options.fallbackHideEffect;
|
448 |
+
}
|
449 |
+
}
|
450 |
+
|
451 |
+
if (options.targetJoint == null) {
|
452 |
+
options.targetJoint = [];
|
453 |
+
options.targetJoint[0] = options.tipJoint[0] == 'left' ? 'right' : (options.tipJoint[0] == 'right' ? 'left' : 'center');
|
454 |
+
options.targetJoint[1] = options.tipJoint[1] == 'top' ? 'bottom' : (options.tipJoint[1] == 'bottom' ? 'top' : 'middle');
|
455 |
+
}
|
456 |
+
|
457 |
+
this.options = options;
|
458 |
+
|
459 |
+
this.options.showTriggerElementsWhenHidden = [];
|
460 |
+
|
461 |
+
if (this.options.showOn && this.options.showOn != 'creation') {
|
462 |
+
this.options.showTriggerElementsWhenHidden.push({element: this.triggerElement, event: this.options.showOn});
|
463 |
+
}
|
464 |
+
|
465 |
+
this.options.showTriggerElementsWhenVisible = [];
|
466 |
+
|
467 |
+
|
468 |
+
this.options.hideTriggerElements = [];
|
469 |
+
},
|
470 |
+
/**
|
471 |
+
* This builds the container, and sets the correct hide trigger.
|
472 |
+
* Since it's a problem for IE to create elements when the page is not fully
|
473 |
+
* loaded, this function has to be posponed until the website is fully loaded.
|
474 |
+
*
|
475 |
+
* This function also activates the tooltip.
|
476 |
+
**/
|
477 |
+
create: function(evt) {
|
478 |
+
this.buildContainer();
|
479 |
+
|
480 |
+
if (this.options.hideTrigger) {
|
481 |
+
var hideOnEvent = null;
|
482 |
+
var hideTriggerElement = null;
|
483 |
+
|
484 |
+
if (!(this.options.hideTrigger instanceof Array)) {
|
485 |
+
this.options.hideTrigger = [this.options.hideTrigger];
|
486 |
+
}
|
487 |
+
|
488 |
+
this.options.hideTrigger.each(function(hideTrigger, i) {
|
489 |
+
|
490 |
+
var hideOnOption = (this.options.hideOn instanceof Array) ? this.options.hideOn[i] : this.options.hideOn;
|
491 |
+
|
492 |
+
switch (hideTrigger) {
|
493 |
+
case 'trigger':
|
494 |
+
hideOnEvent = hideOnOption ? hideOnOption : 'mouseout';
|
495 |
+
hideTriggerElement = this.triggerElement;
|
496 |
+
break;
|
497 |
+
case 'tip':
|
498 |
+
hideOnEvent = hideOnOption ? hideOnOption : 'mouseover';
|
499 |
+
hideTriggerElement = this.container;
|
500 |
+
break;
|
501 |
+
case 'target':
|
502 |
+
hideOnEvent = hideOnOption ? hideOnOption : 'mouseover';
|
503 |
+
hideTriggerElement = this.options.target;
|
504 |
+
break;
|
505 |
+
case 'closeButton':break;
|
506 |
+
default:
|
507 |
+
hideOnEvent = hideOnOption ? hideOnOption : 'mouseover';
|
508 |
+
hideTriggerElement = $(hideTrigger);
|
509 |
+
break;
|
510 |
+
}
|
511 |
+
if (hideTriggerElement) {
|
512 |
+
this.options.hideTriggerElements.push({element: hideTriggerElement, event: hideOnEvent});
|
513 |
+
if (hideOnEvent == 'mouseout') {
|
514 |
+
// When the hide trigger is mouseout, we have to attach a mouseover trigger to that element, so the tooltip doesn't disappear when
|
515 |
+
// hovering child elements. (Hovering children fires a mouseout mouseover event)
|
516 |
+
this.options.showTriggerElementsWhenVisible.push({element: hideTriggerElement, event: 'mouseover'});
|
517 |
+
}
|
518 |
+
}
|
519 |
+
}.bind(this));
|
520 |
+
}
|
521 |
+
|
522 |
+
this.activate();
|
523 |
+
|
524 |
+
if (evt || this.options.showOn == 'creation') this.show(evt);
|
525 |
+
},
|
526 |
+
activate: function() {
|
527 |
+
this.bound = {};
|
528 |
+
this.bound.doShow = this.doShow.bindAsEventListener(this);
|
529 |
+
this.bound.show = this.show.bindAsEventListener(this);
|
530 |
+
this.bound.doHide = this.doHide.bindAsEventListener(this);
|
531 |
+
this.bound.hide = this.hide.bindAsEventListener(this);
|
532 |
+
this.bound.position = this.position.bindAsEventListener(this);
|
533 |
+
|
534 |
+
if (this.options.showEffect || this.options.hideEffect) this.queue = {limit: 1, position: 'end', scope: this.container.identify()};
|
535 |
+
|
536 |
+
// The order is important here! Do not reverse.
|
537 |
+
this.setupObserversForReallyHiddenTip();
|
538 |
+
this.setupObserversForHiddenTip();
|
539 |
+
},
|
540 |
+
deactivate: function() {
|
541 |
+
this.debug('Deactivating tooltip.');
|
542 |
+
this.doHide();
|
543 |
+
this.setupObserversForReallyHiddenTip();
|
544 |
+
},
|
545 |
+
buildContainer: function() {
|
546 |
+
this.container = $(Opentip.element('div', {className: 'ot-container ot-completely-hidden style-' + this.options.className + (this.options.ajax ? ' ot-loading' : '') + (this.options.fixed ? ' ot-fixed' : '')}));
|
547 |
+
if (Opentip.useCss3Transitions) {
|
548 |
+
this.container.setCss3Style({'transitionDuration': '0s'}); // To make sure the initial state doesn't fade
|
549 |
+
|
550 |
+
this.container.addClassName('ot-css3');
|
551 |
+
if (this.options.showEffect) {
|
552 |
+
this.container.addClassName('ot-show-' + this.options.showEffect);
|
553 |
+
}
|
554 |
+
if (this.options.hideEffect) {
|
555 |
+
this.container.addClassName('ot-hide-' + this.options.hideEffect);
|
556 |
+
}
|
557 |
+
}
|
558 |
+
if (Opentip.useScriptaculousTransitions) this.container.setStyle({display: 'none'});
|
559 |
+
},
|
560 |
+
buildElements: function() {
|
561 |
+
var stemCanvas;
|
562 |
+
var closeButtonCanvas;
|
563 |
+
if (this.options.stem) {
|
564 |
+
var stemOffset = '-' + this.options.stemSize + 'px';
|
565 |
+
this.container.appendChild(Opentip.element('div', {className: 'stem-container ' + this.options.stem[0] + ' ' + this.options.stem[1]}, stemCanvas = Opentip.element('canvas', {className: 'stem'})));
|
566 |
+
}
|
567 |
+
var self = this;
|
568 |
+
var content = [];
|
569 |
+
var headerContent = [];
|
570 |
+
if (this.options.title) headerContent.push(Opentip.element('div', {className: 'title'}, this.options.title));
|
571 |
+
|
572 |
+
content.push(Opentip.element('div', {className: 'header'}, headerContent));
|
573 |
+
content.push($(Opentip.element('div', {className: 'content'}))); // Will be updated by updateElementContent()
|
574 |
+
if (this.options.ajax) {content.push($(Opentip.element('div', {className: 'loadingIndication'}, Opentip.element('span', 'Loading...'))));}
|
575 |
+
this.tooltipElement = $(Opentip.element('div', {className: 'opentip'}, content));
|
576 |
+
|
577 |
+
this.container.appendChild(this.tooltipElement);
|
578 |
+
|
579 |
+
var buttons = this.container.appendChild(Opentip.element('div', {className: 'ot-buttons'}));
|
580 |
+
var drawCloseButton = false;
|
581 |
+
if (this.options.hideTrigger && this.options.hideTrigger.include('closeButton')) {
|
582 |
+
buttons.appendChild(Opentip.element('a', {href: 'javascript:undefined', className: 'close'}, closeButtonCanvas = Opentip.element('canvas', { className: 'canvas' })));
|
583 |
+
// The canvas has to have a className assigned, because IE < 9 doesn't know the element, and won't assign any css to it.
|
584 |
+
drawCloseButton = true;
|
585 |
+
}
|
586 |
+
|
587 |
+
if (Opentip.useIFrame()) this.iFrameElement = this.container.appendChild($(Opentip.element('iframe', {className: 'opentipIFrame', src: 'javascript:false;'})).setStyle({display: 'none', zIndex: 100}).setOpacity(0));
|
588 |
+
|
589 |
+
document.body.appendChild(this.container);
|
590 |
+
|
591 |
+
if (typeof G_vmlCanvasManager !== "undefined") {
|
592 |
+
if (stemCanvas) G_vmlCanvasManager.initElement(stemCanvas);
|
593 |
+
if (closeButtonCanvas) G_vmlCanvasManager.initElement(closeButtonCanvas);
|
594 |
+
}
|
595 |
+
|
596 |
+
if (drawCloseButton) this.drawCloseButton();
|
597 |
+
},
|
598 |
+
drawCloseButton: function() {
|
599 |
+
var canvasElement = this.container.down('.ot-buttons canvas');
|
600 |
+
var containerElement = this.container.down('.ot-buttons .close');
|
601 |
+
var size = parseInt(containerElement.getStyle('width')) || 20; // Opera 10 has a bug here.. it seems to never get the width right.
|
602 |
+
|
603 |
+
var crossColor = canvasElement.getStyle('color');
|
604 |
+
if ( ! crossColor || crossColor == 'transparent') crossColor = 'white';
|
605 |
+
|
606 |
+
var backgroundColor = canvasElement.getStyle('backgroundColor');
|
607 |
+
if ( ! backgroundColor || backgroundColor == 'transparent') backgroundColor = 'rgba(0, 0, 0, 0.2)';
|
608 |
+
canvasElement.setStyle({backgroundColor: 'transparent'});
|
609 |
+
|
610 |
+
canvasElement.width = size;
|
611 |
+
canvasElement.height = size;
|
612 |
+
|
613 |
+
var ctx = canvasElement.getContext('2d');
|
614 |
+
|
615 |
+
ctx.clearRect (0, 0, size, size);
|
616 |
+
|
617 |
+
ctx.beginPath();
|
618 |
+
|
619 |
+
var padding = size / 2.95;
|
620 |
+
ctx.fillStyle = backgroundColor;
|
621 |
+
ctx.lineWidth = size / 5.26;
|
622 |
+
ctx.strokeStyle = crossColor;
|
623 |
+
ctx.lineCap = 'round';
|
624 |
+
|
625 |
+
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2, false);
|
626 |
+
ctx.fill();
|
627 |
+
|
628 |
+
ctx.beginPath();
|
629 |
+
ctx.moveTo(padding, padding);
|
630 |
+
ctx.lineTo(size - padding, size - padding);
|
631 |
+
ctx.stroke();
|
632 |
+
|
633 |
+
ctx.beginPath();
|
634 |
+
ctx.moveTo(size - padding, padding);
|
635 |
+
ctx.lineTo(padding, size - padding);
|
636 |
+
ctx.stroke();
|
637 |
+
|
638 |
+
},
|
639 |
+
/**
|
640 |
+
* Sets the content of the tooltip.
|
641 |
+
* This can be a function or a string. The function will be executed, and the
|
642 |
+
* result used as new content of the tooltip.
|
643 |
+
*
|
644 |
+
* If the tooltip is visible, this function calls updateElementContent()
|
645 |
+
**/
|
646 |
+
setContent: function(content) {
|
647 |
+
this.content = content;
|
648 |
+
if (this.visible) this.updateElementContent();
|
649 |
+
},
|
650 |
+
/**
|
651 |
+
* Actually updates the html element with the content.
|
652 |
+
* This function also evaluates the content function, if content is a function.
|
653 |
+
**/
|
654 |
+
updateElementContent: function() {
|
655 |
+
var contentDiv = this.container.down('.content');
|
656 |
+
if (contentDiv) {
|
657 |
+
|
658 |
+
if (Object.isFunction(this.content)) {
|
659 |
+
this.debug('Executing content function.');
|
660 |
+
this.content = this.content(this);
|
661 |
+
}
|
662 |
+
|
663 |
+
contentDiv.update(this.options.escapeHtml ? this.content.escapeHTML() : this.content);
|
664 |
+
}
|
665 |
+
this.storeAndFixDimensions();
|
666 |
+
},
|
667 |
+
storeAndFixDimensions: function() {
|
668 |
+
this.container.setStyle({width: 'auto', left: '0px', top: '0px'});
|
669 |
+
this.dimensions = this.container.getDimensions();
|
670 |
+
this.container.setStyle({width: this.dimensions.width + 'px', left: this.lastPosition.left + 'px', top: this.lastPosition.top + 'px'});
|
671 |
+
},
|
672 |
+
destroyAllElements: function() {if (this.container) this.container.remove();},
|
673 |
+
clearShowTimeout: function() {window.clearTimeout(this.timeoutId);},
|
674 |
+
clearHideTimeout: function() {window.clearTimeout(this.hideTimeoutId);},
|
675 |
+
clearTimeouts: function() {
|
676 |
+
window.clearTimeout(this.visibilityStateTimeoutId);
|
677 |
+
this.clearShowTimeout();
|
678 |
+
this.clearHideTimeout();
|
679 |
+
},
|
680 |
+
/** Gets called only when doShow() is called, not when show() is called **/
|
681 |
+
setupObserversForReallyVisibleTip: function() {
|
682 |
+
this.options.showTriggerElementsWhenVisible.each(function(pair) {$(pair.element).observe(pair.event, this.bound.show);}, this);
|
683 |
+
},
|
684 |
+
/** Gets only called when show() is called. show() might not really result in showing the tooltip, because there may
|
685 |
+
be another trigger that calls hide() directly after. **/
|
686 |
+
setupObserversForVisibleTip: function() {
|
687 |
+
this.options.hideTriggerElements.each(function(pair) {$(pair.element).observe(pair.event, this.bound.hide);}, this);
|
688 |
+
this.options.showTriggerElementsWhenHidden.each(function(pair) {$(pair.element).stopObserving(pair.event, this.bound.show);}, this);
|
689 |
+
Event.observe(document.onresize ? document : window, "resize", this.bound.position);
|
690 |
+
Event.observe(window, "scroll", this.bound.position);
|
691 |
+
},
|
692 |
+
/** Gets called only when doHide() is called. */
|
693 |
+
setupObserversForReallyHiddenTip: function() {
|
694 |
+
this.options.showTriggerElementsWhenVisible.each(function(pair) {$(pair.element).stopObserving(pair.event, this.bound.show);}, this);
|
695 |
+
},
|
696 |
+
/** Gets called everytime hide() is called. See setupObserversForVisibleTip for more info **/
|
697 |
+
setupObserversForHiddenTip: function() {
|
698 |
+
this.options.showTriggerElementsWhenHidden.each(function(pair) {$(pair.element).observe(pair.event, this.bound.show);}, this);
|
699 |
+
this.options.hideTriggerElements.each(function(pair) {$(pair.element).stopObserving(pair.event, this.bound.hide);}, this);
|
700 |
+
Event.stopObserving(document.onresize ? document : window, "resize", this.bound.position);
|
701 |
+
Event.stopObserving(window, "scroll", this.bound.position);
|
702 |
+
},
|
703 |
+
/**
|
704 |
+
* The show function only schedules the tooltip to show. (If there is a delay, this function will generate the timer)
|
705 |
+
* The actual function to show the tooltip is doShow().
|
706 |
+
**/
|
707 |
+
show: function(evt) {
|
708 |
+
this.abortHiding();
|
709 |
+
if (this.visible) return;
|
710 |
+
|
711 |
+
this.debug('Showing in ' + this.options.delay + 's.');
|
712 |
+
|
713 |
+
if (this.options.group) Tips.abortShowingGroup(this.options.group);
|
714 |
+
|
715 |
+
this.waitingToShow = true;
|
716 |
+
|
717 |
+
// Even though it is not yet visible, I already attach the observers, so the tooltip won't show if a hideEvent is triggered.
|
718 |
+
this.setupObserversForVisibleTip();
|
719 |
+
|
720 |
+
// So the tooltip is positioned as soon as it shows.
|
721 |
+
this.followMousePosition();
|
722 |
+
this.position(evt);
|
723 |
+
|
724 |
+
if (!this.options.delay) this.bound.doShow(evt);
|
725 |
+
else this.timeoutId = this.bound.doShow.delay(this.options.delay);
|
726 |
+
},
|
727 |
+
// If the tip is waiting to show (and only then), this will abort it.
|
728 |
+
abortShowing: function() {
|
729 |
+
if (this.waitingToShow) {
|
730 |
+
this.debug('Aborting showing.');
|
731 |
+
this.clearTimeouts();
|
732 |
+
this.stopFollowingMousePosition();
|
733 |
+
this.waitingToShow = false;
|
734 |
+
this.setupObserversForHiddenTip();
|
735 |
+
}
|
736 |
+
},
|
737 |
+
/**
|
738 |
+
* Actually shows the tooltip. This function is called when any possible delay has expired.
|
739 |
+
**/
|
740 |
+
doShow: function() {
|
741 |
+
this.clearTimeouts();
|
742 |
+
if (this.visible) return;
|
743 |
+
|
744 |
+
// Thanks to Torsten Saam for this enhancement.
|
745 |
+
if ( ! this.triggerElementExists()) { this.deactivate(); return; }
|
746 |
+
|
747 |
+
this.debug('Showing!');
|
748 |
+
|
749 |
+
if (this.options.group) Tips.hideGroup(this.options.group);
|
750 |
+
|
751 |
+
|
752 |
+
this.visible = true;
|
753 |
+
this.waitingToShow = false;
|
754 |
+
|
755 |
+
if (!this.tooltipElement) this.buildElements();
|
756 |
+
this.updateElementContent();
|
757 |
+
|
758 |
+
if (this.options.ajax && !this.loaded) {this.loadAjax();}
|
759 |
+
|
760 |
+
this.searchAndActivateHideButtons();
|
761 |
+
|
762 |
+
this.ensureElement();
|
763 |
+
this.container.setStyle({zIndex: Opentip.lastZIndex += 1});
|
764 |
+
|
765 |
+
// The order is important here! Do not reverse.
|
766 |
+
this.setupObserversForReallyVisibleTip();
|
767 |
+
this.setupObserversForVisibleTip();
|
768 |
+
|
769 |
+
if (Opentip.useScriptaculousTransitions) {
|
770 |
+
if (this.options.showEffect || this.options.hideEffect) this.cancelEffects();
|
771 |
+
|
772 |
+
if (!this.options.showEffect || !this.container[this.options.showEffect]) this.container.show();
|
773 |
+
else this.container[this.options.showEffect]({duration: this.options.showEffectDuration, queue: this.queue, afterFinish: this.afterShowEffect.bind(this)});
|
774 |
+
if (Opentip.useIFrame()) this.iFrameElement.show();
|
775 |
+
}
|
776 |
+
|
777 |
+
this.position();
|
778 |
+
|
779 |
+
this.container.removeClassName('ot-hidden').addClassName('ot-becoming-visible');
|
780 |
+
|
781 |
+
|
782 |
+
/**
|
783 |
+
* The next lines may seem a bit weird. I ran into some bizarre opera problems
|
784 |
+
* while implementing the switch of the different states.
|
785 |
+
*
|
786 |
+
* This is what's happening here:
|
787 |
+
*
|
788 |
+
* I wanted to just remove ot-completely-hidden, and add ot-becoming-visible
|
789 |
+
* (so the tip has the style it should have when it appears) and then switch
|
790 |
+
* ot-becoming-visible with ot-visible so the transition can take place.
|
791 |
+
* I then setup a timer to set ot-completely-visible when appropriate.
|
792 |
+
*
|
793 |
+
* I ran into problems with opera, which showed the tip for a frame because
|
794 |
+
* apparently the -o-transforms are slower then just setting display: none
|
795 |
+
* (or something...)
|
796 |
+
*
|
797 |
+
* So I have to 1) set ot-becoming-visible first, so the tip has the appropriate
|
798 |
+
* CSS definitions set, 2) defer the removal of ot-completely-hidden, so it's
|
799 |
+
* not invisible anymore, and 3) defer the rest of the process (setting ot-visible
|
800 |
+
* and stuff) so the transition takes place.
|
801 |
+
*/
|
802 |
+
|
803 |
+
var startShowEffect = function() {
|
804 |
+
if (Opentip.useCss3Transitions) {
|
805 |
+
this.container.setCss3Style({'transitionDuration': this.options.showEffectDuration + 's'});
|
806 |
+
}
|
807 |
+
|
808 |
+
this.container.removeClassName('ot-becoming-visible').addClassName('ot-visible');
|
809 |
+
if (this.options.showEffect && this.options.showEffectDuration) {
|
810 |
+
this.visibilityStateTimeoutId = (function() {this.removeClassName('ot-visible').addClassName('ot-completely-visible');}).bind(this.container).delay(this.options.showEffectDuration);
|
811 |
+
}
|
812 |
+
else {
|
813 |
+
this.container.removeClassName('ot-visible').addClassName('ot-completely-visible');
|
814 |
+
}
|
815 |
+
|
816 |
+
this.activateFirstInput();
|
817 |
+
};
|
818 |
+
|
819 |
+
|
820 |
+
(function() {
|
821 |
+
this.container.removeClassName('ot-completely-hidden');
|
822 |
+
(startShowEffect).bind(this).defer(); // Has to be deferred, so the div has the class ot-becoming-visible.
|
823 |
+
}).bind(this).defer();
|
824 |
+
|
825 |
+
|
826 |
+
|
827 |
+
},
|
828 |
+
loadAjax: function() {
|
829 |
+
if (this.loading) return;
|
830 |
+
this.loading = true;
|
831 |
+
this.container.addClassName('ot-loading');
|
832 |
+
|
833 |
+
this.debug('Loading content from ' + this.options.ajax.url + '.');
|
834 |
+
|
835 |
+
new Ajax.Request(this.options.ajax.url,
|
836 |
+
Object.extend({
|
837 |
+
onComplete: function() {
|
838 |
+
this.container.removeClassName('ot-loading');
|
839 |
+
this.loaded = true;
|
840 |
+
this.loading = false;
|
841 |
+
this.updateElementContent();
|
842 |
+
this.searchAndActivateHideButtons();
|
843 |
+
this.activateFirstInput();
|
844 |
+
this.position();
|
845 |
+
}.bind(this),
|
846 |
+
onSuccess: function(transport) {
|
847 |
+
this.debug('Loading successfull.');
|
848 |
+
this.content = transport.responseText;
|
849 |
+
}.bind(this),
|
850 |
+
onFailure: function() {
|
851 |
+
this.debug('There was a problem downloading the file.');
|
852 |
+
this.options.escapeHtml = false;
|
853 |
+
this.content = '<a class="close">There was a problem downloading the content.</a>';
|
854 |
+
}.bind(this)}, this.options.ajax.options || {}));
|
855 |
+
},
|
856 |
+
afterShowEffect: function() {
|
857 |
+
this.activateFirstInput();
|
858 |
+
this.position();
|
859 |
+
},
|
860 |
+
activateFirstInput: function() {
|
861 |
+
// TODO: check if there is a simple way of finding EITHER an input OR a textarea.
|
862 |
+
var input = this.container.down('input');
|
863 |
+
var textarea = this.container.down('textarea');
|
864 |
+
if (input) {input.focus();}
|
865 |
+
else if (textarea) textarea.focus();
|
866 |
+
},
|
867 |
+
searchAndActivateHideButtons: function() {
|
868 |
+
if (!this.options.hideTrigger || this.options.hideTrigger.include('closeButton')) {
|
869 |
+
this.options.hideTriggerElements = [];
|
870 |
+
this.container.select('.close').each(function(el) {
|
871 |
+
this.options.hideTriggerElements.push({element: el, event: 'click'});
|
872 |
+
}, this);
|
873 |
+
if (this.visible) this.setupObserversForVisibleTip();
|
874 |
+
}
|
875 |
+
},
|
876 |
+
hide: function(afterFinish) {
|
877 |
+
this.abortShowing();
|
878 |
+
if (!this.visible) return;
|
879 |
+
|
880 |
+
this.debug('Hiding in ' + this.options.hideDelay + 's.');
|
881 |
+
|
882 |
+
this.waitingToHide = true;
|
883 |
+
|
884 |
+
// We start observing even though it is not yet hidden, so the tooltip does not disappear when a showEvent is triggered.
|
885 |
+
this.setupObserversForHiddenTip();
|
886 |
+
|
887 |
+
this.hideTimeoutId = this.bound.doHide.delay(this.options.hideDelay, afterFinish); // hide has to be delayed because when hovering children a mouseout is registered.
|
888 |
+
},
|
889 |
+
abortHiding: function() {
|
890 |
+
if (this.waitingToHide) {
|
891 |
+
this.debug('Aborting hiding.');
|
892 |
+
this.clearTimeouts();
|
893 |
+
this.waitingToHide = false;
|
894 |
+
this.setupObserversForVisibleTip();
|
895 |
+
}
|
896 |
+
},
|
897 |
+
doHide: function(afterFinish) {
|
898 |
+
this.clearTimeouts();
|
899 |
+
if (!this.visible) return;
|
900 |
+
|
901 |
+
this.debug('Hiding!');
|
902 |
+
|
903 |
+
this.visible = false;
|
904 |
+
|
905 |
+
this.waitingToHide = false;
|
906 |
+
|
907 |
+
this.deactivateElementEnsurance();
|
908 |
+
|
909 |
+
// The order is important here! Do not reverse.
|
910 |
+
this.setupObserversForReallyHiddenTip();
|
911 |
+
this.setupObserversForHiddenTip();
|
912 |
+
|
913 |
+
if (!this.options.fixed) this.stopFollowingMousePosition();
|
914 |
+
|
915 |
+
if (Opentip.useScriptaculousTransitions) {
|
916 |
+
if (this.options.showEffect || this.options.hideEffect) this.cancelEffects();
|
917 |
+
|
918 |
+
if (!this.options.hideEffect || !this.container[this.options.hideEffect]) this.container.hide();
|
919 |
+
else {
|
920 |
+
var effectOptions = {duration: this.options.hideEffectDuration, queue: this.queue};
|
921 |
+
if(afterFinish && Object.isFunction(afterFinish)) effectOptions.afterFinish = afterFinish;
|
922 |
+
this.container[this.options.hideEffect](effectOptions);
|
923 |
+
}
|
924 |
+
if (Opentip.useIFrame()) this.iFrameElement.hide();
|
925 |
+
}
|
926 |
+
|
927 |
+
if (Opentip.useCss3Transitions) {
|
928 |
+
this.container.setCss3Style({'transitionDuration': this.options.hideEffectDuration + 's'});
|
929 |
+
}
|
930 |
+
|
931 |
+
this.container.removeClassName('ot-visible').removeClassName('ot-completely-visible').addClassName('ot-hidden');
|
932 |
+
if (this.options.hideEffect && this.options.hideEffectDuration) {
|
933 |
+
this.visibilityStateTimeoutId = (function() {
|
934 |
+
this.setCss3Style({'transitionDuration': '0s'});
|
935 |
+
this.removeClassName('ot-hidden').addClassName('ot-completely-hidden');
|
936 |
+
}).bind(this.container).delay(this.options.showEffectDuration);
|
937 |
+
}
|
938 |
+
else {
|
939 |
+
this.container.removeClassName('ot-hidden').addClassName('ot-completely-hidden');
|
940 |
+
}
|
941 |
+
|
942 |
+
},
|
943 |
+
cancelEffects: function() {Effect.Queues.get(this.queue.scope).invoke('cancel');},
|
944 |
+
followMousePosition: function() {if (!this.options.fixed) $(document.body).observe('mousemove', this.bound.position);},
|
945 |
+
stopFollowingMousePosition: function() {if (!this.options.fixed) $(document.body).stopObserving('mousemove', this.bound.position);},
|
946 |
+
positionsEqual: function(position1, position2) {
|
947 |
+
return (position1.left == position2.left && position1.top == position2.top);
|
948 |
+
},
|
949 |
+
position: function(evt) {
|
950 |
+
var evt = evt || this.lastEvt;
|
951 |
+
|
952 |
+
this.currentStemPosition = this.options.stem; // This gets reset by ensureViewportContainment if necessary.
|
953 |
+
var position = this.ensureViewportContainment(evt, this.getPosition(evt));
|
954 |
+
if (this.positionsEqual(position, this.lastPosition)) {
|
955 |
+
this.positionStem();
|
956 |
+
return;
|
957 |
+
}
|
958 |
+
|
959 |
+
this.lastPosition = position;
|
960 |
+
if (position) {
|
961 |
+
var style = {'left': position.left + 'px', 'top': position.top + 'px'};
|
962 |
+
this.container.setStyle(style);
|
963 |
+
if (Opentip.useIFrame() && this.iFrameElement) {
|
964 |
+
this.iFrameElement.setStyle({width: this.container.getWidth() + 'px', height: this.container.getHeight() + 'px'});
|
965 |
+
}
|
966 |
+
|
967 |
+
/**
|
968 |
+
* Following is a redraw fix, because I noticed some drawing errors in some browsers when tooltips where overlapping.
|
969 |
+
*/
|
970 |
+
var container = this.container;
|
971 |
+
(function() {
|
972 |
+
container.style.visibility = "hidden"; // I chose visibility instead of display so that I don't interfere with appear/disappear effects.
|
973 |
+
var redrawFix = container.offsetHeight;
|
974 |
+
container.style.visibility = "visible";
|
975 |
+
}).defer();
|
976 |
+
}
|
977 |
+
this.positionStem();
|
978 |
+
},
|
979 |
+
getPosition: function(evt, tipJ, trgJ, stem) {
|
980 |
+
var tipJ = tipJ || this.options.tipJoint;
|
981 |
+
var trgJ = trgJ || this.options.targetJoint;
|
982 |
+
|
983 |
+
var position = {};
|
984 |
+
|
985 |
+
if (this.options.target) {
|
986 |
+
var tmp = this.options.target.cumulativeOffset();
|
987 |
+
position.left = tmp[0];
|
988 |
+
position.top = tmp[1];
|
989 |
+
if (trgJ[0] == 'right') {
|
990 |
+
// For wrapping inline elements, left + width does not give the right border, because left is where
|
991 |
+
// the element started, not its most left position.
|
992 |
+
if (typeof this.options.target.getBoundingClientRect != 'undefined') {
|
993 |
+
position.left = this.options.target.getBoundingClientRect().right + $(document.viewport).getScrollOffsets().left;
|
994 |
+
}
|
995 |
+
else {
|
996 |
+
position.left = position.left + this.options.target.getWidth();
|
997 |
+
}
|
998 |
+
}
|
999 |
+
else if (trgJ[0] == 'center') {position.left += Math.round(this.options.target.getWidth() / 2);}
|
1000 |
+
if (trgJ[1] == 'bottom') {position.top += this.options.target.getHeight();}
|
1001 |
+
else if (trgJ[1] == 'middle') {position.top += Math.round(this.options.target.getHeight() / 2);}
|
1002 |
+
} else {
|
1003 |
+
if (!evt) return; // No event passed, so returning.
|
1004 |
+
this.lastEvt = evt;
|
1005 |
+
position.left = Event.pointerX(evt);
|
1006 |
+
position.top = Event.pointerY(evt);
|
1007 |
+
}
|
1008 |
+
|
1009 |
+
if (this.options.autoOffset) {
|
1010 |
+
var stemSize = this.options.stem ? this.options.stemSize : 0;
|
1011 |
+
var offsetDistance = (stemSize && this.options.fixed) ? 2 : 10; // If there is as stem offsets dont need to be that big if fixed.
|
1012 |
+
var additionalHorizontal = (tipJ[1] == 'middle' && !this.options.fixed) ? 15 : 0;
|
1013 |
+
var additionalVertical = (tipJ[0] == 'center' && !this.options.fixed) ? 15 : 0;
|
1014 |
+
if (tipJ[0] == 'right') position.left -= offsetDistance + additionalHorizontal;
|
1015 |
+
else if (tipJ[0] == 'left') position.left += offsetDistance + additionalHorizontal;
|
1016 |
+
if (tipJ[1] == 'bottom') position.top -= offsetDistance + additionalVertical;
|
1017 |
+
else if (tipJ[1] == 'top') position.top += offsetDistance + additionalVertical;
|
1018 |
+
|
1019 |
+
if (stemSize) {
|
1020 |
+
var stem = stem || this.options.stem;
|
1021 |
+
if (stem[0] == 'right') position.left -= stemSize;
|
1022 |
+
else if (stem[0] == 'left') position.left += stemSize;
|
1023 |
+
if (stem[1] == 'bottom') position.top -= stemSize;
|
1024 |
+
else if (stem[1] == 'top') position.top += stemSize;
|
1025 |
+
}
|
1026 |
+
}
|
1027 |
+
position.left += this.options.offset[0];
|
1028 |
+
position.top += this.options.offset[1];
|
1029 |
+
|
1030 |
+
if (tipJ[0] == 'right') {position.left -= this.container.getWidth();}
|
1031 |
+
if (tipJ[0] == 'center') {position.left -= Math.round(this.container.getWidth()/2);}
|
1032 |
+
if (tipJ[1] == 'bottom') {position.top -= this.container.getHeight();}
|
1033 |
+
if (tipJ[1] == 'middle') {position.top -= Math.round(this.container.getHeight()/2);}
|
1034 |
+
|
1035 |
+
return position;
|
1036 |
+
},
|
1037 |
+
ensureViewportContainment: function(evt, position) {
|
1038 |
+
// Sometimes the element is theoretically visible, but an effect is not yet showing it.
|
1039 |
+
// So the calculation of the offsets is incorrect sometimes, which results in faulty repositioning.
|
1040 |
+
if (!this.visible) return position;
|
1041 |
+
|
1042 |
+
var sticksOut = [ this.sticksOutX(position), this.sticksOutY(position) ];
|
1043 |
+
if (!sticksOut[0] && !sticksOut[1]) return position;
|
1044 |
+
|
1045 |
+
var tipJ = this.options.tipJoint.clone();
|
1046 |
+
var trgJ = this.options.targetJoint.clone();
|
1047 |
+
|
1048 |
+
var viewportScrollOffset = $(document.viewport).getScrollOffsets();
|
1049 |
+
var dimensions = this.dimensions;
|
1050 |
+
var viewportOffset = {left: position.left - viewportScrollOffset.left, top: position.top - viewportScrollOffset.top};
|
1051 |
+
var viewportDimensions = document.viewport.getDimensions();
|
1052 |
+
var reposition = false;
|
1053 |
+
|
1054 |
+
if (viewportDimensions.width >= dimensions.width) {
|
1055 |
+
if (viewportOffset.left < 0) {
|
1056 |
+
reposition = true;
|
1057 |
+
tipJ[0] = 'left';
|
1058 |
+
if (this.options.target && trgJ[0] == 'left') {trgJ[0] = 'right';}
|
1059 |
+
}
|
1060 |
+
else if (viewportOffset.left + dimensions.width > viewportDimensions.width) {
|
1061 |
+
reposition = true;
|
1062 |
+
tipJ[0] = 'right';
|
1063 |
+
if (this.options.target && trgJ[0] == 'right') {trgJ[0] = 'left';}
|
1064 |
+
}
|
1065 |
+
}
|
1066 |
+
|
1067 |
+
if (viewportDimensions.height >= dimensions.height) {
|
1068 |
+
if (viewportOffset.top < 0) {
|
1069 |
+
reposition = true;
|
1070 |
+
tipJ[1] = 'top';
|
1071 |
+
if (this.options.target && trgJ[1] == 'top') {trgJ[1] = 'bottom';}
|
1072 |
+
}
|
1073 |
+
else if (viewportOffset.top + dimensions.height > viewportDimensions.height) {
|
1074 |
+
reposition = true;
|
1075 |
+
tipJ[1] = 'bottom';
|
1076 |
+
if (this.options.target && trgJ[1] == 'bottom') {trgJ[1] = 'top';}
|
1077 |
+
}
|
1078 |
+
}
|
1079 |
+
if (reposition) {
|
1080 |
+
var newPosition = this.getPosition(evt, tipJ, trgJ, tipJ);
|
1081 |
+
var newSticksOut = [ this.sticksOutX(newPosition), this.sticksOutY(newPosition) ];
|
1082 |
+
var revertedCount = 0;
|
1083 |
+
for (var i = 0; i <=1; i ++) {
|
1084 |
+
if (newSticksOut[i] && newSticksOut[i] != sticksOut[i]) {
|
1085 |
+
// The tooltip changed sides, but now is sticking out the other side of the window.
|
1086 |
+
// If its still sticking out, but on the same side, it's ok. At least, it sticks out less.
|
1087 |
+
revertedCount ++;
|
1088 |
+
tipJ[i] = this.options.tipJoint[i];
|
1089 |
+
if (this.options.target) {trgJ[i] = this.options.targetJoint[i];}
|
1090 |
+
}
|
1091 |
+
}
|
1092 |
+
if (revertedCount < 2) {
|
1093 |
+
this.currentStemPosition = tipJ;
|
1094 |
+
return this.getPosition(evt, tipJ, trgJ, tipJ);
|
1095 |
+
}
|
1096 |
+
}
|
1097 |
+
return position;
|
1098 |
+
},
|
1099 |
+
sticksOut: function(position) {
|
1100 |
+
return this.sticksOutX(position) || this.sticksOutY(position);
|
1101 |
+
},
|
1102 |
+
/**
|
1103 |
+
* return 1 for left 2 for right
|
1104 |
+
*/
|
1105 |
+
sticksOutX: function(position) {
|
1106 |
+
var viewportScrollOffset = $(document.viewport).getScrollOffsets();
|
1107 |
+
var viewportOffset = {left: position.left - viewportScrollOffset.left, top: position.top - viewportScrollOffset.top};
|
1108 |
+
if (viewportOffset.left < 0) return Opentip.STICKS_OUT_LEFT;
|
1109 |
+
if (viewportOffset.left + this.dimensions.width > document.viewport.getDimensions().width) {return Opentip.STICKS_OUT_RIGHT;}
|
1110 |
+
},
|
1111 |
+
/**
|
1112 |
+
* return 1 for top 2 for bottom
|
1113 |
+
*/
|
1114 |
+
sticksOutY: function(position) {
|
1115 |
+
var viewportScrollOffset = $(document.viewport).getScrollOffsets();
|
1116 |
+
var viewportOffset = {left: position.left - viewportScrollOffset.left, top: position.top - viewportScrollOffset.top};
|
1117 |
+
if (viewportOffset.top < 0) return Opentip.STICKS_OUT_TOP;
|
1118 |
+
if (viewportOffset.top + this.dimensions.height > document.viewport.getDimensions().height) return Opentip.STICKS_OUT_BOTTOM;
|
1119 |
+
},
|
1120 |
+
getStemCanvas: function() {
|
1121 |
+
return this.container.down('.stem');
|
1122 |
+
},
|
1123 |
+
stemPositionsEqual: function(position1, position2) {
|
1124 |
+
return (position1 && position2 && position1[0] == position2[0] && position1[1] == position2[1]);
|
1125 |
+
},
|
1126 |
+
positionStem: function() {
|
1127 |
+
// Position stem
|
1128 |
+
if (this.options.stem) {
|
1129 |
+
|
1130 |
+
var canvasElement = this.getStemCanvas();
|
1131 |
+
|
1132 |
+
if (canvasElement && !this.stemPositionsEqual(this.lastStemPosition, this.currentStemPosition)) {
|
1133 |
+
|
1134 |
+
this.debug('Setting stem style');
|
1135 |
+
|
1136 |
+
this.lastStemPosition = this.currentStemPosition;
|
1137 |
+
|
1138 |
+
var stemPosition = Opentip.sanitizePosition(this.currentStemPosition);
|
1139 |
+
var stemSize = this.options.stemSize;
|
1140 |
+
|
1141 |
+
var rotationRad = stemPosition * Math.PI / 4; // Every number means 45deg
|
1142 |
+
|
1143 |
+
var baseThikness = Math.round(stemSize * 1.5);
|
1144 |
+
|
1145 |
+
var realDim = {w: baseThikness, h: stemSize};
|
1146 |
+
|
1147 |
+
var isCorner = false;
|
1148 |
+
if (stemPosition % 2 == 1) {
|
1149 |
+
// Corner
|
1150 |
+
isCorner = true;
|
1151 |
+
var additionalWidth = Math.round(0.707106781 * baseThikness); // 0.707106781 == sqrt(2) / 2 to calculate the adjacent leg of the triangle
|
1152 |
+
realDim = {w: stemSize + additionalWidth, h: stemSize + additionalWidth};
|
1153 |
+
}
|
1154 |
+
|
1155 |
+
var drawDim = Object.clone(realDim); // The drawDim is so that I can draw without takin the rotation into calculation
|
1156 |
+
|
1157 |
+
if (stemPosition == Opentip.position.left || stemPosition == Opentip.position.right) {
|
1158 |
+
// The canvas has to be rotated
|
1159 |
+
realDim.h = drawDim.w;
|
1160 |
+
realDim.w = drawDim.h;
|
1161 |
+
}
|
1162 |
+
|
1163 |
+
|
1164 |
+
var stemColor = canvasElement.getStyle('color') || 'black';
|
1165 |
+
|
1166 |
+
|
1167 |
+
canvasElement.width = realDim.w;
|
1168 |
+
canvasElement.height = realDim.h;
|
1169 |
+
|
1170 |
+
// Now draw the stem.
|
1171 |
+
var ctx = canvasElement.getContext('2d');
|
1172 |
+
|
1173 |
+
ctx.clearRect (0, 0, canvasElement.width, canvasElement.height);
|
1174 |
+
ctx.beginPath();
|
1175 |
+
|
1176 |
+
ctx.fillStyle = stemColor;
|
1177 |
+
|
1178 |
+
ctx.save();
|
1179 |
+
|
1180 |
+
ctx.translate(realDim.w / 2, realDim.h / 2);
|
1181 |
+
var rotations = Math.floor(stemPosition / 2);
|
1182 |
+
ctx.rotate(rotations * Math.PI / 2);
|
1183 |
+
if (realDim.w == drawDim.w) { // This is a real hack because I don't know how to reset to 0,0
|
1184 |
+
ctx.translate(-realDim.w / 2, -realDim.h / 2);
|
1185 |
+
}
|
1186 |
+
else {
|
1187 |
+
ctx.translate(-realDim.h / 2, -realDim.w / 2);
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
if (isCorner) {
|
1191 |
+
ctx.moveTo(additionalWidth, drawDim.h);
|
1192 |
+
ctx.lineTo(drawDim.w, 0);
|
1193 |
+
ctx.lineTo(0, drawDim.h - additionalWidth);
|
1194 |
+
}
|
1195 |
+
else {
|
1196 |
+
ctx.moveTo(drawDim.w / 2 - baseThikness / 2, drawDim.h);
|
1197 |
+
ctx.lineTo(drawDim.w / 2, 0);
|
1198 |
+
ctx.lineTo(drawDim.w / 2 + baseThikness / 2, drawDim.h);
|
1199 |
+
}
|
1200 |
+
ctx.fill();
|
1201 |
+
ctx.restore();
|
1202 |
+
|
1203 |
+
|
1204 |
+
var style = {width: realDim.w + 'px', height: realDim.h + 'px', left: '', right: '', top: '', bottom: ''};
|
1205 |
+
|
1206 |
+
switch (stemPosition) {
|
1207 |
+
case Opentip.position.top:
|
1208 |
+
style.top = - realDim.h + 'px';
|
1209 |
+
style.left = - Math.round(realDim.w / 2) + 'px';
|
1210 |
+
break;
|
1211 |
+
case Opentip.position.right:
|
1212 |
+
style.top = - Math.round(realDim.h / 2) + 'px';
|
1213 |
+
style.left = 0;
|
1214 |
+
break;
|
1215 |
+
case Opentip.position.bottom:
|
1216 |
+
style.top = 0;
|
1217 |
+
style.left = - Math.round(realDim.w / 2) + 'px';
|
1218 |
+
break;
|
1219 |
+
case Opentip.position.left:
|
1220 |
+
style.top = - Math.round(realDim.h / 2) + 'px';
|
1221 |
+
style.left = - realDim.w + 'px';
|
1222 |
+
break;
|
1223 |
+
case Opentip.position.topRight:
|
1224 |
+
style.top = - stemSize + 'px';
|
1225 |
+
style.left = - additionalWidth + 'px';
|
1226 |
+
break;
|
1227 |
+
case Opentip.position.bottomRight:
|
1228 |
+
style.top = - additionalWidth + 'px';
|
1229 |
+
style.left = - additionalWidth + 'px';
|
1230 |
+
break;
|
1231 |
+
case Opentip.position.bottomLeft:
|
1232 |
+
style.top = - additionalWidth + 'px';
|
1233 |
+
style.left = - stemSize + 'px';
|
1234 |
+
break;
|
1235 |
+
case Opentip.position.topLeft:
|
1236 |
+
style.top = - stemSize + 'px';
|
1237 |
+
style.left = - stemSize + 'px';
|
1238 |
+
break;
|
1239 |
+
default:
|
1240 |
+
throw 'Unknown stem position: ' + stemPosition;
|
1241 |
+
}
|
1242 |
+
|
1243 |
+
canvasElement.setStyle(style);
|
1244 |
+
|
1245 |
+
var stemContainer = canvasElement.up('.stem-container');
|
1246 |
+
stemContainer.removeClassName('left').removeClassName('right').removeClassName('center').removeClassName('top').removeClassName('bottom').removeClassName('middle');
|
1247 |
+
|
1248 |
+
switch (stemPosition) {
|
1249 |
+
case Opentip.position.top: case Opentip.position.topLeft: case Opentip.position.topRight:
|
1250 |
+
stemContainer.addClassName('top');
|
1251 |
+
break;
|
1252 |
+
case Opentip.position.bottom: case Opentip.position.bottomLeft: case Opentip.position.bottomRight:
|
1253 |
+
stemContainer.addClassName('bottom');
|
1254 |
+
break;
|
1255 |
+
default:
|
1256 |
+
stemContainer.addClassName('middle');
|
1257 |
+
break;
|
1258 |
+
}
|
1259 |
+
switch (stemPosition) {
|
1260 |
+
case Opentip.position.left: case Opentip.position.topLeft: case Opentip.position.bottomLeft:
|
1261 |
+
stemContainer.addClassName('left');
|
1262 |
+
break;
|
1263 |
+
case Opentip.position.right: case Opentip.position.topRight: case Opentip.position.bottomRight:
|
1264 |
+
stemContainer.addClassName('right');
|
1265 |
+
break;
|
1266 |
+
default:
|
1267 |
+
stemContainer.addClassName('center');
|
1268 |
+
break;
|
1269 |
+
}
|
1270 |
+
|
1271 |
+
}
|
1272 |
+
|
1273 |
+
}
|
1274 |
+
},
|
1275 |
+
triggerElementExists: function(element) {
|
1276 |
+
return this.triggerElement.parentNode && this.triggerElement.visible() && this.triggerElement.descendantOf(document.body);
|
1277 |
+
},
|
1278 |
+
ensureElementInterval: 1000, // In milliseconds, how often opentip should check for the existance of the element
|
1279 |
+
ensureElement: function() { // Regularely checks if the element is still in the dom.
|
1280 |
+
this.deactivateElementEnsurance();
|
1281 |
+
if ( ! this.triggerElementExists()) {this.deactivate();}
|
1282 |
+
this.ensureElementTimeoutId = setTimeout(this.ensureElement.bind(this), this.ensureElementInterval);
|
1283 |
+
},
|
1284 |
+
deactivateElementEnsurance: function() {clearTimeout(this.ensureElementTimeoutId);}
|
1285 |
+
});
|
js/mageho/sortproducts/prototype.js
ADDED
@@ -0,0 +1,6081 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Prototype JavaScript framework, version 1.7
|
2 |
+
* (c) 2005-2010 Sam Stephenson
|
3 |
+
*
|
4 |
+
* Prototype is freely distributable under the terms of an MIT-style license.
|
5 |
+
* For details, see the Prototype web site: http://www.prototypejs.org/
|
6 |
+
*
|
7 |
+
*--------------------------------------------------------------------------*/
|
8 |
+
|
9 |
+
var Prototype = {
|
10 |
+
|
11 |
+
Version: '1.7',
|
12 |
+
|
13 |
+
Browser: (function(){
|
14 |
+
var ua = navigator.userAgent;
|
15 |
+
var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
|
16 |
+
return {
|
17 |
+
IE: !!window.attachEvent && !isOpera,
|
18 |
+
Opera: isOpera,
|
19 |
+
WebKit: ua.indexOf('AppleWebKit/') > -1,
|
20 |
+
Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
|
21 |
+
MobileSafari: /Apple.*Mobile/.test(ua)
|
22 |
+
}
|
23 |
+
})(),
|
24 |
+
|
25 |
+
BrowserFeatures: {
|
26 |
+
XPath: !!document.evaluate,
|
27 |
+
|
28 |
+
SelectorsAPI: !!document.querySelector,
|
29 |
+
|
30 |
+
ElementExtensions: (function() {
|
31 |
+
var constructor = window.Element || window.HTMLElement;
|
32 |
+
return !!(constructor && constructor.prototype);
|
33 |
+
})(),
|
34 |
+
SpecificElementExtensions: (function() {
|
35 |
+
if (typeof window.HTMLDivElement !== 'undefined')
|
36 |
+
return true;
|
37 |
+
|
38 |
+
var div = document.createElement('div'),
|
39 |
+
form = document.createElement('form'),
|
40 |
+
isSupported = false;
|
41 |
+
|
42 |
+
if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
|
43 |
+
isSupported = true;
|
44 |
+
}
|
45 |
+
|
46 |
+
div = form = null;
|
47 |
+
|
48 |
+
return isSupported;
|
49 |
+
})()
|
50 |
+
},
|
51 |
+
|
52 |
+
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
|
53 |
+
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
|
54 |
+
|
55 |
+
emptyFunction: function() { },
|
56 |
+
|
57 |
+
K: function(x) { return x }
|
58 |
+
};
|
59 |
+
|
60 |
+
if (Prototype.Browser.MobileSafari)
|
61 |
+
Prototype.BrowserFeatures.SpecificElementExtensions = false;
|
62 |
+
/* Based on Alex Arnell's inheritance implementation. */
|
63 |
+
|
64 |
+
var Class = (function() {
|
65 |
+
|
66 |
+
var IS_DONTENUM_BUGGY = (function(){
|
67 |
+
for (var p in { toString: 1 }) {
|
68 |
+
if (p === 'toString') return false;
|
69 |
+
}
|
70 |
+
return true;
|
71 |
+
})();
|
72 |
+
|
73 |
+
function subclass() {};
|
74 |
+
function create() {
|
75 |
+
var parent = null, properties = $A(arguments);
|
76 |
+
if (Object.isFunction(properties[0]))
|
77 |
+
parent = properties.shift();
|
78 |
+
|
79 |
+
function klass() {
|
80 |
+
this.initialize.apply(this, arguments);
|
81 |
+
}
|
82 |
+
|
83 |
+
Object.extend(klass, Class.Methods);
|
84 |
+
klass.superclass = parent;
|
85 |
+
klass.subclasses = [];
|
86 |
+
|
87 |
+
if (parent) {
|
88 |
+
subclass.prototype = parent.prototype;
|
89 |
+
klass.prototype = new subclass;
|
90 |
+
parent.subclasses.push(klass);
|
91 |
+
}
|
92 |
+
|
93 |
+
for (var i = 0, length = properties.length; i < length; i++)
|
94 |
+
klass.addMethods(properties[i]);
|
95 |
+
|
96 |
+
if (!klass.prototype.initialize)
|
97 |
+
klass.prototype.initialize = Prototype.emptyFunction;
|
98 |
+
|
99 |
+
klass.prototype.constructor = klass;
|
100 |
+
return klass;
|
101 |
+
}
|
102 |
+
|
103 |
+
function addMethods(source) {
|
104 |
+
var ancestor = this.superclass && this.superclass.prototype,
|
105 |
+
properties = Object.keys(source);
|
106 |
+
|
107 |
+
if (IS_DONTENUM_BUGGY) {
|
108 |
+
if (source.toString != Object.prototype.toString)
|
109 |
+
properties.push("toString");
|
110 |
+
if (source.valueOf != Object.prototype.valueOf)
|
111 |
+
properties.push("valueOf");
|
112 |
+
}
|
113 |
+
|
114 |
+
for (var i = 0, length = properties.length; i < length; i++) {
|
115 |
+
var property = properties[i], value = source[property];
|
116 |
+
if (ancestor && Object.isFunction(value) &&
|
117 |
+
value.argumentNames()[0] == "$super") {
|
118 |
+
var method = value;
|
119 |
+
value = (function(m) {
|
120 |
+
return function() { return ancestor[m].apply(this, arguments); };
|
121 |
+
})(property).wrap(method);
|
122 |
+
|
123 |
+
value.valueOf = method.valueOf.bind(method);
|
124 |
+
value.toString = method.toString.bind(method);
|
125 |
+
}
|
126 |
+
this.prototype[property] = value;
|
127 |
+
}
|
128 |
+
|
129 |
+
return this;
|
130 |
+
}
|
131 |
+
|
132 |
+
return {
|
133 |
+
create: create,
|
134 |
+
Methods: {
|
135 |
+
addMethods: addMethods
|
136 |
+
}
|
137 |
+
};
|
138 |
+
})();
|
139 |
+
(function() {
|
140 |
+
|
141 |
+
var _toString = Object.prototype.toString,
|
142 |
+
NULL_TYPE = 'Null',
|
143 |
+
UNDEFINED_TYPE = 'Undefined',
|
144 |
+
BOOLEAN_TYPE = 'Boolean',
|
145 |
+
NUMBER_TYPE = 'Number',
|
146 |
+
STRING_TYPE = 'String',
|
147 |
+
OBJECT_TYPE = 'Object',
|
148 |
+
FUNCTION_CLASS = '[object Function]',
|
149 |
+
BOOLEAN_CLASS = '[object Boolean]',
|
150 |
+
NUMBER_CLASS = '[object Number]',
|
151 |
+
STRING_CLASS = '[object String]',
|
152 |
+
ARRAY_CLASS = '[object Array]',
|
153 |
+
DATE_CLASS = '[object Date]',
|
154 |
+
NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
|
155 |
+
typeof JSON.stringify === 'function' &&
|
156 |
+
JSON.stringify(0) === '0' &&
|
157 |
+
typeof JSON.stringify(Prototype.K) === 'undefined';
|
158 |
+
|
159 |
+
function Type(o) {
|
160 |
+
switch(o) {
|
161 |
+
case null: return NULL_TYPE;
|
162 |
+
case (void 0): return UNDEFINED_TYPE;
|
163 |
+
}
|
164 |
+
var type = typeof o;
|
165 |
+
switch(type) {
|
166 |
+
case 'boolean': return BOOLEAN_TYPE;
|
167 |
+
case 'number': return NUMBER_TYPE;
|
168 |
+
case 'string': return STRING_TYPE;
|
169 |
+
}
|
170 |
+
return OBJECT_TYPE;
|
171 |
+
}
|
172 |
+
|
173 |
+
function extend(destination, source) {
|
174 |
+
for (var property in source)
|
175 |
+
destination[property] = source[property];
|
176 |
+
return destination;
|
177 |
+
}
|
178 |
+
|
179 |
+
function inspect(object) {
|
180 |
+
try {
|
181 |
+
if (isUndefined(object)) return 'undefined';
|
182 |
+
if (object === null) return 'null';
|
183 |
+
return object.inspect ? object.inspect() : String(object);
|
184 |
+
} catch (e) {
|
185 |
+
if (e instanceof RangeError) return '...';
|
186 |
+
throw e;
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
function toJSON(value) {
|
191 |
+
return Str('', { '': value }, []);
|
192 |
+
}
|
193 |
+
|
194 |
+
function Str(key, holder, stack) {
|
195 |
+
var value = holder[key],
|
196 |
+
type = typeof value;
|
197 |
+
|
198 |
+
if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
|
199 |
+
value = value.toJSON(key);
|
200 |
+
}
|
201 |
+
|
202 |
+
var _class = _toString.call(value);
|
203 |
+
|
204 |
+
switch (_class) {
|
205 |
+
case NUMBER_CLASS:
|
206 |
+
case BOOLEAN_CLASS:
|
207 |
+
case STRING_CLASS:
|
208 |
+
value = value.valueOf();
|
209 |
+
}
|
210 |
+
|
211 |
+
switch (value) {
|
212 |
+
case null: return 'null';
|
213 |
+
case true: return 'true';
|
214 |
+
case false: return 'false';
|
215 |
+
}
|
216 |
+
|
217 |
+
type = typeof value;
|
218 |
+
switch (type) {
|
219 |
+
case 'string':
|
220 |
+
return value.inspect(true);
|
221 |
+
case 'number':
|
222 |
+
return isFinite(value) ? String(value) : 'null';
|
223 |
+
case 'object':
|
224 |
+
|
225 |
+
for (var i = 0, length = stack.length; i < length; i++) {
|
226 |
+
if (stack[i] === value) { throw new TypeError(); }
|
227 |
+
}
|
228 |
+
stack.push(value);
|
229 |
+
|
230 |
+
var partial = [];
|
231 |
+
if (_class === ARRAY_CLASS) {
|
232 |
+
for (var i = 0, length = value.length; i < length; i++) {
|
233 |
+
var str = Str(i, value, stack);
|
234 |
+
partial.push(typeof str === 'undefined' ? 'null' : str);
|
235 |
+
}
|
236 |
+
partial = '[' + partial.join(',') + ']';
|
237 |
+
} else {
|
238 |
+
var keys = Object.keys(value);
|
239 |
+
for (var i = 0, length = keys.length; i < length; i++) {
|
240 |
+
var key = keys[i], str = Str(key, value, stack);
|
241 |
+
if (typeof str !== "undefined") {
|
242 |
+
partial.push(key.inspect(true)+ ':' + str);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
partial = '{' + partial.join(',') + '}';
|
246 |
+
}
|
247 |
+
stack.pop();
|
248 |
+
return partial;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
function stringify(object) {
|
253 |
+
return JSON.stringify(object);
|
254 |
+
}
|
255 |
+
|
256 |
+
function toQueryString(object) {
|
257 |
+
return $H(object).toQueryString();
|
258 |
+
}
|
259 |
+
|
260 |
+
function toHTML(object) {
|
261 |
+
return object && object.toHTML ? object.toHTML() : String.interpret(object);
|
262 |
+
}
|
263 |
+
|
264 |
+
function keys(object) {
|
265 |
+
if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
|
266 |
+
var results = [];
|
267 |
+
for (var property in object) {
|
268 |
+
if (object.hasOwnProperty(property)) {
|
269 |
+
results.push(property);
|
270 |
+
}
|
271 |
+
}
|
272 |
+
return results;
|
273 |
+
}
|
274 |
+
|
275 |
+
function values(object) {
|
276 |
+
var results = [];
|
277 |
+
for (var property in object)
|
278 |
+
results.push(object[property]);
|
279 |
+
return results;
|
280 |
+
}
|
281 |
+
|
282 |
+
function clone(object) {
|
283 |
+
return extend({ }, object);
|
284 |
+
}
|
285 |
+
|
286 |
+
function isElement(object) {
|
287 |
+
return !!(object && object.nodeType == 1);
|
288 |
+
}
|
289 |
+
|
290 |
+
function isArray(object) {
|
291 |
+
return _toString.call(object) === ARRAY_CLASS;
|
292 |
+
}
|
293 |
+
|
294 |
+
var hasNativeIsArray = (typeof Array.isArray == 'function')
|
295 |
+
&& Array.isArray([]) && !Array.isArray({});
|
296 |
+
|
297 |
+
if (hasNativeIsArray) {
|
298 |
+
isArray = Array.isArray;
|
299 |
+
}
|
300 |
+
|
301 |
+
function isHash(object) {
|
302 |
+
return object instanceof Hash;
|
303 |
+
}
|
304 |
+
|
305 |
+
function isFunction(object) {
|
306 |
+
return _toString.call(object) === FUNCTION_CLASS;
|
307 |
+
}
|
308 |
+
|
309 |
+
function isString(object) {
|
310 |
+
return _toString.call(object) === STRING_CLASS;
|
311 |
+
}
|
312 |
+
|
313 |
+
function isNumber(object) {
|
314 |
+
return _toString.call(object) === NUMBER_CLASS;
|
315 |
+
}
|
316 |
+
|
317 |
+
function isDate(object) {
|
318 |
+
return _toString.call(object) === DATE_CLASS;
|
319 |
+
}
|
320 |
+
|
321 |
+
function isUndefined(object) {
|
322 |
+
return typeof object === "undefined";
|
323 |
+
}
|
324 |
+
|
325 |
+
extend(Object, {
|
326 |
+
extend: extend,
|
327 |
+
inspect: inspect,
|
328 |
+
toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
|
329 |
+
toQueryString: toQueryString,
|
330 |
+
toHTML: toHTML,
|
331 |
+
keys: Object.keys || keys,
|
332 |
+
values: values,
|
333 |
+
clone: clone,
|
334 |
+
isElement: isElement,
|
335 |
+
isArray: isArray,
|
336 |
+
isHash: isHash,
|
337 |
+
isFunction: isFunction,
|
338 |
+
isString: isString,
|
339 |
+
isNumber: isNumber,
|
340 |
+
isDate: isDate,
|
341 |
+
isUndefined: isUndefined
|
342 |
+
});
|
343 |
+
})();
|
344 |
+
Object.extend(Function.prototype, (function() {
|
345 |
+
var slice = Array.prototype.slice;
|
346 |
+
|
347 |
+
function update(array, args) {
|
348 |
+
var arrayLength = array.length, length = args.length;
|
349 |
+
while (length--) array[arrayLength + length] = args[length];
|
350 |
+
return array;
|
351 |
+
}
|
352 |
+
|
353 |
+
function merge(array, args) {
|
354 |
+
array = slice.call(array, 0);
|
355 |
+
return update(array, args);
|
356 |
+
}
|
357 |
+
|
358 |
+
function argumentNames() {
|
359 |
+
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
|
360 |
+
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
|
361 |
+
.replace(/\s+/g, '').split(',');
|
362 |
+
return names.length == 1 && !names[0] ? [] : names;
|
363 |
+
}
|
364 |
+
|
365 |
+
function bind(context) {
|
366 |
+
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
|
367 |
+
var __method = this, args = slice.call(arguments, 1);
|
368 |
+
return function() {
|
369 |
+
var a = merge(args, arguments);
|
370 |
+
return __method.apply(context, a);
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
function bindAsEventListener(context) {
|
375 |
+
var __method = this, args = slice.call(arguments, 1);
|
376 |
+
return function(event) {
|
377 |
+
var a = update([event || window.event], args);
|
378 |
+
return __method.apply(context, a);
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
function curry() {
|
383 |
+
if (!arguments.length) return this;
|
384 |
+
var __method = this, args = slice.call(arguments, 0);
|
385 |
+
return function() {
|
386 |
+
var a = merge(args, arguments);
|
387 |
+
return __method.apply(this, a);
|
388 |
+
}
|
389 |
+
}
|
390 |
+
|
391 |
+
function delay(timeout) {
|
392 |
+
var __method = this, args = slice.call(arguments, 1);
|
393 |
+
timeout = timeout * 1000;
|
394 |
+
return window.setTimeout(function() {
|
395 |
+
return __method.apply(__method, args);
|
396 |
+
}, timeout);
|
397 |
+
}
|
398 |
+
|
399 |
+
function defer() {
|
400 |
+
var args = update([0.01], arguments);
|
401 |
+
return this.delay.apply(this, args);
|
402 |
+
}
|
403 |
+
|
404 |
+
function wrap(wrapper) {
|
405 |
+
var __method = this;
|
406 |
+
return function() {
|
407 |
+
var a = update([__method.bind(this)], arguments);
|
408 |
+
return wrapper.apply(this, a);
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
function methodize() {
|
413 |
+
if (this._methodized) return this._methodized;
|
414 |
+
var __method = this;
|
415 |
+
return this._methodized = function() {
|
416 |
+
var a = update([this], arguments);
|
417 |
+
return __method.apply(null, a);
|
418 |
+
};
|
419 |
+
}
|
420 |
+
|
421 |
+
return {
|
422 |
+
argumentNames: argumentNames,
|
423 |
+
bind: bind,
|
424 |
+
bindAsEventListener: bindAsEventListener,
|
425 |
+
curry: curry,
|
426 |
+
delay: delay,
|
427 |
+
defer: defer,
|
428 |
+
wrap: wrap,
|
429 |
+
methodize: methodize
|
430 |
+
}
|
431 |
+
})());
|
432 |
+
|
433 |
+
|
434 |
+
|
435 |
+
(function(proto) {
|
436 |
+
|
437 |
+
|
438 |
+
function toISOString() {
|
439 |
+
return this.getUTCFullYear() + '-' +
|
440 |
+
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
|
441 |
+
this.getUTCDate().toPaddedString(2) + 'T' +
|
442 |
+
this.getUTCHours().toPaddedString(2) + ':' +
|
443 |
+
this.getUTCMinutes().toPaddedString(2) + ':' +
|
444 |
+
this.getUTCSeconds().toPaddedString(2) + 'Z';
|
445 |
+
}
|
446 |
+
|
447 |
+
|
448 |
+
function toJSON() {
|
449 |
+
return this.toISOString();
|
450 |
+
}
|
451 |
+
|
452 |
+
if (!proto.toISOString) proto.toISOString = toISOString;
|
453 |
+
if (!proto.toJSON) proto.toJSON = toJSON;
|
454 |
+
|
455 |
+
})(Date.prototype);
|
456 |
+
|
457 |
+
|
458 |
+
RegExp.prototype.match = RegExp.prototype.test;
|
459 |
+
|
460 |
+
RegExp.escape = function(str) {
|
461 |
+
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
|
462 |
+
};
|
463 |
+
var PeriodicalExecuter = Class.create({
|
464 |
+
initialize: function(callback, frequency) {
|
465 |
+
this.callback = callback;
|
466 |
+
this.frequency = frequency;
|
467 |
+
this.currentlyExecuting = false;
|
468 |
+
|
469 |
+
this.registerCallback();
|
470 |
+
},
|
471 |
+
|
472 |
+
registerCallback: function() {
|
473 |
+
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
|
474 |
+
},
|
475 |
+
|
476 |
+
execute: function() {
|
477 |
+
this.callback(this);
|
478 |
+
},
|
479 |
+
|
480 |
+
stop: function() {
|
481 |
+
if (!this.timer) return;
|
482 |
+
clearInterval(this.timer);
|
483 |
+
this.timer = null;
|
484 |
+
},
|
485 |
+
|
486 |
+
onTimerEvent: function() {
|
487 |
+
if (!this.currentlyExecuting) {
|
488 |
+
try {
|
489 |
+
this.currentlyExecuting = true;
|
490 |
+
this.execute();
|
491 |
+
this.currentlyExecuting = false;
|
492 |
+
} catch(e) {
|
493 |
+
this.currentlyExecuting = false;
|
494 |
+
throw e;
|
495 |
+
}
|
496 |
+
}
|
497 |
+
}
|
498 |
+
});
|
499 |
+
Object.extend(String, {
|
500 |
+
interpret: function(value) {
|
501 |
+
return value == null ? '' : String(value);
|
502 |
+
},
|
503 |
+
specialChar: {
|
504 |
+
'\b': '\\b',
|
505 |
+
'\t': '\\t',
|
506 |
+
'\n': '\\n',
|
507 |
+
'\f': '\\f',
|
508 |
+
'\r': '\\r',
|
509 |
+
'\\': '\\\\'
|
510 |
+
}
|
511 |
+
});
|
512 |
+
|
513 |
+
Object.extend(String.prototype, (function() {
|
514 |
+
var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
|
515 |
+
typeof JSON.parse === 'function' &&
|
516 |
+
JSON.parse('{"test": true}').test;
|
517 |
+
|
518 |
+
function prepareReplacement(replacement) {
|
519 |
+
if (Object.isFunction(replacement)) return replacement;
|
520 |
+
var template = new Template(replacement);
|
521 |
+
return function(match) { return template.evaluate(match) };
|
522 |
+
}
|
523 |
+
|
524 |
+
function gsub(pattern, replacement) {
|
525 |
+
var result = '', source = this, match;
|
526 |
+
replacement = prepareReplacement(replacement);
|
527 |
+
|
528 |
+
if (Object.isString(pattern))
|
529 |
+
pattern = RegExp.escape(pattern);
|
530 |
+
|
531 |
+
if (!(pattern.length || pattern.source)) {
|
532 |
+
replacement = replacement('');
|
533 |
+
return replacement + source.split('').join(replacement) + replacement;
|
534 |
+
}
|
535 |
+
|
536 |
+
while (source.length > 0) {
|
537 |
+
if (match = source.match(pattern)) {
|
538 |
+
result += source.slice(0, match.index);
|
539 |
+
result += String.interpret(replacement(match));
|
540 |
+
source = source.slice(match.index + match[0].length);
|
541 |
+
} else {
|
542 |
+
result += source, source = '';
|
543 |
+
}
|
544 |
+
}
|
545 |
+
return result;
|
546 |
+
}
|
547 |
+
|
548 |
+
function sub(pattern, replacement, count) {
|
549 |
+
replacement = prepareReplacement(replacement);
|
550 |
+
count = Object.isUndefined(count) ? 1 : count;
|
551 |
+
|
552 |
+
return this.gsub(pattern, function(match) {
|
553 |
+
if (--count < 0) return match[0];
|
554 |
+
return replacement(match);
|
555 |
+
});
|
556 |
+
}
|
557 |
+
|
558 |
+
function scan(pattern, iterator) {
|
559 |
+
this.gsub(pattern, iterator);
|
560 |
+
return String(this);
|
561 |
+
}
|
562 |
+
|
563 |
+
function truncate(length, truncation) {
|
564 |
+
length = length || 30;
|
565 |
+
truncation = Object.isUndefined(truncation) ? '...' : truncation;
|
566 |
+
return this.length > length ?
|
567 |
+
this.slice(0, length - truncation.length) + truncation : String(this);
|
568 |
+
}
|
569 |
+
|
570 |
+
function strip() {
|
571 |
+
return this.replace(/^\s+/, '').replace(/\s+$/, '');
|
572 |
+
}
|
573 |
+
|
574 |
+
function stripTags() {
|
575 |
+
return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
|
576 |
+
}
|
577 |
+
|
578 |
+
function stripScripts() {
|
579 |
+
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
|
580 |
+
}
|
581 |
+
|
582 |
+
function extractScripts() {
|
583 |
+
var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
|
584 |
+
matchOne = new RegExp(Prototype.ScriptFragment, 'im');
|
585 |
+
return (this.match(matchAll) || []).map(function(scriptTag) {
|
586 |
+
return (scriptTag.match(matchOne) || ['', ''])[1];
|
587 |
+
});
|
588 |
+
}
|
589 |
+
|
590 |
+
function evalScripts() {
|
591 |
+
return this.extractScripts().map(function(script) { return eval(script) });
|
592 |
+
}
|
593 |
+
|
594 |
+
function escapeHTML() {
|
595 |
+
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
596 |
+
}
|
597 |
+
|
598 |
+
function unescapeHTML() {
|
599 |
+
return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
|
600 |
+
}
|
601 |
+
|
602 |
+
|
603 |
+
function toQueryParams(separator) {
|
604 |
+
var match = this.strip().match(/([^?#]*)(#.*)?$/);
|
605 |
+
if (!match) return { };
|
606 |
+
|
607 |
+
return match[1].split(separator || '&').inject({ }, function(hash, pair) {
|
608 |
+
if ((pair = pair.split('='))[0]) {
|
609 |
+
var key = decodeURIComponent(pair.shift()),
|
610 |
+
value = pair.length > 1 ? pair.join('=') : pair[0];
|
611 |
+
|
612 |
+
if (value != undefined) value = decodeURIComponent(value);
|
613 |
+
|
614 |
+
if (key in hash) {
|
615 |
+
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
|
616 |
+
hash[key].push(value);
|
617 |
+
}
|
618 |
+
else hash[key] = value;
|
619 |
+
}
|
620 |
+
return hash;
|
621 |
+
});
|
622 |
+
}
|
623 |
+
|
624 |
+
function toArray() {
|
625 |
+
return this.split('');
|
626 |
+
}
|
627 |
+
|
628 |
+
function succ() {
|
629 |
+
return this.slice(0, this.length - 1) +
|
630 |
+
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
|
631 |
+
}
|
632 |
+
|
633 |
+
function times(count) {
|
634 |
+
return count < 1 ? '' : new Array(count + 1).join(this);
|
635 |
+
}
|
636 |
+
|
637 |
+
function camelize() {
|
638 |
+
return this.replace(/-+(.)?/g, function(match, chr) {
|
639 |
+
return chr ? chr.toUpperCase() : '';
|
640 |
+
});
|
641 |
+
}
|
642 |
+
|
643 |
+
function capitalize() {
|
644 |
+
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
|
645 |
+
}
|
646 |
+
|
647 |
+
function underscore() {
|
648 |
+
return this.replace(/::/g, '/')
|
649 |
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
|
650 |
+
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
|
651 |
+
.replace(/-/g, '_')
|
652 |
+
.toLowerCase();
|
653 |
+
}
|
654 |
+
|
655 |
+
function dasherize() {
|
656 |
+
return this.replace(/_/g, '-');
|
657 |
+
}
|
658 |
+
|
659 |
+
function inspect(useDoubleQuotes) {
|
660 |
+
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
|
661 |
+
if (character in String.specialChar) {
|
662 |
+
return String.specialChar[character];
|
663 |
+
}
|
664 |
+
return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
|
665 |
+
});
|
666 |
+
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
|
667 |
+
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
|
668 |
+
}
|
669 |
+
|
670 |
+
function unfilterJSON(filter) {
|
671 |
+
return this.replace(filter || Prototype.JSONFilter, '$1');
|
672 |
+
}
|
673 |
+
|
674 |
+
function isJSON() {
|
675 |
+
var str = this;
|
676 |
+
if (str.blank()) return false;
|
677 |
+
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
|
678 |
+
str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
|
679 |
+
str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
|
680 |
+
return (/^[\],:{}\s]*$/).test(str);
|
681 |
+
}
|
682 |
+
|
683 |
+
function evalJSON(sanitize) {
|
684 |
+
var json = this.unfilterJSON(),
|
685 |
+
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
686 |
+
if (cx.test(json)) {
|
687 |
+
json = json.replace(cx, function (a) {
|
688 |
+
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
689 |
+
});
|
690 |
+
}
|
691 |
+
try {
|
692 |
+
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
|
693 |
+
} catch (e) { }
|
694 |
+
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
|
695 |
+
}
|
696 |
+
|
697 |
+
function parseJSON() {
|
698 |
+
var json = this.unfilterJSON();
|
699 |
+
return JSON.parse(json);
|
700 |
+
}
|
701 |
+
|
702 |
+
function include(pattern) {
|
703 |
+
return this.indexOf(pattern) > -1;
|
704 |
+
}
|
705 |
+
|
706 |
+
function startsWith(pattern) {
|
707 |
+
return this.lastIndexOf(pattern, 0) === 0;
|
708 |
+
}
|
709 |
+
|
710 |
+
function endsWith(pattern) {
|
711 |
+
var d = this.length - pattern.length;
|
712 |
+
return d >= 0 && this.indexOf(pattern, d) === d;
|
713 |
+
}
|
714 |
+
|
715 |
+
function empty() {
|
716 |
+
return this == '';
|
717 |
+
}
|
718 |
+
|
719 |
+
function blank() {
|
720 |
+
return /^\s*$/.test(this);
|
721 |
+
}
|
722 |
+
|
723 |
+
function interpolate(object, pattern) {
|
724 |
+
return new Template(this, pattern).evaluate(object);
|
725 |
+
}
|
726 |
+
|
727 |
+
return {
|
728 |
+
gsub: gsub,
|
729 |
+
sub: sub,
|
730 |
+
scan: scan,
|
731 |
+
truncate: truncate,
|
732 |
+
strip: String.prototype.trim || strip,
|
733 |
+
stripTags: stripTags,
|
734 |
+
stripScripts: stripScripts,
|
735 |
+
extractScripts: extractScripts,
|
736 |
+
evalScripts: evalScripts,
|
737 |
+
escapeHTML: escapeHTML,
|
738 |
+
unescapeHTML: unescapeHTML,
|
739 |
+
toQueryParams: toQueryParams,
|
740 |
+
parseQuery: toQueryParams,
|
741 |
+
toArray: toArray,
|
742 |
+
succ: succ,
|
743 |
+
times: times,
|
744 |
+
camelize: camelize,
|
745 |
+
capitalize: capitalize,
|
746 |
+
underscore: underscore,
|
747 |
+
dasherize: dasherize,
|
748 |
+
inspect: inspect,
|
749 |
+
unfilterJSON: unfilterJSON,
|
750 |
+
isJSON: isJSON,
|
751 |
+
evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
|
752 |
+
include: include,
|
753 |
+
startsWith: startsWith,
|
754 |
+
endsWith: endsWith,
|
755 |
+
empty: empty,
|
756 |
+
blank: blank,
|
757 |
+
interpolate: interpolate
|
758 |
+
};
|
759 |
+
})());
|
760 |
+
|
761 |
+
var Template = Class.create({
|
762 |
+
initialize: function(template, pattern) {
|
763 |
+
this.template = template.toString();
|
764 |
+
this.pattern = pattern || Template.Pattern;
|
765 |
+
},
|
766 |
+
|
767 |
+
evaluate: function(object) {
|
768 |
+
if (object && Object.isFunction(object.toTemplateReplacements))
|
769 |
+
object = object.toTemplateReplacements();
|
770 |
+
|
771 |
+
return this.template.gsub(this.pattern, function(match) {
|
772 |
+
if (object == null) return (match[1] + '');
|
773 |
+
|
774 |
+
var before = match[1] || '';
|
775 |
+
if (before == '\\') return match[2];
|
776 |
+
|
777 |
+
var ctx = object, expr = match[3],
|
778 |
+
pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
|
779 |
+
|
780 |
+
match = pattern.exec(expr);
|
781 |
+
if (match == null) return before;
|
782 |
+
|
783 |
+
while (match != null) {
|
784 |
+
var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
|
785 |
+
ctx = ctx[comp];
|
786 |
+
if (null == ctx || '' == match[3]) break;
|
787 |
+
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
|
788 |
+
match = pattern.exec(expr);
|
789 |
+
}
|
790 |
+
|
791 |
+
return before + String.interpret(ctx);
|
792 |
+
});
|
793 |
+
}
|
794 |
+
});
|
795 |
+
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
|
796 |
+
|
797 |
+
var $break = { };
|
798 |
+
|
799 |
+
var Enumerable = (function() {
|
800 |
+
function each(iterator, context) {
|
801 |
+
var index = 0;
|
802 |
+
try {
|
803 |
+
this._each(function(value) {
|
804 |
+
iterator.call(context, value, index++);
|
805 |
+
});
|
806 |
+
} catch (e) {
|
807 |
+
if (e != $break) throw e;
|
808 |
+
}
|
809 |
+
return this;
|
810 |
+
}
|
811 |
+
|
812 |
+
function eachSlice(number, iterator, context) {
|
813 |
+
var index = -number, slices = [], array = this.toArray();
|
814 |
+
if (number < 1) return array;
|
815 |
+
while ((index += number) < array.length)
|
816 |
+
slices.push(array.slice(index, index+number));
|
817 |
+
return slices.collect(iterator, context);
|
818 |
+
}
|
819 |
+
|
820 |
+
function all(iterator, context) {
|
821 |
+
iterator = iterator || Prototype.K;
|
822 |
+
var result = true;
|
823 |
+
this.each(function(value, index) {
|
824 |
+
result = result && !!iterator.call(context, value, index);
|
825 |
+
if (!result) throw $break;
|
826 |
+
});
|
827 |
+
return result;
|
828 |
+
}
|
829 |
+
|
830 |
+
function any(iterator, context) {
|
831 |
+
iterator = iterator || Prototype.K;
|
832 |
+
var result = false;
|
833 |
+
this.each(function(value, index) {
|
834 |
+
if (result = !!iterator.call(context, value, index))
|
835 |
+
throw $break;
|
836 |
+
});
|
837 |
+
return result;
|
838 |
+
}
|
839 |
+
|
840 |
+
function collect(iterator, context) {
|
841 |
+
iterator = iterator || Prototype.K;
|
842 |
+
var results = [];
|
843 |
+
this.each(function(value, index) {
|
844 |
+
results.push(iterator.call(context, value, index));
|
845 |
+
});
|
846 |
+
return results;
|
847 |
+
}
|
848 |
+
|
849 |
+
function detect(iterator, context) {
|
850 |
+
var result;
|
851 |
+
this.each(function(value, index) {
|
852 |
+
if (iterator.call(context, value, index)) {
|
853 |
+
result = value;
|
854 |
+
throw $break;
|
855 |
+
}
|
856 |
+
});
|
857 |
+
return result;
|
858 |
+
}
|
859 |
+
|
860 |
+
function findAll(iterator, context) {
|
861 |
+
var results = [];
|
862 |
+
this.each(function(value, index) {
|
863 |
+
if (iterator.call(context, value, index))
|
864 |
+
results.push(value);
|
865 |
+
});
|
866 |
+
return results;
|
867 |
+
}
|
868 |
+
|
869 |
+
function grep(filter, iterator, context) {
|
870 |
+
iterator = iterator || Prototype.K;
|
871 |
+
var results = [];
|
872 |
+
|
873 |
+
if (Object.isString(filter))
|
874 |
+
filter = new RegExp(RegExp.escape(filter));
|
875 |
+
|
876 |
+
this.each(function(value, index) {
|
877 |
+
if (filter.match(value))
|
878 |
+
results.push(iterator.call(context, value, index));
|
879 |
+
});
|
880 |
+
return results;
|
881 |
+
}
|
882 |
+
|
883 |
+
function include(object) {
|
884 |
+
if (Object.isFunction(this.indexOf))
|
885 |
+
if (this.indexOf(object) != -1) return true;
|
886 |
+
|
887 |
+
var found = false;
|
888 |
+
this.each(function(value) {
|
889 |
+
if (value == object) {
|
890 |
+
found = true;
|
891 |
+
throw $break;
|
892 |
+
}
|
893 |
+
});
|
894 |
+
return found;
|
895 |
+
}
|
896 |
+
|
897 |
+
function inGroupsOf(number, fillWith) {
|
898 |
+
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
|
899 |
+
return this.eachSlice(number, function(slice) {
|
900 |
+
while(slice.length < number) slice.push(fillWith);
|
901 |
+
return slice;
|
902 |
+
});
|
903 |
+
}
|
904 |
+
|
905 |
+
function inject(memo, iterator, context) {
|
906 |
+
this.each(function(value, index) {
|
907 |
+
memo = iterator.call(context, memo, value, index);
|
908 |
+
});
|
909 |
+
return memo;
|
910 |
+
}
|
911 |
+
|
912 |
+
function invoke(method) {
|
913 |
+
var args = $A(arguments).slice(1);
|
914 |
+
return this.map(function(value) {
|
915 |
+
return value[method].apply(value, args);
|
916 |
+
});
|
917 |
+
}
|
918 |
+
|
919 |
+
function max(iterator, context) {
|
920 |
+
iterator = iterator || Prototype.K;
|
921 |
+
var result;
|
922 |
+
this.each(function(value, index) {
|
923 |
+
value = iterator.call(context, value, index);
|
924 |
+
if (result == null || value >= result)
|
925 |
+
result = value;
|
926 |
+
});
|
927 |
+
return result;
|
928 |
+
}
|
929 |
+
|
930 |
+
function min(iterator, context) {
|
931 |
+
iterator = iterator || Prototype.K;
|
932 |
+
var result;
|
933 |
+
this.each(function(value, index) {
|
934 |
+
value = iterator.call(context, value, index);
|
935 |
+
if (result == null || value < result)
|
936 |
+
result = value;
|
937 |
+
});
|
938 |
+
return result;
|
939 |
+
}
|
940 |
+
|
941 |
+
function partition(iterator, context) {
|
942 |
+
iterator = iterator || Prototype.K;
|
943 |
+
var trues = [], falses = [];
|
944 |
+
this.each(function(value, index) {
|
945 |
+
(iterator.call(context, value, index) ?
|
946 |
+
trues : falses).push(value);
|
947 |
+
});
|
948 |
+
return [trues, falses];
|
949 |
+
}
|
950 |
+
|
951 |
+
function pluck(property) {
|
952 |
+
var results = [];
|
953 |
+
this.each(function(value) {
|
954 |
+
results.push(value[property]);
|
955 |
+
});
|
956 |
+
return results;
|
957 |
+
}
|
958 |
+
|
959 |
+
function reject(iterator, context) {
|
960 |
+
var results = [];
|
961 |
+
this.each(function(value, index) {
|
962 |
+
if (!iterator.call(context, value, index))
|
963 |
+
results.push(value);
|
964 |
+
});
|
965 |
+
return results;
|
966 |
+
}
|
967 |
+
|
968 |
+
function sortBy(iterator, context) {
|
969 |
+
return this.map(function(value, index) {
|
970 |
+
return {
|
971 |
+
value: value,
|
972 |
+
criteria: iterator.call(context, value, index)
|
973 |
+
};
|
974 |
+
}).sort(function(left, right) {
|
975 |
+
var a = left.criteria, b = right.criteria;
|
976 |
+
return a < b ? -1 : a > b ? 1 : 0;
|
977 |
+
}).pluck('value');
|
978 |
+
}
|
979 |
+
|
980 |
+
function toArray() {
|
981 |
+
return this.map();
|
982 |
+
}
|
983 |
+
|
984 |
+
function zip() {
|
985 |
+
var iterator = Prototype.K, args = $A(arguments);
|
986 |
+
if (Object.isFunction(args.last()))
|
987 |
+
iterator = args.pop();
|
988 |
+
|
989 |
+
var collections = [this].concat(args).map($A);
|
990 |
+
return this.map(function(value, index) {
|
991 |
+
return iterator(collections.pluck(index));
|
992 |
+
});
|
993 |
+
}
|
994 |
+
|
995 |
+
function size() {
|
996 |
+
return this.toArray().length;
|
997 |
+
}
|
998 |
+
|
999 |
+
function inspect() {
|
1000 |
+
return '#<Enumerable:' + this.toArray().inspect() + '>';
|
1001 |
+
}
|
1002 |
+
|
1003 |
+
|
1004 |
+
|
1005 |
+
|
1006 |
+
|
1007 |
+
|
1008 |
+
|
1009 |
+
|
1010 |
+
|
1011 |
+
return {
|
1012 |
+
each: each,
|
1013 |
+
eachSlice: eachSlice,
|
1014 |
+
all: all,
|
1015 |
+
every: all,
|
1016 |
+
any: any,
|
1017 |
+
some: any,
|
1018 |
+
collect: collect,
|
1019 |
+
map: collect,
|
1020 |
+
detect: detect,
|
1021 |
+
findAll: findAll,
|
1022 |
+
select: findAll,
|
1023 |
+
filter: findAll,
|
1024 |
+
grep: grep,
|
1025 |
+
include: include,
|
1026 |
+
member: include,
|
1027 |
+
inGroupsOf: inGroupsOf,
|
1028 |
+
inject: inject,
|
1029 |
+
invoke: invoke,
|
1030 |
+
max: max,
|
1031 |
+
min: min,
|
1032 |
+
partition: partition,
|
1033 |
+
pluck: pluck,
|
1034 |
+
reject: reject,
|
1035 |
+
sortBy: sortBy,
|
1036 |
+
toArray: toArray,
|
1037 |
+
entries: toArray,
|
1038 |
+
zip: zip,
|
1039 |
+
size: size,
|
1040 |
+
inspect: inspect,
|
1041 |
+
find: detect
|
1042 |
+
};
|
1043 |
+
})();
|
1044 |
+
|
1045 |
+
function $A(iterable) {
|
1046 |
+
if (!iterable) return [];
|
1047 |
+
if ('toArray' in Object(iterable)) return iterable.toArray();
|
1048 |
+
var length = iterable.length || 0, results = new Array(length);
|
1049 |
+
while (length--) results[length] = iterable[length];
|
1050 |
+
return results;
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
|
1054 |
+
function $w(string) {
|
1055 |
+
if (!Object.isString(string)) return [];
|
1056 |
+
string = string.strip();
|
1057 |
+
return string ? string.split(/\s+/) : [];
|
1058 |
+
}
|
1059 |
+
|
1060 |
+
Array.from = $A;
|
1061 |
+
|
1062 |
+
|
1063 |
+
(function() {
|
1064 |
+
var arrayProto = Array.prototype,
|
1065 |
+
slice = arrayProto.slice,
|
1066 |
+
_each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
|
1067 |
+
|
1068 |
+
function each(iterator, context) {
|
1069 |
+
for (var i = 0, length = this.length >>> 0; i < length; i++) {
|
1070 |
+
if (i in this) iterator.call(context, this[i], i, this);
|
1071 |
+
}
|
1072 |
+
}
|
1073 |
+
if (!_each) _each = each;
|
1074 |
+
|
1075 |
+
function clear() {
|
1076 |
+
this.length = 0;
|
1077 |
+
return this;
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
function first() {
|
1081 |
+
return this[0];
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
function last() {
|
1085 |
+
return this[this.length - 1];
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
function compact() {
|
1089 |
+
return this.select(function(value) {
|
1090 |
+
return value != null;
|
1091 |
+
});
|
1092 |
+
}
|
1093 |
+
|
1094 |
+
function flatten() {
|
1095 |
+
return this.inject([], function(array, value) {
|
1096 |
+
if (Object.isArray(value))
|
1097 |
+
return array.concat(value.flatten());
|
1098 |
+
array.push(value);
|
1099 |
+
return array;
|
1100 |
+
});
|
1101 |
+
}
|
1102 |
+
|
1103 |
+
function without() {
|
1104 |
+
var values = slice.call(arguments, 0);
|
1105 |
+
return this.select(function(value) {
|
1106 |
+
return !values.include(value);
|
1107 |
+
});
|
1108 |
+
}
|
1109 |
+
|
1110 |
+
function reverse(inline) {
|
1111 |
+
return (inline === false ? this.toArray() : this)._reverse();
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
function uniq(sorted) {
|
1115 |
+
return this.inject([], function(array, value, index) {
|
1116 |
+
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
|
1117 |
+
array.push(value);
|
1118 |
+
return array;
|
1119 |
+
});
|
1120 |
+
}
|
1121 |
+
|
1122 |
+
function intersect(array) {
|
1123 |
+
return this.uniq().findAll(function(item) {
|
1124 |
+
return array.detect(function(value) { return item === value });
|
1125 |
+
});
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
|
1129 |
+
function clone() {
|
1130 |
+
return slice.call(this, 0);
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
function size() {
|
1134 |
+
return this.length;
|
1135 |
+
}
|
1136 |
+
|
1137 |
+
function inspect() {
|
1138 |
+
return '[' + this.map(Object.inspect).join(', ') + ']';
|
1139 |
+
}
|
1140 |
+
|
1141 |
+
function indexOf(item, i) {
|
1142 |
+
i || (i = 0);
|
1143 |
+
var length = this.length;
|
1144 |
+
if (i < 0) i = length + i;
|
1145 |
+
for (; i < length; i++)
|
1146 |
+
if (this[i] === item) return i;
|
1147 |
+
return -1;
|
1148 |
+
}
|
1149 |
+
|
1150 |
+
function lastIndexOf(item, i) {
|
1151 |
+
i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
|
1152 |
+
var n = this.slice(0, i).reverse().indexOf(item);
|
1153 |
+
return (n < 0) ? n : i - n - 1;
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
function concat() {
|
1157 |
+
var array = slice.call(this, 0), item;
|
1158 |
+
for (var i = 0, length = arguments.length; i < length; i++) {
|
1159 |
+
item = arguments[i];
|
1160 |
+
if (Object.isArray(item) && !('callee' in item)) {
|
1161 |
+
for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
|
1162 |
+
array.push(item[j]);
|
1163 |
+
} else {
|
1164 |
+
array.push(item);
|
1165 |
+
}
|
1166 |
+
}
|
1167 |
+
return array;
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
Object.extend(arrayProto, Enumerable);
|
1171 |
+
|
1172 |
+
if (!arrayProto._reverse)
|
1173 |
+
arrayProto._reverse = arrayProto.reverse;
|
1174 |
+
|
1175 |
+
Object.extend(arrayProto, {
|
1176 |
+
_each: _each,
|
1177 |
+
clear: clear,
|
1178 |
+
first: first,
|
1179 |
+
last: last,
|
1180 |
+
compact: compact,
|
1181 |
+
flatten: flatten,
|
1182 |
+
without: without,
|
1183 |
+
reverse: reverse,
|
1184 |
+
uniq: uniq,
|
1185 |
+
intersect: intersect,
|
1186 |
+
clone: clone,
|
1187 |
+
toArray: clone,
|
1188 |
+
size: size,
|
1189 |
+
inspect: inspect
|
1190 |
+
});
|
1191 |
+
|
1192 |
+
var CONCAT_ARGUMENTS_BUGGY = (function() {
|
1193 |
+
return [].concat(arguments)[0][0] !== 1;
|
1194 |
+
})(1,2)
|
1195 |
+
|
1196 |
+
if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
|
1197 |
+
|
1198 |
+
if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
|
1199 |
+
if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
|
1200 |
+
})();
|
1201 |
+
function $H(object) {
|
1202 |
+
return new Hash(object);
|
1203 |
+
};
|
1204 |
+
|
1205 |
+
var Hash = Class.create(Enumerable, (function() {
|
1206 |
+
function initialize(object) {
|
1207 |
+
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
|
1208 |
+
}
|
1209 |
+
|
1210 |
+
|
1211 |
+
function _each(iterator) {
|
1212 |
+
for (var key in this._object) {
|
1213 |
+
var value = this._object[key], pair = [key, value];
|
1214 |
+
pair.key = key;
|
1215 |
+
pair.value = value;
|
1216 |
+
iterator(pair);
|
1217 |
+
}
|
1218 |
+
}
|
1219 |
+
|
1220 |
+
function set(key, value) {
|
1221 |
+
return this._object[key] = value;
|
1222 |
+
}
|
1223 |
+
|
1224 |
+
function get(key) {
|
1225 |
+
if (this._object[key] !== Object.prototype[key])
|
1226 |
+
return this._object[key];
|
1227 |
+
}
|
1228 |
+
|
1229 |
+
function unset(key) {
|
1230 |
+
var value = this._object[key];
|
1231 |
+
delete this._object[key];
|
1232 |
+
return value;
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
function toObject() {
|
1236 |
+
return Object.clone(this._object);
|
1237 |
+
}
|
1238 |
+
|
1239 |
+
|
1240 |
+
|
1241 |
+
function keys() {
|
1242 |
+
return this.pluck('key');
|
1243 |
+
}
|
1244 |
+
|
1245 |
+
function values() {
|
1246 |
+
return this.pluck('value');
|
1247 |
+
}
|
1248 |
+
|
1249 |
+
function index(value) {
|
1250 |
+
var match = this.detect(function(pair) {
|
1251 |
+
return pair.value === value;
|
1252 |
+
});
|
1253 |
+
return match && match.key;
|
1254 |
+
}
|
1255 |
+
|
1256 |
+
function merge(object) {
|
1257 |
+
return this.clone().update(object);
|
1258 |
+
}
|
1259 |
+
|
1260 |
+
function update(object) {
|
1261 |
+
return new Hash(object).inject(this, function(result, pair) {
|
1262 |
+
result.set(pair.key, pair.value);
|
1263 |
+
return result;
|
1264 |
+
});
|
1265 |
+
}
|
1266 |
+
|
1267 |
+
function toQueryPair(key, value) {
|
1268 |
+
if (Object.isUndefined(value)) return key;
|
1269 |
+
return key + '=' + encodeURIComponent(String.interpret(value));
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
function toQueryString() {
|
1273 |
+
return this.inject([], function(results, pair) {
|
1274 |
+
var key = encodeURIComponent(pair.key), values = pair.value;
|
1275 |
+
|
1276 |
+
if (values && typeof values == 'object') {
|
1277 |
+
if (Object.isArray(values)) {
|
1278 |
+
var queryValues = [];
|
1279 |
+
for (var i = 0, len = values.length, value; i < len; i++) {
|
1280 |
+
value = values[i];
|
1281 |
+
queryValues.push(toQueryPair(key, value));
|
1282 |
+
}
|
1283 |
+
return results.concat(queryValues);
|
1284 |
+
}
|
1285 |
+
} else results.push(toQueryPair(key, values));
|
1286 |
+
return results;
|
1287 |
+
}).join('&');
|
1288 |
+
}
|
1289 |
+
|
1290 |
+
function inspect() {
|
1291 |
+
return '#<Hash:{' + this.map(function(pair) {
|
1292 |
+
return pair.map(Object.inspect).join(': ');
|
1293 |
+
}).join(', ') + '}>';
|
1294 |
+
}
|
1295 |
+
|
1296 |
+
function clone() {
|
1297 |
+
return new Hash(this);
|
1298 |
+
}
|
1299 |
+
|
1300 |
+
return {
|
1301 |
+
initialize: initialize,
|
1302 |
+
_each: _each,
|
1303 |
+
set: set,
|
1304 |
+
get: get,
|
1305 |
+
unset: unset,
|
1306 |
+
toObject: toObject,
|
1307 |
+
toTemplateReplacements: toObject,
|
1308 |
+
keys: keys,
|
1309 |
+
values: values,
|
1310 |
+
index: index,
|
1311 |
+
merge: merge,
|
1312 |
+
update: update,
|
1313 |
+
toQueryString: toQueryString,
|
1314 |
+
inspect: inspect,
|
1315 |
+
toJSON: toObject,
|
1316 |
+
clone: clone
|
1317 |
+
};
|
1318 |
+
})());
|
1319 |
+
|
1320 |
+
Hash.from = $H;
|
1321 |
+
Object.extend(Number.prototype, (function() {
|
1322 |
+
function toColorPart() {
|
1323 |
+
return this.toPaddedString(2, 16);
|
1324 |
+
}
|
1325 |
+
|
1326 |
+
function succ() {
|
1327 |
+
return this + 1;
|
1328 |
+
}
|
1329 |
+
|
1330 |
+
function times(iterator, context) {
|
1331 |
+
$R(0, this, true).each(iterator, context);
|
1332 |
+
return this;
|
1333 |
+
}
|
1334 |
+
|
1335 |
+
function toPaddedString(length, radix) {
|
1336 |
+
var string = this.toString(radix || 10);
|
1337 |
+
return '0'.times(length - string.length) + string;
|
1338 |
+
}
|
1339 |
+
|
1340 |
+
function abs() {
|
1341 |
+
return Math.abs(this);
|
1342 |
+
}
|
1343 |
+
|
1344 |
+
function round() {
|
1345 |
+
return Math.round(this);
|
1346 |
+
}
|
1347 |
+
|
1348 |
+
function ceil() {
|
1349 |
+
return Math.ceil(this);
|
1350 |
+
}
|
1351 |
+
|
1352 |
+
function floor() {
|
1353 |
+
return Math.floor(this);
|
1354 |
+
}
|
1355 |
+
|
1356 |
+
return {
|
1357 |
+
toColorPart: toColorPart,
|
1358 |
+
succ: succ,
|
1359 |
+
times: times,
|
1360 |
+
toPaddedString: toPaddedString,
|
1361 |
+
abs: abs,
|
1362 |
+
round: round,
|
1363 |
+
ceil: ceil,
|
1364 |
+
floor: floor
|
1365 |
+
};
|
1366 |
+
})());
|
1367 |
+
|
1368 |
+
function $R(start, end, exclusive) {
|
1369 |
+
return new ObjectRange(start, end, exclusive);
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
var ObjectRange = Class.create(Enumerable, (function() {
|
1373 |
+
function initialize(start, end, exclusive) {
|
1374 |
+
this.start = start;
|
1375 |
+
this.end = end;
|
1376 |
+
this.exclusive = exclusive;
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
function _each(iterator) {
|
1380 |
+
var value = this.start;
|
1381 |
+
while (this.include(value)) {
|
1382 |
+
iterator(value);
|
1383 |
+
value = value.succ();
|
1384 |
+
}
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
function include(value) {
|
1388 |
+
if (value < this.start)
|
1389 |
+
return false;
|
1390 |
+
if (this.exclusive)
|
1391 |
+
return value < this.end;
|
1392 |
+
return value <= this.end;
|
1393 |
+
}
|
1394 |
+
|
1395 |
+
return {
|
1396 |
+
initialize: initialize,
|
1397 |
+
_each: _each,
|
1398 |
+
include: include
|
1399 |
+
};
|
1400 |
+
})());
|
1401 |
+
|
1402 |
+
|
1403 |
+
|
1404 |
+
var Abstract = { };
|
1405 |
+
|
1406 |
+
|
1407 |
+
var Try = {
|
1408 |
+
these: function() {
|
1409 |
+
var returnValue;
|
1410 |
+
|
1411 |
+
for (var i = 0, length = arguments.length; i < length; i++) {
|
1412 |
+
var lambda = arguments[i];
|
1413 |
+
try {
|
1414 |
+
returnValue = lambda();
|
1415 |
+
break;
|
1416 |
+
} catch (e) { }
|
1417 |
+
}
|
1418 |
+
|
1419 |
+
return returnValue;
|
1420 |
+
}
|
1421 |
+
};
|
1422 |
+
|
1423 |
+
var Ajax = {
|
1424 |
+
getTransport: function() {
|
1425 |
+
return Try.these(
|
1426 |
+
function() {return new XMLHttpRequest()},
|
1427 |
+
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
|
1428 |
+
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
|
1429 |
+
) || false;
|
1430 |
+
},
|
1431 |
+
|
1432 |
+
activeRequestCount: 0
|
1433 |
+
};
|
1434 |
+
|
1435 |
+
Ajax.Responders = {
|
1436 |
+
responders: [],
|
1437 |
+
|
1438 |
+
_each: function(iterator) {
|
1439 |
+
this.responders._each(iterator);
|
1440 |
+
},
|
1441 |
+
|
1442 |
+
register: function(responder) {
|
1443 |
+
if (!this.include(responder))
|
1444 |
+
this.responders.push(responder);
|
1445 |
+
},
|
1446 |
+
|
1447 |
+
unregister: function(responder) {
|
1448 |
+
this.responders = this.responders.without(responder);
|
1449 |
+
},
|
1450 |
+
|
1451 |
+
dispatch: function(callback, request, transport, json) {
|
1452 |
+
this.each(function(responder) {
|
1453 |
+
if (Object.isFunction(responder[callback])) {
|
1454 |
+
try {
|
1455 |
+
responder[callback].apply(responder, [request, transport, json]);
|
1456 |
+
} catch (e) { }
|
1457 |
+
}
|
1458 |
+
});
|
1459 |
+
}
|
1460 |
+
};
|
1461 |
+
|
1462 |
+
Object.extend(Ajax.Responders, Enumerable);
|
1463 |
+
|
1464 |
+
Ajax.Responders.register({
|
1465 |
+
onCreate: function() { Ajax.activeRequestCount++ },
|
1466 |
+
onComplete: function() { Ajax.activeRequestCount-- }
|
1467 |
+
});
|
1468 |
+
Ajax.Base = Class.create({
|
1469 |
+
initialize: function(options) {
|
1470 |
+
this.options = {
|
1471 |
+
method: 'post',
|
1472 |
+
asynchronous: true,
|
1473 |
+
contentType: 'application/x-www-form-urlencoded',
|
1474 |
+
encoding: 'UTF-8',
|
1475 |
+
parameters: '',
|
1476 |
+
evalJSON: true,
|
1477 |
+
evalJS: true
|
1478 |
+
};
|
1479 |
+
Object.extend(this.options, options || { });
|
1480 |
+
|
1481 |
+
this.options.method = this.options.method.toLowerCase();
|
1482 |
+
|
1483 |
+
if (Object.isHash(this.options.parameters))
|
1484 |
+
this.options.parameters = this.options.parameters.toObject();
|
1485 |
+
}
|
1486 |
+
});
|
1487 |
+
Ajax.Request = Class.create(Ajax.Base, {
|
1488 |
+
_complete: false,
|
1489 |
+
|
1490 |
+
initialize: function($super, url, options) {
|
1491 |
+
$super(options);
|
1492 |
+
this.transport = Ajax.getTransport();
|
1493 |
+
this.request(url);
|
1494 |
+
},
|
1495 |
+
|
1496 |
+
request: function(url) {
|
1497 |
+
this.url = url;
|
1498 |
+
this.method = this.options.method;
|
1499 |
+
var params = Object.isString(this.options.parameters) ?
|
1500 |
+
this.options.parameters :
|
1501 |
+
Object.toQueryString(this.options.parameters);
|
1502 |
+
|
1503 |
+
if (!['get', 'post'].include(this.method)) {
|
1504 |
+
params += (params ? '&' : '') + "_method=" + this.method;
|
1505 |
+
this.method = 'post';
|
1506 |
+
}
|
1507 |
+
|
1508 |
+
if (params && this.method === 'get') {
|
1509 |
+
this.url += (this.url.include('?') ? '&' : '?') + params;
|
1510 |
+
}
|
1511 |
+
|
1512 |
+
this.parameters = params.toQueryParams();
|
1513 |
+
|
1514 |
+
try {
|
1515 |
+
var response = new Ajax.Response(this);
|
1516 |
+
if (this.options.onCreate) this.options.onCreate(response);
|
1517 |
+
Ajax.Responders.dispatch('onCreate', this, response);
|
1518 |
+
|
1519 |
+
this.transport.open(this.method.toUpperCase(), this.url,
|
1520 |
+
this.options.asynchronous);
|
1521 |
+
|
1522 |
+
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
|
1523 |
+
|
1524 |
+
this.transport.onreadystatechange = this.onStateChange.bind(this);
|
1525 |
+
this.setRequestHeaders();
|
1526 |
+
|
1527 |
+
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
|
1528 |
+
this.transport.send(this.body);
|
1529 |
+
|
1530 |
+
/* Force Firefox to handle ready state 4 for synchronous requests */
|
1531 |
+
if (!this.options.asynchronous && this.transport.overrideMimeType)
|
1532 |
+
this.onStateChange();
|
1533 |
+
|
1534 |
+
}
|
1535 |
+
catch (e) {
|
1536 |
+
this.dispatchException(e);
|
1537 |
+
}
|
1538 |
+
},
|
1539 |
+
|
1540 |
+
onStateChange: function() {
|
1541 |
+
var readyState = this.transport.readyState;
|
1542 |
+
if (readyState > 1 && !((readyState == 4) && this._complete))
|
1543 |
+
this.respondToReadyState(this.transport.readyState);
|
1544 |
+
},
|
1545 |
+
|
1546 |
+
setRequestHeaders: function() {
|
1547 |
+
var headers = {
|
1548 |
+
'X-Requested-With': 'XMLHttpRequest',
|
1549 |
+
'X-Prototype-Version': Prototype.Version,
|
1550 |
+
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
|
1551 |
+
};
|
1552 |
+
|
1553 |
+
if (this.method == 'post') {
|
1554 |
+
headers['Content-type'] = this.options.contentType +
|
1555 |
+
(this.options.encoding ? '; charset=' + this.options.encoding : '');
|
1556 |
+
|
1557 |
+
/* Force "Connection: close" for older Mozilla browsers to work
|
1558 |
+
* around a bug where XMLHttpRequest sends an incorrect
|
1559 |
+
* Content-length header. See Mozilla Bugzilla #246651.
|
1560 |
+
*/
|
1561 |
+
if (this.transport.overrideMimeType &&
|
1562 |
+
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
|
1563 |
+
headers['Connection'] = 'close';
|
1564 |
+
}
|
1565 |
+
|
1566 |
+
if (typeof this.options.requestHeaders == 'object') {
|
1567 |
+
var extras = this.options.requestHeaders;
|
1568 |
+
|
1569 |
+
if (Object.isFunction(extras.push))
|
1570 |
+
for (var i = 0, length = extras.length; i < length; i += 2)
|
1571 |
+
headers[extras[i]] = extras[i+1];
|
1572 |
+
else
|
1573 |
+
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
|
1574 |
+
}
|
1575 |
+
|
1576 |
+
for (var name in headers)
|
1577 |
+
this.transport.setRequestHeader(name, headers[name]);
|
1578 |
+
},
|
1579 |
+
|
1580 |
+
success: function() {
|
1581 |
+
var status = this.getStatus();
|
1582 |
+
return !status || (status >= 200 && status < 300) || status == 304;
|
1583 |
+
},
|
1584 |
+
|
1585 |
+
getStatus: function() {
|
1586 |
+
try {
|
1587 |
+
if (this.transport.status === 1223) return 204;
|
1588 |
+
return this.transport.status || 0;
|
1589 |
+
} catch (e) { return 0 }
|
1590 |
+
},
|
1591 |
+
|
1592 |
+
respondToReadyState: function(readyState) {
|
1593 |
+
var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
|
1594 |
+
|
1595 |
+
if (state == 'Complete') {
|
1596 |
+
try {
|
1597 |
+
this._complete = true;
|
1598 |
+
(this.options['on' + response.status]
|
1599 |
+
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|
1600 |
+
|| Prototype.emptyFunction)(response, response.headerJSON);
|
1601 |
+
} catch (e) {
|
1602 |
+
this.dispatchException(e);
|
1603 |
+
}
|
1604 |
+
|
1605 |
+
var contentType = response.getHeader('Content-type');
|
1606 |
+
if (this.options.evalJS == 'force'
|
1607 |
+
|| (this.options.evalJS && this.isSameOrigin() && contentType
|
1608 |
+
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
|
1609 |
+
this.evalResponse();
|
1610 |
+
}
|
1611 |
+
|
1612 |
+
try {
|
1613 |
+
(this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
|
1614 |
+
Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
|
1615 |
+
} catch (e) {
|
1616 |
+
this.dispatchException(e);
|
1617 |
+
}
|
1618 |
+
|
1619 |
+
if (state == 'Complete') {
|
1620 |
+
this.transport.onreadystatechange = Prototype.emptyFunction;
|
1621 |
+
}
|
1622 |
+
},
|
1623 |
+
|
1624 |
+
isSameOrigin: function() {
|
1625 |
+
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
|
1626 |
+
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
|
1627 |
+
protocol: location.protocol,
|
1628 |
+
domain: document.domain,
|
1629 |
+
port: location.port ? ':' + location.port : ''
|
1630 |
+
}));
|
1631 |
+
},
|
1632 |
+
|
1633 |
+
getHeader: function(name) {
|
1634 |
+
try {
|
1635 |
+
return this.transport.getResponseHeader(name) || null;
|
1636 |
+
} catch (e) { return null; }
|
1637 |
+
},
|
1638 |
+
|
1639 |
+
evalResponse: function() {
|
1640 |
+
try {
|
1641 |
+
return eval((this.transport.responseText || '').unfilterJSON());
|
1642 |
+
} catch (e) {
|
1643 |
+
this.dispatchException(e);
|
1644 |
+
}
|
1645 |
+
},
|
1646 |
+
|
1647 |
+
dispatchException: function(exception) {
|
1648 |
+
(this.options.onException || Prototype.emptyFunction)(this, exception);
|
1649 |
+
Ajax.Responders.dispatch('onException', this, exception);
|
1650 |
+
}
|
1651 |
+
});
|
1652 |
+
|
1653 |
+
Ajax.Request.Events =
|
1654 |
+
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
|
1655 |
+
|
1656 |
+
|
1657 |
+
|
1658 |
+
|
1659 |
+
|
1660 |
+
|
1661 |
+
|
1662 |
+
|
1663 |
+
Ajax.Response = Class.create({
|
1664 |
+
initialize: function(request){
|
1665 |
+
this.request = request;
|
1666 |
+
var transport = this.transport = request.transport,
|
1667 |
+
readyState = this.readyState = transport.readyState;
|
1668 |
+
|
1669 |
+
if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
|
1670 |
+
this.status = this.getStatus();
|
1671 |
+
this.statusText = this.getStatusText();
|
1672 |
+
this.responseText = String.interpret(transport.responseText);
|
1673 |
+
this.headerJSON = this._getHeaderJSON();
|
1674 |
+
}
|
1675 |
+
|
1676 |
+
if (readyState == 4) {
|
1677 |
+
var xml = transport.responseXML;
|
1678 |
+
this.responseXML = Object.isUndefined(xml) ? null : xml;
|
1679 |
+
this.responseJSON = this._getResponseJSON();
|
1680 |
+
}
|
1681 |
+
},
|
1682 |
+
|
1683 |
+
status: 0,
|
1684 |
+
|
1685 |
+
statusText: '',
|
1686 |
+
|
1687 |
+
getStatus: Ajax.Request.prototype.getStatus,
|
1688 |
+
|
1689 |
+
getStatusText: function() {
|
1690 |
+
try {
|
1691 |
+
return this.transport.statusText || '';
|
1692 |
+
} catch (e) { return '' }
|
1693 |
+
},
|
1694 |
+
|
1695 |
+
getHeader: Ajax.Request.prototype.getHeader,
|
1696 |
+
|
1697 |
+
getAllHeaders: function() {
|
1698 |
+
try {
|
1699 |
+
return this.getAllResponseHeaders();
|
1700 |
+
} catch (e) { return null }
|
1701 |
+
},
|
1702 |
+
|
1703 |
+
getResponseHeader: function(name) {
|
1704 |
+
return this.transport.getResponseHeader(name);
|
1705 |
+
},
|
1706 |
+
|
1707 |
+
getAllResponseHeaders: function() {
|
1708 |
+
return this.transport.getAllResponseHeaders();
|
1709 |
+
},
|
1710 |
+
|
1711 |
+
_getHeaderJSON: function() {
|
1712 |
+
var json = this.getHeader('X-JSON');
|
1713 |
+
if (!json) return null;
|
1714 |
+
json = decodeURIComponent(escape(json));
|
1715 |
+
try {
|
1716 |
+
return json.evalJSON(this.request.options.sanitizeJSON ||
|
1717 |
+
!this.request.isSameOrigin());
|
1718 |
+
} catch (e) {
|
1719 |
+
this.request.dispatchException(e);
|
1720 |
+
}
|
1721 |
+
},
|
1722 |
+
|
1723 |
+
_getResponseJSON: function() {
|
1724 |
+
var options = this.request.options;
|
1725 |
+
if (!options.evalJSON || (options.evalJSON != 'force' &&
|
1726 |
+
!(this.getHeader('Content-type') || '').include('application/json')) ||
|
1727 |
+
this.responseText.blank())
|
1728 |
+
return null;
|
1729 |
+
try {
|
1730 |
+
return this.responseText.evalJSON(options.sanitizeJSON ||
|
1731 |
+
!this.request.isSameOrigin());
|
1732 |
+
} catch (e) {
|
1733 |
+
this.request.dispatchException(e);
|
1734 |
+
}
|
1735 |
+
}
|
1736 |
+
});
|
1737 |
+
|
1738 |
+
Ajax.Updater = Class.create(Ajax.Request, {
|
1739 |
+
initialize: function($super, container, url, options) {
|
1740 |
+
this.container = {
|
1741 |
+
success: (container.success || container),
|
1742 |
+
failure: (container.failure || (container.success ? null : container))
|
1743 |
+
};
|
1744 |
+
|
1745 |
+
options = Object.clone(options);
|
1746 |
+
var onComplete = options.onComplete;
|
1747 |
+
options.onComplete = (function(response, json) {
|
1748 |
+
this.updateContent(response.responseText);
|
1749 |
+
if (Object.isFunction(onComplete)) onComplete(response, json);
|
1750 |
+
}).bind(this);
|
1751 |
+
|
1752 |
+
$super(url, options);
|
1753 |
+
},
|
1754 |
+
|
1755 |
+
updateContent: function(responseText) {
|
1756 |
+
var receiver = this.container[this.success() ? 'success' : 'failure'],
|
1757 |
+
options = this.options;
|
1758 |
+
|
1759 |
+
if (!options.evalScripts) responseText = responseText.stripScripts();
|
1760 |
+
|
1761 |
+
if (receiver = $(receiver)) {
|
1762 |
+
if (options.insertion) {
|
1763 |
+
if (Object.isString(options.insertion)) {
|
1764 |
+
var insertion = { }; insertion[options.insertion] = responseText;
|
1765 |
+
receiver.insert(insertion);
|
1766 |
+
}
|
1767 |
+
else options.insertion(receiver, responseText);
|
1768 |
+
}
|
1769 |
+
else receiver.update(responseText);
|
1770 |
+
}
|
1771 |
+
}
|
1772 |
+
});
|
1773 |
+
|
1774 |
+
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
|
1775 |
+
initialize: function($super, container, url, options) {
|
1776 |
+
$super(options);
|
1777 |
+
this.onComplete = this.options.onComplete;
|
1778 |
+
|
1779 |
+
this.frequency = (this.options.frequency || 2);
|
1780 |
+
this.decay = (this.options.decay || 1);
|
1781 |
+
|
1782 |
+
this.updater = { };
|
1783 |
+
this.container = container;
|
1784 |
+
this.url = url;
|
1785 |
+
|
1786 |
+
this.start();
|
1787 |
+
},
|
1788 |
+
|
1789 |
+
start: function() {
|
1790 |
+
this.options.onComplete = this.updateComplete.bind(this);
|
1791 |
+
this.onTimerEvent();
|
1792 |
+
},
|
1793 |
+
|
1794 |
+
stop: function() {
|
1795 |
+
this.updater.options.onComplete = undefined;
|
1796 |
+
clearTimeout(this.timer);
|
1797 |
+
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
|
1798 |
+
},
|
1799 |
+
|
1800 |
+
updateComplete: function(response) {
|
1801 |
+
if (this.options.decay) {
|
1802 |
+
this.decay = (response.responseText == this.lastText ?
|
1803 |
+
this.decay * this.options.decay : 1);
|
1804 |
+
|
1805 |
+
this.lastText = response.responseText;
|
1806 |
+
}
|
1807 |
+
this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
|
1808 |
+
},
|
1809 |
+
|
1810 |
+
onTimerEvent: function() {
|
1811 |
+
this.updater = new Ajax.Updater(this.container, this.url, this.options);
|
1812 |
+
}
|
1813 |
+
});
|
1814 |
+
|
1815 |
+
|
1816 |
+
function $(element) {
|
1817 |
+
if (arguments.length > 1) {
|
1818 |
+
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
|
1819 |
+
elements.push($(arguments[i]));
|
1820 |
+
return elements;
|
1821 |
+
}
|
1822 |
+
if (Object.isString(element))
|
1823 |
+
element = document.getElementById(element);
|
1824 |
+
return Element.extend(element);
|
1825 |
+
}
|
1826 |
+
|
1827 |
+
if (Prototype.BrowserFeatures.XPath) {
|
1828 |
+
document._getElementsByXPath = function(expression, parentElement) {
|
1829 |
+
var results = [];
|
1830 |
+
var query = document.evaluate(expression, $(parentElement) || document,
|
1831 |
+
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
1832 |
+
for (var i = 0, length = query.snapshotLength; i < length; i++)
|
1833 |
+
results.push(Element.extend(query.snapshotItem(i)));
|
1834 |
+
return results;
|
1835 |
+
};
|
1836 |
+
}
|
1837 |
+
|
1838 |
+
/*--------------------------------------------------------------------------*/
|
1839 |
+
|
1840 |
+
if (!Node) var Node = { };
|
1841 |
+
|
1842 |
+
if (!Node.ELEMENT_NODE) {
|
1843 |
+
Object.extend(Node, {
|
1844 |
+
ELEMENT_NODE: 1,
|
1845 |
+
ATTRIBUTE_NODE: 2,
|
1846 |
+
TEXT_NODE: 3,
|
1847 |
+
CDATA_SECTION_NODE: 4,
|
1848 |
+
ENTITY_REFERENCE_NODE: 5,
|
1849 |
+
ENTITY_NODE: 6,
|
1850 |
+
PROCESSING_INSTRUCTION_NODE: 7,
|
1851 |
+
COMMENT_NODE: 8,
|
1852 |
+
DOCUMENT_NODE: 9,
|
1853 |
+
DOCUMENT_TYPE_NODE: 10,
|
1854 |
+
DOCUMENT_FRAGMENT_NODE: 11,
|
1855 |
+
NOTATION_NODE: 12
|
1856 |
+
});
|
1857 |
+
}
|
1858 |
+
|
1859 |
+
|
1860 |
+
|
1861 |
+
(function(global) {
|
1862 |
+
function shouldUseCache(tagName, attributes) {
|
1863 |
+
if (tagName === 'select') return false;
|
1864 |
+
if ('type' in attributes) return false;
|
1865 |
+
return true;
|
1866 |
+
}
|
1867 |
+
|
1868 |
+
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
|
1869 |
+
try {
|
1870 |
+
var el = document.createElement('<input name="x">');
|
1871 |
+
return el.tagName.toLowerCase() === 'input' && el.name === 'x';
|
1872 |
+
}
|
1873 |
+
catch(err) {
|
1874 |
+
return false;
|
1875 |
+
}
|
1876 |
+
})();
|
1877 |
+
|
1878 |
+
var element = global.Element;
|
1879 |
+
|
1880 |
+
global.Element = function(tagName, attributes) {
|
1881 |
+
attributes = attributes || { };
|
1882 |
+
tagName = tagName.toLowerCase();
|
1883 |
+
var cache = Element.cache;
|
1884 |
+
|
1885 |
+
if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
|
1886 |
+
tagName = '<' + tagName + ' name="' + attributes.name + '">';
|
1887 |
+
delete attributes.name;
|
1888 |
+
return Element.writeAttribute(document.createElement(tagName), attributes);
|
1889 |
+
}
|
1890 |
+
|
1891 |
+
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
|
1892 |
+
|
1893 |
+
var node = shouldUseCache(tagName, attributes) ?
|
1894 |
+
cache[tagName].cloneNode(false) : document.createElement(tagName);
|
1895 |
+
|
1896 |
+
return Element.writeAttribute(node, attributes);
|
1897 |
+
};
|
1898 |
+
|
1899 |
+
Object.extend(global.Element, element || { });
|
1900 |
+
if (element) global.Element.prototype = element.prototype;
|
1901 |
+
|
1902 |
+
})(this);
|
1903 |
+
|
1904 |
+
Element.idCounter = 1;
|
1905 |
+
Element.cache = { };
|
1906 |
+
|
1907 |
+
Element._purgeElement = function(element) {
|
1908 |
+
var uid = element._prototypeUID;
|
1909 |
+
if (uid) {
|
1910 |
+
Element.stopObserving(element);
|
1911 |
+
element._prototypeUID = void 0;
|
1912 |
+
delete Element.Storage[uid];
|
1913 |
+
}
|
1914 |
+
}
|
1915 |
+
|
1916 |
+
Element.Methods = {
|
1917 |
+
visible: function(element) {
|
1918 |
+
return $(element).style.display != 'none';
|
1919 |
+
},
|
1920 |
+
|
1921 |
+
toggle: function(element) {
|
1922 |
+
element = $(element);
|
1923 |
+
Element[Element.visible(element) ? 'hide' : 'show'](element);
|
1924 |
+
return element;
|
1925 |
+
},
|
1926 |
+
|
1927 |
+
hide: function(element) {
|
1928 |
+
element = $(element);
|
1929 |
+
element.style.display = 'none';
|
1930 |
+
return element;
|
1931 |
+
},
|
1932 |
+
|
1933 |
+
show: function(element) {
|
1934 |
+
element = $(element);
|
1935 |
+
element.style.display = '';
|
1936 |
+
return element;
|
1937 |
+
},
|
1938 |
+
|
1939 |
+
remove: function(element) {
|
1940 |
+
element = $(element);
|
1941 |
+
element.parentNode.removeChild(element);
|
1942 |
+
return element;
|
1943 |
+
},
|
1944 |
+
|
1945 |
+
update: (function(){
|
1946 |
+
|
1947 |
+
var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
|
1948 |
+
var el = document.createElement("select"),
|
1949 |
+
isBuggy = true;
|
1950 |
+
el.innerHTML = "<option value=\"test\">test</option>";
|
1951 |
+
if (el.options && el.options[0]) {
|
1952 |
+
isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
|
1953 |
+
}
|
1954 |
+
el = null;
|
1955 |
+
return isBuggy;
|
1956 |
+
})();
|
1957 |
+
|
1958 |
+
var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
|
1959 |
+
try {
|
1960 |
+
var el = document.createElement("table");
|
1961 |
+
if (el && el.tBodies) {
|
1962 |
+
el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
|
1963 |
+
var isBuggy = typeof el.tBodies[0] == "undefined";
|
1964 |
+
el = null;
|
1965 |
+
return isBuggy;
|
1966 |
+
}
|
1967 |
+
} catch (e) {
|
1968 |
+
return true;
|
1969 |
+
}
|
1970 |
+
})();
|
1971 |
+
|
1972 |
+
var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
|
1973 |
+
try {
|
1974 |
+
var el = document.createElement('div');
|
1975 |
+
el.innerHTML = "<link>";
|
1976 |
+
var isBuggy = (el.childNodes.length === 0);
|
1977 |
+
el = null;
|
1978 |
+
return isBuggy;
|
1979 |
+
} catch(e) {
|
1980 |
+
return true;
|
1981 |
+
}
|
1982 |
+
})();
|
1983 |
+
|
1984 |
+
var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
|
1985 |
+
TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
|
1986 |
+
|
1987 |
+
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
|
1988 |
+
var s = document.createElement("script"),
|
1989 |
+
isBuggy = false;
|
1990 |
+
try {
|
1991 |
+
s.appendChild(document.createTextNode(""));
|
1992 |
+
isBuggy = !s.firstChild ||
|
1993 |
+
s.firstChild && s.firstChild.nodeType !== 3;
|
1994 |
+
} catch (e) {
|
1995 |
+
isBuggy = true;
|
1996 |
+
}
|
1997 |
+
s = null;
|
1998 |
+
return isBuggy;
|
1999 |
+
})();
|
2000 |
+
|
2001 |
+
|
2002 |
+
function update(element, content) {
|
2003 |
+
element = $(element);
|
2004 |
+
var purgeElement = Element._purgeElement;
|
2005 |
+
|
2006 |
+
var descendants = element.getElementsByTagName('*'),
|
2007 |
+
i = descendants.length;
|
2008 |
+
while (i--) purgeElement(descendants[i]);
|
2009 |
+
|
2010 |
+
if (content && content.toElement)
|
2011 |
+
content = content.toElement();
|
2012 |
+
|
2013 |
+
if (Object.isElement(content))
|
2014 |
+
return element.update().insert(content);
|
2015 |
+
|
2016 |
+
content = Object.toHTML(content);
|
2017 |
+
|
2018 |
+
var tagName = element.tagName.toUpperCase();
|
2019 |
+
|
2020 |
+
if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
|
2021 |
+
element.text = content;
|
2022 |
+
return element;
|
2023 |
+
}
|
2024 |
+
|
2025 |
+
if (ANY_INNERHTML_BUGGY) {
|
2026 |
+
if (tagName in Element._insertionTranslations.tags) {
|
2027 |
+
while (element.firstChild) {
|
2028 |
+
element.removeChild(element.firstChild);
|
2029 |
+
}
|
2030 |
+
Element._getContentFromAnonymousElement(tagName, content.stripScripts())
|
2031 |
+
.each(function(node) {
|
2032 |
+
element.appendChild(node)
|
2033 |
+
});
|
2034 |
+
} else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
|
2035 |
+
while (element.firstChild) {
|
2036 |
+
element.removeChild(element.firstChild);
|
2037 |
+
}
|
2038 |
+
var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
|
2039 |
+
nodes.each(function(node) { element.appendChild(node) });
|
2040 |
+
}
|
2041 |
+
else {
|
2042 |
+
element.innerHTML = content.stripScripts();
|
2043 |
+
}
|
2044 |
+
}
|
2045 |
+
else {
|
2046 |
+
element.innerHTML = content.stripScripts();
|
2047 |
+
}
|
2048 |
+
|
2049 |
+
content.evalScripts.bind(content).defer();
|
2050 |
+
return element;
|
2051 |
+
}
|
2052 |
+
|
2053 |
+
return update;
|
2054 |
+
})(),
|
2055 |
+
|
2056 |
+
replace: function(element, content) {
|
2057 |
+
element = $(element);
|
2058 |
+
if (content && content.toElement) content = content.toElement();
|
2059 |
+
else if (!Object.isElement(content)) {
|
2060 |
+
content = Object.toHTML(content);
|
2061 |
+
var range = element.ownerDocument.createRange();
|
2062 |
+
range.selectNode(element);
|
2063 |
+
content.evalScripts.bind(content).defer();
|
2064 |
+
content = range.createContextualFragment(content.stripScripts());
|
2065 |
+
}
|
2066 |
+
element.parentNode.replaceChild(content, element);
|
2067 |
+
return element;
|
2068 |
+
},
|
2069 |
+
|
2070 |
+
insert: function(element, insertions) {
|
2071 |
+
element = $(element);
|
2072 |
+
|
2073 |
+
if (Object.isString(insertions) || Object.isNumber(insertions) ||
|
2074 |
+
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
|
2075 |
+
insertions = {bottom:insertions};
|
2076 |
+
|
2077 |
+
var content, insert, tagName, childNodes;
|
2078 |
+
|
2079 |
+
for (var position in insertions) {
|
2080 |
+
content = insertions[position];
|
2081 |
+
position = position.toLowerCase();
|
2082 |
+
insert = Element._insertionTranslations[position];
|
2083 |
+
|
2084 |
+
if (content && content.toElement) content = content.toElement();
|
2085 |
+
if (Object.isElement(content)) {
|
2086 |
+
insert(element, content);
|
2087 |
+
continue;
|
2088 |
+
}
|
2089 |
+
|
2090 |
+
content = Object.toHTML(content);
|
2091 |
+
|
2092 |
+
tagName = ((position == 'before' || position == 'after')
|
2093 |
+
? element.parentNode : element).tagName.toUpperCase();
|
2094 |
+
|
2095 |
+
childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
|
2096 |
+
|
2097 |
+
if (position == 'top' || position == 'after') childNodes.reverse();
|
2098 |
+
childNodes.each(insert.curry(element));
|
2099 |
+
|
2100 |
+
content.evalScripts.bind(content).defer();
|
2101 |
+
}
|
2102 |
+
|
2103 |
+
return element;
|
2104 |
+
},
|
2105 |
+
|
2106 |
+
wrap: function(element, wrapper, attributes) {
|
2107 |
+
element = $(element);
|
2108 |
+
if (Object.isElement(wrapper))
|
2109 |
+
$(wrapper).writeAttribute(attributes || { });
|
2110 |
+
else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
|
2111 |
+
else wrapper = new Element('div', wrapper);
|
2112 |
+
if (element.parentNode)
|
2113 |
+
element.parentNode.replaceChild(wrapper, element);
|
2114 |
+
wrapper.appendChild(element);
|
2115 |
+
return wrapper;
|
2116 |
+
},
|
2117 |
+
|
2118 |
+
inspect: function(element) {
|
2119 |
+
element = $(element);
|
2120 |
+
var result = '<' + element.tagName.toLowerCase();
|
2121 |
+
$H({'id': 'id', 'className': 'class'}).each(function(pair) {
|
2122 |
+
var property = pair.first(),
|
2123 |
+
attribute = pair.last(),
|
2124 |
+
value = (element[property] || '').toString();
|
2125 |
+
if (value) result += ' ' + attribute + '=' + value.inspect(true);
|
2126 |
+
});
|
2127 |
+
return result + '>';
|
2128 |
+
},
|
2129 |
+
|
2130 |
+
recursivelyCollect: function(element, property, maximumLength) {
|
2131 |
+
element = $(element);
|
2132 |
+
maximumLength = maximumLength || -1;
|
2133 |
+
var elements = [];
|
2134 |
+
|
2135 |
+
while (element = element[property]) {
|
2136 |
+
if (element.nodeType == 1)
|
2137 |
+
elements.push(Element.extend(element));
|
2138 |
+
if (elements.length == maximumLength)
|
2139 |
+
break;
|
2140 |
+
}
|
2141 |
+
|
2142 |
+
return elements;
|
2143 |
+
},
|
2144 |
+
|
2145 |
+
ancestors: function(element) {
|
2146 |
+
return Element.recursivelyCollect(element, 'parentNode');
|
2147 |
+
},
|
2148 |
+
|
2149 |
+
descendants: function(element) {
|
2150 |
+
return Element.select(element, "*");
|
2151 |
+
},
|
2152 |
+
|
2153 |
+
firstDescendant: function(element) {
|
2154 |
+
element = $(element).firstChild;
|
2155 |
+
while (element && element.nodeType != 1) element = element.nextSibling;
|
2156 |
+
return $(element);
|
2157 |
+
},
|
2158 |
+
|
2159 |
+
immediateDescendants: function(element) {
|
2160 |
+
var results = [], child = $(element).firstChild;
|
2161 |
+
while (child) {
|
2162 |
+
if (child.nodeType === 1) {
|
2163 |
+
results.push(Element.extend(child));
|
2164 |
+
}
|
2165 |
+
child = child.nextSibling;
|
2166 |
+
}
|
2167 |
+
return results;
|
2168 |
+
},
|
2169 |
+
|
2170 |
+
previousSiblings: function(element, maximumLength) {
|
2171 |
+
return Element.recursivelyCollect(element, 'previousSibling');
|
2172 |
+
},
|
2173 |
+
|
2174 |
+
nextSiblings: function(element) {
|
2175 |
+
return Element.recursivelyCollect(element, 'nextSibling');
|
2176 |
+
},
|
2177 |
+
|
2178 |
+
siblings: function(element) {
|
2179 |
+
element = $(element);
|
2180 |
+
return Element.previousSiblings(element).reverse()
|
2181 |
+
.concat(Element.nextSiblings(element));
|
2182 |
+
},
|
2183 |
+
|
2184 |
+
match: function(element, selector) {
|
2185 |
+
element = $(element);
|
2186 |
+
if (Object.isString(selector))
|
2187 |
+
return Prototype.Selector.match(element, selector);
|
2188 |
+
return selector.match(element);
|
2189 |
+
},
|
2190 |
+
|
2191 |
+
up: function(element, expression, index) {
|
2192 |
+
element = $(element);
|
2193 |
+
if (arguments.length == 1) return $(element.parentNode);
|
2194 |
+
var ancestors = Element.ancestors(element);
|
2195 |
+
return Object.isNumber(expression) ? ancestors[expression] :
|
2196 |
+
Prototype.Selector.find(ancestors, expression, index);
|
2197 |
+
},
|
2198 |
+
|
2199 |
+
down: function(element, expression, index) {
|
2200 |
+
element = $(element);
|
2201 |
+
if (arguments.length == 1) return Element.firstDescendant(element);
|
2202 |
+
return Object.isNumber(expression) ? Element.descendants(element)[expression] :
|
2203 |
+
Element.select(element, expression)[index || 0];
|
2204 |
+
},
|
2205 |
+
|
2206 |
+
previous: function(element, expression, index) {
|
2207 |
+
element = $(element);
|
2208 |
+
if (Object.isNumber(expression)) index = expression, expression = false;
|
2209 |
+
if (!Object.isNumber(index)) index = 0;
|
2210 |
+
|
2211 |
+
if (expression) {
|
2212 |
+
return Prototype.Selector.find(element.previousSiblings(), expression, index);
|
2213 |
+
} else {
|
2214 |
+
return element.recursivelyCollect("previousSibling", index + 1)[index];
|
2215 |
+
}
|
2216 |
+
},
|
2217 |
+
|
2218 |
+
next: function(element, expression, index) {
|
2219 |
+
element = $(element);
|
2220 |
+
if (Object.isNumber(expression)) index = expression, expression = false;
|
2221 |
+
if (!Object.isNumber(index)) index = 0;
|
2222 |
+
|
2223 |
+
if (expression) {
|
2224 |
+
return Prototype.Selector.find(element.nextSiblings(), expression, index);
|
2225 |
+
} else {
|
2226 |
+
var maximumLength = Object.isNumber(index) ? index + 1 : 1;
|
2227 |
+
return element.recursivelyCollect("nextSibling", index + 1)[index];
|
2228 |
+
}
|
2229 |
+
},
|
2230 |
+
|
2231 |
+
|
2232 |
+
select: function(element) {
|
2233 |
+
element = $(element);
|
2234 |
+
var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
|
2235 |
+
return Prototype.Selector.select(expressions, element);
|
2236 |
+
},
|
2237 |
+
|
2238 |
+
adjacent: function(element) {
|
2239 |
+
element = $(element);
|
2240 |
+
var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
|
2241 |
+
return Prototype.Selector.select(expressions, element.parentNode).without(element);
|
2242 |
+
},
|
2243 |
+
|
2244 |
+
identify: function(element) {
|
2245 |
+
element = $(element);
|
2246 |
+
var id = Element.readAttribute(element, 'id');
|
2247 |
+
if (id) return id;
|
2248 |
+
do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
|
2249 |
+
Element.writeAttribute(element, 'id', id);
|
2250 |
+
return id;
|
2251 |
+
},
|
2252 |
+
|
2253 |
+
readAttribute: function(element, name) {
|
2254 |
+
element = $(element);
|
2255 |
+
if (Prototype.Browser.IE) {
|
2256 |
+
var t = Element._attributeTranslations.read;
|
2257 |
+
if (t.values[name]) return t.values[name](element, name);
|
2258 |
+
if (t.names[name]) name = t.names[name];
|
2259 |
+
if (name.include(':')) {
|
2260 |
+
return (!element.attributes || !element.attributes[name]) ? null :
|
2261 |
+
element.attributes[name].value;
|
2262 |
+
}
|
2263 |
+
}
|
2264 |
+
return element.getAttribute(name);
|
2265 |
+
},
|
2266 |
+
|
2267 |
+
writeAttribute: function(element, name, value) {
|
2268 |
+
element = $(element);
|
2269 |
+
var attributes = { }, t = Element._attributeTranslations.write;
|
2270 |
+
|
2271 |
+
if (typeof name == 'object') attributes = name;
|
2272 |
+
else attributes[name] = Object.isUndefined(value) ? true : value;
|
2273 |
+
|
2274 |
+
for (var attr in attributes) {
|
2275 |
+
name = t.names[attr] || attr;
|
2276 |
+
value = attributes[attr];
|
2277 |
+
if (t.values[attr]) name = t.values[attr](element, value);
|
2278 |
+
if (value === false || value === null)
|
2279 |
+
element.removeAttribute(name);
|
2280 |
+
else if (value === true)
|
2281 |
+
element.setAttribute(name, name);
|
2282 |
+
else element.setAttribute(name, value);
|
2283 |
+
}
|
2284 |
+
return element;
|
2285 |
+
},
|
2286 |
+
|
2287 |
+
getHeight: function(element) {
|
2288 |
+
return Element.getDimensions(element).height;
|
2289 |
+
},
|
2290 |
+
|
2291 |
+
getWidth: function(element) {
|
2292 |
+
return Element.getDimensions(element).width;
|
2293 |
+
},
|
2294 |
+
|
2295 |
+
classNames: function(element) {
|
2296 |
+
return new Element.ClassNames(element);
|
2297 |
+
},
|
2298 |
+
|
2299 |
+
hasClassName: function(element, className) {
|
2300 |
+
if (!(element = $(element))) return;
|
2301 |
+
var elementClassName = element.className;
|
2302 |
+
return (elementClassName.length > 0 && (elementClassName == className ||
|
2303 |
+
new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
|
2304 |
+
},
|
2305 |
+
|
2306 |
+
addClassName: function(element, className) {
|
2307 |
+
if (!(element = $(element))) return;
|
2308 |
+
if (!Element.hasClassName(element, className))
|
2309 |
+
element.className += (element.className ? ' ' : '') + className;
|
2310 |
+
return element;
|
2311 |
+
},
|
2312 |
+
|
2313 |
+
removeClassName: function(element, className) {
|
2314 |
+
if (!(element = $(element))) return;
|
2315 |
+
element.className = element.className.replace(
|
2316 |
+
new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
|
2317 |
+
return element;
|
2318 |
+
},
|
2319 |
+
|
2320 |
+
toggleClassName: function(element, className) {
|
2321 |
+
if (!(element = $(element))) return;
|
2322 |
+
return Element[Element.hasClassName(element, className) ?
|
2323 |
+
'removeClassName' : 'addClassName'](element, className);
|
2324 |
+
},
|
2325 |
+
|
2326 |
+
cleanWhitespace: function(element) {
|
2327 |
+
element = $(element);
|
2328 |
+
var node = element.firstChild;
|
2329 |
+
while (node) {
|
2330 |
+
var nextNode = node.nextSibling;
|
2331 |
+
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
|
2332 |
+
element.removeChild(node);
|
2333 |
+
node = nextNode;
|
2334 |
+
}
|
2335 |
+
return element;
|
2336 |
+
},
|
2337 |
+
|
2338 |
+
empty: function(element) {
|
2339 |
+
return $(element).innerHTML.blank();
|
2340 |
+
},
|
2341 |
+
|
2342 |
+
descendantOf: function(element, ancestor) {
|
2343 |
+
element = $(element), ancestor = $(ancestor);
|
2344 |
+
|
2345 |
+
if (element.compareDocumentPosition)
|
2346 |
+
return (element.compareDocumentPosition(ancestor) & 8) === 8;
|
2347 |
+
|
2348 |
+
if (ancestor.contains)
|
2349 |
+
return ancestor.contains(element) && ancestor !== element;
|
2350 |
+
|
2351 |
+
while (element = element.parentNode)
|
2352 |
+
if (element == ancestor) return true;
|
2353 |
+
|
2354 |
+
return false;
|
2355 |
+
},
|
2356 |
+
|
2357 |
+
scrollTo: function(element) {
|
2358 |
+
element = $(element);
|
2359 |
+
var pos = Element.cumulativeOffset(element);
|
2360 |
+
window.scrollTo(pos[0], pos[1]);
|
2361 |
+
return element;
|
2362 |
+
},
|
2363 |
+
|
2364 |
+
getStyle: function(element, style) {
|
2365 |
+
element = $(element);
|
2366 |
+
style = style == 'float' ? 'cssFloat' : style.camelize();
|
2367 |
+
var value = element.style[style];
|
2368 |
+
if (!value || value == 'auto') {
|
2369 |
+
var css = document.defaultView.getComputedStyle(element, null);
|
2370 |
+
value = css ? css[style] : null;
|
2371 |
+
}
|
2372 |
+
if (style == 'opacity') return value ? parseFloat(value) : 1.0;
|
2373 |
+
return value == 'auto' ? null : value;
|
2374 |
+
},
|
2375 |
+
|
2376 |
+
getOpacity: function(element) {
|
2377 |
+
return $(element).getStyle('opacity');
|
2378 |
+
},
|
2379 |
+
|
2380 |
+
setStyle: function(element, styles) {
|
2381 |
+
element = $(element);
|
2382 |
+
var elementStyle = element.style, match;
|
2383 |
+
if (Object.isString(styles)) {
|
2384 |
+
element.style.cssText += ';' + styles;
|
2385 |
+
return styles.include('opacity') ?
|
2386 |
+
element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
|
2387 |
+
}
|
2388 |
+
for (var property in styles)
|
2389 |
+
if (property == 'opacity') element.setOpacity(styles[property]);
|
2390 |
+
else
|
2391 |
+
elementStyle[(property == 'float' || property == 'cssFloat') ?
|
2392 |
+
(Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
|
2393 |
+
property] = styles[property];
|
2394 |
+
|
2395 |
+
return element;
|
2396 |
+
},
|
2397 |
+
|
2398 |
+
setOpacity: function(element, value) {
|
2399 |
+
element = $(element);
|
2400 |
+
element.style.opacity = (value == 1 || value === '') ? '' :
|
2401 |
+
(value < 0.00001) ? 0 : value;
|
2402 |
+
return element;
|
2403 |
+
},
|
2404 |
+
|
2405 |
+
makePositioned: function(element) {
|
2406 |
+
element = $(element);
|
2407 |
+
var pos = Element.getStyle(element, 'position');
|
2408 |
+
if (pos == 'static' || !pos) {
|
2409 |
+
element._madePositioned = true;
|
2410 |
+
element.style.position = 'relative';
|
2411 |
+
if (Prototype.Browser.Opera) {
|
2412 |
+
element.style.top = 0;
|
2413 |
+
element.style.left = 0;
|
2414 |
+
}
|
2415 |
+
}
|
2416 |
+
return element;
|
2417 |
+
},
|
2418 |
+
|
2419 |
+
undoPositioned: function(element) {
|
2420 |
+
element = $(element);
|
2421 |
+
if (element._madePositioned) {
|
2422 |
+
element._madePositioned = undefined;
|
2423 |
+
element.style.position =
|
2424 |
+
element.style.top =
|
2425 |
+
element.style.left =
|
2426 |
+
element.style.bottom =
|
2427 |
+
element.style.right = '';
|
2428 |
+
}
|
2429 |
+
return element;
|
2430 |
+
},
|
2431 |
+
|
2432 |
+
makeClipping: function(element) {
|
2433 |
+
element = $(element);
|
2434 |
+
if (element._overflow) return element;
|
2435 |
+
element._overflow = Element.getStyle(element, 'overflow') || 'auto';
|
2436 |
+
if (element._overflow !== 'hidden')
|
2437 |
+
element.style.overflow = 'hidden';
|
2438 |
+
return element;
|
2439 |
+
},
|
2440 |
+
|
2441 |
+
undoClipping: function(element) {
|
2442 |
+
element = $(element);
|
2443 |
+
if (!element._overflow) return element;
|
2444 |
+
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
|
2445 |
+
element._overflow = null;
|
2446 |
+
return element;
|
2447 |
+
},
|
2448 |
+
|
2449 |
+
clonePosition: function(element, source) {
|
2450 |
+
var options = Object.extend({
|
2451 |
+
setLeft: true,
|
2452 |
+
setTop: true,
|
2453 |
+
setWidth: true,
|
2454 |
+
setHeight: true,
|
2455 |
+
offsetTop: 0,
|
2456 |
+
offsetLeft: 0
|
2457 |
+
}, arguments[2] || { });
|
2458 |
+
|
2459 |
+
source = $(source);
|
2460 |
+
var p = Element.viewportOffset(source), delta = [0, 0], parent = null;
|
2461 |
+
|
2462 |
+
element = $(element);
|
2463 |
+
|
2464 |
+
if (Element.getStyle(element, 'position') == 'absolute') {
|
2465 |
+
parent = Element.getOffsetParent(element);
|
2466 |
+
delta = Element.viewportOffset(parent);
|
2467 |
+
}
|
2468 |
+
|
2469 |
+
if (parent == document.body) {
|
2470 |
+
delta[0] -= document.body.offsetLeft;
|
2471 |
+
delta[1] -= document.body.offsetTop;
|
2472 |
+
}
|
2473 |
+
|
2474 |
+
if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
|
2475 |
+
if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
|
2476 |
+
if (options.setWidth) element.style.width = source.offsetWidth + 'px';
|
2477 |
+
if (options.setHeight) element.style.height = source.offsetHeight + 'px';
|
2478 |
+
return element;
|
2479 |
+
}
|
2480 |
+
};
|
2481 |
+
|
2482 |
+
Object.extend(Element.Methods, {
|
2483 |
+
getElementsBySelector: Element.Methods.select,
|
2484 |
+
|
2485 |
+
childElements: Element.Methods.immediateDescendants
|
2486 |
+
});
|
2487 |
+
|
2488 |
+
Element._attributeTranslations = {
|
2489 |
+
write: {
|
2490 |
+
names: {
|
2491 |
+
className: 'class',
|
2492 |
+
htmlFor: 'for'
|
2493 |
+
},
|
2494 |
+
values: { }
|
2495 |
+
}
|
2496 |
+
};
|
2497 |
+
|
2498 |
+
if (Prototype.Browser.Opera) {
|
2499 |
+
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
|
2500 |
+
function(proceed, element, style) {
|
2501 |
+
switch (style) {
|
2502 |
+
case 'height': case 'width':
|
2503 |
+
if (!Element.visible(element)) return null;
|
2504 |
+
|
2505 |
+
var dim = parseInt(proceed(element, style), 10);
|
2506 |
+
|
2507 |
+
if (dim !== element['offset' + style.capitalize()])
|
2508 |
+
return dim + 'px';
|
2509 |
+
|
2510 |
+
var properties;
|
2511 |
+
if (style === 'height') {
|
2512 |
+
properties = ['border-top-width', 'padding-top',
|
2513 |
+
'padding-bottom', 'border-bottom-width'];
|
2514 |
+
}
|
2515 |
+
else {
|
2516 |
+
properties = ['border-left-width', 'padding-left',
|
2517 |
+
'padding-right', 'border-right-width'];
|
2518 |
+
}
|
2519 |
+
return properties.inject(dim, function(memo, property) {
|
2520 |
+
var val = proceed(element, property);
|
2521 |
+
return val === null ? memo : memo - parseInt(val, 10);
|
2522 |
+
}) + 'px';
|
2523 |
+
default: return proceed(element, style);
|
2524 |
+
}
|
2525 |
+
}
|
2526 |
+
);
|
2527 |
+
|
2528 |
+
Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
|
2529 |
+
function(proceed, element, attribute) {
|
2530 |
+
if (attribute === 'title') return element.title;
|
2531 |
+
return proceed(element, attribute);
|
2532 |
+
}
|
2533 |
+
);
|
2534 |
+
}
|
2535 |
+
|
2536 |
+
else if (Prototype.Browser.IE) {
|
2537 |
+
Element.Methods.getStyle = function(element, style) {
|
2538 |
+
element = $(element);
|
2539 |
+
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
|
2540 |
+
var value = element.style[style];
|
2541 |
+
if (!value && element.currentStyle) value = element.currentStyle[style];
|
2542 |
+
|
2543 |
+
if (style == 'opacity') {
|
2544 |
+
if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
|
2545 |
+
if (value[1]) return parseFloat(value[1]) / 100;
|
2546 |
+
return 1.0;
|
2547 |
+
}
|
2548 |
+
|
2549 |
+
if (value == 'auto') {
|
2550 |
+
if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
|
2551 |
+
return element['offset' + style.capitalize()] + 'px';
|
2552 |
+
return null;
|
2553 |
+
}
|
2554 |
+
return value;
|
2555 |
+
};
|
2556 |
+
|
2557 |
+
Element.Methods.setOpacity = function(element, value) {
|
2558 |
+
function stripAlpha(filter){
|
2559 |
+
return filter.replace(/alpha\([^\)]*\)/gi,'');
|
2560 |
+
}
|
2561 |
+
element = $(element);
|
2562 |
+
var currentStyle = element.currentStyle;
|
2563 |
+
if ((currentStyle && !currentStyle.hasLayout) ||
|
2564 |
+
(!currentStyle && element.style.zoom == 'normal'))
|
2565 |
+
element.style.zoom = 1;
|
2566 |
+
|
2567 |
+
var filter = element.getStyle('filter'), style = element.style;
|
2568 |
+
if (value == 1 || value === '') {
|
2569 |
+
(filter = stripAlpha(filter)) ?
|
2570 |
+
style.filter = filter : style.removeAttribute('filter');
|
2571 |
+
return element;
|
2572 |
+
} else if (value < 0.00001) value = 0;
|
2573 |
+
style.filter = stripAlpha(filter) +
|
2574 |
+
'alpha(opacity=' + (value * 100) + ')';
|
2575 |
+
return element;
|
2576 |
+
};
|
2577 |
+
|
2578 |
+
Element._attributeTranslations = (function(){
|
2579 |
+
|
2580 |
+
var classProp = 'className',
|
2581 |
+
forProp = 'for',
|
2582 |
+
el = document.createElement('div');
|
2583 |
+
|
2584 |
+
el.setAttribute(classProp, 'x');
|
2585 |
+
|
2586 |
+
if (el.className !== 'x') {
|
2587 |
+
el.setAttribute('class', 'x');
|
2588 |
+
if (el.className === 'x') {
|
2589 |
+
classProp = 'class';
|
2590 |
+
}
|
2591 |
+
}
|
2592 |
+
el = null;
|
2593 |
+
|
2594 |
+
el = document.createElement('label');
|
2595 |
+
el.setAttribute(forProp, 'x');
|
2596 |
+
if (el.htmlFor !== 'x') {
|
2597 |
+
el.setAttribute('htmlFor', 'x');
|
2598 |
+
if (el.htmlFor === 'x') {
|
2599 |
+
forProp = 'htmlFor';
|
2600 |
+
}
|
2601 |
+
}
|
2602 |
+
el = null;
|
2603 |
+
|
2604 |
+
return {
|
2605 |
+
read: {
|
2606 |
+
names: {
|
2607 |
+
'class': classProp,
|
2608 |
+
'className': classProp,
|
2609 |
+
'for': forProp,
|
2610 |
+
'htmlFor': forProp
|
2611 |
+
},
|
2612 |
+
values: {
|
2613 |
+
_getAttr: function(element, attribute) {
|
2614 |
+
return element.getAttribute(attribute);
|
2615 |
+
},
|
2616 |
+
_getAttr2: function(element, attribute) {
|
2617 |
+
return element.getAttribute(attribute, 2);
|
2618 |
+
},
|
2619 |
+
_getAttrNode: function(element, attribute) {
|
2620 |
+
var node = element.getAttributeNode(attribute);
|
2621 |
+
return node ? node.value : "";
|
2622 |
+
},
|
2623 |
+
_getEv: (function(){
|
2624 |
+
|
2625 |
+
var el = document.createElement('div'), f;
|
2626 |
+
el.onclick = Prototype.emptyFunction;
|
2627 |
+
var value = el.getAttribute('onclick');
|
2628 |
+
|
2629 |
+
if (String(value).indexOf('{') > -1) {
|
2630 |
+
f = function(element, attribute) {
|
2631 |
+
attribute = element.getAttribute(attribute);
|
2632 |
+
if (!attribute) return null;
|
2633 |
+
attribute = attribute.toString();
|
2634 |
+
attribute = attribute.split('{')[1];
|
2635 |
+
attribute = attribute.split('}')[0];
|
2636 |
+
return attribute.strip();
|
2637 |
+
};
|
2638 |
+
}
|
2639 |
+
else if (value === '') {
|
2640 |
+
f = function(element, attribute) {
|
2641 |
+
attribute = element.getAttribute(attribute);
|
2642 |
+
if (!attribute) return null;
|
2643 |
+
return attribute.strip();
|
2644 |
+
};
|
2645 |
+
}
|
2646 |
+
el = null;
|
2647 |
+
return f;
|
2648 |
+
})(),
|
2649 |
+
_flag: function(element, attribute) {
|
2650 |
+
return $(element).hasAttribute(attribute) ? attribute : null;
|
2651 |
+
},
|
2652 |
+
style: function(element) {
|
2653 |
+
return element.style.cssText.toLowerCase();
|
2654 |
+
},
|
2655 |
+
title: function(element) {
|
2656 |
+
return element.title;
|
2657 |
+
}
|
2658 |
+
}
|
2659 |
+
}
|
2660 |
+
}
|
2661 |
+
})();
|
2662 |
+
|
2663 |
+
Element._attributeTranslations.write = {
|
2664 |
+
names: Object.extend({
|
2665 |
+
cellpadding: 'cellPadding',
|
2666 |
+
cellspacing: 'cellSpacing'
|
2667 |
+
}, Element._attributeTranslations.read.names),
|
2668 |
+
values: {
|
2669 |
+
checked: function(element, value) {
|
2670 |
+
element.checked = !!value;
|
2671 |
+
},
|
2672 |
+
|
2673 |
+
style: function(element, value) {
|
2674 |
+
element.style.cssText = value ? value : '';
|
2675 |
+
}
|
2676 |
+
}
|
2677 |
+
};
|
2678 |
+
|
2679 |
+
Element._attributeTranslations.has = {};
|
2680 |
+
|
2681 |
+
$w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
|
2682 |
+
'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
|
2683 |
+
Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
|
2684 |
+
Element._attributeTranslations.has[attr.toLowerCase()] = attr;
|
2685 |
+
});
|
2686 |
+
|
2687 |
+
(function(v) {
|
2688 |
+
Object.extend(v, {
|
2689 |
+
href: v._getAttr2,
|
2690 |
+
src: v._getAttr2,
|
2691 |
+
type: v._getAttr,
|
2692 |
+
action: v._getAttrNode,
|
2693 |
+
disabled: v._flag,
|
2694 |
+
checked: v._flag,
|
2695 |
+
readonly: v._flag,
|
2696 |
+
multiple: v._flag,
|
2697 |
+
onload: v._getEv,
|
2698 |
+
onunload: v._getEv,
|
2699 |
+
onclick: v._getEv,
|
2700 |
+
ondblclick: v._getEv,
|
2701 |
+
onmousedown: v._getEv,
|
2702 |
+
onmouseup: v._getEv,
|
2703 |
+
onmouseover: v._getEv,
|
2704 |
+
onmousemove: v._getEv,
|
2705 |
+
onmouseout: v._getEv,
|
2706 |
+
onfocus: v._getEv,
|
2707 |
+
onblur: v._getEv,
|
2708 |
+
onkeypress: v._getEv,
|
2709 |
+
onkeydown: v._getEv,
|
2710 |
+
onkeyup: v._getEv,
|
2711 |
+
onsubmit: v._getEv,
|
2712 |
+
onreset: v._getEv,
|
2713 |
+
onselect: v._getEv,
|
2714 |
+
onchange: v._getEv
|
2715 |
+
});
|
2716 |
+
})(Element._attributeTranslations.read.values);
|
2717 |
+
|
2718 |
+
if (Prototype.BrowserFeatures.ElementExtensions) {
|
2719 |
+
(function() {
|
2720 |
+
function _descendants(element) {
|
2721 |
+
var nodes = element.getElementsByTagName('*'), results = [];
|
2722 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2723 |
+
if (node.tagName !== "!") // Filter out comment nodes.
|
2724 |
+
results.push(node);
|
2725 |
+
return results;
|
2726 |
+
}
|
2727 |
+
|
2728 |
+
Element.Methods.down = function(element, expression, index) {
|
2729 |
+
element = $(element);
|
2730 |
+
if (arguments.length == 1) return element.firstDescendant();
|
2731 |
+
return Object.isNumber(expression) ? _descendants(element)[expression] :
|
2732 |
+
Element.select(element, expression)[index || 0];
|
2733 |
+
}
|
2734 |
+
})();
|
2735 |
+
}
|
2736 |
+
|
2737 |
+
}
|
2738 |
+
|
2739 |
+
else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
|
2740 |
+
Element.Methods.setOpacity = function(element, value) {
|
2741 |
+
element = $(element);
|
2742 |
+
element.style.opacity = (value == 1) ? 0.999999 :
|
2743 |
+
(value === '') ? '' : (value < 0.00001) ? 0 : value;
|
2744 |
+
return element;
|
2745 |
+
};
|
2746 |
+
}
|
2747 |
+
|
2748 |
+
else if (Prototype.Browser.WebKit) {
|
2749 |
+
Element.Methods.setOpacity = function(element, value) {
|
2750 |
+
element = $(element);
|
2751 |
+
element.style.opacity = (value == 1 || value === '') ? '' :
|
2752 |
+
(value < 0.00001) ? 0 : value;
|
2753 |
+
|
2754 |
+
if (value == 1)
|
2755 |
+
if (element.tagName.toUpperCase() == 'IMG' && element.width) {
|
2756 |
+
element.width++; element.width--;
|
2757 |
+
} else try {
|
2758 |
+
var n = document.createTextNode(' ');
|
2759 |
+
element.appendChild(n);
|
2760 |
+
element.removeChild(n);
|
2761 |
+
} catch (e) { }
|
2762 |
+
|
2763 |
+
return element;
|
2764 |
+
};
|
2765 |
+
}
|
2766 |
+
|
2767 |
+
if ('outerHTML' in document.documentElement) {
|
2768 |
+
Element.Methods.replace = function(element, content) {
|
2769 |
+
element = $(element);
|
2770 |
+
|
2771 |
+
if (content && content.toElement) content = content.toElement();
|
2772 |
+
if (Object.isElement(content)) {
|
2773 |
+
element.parentNode.replaceChild(content, element);
|
2774 |
+
return element;
|
2775 |
+
}
|
2776 |
+
|
2777 |
+
content = Object.toHTML(content);
|
2778 |
+
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
|
2779 |
+
|
2780 |
+
if (Element._insertionTranslations.tags[tagName]) {
|
2781 |
+
var nextSibling = element.next(),
|
2782 |
+
fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
|
2783 |
+
parent.removeChild(element);
|
2784 |
+
if (nextSibling)
|
2785 |
+
fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
|
2786 |
+
else
|
2787 |
+
fragments.each(function(node) { parent.appendChild(node) });
|
2788 |
+
}
|
2789 |
+
else element.outerHTML = content.stripScripts();
|
2790 |
+
|
2791 |
+
content.evalScripts.bind(content).defer();
|
2792 |
+
return element;
|
2793 |
+
};
|
2794 |
+
}
|
2795 |
+
|
2796 |
+
Element._returnOffset = function(l, t) {
|
2797 |
+
var result = [l, t];
|
2798 |
+
result.left = l;
|
2799 |
+
result.top = t;
|
2800 |
+
return result;
|
2801 |
+
};
|
2802 |
+
|
2803 |
+
Element._getContentFromAnonymousElement = function(tagName, html, force) {
|
2804 |
+
var div = new Element('div'),
|
2805 |
+
t = Element._insertionTranslations.tags[tagName];
|
2806 |
+
|
2807 |
+
var workaround = false;
|
2808 |
+
if (t) workaround = true;
|
2809 |
+
else if (force) {
|
2810 |
+
workaround = true;
|
2811 |
+
t = ['', '', 0];
|
2812 |
+
}
|
2813 |
+
|
2814 |
+
if (workaround) {
|
2815 |
+
div.innerHTML = ' ' + t[0] + html + t[1];
|
2816 |
+
div.removeChild(div.firstChild);
|
2817 |
+
for (var i = t[2]; i--; ) {
|
2818 |
+
div = div.firstChild;
|
2819 |
+
}
|
2820 |
+
}
|
2821 |
+
else {
|
2822 |
+
div.innerHTML = html;
|
2823 |
+
}
|
2824 |
+
return $A(div.childNodes);
|
2825 |
+
};
|
2826 |
+
|
2827 |
+
Element._insertionTranslations = {
|
2828 |
+
before: function(element, node) {
|
2829 |
+
element.parentNode.insertBefore(node, element);
|
2830 |
+
},
|
2831 |
+
top: function(element, node) {
|
2832 |
+
element.insertBefore(node, element.firstChild);
|
2833 |
+
},
|
2834 |
+
bottom: function(element, node) {
|
2835 |
+
element.appendChild(node);
|
2836 |
+
},
|
2837 |
+
after: function(element, node) {
|
2838 |
+
element.parentNode.insertBefore(node, element.nextSibling);
|
2839 |
+
},
|
2840 |
+
tags: {
|
2841 |
+
TABLE: ['<table>', '</table>', 1],
|
2842 |
+
TBODY: ['<table><tbody>', '</tbody></table>', 2],
|
2843 |
+
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
|
2844 |
+
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
|
2845 |
+
SELECT: ['<select>', '</select>', 1]
|
2846 |
+
}
|
2847 |
+
};
|
2848 |
+
|
2849 |
+
(function() {
|
2850 |
+
var tags = Element._insertionTranslations.tags;
|
2851 |
+
Object.extend(tags, {
|
2852 |
+
THEAD: tags.TBODY,
|
2853 |
+
TFOOT: tags.TBODY,
|
2854 |
+
TH: tags.TD
|
2855 |
+
});
|
2856 |
+
})();
|
2857 |
+
|
2858 |
+
Element.Methods.Simulated = {
|
2859 |
+
hasAttribute: function(element, attribute) {
|
2860 |
+
attribute = Element._attributeTranslations.has[attribute] || attribute;
|
2861 |
+
var node = $(element).getAttributeNode(attribute);
|
2862 |
+
return !!(node && node.specified);
|
2863 |
+
}
|
2864 |
+
};
|
2865 |
+
|
2866 |
+
Element.Methods.ByTag = { };
|
2867 |
+
|
2868 |
+
Object.extend(Element, Element.Methods);
|
2869 |
+
|
2870 |
+
(function(div) {
|
2871 |
+
|
2872 |
+
if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
|
2873 |
+
window.HTMLElement = { };
|
2874 |
+
window.HTMLElement.prototype = div['__proto__'];
|
2875 |
+
Prototype.BrowserFeatures.ElementExtensions = true;
|
2876 |
+
}
|
2877 |
+
|
2878 |
+
div = null;
|
2879 |
+
|
2880 |
+
})(document.createElement('div'));
|
2881 |
+
|
2882 |
+
Element.extend = (function() {
|
2883 |
+
|
2884 |
+
function checkDeficiency(tagName) {
|
2885 |
+
if (typeof window.Element != 'undefined') {
|
2886 |
+
var proto = window.Element.prototype;
|
2887 |
+
if (proto) {
|
2888 |
+
var id = '_' + (Math.random()+'').slice(2),
|
2889 |
+
el = document.createElement(tagName);
|
2890 |
+
proto[id] = 'x';
|
2891 |
+
var isBuggy = (el[id] !== 'x');
|
2892 |
+
delete proto[id];
|
2893 |
+
el = null;
|
2894 |
+
return isBuggy;
|
2895 |
+
}
|
2896 |
+
}
|
2897 |
+
return false;
|
2898 |
+
}
|
2899 |
+
|
2900 |
+
function extendElementWith(element, methods) {
|
2901 |
+
for (var property in methods) {
|
2902 |
+
var value = methods[property];
|
2903 |
+
if (Object.isFunction(value) && !(property in element))
|
2904 |
+
element[property] = value.methodize();
|
2905 |
+
}
|
2906 |
+
}
|
2907 |
+
|
2908 |
+
var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
|
2909 |
+
|
2910 |
+
if (Prototype.BrowserFeatures.SpecificElementExtensions) {
|
2911 |
+
if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
|
2912 |
+
return function(element) {
|
2913 |
+
if (element && typeof element._extendedByPrototype == 'undefined') {
|
2914 |
+
var t = element.tagName;
|
2915 |
+
if (t && (/^(?:object|applet|embed)$/i.test(t))) {
|
2916 |
+
extendElementWith(element, Element.Methods);
|
2917 |
+
extendElementWith(element, Element.Methods.Simulated);
|
2918 |
+
extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
|
2919 |
+
}
|
2920 |
+
}
|
2921 |
+
return element;
|
2922 |
+
}
|
2923 |
+
}
|
2924 |
+
return Prototype.K;
|
2925 |
+
}
|
2926 |
+
|
2927 |
+
var Methods = { }, ByTag = Element.Methods.ByTag;
|
2928 |
+
|
2929 |
+
var extend = Object.extend(function(element) {
|
2930 |
+
if (!element || typeof element._extendedByPrototype != 'undefined' ||
|
2931 |
+
element.nodeType != 1 || element == window) return element;
|
2932 |
+
|
2933 |
+
var methods = Object.clone(Methods),
|
2934 |
+
tagName = element.tagName.toUpperCase();
|
2935 |
+
|
2936 |
+
if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
|
2937 |
+
|
2938 |
+
extendElementWith(element, methods);
|
2939 |
+
|
2940 |
+
element._extendedByPrototype = Prototype.emptyFunction;
|
2941 |
+
return element;
|
2942 |
+
|
2943 |
+
}, {
|
2944 |
+
refresh: function() {
|
2945 |
+
if (!Prototype.BrowserFeatures.ElementExtensions) {
|
2946 |
+
Object.extend(Methods, Element.Methods);
|
2947 |
+
Object.extend(Methods, Element.Methods.Simulated);
|
2948 |
+
}
|
2949 |
+
}
|
2950 |
+
});
|
2951 |
+
|
2952 |
+
extend.refresh();
|
2953 |
+
return extend;
|
2954 |
+
})();
|
2955 |
+
|
2956 |
+
if (document.documentElement.hasAttribute) {
|
2957 |
+
Element.hasAttribute = function(element, attribute) {
|
2958 |
+
return element.hasAttribute(attribute);
|
2959 |
+
};
|
2960 |
+
}
|
2961 |
+
else {
|
2962 |
+
Element.hasAttribute = Element.Methods.Simulated.hasAttribute;
|
2963 |
+
}
|
2964 |
+
|
2965 |
+
Element.addMethods = function(methods) {
|
2966 |
+
var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
|
2967 |
+
|
2968 |
+
if (!methods) {
|
2969 |
+
Object.extend(Form, Form.Methods);
|
2970 |
+
Object.extend(Form.Element, Form.Element.Methods);
|
2971 |
+
Object.extend(Element.Methods.ByTag, {
|
2972 |
+
"FORM": Object.clone(Form.Methods),
|
2973 |
+
"INPUT": Object.clone(Form.Element.Methods),
|
2974 |
+
"SELECT": Object.clone(Form.Element.Methods),
|
2975 |
+
"TEXTAREA": Object.clone(Form.Element.Methods),
|
2976 |
+
"BUTTON": Object.clone(Form.Element.Methods)
|
2977 |
+
});
|
2978 |
+
}
|
2979 |
+
|
2980 |
+
if (arguments.length == 2) {
|
2981 |
+
var tagName = methods;
|
2982 |
+
methods = arguments[1];
|
2983 |
+
}
|
2984 |
+
|
2985 |
+
if (!tagName) Object.extend(Element.Methods, methods || { });
|
2986 |
+
else {
|
2987 |
+
if (Object.isArray(tagName)) tagName.each(extend);
|
2988 |
+
else extend(tagName);
|
2989 |
+
}
|
2990 |
+
|
2991 |
+
function extend(tagName) {
|
2992 |
+
tagName = tagName.toUpperCase();
|
2993 |
+
if (!Element.Methods.ByTag[tagName])
|
2994 |
+
Element.Methods.ByTag[tagName] = { };
|
2995 |
+
Object.extend(Element.Methods.ByTag[tagName], methods);
|
2996 |
+
}
|
2997 |
+
|
2998 |
+
function copy(methods, destination, onlyIfAbsent) {
|
2999 |
+
onlyIfAbsent = onlyIfAbsent || false;
|
3000 |
+
for (var property in methods) {
|
3001 |
+
var value = methods[property];
|
3002 |
+
if (!Object.isFunction(value)) continue;
|
3003 |
+
if (!onlyIfAbsent || !(property in destination))
|
3004 |
+
destination[property] = value.methodize();
|
3005 |
+
}
|
3006 |
+
}
|
3007 |
+
|
3008 |
+
function findDOMClass(tagName) {
|
3009 |
+
var klass;
|
3010 |
+
var trans = {
|
3011 |
+
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
|
3012 |
+
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
|
3013 |
+
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
|
3014 |
+
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
|
3015 |
+
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
|
3016 |
+
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
|
3017 |
+
"TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
|
3018 |
+
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
|
3019 |
+
"FrameSet", "IFRAME": "IFrame"
|
3020 |
+
};
|
3021 |
+
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
|
3022 |
+
if (window[klass]) return window[klass];
|
3023 |
+
klass = 'HTML' + tagName + 'Element';
|
3024 |
+
if (window[klass]) return window[klass];
|
3025 |
+
klass = 'HTML' + tagName.capitalize() + 'Element';
|
3026 |
+
if (window[klass]) return window[klass];
|
3027 |
+
|
3028 |
+
var element = document.createElement(tagName),
|
3029 |
+
proto = element['__proto__'] || element.constructor.prototype;
|
3030 |
+
|
3031 |
+
element = null;
|
3032 |
+
return proto;
|
3033 |
+
}
|
3034 |
+
|
3035 |
+
var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
|
3036 |
+
Element.prototype;
|
3037 |
+
|
3038 |
+
if (F.ElementExtensions) {
|
3039 |
+
copy(Element.Methods, elementPrototype);
|
3040 |
+
copy(Element.Methods.Simulated, elementPrototype, true);
|
3041 |
+
}
|
3042 |
+
|
3043 |
+
if (F.SpecificElementExtensions) {
|
3044 |
+
for (var tag in Element.Methods.ByTag) {
|
3045 |
+
var klass = findDOMClass(tag);
|
3046 |
+
if (Object.isUndefined(klass)) continue;
|
3047 |
+
copy(T[tag], klass.prototype);
|
3048 |
+
}
|
3049 |
+
}
|
3050 |
+
|
3051 |
+
Object.extend(Element, Element.Methods);
|
3052 |
+
delete Element.ByTag;
|
3053 |
+
|
3054 |
+
if (Element.extend.refresh) Element.extend.refresh();
|
3055 |
+
Element.cache = { };
|
3056 |
+
};
|
3057 |
+
|
3058 |
+
|
3059 |
+
document.viewport = {
|
3060 |
+
|
3061 |
+
getDimensions: function() {
|
3062 |
+
return { width: this.getWidth(), height: this.getHeight() };
|
3063 |
+
},
|
3064 |
+
|
3065 |
+
getScrollOffsets: function() {
|
3066 |
+
return Element._returnOffset(
|
3067 |
+
window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
|
3068 |
+
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
|
3069 |
+
}
|
3070 |
+
};
|
3071 |
+
|
3072 |
+
(function(viewport) {
|
3073 |
+
var B = Prototype.Browser, doc = document, element, property = {};
|
3074 |
+
|
3075 |
+
function getRootElement() {
|
3076 |
+
if (B.WebKit && !doc.evaluate)
|
3077 |
+
return document;
|
3078 |
+
|
3079 |
+
if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
|
3080 |
+
return document.body;
|
3081 |
+
|
3082 |
+
return document.documentElement;
|
3083 |
+
}
|
3084 |
+
|
3085 |
+
function define(D) {
|
3086 |
+
if (!element) element = getRootElement();
|
3087 |
+
|
3088 |
+
property[D] = 'client' + D;
|
3089 |
+
|
3090 |
+
viewport['get' + D] = function() { return element[property[D]] };
|
3091 |
+
return viewport['get' + D]();
|
3092 |
+
}
|
3093 |
+
|
3094 |
+
viewport.getWidth = define.curry('Width');
|
3095 |
+
|
3096 |
+
viewport.getHeight = define.curry('Height');
|
3097 |
+
})(document.viewport);
|
3098 |
+
|
3099 |
+
|
3100 |
+
Element.Storage = {
|
3101 |
+
UID: 1
|
3102 |
+
};
|
3103 |
+
|
3104 |
+
Element.addMethods({
|
3105 |
+
getStorage: function(element) {
|
3106 |
+
if (!(element = $(element))) return;
|
3107 |
+
|
3108 |
+
var uid;
|
3109 |
+
if (element === window) {
|
3110 |
+
uid = 0;
|
3111 |
+
} else {
|
3112 |
+
if (typeof element._prototypeUID === "undefined")
|
3113 |
+
element._prototypeUID = Element.Storage.UID++;
|
3114 |
+
uid = element._prototypeUID;
|
3115 |
+
}
|
3116 |
+
|
3117 |
+
if (!Element.Storage[uid])
|
3118 |
+
Element.Storage[uid] = $H();
|
3119 |
+
|
3120 |
+
return Element.Storage[uid];
|
3121 |
+
},
|
3122 |
+
|
3123 |
+
store: function(element, key, value) {
|
3124 |
+
if (!(element = $(element))) return;
|
3125 |
+
|
3126 |
+
if (arguments.length === 2) {
|
3127 |
+
Element.getStorage(element).update(key);
|
3128 |
+
} else {
|
3129 |
+
Element.getStorage(element).set(key, value);
|
3130 |
+
}
|
3131 |
+
|
3132 |
+
return element;
|
3133 |
+
},
|
3134 |
+
|
3135 |
+
retrieve: function(element, key, defaultValue) {
|
3136 |
+
if (!(element = $(element))) return;
|
3137 |
+
var hash = Element.getStorage(element), value = hash.get(key);
|
3138 |
+
|
3139 |
+
if (Object.isUndefined(value)) {
|
3140 |
+
hash.set(key, defaultValue);
|
3141 |
+
value = defaultValue;
|
3142 |
+
}
|
3143 |
+
|
3144 |
+
return value;
|
3145 |
+
},
|
3146 |
+
|
3147 |
+
clone: function(element, deep) {
|
3148 |
+
if (!(element = $(element))) return;
|
3149 |
+
var clone = element.cloneNode(deep);
|
3150 |
+
clone._prototypeUID = void 0;
|
3151 |
+
if (deep) {
|
3152 |
+
var descendants = Element.select(clone, '*'),
|
3153 |
+
i = descendants.length;
|
3154 |
+
while (i--) {
|
3155 |
+
descendants[i]._prototypeUID = void 0;
|
3156 |
+
}
|
3157 |
+
}
|
3158 |
+
return Element.extend(clone);
|
3159 |
+
},
|
3160 |
+
|
3161 |
+
purge: function(element) {
|
3162 |
+
if (!(element = $(element))) return;
|
3163 |
+
var purgeElement = Element._purgeElement;
|
3164 |
+
|
3165 |
+
purgeElement(element);
|
3166 |
+
|
3167 |
+
var descendants = element.getElementsByTagName('*'),
|
3168 |
+
i = descendants.length;
|
3169 |
+
|
3170 |
+
while (i--) purgeElement(descendants[i]);
|
3171 |
+
|
3172 |
+
return null;
|
3173 |
+
}
|
3174 |
+
});
|
3175 |
+
|
3176 |
+
(function() {
|
3177 |
+
|
3178 |
+
function toDecimal(pctString) {
|
3179 |
+
var match = pctString.match(/^(\d+)%?$/i);
|
3180 |
+
if (!match) return null;
|
3181 |
+
return (Number(match[1]) / 100);
|
3182 |
+
}
|
3183 |
+
|
3184 |
+
function getPixelValue(value, property, context) {
|
3185 |
+
var element = null;
|
3186 |
+
if (Object.isElement(value)) {
|
3187 |
+
element = value;
|
3188 |
+
value = element.getStyle(property);
|
3189 |
+
}
|
3190 |
+
|
3191 |
+
if (value === null) {
|
3192 |
+
return null;
|
3193 |
+
}
|
3194 |
+
|
3195 |
+
if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
|
3196 |
+
return window.parseFloat(value);
|
3197 |
+
}
|
3198 |
+
|
3199 |
+
var isPercentage = value.include('%'), isViewport = (context === document.viewport);
|
3200 |
+
|
3201 |
+
if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
|
3202 |
+
var style = element.style.left, rStyle = element.runtimeStyle.left;
|
3203 |
+
element.runtimeStyle.left = element.currentStyle.left;
|
3204 |
+
element.style.left = value || 0;
|
3205 |
+
value = element.style.pixelLeft;
|
3206 |
+
element.style.left = style;
|
3207 |
+
element.runtimeStyle.left = rStyle;
|
3208 |
+
|
3209 |
+
return value;
|
3210 |
+
}
|
3211 |
+
|
3212 |
+
if (element && isPercentage) {
|
3213 |
+
context = context || element.parentNode;
|
3214 |
+
var decimal = toDecimal(value);
|
3215 |
+
var whole = null;
|
3216 |
+
var position = element.getStyle('position');
|
3217 |
+
|
3218 |
+
var isHorizontal = property.include('left') || property.include('right') ||
|
3219 |
+
property.include('width');
|
3220 |
+
|
3221 |
+
var isVertical = property.include('top') || property.include('bottom') ||
|
3222 |
+
property.include('height');
|
3223 |
+
|
3224 |
+
if (context === document.viewport) {
|
3225 |
+
if (isHorizontal) {
|
3226 |
+
whole = document.viewport.getWidth();
|
3227 |
+
} else if (isVertical) {
|
3228 |
+
whole = document.viewport.getHeight();
|
3229 |
+
}
|
3230 |
+
} else {
|
3231 |
+
if (isHorizontal) {
|
3232 |
+
whole = $(context).measure('width');
|
3233 |
+
} else if (isVertical) {
|
3234 |
+
whole = $(context).measure('height');
|
3235 |
+
}
|
3236 |
+
}
|
3237 |
+
|
3238 |
+
return (whole === null) ? 0 : whole * decimal;
|
3239 |
+
}
|
3240 |
+
|
3241 |
+
return 0;
|
3242 |
+
}
|
3243 |
+
|
3244 |
+
function toCSSPixels(number) {
|
3245 |
+
if (Object.isString(number) && number.endsWith('px')) {
|
3246 |
+
return number;
|
3247 |
+
}
|
3248 |
+
return number + 'px';
|
3249 |
+
}
|
3250 |
+
|
3251 |
+
function isDisplayed(element) {
|
3252 |
+
var originalElement = element;
|
3253 |
+
while (element && element.parentNode) {
|
3254 |
+
var display = element.getStyle('display');
|
3255 |
+
if (display === 'none') {
|
3256 |
+
return false;
|
3257 |
+
}
|
3258 |
+
element = $(element.parentNode);
|
3259 |
+
}
|
3260 |
+
return true;
|
3261 |
+
}
|
3262 |
+
|
3263 |
+
var hasLayout = Prototype.K;
|
3264 |
+
if ('currentStyle' in document.documentElement) {
|
3265 |
+
hasLayout = function(element) {
|
3266 |
+
if (!element.currentStyle.hasLayout) {
|
3267 |
+
element.style.zoom = 1;
|
3268 |
+
}
|
3269 |
+
return element;
|
3270 |
+
};
|
3271 |
+
}
|
3272 |
+
|
3273 |
+
function cssNameFor(key) {
|
3274 |
+
if (key.include('border')) key = key + '-width';
|
3275 |
+
return key.camelize();
|
3276 |
+
}
|
3277 |
+
|
3278 |
+
Element.Layout = Class.create(Hash, {
|
3279 |
+
initialize: function($super, element, preCompute) {
|
3280 |
+
$super();
|
3281 |
+
this.element = $(element);
|
3282 |
+
|
3283 |
+
Element.Layout.PROPERTIES.each( function(property) {
|
3284 |
+
this._set(property, null);
|
3285 |
+
}, this);
|
3286 |
+
|
3287 |
+
if (preCompute) {
|
3288 |
+
this._preComputing = true;
|
3289 |
+
this._begin();
|
3290 |
+
Element.Layout.PROPERTIES.each( this._compute, this );
|
3291 |
+
this._end();
|
3292 |
+
this._preComputing = false;
|
3293 |
+
}
|
3294 |
+
},
|
3295 |
+
|
3296 |
+
_set: function(property, value) {
|
3297 |
+
return Hash.prototype.set.call(this, property, value);
|
3298 |
+
},
|
3299 |
+
|
3300 |
+
set: function(property, value) {
|
3301 |
+
throw "Properties of Element.Layout are read-only.";
|
3302 |
+
},
|
3303 |
+
|
3304 |
+
get: function($super, property) {
|
3305 |
+
var value = $super(property);
|
3306 |
+
return value === null ? this._compute(property) : value;
|
3307 |
+
},
|
3308 |
+
|
3309 |
+
_begin: function() {
|
3310 |
+
if (this._prepared) return;
|
3311 |
+
|
3312 |
+
var element = this.element;
|
3313 |
+
if (isDisplayed(element)) {
|
3314 |
+
this._prepared = true;
|
3315 |
+
return;
|
3316 |
+
}
|
3317 |
+
|
3318 |
+
var originalStyles = {
|
3319 |
+
position: element.style.position || '',
|
3320 |
+
width: element.style.width || '',
|
3321 |
+
visibility: element.style.visibility || '',
|
3322 |
+
display: element.style.display || ''
|
3323 |
+
};
|
3324 |
+
|
3325 |
+
element.store('prototype_original_styles', originalStyles);
|
3326 |
+
|
3327 |
+
var position = element.getStyle('position'),
|
3328 |
+
width = element.getStyle('width');
|
3329 |
+
|
3330 |
+
if (width === "0px" || width === null) {
|
3331 |
+
element.style.display = 'block';
|
3332 |
+
width = element.getStyle('width');
|
3333 |
+
}
|
3334 |
+
|
3335 |
+
var context = (position === 'fixed') ? document.viewport :
|
3336 |
+
element.parentNode;
|
3337 |
+
|
3338 |
+
element.setStyle({
|
3339 |
+
position: 'absolute',
|
3340 |
+
visibility: 'hidden',
|
3341 |
+
display: 'block'
|
3342 |
+
});
|
3343 |
+
|
3344 |
+
var positionedWidth = element.getStyle('width');
|
3345 |
+
|
3346 |
+
var newWidth;
|
3347 |
+
if (width && (positionedWidth === width)) {
|
3348 |
+
newWidth = getPixelValue(element, 'width', context);
|
3349 |
+
} else if (position === 'absolute' || position === 'fixed') {
|
3350 |
+
newWidth = getPixelValue(element, 'width', context);
|
3351 |
+
} else {
|
3352 |
+
var parent = element.parentNode, pLayout = $(parent).getLayout();
|
3353 |
+
|
3354 |
+
newWidth = pLayout.get('width') -
|
3355 |
+
this.get('margin-left') -
|
3356 |
+
this.get('border-left') -
|
3357 |
+
this.get('padding-left') -
|
3358 |
+
this.get('padding-right') -
|
3359 |
+
this.get('border-right') -
|
3360 |
+
this.get('margin-right');
|
3361 |
+
}
|
3362 |
+
|
3363 |
+
element.setStyle({ width: newWidth + 'px' });
|
3364 |
+
|
3365 |
+
this._prepared = true;
|
3366 |
+
},
|
3367 |
+
|
3368 |
+
_end: function() {
|
3369 |
+
var element = this.element;
|
3370 |
+
var originalStyles = element.retrieve('prototype_original_styles');
|
3371 |
+
element.store('prototype_original_styles', null);
|
3372 |
+
element.setStyle(originalStyles);
|
3373 |
+
this._prepared = false;
|
3374 |
+
},
|
3375 |
+
|
3376 |
+
_compute: function(property) {
|
3377 |
+
var COMPUTATIONS = Element.Layout.COMPUTATIONS;
|
3378 |
+
if (!(property in COMPUTATIONS)) {
|
3379 |
+
throw "Property not found.";
|
3380 |
+
}
|
3381 |
+
|
3382 |
+
return this._set(property, COMPUTATIONS[property].call(this, this.element));
|
3383 |
+
},
|
3384 |
+
|
3385 |
+
toObject: function() {
|
3386 |
+
var args = $A(arguments);
|
3387 |
+
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
|
3388 |
+
args.join(' ').split(' ');
|
3389 |
+
var obj = {};
|
3390 |
+
keys.each( function(key) {
|
3391 |
+
if (!Element.Layout.PROPERTIES.include(key)) return;
|
3392 |
+
var value = this.get(key);
|
3393 |
+
if (value != null) obj[key] = value;
|
3394 |
+
}, this);
|
3395 |
+
return obj;
|
3396 |
+
},
|
3397 |
+
|
3398 |
+
toHash: function() {
|
3399 |
+
var obj = this.toObject.apply(this, arguments);
|
3400 |
+
return new Hash(obj);
|
3401 |
+
},
|
3402 |
+
|
3403 |
+
toCSS: function() {
|
3404 |
+
var args = $A(arguments);
|
3405 |
+
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
|
3406 |
+
args.join(' ').split(' ');
|
3407 |
+
var css = {};
|
3408 |
+
|
3409 |
+
keys.each( function(key) {
|
3410 |
+
if (!Element.Layout.PROPERTIES.include(key)) return;
|
3411 |
+
if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
|
3412 |
+
|
3413 |
+
var value = this.get(key);
|
3414 |
+
if (value != null) css[cssNameFor(key)] = value + 'px';
|
3415 |
+
}, this);
|
3416 |
+
return css;
|
3417 |
+
},
|
3418 |
+
|
3419 |
+
inspect: function() {
|
3420 |
+
return "#<Element.Layout>";
|
3421 |
+
}
|
3422 |
+
});
|
3423 |
+
|
3424 |
+
Object.extend(Element.Layout, {
|
3425 |
+
PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
|
3426 |
+
|
3427 |
+
COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
|
3428 |
+
|
3429 |
+
COMPUTATIONS: {
|
3430 |
+
'height': function(element) {
|
3431 |
+
if (!this._preComputing) this._begin();
|
3432 |
+
|
3433 |
+
var bHeight = this.get('border-box-height');
|
3434 |
+
if (bHeight <= 0) {
|
3435 |
+
if (!this._preComputing) this._end();
|
3436 |
+
return 0;
|
3437 |
+
}
|
3438 |
+
|
3439 |
+
var bTop = this.get('border-top'),
|
3440 |
+
bBottom = this.get('border-bottom');
|
3441 |
+
|
3442 |
+
var pTop = this.get('padding-top'),
|
3443 |
+
pBottom = this.get('padding-bottom');
|
3444 |
+
|
3445 |
+
if (!this._preComputing) this._end();
|
3446 |
+
|
3447 |
+
return bHeight - bTop - bBottom - pTop - pBottom;
|
3448 |
+
},
|
3449 |
+
|
3450 |
+
'width': function(element) {
|
3451 |
+
if (!this._preComputing) this._begin();
|
3452 |
+
|
3453 |
+
var bWidth = this.get('border-box-width');
|
3454 |
+
if (bWidth <= 0) {
|
3455 |
+
if (!this._preComputing) this._end();
|
3456 |
+
return 0;
|
3457 |
+
}
|
3458 |
+
|
3459 |
+
var bLeft = this.get('border-left'),
|
3460 |
+
bRight = this.get('border-right');
|
3461 |
+
|
3462 |
+
var pLeft = this.get('padding-left'),
|
3463 |
+
pRight = this.get('padding-right');
|
3464 |
+
|
3465 |
+
if (!this._preComputing) this._end();
|
3466 |
+
|
3467 |
+
return bWidth - bLeft - bRight - pLeft - pRight;
|
3468 |
+
},
|
3469 |
+
|
3470 |
+
'padding-box-height': function(element) {
|
3471 |
+
var height = this.get('height'),
|
3472 |
+
pTop = this.get('padding-top'),
|
3473 |
+
pBottom = this.get('padding-bottom');
|
3474 |
+
|
3475 |
+
return height + pTop + pBottom;
|
3476 |
+
},
|
3477 |
+
|
3478 |
+
'padding-box-width': function(element) {
|
3479 |
+
var width = this.get('width'),
|
3480 |
+
pLeft = this.get('padding-left'),
|
3481 |
+
pRight = this.get('padding-right');
|
3482 |
+
|
3483 |
+
return width + pLeft + pRight;
|
3484 |
+
},
|
3485 |
+
|
3486 |
+
'border-box-height': function(element) {
|
3487 |
+
if (!this._preComputing) this._begin();
|
3488 |
+
var height = element.offsetHeight;
|
3489 |
+
if (!this._preComputing) this._end();
|
3490 |
+
return height;
|
3491 |
+
},
|
3492 |
+
|
3493 |
+
'border-box-width': function(element) {
|
3494 |
+
if (!this._preComputing) this._begin();
|
3495 |
+
var width = element.offsetWidth;
|
3496 |
+
if (!this._preComputing) this._end();
|
3497 |
+
return width;
|
3498 |
+
},
|
3499 |
+
|
3500 |
+
'margin-box-height': function(element) {
|
3501 |
+
var bHeight = this.get('border-box-height'),
|
3502 |
+
mTop = this.get('margin-top'),
|
3503 |
+
mBottom = this.get('margin-bottom');
|
3504 |
+
|
3505 |
+
if (bHeight <= 0) return 0;
|
3506 |
+
|
3507 |
+
return bHeight + mTop + mBottom;
|
3508 |
+
},
|
3509 |
+
|
3510 |
+
'margin-box-width': function(element) {
|
3511 |
+
var bWidth = this.get('border-box-width'),
|
3512 |
+
mLeft = this.get('margin-left'),
|
3513 |
+
mRight = this.get('margin-right');
|
3514 |
+
|
3515 |
+
if (bWidth <= 0) return 0;
|
3516 |
+
|
3517 |
+
return bWidth + mLeft + mRight;
|
3518 |
+
},
|
3519 |
+
|
3520 |
+
'top': function(element) {
|
3521 |
+
var offset = element.positionedOffset();
|
3522 |
+
return offset.top;
|
3523 |
+
},
|
3524 |
+
|
3525 |
+
'bottom': function(element) {
|
3526 |
+
var offset = element.positionedOffset(),
|
3527 |
+
parent = element.getOffsetParent(),
|
3528 |
+
pHeight = parent.measure('height');
|
3529 |
+
|
3530 |
+
var mHeight = this.get('border-box-height');
|
3531 |
+
|
3532 |
+
return pHeight - mHeight - offset.top;
|
3533 |
+
},
|
3534 |
+
|
3535 |
+
'left': function(element) {
|
3536 |
+
var offset = element.positionedOffset();
|
3537 |
+
return offset.left;
|
3538 |
+
},
|
3539 |
+
|
3540 |
+
'right': function(element) {
|
3541 |
+
var offset = element.positionedOffset(),
|
3542 |
+
parent = element.getOffsetParent(),
|
3543 |
+
pWidth = parent.measure('width');
|
3544 |
+
|
3545 |
+
var mWidth = this.get('border-box-width');
|
3546 |
+
|
3547 |
+
return pWidth - mWidth - offset.left;
|
3548 |
+
},
|
3549 |
+
|
3550 |
+
'padding-top': function(element) {
|
3551 |
+
return getPixelValue(element, 'paddingTop');
|
3552 |
+
},
|
3553 |
+
|
3554 |
+
'padding-bottom': function(element) {
|
3555 |
+
return getPixelValue(element, 'paddingBottom');
|
3556 |
+
},
|
3557 |
+
|
3558 |
+
'padding-left': function(element) {
|
3559 |
+
return getPixelValue(element, 'paddingLeft');
|
3560 |
+
},
|
3561 |
+
|
3562 |
+
'padding-right': function(element) {
|
3563 |
+
return getPixelValue(element, 'paddingRight');
|
3564 |
+
},
|
3565 |
+
|
3566 |
+
'border-top': function(element) {
|
3567 |
+
return getPixelValue(element, 'borderTopWidth');
|
3568 |
+
},
|
3569 |
+
|
3570 |
+
'border-bottom': function(element) {
|
3571 |
+
return getPixelValue(element, 'borderBottomWidth');
|
3572 |
+
},
|
3573 |
+
|
3574 |
+
'border-left': function(element) {
|
3575 |
+
return getPixelValue(element, 'borderLeftWidth');
|
3576 |
+
},
|
3577 |
+
|
3578 |
+
'border-right': function(element) {
|
3579 |
+
return getPixelValue(element, 'borderRightWidth');
|
3580 |
+
},
|
3581 |
+
|
3582 |
+
'margin-top': function(element) {
|
3583 |
+
return getPixelValue(element, 'marginTop');
|
3584 |
+
},
|
3585 |
+
|
3586 |
+
'margin-bottom': function(element) {
|
3587 |
+
return getPixelValue(element, 'marginBottom');
|
3588 |
+
},
|
3589 |
+
|
3590 |
+
'margin-left': function(element) {
|
3591 |
+
return getPixelValue(element, 'marginLeft');
|
3592 |
+
},
|
3593 |
+
|
3594 |
+
'margin-right': function(element) {
|
3595 |
+
return getPixelValue(element, 'marginRight');
|
3596 |
+
}
|
3597 |
+
}
|
3598 |
+
});
|
3599 |
+
|
3600 |
+
if ('getBoundingClientRect' in document.documentElement) {
|
3601 |
+
Object.extend(Element.Layout.COMPUTATIONS, {
|
3602 |
+
'right': function(element) {
|
3603 |
+
var parent = hasLayout(element.getOffsetParent());
|
3604 |
+
var rect = element.getBoundingClientRect(),
|
3605 |
+
pRect = parent.getBoundingClientRect();
|
3606 |
+
|
3607 |
+
return (pRect.right - rect.right).round();
|
3608 |
+
},
|
3609 |
+
|
3610 |
+
'bottom': function(element) {
|
3611 |
+
var parent = hasLayout(element.getOffsetParent());
|
3612 |
+
var rect = element.getBoundingClientRect(),
|
3613 |
+
pRect = parent.getBoundingClientRect();
|
3614 |
+
|
3615 |
+
return (pRect.bottom - rect.bottom).round();
|
3616 |
+
}
|
3617 |
+
});
|
3618 |
+
}
|
3619 |
+
|
3620 |
+
Element.Offset = Class.create({
|
3621 |
+
initialize: function(left, top) {
|
3622 |
+
this.left = left.round();
|
3623 |
+
this.top = top.round();
|
3624 |
+
|
3625 |
+
this[0] = this.left;
|
3626 |
+
this[1] = this.top;
|
3627 |
+
},
|
3628 |
+
|
3629 |
+
relativeTo: function(offset) {
|
3630 |
+
return new Element.Offset(
|
3631 |
+
this.left - offset.left,
|
3632 |
+
this.top - offset.top
|
3633 |
+
);
|
3634 |
+
},
|
3635 |
+
|
3636 |
+
inspect: function() {
|
3637 |
+
return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
|
3638 |
+
},
|
3639 |
+
|
3640 |
+
toString: function() {
|
3641 |
+
return "[#{left}, #{top}]".interpolate(this);
|
3642 |
+
},
|
3643 |
+
|
3644 |
+
toArray: function() {
|
3645 |
+
return [this.left, this.top];
|
3646 |
+
}
|
3647 |
+
});
|
3648 |
+
|
3649 |
+
function getLayout(element, preCompute) {
|
3650 |
+
return new Element.Layout(element, preCompute);
|
3651 |
+
}
|
3652 |
+
|
3653 |
+
function measure(element, property) {
|
3654 |
+
return $(element).getLayout().get(property);
|
3655 |
+
}
|
3656 |
+
|
3657 |
+
function getDimensions(element) {
|
3658 |
+
element = $(element);
|
3659 |
+
var display = Element.getStyle(element, 'display');
|
3660 |
+
|
3661 |
+
if (display && display !== 'none') {
|
3662 |
+
return { width: element.offsetWidth, height: element.offsetHeight };
|
3663 |
+
}
|
3664 |
+
|
3665 |
+
var style = element.style;
|
3666 |
+
var originalStyles = {
|
3667 |
+
visibility: style.visibility,
|
3668 |
+
position: style.position,
|
3669 |
+
display: style.display
|
3670 |
+
};
|
3671 |
+
|
3672 |
+
var newStyles = {
|
3673 |
+
visibility: 'hidden',
|
3674 |
+
display: 'block'
|
3675 |
+
};
|
3676 |
+
|
3677 |
+
if (originalStyles.position !== 'fixed')
|
3678 |
+
newStyles.position = 'absolute';
|
3679 |
+
|
3680 |
+
Element.setStyle(element, newStyles);
|
3681 |
+
|
3682 |
+
var dimensions = {
|
3683 |
+
width: element.offsetWidth,
|
3684 |
+
height: element.offsetHeight
|
3685 |
+
};
|
3686 |
+
|
3687 |
+
Element.setStyle(element, originalStyles);
|
3688 |
+
|
3689 |
+
return dimensions;
|
3690 |
+
}
|
3691 |
+
|
3692 |
+
function getOffsetParent(element) {
|
3693 |
+
element = $(element);
|
3694 |
+
|
3695 |
+
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
|
3696 |
+
return $(document.body);
|
3697 |
+
|
3698 |
+
var isInline = (Element.getStyle(element, 'display') === 'inline');
|
3699 |
+
if (!isInline && element.offsetParent) return $(element.offsetParent);
|
3700 |
+
|
3701 |
+
while ((element = element.parentNode) && element !== document.body) {
|
3702 |
+
if (Element.getStyle(element, 'position') !== 'static') {
|
3703 |
+
return isHtml(element) ? $(document.body) : $(element);
|
3704 |
+
}
|
3705 |
+
}
|
3706 |
+
|
3707 |
+
return $(document.body);
|
3708 |
+
}
|
3709 |
+
|
3710 |
+
|
3711 |
+
function cumulativeOffset(element) {
|
3712 |
+
element = $(element);
|
3713 |
+
var valueT = 0, valueL = 0;
|
3714 |
+
if (element.parentNode) {
|
3715 |
+
do {
|
3716 |
+
valueT += element.offsetTop || 0;
|
3717 |
+
valueL += element.offsetLeft || 0;
|
3718 |
+
element = element.offsetParent;
|
3719 |
+
} while (element);
|
3720 |
+
}
|
3721 |
+
return new Element.Offset(valueL, valueT);
|
3722 |
+
}
|
3723 |
+
|
3724 |
+
function positionedOffset(element) {
|
3725 |
+
element = $(element);
|
3726 |
+
|
3727 |
+
var layout = element.getLayout();
|
3728 |
+
|
3729 |
+
var valueT = 0, valueL = 0;
|
3730 |
+
do {
|
3731 |
+
valueT += element.offsetTop || 0;
|
3732 |
+
valueL += element.offsetLeft || 0;
|
3733 |
+
element = element.offsetParent;
|
3734 |
+
if (element) {
|
3735 |
+
if (isBody(element)) break;
|
3736 |
+
var p = Element.getStyle(element, 'position');
|
3737 |
+
if (p !== 'static') break;
|
3738 |
+
}
|
3739 |
+
} while (element);
|
3740 |
+
|
3741 |
+
valueL -= layout.get('margin-top');
|
3742 |
+
valueT -= layout.get('margin-left');
|
3743 |
+
|
3744 |
+
return new Element.Offset(valueL, valueT);
|
3745 |
+
}
|
3746 |
+
|
3747 |
+
function cumulativeScrollOffset(element) {
|
3748 |
+
var valueT = 0, valueL = 0;
|
3749 |
+
do {
|
3750 |
+
valueT += element.scrollTop || 0;
|
3751 |
+
valueL += element.scrollLeft || 0;
|
3752 |
+
element = element.parentNode;
|
3753 |
+
} while (element);
|
3754 |
+
return new Element.Offset(valueL, valueT);
|
3755 |
+
}
|
3756 |
+
|
3757 |
+
function viewportOffset(forElement) {
|
3758 |
+
element = $(element);
|
3759 |
+
var valueT = 0, valueL = 0, docBody = document.body;
|
3760 |
+
|
3761 |
+
var element = forElement;
|
3762 |
+
do {
|
3763 |
+
valueT += element.offsetTop || 0;
|
3764 |
+
valueL += element.offsetLeft || 0;
|
3765 |
+
if (element.offsetParent == docBody &&
|
3766 |
+
Element.getStyle(element, 'position') == 'absolute') break;
|
3767 |
+
} while (element = element.offsetParent);
|
3768 |
+
|
3769 |
+
element = forElement;
|
3770 |
+
do {
|
3771 |
+
if (element != docBody) {
|
3772 |
+
valueT -= element.scrollTop || 0;
|
3773 |
+
valueL -= element.scrollLeft || 0;
|
3774 |
+
}
|
3775 |
+
} while (element = element.parentNode);
|
3776 |
+
return new Element.Offset(valueL, valueT);
|
3777 |
+
}
|
3778 |
+
|
3779 |
+
function absolutize(element) {
|
3780 |
+
element = $(element);
|
3781 |
+
|
3782 |
+
if (Element.getStyle(element, 'position') === 'absolute') {
|
3783 |
+
return element;
|
3784 |
+
}
|
3785 |
+
|
3786 |
+
var offsetParent = getOffsetParent(element);
|
3787 |
+
var eOffset = element.viewportOffset(),
|
3788 |
+
pOffset = offsetParent.viewportOffset();
|
3789 |
+
|
3790 |
+
var offset = eOffset.relativeTo(pOffset);
|
3791 |
+
var layout = element.getLayout();
|
3792 |
+
|
3793 |
+
element.store('prototype_absolutize_original_styles', {
|
3794 |
+
left: element.getStyle('left'),
|
3795 |
+
top: element.getStyle('top'),
|
3796 |
+
width: element.getStyle('width'),
|
3797 |
+
height: element.getStyle('height')
|
3798 |
+
});
|
3799 |
+
|
3800 |
+
element.setStyle({
|
3801 |
+
position: 'absolute',
|
3802 |
+
top: offset.top + 'px',
|
3803 |
+
left: offset.left + 'px',
|
3804 |
+
width: layout.get('width') + 'px',
|
3805 |
+
height: layout.get('height') + 'px'
|
3806 |
+
});
|
3807 |
+
|
3808 |
+
return element;
|
3809 |
+
}
|
3810 |
+
|
3811 |
+
function relativize(element) {
|
3812 |
+
element = $(element);
|
3813 |
+
if (Element.getStyle(element, 'position') === 'relative') {
|
3814 |
+
return element;
|
3815 |
+
}
|
3816 |
+
|
3817 |
+
var originalStyles =
|
3818 |
+
element.retrieve('prototype_absolutize_original_styles');
|
3819 |
+
|
3820 |
+
if (originalStyles) element.setStyle(originalStyles);
|
3821 |
+
return element;
|
3822 |
+
}
|
3823 |
+
|
3824 |
+
if (Prototype.Browser.IE) {
|
3825 |
+
getOffsetParent = getOffsetParent.wrap(
|
3826 |
+
function(proceed, element) {
|
3827 |
+
element = $(element);
|
3828 |
+
|
3829 |
+
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
|
3830 |
+
return $(document.body);
|
3831 |
+
|
3832 |
+
var position = element.getStyle('position');
|
3833 |
+
if (position !== 'static') return proceed(element);
|
3834 |
+
|
3835 |
+
element.setStyle({ position: 'relative' });
|
3836 |
+
var value = proceed(element);
|
3837 |
+
element.setStyle({ position: position });
|
3838 |
+
return value;
|
3839 |
+
}
|
3840 |
+
);
|
3841 |
+
|
3842 |
+
positionedOffset = positionedOffset.wrap(function(proceed, element) {
|
3843 |
+
element = $(element);
|
3844 |
+
if (!element.parentNode) return new Element.Offset(0, 0);
|
3845 |
+
var position = element.getStyle('position');
|
3846 |
+
if (position !== 'static') return proceed(element);
|
3847 |
+
|
3848 |
+
var offsetParent = element.getOffsetParent();
|
3849 |
+
if (offsetParent && offsetParent.getStyle('position') === 'fixed')
|
3850 |
+
hasLayout(offsetParent);
|
3851 |
+
|
3852 |
+
element.setStyle({ position: 'relative' });
|
3853 |
+
var value = proceed(element);
|
3854 |
+
element.setStyle({ position: position });
|
3855 |
+
return value;
|
3856 |
+
});
|
3857 |
+
} else if (Prototype.Browser.Webkit) {
|
3858 |
+
cumulativeOffset = function(element) {
|
3859 |
+
element = $(element);
|
3860 |
+
var valueT = 0, valueL = 0;
|
3861 |
+
do {
|
3862 |
+
valueT += element.offsetTop || 0;
|
3863 |
+
valueL += element.offsetLeft || 0;
|
3864 |
+
if (element.offsetParent == document.body)
|
3865 |
+
if (Element.getStyle(element, 'position') == 'absolute') break;
|
3866 |
+
|
3867 |
+
element = element.offsetParent;
|
3868 |
+
} while (element);
|
3869 |
+
|
3870 |
+
return new Element.Offset(valueL, valueT);
|
3871 |
+
};
|
3872 |
+
}
|
3873 |
+
|
3874 |
+
|
3875 |
+
Element.addMethods({
|
3876 |
+
getLayout: getLayout,
|
3877 |
+
measure: measure,
|
3878 |
+
getDimensions: getDimensions,
|
3879 |
+
getOffsetParent: getOffsetParent,
|
3880 |
+
cumulativeOffset: cumulativeOffset,
|
3881 |
+
positionedOffset: positionedOffset,
|
3882 |
+
cumulativeScrollOffset: cumulativeScrollOffset,
|
3883 |
+
viewportOffset: viewportOffset,
|
3884 |
+
absolutize: absolutize,
|
3885 |
+
relativize: relativize
|
3886 |
+
});
|
3887 |
+
|
3888 |
+
function isBody(element) {
|
3889 |
+
return element.nodeName.toUpperCase() === 'BODY';
|
3890 |
+
}
|
3891 |
+
|
3892 |
+
function isHtml(element) {
|
3893 |
+
return element.nodeName.toUpperCase() === 'HTML';
|
3894 |
+
}
|
3895 |
+
|
3896 |
+
function isDocument(element) {
|
3897 |
+
return element.nodeType === Node.DOCUMENT_NODE;
|
3898 |
+
}
|
3899 |
+
|
3900 |
+
function isDetached(element) {
|
3901 |
+
return element !== document.body &&
|
3902 |
+
!Element.descendantOf(element, document.body);
|
3903 |
+
}
|
3904 |
+
|
3905 |
+
if ('getBoundingClientRect' in document.documentElement) {
|
3906 |
+
Element.addMethods({
|
3907 |
+
viewportOffset: function(element) {
|
3908 |
+
element = $(element);
|
3909 |
+
if (isDetached(element)) return new Element.Offset(0, 0);
|
3910 |
+
|
3911 |
+
var rect = element.getBoundingClientRect(),
|
3912 |
+
docEl = document.documentElement;
|
3913 |
+
return new Element.Offset(rect.left - docEl.clientLeft,
|
3914 |
+
rect.top - docEl.clientTop);
|
3915 |
+
}
|
3916 |
+
});
|
3917 |
+
}
|
3918 |
+
})();
|
3919 |
+
window.$$ = function() {
|
3920 |
+
var expression = $A(arguments).join(', ');
|
3921 |
+
return Prototype.Selector.select(expression, document);
|
3922 |
+
};
|
3923 |
+
|
3924 |
+
Prototype.Selector = (function() {
|
3925 |
+
|
3926 |
+
function select() {
|
3927 |
+
throw new Error('Method "Prototype.Selector.select" must be defined.');
|
3928 |
+
}
|
3929 |
+
|
3930 |
+
function match() {
|
3931 |
+
throw new Error('Method "Prototype.Selector.match" must be defined.');
|
3932 |
+
}
|
3933 |
+
|
3934 |
+
function find(elements, expression, index) {
|
3935 |
+
index = index || 0;
|
3936 |
+
var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
|
3937 |
+
|
3938 |
+
for (i = 0; i < length; i++) {
|
3939 |
+
if (match(elements[i], expression) && index == matchIndex++) {
|
3940 |
+
return Element.extend(elements[i]);
|
3941 |
+
}
|
3942 |
+
}
|
3943 |
+
}
|
3944 |
+
|
3945 |
+
function extendElements(elements) {
|
3946 |
+
for (var i = 0, length = elements.length; i < length; i++) {
|
3947 |
+
Element.extend(elements[i]);
|
3948 |
+
}
|
3949 |
+
return elements;
|
3950 |
+
}
|
3951 |
+
|
3952 |
+
|
3953 |
+
var K = Prototype.K;
|
3954 |
+
|
3955 |
+
return {
|
3956 |
+
select: select,
|
3957 |
+
match: match,
|
3958 |
+
find: find,
|
3959 |
+
extendElements: (Element.extend === K) ? K : extendElements,
|
3960 |
+
extendElement: Element.extend
|
3961 |
+
};
|
3962 |
+
})();
|
3963 |
+
/*!
|
3964 |
+
* Sizzle CSS Selector Engine - v1.0
|
3965 |
+
* Copyright 2009, The Dojo Foundation
|
3966 |
+
* Released under the MIT, BSD, and GPL Licenses.
|
3967 |
+
* More information: http://sizzlejs.com/
|
3968 |
+
*/
|
3969 |
+
(function(){
|
3970 |
+
|
3971 |
+
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
3972 |
+
done = 0,
|
3973 |
+
toString = Object.prototype.toString,
|
3974 |
+
hasDuplicate = false,
|
3975 |
+
baseHasDuplicate = true;
|
3976 |
+
|
3977 |
+
[0, 0].sort(function(){
|
3978 |
+
baseHasDuplicate = false;
|
3979 |
+
return 0;
|
3980 |
+
});
|
3981 |
+
|
3982 |
+
var Sizzle = function(selector, context, results, seed) {
|
3983 |
+
results = results || [];
|
3984 |
+
var origContext = context = context || document;
|
3985 |
+
|
3986 |
+
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
|
3987 |
+
return [];
|
3988 |
+
}
|
3989 |
+
|
3990 |
+
if ( !selector || typeof selector !== "string" ) {
|
3991 |
+
return results;
|
3992 |
+
}
|
3993 |
+
|
3994 |
+
var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
|
3995 |
+
soFar = selector;
|
3996 |
+
|
3997 |
+
while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
|
3998 |
+
soFar = m[3];
|
3999 |
+
|
4000 |
+
parts.push( m[1] );
|
4001 |
+
|
4002 |
+
if ( m[2] ) {
|
4003 |
+
extra = m[3];
|
4004 |
+
break;
|
4005 |
+
}
|
4006 |
+
}
|
4007 |
+
|
4008 |
+
if ( parts.length > 1 && origPOS.exec( selector ) ) {
|
4009 |
+
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
|
4010 |
+
set = posProcess( parts[0] + parts[1], context );
|
4011 |
+
} else {
|
4012 |
+
set = Expr.relative[ parts[0] ] ?
|
4013 |
+
[ context ] :
|
4014 |
+
Sizzle( parts.shift(), context );
|
4015 |
+
|
4016 |
+
while ( parts.length ) {
|
4017 |
+
selector = parts.shift();
|
4018 |
+
|
4019 |
+
if ( Expr.relative[ selector ] )
|
4020 |
+
selector += parts.shift();
|
4021 |
+
|
4022 |
+
set = posProcess( selector, set );
|
4023 |
+
}
|
4024 |
+
}
|
4025 |
+
} else {
|
4026 |
+
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
|
4027 |
+
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
|
4028 |
+
var ret = Sizzle.find( parts.shift(), context, contextXML );
|
4029 |
+
context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
|
4030 |
+
}
|
4031 |
+
|
4032 |
+
if ( context ) {
|
4033 |
+
var ret = seed ?
|
4034 |
+
{ expr: parts.pop(), set: makeArray(seed) } :
|
4035 |
+
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
|
4036 |
+
set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
|
4037 |
+
|
4038 |
+
if ( parts.length > 0 ) {
|
4039 |
+
checkSet = makeArray(set);
|
4040 |
+
} else {
|
4041 |
+
prune = false;
|
4042 |
+
}
|
4043 |
+
|
4044 |
+
while ( parts.length ) {
|
4045 |
+
var cur = parts.pop(), pop = cur;
|
4046 |
+
|
4047 |
+
if ( !Expr.relative[ cur ] ) {
|
4048 |
+
cur = "";
|
4049 |
+
} else {
|
4050 |
+
pop = parts.pop();
|
4051 |
+
}
|
4052 |
+
|
4053 |
+
if ( pop == null ) {
|
4054 |
+
pop = context;
|
4055 |
+
}
|
4056 |
+
|
4057 |
+
Expr.relative[ cur ]( checkSet, pop, contextXML );
|
4058 |
+
}
|
4059 |
+
} else {
|
4060 |
+
checkSet = parts = [];
|
4061 |
+
}
|
4062 |
+
}
|
4063 |
+
|
4064 |
+
if ( !checkSet ) {
|
4065 |
+
checkSet = set;
|
4066 |
+
}
|
4067 |
+
|
4068 |
+
if ( !checkSet ) {
|
4069 |
+
throw "Syntax error, unrecognized expression: " + (cur || selector);
|
4070 |
+
}
|
4071 |
+
|
4072 |
+
if ( toString.call(checkSet) === "[object Array]" ) {
|
4073 |
+
if ( !prune ) {
|
4074 |
+
results.push.apply( results, checkSet );
|
4075 |
+
} else if ( context && context.nodeType === 1 ) {
|
4076 |
+
for ( var i = 0; checkSet[i] != null; i++ ) {
|
4077 |
+
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
|
4078 |
+
results.push( set[i] );
|
4079 |
+
}
|
4080 |
+
}
|
4081 |
+
} else {
|
4082 |
+
for ( var i = 0; checkSet[i] != null; i++ ) {
|
4083 |
+
if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
|
4084 |
+
results.push( set[i] );
|
4085 |
+
}
|
4086 |
+
}
|
4087 |
+
}
|
4088 |
+
} else {
|
4089 |
+
makeArray( checkSet, results );
|
4090 |
+
}
|
4091 |
+
|
4092 |
+
if ( extra ) {
|
4093 |
+
Sizzle( extra, origContext, results, seed );
|
4094 |
+
Sizzle.uniqueSort( results );
|
4095 |
+
}
|
4096 |
+
|
4097 |
+
return results;
|
4098 |
+
};
|
4099 |
+
|
4100 |
+
Sizzle.uniqueSort = function(results){
|
4101 |
+
if ( sortOrder ) {
|
4102 |
+
hasDuplicate = baseHasDuplicate;
|
4103 |
+
results.sort(sortOrder);
|
4104 |
+
|
4105 |
+
if ( hasDuplicate ) {
|
4106 |
+
for ( var i = 1; i < results.length; i++ ) {
|
4107 |
+
if ( results[i] === results[i-1] ) {
|
4108 |
+
results.splice(i--, 1);
|
4109 |
+
}
|
4110 |
+
}
|
4111 |
+
}
|
4112 |
+
}
|
4113 |
+
|
4114 |
+
return results;
|
4115 |
+
};
|
4116 |
+
|
4117 |
+
Sizzle.matches = function(expr, set){
|
4118 |
+
return Sizzle(expr, null, null, set);
|
4119 |
+
};
|
4120 |
+
|
4121 |
+
Sizzle.find = function(expr, context, isXML){
|
4122 |
+
var set, match;
|
4123 |
+
|
4124 |
+
if ( !expr ) {
|
4125 |
+
return [];
|
4126 |
+
}
|
4127 |
+
|
4128 |
+
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
|
4129 |
+
var type = Expr.order[i], match;
|
4130 |
+
|
4131 |
+
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
|
4132 |
+
var left = match[1];
|
4133 |
+
match.splice(1,1);
|
4134 |
+
|
4135 |
+
if ( left.substr( left.length - 1 ) !== "\\" ) {
|
4136 |
+
match[1] = (match[1] || "").replace(/\\/g, "");
|
4137 |
+
set = Expr.find[ type ]( match, context, isXML );
|
4138 |
+
if ( set != null ) {
|
4139 |
+
expr = expr.replace( Expr.match[ type ], "" );
|
4140 |
+
break;
|
4141 |
+
}
|
4142 |
+
}
|
4143 |
+
}
|
4144 |
+
}
|
4145 |
+
|
4146 |
+
if ( !set ) {
|
4147 |
+
set = context.getElementsByTagName("*");
|
4148 |
+
}
|
4149 |
+
|
4150 |
+
return {set: set, expr: expr};
|
4151 |
+
};
|
4152 |
+
|
4153 |
+
Sizzle.filter = function(expr, set, inplace, not){
|
4154 |
+
var old = expr, result = [], curLoop = set, match, anyFound,
|
4155 |
+
isXMLFilter = set && set[0] && isXML(set[0]);
|
4156 |
+
|
4157 |
+
while ( expr && set.length ) {
|
4158 |
+
for ( var type in Expr.filter ) {
|
4159 |
+
if ( (match = Expr.match[ type ].exec( expr )) != null ) {
|
4160 |
+
var filter = Expr.filter[ type ], found, item;
|
4161 |
+
anyFound = false;
|
4162 |
+
|
4163 |
+
if ( curLoop == result ) {
|
4164 |
+
result = [];
|
4165 |
+
}
|
4166 |
+
|
4167 |
+
if ( Expr.preFilter[ type ] ) {
|
4168 |
+
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
|
4169 |
+
|
4170 |
+
if ( !match ) {
|
4171 |
+
anyFound = found = true;
|
4172 |
+
} else if ( match === true ) {
|
4173 |
+
continue;
|
4174 |
+
}
|
4175 |
+
}
|
4176 |
+
|
4177 |
+
if ( match ) {
|
4178 |
+
for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
|
4179 |
+
if ( item ) {
|
4180 |
+
found = filter( item, match, i, curLoop );
|
4181 |
+
var pass = not ^ !!found;
|
4182 |
+
|
4183 |
+
if ( inplace && found != null ) {
|
4184 |
+
if ( pass ) {
|
4185 |
+
anyFound = true;
|
4186 |
+
} else {
|
4187 |
+
curLoop[i] = false;
|
4188 |
+
}
|
4189 |
+
} else if ( pass ) {
|
4190 |
+
result.push( item );
|
4191 |
+
anyFound = true;
|
4192 |
+
}
|
4193 |
+
}
|
4194 |
+
}
|
4195 |
+
}
|
4196 |
+
|
4197 |
+
if ( found !== undefined ) {
|
4198 |
+
if ( !inplace ) {
|
4199 |
+
curLoop = result;
|
4200 |
+
}
|
4201 |
+
|
4202 |
+
expr = expr.replace( Expr.match[ type ], "" );
|
4203 |
+
|
4204 |
+
if ( !anyFound ) {
|
4205 |
+
return [];
|
4206 |
+
}
|
4207 |
+
|
4208 |
+
break;
|
4209 |
+
}
|
4210 |
+
}
|
4211 |
+
}
|
4212 |
+
|
4213 |
+
if ( expr == old ) {
|
4214 |
+
if ( anyFound == null ) {
|
4215 |
+
throw "Syntax error, unrecognized expression: " + expr;
|
4216 |
+
} else {
|
4217 |
+
break;
|
4218 |
+
}
|
4219 |
+
}
|
4220 |
+
|
4221 |
+
old = expr;
|
4222 |
+
}
|
4223 |
+
|
4224 |
+
return curLoop;
|
4225 |
+
};
|
4226 |
+
|
4227 |
+
var Expr = Sizzle.selectors = {
|
4228 |
+
order: [ "ID", "NAME", "TAG" ],
|
4229 |
+
match: {
|
4230 |
+
ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
4231 |
+
CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
4232 |
+
NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
|
4233 |
+
ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
|
4234 |
+
TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
|
4235 |
+
CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
|
4236 |
+
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
|
4237 |
+
PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
|
4238 |
+
},
|
4239 |
+
leftMatch: {},
|
4240 |
+
attrMap: {
|
4241 |
+
"class": "className",
|
4242 |
+
"for": "htmlFor"
|
4243 |
+
},
|
4244 |
+
attrHandle: {
|
4245 |
+
href: function(elem){
|
4246 |
+
return elem.getAttribute("href");
|
4247 |
+
}
|
4248 |
+
},
|
4249 |
+
relative: {
|
4250 |
+
"+": function(checkSet, part, isXML){
|
4251 |
+
var isPartStr = typeof part === "string",
|
4252 |
+
isTag = isPartStr && !/\W/.test(part),
|
4253 |
+
isPartStrNotTag = isPartStr && !isTag;
|
4254 |
+
|
4255 |
+
if ( isTag && !isXML ) {
|
4256 |
+
part = part.toUpperCase();
|
4257 |
+
}
|
4258 |
+
|
4259 |
+
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
|
4260 |
+
if ( (elem = checkSet[i]) ) {
|
4261 |
+
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
|
4262 |
+
|
4263 |
+
checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
|
4264 |
+
elem || false :
|
4265 |
+
elem === part;
|
4266 |
+
}
|
4267 |
+
}
|
4268 |
+
|
4269 |
+
if ( isPartStrNotTag ) {
|
4270 |
+
Sizzle.filter( part, checkSet, true );
|
4271 |
+
}
|
4272 |
+
},
|
4273 |
+
">": function(checkSet, part, isXML){
|
4274 |
+
var isPartStr = typeof part === "string";
|
4275 |
+
|
4276 |
+
if ( isPartStr && !/\W/.test(part) ) {
|
4277 |
+
part = isXML ? part : part.toUpperCase();
|
4278 |
+
|
4279 |
+
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
4280 |
+
var elem = checkSet[i];
|
4281 |
+
if ( elem ) {
|
4282 |
+
var parent = elem.parentNode;
|
4283 |
+
checkSet[i] = parent.nodeName === part ? parent : false;
|
4284 |
+
}
|
4285 |
+
}
|
4286 |
+
} else {
|
4287 |
+
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
4288 |
+
var elem = checkSet[i];
|
4289 |
+
if ( elem ) {
|
4290 |
+
checkSet[i] = isPartStr ?
|
4291 |
+
elem.parentNode :
|
4292 |
+
elem.parentNode === part;
|
4293 |
+
}
|
4294 |
+
}
|
4295 |
+
|
4296 |
+
if ( isPartStr ) {
|
4297 |
+
Sizzle.filter( part, checkSet, true );
|
4298 |
+
}
|
4299 |
+
}
|
4300 |
+
},
|
4301 |
+
"": function(checkSet, part, isXML){
|
4302 |
+
var doneName = done++, checkFn = dirCheck;
|
4303 |
+
|
4304 |
+
if ( !/\W/.test(part) ) {
|
4305 |
+
var nodeCheck = part = isXML ? part : part.toUpperCase();
|
4306 |
+
checkFn = dirNodeCheck;
|
4307 |
+
}
|
4308 |
+
|
4309 |
+
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
|
4310 |
+
},
|
4311 |
+
"~": function(checkSet, part, isXML){
|
4312 |
+
var doneName = done++, checkFn = dirCheck;
|
4313 |
+
|
4314 |
+
if ( typeof part === "string" && !/\W/.test(part) ) {
|
4315 |
+
var nodeCheck = part = isXML ? part : part.toUpperCase();
|
4316 |
+
checkFn = dirNodeCheck;
|
4317 |
+
}
|
4318 |
+
|
4319 |
+
checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
|
4320 |
+
}
|
4321 |
+
},
|
4322 |
+
find: {
|
4323 |
+
ID: function(match, context, isXML){
|
4324 |
+
if ( typeof context.getElementById !== "undefined" && !isXML ) {
|
4325 |
+
var m = context.getElementById(match[1]);
|
4326 |
+
return m ? [m] : [];
|
4327 |
+
}
|
4328 |
+
},
|
4329 |
+
NAME: function(match, context, isXML){
|
4330 |
+
if ( typeof context.getElementsByName !== "undefined" ) {
|
4331 |
+
var ret = [], results = context.getElementsByName(match[1]);
|
4332 |
+
|
4333 |
+
for ( var i = 0, l = results.length; i < l; i++ ) {
|
4334 |
+
if ( results[i].getAttribute("name") === match[1] ) {
|
4335 |
+
ret.push( results[i] );
|
4336 |
+
}
|
4337 |
+
}
|
4338 |
+
|
4339 |
+
return ret.length === 0 ? null : ret;
|
4340 |
+
}
|
4341 |
+
},
|
4342 |
+
TAG: function(match, context){
|
4343 |
+
return context.getElementsByTagName(match[1]);
|
4344 |
+
}
|
4345 |
+
},
|
4346 |
+
preFilter: {
|
4347 |
+
CLASS: function(match, curLoop, inplace, result, not, isXML){
|
4348 |
+
match = " " + match[1].replace(/\\/g, "") + " ";
|
4349 |
+
|
4350 |
+
if ( isXML ) {
|
4351 |
+
return match;
|
4352 |
+
}
|
4353 |
+
|
4354 |
+
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
|
4355 |
+
if ( elem ) {
|
4356 |
+
if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
|
4357 |
+
if ( !inplace )
|
4358 |
+
result.push( elem );
|
4359 |
+
} else if ( inplace ) {
|
4360 |
+
curLoop[i] = false;
|
4361 |
+
}
|
4362 |
+
}
|
4363 |
+
}
|
4364 |
+
|
4365 |
+
return false;
|
4366 |
+
},
|
4367 |
+
ID: function(match){
|
4368 |
+
return match[1].replace(/\\/g, "");
|
4369 |
+
},
|
4370 |
+
TAG: function(match, curLoop){
|
4371 |
+
for ( var i = 0; curLoop[i] === false; i++ ){}
|
4372 |
+
return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
|
4373 |
+
},
|
4374 |
+
CHILD: function(match){
|
4375 |
+
if ( match[1] == "nth" ) {
|
4376 |
+
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
|
4377 |
+
match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
|
4378 |
+
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
|
4379 |
+
|
4380 |
+
match[2] = (test[1] + (test[2] || 1)) - 0;
|
4381 |
+
match[3] = test[3] - 0;
|
4382 |
+
}
|
4383 |
+
|
4384 |
+
match[0] = done++;
|
4385 |
+
|
4386 |
+
return match;
|
4387 |
+
},
|
4388 |
+
ATTR: function(match, curLoop, inplace, result, not, isXML){
|
4389 |
+
var name = match[1].replace(/\\/g, "");
|
4390 |
+
|
4391 |
+
if ( !isXML && Expr.attrMap[name] ) {
|
4392 |
+
match[1] = Expr.attrMap[name];
|
4393 |
+
}
|
4394 |
+
|
4395 |
+
if ( match[2] === "~=" ) {
|
4396 |
+
match[4] = " " + match[4] + " ";
|
4397 |
+
}
|
4398 |
+
|
4399 |
+
return match;
|
4400 |
+
},
|
4401 |
+
PSEUDO: function(match, curLoop, inplace, result, not){
|
4402 |
+
if ( match[1] === "not" ) {
|
4403 |
+
if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
|
4404 |
+
match[3] = Sizzle(match[3], null, null, curLoop);
|
4405 |
+
} else {
|
4406 |
+
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
|
4407 |
+
if ( !inplace ) {
|
4408 |
+
result.push.apply( result, ret );
|
4409 |
+
}
|
4410 |
+
return false;
|
4411 |
+
}
|
4412 |
+
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
|
4413 |
+
return true;
|
4414 |
+
}
|
4415 |
+
|
4416 |
+
return match;
|
4417 |
+
},
|
4418 |
+
POS: function(match){
|
4419 |
+
match.unshift( true );
|
4420 |
+
return match;
|
4421 |
+
}
|
4422 |
+
},
|
4423 |
+
filters: {
|
4424 |
+
enabled: function(elem){
|
4425 |
+
return elem.disabled === false && elem.type !== "hidden";
|
4426 |
+
},
|
4427 |
+
disabled: function(elem){
|
4428 |
+
return elem.disabled === true;
|
4429 |
+
},
|
4430 |
+
checked: function(elem){
|
4431 |
+
return elem.checked === true;
|
4432 |
+
},
|
4433 |
+
selected: function(elem){
|
4434 |
+
elem.parentNode.selectedIndex;
|
4435 |
+
return elem.selected === true;
|
4436 |
+
},
|
4437 |
+
parent: function(elem){
|
4438 |
+
return !!elem.firstChild;
|
4439 |
+
},
|
4440 |
+
empty: function(elem){
|
4441 |
+
return !elem.firstChild;
|
4442 |
+
},
|
4443 |
+
has: function(elem, i, match){
|
4444 |
+
return !!Sizzle( match[3], elem ).length;
|
4445 |
+
},
|
4446 |
+
header: function(elem){
|
4447 |
+
return /h\d/i.test( elem.nodeName );
|
4448 |
+
},
|
4449 |
+
text: function(elem){
|
4450 |
+
return "text" === elem.type;
|
4451 |
+
},
|
4452 |
+
radio: function(elem){
|
4453 |
+
return "radio" === elem.type;
|
4454 |
+
},
|
4455 |
+
checkbox: function(elem){
|
4456 |
+
return "checkbox" === elem.type;
|
4457 |
+
},
|
4458 |
+
file: function(elem){
|
4459 |
+
return "file" === elem.type;
|
4460 |
+
},
|
4461 |
+
password: function(elem){
|
4462 |
+
return "password" === elem.type;
|
4463 |
+
},
|
4464 |
+
submit: function(elem){
|
4465 |
+
return "submit" === elem.type;
|
4466 |
+
},
|
4467 |
+
image: function(elem){
|
4468 |
+
return "image" === elem.type;
|
4469 |
+
},
|
4470 |
+
reset: function(elem){
|
4471 |
+
return "reset" === elem.type;
|
4472 |
+
},
|
4473 |
+
button: function(elem){
|
4474 |
+
return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
|
4475 |
+
},
|
4476 |
+
input: function(elem){
|
4477 |
+
return /input|select|textarea|button/i.test(elem.nodeName);
|
4478 |
+
}
|
4479 |
+
},
|
4480 |
+
setFilters: {
|
4481 |
+
first: function(elem, i){
|
4482 |
+
return i === 0;
|
4483 |
+
},
|
4484 |
+
last: function(elem, i, match, array){
|
4485 |
+
return i === array.length - 1;
|
4486 |
+
},
|
4487 |
+
even: function(elem, i){
|
4488 |
+
return i % 2 === 0;
|
4489 |
+
},
|
4490 |
+
odd: function(elem, i){
|
4491 |
+
return i % 2 === 1;
|
4492 |
+
},
|
4493 |
+
lt: function(elem, i, match){
|
4494 |
+
return i < match[3] - 0;
|
4495 |
+
},
|
4496 |
+
gt: function(elem, i, match){
|
4497 |
+
return i > match[3] - 0;
|
4498 |
+
},
|
4499 |
+
nth: function(elem, i, match){
|
4500 |
+
return match[3] - 0 == i;
|
4501 |
+
},
|
4502 |
+
eq: function(elem, i, match){
|
4503 |
+
return match[3] - 0 == i;
|
4504 |
+
}
|
4505 |
+
},
|
4506 |
+
filter: {
|
4507 |
+
PSEUDO: function(elem, match, i, array){
|
4508 |
+
var name = match[1], filter = Expr.filters[ name ];
|
4509 |
+
|
4510 |
+
if ( filter ) {
|
4511 |
+
return filter( elem, i, match, array );
|
4512 |
+
} else if ( name === "contains" ) {
|
4513 |
+
return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
|
4514 |
+
} else if ( name === "not" ) {
|
4515 |
+
var not = match[3];
|
4516 |
+
|
4517 |
+
for ( var i = 0, l = not.length; i < l; i++ ) {
|
4518 |
+
if ( not[i] === elem ) {
|
4519 |
+
return false;
|
4520 |
+
}
|
4521 |
+
}
|
4522 |
+
|
4523 |
+
return true;
|
4524 |
+
}
|
4525 |
+
},
|
4526 |
+
CHILD: function(elem, match){
|
4527 |
+
var type = match[1], node = elem;
|
4528 |
+
switch (type) {
|
4529 |
+
case 'only':
|
4530 |
+
case 'first':
|
4531 |
+
while ( (node = node.previousSibling) ) {
|
4532 |
+
if ( node.nodeType === 1 ) return false;
|
4533 |
+
}
|
4534 |
+
if ( type == 'first') return true;
|
4535 |
+
node = elem;
|
4536 |
+
case 'last':
|
4537 |
+
while ( (node = node.nextSibling) ) {
|
4538 |
+
if ( node.nodeType === 1 ) return false;
|
4539 |
+
}
|
4540 |
+
return true;
|
4541 |
+
case 'nth':
|
4542 |
+
var first = match[2], last = match[3];
|
4543 |
+
|
4544 |
+
if ( first == 1 && last == 0 ) {
|
4545 |
+
return true;
|
4546 |
+
}
|
4547 |
+
|
4548 |
+
var doneName = match[0],
|
4549 |
+
parent = elem.parentNode;
|
4550 |
+
|
4551 |
+
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
|
4552 |
+
var count = 0;
|
4553 |
+
for ( node = parent.firstChild; node; node = node.nextSibling ) {
|
4554 |
+
if ( node.nodeType === 1 ) {
|
4555 |
+
node.nodeIndex = ++count;
|
4556 |
+
}
|
4557 |
+
}
|
4558 |
+
parent.sizcache = doneName;
|
4559 |
+
}
|
4560 |
+
|
4561 |
+
var diff = elem.nodeIndex - last;
|
4562 |
+
if ( first == 0 ) {
|
4563 |
+
return diff == 0;
|
4564 |
+
} else {
|
4565 |
+
return ( diff % first == 0 && diff / first >= 0 );
|
4566 |
+
}
|
4567 |
+
}
|
4568 |
+
},
|
4569 |
+
ID: function(elem, match){
|
4570 |
+
return elem.nodeType === 1 && elem.getAttribute("id") === match;
|
4571 |
+
},
|
4572 |
+
TAG: function(elem, match){
|
4573 |
+
return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
|
4574 |
+
},
|
4575 |
+
CLASS: function(elem, match){
|
4576 |
+
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
4577 |
+
.indexOf( match ) > -1;
|
4578 |
+
},
|
4579 |
+
ATTR: function(elem, match){
|
4580 |
+
var name = match[1],
|
4581 |
+
result = Expr.attrHandle[ name ] ?
|
4582 |
+
Expr.attrHandle[ name ]( elem ) :
|
4583 |
+
elem[ name ] != null ?
|
4584 |
+
elem[ name ] :
|
4585 |
+
elem.getAttribute( name ),
|
4586 |
+
value = result + "",
|
4587 |
+
type = match[2],
|
4588 |
+
check = match[4];
|
4589 |
+
|
4590 |
+
return result == null ?
|
4591 |
+
type === "!=" :
|
4592 |
+
type === "=" ?
|
4593 |
+
value === check :
|
4594 |
+
type === "*=" ?
|
4595 |
+
value.indexOf(check) >= 0 :
|
4596 |
+
type === "~=" ?
|
4597 |
+
(" " + value + " ").indexOf(check) >= 0 :
|
4598 |
+
!check ?
|
4599 |
+
value && result !== false :
|
4600 |
+
type === "!=" ?
|
4601 |
+
value != check :
|
4602 |
+
type === "^=" ?
|
4603 |
+
value.indexOf(check) === 0 :
|
4604 |
+
type === "$=" ?
|
4605 |
+
value.substr(value.length - check.length) === check :
|
4606 |
+
type === "|=" ?
|
4607 |
+
value === check || value.substr(0, check.length + 1) === check + "-" :
|
4608 |
+
false;
|
4609 |
+
},
|
4610 |
+
POS: function(elem, match, i, array){
|
4611 |
+
var name = match[2], filter = Expr.setFilters[ name ];
|
4612 |
+
|
4613 |
+
if ( filter ) {
|
4614 |
+
return filter( elem, i, match, array );
|
4615 |
+
}
|
4616 |
+
}
|
4617 |
+
}
|
4618 |
+
};
|
4619 |
+
|
4620 |
+
var origPOS = Expr.match.POS;
|
4621 |
+
|
4622 |
+
for ( var type in Expr.match ) {
|
4623 |
+
Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
|
4624 |
+
Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
|
4625 |
+
}
|
4626 |
+
|
4627 |
+
var makeArray = function(array, results) {
|
4628 |
+
array = Array.prototype.slice.call( array, 0 );
|
4629 |
+
|
4630 |
+
if ( results ) {
|
4631 |
+
results.push.apply( results, array );
|
4632 |
+
return results;
|
4633 |
+
}
|
4634 |
+
|
4635 |
+
return array;
|
4636 |
+
};
|
4637 |
+
|
4638 |
+
try {
|
4639 |
+
Array.prototype.slice.call( document.documentElement.childNodes, 0 );
|
4640 |
+
|
4641 |
+
} catch(e){
|
4642 |
+
makeArray = function(array, results) {
|
4643 |
+
var ret = results || [];
|
4644 |
+
|
4645 |
+
if ( toString.call(array) === "[object Array]" ) {
|
4646 |
+
Array.prototype.push.apply( ret, array );
|
4647 |
+
} else {
|
4648 |
+
if ( typeof array.length === "number" ) {
|
4649 |
+
for ( var i = 0, l = array.length; i < l; i++ ) {
|
4650 |
+
ret.push( array[i] );
|
4651 |
+
}
|
4652 |
+
} else {
|
4653 |
+
for ( var i = 0; array[i]; i++ ) {
|
4654 |
+
ret.push( array[i] );
|
4655 |
+
}
|
4656 |
+
}
|
4657 |
+
}
|
4658 |
+
|
4659 |
+
return ret;
|
4660 |
+
};
|
4661 |
+
}
|
4662 |
+
|
4663 |
+
var sortOrder;
|
4664 |
+
|
4665 |
+
if ( document.documentElement.compareDocumentPosition ) {
|
4666 |
+
sortOrder = function( a, b ) {
|
4667 |
+
if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
|
4668 |
+
if ( a == b ) {
|
4669 |
+
hasDuplicate = true;
|
4670 |
+
}
|
4671 |
+
return 0;
|
4672 |
+
}
|
4673 |
+
|
4674 |
+
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
|
4675 |
+
if ( ret === 0 ) {
|
4676 |
+
hasDuplicate = true;
|
4677 |
+
}
|
4678 |
+
return ret;
|
4679 |
+
};
|
4680 |
+
} else if ( "sourceIndex" in document.documentElement ) {
|
4681 |
+
sortOrder = function( a, b ) {
|
4682 |
+
if ( !a.sourceIndex || !b.sourceIndex ) {
|
4683 |
+
if ( a == b ) {
|
4684 |
+
hasDuplicate = true;
|
4685 |
+
}
|
4686 |
+
return 0;
|
4687 |
+
}
|
4688 |
+
|
4689 |
+
var ret = a.sourceIndex - b.sourceIndex;
|
4690 |
+
if ( ret === 0 ) {
|
4691 |
+
hasDuplicate = true;
|
4692 |
+
}
|
4693 |
+
return ret;
|
4694 |
+
};
|
4695 |
+
} else if ( document.createRange ) {
|
4696 |
+
sortOrder = function( a, b ) {
|
4697 |
+
if ( !a.ownerDocument || !b.ownerDocument ) {
|
4698 |
+
if ( a == b ) {
|
4699 |
+
hasDuplicate = true;
|
4700 |
+
}
|
4701 |
+
return 0;
|
4702 |
+
}
|
4703 |
+
|
4704 |
+
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
|
4705 |
+
aRange.setStart(a, 0);
|
4706 |
+
aRange.setEnd(a, 0);
|
4707 |
+
bRange.setStart(b, 0);
|
4708 |
+
bRange.setEnd(b, 0);
|
4709 |
+
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
|
4710 |
+
if ( ret === 0 ) {
|
4711 |
+
hasDuplicate = true;
|
4712 |
+
}
|
4713 |
+
return ret;
|
4714 |
+
};
|
4715 |
+
}
|
4716 |
+
|
4717 |
+
(function(){
|
4718 |
+
var form = document.createElement("div"),
|
4719 |
+
id = "script" + (new Date).getTime();
|
4720 |
+
form.innerHTML = "<a name='" + id + "'/>";
|
4721 |
+
|
4722 |
+
var root = document.documentElement;
|
4723 |
+
root.insertBefore( form, root.firstChild );
|
4724 |
+
|
4725 |
+
if ( !!document.getElementById( id ) ) {
|
4726 |
+
Expr.find.ID = function(match, context, isXML){
|
4727 |
+
if ( typeof context.getElementById !== "undefined" && !isXML ) {
|
4728 |
+
var m = context.getElementById(match[1]);
|
4729 |
+
return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
|
4730 |
+
}
|
4731 |
+
};
|
4732 |
+
|
4733 |
+
Expr.filter.ID = function(elem, match){
|
4734 |
+
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
|
4735 |
+
return elem.nodeType === 1 && node && node.nodeValue === match;
|
4736 |
+
};
|
4737 |
+
}
|
4738 |
+
|
4739 |
+
root.removeChild( form );
|
4740 |
+
root = form = null; // release memory in IE
|
4741 |
+
})();
|
4742 |
+
|
4743 |
+
(function(){
|
4744 |
+
|
4745 |
+
var div = document.createElement("div");
|
4746 |
+
div.appendChild( document.createComment("") );
|
4747 |
+
|
4748 |
+
if ( div.getElementsByTagName("*").length > 0 ) {
|
4749 |
+
Expr.find.TAG = function(match, context){
|
4750 |
+
var results = context.getElementsByTagName(match[1]);
|
4751 |
+
|
4752 |
+
if ( match[1] === "*" ) {
|
4753 |
+
var tmp = [];
|
4754 |
+
|
4755 |
+
for ( var i = 0; results[i]; i++ ) {
|
4756 |
+
if ( results[i].nodeType === 1 ) {
|
4757 |
+
tmp.push( results[i] );
|
4758 |
+
}
|
4759 |
+
}
|
4760 |
+
|
4761 |
+
results = tmp;
|
4762 |
+
}
|
4763 |
+
|
4764 |
+
return results;
|
4765 |
+
};
|
4766 |
+
}
|
4767 |
+
|
4768 |
+
div.innerHTML = "<a href='#'></a>";
|
4769 |
+
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
|
4770 |
+
div.firstChild.getAttribute("href") !== "#" ) {
|
4771 |
+
Expr.attrHandle.href = function(elem){
|
4772 |
+
return elem.getAttribute("href", 2);
|
4773 |
+
};
|
4774 |
+
}
|
4775 |
+
|
4776 |
+
div = null; // release memory in IE
|
4777 |
+
})();
|
4778 |
+
|
4779 |
+
if ( document.querySelectorAll ) (function(){
|
4780 |
+
var oldSizzle = Sizzle, div = document.createElement("div");
|
4781 |
+
div.innerHTML = "<p class='TEST'></p>";
|
4782 |
+
|
4783 |
+
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
|
4784 |
+
return;
|
4785 |
+
}
|
4786 |
+
|
4787 |
+
Sizzle = function(query, context, extra, seed){
|
4788 |
+
context = context || document;
|
4789 |
+
|
4790 |
+
if ( !seed && context.nodeType === 9 && !isXML(context) ) {
|
4791 |
+
try {
|
4792 |
+
return makeArray( context.querySelectorAll(query), extra );
|
4793 |
+
} catch(e){}
|
4794 |
+
}
|
4795 |
+
|
4796 |
+
return oldSizzle(query, context, extra, seed);
|
4797 |
+
};
|
4798 |
+
|
4799 |
+
for ( var prop in oldSizzle ) {
|
4800 |
+
Sizzle[ prop ] = oldSizzle[ prop ];
|
4801 |
+
}
|
4802 |
+
|
4803 |
+
div = null; // release memory in IE
|
4804 |
+
})();
|
4805 |
+
|
4806 |
+
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
|
4807 |
+
var div = document.createElement("div");
|
4808 |
+
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
|
4809 |
+
|
4810 |
+
if ( div.getElementsByClassName("e").length === 0 )
|
4811 |
+
return;
|
4812 |
+
|
4813 |
+
div.lastChild.className = "e";
|
4814 |
+
|
4815 |
+
if ( div.getElementsByClassName("e").length === 1 )
|
4816 |
+
return;
|
4817 |
+
|
4818 |
+
Expr.order.splice(1, 0, "CLASS");
|
4819 |
+
Expr.find.CLASS = function(match, context, isXML) {
|
4820 |
+
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
|
4821 |
+
return context.getElementsByClassName(match[1]);
|
4822 |
+
}
|
4823 |
+
};
|
4824 |
+
|
4825 |
+
div = null; // release memory in IE
|
4826 |
+
})();
|
4827 |
+
|
4828 |
+
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
4829 |
+
var sibDir = dir == "previousSibling" && !isXML;
|
4830 |
+
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
4831 |
+
var elem = checkSet[i];
|
4832 |
+
if ( elem ) {
|
4833 |
+
if ( sibDir && elem.nodeType === 1 ){
|
4834 |
+
elem.sizcache = doneName;
|
4835 |
+
elem.sizset = i;
|
4836 |
+
}
|
4837 |
+
elem = elem[dir];
|
4838 |
+
var match = false;
|
4839 |
+
|
4840 |
+
while ( elem ) {
|
4841 |
+
if ( elem.sizcache === doneName ) {
|
4842 |
+
match = checkSet[elem.sizset];
|
4843 |
+
break;
|
4844 |
+
}
|
4845 |
+
|
4846 |
+
if ( elem.nodeType === 1 && !isXML ){
|
4847 |
+
elem.sizcache = doneName;
|
4848 |
+
elem.sizset = i;
|
4849 |
+
}
|
4850 |
+
|
4851 |
+
if ( elem.nodeName === cur ) {
|
4852 |
+
match = elem;
|
4853 |
+
break;
|
4854 |
+
}
|
4855 |
+
|
4856 |
+
elem = elem[dir];
|
4857 |
+
}
|
4858 |
+
|
4859 |
+
checkSet[i] = match;
|
4860 |
+
}
|
4861 |
+
}
|
4862 |
+
}
|
4863 |
+
|
4864 |
+
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
4865 |
+
var sibDir = dir == "previousSibling" && !isXML;
|
4866 |
+
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
4867 |
+
var elem = checkSet[i];
|
4868 |
+
if ( elem ) {
|
4869 |
+
if ( sibDir && elem.nodeType === 1 ) {
|
4870 |
+
elem.sizcache = doneName;
|
4871 |
+
elem.sizset = i;
|
4872 |
+
}
|
4873 |
+
elem = elem[dir];
|
4874 |
+
var match = false;
|
4875 |
+
|
4876 |
+
while ( elem ) {
|
4877 |
+
if ( elem.sizcache === doneName ) {
|
4878 |
+
match = checkSet[elem.sizset];
|
4879 |
+
break;
|
4880 |
+
}
|
4881 |
+
|
4882 |
+
if ( elem.nodeType === 1 ) {
|
4883 |
+
if ( !isXML ) {
|
4884 |
+
elem.sizcache = doneName;
|
4885 |
+
elem.sizset = i;
|
4886 |
+
}
|
4887 |
+
if ( typeof cur !== "string" ) {
|
4888 |
+
if ( elem === cur ) {
|
4889 |
+
match = true;
|
4890 |
+
break;
|
4891 |
+
}
|
4892 |
+
|
4893 |
+
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
|
4894 |
+
match = elem;
|
4895 |
+
break;
|
4896 |
+
}
|
4897 |
+
}
|
4898 |
+
|
4899 |
+
elem = elem[dir];
|
4900 |
+
}
|
4901 |
+
|
4902 |
+
checkSet[i] = match;
|
4903 |
+
}
|
4904 |
+
}
|
4905 |
+
}
|
4906 |
+
|
4907 |
+
var contains = document.compareDocumentPosition ? function(a, b){
|
4908 |
+
return a.compareDocumentPosition(b) & 16;
|
4909 |
+
} : function(a, b){
|
4910 |
+
return a !== b && (a.contains ? a.contains(b) : true);
|
4911 |
+
};
|
4912 |
+
|
4913 |
+
var isXML = function(elem){
|
4914 |
+
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
|
4915 |
+
!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
|
4916 |
+
};
|
4917 |
+
|
4918 |
+
var posProcess = function(selector, context){
|
4919 |
+
var tmpSet = [], later = "", match,
|
4920 |
+
root = context.nodeType ? [context] : context;
|
4921 |
+
|
4922 |
+
while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
|
4923 |
+
later += match[0];
|
4924 |
+
selector = selector.replace( Expr.match.PSEUDO, "" );
|
4925 |
+
}
|
4926 |
+
|
4927 |
+
selector = Expr.relative[selector] ? selector + "*" : selector;
|
4928 |
+
|
4929 |
+
for ( var i = 0, l = root.length; i < l; i++ ) {
|
4930 |
+
Sizzle( selector, root[i], tmpSet );
|
4931 |
+
}
|
4932 |
+
|
4933 |
+
return Sizzle.filter( later, tmpSet );
|
4934 |
+
};
|
4935 |
+
|
4936 |
+
|
4937 |
+
window.Sizzle = Sizzle;
|
4938 |
+
|
4939 |
+
})();
|
4940 |
+
|
4941 |
+
Prototype._original_property = window.Sizzle;
|
4942 |
+
|
4943 |
+
;(function(engine) {
|
4944 |
+
var extendElements = Prototype.Selector.extendElements;
|
4945 |
+
|
4946 |
+
function select(selector, scope) {
|
4947 |
+
return extendElements(engine(selector, scope || document));
|
4948 |
+
}
|
4949 |
+
|
4950 |
+
function match(element, selector) {
|
4951 |
+
return engine.matches(selector, [element]).length == 1;
|
4952 |
+
}
|
4953 |
+
|
4954 |
+
Prototype.Selector.engine = engine;
|
4955 |
+
Prototype.Selector.select = select;
|
4956 |
+
Prototype.Selector.match = match;
|
4957 |
+
})(Sizzle);
|
4958 |
+
|
4959 |
+
window.Sizzle = Prototype._original_property;
|
4960 |
+
delete Prototype._original_property;
|
4961 |
+
|
4962 |
+
var Form = {
|
4963 |
+
reset: function(form) {
|
4964 |
+
form = $(form);
|
4965 |
+
form.reset();
|
4966 |
+
return form;
|
4967 |
+
},
|
4968 |
+
|
4969 |
+
serializeElements: function(elements, options) {
|
4970 |
+
if (typeof options != 'object') options = { hash: !!options };
|
4971 |
+
else if (Object.isUndefined(options.hash)) options.hash = true;
|
4972 |
+
var key, value, submitted = false, submit = options.submit, accumulator, initial;
|
4973 |
+
|
4974 |
+
if (options.hash) {
|
4975 |
+
initial = {};
|
4976 |
+
accumulator = function(result, key, value) {
|
4977 |
+
if (key in result) {
|
4978 |
+
if (!Object.isArray(result[key])) result[key] = [result[key]];
|
4979 |
+
result[key].push(value);
|
4980 |
+
} else result[key] = value;
|
4981 |
+
return result;
|
4982 |
+
};
|
4983 |
+
} else {
|
4984 |
+
initial = '';
|
4985 |
+
accumulator = function(result, key, value) {
|
4986 |
+
return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
4987 |
+
}
|
4988 |
+
}
|
4989 |
+
|
4990 |
+
return elements.inject(initial, function(result, element) {
|
4991 |
+
if (!element.disabled && element.name) {
|
4992 |
+
key = element.name; value = $(element).getValue();
|
4993 |
+
if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
|
4994 |
+
submit !== false && (!submit || key == submit) && (submitted = true)))) {
|
4995 |
+
result = accumulator(result, key, value);
|
4996 |
+
}
|
4997 |
+
}
|
4998 |
+
return result;
|
4999 |
+
});
|
5000 |
+
}
|
5001 |
+
};
|
5002 |
+
|
5003 |
+
Form.Methods = {
|
5004 |
+
serialize: function(form, options) {
|
5005 |
+
return Form.serializeElements(Form.getElements(form), options);
|
5006 |
+
},
|
5007 |
+
|
5008 |
+
getElements: function(form) {
|
5009 |
+
var elements = $(form).getElementsByTagName('*'),
|
5010 |
+
element,
|
5011 |
+
arr = [ ],
|
5012 |
+
serializers = Form.Element.Serializers;
|
5013 |
+
for (var i = 0; element = elements[i]; i++) {
|
5014 |
+
arr.push(element);
|
5015 |
+
}
|
5016 |
+
return arr.inject([], function(elements, child) {
|
5017 |
+
if (serializers[child.tagName.toLowerCase()])
|
5018 |
+
elements.push(Element.extend(child));
|
5019 |
+
return elements;
|
5020 |
+
})
|
5021 |
+
},
|
5022 |
+
|
5023 |
+
getInputs: function(form, typeName, name) {
|
5024 |
+
form = $(form);
|
5025 |
+
var inputs = form.getElementsByTagName('input');
|
5026 |
+
|
5027 |
+
if (!typeName && !name) return $A(inputs).map(Element.extend);
|
5028 |
+
|
5029 |
+
for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
|
5030 |
+
var input = inputs[i];
|
5031 |
+
if ((typeName && input.type != typeName) || (name && input.name != name))
|
5032 |
+
continue;
|
5033 |
+
matchingInputs.push(Element.extend(input));
|
5034 |
+
}
|
5035 |
+
|
5036 |
+
return matchingInputs;
|
5037 |
+
},
|
5038 |
+
|
5039 |
+
disable: function(form) {
|
5040 |
+
form = $(form);
|
5041 |
+
Form.getElements(form).invoke('disable');
|
5042 |
+
return form;
|
5043 |
+
},
|
5044 |
+
|
5045 |
+
enable: function(form) {
|
5046 |
+
form = $(form);
|
5047 |
+
Form.getElements(form).invoke('enable');
|
5048 |
+
return form;
|
5049 |
+
},
|
5050 |
+
|
5051 |
+
findFirstElement: function(form) {
|
5052 |
+
var elements = $(form).getElements().findAll(function(element) {
|
5053 |
+
return 'hidden' != element.type && !element.disabled;
|
5054 |
+
});
|
5055 |
+
var firstByIndex = elements.findAll(function(element) {
|
5056 |
+
return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
|
5057 |
+
}).sortBy(function(element) { return element.tabIndex }).first();
|
5058 |
+
|
5059 |
+
return firstByIndex ? firstByIndex : elements.find(function(element) {
|
5060 |
+
return /^(?:input|select|textarea)$/i.test(element.tagName);
|
5061 |
+
});
|
5062 |
+
},
|
5063 |
+
|
5064 |
+
focusFirstElement: function(form) {
|
5065 |
+
form = $(form);
|
5066 |
+
var element = form.findFirstElement();
|
5067 |
+
if (element) element.activate();
|
5068 |
+
return form;
|
5069 |
+
},
|
5070 |
+
|
5071 |
+
request: function(form, options) {
|
5072 |
+
form = $(form), options = Object.clone(options || { });
|
5073 |
+
|
5074 |
+
var params = options.parameters, action = form.readAttribute('action') || '';
|
5075 |
+
if (action.blank()) action = window.location.href;
|
5076 |
+
options.parameters = form.serialize(true);
|
5077 |
+
|
5078 |
+
if (params) {
|
5079 |
+
if (Object.isString(params)) params = params.toQueryParams();
|
5080 |
+
Object.extend(options.parameters, params);
|
5081 |
+
}
|
5082 |
+
|
5083 |
+
if (form.hasAttribute('method') && !options.method)
|
5084 |
+
options.method = form.method;
|
5085 |
+
|
5086 |
+
return new Ajax.Request(action, options);
|
5087 |
+
}
|
5088 |
+
};
|
5089 |
+
|
5090 |
+
/*--------------------------------------------------------------------------*/
|
5091 |
+
|
5092 |
+
|
5093 |
+
Form.Element = {
|
5094 |
+
focus: function(element) {
|
5095 |
+
$(element).focus();
|
5096 |
+
return element;
|
5097 |
+
},
|
5098 |
+
|
5099 |
+
select: function(element) {
|
5100 |
+
$(element).select();
|
5101 |
+
return element;
|
5102 |
+
}
|
5103 |
+
};
|
5104 |
+
|
5105 |
+
Form.Element.Methods = {
|
5106 |
+
|
5107 |
+
serialize: function(element) {
|
5108 |
+
element = $(element);
|
5109 |
+
if (!element.disabled && element.name) {
|
5110 |
+
var value = element.getValue();
|
5111 |
+
if (value != undefined) {
|
5112 |
+
var pair = { };
|
5113 |
+
pair[element.name] = value;
|
5114 |
+
return Object.toQueryString(pair);
|
5115 |
+
}
|
5116 |
+
}
|
5117 |
+
return '';
|
5118 |
+
},
|
5119 |
+
|
5120 |
+
getValue: function(element) {
|
5121 |
+
element = $(element);
|
5122 |
+
var method = element.tagName.toLowerCase();
|
5123 |
+
return Form.Element.Serializers[method](element);
|
5124 |
+
},
|
5125 |
+
|
5126 |
+
setValue: function(element, value) {
|
5127 |
+
element = $(element);
|
5128 |
+
var method = element.tagName.toLowerCase();
|
5129 |
+
Form.Element.Serializers[method](element, value);
|
5130 |
+
return element;
|
5131 |
+
},
|
5132 |
+
|
5133 |
+
clear: function(element) {
|
5134 |
+
$(element).value = '';
|
5135 |
+
return element;
|
5136 |
+
},
|
5137 |
+
|
5138 |
+
present: function(element) {
|
5139 |
+
return $(element).value != '';
|
5140 |
+
},
|
5141 |
+
|
5142 |
+
activate: function(element) {
|
5143 |
+
element = $(element);
|
5144 |
+
try {
|
5145 |
+
element.focus();
|
5146 |
+
if (element.select && (element.tagName.toLowerCase() != 'input' ||
|
5147 |
+
!(/^(?:button|reset|submit)$/i.test(element.type))))
|
5148 |
+
element.select();
|
5149 |
+
} catch (e) { }
|
5150 |
+
return element;
|
5151 |
+
},
|
5152 |
+
|
5153 |
+
disable: function(element) {
|
5154 |
+
element = $(element);
|
5155 |
+
element.disabled = true;
|
5156 |
+
return element;
|
5157 |
+
},
|
5158 |
+
|
5159 |
+
enable: function(element) {
|
5160 |
+
element = $(element);
|
5161 |
+
element.disabled = false;
|
5162 |
+
return element;
|
5163 |
+
}
|
5164 |
+
};
|
5165 |
+
|
5166 |
+
/*--------------------------------------------------------------------------*/
|
5167 |
+
|
5168 |
+
var Field = Form.Element;
|
5169 |
+
|
5170 |
+
var $F = Form.Element.Methods.getValue;
|
5171 |
+
|
5172 |
+
/*--------------------------------------------------------------------------*/
|
5173 |
+
|
5174 |
+
Form.Element.Serializers = (function() {
|
5175 |
+
function input(element, value) {
|
5176 |
+
switch (element.type.toLowerCase()) {
|
5177 |
+
case 'checkbox':
|
5178 |
+
case 'radio':
|
5179 |
+
return inputSelector(element, value);
|
5180 |
+
default:
|
5181 |
+
return valueSelector(element, value);
|
5182 |
+
}
|
5183 |
+
}
|
5184 |
+
|
5185 |
+
function inputSelector(element, value) {
|
5186 |
+
if (Object.isUndefined(value))
|
5187 |
+
return element.checked ? element.value : null;
|
5188 |
+
else element.checked = !!value;
|
5189 |
+
}
|
5190 |
+
|
5191 |
+
function valueSelector(element, value) {
|
5192 |
+
if (Object.isUndefined(value)) return element.value;
|
5193 |
+
else element.value = value;
|
5194 |
+
}
|
5195 |
+
|
5196 |
+
function select(element, value) {
|
5197 |
+
if (Object.isUndefined(value))
|
5198 |
+
return (element.type === 'select-one' ? selectOne : selectMany)(element);
|
5199 |
+
|
5200 |
+
var opt, currentValue, single = !Object.isArray(value);
|
5201 |
+
for (var i = 0, length = element.length; i < length; i++) {
|
5202 |
+
opt = element.options[i];
|
5203 |
+
currentValue = this.optionValue(opt);
|
5204 |
+
if (single) {
|
5205 |
+
if (currentValue == value) {
|
5206 |
+
opt.selected = true;
|
5207 |
+
return;
|
5208 |
+
}
|
5209 |
+
}
|
5210 |
+
else opt.selected = value.include(currentValue);
|
5211 |
+
}
|
5212 |
+
}
|
5213 |
+
|
5214 |
+
function selectOne(element) {
|
5215 |
+
var index = element.selectedIndex;
|
5216 |
+
return index >= 0 ? optionValue(element.options[index]) : null;
|
5217 |
+
}
|
5218 |
+
|
5219 |
+
function selectMany(element) {
|
5220 |
+
var values, length = element.length;
|
5221 |
+
if (!length) return null;
|
5222 |
+
|
5223 |
+
for (var i = 0, values = []; i < length; i++) {
|
5224 |
+
var opt = element.options[i];
|
5225 |
+
if (opt.selected) values.push(optionValue(opt));
|
5226 |
+
}
|
5227 |
+
return values;
|
5228 |
+
}
|
5229 |
+
|
5230 |
+
function optionValue(opt) {
|
5231 |
+
return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
|
5232 |
+
}
|
5233 |
+
|
5234 |
+
return {
|
5235 |
+
input: input,
|
5236 |
+
inputSelector: inputSelector,
|
5237 |
+
textarea: valueSelector,
|
5238 |
+
select: select,
|
5239 |
+
selectOne: selectOne,
|
5240 |
+
selectMany: selectMany,
|
5241 |
+
optionValue: optionValue,
|
5242 |
+
button: valueSelector
|
5243 |
+
};
|
5244 |
+
})();
|
5245 |
+
|
5246 |
+
/*--------------------------------------------------------------------------*/
|
5247 |
+
|
5248 |
+
|
5249 |
+
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
|
5250 |
+
initialize: function($super, element, frequency, callback) {
|
5251 |
+
$super(callback, frequency);
|
5252 |
+
this.element = $(element);
|
5253 |
+
this.lastValue = this.getValue();
|
5254 |
+
},
|
5255 |
+
|
5256 |
+
execute: function() {
|
5257 |
+
var value = this.getValue();
|
5258 |
+
if (Object.isString(this.lastValue) && Object.isString(value) ?
|
5259 |
+
this.lastValue != value : String(this.lastValue) != String(value)) {
|
5260 |
+
this.callback(this.element, value);
|
5261 |
+
this.lastValue = value;
|
5262 |
+
}
|
5263 |
+
}
|
5264 |
+
});
|
5265 |
+
|
5266 |
+
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
|
5267 |
+
getValue: function() {
|
5268 |
+
return Form.Element.getValue(this.element);
|
5269 |
+
}
|
5270 |
+
});
|
5271 |
+
|
5272 |
+
Form.Observer = Class.create(Abstract.TimedObserver, {
|
5273 |
+
getValue: function() {
|
5274 |
+
return Form.serialize(this.element);
|
5275 |
+
}
|
5276 |
+
});
|
5277 |
+
|
5278 |
+
/*--------------------------------------------------------------------------*/
|
5279 |
+
|
5280 |
+
Abstract.EventObserver = Class.create({
|
5281 |
+
initialize: function(element, callback) {
|
5282 |
+
this.element = $(element);
|
5283 |
+
this.callback = callback;
|
5284 |
+
|
5285 |
+
this.lastValue = this.getValue();
|
5286 |
+
if (this.element.tagName.toLowerCase() == 'form')
|
5287 |
+
this.registerFormCallbacks();
|
5288 |
+
else
|
5289 |
+
this.registerCallback(this.element);
|
5290 |
+
},
|
5291 |
+
|
5292 |
+
onElementEvent: function() {
|
5293 |
+
var value = this.getValue();
|
5294 |
+
if (this.lastValue != value) {
|
5295 |
+
this.callback(this.element, value);
|
5296 |
+
this.lastValue = value;
|
5297 |
+
}
|
5298 |
+
},
|
5299 |
+
|
5300 |
+
registerFormCallbacks: function() {
|
5301 |
+
Form.getElements(this.element).each(this.registerCallback, this);
|
5302 |
+
},
|
5303 |
+
|
5304 |
+
registerCallback: function(element) {
|
5305 |
+
if (element.type) {
|
5306 |
+
switch (element.type.toLowerCase()) {
|
5307 |
+
case 'checkbox':
|
5308 |
+
case 'radio':
|
5309 |
+
Event.observe(element, 'click', this.onElementEvent.bind(this));
|
5310 |
+
break;
|
5311 |
+
default:
|
5312 |
+
Event.observe(element, 'change', this.onElementEvent.bind(this));
|
5313 |
+
break;
|
5314 |
+
}
|
5315 |
+
}
|
5316 |
+
}
|
5317 |
+
});
|
5318 |
+
|
5319 |
+
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
|
5320 |
+
getValue: function() {
|
5321 |
+
return Form.Element.getValue(this.element);
|
5322 |
+
}
|
5323 |
+
});
|
5324 |
+
|
5325 |
+
Form.EventObserver = Class.create(Abstract.EventObserver, {
|
5326 |
+
getValue: function() {
|
5327 |
+
return Form.serialize(this.element);
|
5328 |
+
}
|
5329 |
+
});
|
5330 |
+
(function() {
|
5331 |
+
|
5332 |
+
var Event = {
|
5333 |
+
KEY_BACKSPACE: 8,
|
5334 |
+
KEY_TAB: 9,
|
5335 |
+
KEY_RETURN: 13,
|
5336 |
+
KEY_ESC: 27,
|
5337 |
+
KEY_LEFT: 37,
|
5338 |
+
KEY_UP: 38,
|
5339 |
+
KEY_RIGHT: 39,
|
5340 |
+
KEY_DOWN: 40,
|
5341 |
+
KEY_DELETE: 46,
|
5342 |
+
KEY_HOME: 36,
|
5343 |
+
KEY_END: 35,
|
5344 |
+
KEY_PAGEUP: 33,
|
5345 |
+
KEY_PAGEDOWN: 34,
|
5346 |
+
KEY_INSERT: 45,
|
5347 |
+
|
5348 |
+
cache: {}
|
5349 |
+
};
|
5350 |
+
|
5351 |
+
var docEl = document.documentElement;
|
5352 |
+
var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
|
5353 |
+
&& 'onmouseleave' in docEl;
|
5354 |
+
|
5355 |
+
|
5356 |
+
|
5357 |
+
var isIELegacyEvent = function(event) { return false; };
|
5358 |
+
|
5359 |
+
if (window.attachEvent) {
|
5360 |
+
if (window.addEventListener) {
|
5361 |
+
isIELegacyEvent = function(event) {
|
5362 |
+
return !(event instanceof window.Event);
|
5363 |
+
};
|
5364 |
+
} else {
|
5365 |
+
isIELegacyEvent = function(event) { return true; };
|
5366 |
+
}
|
5367 |
+
}
|
5368 |
+
|
5369 |
+
var _isButton;
|
5370 |
+
|
5371 |
+
function _isButtonForDOMEvents(event, code) {
|
5372 |
+
return event.which ? (event.which === code + 1) : (event.button === code);
|
5373 |
+
}
|
5374 |
+
|
5375 |
+
var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
|
5376 |
+
function _isButtonForLegacyEvents(event, code) {
|
5377 |
+
return event.button === legacyButtonMap[code];
|
5378 |
+
}
|
5379 |
+
|
5380 |
+
function _isButtonForWebKit(event, code) {
|
5381 |
+
switch (code) {
|
5382 |
+
case 0: return event.which == 1 && !event.metaKey;
|
5383 |
+
case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
|
5384 |
+
case 2: return event.which == 3;
|
5385 |
+
default: return false;
|
5386 |
+
}
|
5387 |
+
}
|
5388 |
+
|
5389 |
+
if (window.attachEvent) {
|
5390 |
+
if (!window.addEventListener) {
|
5391 |
+
_isButton = _isButtonForLegacyEvents;
|
5392 |
+
} else {
|
5393 |
+
_isButton = function(event, code) {
|
5394 |
+
return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
|
5395 |
+
_isButtonForDOMEvents(event, code);
|
5396 |
+
}
|
5397 |
+
}
|
5398 |
+
} else if (Prototype.Browser.WebKit) {
|
5399 |
+
_isButton = _isButtonForWebKit;
|
5400 |
+
} else {
|
5401 |
+
_isButton = _isButtonForDOMEvents;
|
5402 |
+
}
|
5403 |
+
|
5404 |
+
function isLeftClick(event) { return _isButton(event, 0) }
|
5405 |
+
|
5406 |
+
function isMiddleClick(event) { return _isButton(event, 1) }
|
5407 |
+
|
5408 |
+
function isRightClick(event) { return _isButton(event, 2) }
|
5409 |
+
|
5410 |
+
function element(event) {
|
5411 |
+
event = Event.extend(event);
|
5412 |
+
|
5413 |
+
var node = event.target, type = event.type,
|
5414 |
+
currentTarget = event.currentTarget;
|
5415 |
+
|
5416 |
+
if (currentTarget && currentTarget.tagName) {
|
5417 |
+
if (type === 'load' || type === 'error' ||
|
5418 |
+
(type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
|
5419 |
+
&& currentTarget.type === 'radio'))
|
5420 |
+
node = currentTarget;
|
5421 |
+
}
|
5422 |
+
|
5423 |
+
if (node.nodeType == Node.TEXT_NODE)
|
5424 |
+
node = node.parentNode;
|
5425 |
+
|
5426 |
+
return Element.extend(node);
|
5427 |
+
}
|
5428 |
+
|
5429 |
+
function findElement(event, expression) {
|
5430 |
+
var element = Event.element(event);
|
5431 |
+
|
5432 |
+
if (!expression) return element;
|
5433 |
+
while (element) {
|
5434 |
+
if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
|
5435 |
+
return Element.extend(element);
|
5436 |
+
}
|
5437 |
+
element = element.parentNode;
|
5438 |
+
}
|
5439 |
+
}
|
5440 |
+
|
5441 |
+
function pointer(event) {
|
5442 |
+
return { x: pointerX(event), y: pointerY(event) };
|
5443 |
+
}
|
5444 |
+
|
5445 |
+
function pointerX(event) {
|
5446 |
+
var docElement = document.documentElement,
|
5447 |
+
body = document.body || { scrollLeft: 0 };
|
5448 |
+
|
5449 |
+
return event.pageX || (event.clientX +
|
5450 |
+
(docElement.scrollLeft || body.scrollLeft) -
|
5451 |
+
(docElement.clientLeft || 0));
|
5452 |
+
}
|
5453 |
+
|
5454 |
+
function pointerY(event) {
|
5455 |
+
var docElement = document.documentElement,
|
5456 |
+
body = document.body || { scrollTop: 0 };
|
5457 |
+
|
5458 |
+
return event.pageY || (event.clientY +
|
5459 |
+
(docElement.scrollTop || body.scrollTop) -
|
5460 |
+
(docElement.clientTop || 0));
|
5461 |
+
}
|
5462 |
+
|
5463 |
+
|
5464 |
+
function stop(event) {
|
5465 |
+
Event.extend(event);
|
5466 |
+
event.preventDefault();
|
5467 |
+
event.stopPropagation();
|
5468 |
+
|
5469 |
+
event.stopped = true;
|
5470 |
+
}
|
5471 |
+
|
5472 |
+
|
5473 |
+
Event.Methods = {
|
5474 |
+
isLeftClick: isLeftClick,
|
5475 |
+
isMiddleClick: isMiddleClick,
|
5476 |
+
isRightClick: isRightClick,
|
5477 |
+
|
5478 |
+
element: element,
|
5479 |
+
findElement: findElement,
|
5480 |
+
|
5481 |
+
pointer: pointer,
|
5482 |
+
pointerX: pointerX,
|
5483 |
+
pointerY: pointerY,
|
5484 |
+
|
5485 |
+
stop: stop
|
5486 |
+
};
|
5487 |
+
|
5488 |
+
var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
|
5489 |
+
m[name] = Event.Methods[name].methodize();
|
5490 |
+
return m;
|
5491 |
+
});
|
5492 |
+
|
5493 |
+
if (window.attachEvent) {
|
5494 |
+
function _relatedTarget(event) {
|
5495 |
+
var element;
|
5496 |
+
switch (event.type) {
|
5497 |
+
case 'mouseover':
|
5498 |
+
case 'mouseenter':
|
5499 |
+
element = event.fromElement;
|
5500 |
+
break;
|
5501 |
+
case 'mouseout':
|
5502 |
+
case 'mouseleave':
|
5503 |
+
element = event.toElement;
|
5504 |
+
break;
|
5505 |
+
default:
|
5506 |
+
return null;
|
5507 |
+
}
|
5508 |
+
return Element.extend(element);
|
5509 |
+
}
|
5510 |
+
|
5511 |
+
var additionalMethods = {
|
5512 |
+
stopPropagation: function() { this.cancelBubble = true },
|
5513 |
+
preventDefault: function() { this.returnValue = false },
|
5514 |
+
inspect: function() { return '[object Event]' }
|
5515 |
+
};
|
5516 |
+
|
5517 |
+
Event.extend = function(event, element) {
|
5518 |
+
if (!event) return false;
|
5519 |
+
|
5520 |
+
if (!isIELegacyEvent(event)) return event;
|
5521 |
+
|
5522 |
+
if (event._extendedByPrototype) return event;
|
5523 |
+
event._extendedByPrototype = Prototype.emptyFunction;
|
5524 |
+
|
5525 |
+
var pointer = Event.pointer(event);
|
5526 |
+
|
5527 |
+
Object.extend(event, {
|
5528 |
+
target: event.srcElement || element,
|
5529 |
+
relatedTarget: _relatedTarget(event),
|
5530 |
+
pageX: pointer.x,
|
5531 |
+
pageY: pointer.y
|
5532 |
+
});
|
5533 |
+
|
5534 |
+
Object.extend(event, methods);
|
5535 |
+
Object.extend(event, additionalMethods);
|
5536 |
+
|
5537 |
+
return event;
|
5538 |
+
};
|
5539 |
+
} else {
|
5540 |
+
Event.extend = Prototype.K;
|
5541 |
+
}
|
5542 |
+
|
5543 |
+
if (window.addEventListener) {
|
5544 |
+
Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
|
5545 |
+
Object.extend(Event.prototype, methods);
|
5546 |
+
}
|
5547 |
+
|
5548 |
+
function _createResponder(element, eventName, handler) {
|
5549 |
+
var registry = Element.retrieve(element, 'prototype_event_registry');
|
5550 |
+
|
5551 |
+
if (Object.isUndefined(registry)) {
|
5552 |
+
CACHE.push(element);
|
5553 |
+
registry = Element.retrieve(element, 'prototype_event_registry', $H());
|
5554 |
+
}
|
5555 |
+
|
5556 |
+
var respondersForEvent = registry.get(eventName);
|
5557 |
+
if (Object.isUndefined(respondersForEvent)) {
|
5558 |
+
respondersForEvent = [];
|
5559 |
+
registry.set(eventName, respondersForEvent);
|
5560 |
+
}
|
5561 |
+
|
5562 |
+
if (respondersForEvent.pluck('handler').include(handler)) return false;
|
5563 |
+
|
5564 |
+
var responder;
|
5565 |
+
if (eventName.include(":")) {
|
5566 |
+
responder = function(event) {
|
5567 |
+
if (Object.isUndefined(event.eventName))
|
5568 |
+
return false;
|
5569 |
+
|
5570 |
+
if (event.eventName !== eventName)
|
5571 |
+
return false;
|
5572 |
+
|
5573 |
+
Event.extend(event, element);
|
5574 |
+
handler.call(element, event);
|
5575 |
+
};
|
5576 |
+
} else {
|
5577 |
+
if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
|
5578 |
+
(eventName === "mouseenter" || eventName === "mouseleave")) {
|
5579 |
+
if (eventName === "mouseenter" || eventName === "mouseleave") {
|
5580 |
+
responder = function(event) {
|
5581 |
+
Event.extend(event, element);
|
5582 |
+
|
5583 |
+
var parent = event.relatedTarget;
|
5584 |
+
while (parent && parent !== element) {
|
5585 |
+
try { parent = parent.parentNode; }
|
5586 |
+
catch(e) { parent = element; }
|
5587 |
+
}
|
5588 |
+
|
5589 |
+
if (parent === element) return;
|
5590 |
+
|
5591 |
+
handler.call(element, event);
|
5592 |
+
};
|
5593 |
+
}
|
5594 |
+
} else {
|
5595 |
+
responder = function(event) {
|
5596 |
+
Event.extend(event, element);
|
5597 |
+
handler.call(element, event);
|
5598 |
+
};
|
5599 |
+
}
|
5600 |
+
}
|
5601 |
+
|
5602 |
+
responder.handler = handler;
|
5603 |
+
respondersForEvent.push(responder);
|
5604 |
+
return responder;
|
5605 |
+
}
|
5606 |
+
|
5607 |
+
function _destroyCache() {
|
5608 |
+
for (var i = 0, length = CACHE.length; i < length; i++) {
|
5609 |
+
Event.stopObserving(CACHE[i]);
|
5610 |
+
CACHE[i] = null;
|
5611 |
+
}
|
5612 |
+
}
|
5613 |
+
|
5614 |
+
var CACHE = [];
|
5615 |
+
|
5616 |
+
if (Prototype.Browser.IE)
|
5617 |
+
window.attachEvent('onunload', _destroyCache);
|
5618 |
+
|
5619 |
+
if (Prototype.Browser.WebKit)
|
5620 |
+
window.addEventListener('unload', Prototype.emptyFunction, false);
|
5621 |
+
|
5622 |
+
|
5623 |
+
var _getDOMEventName = Prototype.K,
|
5624 |
+
translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
|
5625 |
+
|
5626 |
+
if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
|
5627 |
+
_getDOMEventName = function(eventName) {
|
5628 |
+
return (translations[eventName] || eventName);
|
5629 |
+
};
|
5630 |
+
}
|
5631 |
+
|
5632 |
+
function observe(element, eventName, handler) {
|
5633 |
+
element = $(element);
|
5634 |
+
|
5635 |
+
var responder = _createResponder(element, eventName, handler);
|
5636 |
+
|
5637 |
+
if (!responder) return element;
|
5638 |
+
|
5639 |
+
if (eventName.include(':')) {
|
5640 |
+
if (element.addEventListener)
|
5641 |
+
element.addEventListener("dataavailable", responder, false);
|
5642 |
+
else {
|
5643 |
+
element.attachEvent("ondataavailable", responder);
|
5644 |
+
element.attachEvent("onlosecapture", responder);
|
5645 |
+
}
|
5646 |
+
} else {
|
5647 |
+
var actualEventName = _getDOMEventName(eventName);
|
5648 |
+
|
5649 |
+
if (element.addEventListener)
|
5650 |
+
element.addEventListener(actualEventName, responder, false);
|
5651 |
+
else
|
5652 |
+
element.attachEvent("on" + actualEventName, responder);
|
5653 |
+
}
|
5654 |
+
|
5655 |
+
return element;
|
5656 |
+
}
|
5657 |
+
|
5658 |
+
function stopObserving(element, eventName, handler) {
|
5659 |
+
element = $(element);
|
5660 |
+
|
5661 |
+
var registry = Element.retrieve(element, 'prototype_event_registry');
|
5662 |
+
if (!registry) return element;
|
5663 |
+
|
5664 |
+
if (!eventName) {
|
5665 |
+
registry.each( function(pair) {
|
5666 |
+
var eventName = pair.key;
|
5667 |
+
stopObserving(element, eventName);
|
5668 |
+
});
|
5669 |
+
return element;
|
5670 |
+
}
|
5671 |
+
|
5672 |
+
var responders = registry.get(eventName);
|
5673 |
+
if (!responders) return element;
|
5674 |
+
|
5675 |
+
if (!handler) {
|
5676 |
+
responders.each(function(r) {
|
5677 |
+
stopObserving(element, eventName, r.handler);
|
5678 |
+
});
|
5679 |
+
return element;
|
5680 |
+
}
|
5681 |
+
|
5682 |
+
var i = responders.length, responder;
|
5683 |
+
while (i--) {
|
5684 |
+
if (responders[i].handler === handler) {
|
5685 |
+
responder = responders[i];
|
5686 |
+
break;
|
5687 |
+
}
|
5688 |
+
}
|
5689 |
+
if (!responder) return element;
|
5690 |
+
|
5691 |
+
if (eventName.include(':')) {
|
5692 |
+
if (element.removeEventListener)
|
5693 |
+
element.removeEventListener("dataavailable", responder, false);
|
5694 |
+
else {
|
5695 |
+
element.detachEvent("ondataavailable", responder);
|
5696 |
+
element.detachEvent("onlosecapture", responder);
|
5697 |
+
}
|
5698 |
+
} else {
|
5699 |
+
var actualEventName = _getDOMEventName(eventName);
|
5700 |
+
if (element.removeEventListener)
|
5701 |
+
element.removeEventListener(actualEventName, responder, false);
|
5702 |
+
else
|
5703 |
+
element.detachEvent('on' + actualEventName, responder);
|
5704 |
+
}
|
5705 |
+
|
5706 |
+
registry.set(eventName, responders.without(responder));
|
5707 |
+
|
5708 |
+
return element;
|
5709 |
+
}
|
5710 |
+
|
5711 |
+
function fire(element, eventName, memo, bubble) {
|
5712 |
+
element = $(element);
|
5713 |
+
|
5714 |
+
if (Object.isUndefined(bubble))
|
5715 |
+
bubble = true;
|
5716 |
+
|
5717 |
+
if (element == document && document.createEvent && !element.dispatchEvent)
|
5718 |
+
element = document.documentElement;
|
5719 |
+
|
5720 |
+
var event;
|
5721 |
+
if (document.createEvent) {
|
5722 |
+
event = document.createEvent('HTMLEvents');
|
5723 |
+
event.initEvent('dataavailable', bubble, true);
|
5724 |
+
} else {
|
5725 |
+
event = document.createEventObject();
|
5726 |
+
event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
|
5727 |
+
}
|
5728 |
+
|
5729 |
+
event.eventName = eventName;
|
5730 |
+
event.memo = memo || { };
|
5731 |
+
|
5732 |
+
if (document.createEvent)
|
5733 |
+
element.dispatchEvent(event);
|
5734 |
+
else
|
5735 |
+
element.fireEvent(event.eventType, event);
|
5736 |
+
|
5737 |
+
return Event.extend(event);
|
5738 |
+
}
|
5739 |
+
|
5740 |
+
Event.Handler = Class.create({
|
5741 |
+
initialize: function(element, eventName, selector, callback) {
|
5742 |
+
this.element = $(element);
|
5743 |
+
this.eventName = eventName;
|
5744 |
+
this.selector = selector;
|
5745 |
+
this.callback = callback;
|
5746 |
+
this.handler = this.handleEvent.bind(this);
|
5747 |
+
},
|
5748 |
+
|
5749 |
+
start: function() {
|
5750 |
+
Event.observe(this.element, this.eventName, this.handler);
|
5751 |
+
return this;
|
5752 |
+
},
|
5753 |
+
|
5754 |
+
stop: function() {
|
5755 |
+
Event.stopObserving(this.element, this.eventName, this.handler);
|
5756 |
+
return this;
|
5757 |
+
},
|
5758 |
+
|
5759 |
+
handleEvent: function(event) {
|
5760 |
+
var element = Event.findElement(event, this.selector);
|
5761 |
+
if (element) this.callback.call(this.element, event, element);
|
5762 |
+
}
|
5763 |
+
});
|
5764 |
+
|
5765 |
+
function on(element, eventName, selector, callback) {
|
5766 |
+
element = $(element);
|
5767 |
+
if (Object.isFunction(selector) && Object.isUndefined(callback)) {
|
5768 |
+
callback = selector, selector = null;
|
5769 |
+
}
|
5770 |
+
|
5771 |
+
return new Event.Handler(element, eventName, selector, callback).start();
|
5772 |
+
}
|
5773 |
+
|
5774 |
+
Object.extend(Event, Event.Methods);
|
5775 |
+
|
5776 |
+
Object.extend(Event, {
|
5777 |
+
fire: fire,
|
5778 |
+
observe: observe,
|
5779 |
+
stopObserving: stopObserving,
|
5780 |
+
on: on
|
5781 |
+
});
|
5782 |
+
|
5783 |
+
Element.addMethods({
|
5784 |
+
fire: fire,
|
5785 |
+
|
5786 |
+
observe: observe,
|
5787 |
+
|
5788 |
+
stopObserving: stopObserving,
|
5789 |
+
|
5790 |
+
on: on
|
5791 |
+
});
|
5792 |
+
|
5793 |
+
Object.extend(document, {
|
5794 |
+
fire: fire.methodize(),
|
5795 |
+
|
5796 |
+
observe: observe.methodize(),
|
5797 |
+
|
5798 |
+
stopObserving: stopObserving.methodize(),
|
5799 |
+
|
5800 |
+
on: on.methodize(),
|
5801 |
+
|
5802 |
+
loaded: false
|
5803 |
+
});
|
5804 |
+
|
5805 |
+
if (window.Event) Object.extend(window.Event, Event);
|
5806 |
+
else window.Event = Event;
|
5807 |
+
})();
|
5808 |
+
|
5809 |
+
(function() {
|
5810 |
+
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
|
5811 |
+
Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
|
5812 |
+
|
5813 |
+
var timer;
|
5814 |
+
|
5815 |
+
function fireContentLoadedEvent() {
|
5816 |
+
if (document.loaded) return;
|
5817 |
+
if (timer) window.clearTimeout(timer);
|
5818 |
+
document.loaded = true;
|
5819 |
+
document.fire('dom:loaded');
|
5820 |
+
}
|
5821 |
+
|
5822 |
+
function checkReadyState() {
|
5823 |
+
if (document.readyState === 'complete') {
|
5824 |
+
document.stopObserving('readystatechange', checkReadyState);
|
5825 |
+
fireContentLoadedEvent();
|
5826 |
+
}
|
5827 |
+
}
|
5828 |
+
|
5829 |
+
function pollDoScroll() {
|
5830 |
+
try { document.documentElement.doScroll('left'); }
|
5831 |
+
catch(e) {
|
5832 |
+
timer = pollDoScroll.defer();
|
5833 |
+
return;
|
5834 |
+
}
|
5835 |
+
fireContentLoadedEvent();
|
5836 |
+
}
|
5837 |
+
|
5838 |
+
if (document.addEventListener) {
|
5839 |
+
document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
|
5840 |
+
} else {
|
5841 |
+
document.observe('readystatechange', checkReadyState);
|
5842 |
+
if (window == top)
|
5843 |
+
timer = pollDoScroll.defer();
|
5844 |
+
}
|
5845 |
+
|
5846 |
+
Event.observe(window, 'load', fireContentLoadedEvent);
|
5847 |
+
})();
|
5848 |
+
|
5849 |
+
|
5850 |
+
Element.addMethods();
|
5851 |
+
/*------------------------------- DEPRECATED -------------------------------*/
|
5852 |
+
|
5853 |
+
Hash.toQueryString = Object.toQueryString;
|
5854 |
+
|
5855 |
+
var Toggle = { display: Element.toggle };
|
5856 |
+
|
5857 |
+
Element.Methods.childOf = Element.Methods.descendantOf;
|
5858 |
+
|
5859 |
+
var Insertion = {
|
5860 |
+
Before: function(element, content) {
|
5861 |
+
return Element.insert(element, {before:content});
|
5862 |
+
},
|
5863 |
+
|
5864 |
+
Top: function(element, content) {
|
5865 |
+
return Element.insert(element, {top:content});
|
5866 |
+
},
|
5867 |
+
|
5868 |
+
Bottom: function(element, content) {
|
5869 |
+
return Element.insert(element, {bottom:content});
|
5870 |
+
},
|
5871 |
+
|
5872 |
+
After: function(element, content) {
|
5873 |
+
return Element.insert(element, {after:content});
|
5874 |
+
}
|
5875 |
+
};
|
5876 |
+
|
5877 |
+
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
|
5878 |
+
|
5879 |
+
var Position = {
|
5880 |
+
includeScrollOffsets: false,
|
5881 |
+
|
5882 |
+
prepare: function() {
|
5883 |
+
this.deltaX = window.pageXOffset
|
5884 |
+
|| document.documentElement.scrollLeft
|
5885 |
+
|| document.body.scrollLeft
|
5886 |
+
|| 0;
|
5887 |
+
this.deltaY = window.pageYOffset
|
5888 |
+
|| document.documentElement.scrollTop
|
5889 |
+
|| document.body.scrollTop
|
5890 |
+
|| 0;
|
5891 |
+
},
|
5892 |
+
|
5893 |
+
within: function(element, x, y) {
|
5894 |
+
if (this.includeScrollOffsets)
|
5895 |
+
return this.withinIncludingScrolloffsets(element, x, y);
|
5896 |
+
this.xcomp = x;
|
5897 |
+
this.ycomp = y;
|
5898 |
+
this.offset = Element.cumulativeOffset(element);
|
5899 |
+
|
5900 |
+
return (y >= this.offset[1] &&
|
5901 |
+
y < this.offset[1] + element.offsetHeight &&
|
5902 |
+
x >= this.offset[0] &&
|
5903 |
+
x < this.offset[0] + element.offsetWidth);
|
5904 |
+
},
|
5905 |
+
|
5906 |
+
withinIncludingScrolloffsets: function(element, x, y) {
|
5907 |
+
var offsetcache = Element.cumulativeScrollOffset(element);
|
5908 |
+
|
5909 |
+
this.xcomp = x + offsetcache[0] - this.deltaX;
|
5910 |
+
this.ycomp = y + offsetcache[1] - this.deltaY;
|
5911 |
+
this.offset = Element.cumulativeOffset(element);
|
5912 |
+
|
5913 |
+
return (this.ycomp >= this.offset[1] &&
|
5914 |
+
this.ycomp < this.offset[1] + element.offsetHeight &&
|
5915 |
+
this.xcomp >= this.offset[0] &&
|
5916 |
+
this.xcomp < this.offset[0] + element.offsetWidth);
|
5917 |
+
},
|
5918 |
+
|
5919 |
+
overlap: function(mode, element) {
|
5920 |
+
if (!mode) return 0;
|
5921 |
+
if (mode == 'vertical')
|
5922 |
+
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
|
5923 |
+
element.offsetHeight;
|
5924 |
+
if (mode == 'horizontal')
|
5925 |
+
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
|
5926 |
+
element.offsetWidth;
|
5927 |
+
},
|
5928 |
+
|
5929 |
+
|
5930 |
+
cumulativeOffset: Element.Methods.cumulativeOffset,
|
5931 |
+
|
5932 |
+
positionedOffset: Element.Methods.positionedOffset,
|
5933 |
+
|
5934 |
+
absolutize: function(element) {
|
5935 |
+
Position.prepare();
|
5936 |
+
return Element.absolutize(element);
|
5937 |
+
},
|
5938 |
+
|
5939 |
+
relativize: function(element) {
|
5940 |
+
Position.prepare();
|
5941 |
+
return Element.relativize(element);
|
5942 |
+
},
|
5943 |
+
|
5944 |
+
realOffset: Element.Methods.cumulativeScrollOffset,
|
5945 |
+
|
5946 |
+
offsetParent: Element.Methods.getOffsetParent,
|
5947 |
+
|
5948 |
+
page: Element.Methods.viewportOffset,
|
5949 |
+
|
5950 |
+
clone: function(source, target, options) {
|
5951 |
+
options = options || { };
|
5952 |
+
return Element.clonePosition(target, source, options);
|
5953 |
+
}
|
5954 |
+
};
|
5955 |
+
|
5956 |
+
/*--------------------------------------------------------------------------*/
|
5957 |
+
|
5958 |
+
if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
|
5959 |
+
function iter(name) {
|
5960 |
+
return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
|
5961 |
+
}
|
5962 |
+
|
5963 |
+
instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
|
5964 |
+
function(element, className) {
|
5965 |
+
className = className.toString().strip();
|
5966 |
+
var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
|
5967 |
+
return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
|
5968 |
+
} : function(element, className) {
|
5969 |
+
className = className.toString().strip();
|
5970 |
+
var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
|
5971 |
+
if (!classNames && !className) return elements;
|
5972 |
+
|
5973 |
+
var nodes = $(element).getElementsByTagName('*');
|
5974 |
+
className = ' ' + className + ' ';
|
5975 |
+
|
5976 |
+
for (var i = 0, child, cn; child = nodes[i]; i++) {
|
5977 |
+
if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
|
5978 |
+
(classNames && classNames.all(function(name) {
|
5979 |
+
return !name.toString().blank() && cn.include(' ' + name + ' ');
|
5980 |
+
}))))
|
5981 |
+
elements.push(Element.extend(child));
|
5982 |
+
}
|
5983 |
+
return elements;
|
5984 |
+
};
|
5985 |
+
|
5986 |
+
return function(className, parentElement) {
|
5987 |
+
return $(parentElement || document.body).getElementsByClassName(className);
|
5988 |
+
};
|
5989 |
+
}(Element.Methods);
|
5990 |
+
|
5991 |
+
/*--------------------------------------------------------------------------*/
|
5992 |
+
|
5993 |
+
Element.ClassNames = Class.create();
|
5994 |
+
Element.ClassNames.prototype = {
|
5995 |
+
initialize: function(element) {
|
5996 |
+
this.element = $(element);
|
5997 |
+
},
|
5998 |
+
|
5999 |
+
_each: function(iterator) {
|
6000 |
+
this.element.className.split(/\s+/).select(function(name) {
|
6001 |
+
return name.length > 0;
|
6002 |
+
})._each(iterator);
|
6003 |
+
},
|
6004 |
+
|
6005 |
+
set: function(className) {
|
6006 |
+
this.element.className = className;
|
6007 |
+
},
|
6008 |
+
|
6009 |
+
add: function(classNameToAdd) {
|
6010 |
+
if (this.include(classNameToAdd)) return;
|
6011 |
+
this.set($A(this).concat(classNameToAdd).join(' '));
|
6012 |
+
},
|
6013 |
+
|
6014 |
+
remove: function(classNameToRemove) {
|
6015 |
+
if (!this.include(classNameToRemove)) return;
|
6016 |
+
this.set($A(this).without(classNameToRemove).join(' '));
|
6017 |
+
},
|
6018 |
+
|
6019 |
+
toString: function() {
|
6020 |
+
return $A(this).join(' ');
|
6021 |
+
}
|
6022 |
+
};
|
6023 |
+
|
6024 |
+
Object.extend(Element.ClassNames.prototype, Enumerable);
|
6025 |
+
|
6026 |
+
/*--------------------------------------------------------------------------*/
|
6027 |
+
|
6028 |
+
(function() {
|
6029 |
+
window.Selector = Class.create({
|
6030 |
+
initialize: function(expression) {
|
6031 |
+
this.expression = expression.strip();
|
6032 |
+
},
|
6033 |
+
|
6034 |
+
findElements: function(rootElement) {
|
6035 |
+
return Prototype.Selector.select(this.expression, rootElement);
|
6036 |
+
},
|
6037 |
+
|
6038 |
+
match: function(element) {
|
6039 |
+
return Prototype.Selector.match(element, this.expression);
|
6040 |
+
},
|
6041 |
+
|
6042 |
+
toString: function() {
|
6043 |
+
return this.expression;
|
6044 |
+
},
|
6045 |
+
|
6046 |
+
inspect: function() {
|
6047 |
+
return "#<Selector: " + this.expression + ">";
|
6048 |
+
}
|
6049 |
+
});
|
6050 |
+
|
6051 |
+
Object.extend(Selector, {
|
6052 |
+
matchElements: function(elements, expression) {
|
6053 |
+
var match = Prototype.Selector.match,
|
6054 |
+
results = [];
|
6055 |
+
|
6056 |
+
for (var i = 0, length = elements.length; i < length; i++) {
|
6057 |
+
var element = elements[i];
|
6058 |
+
if (match(element, expression)) {
|
6059 |
+
results.push(Element.extend(element));
|
6060 |
+
}
|
6061 |
+
}
|
6062 |
+
return results;
|
6063 |
+
},
|
6064 |
+
|
6065 |
+
findElement: function(elements, expression, index) {
|
6066 |
+
index = index || 0;
|
6067 |
+
var matchIndex = 0, element;
|
6068 |
+
for (var i = 0, length = elements.length; i < length; i++) {
|
6069 |
+
element = elements[i];
|
6070 |
+
if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
|
6071 |
+
return Element.extend(element);
|
6072 |
+
}
|
6073 |
+
}
|
6074 |
+
},
|
6075 |
+
|
6076 |
+
findChildElements: function(element, expressions) {
|
6077 |
+
var selector = expressions.toArray().join(', ');
|
6078 |
+
return Prototype.Selector.select(selector, element || document);
|
6079 |
+
}
|
6080 |
+
});
|
6081 |
+
})();
|
js/mageho/sortproducts/scriptaculous.js
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us scriptaculous.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
//
|
5 |
+
// Permission is hereby granted, free of charge, to any person obtaining
|
6 |
+
// a copy of this software and associated documentation files (the
|
7 |
+
// "Software"), to deal in the Software without restriction, including
|
8 |
+
// without limitation the rights to use, copy, modify, merge, publish,
|
9 |
+
// distribute, sublicense, and/or sell copies of the Software, and to
|
10 |
+
// permit persons to whom the Software is furnished to do so, subject to
|
11 |
+
// the following conditions:
|
12 |
+
//
|
13 |
+
// The above copyright notice and this permission notice shall be
|
14 |
+
// included in all copies or substantial portions of the Software.
|
15 |
+
//
|
16 |
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17 |
+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18 |
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19 |
+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20 |
+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21 |
+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22 |
+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23 |
+
//
|
24 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
25 |
+
|
26 |
+
var Scriptaculous = {
|
27 |
+
Version: '1.9.0',
|
28 |
+
require: function(libraryName) {
|
29 |
+
try{
|
30 |
+
// inserting via DOM fails in Safari 2.0, so brute force approach
|
31 |
+
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
|
32 |
+
} catch(e) {
|
33 |
+
// for xhtml+xml served content, fall back to DOM methods
|
34 |
+
var script = document.createElement('script');
|
35 |
+
script.type = 'text/javascript';
|
36 |
+
script.src = libraryName;
|
37 |
+
document.getElementsByTagName('head')[0].appendChild(script);
|
38 |
+
}
|
39 |
+
},
|
40 |
+
REQUIRED_PROTOTYPE: '1.6.0.3',
|
41 |
+
load: function() {
|
42 |
+
function convertVersionString(versionString) {
|
43 |
+
var v = versionString.replace(/_.*|\./g, '');
|
44 |
+
v = parseInt(v + '0'.times(4-v.length));
|
45 |
+
return versionString.indexOf('_') > -1 ? v-1 : v;
|
46 |
+
}
|
47 |
+
|
48 |
+
if((typeof Prototype=='undefined') ||
|
49 |
+
(typeof Element == 'undefined') ||
|
50 |
+
(typeof Element.Methods=='undefined') ||
|
51 |
+
(convertVersionString(Prototype.Version) <
|
52 |
+
convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
|
53 |
+
throw("script.aculo.us requires the Prototype JavaScript framework >= " +
|
54 |
+
Scriptaculous.REQUIRED_PROTOTYPE);
|
55 |
+
|
56 |
+
var js = /scriptaculous\.js(\?.*)?$/;
|
57 |
+
$$('script[src]').findAll(function(s) {
|
58 |
+
return s.src.match(js);
|
59 |
+
}).each(function(s) {
|
60 |
+
var path = s.src.replace(js, ''),
|
61 |
+
includes = s.src.match(/\?.*load=([a-z,]*)/);
|
62 |
+
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
|
63 |
+
function(include) { Scriptaculous.require(path+include+'.js') });
|
64 |
+
});
|
65 |
+
}
|
66 |
+
};
|
67 |
+
|
68 |
+
Scriptaculous.load();
|
js/mageho/sortproducts/slider.js
ADDED
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us slider.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Marty Haught, Thomas Fuchs
|
4 |
+
//
|
5 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
6 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
7 |
+
|
8 |
+
if (!Control) var Control = { };
|
9 |
+
|
10 |
+
// options:
|
11 |
+
// axis: 'vertical', or 'horizontal' (default)
|
12 |
+
//
|
13 |
+
// callbacks:
|
14 |
+
// onChange(value)
|
15 |
+
// onSlide(value)
|
16 |
+
Control.Slider = Class.create({
|
17 |
+
initialize: function(handle, track, options) {
|
18 |
+
var slider = this;
|
19 |
+
|
20 |
+
if (Object.isArray(handle)) {
|
21 |
+
this.handles = handle.collect( function(e) { return $(e) });
|
22 |
+
} else {
|
23 |
+
this.handles = [$(handle)];
|
24 |
+
}
|
25 |
+
|
26 |
+
this.track = $(track);
|
27 |
+
this.options = options || { };
|
28 |
+
|
29 |
+
this.axis = this.options.axis || 'horizontal';
|
30 |
+
this.increment = this.options.increment || 1;
|
31 |
+
this.step = parseInt(this.options.step || '1');
|
32 |
+
this.range = this.options.range || $R(0,1);
|
33 |
+
|
34 |
+
this.value = 0; // assure backwards compat
|
35 |
+
this.values = this.handles.map( function() { return 0 });
|
36 |
+
this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
|
37 |
+
this.options.startSpan = $(this.options.startSpan || null);
|
38 |
+
this.options.endSpan = $(this.options.endSpan || null);
|
39 |
+
|
40 |
+
this.restricted = this.options.restricted || false;
|
41 |
+
|
42 |
+
this.maximum = this.options.maximum || this.range.end;
|
43 |
+
this.minimum = this.options.minimum || this.range.start;
|
44 |
+
|
45 |
+
// Will be used to align the handle onto the track, if necessary
|
46 |
+
this.alignX = parseInt(this.options.alignX || '0');
|
47 |
+
this.alignY = parseInt(this.options.alignY || '0');
|
48 |
+
|
49 |
+
this.trackLength = this.maximumOffset() - this.minimumOffset();
|
50 |
+
|
51 |
+
this.handleLength = this.isVertical() ?
|
52 |
+
(this.handles[0].offsetHeight != 0 ?
|
53 |
+
this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
|
54 |
+
(this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
|
55 |
+
this.handles[0].style.width.replace(/px$/,""));
|
56 |
+
|
57 |
+
this.active = false;
|
58 |
+
this.dragging = false;
|
59 |
+
this.disabled = false;
|
60 |
+
|
61 |
+
if (this.options.disabled) this.setDisabled();
|
62 |
+
|
63 |
+
// Allowed values array
|
64 |
+
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
|
65 |
+
if (this.allowedValues) {
|
66 |
+
this.minimum = this.allowedValues.min();
|
67 |
+
this.maximum = this.allowedValues.max();
|
68 |
+
}
|
69 |
+
|
70 |
+
this.eventMouseDown = this.startDrag.bindAsEventListener(this);
|
71 |
+
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
|
72 |
+
this.eventMouseMove = this.update.bindAsEventListener(this);
|
73 |
+
|
74 |
+
// Initialize handles in reverse (make sure first handle is active)
|
75 |
+
this.handles.each( function(h,i) {
|
76 |
+
i = slider.handles.length-1-i;
|
77 |
+
slider.setValue(parseFloat(
|
78 |
+
(Object.isArray(slider.options.sliderValue) ?
|
79 |
+
slider.options.sliderValue[i] : slider.options.sliderValue) ||
|
80 |
+
slider.range.start), i);
|
81 |
+
h.makePositioned().observe("mousedown", slider.eventMouseDown);
|
82 |
+
});
|
83 |
+
|
84 |
+
this.track.observe("mousedown", this.eventMouseDown);
|
85 |
+
document.observe("mouseup", this.eventMouseUp);
|
86 |
+
document.observe("mousemove", this.eventMouseMove);
|
87 |
+
|
88 |
+
this.initialized = true;
|
89 |
+
},
|
90 |
+
dispose: function() {
|
91 |
+
var slider = this;
|
92 |
+
Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
|
93 |
+
Event.stopObserving(document, "mouseup", this.eventMouseUp);
|
94 |
+
Event.stopObserving(document, "mousemove", this.eventMouseMove);
|
95 |
+
this.handles.each( function(h) {
|
96 |
+
Event.stopObserving(h, "mousedown", slider.eventMouseDown);
|
97 |
+
});
|
98 |
+
},
|
99 |
+
setDisabled: function(){
|
100 |
+
this.disabled = true;
|
101 |
+
},
|
102 |
+
setEnabled: function(){
|
103 |
+
this.disabled = false;
|
104 |
+
},
|
105 |
+
getNearestValue: function(value){
|
106 |
+
if (this.allowedValues){
|
107 |
+
if (value >= this.allowedValues.max()) return(this.allowedValues.max());
|
108 |
+
if (value <= this.allowedValues.min()) return(this.allowedValues.min());
|
109 |
+
|
110 |
+
var offset = Math.abs(this.allowedValues[0] - value);
|
111 |
+
var newValue = this.allowedValues[0];
|
112 |
+
this.allowedValues.each( function(v) {
|
113 |
+
var currentOffset = Math.abs(v - value);
|
114 |
+
if (currentOffset <= offset){
|
115 |
+
newValue = v;
|
116 |
+
offset = currentOffset;
|
117 |
+
}
|
118 |
+
});
|
119 |
+
return newValue;
|
120 |
+
}
|
121 |
+
if (value > this.range.end) return this.range.end;
|
122 |
+
if (value < this.range.start) return this.range.start;
|
123 |
+
return value;
|
124 |
+
},
|
125 |
+
setValue: function(sliderValue, handleIdx){
|
126 |
+
if (!this.active) {
|
127 |
+
this.activeHandleIdx = handleIdx || 0;
|
128 |
+
this.activeHandle = this.handles[this.activeHandleIdx];
|
129 |
+
this.updateStyles();
|
130 |
+
}
|
131 |
+
handleIdx = handleIdx || this.activeHandleIdx || 0;
|
132 |
+
if (this.initialized && this.restricted) {
|
133 |
+
if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
|
134 |
+
sliderValue = this.values[handleIdx-1];
|
135 |
+
if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
|
136 |
+
sliderValue = this.values[handleIdx+1];
|
137 |
+
}
|
138 |
+
sliderValue = this.getNearestValue(sliderValue);
|
139 |
+
this.values[handleIdx] = sliderValue;
|
140 |
+
this.value = this.values[0]; // assure backwards compat
|
141 |
+
|
142 |
+
this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
|
143 |
+
this.translateToPx(sliderValue);
|
144 |
+
|
145 |
+
this.drawSpans();
|
146 |
+
if (!this.dragging || !this.event) this.updateFinished();
|
147 |
+
},
|
148 |
+
setValueBy: function(delta, handleIdx) {
|
149 |
+
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
|
150 |
+
handleIdx || this.activeHandleIdx || 0);
|
151 |
+
},
|
152 |
+
translateToPx: function(value) {
|
153 |
+
return Math.round(
|
154 |
+
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
|
155 |
+
(value - this.range.start)) + "px";
|
156 |
+
},
|
157 |
+
translateToValue: function(offset) {
|
158 |
+
return ((offset/(this.trackLength-this.handleLength) *
|
159 |
+
(this.range.end-this.range.start)) + this.range.start);
|
160 |
+
},
|
161 |
+
getRange: function(range) {
|
162 |
+
var v = this.values.sortBy(Prototype.K);
|
163 |
+
range = range || 0;
|
164 |
+
return $R(v[range],v[range+1]);
|
165 |
+
},
|
166 |
+
minimumOffset: function(){
|
167 |
+
return(this.isVertical() ? this.alignY : this.alignX);
|
168 |
+
},
|
169 |
+
maximumOffset: function(){
|
170 |
+
return(this.isVertical() ?
|
171 |
+
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
|
172 |
+
this.track.style.height.replace(/px$/,"")) - this.alignY :
|
173 |
+
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
|
174 |
+
this.track.style.width.replace(/px$/,"")) - this.alignX);
|
175 |
+
},
|
176 |
+
isVertical: function(){
|
177 |
+
return (this.axis == 'vertical');
|
178 |
+
},
|
179 |
+
drawSpans: function() {
|
180 |
+
var slider = this;
|
181 |
+
if (this.spans)
|
182 |
+
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
|
183 |
+
if (this.options.startSpan)
|
184 |
+
this.setSpan(this.options.startSpan,
|
185 |
+
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
|
186 |
+
if (this.options.endSpan)
|
187 |
+
this.setSpan(this.options.endSpan,
|
188 |
+
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
|
189 |
+
},
|
190 |
+
setSpan: function(span, range) {
|
191 |
+
if (this.isVertical()) {
|
192 |
+
span.style.top = this.translateToPx(range.start);
|
193 |
+
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
|
194 |
+
} else {
|
195 |
+
span.style.left = this.translateToPx(range.start);
|
196 |
+
span.style.width = this.translateToPx(range.end - range.start + this.range.start);
|
197 |
+
}
|
198 |
+
},
|
199 |
+
updateStyles: function() {
|
200 |
+
this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
|
201 |
+
Element.addClassName(this.activeHandle, 'selected');
|
202 |
+
},
|
203 |
+
startDrag: function(event) {
|
204 |
+
if (Event.isLeftClick(event)) {
|
205 |
+
if (!this.disabled){
|
206 |
+
this.active = true;
|
207 |
+
|
208 |
+
var handle = Event.element(event);
|
209 |
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
210 |
+
var track = handle;
|
211 |
+
if (track==this.track) {
|
212 |
+
var offsets = this.track.cumulativeOffset();
|
213 |
+
this.event = event;
|
214 |
+
this.setValue(this.translateToValue(
|
215 |
+
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
|
216 |
+
));
|
217 |
+
var offsets = this.activeHandle.cumulativeOffset();
|
218 |
+
this.offsetX = (pointer[0] - offsets[0]);
|
219 |
+
this.offsetY = (pointer[1] - offsets[1]);
|
220 |
+
} else {
|
221 |
+
// find the handle (prevents issues with Safari)
|
222 |
+
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
|
223 |
+
handle = handle.parentNode;
|
224 |
+
|
225 |
+
if (this.handles.indexOf(handle)!=-1) {
|
226 |
+
this.activeHandle = handle;
|
227 |
+
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
|
228 |
+
this.updateStyles();
|
229 |
+
|
230 |
+
var offsets = this.activeHandle.cumulativeOffset();
|
231 |
+
this.offsetX = (pointer[0] - offsets[0]);
|
232 |
+
this.offsetY = (pointer[1] - offsets[1]);
|
233 |
+
}
|
234 |
+
}
|
235 |
+
}
|
236 |
+
Event.stop(event);
|
237 |
+
}
|
238 |
+
},
|
239 |
+
update: function(event) {
|
240 |
+
if (this.active) {
|
241 |
+
if (!this.dragging) this.dragging = true;
|
242 |
+
this.draw(event);
|
243 |
+
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
|
244 |
+
Event.stop(event);
|
245 |
+
}
|
246 |
+
},
|
247 |
+
draw: function(event) {
|
248 |
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
|
249 |
+
var offsets = this.track.cumulativeOffset();
|
250 |
+
pointer[0] -= this.offsetX + offsets[0];
|
251 |
+
pointer[1] -= this.offsetY + offsets[1];
|
252 |
+
this.event = event;
|
253 |
+
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
|
254 |
+
if (this.initialized && this.options.onSlide)
|
255 |
+
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
|
256 |
+
},
|
257 |
+
endDrag: function(event) {
|
258 |
+
if (this.active && this.dragging) {
|
259 |
+
this.finishDrag(event, true);
|
260 |
+
Event.stop(event);
|
261 |
+
}
|
262 |
+
this.active = false;
|
263 |
+
this.dragging = false;
|
264 |
+
},
|
265 |
+
finishDrag: function(event, success) {
|
266 |
+
this.active = false;
|
267 |
+
this.dragging = false;
|
268 |
+
this.updateFinished();
|
269 |
+
},
|
270 |
+
updateFinished: function() {
|
271 |
+
if (this.initialized && this.options.onChange)
|
272 |
+
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
|
273 |
+
this.event = null;
|
274 |
+
}
|
275 |
+
});
|
js/mageho/sortproducts/sound.js
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us sound.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
//
|
5 |
+
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
|
6 |
+
//
|
7 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
8 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
9 |
+
|
10 |
+
Sound = {
|
11 |
+
tracks: {},
|
12 |
+
_enabled: true,
|
13 |
+
template:
|
14 |
+
new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
|
15 |
+
enable: function(){
|
16 |
+
Sound._enabled = true;
|
17 |
+
},
|
18 |
+
disable: function(){
|
19 |
+
Sound._enabled = false;
|
20 |
+
},
|
21 |
+
play: function(url){
|
22 |
+
if(!Sound._enabled) return;
|
23 |
+
var options = Object.extend({
|
24 |
+
track: 'global', url: url, replace: false
|
25 |
+
}, arguments[1] || {});
|
26 |
+
|
27 |
+
if(options.replace && this.tracks[options.track]) {
|
28 |
+
$R(0, this.tracks[options.track].id).each(function(id){
|
29 |
+
var sound = $('sound_'+options.track+'_'+id);
|
30 |
+
sound.Stop && sound.Stop();
|
31 |
+
sound.remove();
|
32 |
+
});
|
33 |
+
this.tracks[options.track] = null;
|
34 |
+
}
|
35 |
+
|
36 |
+
if(!this.tracks[options.track])
|
37 |
+
this.tracks[options.track] = { id: 0 };
|
38 |
+
else
|
39 |
+
this.tracks[options.track].id++;
|
40 |
+
|
41 |
+
options.id = this.tracks[options.track].id;
|
42 |
+
$$('body')[0].insert(
|
43 |
+
Prototype.Browser.IE ? new Element('bgsound',{
|
44 |
+
id: 'sound_'+options.track+'_'+options.id,
|
45 |
+
src: options.url, loop: 1, autostart: true
|
46 |
+
}) : Sound.template.evaluate(options));
|
47 |
+
}
|
48 |
+
};
|
49 |
+
|
50 |
+
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
|
51 |
+
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
|
52 |
+
Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
|
53 |
+
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('Windows Media') != -1 }))
|
54 |
+
Sound.template = new Template('<object id="sound_#{track}_#{id}" type="application/x-mplayer2" data="#{url}"></object>');
|
55 |
+
else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('RealPlayer') != -1 }))
|
56 |
+
Sound.template = new Template('<embed type="audio/x-pn-realaudio-plugin" style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>');
|
57 |
+
else
|
58 |
+
Sound.play = function(){};
|
59 |
+
}
|
js/mageho/sortproducts/unittest.js
ADDED
@@ -0,0 +1,568 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// script.aculo.us unittest.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010
|
2 |
+
|
3 |
+
// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
4 |
+
// (c) 2005-2010 Jon Tirsen (http://www.tirsen.com)
|
5 |
+
// (c) 2005-2010 Michael Schuerig (http://www.schuerig.de/michael/)
|
6 |
+
//
|
7 |
+
// script.aculo.us is freely distributable under the terms of an MIT-style license.
|
8 |
+
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
9 |
+
|
10 |
+
// experimental, Firefox-only
|
11 |
+
Event.simulateMouse = function(element, eventName) {
|
12 |
+
var options = Object.extend({
|
13 |
+
pointerX: 0,
|
14 |
+
pointerY: 0,
|
15 |
+
buttons: 0,
|
16 |
+
ctrlKey: false,
|
17 |
+
altKey: false,
|
18 |
+
shiftKey: false,
|
19 |
+
metaKey: false
|
20 |
+
}, arguments[2] || {});
|
21 |
+
var oEvent = document.createEvent("MouseEvents");
|
22 |
+
oEvent.initMouseEvent(eventName, true, true, document.defaultView,
|
23 |
+
options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
|
24 |
+
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
|
25 |
+
|
26 |
+
if(this.mark) Element.remove(this.mark);
|
27 |
+
this.mark = document.createElement('div');
|
28 |
+
this.mark.appendChild(document.createTextNode(" "));
|
29 |
+
document.body.appendChild(this.mark);
|
30 |
+
this.mark.style.position = 'absolute';
|
31 |
+
this.mark.style.top = options.pointerY + "px";
|
32 |
+
this.mark.style.left = options.pointerX + "px";
|
33 |
+
this.mark.style.width = "5px";
|
34 |
+
this.mark.style.height = "5px;";
|
35 |
+
this.mark.style.borderTop = "1px solid red;";
|
36 |
+
this.mark.style.borderLeft = "1px solid red;";
|
37 |
+
|
38 |
+
if(this.step)
|
39 |
+
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
|
40 |
+
|
41 |
+
$(element).dispatchEvent(oEvent);
|
42 |
+
};
|
43 |
+
|
44 |
+
// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
|
45 |
+
// You need to downgrade to 1.0.4 for now to get this working
|
46 |
+
// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
|
47 |
+
Event.simulateKey = function(element, eventName) {
|
48 |
+
var options = Object.extend({
|
49 |
+
ctrlKey: false,
|
50 |
+
altKey: false,
|
51 |
+
shiftKey: false,
|
52 |
+
metaKey: false,
|
53 |
+
keyCode: 0,
|
54 |
+
charCode: 0
|
55 |
+
}, arguments[2] || {});
|
56 |
+
|
57 |
+
var oEvent = document.createEvent("KeyEvents");
|
58 |
+
oEvent.initKeyEvent(eventName, true, true, window,
|
59 |
+
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
|
60 |
+
options.keyCode, options.charCode );
|
61 |
+
$(element).dispatchEvent(oEvent);
|
62 |
+
};
|
63 |
+
|
64 |
+
Event.simulateKeys = function(element, command) {
|
65 |
+
for(var i=0; i<command.length; i++) {
|
66 |
+
Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
|
67 |
+
}
|
68 |
+
};
|
69 |
+
|
70 |
+
var Test = {};
|
71 |
+
Test.Unit = {};
|
72 |
+
|
73 |
+
// security exception workaround
|
74 |
+
Test.Unit.inspect = Object.inspect;
|
75 |
+
|
76 |
+
Test.Unit.Logger = Class.create();
|
77 |
+
Test.Unit.Logger.prototype = {
|
78 |
+
initialize: function(log) {
|
79 |
+
this.log = $(log);
|
80 |
+
if (this.log) {
|
81 |
+
this._createLogTable();
|
82 |
+
}
|
83 |
+
},
|
84 |
+
start: function(testName) {
|
85 |
+
if (!this.log) return;
|
86 |
+
this.testName = testName;
|
87 |
+
this.lastLogLine = document.createElement('tr');
|
88 |
+
this.statusCell = document.createElement('td');
|
89 |
+
this.nameCell = document.createElement('td');
|
90 |
+
this.nameCell.className = "nameCell";
|
91 |
+
this.nameCell.appendChild(document.createTextNode(testName));
|
92 |
+
this.messageCell = document.createElement('td');
|
93 |
+
this.lastLogLine.appendChild(this.statusCell);
|
94 |
+
this.lastLogLine.appendChild(this.nameCell);
|
95 |
+
this.lastLogLine.appendChild(this.messageCell);
|
96 |
+
this.loglines.appendChild(this.lastLogLine);
|
97 |
+
},
|
98 |
+
finish: function(status, summary) {
|
99 |
+
if (!this.log) return;
|
100 |
+
this.lastLogLine.className = status;
|
101 |
+
this.statusCell.innerHTML = status;
|
102 |
+
this.messageCell.innerHTML = this._toHTML(summary);
|
103 |
+
this.addLinksToResults();
|
104 |
+
},
|
105 |
+
message: function(message) {
|
106 |
+
if (!this.log) return;
|
107 |
+
this.messageCell.innerHTML = this._toHTML(message);
|
108 |
+
},
|
109 |
+
summary: function(summary) {
|
110 |
+
if (!this.log) return;
|
111 |
+
this.logsummary.innerHTML = this._toHTML(summary);
|
112 |
+
},
|
113 |
+
_createLogTable: function() {
|
114 |
+
this.log.innerHTML =
|
115 |
+
'<div id="logsummary"></div>' +
|
116 |
+
'<table id="logtable">' +
|
117 |
+
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
|
118 |
+
'<tbody id="loglines"></tbody>' +
|
119 |
+
'</table>';
|
120 |
+
this.logsummary = $('logsummary');
|
121 |
+
this.loglines = $('loglines');
|
122 |
+
},
|
123 |
+
_toHTML: function(txt) {
|
124 |
+
return txt.escapeHTML().replace(/\n/g,"<br/>");
|
125 |
+
},
|
126 |
+
addLinksToResults: function(){
|
127 |
+
$$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
|
128 |
+
td.title = "Run only this test";
|
129 |
+
Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
|
130 |
+
});
|
131 |
+
$$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
|
132 |
+
td.title = "Run all tests";
|
133 |
+
Event.observe(td, 'click', function(){ window.location.search = "";});
|
134 |
+
});
|
135 |
+
}
|
136 |
+
};
|
137 |
+
|
138 |
+
Test.Unit.Runner = Class.create();
|
139 |
+
Test.Unit.Runner.prototype = {
|
140 |
+
initialize: function(testcases) {
|
141 |
+
this.options = Object.extend({
|
142 |
+
testLog: 'testlog'
|
143 |
+
}, arguments[1] || {});
|
144 |
+
this.options.resultsURL = this.parseResultsURLQueryParameter();
|
145 |
+
this.options.tests = this.parseTestsQueryParameter();
|
146 |
+
if (this.options.testLog) {
|
147 |
+
this.options.testLog = $(this.options.testLog) || null;
|
148 |
+
}
|
149 |
+
if(this.options.tests) {
|
150 |
+
this.tests = [];
|
151 |
+
for(var i = 0; i < this.options.tests.length; i++) {
|
152 |
+
if(/^test/.test(this.options.tests[i])) {
|
153 |
+
this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
|
154 |
+
}
|
155 |
+
}
|
156 |
+
} else {
|
157 |
+
if (this.options.test) {
|
158 |
+
this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
|
159 |
+
} else {
|
160 |
+
this.tests = [];
|
161 |
+
for(var testcase in testcases) {
|
162 |
+
if(/^test/.test(testcase)) {
|
163 |
+
this.tests.push(
|
164 |
+
new Test.Unit.Testcase(
|
165 |
+
this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
|
166 |
+
testcases[testcase], testcases["setup"], testcases["teardown"]
|
167 |
+
));
|
168 |
+
}
|
169 |
+
}
|
170 |
+
}
|
171 |
+
}
|
172 |
+
this.currentTest = 0;
|
173 |
+
this.logger = new Test.Unit.Logger(this.options.testLog);
|
174 |
+
setTimeout(this.runTests.bind(this), 1000);
|
175 |
+
},
|
176 |
+
parseResultsURLQueryParameter: function() {
|
177 |
+
return window.location.search.parseQuery()["resultsURL"];
|
178 |
+
},
|
179 |
+
parseTestsQueryParameter: function(){
|
180 |
+
if (window.location.search.parseQuery()["tests"]){
|
181 |
+
return window.location.search.parseQuery()["tests"].split(',');
|
182 |
+
};
|
183 |
+
},
|
184 |
+
// Returns:
|
185 |
+
// "ERROR" if there was an error,
|
186 |
+
// "FAILURE" if there was a failure, or
|
187 |
+
// "SUCCESS" if there was neither
|
188 |
+
getResult: function() {
|
189 |
+
var hasFailure = false;
|
190 |
+
for(var i=0;i<this.tests.length;i++) {
|
191 |
+
if (this.tests[i].errors > 0) {
|
192 |
+
return "ERROR";
|
193 |
+
}
|
194 |
+
if (this.tests[i].failures > 0) {
|
195 |
+
hasFailure = true;
|
196 |
+
}
|
197 |
+
}
|
198 |
+
if (hasFailure) {
|
199 |
+
return "FAILURE";
|
200 |
+
} else {
|
201 |
+
return "SUCCESS";
|
202 |
+
}
|
203 |
+
},
|
204 |
+
postResults: function() {
|
205 |
+
if (this.options.resultsURL) {
|
206 |
+
new Ajax.Request(this.options.resultsURL,
|
207 |
+
{ method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
|
208 |
+
}
|
209 |
+
},
|
210 |
+
runTests: function() {
|
211 |
+
var test = this.tests[this.currentTest];
|
212 |
+
if (!test) {
|
213 |
+
// finished!
|
214 |
+
this.postResults();
|
215 |
+
this.logger.summary(this.summary());
|
216 |
+
return;
|
217 |
+
}
|
218 |
+
if(!test.isWaiting) {
|
219 |
+
this.logger.start(test.name);
|
220 |
+
}
|
221 |
+
test.run();
|
222 |
+
if(test.isWaiting) {
|
223 |
+
this.logger.message("Waiting for " + test.timeToWait + "ms");
|
224 |
+
setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
|
225 |
+
} else {
|
226 |
+
this.logger.finish(test.status(), test.summary());
|
227 |
+
this.currentTest++;
|
228 |
+
// tail recursive, hopefully the browser will skip the stackframe
|
229 |
+
this.runTests();
|
230 |
+
}
|
231 |
+
},
|
232 |
+
summary: function() {
|
233 |
+
var assertions = 0;
|
234 |
+
var failures = 0;
|
235 |
+
var errors = 0;
|
236 |
+
var messages = [];
|
237 |
+
for(var i=0;i<this.tests.length;i++) {
|
238 |
+
assertions += this.tests[i].assertions;
|
239 |
+
failures += this.tests[i].failures;
|
240 |
+
errors += this.tests[i].errors;
|
241 |
+
}
|
242 |
+
return (
|
243 |
+
(this.options.context ? this.options.context + ': ': '') +
|
244 |
+
this.tests.length + " tests, " +
|
245 |
+
assertions + " assertions, " +
|
246 |
+
failures + " failures, " +
|
247 |
+
errors + " errors");
|
248 |
+
}
|
249 |
+
};
|
250 |
+
|
251 |
+
Test.Unit.Assertions = Class.create();
|
252 |
+
Test.Unit.Assertions.prototype = {
|
253 |
+
initialize: function() {
|
254 |
+
this.assertions = 0;
|
255 |
+
this.failures = 0;
|
256 |
+
this.errors = 0;
|
257 |
+
this.messages = [];
|
258 |
+
},
|
259 |
+
summary: function() {
|
260 |
+
return (
|
261 |
+
this.assertions + " assertions, " +
|
262 |
+
this.failures + " failures, " +
|
263 |
+
this.errors + " errors" + "\n" +
|
264 |
+
this.messages.join("\n"));
|
265 |
+
},
|
266 |
+
pass: function() {
|
267 |
+
this.assertions++;
|
268 |
+
},
|
269 |
+
fail: function(message) {
|
270 |
+
this.failures++;
|
271 |
+
this.messages.push("Failure: " + message);
|
272 |
+
},
|
273 |
+
info: function(message) {
|
274 |
+
this.messages.push("Info: " + message);
|
275 |
+
},
|
276 |
+
error: function(error) {
|
277 |
+
this.errors++;
|
278 |
+
this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
|
279 |
+
},
|
280 |
+
status: function() {
|
281 |
+
if (this.failures > 0) return 'failed';
|
282 |
+
if (this.errors > 0) return 'error';
|
283 |
+
return 'passed';
|
284 |
+
},
|
285 |
+
assert: function(expression) {
|
286 |
+
var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
|
287 |
+
try { expression ? this.pass() :
|
288 |
+
this.fail(message); }
|
289 |
+
catch(e) { this.error(e); }
|
290 |
+
},
|
291 |
+
assertEqual: function(expected, actual) {
|
292 |
+
var message = arguments[2] || "assertEqual";
|
293 |
+
try { (expected == actual) ? this.pass() :
|
294 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
295 |
+
'", actual "' + Test.Unit.inspect(actual) + '"'); }
|
296 |
+
catch(e) { this.error(e); }
|
297 |
+
},
|
298 |
+
assertInspect: function(expected, actual) {
|
299 |
+
var message = arguments[2] || "assertInspect";
|
300 |
+
try { (expected == actual.inspect()) ? this.pass() :
|
301 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
302 |
+
'", actual "' + Test.Unit.inspect(actual) + '"'); }
|
303 |
+
catch(e) { this.error(e); }
|
304 |
+
},
|
305 |
+
assertEnumEqual: function(expected, actual) {
|
306 |
+
var message = arguments[2] || "assertEnumEqual";
|
307 |
+
try { $A(expected).length == $A(actual).length &&
|
308 |
+
expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
|
309 |
+
this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
|
310 |
+
', actual ' + Test.Unit.inspect(actual)); }
|
311 |
+
catch(e) { this.error(e); }
|
312 |
+
},
|
313 |
+
assertNotEqual: function(expected, actual) {
|
314 |
+
var message = arguments[2] || "assertNotEqual";
|
315 |
+
try { (expected != actual) ? this.pass() :
|
316 |
+
this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
|
317 |
+
catch(e) { this.error(e); }
|
318 |
+
},
|
319 |
+
assertIdentical: function(expected, actual) {
|
320 |
+
var message = arguments[2] || "assertIdentical";
|
321 |
+
try { (expected === actual) ? this.pass() :
|
322 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
323 |
+
'", actual "' + Test.Unit.inspect(actual) + '"'); }
|
324 |
+
catch(e) { this.error(e); }
|
325 |
+
},
|
326 |
+
assertNotIdentical: function(expected, actual) {
|
327 |
+
var message = arguments[2] || "assertNotIdentical";
|
328 |
+
try { !(expected === actual) ? this.pass() :
|
329 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
330 |
+
'", actual "' + Test.Unit.inspect(actual) + '"'); }
|
331 |
+
catch(e) { this.error(e); }
|
332 |
+
},
|
333 |
+
assertNull: function(obj) {
|
334 |
+
var message = arguments[1] || 'assertNull';
|
335 |
+
try { (obj==null) ? this.pass() :
|
336 |
+
this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
|
337 |
+
catch(e) { this.error(e); }
|
338 |
+
},
|
339 |
+
assertMatch: function(expected, actual) {
|
340 |
+
var message = arguments[2] || 'assertMatch';
|
341 |
+
var regex = new RegExp(expected);
|
342 |
+
try { (regex.exec(actual)) ? this.pass() :
|
343 |
+
this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
|
344 |
+
catch(e) { this.error(e); }
|
345 |
+
},
|
346 |
+
assertHidden: function(element) {
|
347 |
+
var message = arguments[1] || 'assertHidden';
|
348 |
+
this.assertEqual("none", element.style.display, message);
|
349 |
+
},
|
350 |
+
assertNotNull: function(object) {
|
351 |
+
var message = arguments[1] || 'assertNotNull';
|
352 |
+
this.assert(object != null, message);
|
353 |
+
},
|
354 |
+
assertType: function(expected, actual) {
|
355 |
+
var message = arguments[2] || 'assertType';
|
356 |
+
try {
|
357 |
+
(actual.constructor == expected) ? this.pass() :
|
358 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
359 |
+
'", actual "' + (actual.constructor) + '"'); }
|
360 |
+
catch(e) { this.error(e); }
|
361 |
+
},
|
362 |
+
assertNotOfType: function(expected, actual) {
|
363 |
+
var message = arguments[2] || 'assertNotOfType';
|
364 |
+
try {
|
365 |
+
(actual.constructor != expected) ? this.pass() :
|
366 |
+
this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
|
367 |
+
'", actual "' + (actual.constructor) + '"'); }
|
368 |
+
catch(e) { this.error(e); }
|
369 |
+
},
|
370 |
+
assertInstanceOf: function(expected, actual) {
|
371 |
+
var message = arguments[2] || 'assertInstanceOf';
|
372 |
+
try {
|
373 |
+
(actual instanceof expected) ? this.pass() :
|
374 |
+
this.fail(message + ": object was not an instance of the expected type"); }
|
375 |
+
catch(e) { this.error(e); }
|
376 |
+
},
|
377 |
+
assertNotInstanceOf: function(expected, actual) {
|
378 |
+
var message = arguments[2] || 'assertNotInstanceOf';
|
379 |
+
try {
|
380 |
+
!(actual instanceof expected) ? this.pass() :
|
381 |
+
this.fail(message + ": object was an instance of the not expected type"); }
|
382 |
+
catch(e) { this.error(e); }
|
383 |
+
},
|
384 |
+
assertRespondsTo: function(method, obj) {
|
385 |
+
var message = arguments[2] || 'assertRespondsTo';
|
386 |
+
try {
|
387 |
+
(obj[method] && typeof obj[method] == 'function') ? this.pass() :
|
388 |
+
this.fail(message + ": object doesn't respond to [" + method + "]"); }
|
389 |
+
catch(e) { this.error(e); }
|
390 |
+
},
|
391 |
+
assertReturnsTrue: function(method, obj) {
|
392 |
+
var message = arguments[2] || 'assertReturnsTrue';
|
393 |
+
try {
|
394 |
+
var m = obj[method];
|
395 |
+
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
|
396 |
+
m() ? this.pass() :
|
397 |
+
this.fail(message + ": method returned false"); }
|
398 |
+
catch(e) { this.error(e); }
|
399 |
+
},
|
400 |
+
assertReturnsFalse: function(method, obj) {
|
401 |
+
var message = arguments[2] || 'assertReturnsFalse';
|
402 |
+
try {
|
403 |
+
var m = obj[method];
|
404 |
+
if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
|
405 |
+
!m() ? this.pass() :
|
406 |
+
this.fail(message + ": method returned true"); }
|
407 |
+
catch(e) { this.error(e); }
|
408 |
+
},
|
409 |
+
assertRaise: function(exceptionName, method) {
|
410 |
+
var message = arguments[2] || 'assertRaise';
|
411 |
+
try {
|
412 |
+
method();
|
413 |
+
this.fail(message + ": exception expected but none was raised"); }
|
414 |
+
catch(e) {
|
415 |
+
((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
|
416 |
+
}
|
417 |
+
},
|
418 |
+
assertElementsMatch: function() {
|
419 |
+
var expressions = $A(arguments), elements = $A(expressions.shift());
|
420 |
+
if (elements.length != expressions.length) {
|
421 |
+
this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
|
422 |
+
return false;
|
423 |
+
}
|
424 |
+
elements.zip(expressions).all(function(pair, index) {
|
425 |
+
var element = $(pair.first()), expression = pair.last();
|
426 |
+
if (element.match(expression)) return true;
|
427 |
+
this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
|
428 |
+
}.bind(this)) && this.pass();
|
429 |
+
},
|
430 |
+
assertElementMatches: function(element, expression) {
|
431 |
+
this.assertElementsMatch([element], expression);
|
432 |
+
},
|
433 |
+
benchmark: function(operation, iterations) {
|
434 |
+
var startAt = new Date();
|
435 |
+
(iterations || 1).times(operation);
|
436 |
+
var timeTaken = ((new Date())-startAt);
|
437 |
+
this.info((arguments[2] || 'Operation') + ' finished ' +
|
438 |
+
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
|
439 |
+
return timeTaken;
|
440 |
+
},
|
441 |
+
_isVisible: function(element) {
|
442 |
+
element = $(element);
|
443 |
+
if(!element.parentNode) return true;
|
444 |
+
this.assertNotNull(element);
|
445 |
+
if(element.style && Element.getStyle(element, 'display') == 'none')
|
446 |
+
return false;
|
447 |
+
|
448 |
+
return this._isVisible(element.parentNode);
|
449 |
+
},
|
450 |
+
assertNotVisible: function(element) {
|
451 |
+
this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
|
452 |
+
},
|
453 |
+
assertVisible: function(element) {
|
454 |
+
this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
|
455 |
+
},
|
456 |
+
benchmark: function(operation, iterations) {
|
457 |
+
var startAt = new Date();
|
458 |
+
(iterations || 1).times(operation);
|
459 |
+
var timeTaken = ((new Date())-startAt);
|
460 |
+
this.info((arguments[2] || 'Operation') + ' finished ' +
|
461 |
+
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
|
462 |
+
return timeTaken;
|
463 |
+
}
|
464 |
+
};
|
465 |
+
|
466 |
+
Test.Unit.Testcase = Class.create();
|
467 |
+
Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
|
468 |
+
initialize: function(name, test, setup, teardown) {
|
469 |
+
Test.Unit.Assertions.prototype.initialize.bind(this)();
|
470 |
+
this.name = name;
|
471 |
+
|
472 |
+
if(typeof test == 'string') {
|
473 |
+
test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
|
474 |
+
test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
|
475 |
+
this.test = function() {
|
476 |
+
eval('with(this){'+test+'}');
|
477 |
+
}
|
478 |
+
} else {
|
479 |
+
this.test = test || function() {};
|
480 |
+
}
|
481 |
+
|
482 |
+
this.setup = setup || function() {};
|
483 |
+
this.teardown = teardown || function() {};
|
484 |
+
this.isWaiting = false;
|
485 |
+
this.timeToWait = 1000;
|
486 |
+
},
|
487 |
+
wait: function(time, nextPart) {
|
488 |
+
this.isWaiting = true;
|
489 |
+
this.test = nextPart;
|
490 |
+
this.timeToWait = time;
|
491 |
+
},
|
492 |
+
run: function() {
|
493 |
+
try {
|
494 |
+
try {
|
495 |
+
if (!this.isWaiting) this.setup.bind(this)();
|
496 |
+
this.isWaiting = false;
|
497 |
+
this.test.bind(this)();
|
498 |
+
} finally {
|
499 |
+
if(!this.isWaiting) {
|
500 |
+
this.teardown.bind(this)();
|
501 |
+
}
|
502 |
+
}
|
503 |
+
}
|
504 |
+
catch(e) { this.error(e); }
|
505 |
+
}
|
506 |
+
});
|
507 |
+
|
508 |
+
// *EXPERIMENTAL* BDD-style testing to please non-technical folk
|
509 |
+
// This draws many ideas from RSpec http://rspec.rubyforge.org/
|
510 |
+
|
511 |
+
Test.setupBDDExtensionMethods = function(){
|
512 |
+
var METHODMAP = {
|
513 |
+
shouldEqual: 'assertEqual',
|
514 |
+
shouldNotEqual: 'assertNotEqual',
|
515 |
+
shouldEqualEnum: 'assertEnumEqual',
|
516 |
+
shouldBeA: 'assertType',
|
517 |
+
shouldNotBeA: 'assertNotOfType',
|
518 |
+
shouldBeAn: 'assertType',
|
519 |
+
shouldNotBeAn: 'assertNotOfType',
|
520 |
+
shouldBeNull: 'assertNull',
|
521 |
+
shouldNotBeNull: 'assertNotNull',
|
522 |
+
|
523 |
+
shouldBe: 'assertReturnsTrue',
|
524 |
+
shouldNotBe: 'assertReturnsFalse',
|
525 |
+
shouldRespondTo: 'assertRespondsTo'
|
526 |
+
};
|
527 |
+
var makeAssertion = function(assertion, args, object) {
|
528 |
+
this[assertion].apply(this,(args || []).concat([object]));
|
529 |
+
};
|
530 |
+
|
531 |
+
Test.BDDMethods = {};
|
532 |
+
$H(METHODMAP).each(function(pair) {
|
533 |
+
Test.BDDMethods[pair.key] = function() {
|
534 |
+
var args = $A(arguments);
|
535 |
+
var scope = args.shift();
|
536 |
+
makeAssertion.apply(scope, [pair.value, args, this]); };
|
537 |
+
});
|
538 |
+
|
539 |
+
[Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
|
540 |
+
function(p){ Object.extend(p, Test.BDDMethods) }
|
541 |
+
);
|
542 |
+
};
|
543 |
+
|
544 |
+
Test.context = function(name, spec, log){
|
545 |
+
Test.setupBDDExtensionMethods();
|
546 |
+
|
547 |
+
var compiledSpec = {};
|
548 |
+
var titles = {};
|
549 |
+
for(specName in spec) {
|
550 |
+
switch(specName){
|
551 |
+
case "setup":
|
552 |
+
case "teardown":
|
553 |
+
compiledSpec[specName] = spec[specName];
|
554 |
+
break;
|
555 |
+
default:
|
556 |
+
var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
|
557 |
+
var body = spec[specName].toString().split('\n').slice(1);
|
558 |
+
if(/^\{/.test(body[0])) body = body.slice(1);
|
559 |
+
body.pop();
|
560 |
+
body = body.map(function(statement){
|
561 |
+
return statement.strip()
|
562 |
+
});
|
563 |
+
compiledSpec[testName] = body.join('\n');
|
564 |
+
titles[testName] = specName;
|
565 |
+
}
|
566 |
+
}
|
567 |
+
new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
|
568 |
+
};
|
package.xml
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Mageho_Sortproducts</name>
|
4 |
+
<version>1.0.1</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0 : Open Software License</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Highlight your best products catalog in a few mouse movements with Merchandising Catalog Extension!</summary>
|
10 |
+
<description><h1>English version</h1>
|
11 |
+

|
12 |
+
<p>Magento extension, merchandising catalog, will help you from your Magento administration to sort your products categories according to their display order.</p>
|
13 |
+

|
14 |
+
<p>By default, Magento application manually fill the position of products. Tedious and cons-productive when you have more than a dozen products. Here, a miniature product identifies a glance the products you want to highlight. A tooltip, loaded via AJAX, displays information that you want! Simply set the attributes you want to display in the configuration space of back-office (see Photo 3).</p>
|
15 |
+

|
16 |
+
<p><span style="font-size:18px">A real time saver !</span></p>
|
17 |
+

|
18 |
+
<h4>Summary of the highlights of this extension Magento</h4>
|
19 |
+

|
20 |
+
<ul class="square-list">
|
21 |
+
<li><p>System <em> Drag & Drop </em> to easily store the products according to the desired position. </p></li>
|
22 |
+
<li><p>Display products per photo instantly identifying those desired. <span class="bold"> Ranger hundreds of products in minutes</p></li>
|
23 |
+
<li><p>Bubble aid overview to have all the technical characteristics such as price, promotional price, the percentage discount special offer product, reference product ID and all attributes of your choice depending on the configuration of the module.</p>
|
24 |
+
<ul class="disc-list">
|
25 |
+
<li>
|
26 |
+
<p>Display with label products not available, it can in the blink of an eye put products exhausted at the end of the list.</p>
|
27 |
+
<p><img src="{{media url="wysiwyg/extension/merchandising/label-product.jpg"}}" width="380" height="160" alt="The products are not available are displayed with the words 'Out of stock'" /></p>
|
28 |
+
<p>It is also possible not to include discontinued products and products whose status is disabled in the list using the module configuration.</p>
|
29 |
+
</li>
|
30 |
+
</ul>
|
31 |
+
</li>
|
32 |
+
</ul>
|
33 |
+

|
34 |
+
<h1>Version française</h1>
|
35 |
+

|
36 |
+
<p>Cette extension Magento, Merchandising Catalogue, va vous permettre depuis votre administration Magento de trier les produits de vos catégories selon leur ordre d'affichage.</p>
|
37 |
+

|
38 |
+
<p>Par défaut, Magento demande de renseigner manuellement la position des produits. Fastidieux et contre-productif quand on a plus d'une dizaine de produits. Ici, une miniature produit permet d'identifier d'un seul coup d'oeil les produits que vous souhaitez mettre en avant. Une bulle d'aide, chargée par AJAX, affiche les informations que l'on souhaitent ! Il suffit de paramétrer les attributs que l'on souhaite afficher dans l'espace de configuration du back-office (voir Photo 3).</p>
|
39 |
+

|
40 |
+
<p><span style="font-size:18px">Un vrai gain de temps !</span></p>
|
41 |
+

|
42 |
+
<h4>Récapitulatif des points forts de cette extension Magento</h4>
|
43 |
+

|
44 |
+
<ul class="square-list">
|
45 |
+
<li><p>Système de <em>Drag & Drop</em> permettant de ranger aisément les produits selon la position souhaitée.</p></li>
|
46 |
+
<li><p>Affichage des produits par photo permettant d'identifier d’instantanément ceux désirés. <span class="bold">Ranger des centaines de produits en quelques minutes !</span></p></li>
|
47 |
+
<li><p>Bulle d'aide au survol permettant d'avoir toutes les caractéristiques techniques telles que le Prix, le Prix promotionnel, le Pourcentage de réduction si produit en offre spéciale, la référence, l'ID produit ainsi que tous les attributs de votre choix selon la configuration du module.</p>
|
48 |
+
<ul class="disc-list">
|
49 |
+
<li>
|
50 |
+
<p>Affichage avec label des produits non disponibles ; cela permet en un clin d’œil de mettre les produits épuisés en fin de liste.</p>
|
51 |
+
<p><img src="{{media url="wysiwyg/extension/merchandising/label-product.jpg"}}" width="380" height="160" alt="Les produits non disponibles sont affichés avec la mention 'Épuisé'" /></p>
|
52 |
+
<p>Il est aussi possible de ne pas inclure les produits épuisés et les produits dont le statut est désactivés dans la liste à l'aide de la configuration du module.</p>
|
53 |
+
</li>
|
54 |
+
</ul>
|
55 |
+
</li>
|
56 |
+
</ul></description>
|
57 |
+
<notes>Initial Release</notes>
|
58 |
+
<authors><author><name>Ilan PARMENTIER</name><user>Mageho</user><email>ilan.parmentier@mageho.com</email></author></authors>
|
59 |
+
<date>2013-05-07</date>
|
60 |
+
<time>17:15:18</time>
|
61 |
+
<contents><target name="magelocale"><dir name="fr_FR"><file name="Mageho_All.csv" hash="e4f2394435fea990e3f6b1ec968c7273"/><file name="Mageho_Sortproducts.csv" hash="2b75d031a008ee52024ee56281bdf7c3"/></dir></target><target name="mageetc"><dir name="modules"><file name="Mageho_All.xml" hash="92fbf727ce4c64233605ee7276525aed"/><file name="Mageho_Sortproducts.xml" hash="777c7b7f72d78e719eda6c2bbe36b690"/></dir></target><target name="magelocal"><dir name="Mageho"><dir name="All"><dir name="Block"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Fieldset"><file name="Extensions.php" hash="3cb049b292385aa84dff14c1472d41eb"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="1f1f8a668f52a26a72df6cfbead6485a"/></dir><dir name="etc"><file name="adminhtml.xml" hash="602adc885b83b88416ab50aced3fc207"/><file name="config.xml" hash="1401e67c17ac1d86daddcdeafca395ef"/><file name="system.xml" hash="3baf3a1ebb1105e7c7260cdcb8a96f9b"/></dir></dir><dir name="Sortproducts"><dir name="Block"><dir name="Adminhtml"><file name="Info.php" hash="d718fada1ab919b5ac6286fda50964bb"/><file name="Info.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/><file name="Sortgrid.php" hash="3cf9c9f27e9bbf893356191072303f3c"/><file name="Sortgrid.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/><file name="Tab.php" hash="4467d5a3fae44d8f9bf74a6769d2c6a8"/><file name="Tab.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir></dir><dir name="Helper"><file name="Data.php" hash="9e24dbfee79b96f5a29692bf132e2ac8"/><file name="Data.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir><dir name="Model"><file name="Observer.php" hash="82f727e0ae154da87afceb6738313945"/><file name="Observer.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/><dir name="Resource"><file name="Position.php" hash="ad41c330a19fed4ea7945c987d0fcf10"/><file name="Position.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir><dir name="System"><dir name="Config"><dir name="Source"><file name="Attributes.php" hash="8e5dd4240d07df4a99fb89578bd4e09a"/><file name="Attributes.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Mageho"><file name="SortproductsController.php" hash="e0786efd1f2557fed892f8f6a4f67dd4"/><file name="SortproductsController.php.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="732d750e132a184dd0027d49fd4f2de0"/><file name="adminhtml.xml.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/><file name="config.xml" hash="d95c26d38a352fa17b966ad50ace437c"/><file name="config.xml.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/><file name="system.xml" hash="7a3bfbdea4e5cff6e383b50a0e563a35"/><file name="system.xml.LCK" hash="091b90ac6be764824a9fa6f1939caaab"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="mageho"><dir name="sortproducts"><file name="placeholder.jpg" hash="b2b682d28a08a748a73d2cda70ab5a57"/><file name="sortproducts.css" hash="0939b00bf328fcb7f6b7f85e61876a3f"/></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="mageho"><file name="sortproducts.xml" hash="e87237697705cb433ea5705656162b75"/></dir></dir><dir name="template"><dir name="mageho"><dir name="sortproducts"><file name="info.phtml" hash="45583e4d8b832206e8c436fe6c41d501"/><file name="sortgrid.phtml" hash="c0b79247a7ac8511cb858aacda6351a9"/><file name="tab.phtml" hash="d55081f3fcbe8ef3d0faba8ec50debe2"/></dir></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="mageho"><dir name="sortproducts"><file name="builder.js" hash="c6321f204481f259724bd6455c0fdded"/><file name="controls.js" hash="03b502fd8ae202eb164b348749392720"/><file name="dragdrop.js" hash="046759400db7a6096376e50110104edd"/><file name="effects.js" hash="0dea24894889a4c537e1a451a35f03ca"/><file name="excanvas.js" hash="9d9cbb230cf8d560faf6f6b0f6b5a7ce"/><file name="loading.gif" hash="505aa41462b8840208e1a7d810eb6f48"/><file name="opentip.css" hash="27c49d652671d27a22d91ba32f22ba42"/><file name="opentip.js" hash="5ed35816281e22b7e8b84ba7fdee9485"/><file name="prototype.js" hash="007ae2fe795811f80cedf92fdb591c1b"/><file name="scriptaculous.js" hash="bb679d586e7fccb154156baaef9dfde5"/><file name="slider.js" hash="a9e58cc5f8dd281daa8d8dfee6a78834"/><file name="sound.js" hash="0b22e4379d79b33b696ee3cccf2827b5"/><file name="unittest.js" hash="07c049c24cb838939925425bb555cdf6"/></dir></dir></dir></target></contents>
|
62 |
+
<compatible/>
|
63 |
+
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
64 |
+
</package>
|
skin/adminhtml/default/default/mageho/sortproducts/placeholder.jpg
ADDED
Binary file
|
skin/adminhtml/default/default/mageho/sortproducts/sortproducts.css
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#sortlist-wrapper { overflow:hidden; margin:15px 0; }
|
2 |
+
#sortlist li { list-style:none; float:left; margin:4px; padding:4px 4px 2px; border:1px solid #ccc; position:relative; }
|
3 |
+
#sortlist li:hover, li.over { border-color:#666; }
|
4 |
+
|
5 |
+
.product_container { position:relative; }
|
6 |
+
.saleable { position:absolute; bottom:0; font-variant:small-caps; font-size:10px; background:#fff; opacity:0.9; padding:0 2px; }
|