Lanot_GridImage - Version 1.0.1.2

Version Notes

Added:
1. Support LightBox2
2. Configuration option for scaling big image.

Download this release

Release Info

Developer Magento Core Team
Extension Lanot_GridImage
Version 1.0.1.2
Comparing to
See all releases


Code changes from version 1.0.1.1 to 1.0.1.2

app/code/community/Lanot/GridImage/Block/Adminhtml/Grid/Renderer/Image.php CHANGED
@@ -1,164 +1,164 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@magentocommerce.com so we can send you a copy immediately.
14
- *
15
- * @category Lanot
16
- * @package Lanot_GridImage
17
- * @copyright Copyright (c) 2012 Lanot
18
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
- */
20
-
21
- class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
22
- extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
23
- {
24
- /**
25
- * @var bool
26
- */
27
- protected $_canClick = false;
28
- /**
29
- * @var bool
30
- */
31
- protected $_canShowLightbox = false;
32
- /**
33
- * @var string
34
- */
35
- protected $_imageClass = '';
36
- /**
37
- * @var null
38
- */
39
- protected $_imageSizeWidth = null;
40
- /**
41
- * @var null
42
- */
43
- protected $_imageSizeHeight = null;
44
- /**
45
- * @var null
46
- */
47
- protected $_imageSizeBigWidth = null;
48
- /**
49
- * @var null
50
- */
51
- protected $_imageSizeBigHeight = null;
52
-
53
- /**
54
- *
55
- */
56
- public function _construct()
57
- {
58
- parent::_construct();
59
-
60
- /** @var $helper Lanot_GridImage_Helper_Data */
61
- $helper = Mage::helper('lanot_gridimage');
62
-
63
- //define configuration
64
- $this->_canClick = $helper->canClick();
65
- $this->_canShowLightbox = $helper->canShowLightbox();
66
- $this->_imageClass = $helper->getImageClass();
67
- $size = $helper->getImageSize();
68
- $sizeBig = $helper->getImageBigSize();
69
-
70
- //thumbnail size in grid
71
- if (isset($size[0]) && !empty($size[0])) {
72
- $this->_imageSizeWidth = $size[0];
73
- }
74
- if (isset($size[1]) && !empty($size[1])) {
75
- $this->_imageSizeHeight = $size[1];
76
- }
77
-
78
- //size by image click
79
- if (isset($sizeBig[0]) && !empty($sizeBig[0])) {
80
- $this->_imageSizeBigWidth = $sizeBig[0];
81
- }
82
- if (isset($sizeBig[1]) && !empty($sizeBig[1])) {
83
- $this->_imageSizeBigHeight = $sizeBig[1];
84
- }
85
- }
86
-
87
- /**
88
- * @param Varien_Object $row
89
- * @return string
90
- */
91
- public function render(Varien_Object $row)
92
- {
93
- $value = $row->getData($this->getColumn()->getIndex());
94
- if (empty($value)) {
95
- return '';
96
- }
97
-
98
- /** @var $imageHelper Mage_Catalog_Helper_Image */
99
- $imageHelper = Mage::helper('catalog/image')->init($row, 'lanot_gridimage', $value);
100
-
101
- //prepare width and height
102
- $widthAndHeightTags = '';
103
- if($this->_imageSizeWidth && $this->_imageSizeHeight) {
104
- $imageHelper->resize($this->_imageSizeWidth, $this->_imageSizeHeight);
105
- $widthAndHeightTags .= ' width="' . $this->_imageSizeWidth . '"';
106
- $widthAndHeightTags .= ' heigth="' . $this->_imageSizeHeight . '"';
107
- } else if ($this->_imageSizeWidth) {
108
- $imageHelper->resize($this->_imageSizeWidth);
109
- $widthAndHeightTags .= ' width="' . $this->_imageSizeWidth . '"';
110
- } elseif ($this->_imageSizeHeight) {
111
- $imageHelper->resize(null, $this->_imageSizeHeight);
112
- $widthAndHeightTags .= ' heigth="' . $this->_imageSizeHeight . '"';
113
- }
114
-
115
- //prepare lightbox rel attribute
116
- $lightboxAttr = '';
117
- if ($this->_canShowLightbox) {
118
- $lightboxAttr = 'rel="lightbox"';
119
- }
120
-
121
- //prepare title attribute
122
- $titleAttr = sprintf('title="%s"', $this->escapeHtml($row->getName()));
123
-
124
- if ($this->_canClick) {
125
- $href = $this->_getImageUrl($row);
126
- return sprintf('<a href="%s" class="%s" target="_blank" %s %s><img src="%s" border="0" alt="" %s/>',
127
- $href,
128
- $this->_imageClass,
129
- $lightboxAttr,
130
- $titleAttr,
131
- $imageHelper,
132
- $widthAndHeightTags
133
- );
134
- } else {
135
- return sprintf('<img src="%s" class="%s" border="0" alt="" %s/>',
136
- $imageHelper,
137
- $this->_imageClass,
138
- $widthAndHeightTags
139
- );
140
- }
141
- }
142
-
143
- /**
144
- * @param Varien_Object $row
145
- * @return string
146
- */
147
- protected function _getImageUrl($row)
148
- {
149
- $value = $row->getData($this->getColumn()->getIndex());
150
-
151
- /** @var $imageHelper Mage_Catalog_Helper_Image */
152
- $imageHelper = Mage::helper('catalog/image')->init($row, 'lanot_gridimage_big', $value);
153
- if($this->_imageSizeBigWidth && $this->_imageSizeBigHeight) {
154
- $imageHelper->resize($this->_imageSizeBigWidth, $this->_imageSizeBigHeight);
155
- } else if ($this->_imageSizeBigWidth) {
156
- $imageHelper->resize($this->_imageSizeBigWidth);
157
- } elseif ($this->_imageSizeBigHeight) {
158
- $imageHelper->resize(null, $this->_imageSizeBigHeight);
159
- } else {
160
- return Mage::getSingleton('catalog/product_media_config')->getMediaUrl($value);
161
- }
162
- return $imageHelper->__toString();
163
- }
164
  }
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category Lanot
16
+ * @package Lanot_GridImage
17
+ * @copyright Copyright (c) 2012 Lanot
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
22
+ extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
23
+ {
24
+ /**
25
+ * @var bool
26
+ */
27
+ protected $_canClick = false;
28
+ /**
29
+ * @var bool
30
+ */
31
+ protected $_canShowLightbox = false;
32
+ /**
33
+ * @var string
34
+ */
35
+ protected $_imageClass = '';
36
+ /**
37
+ * @var null
38
+ */
39
+ protected $_imageSizeWidth = null;
40
+ /**
41
+ * @var null
42
+ */
43
+ protected $_imageSizeHeight = null;
44
+ /**
45
+ * @var null
46
+ */
47
+ protected $_imageSizeBigWidth = null;
48
+ /**
49
+ * @var null
50
+ */
51
+ protected $_imageSizeBigHeight = null;
52
+
53
+ /**
54
+ *
55
+ */
56
+ public function _construct()
57
+ {
58
+ parent::_construct();
59
+
60
+ /** @var $helper Lanot_GridImage_Helper_Data */
61
+ $helper = Mage::helper('lanot_gridimage');
62
+
63
+ //define configuration
64
+ $this->_canClick = $helper->canClick();
65
+ $this->_canShowLightbox = $helper->canShowLightbox();
66
+ $this->_imageClass = $helper->getImageClass();
67
+ $size = $helper->getImageSize();
68
+ $sizeBig = $helper->getImageBigSize();
69
+
70
+ //thumbnail size in grid
71
+ if (isset($size[0]) && !empty($size[0])) {
72
+ $this->_imageSizeWidth = $size[0];
73
+ }
74
+ if (isset($size[1]) && !empty($size[1])) {
75
+ $this->_imageSizeHeight = $size[1];
76
+ }
77
+
78
+ //size by image click
79
+ if (isset($sizeBig[0]) && !empty($sizeBig[0])) {
80
+ $this->_imageSizeBigWidth = $sizeBig[0];
81
+ }
82
+ if (isset($sizeBig[1]) && !empty($sizeBig[1])) {
83
+ $this->_imageSizeBigHeight = $sizeBig[1];
84
+ }
85
+ }
86
+
87
+ /**
88
+ * @param Varien_Object $row
89
+ * @return string
90
+ */
91
+ public function render(Varien_Object $row)
92
+ {
93
+ $value = $row->getData($this->getColumn()->getIndex());
94
+ if (empty($value)) {
95
+ return '';
96
+ }
97
+
98
+ /** @var $imageHelper Mage_Catalog_Helper_Image */
99
+ $imageHelper = Mage::helper('catalog/image')->init($row, 'lanot_gridimage', $value);
100
+
101
+ //prepare width and height
102
+ $widthAndHeightTags = '';
103
+ if($this->_imageSizeWidth && $this->_imageSizeHeight) {
104
+ $imageHelper->resize($this->_imageSizeWidth, $this->_imageSizeHeight);
105
+ $widthAndHeightTags .= ' width="' . $this->_imageSizeWidth . '"';
106
+ $widthAndHeightTags .= ' heigth="' . $this->_imageSizeHeight . '"';
107
+ } else if ($this->_imageSizeWidth) {
108
+ $imageHelper->resize($this->_imageSizeWidth);
109
+ $widthAndHeightTags .= ' width="' . $this->_imageSizeWidth . '"';
110
+ } elseif ($this->_imageSizeHeight) {
111
+ $imageHelper->resize(null, $this->_imageSizeHeight);
112
+ $widthAndHeightTags .= ' heigth="' . $this->_imageSizeHeight . '"';
113
+ }
114
+
115
+ //prepare lightbox rel attribute
116
+ $lightboxAttr = '';
117
+ if ($this->_canShowLightbox) {
118
+ $lightboxAttr = 'rel="lightbox"';
119
+ }
120
+
121
+ //prepare title attribute
122
+ $titleAttr = sprintf('title="%s"', $this->escapeHtml($row->getName()));
123
+
124
+ if ($this->_canClick) {
125
+ $href = $this->_getImageUrl($row);
126
+ return sprintf('<a href="%s" class="%s" target="_blank" %s %s><img src="%s" border="0" alt="" %s/>',
127
+ $href,
128
+ $this->_imageClass,
129
+ $lightboxAttr,
130
+ $titleAttr,
131
+ $imageHelper,
132
+ $widthAndHeightTags
133
+ );
134
+ } else {
135
+ return sprintf('<img src="%s" class="%s" border="0" alt="" %s/>',
136
+ $imageHelper,
137
+ $this->_imageClass,
138
+ $widthAndHeightTags
139
+ );
140
+ }
141
+ }
142
+
143
+ /**
144
+ * @param Varien_Object $row
145
+ * @return string
146
+ */
147
+ protected function _getImageUrl($row)
148
+ {
149
+ $value = $row->getData($this->getColumn()->getIndex());
150
+
151
+ /** @var $imageHelper Mage_Catalog_Helper_Image */
152
+ $imageHelper = Mage::helper('catalog/image')->init($row, 'lanot_gridimage_big', $value);
153
+ if($this->_imageSizeBigWidth && $this->_imageSizeBigHeight) {
154
+ $imageHelper->resize($this->_imageSizeBigWidth, $this->_imageSizeBigHeight);
155
+ } else if ($this->_imageSizeBigWidth) {
156
+ $imageHelper->resize($this->_imageSizeBigWidth);
157
+ } elseif ($this->_imageSizeBigHeight) {
158
+ $imageHelper->resize(null, $this->_imageSizeBigHeight);
159
+ } else {
160
+ return Mage::getSingleton('catalog/product_media_config')->getMediaUrl($value);
161
+ }
162
+ return $imageHelper->__toString();
163
+ }
164
  }
app/code/community/Lanot/GridImage/Helper/Data.php CHANGED
@@ -1,67 +1,67 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@magentocommerce.com so we can send you a copy immediately.
14
- *
15
- * @category Lanot
16
- * @package Lanot_GridImage
17
- * @copyright Copyright (c) 2012 Lanot
18
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
- */
20
-
21
- class Lanot_GridImage_Helper_Data extends Mage_Core_Helper_Abstract
22
- {
23
- /**
24
- * @return bool
25
- */
26
- public function canClick()
27
- {
28
- return (bool) Mage::getStoreConfig('lanot_gridimage/view/image_click', 0);
29
- }
30
-
31
- /**
32
- * @return bool
33
- */
34
- public function getImageClass()
35
- {
36
- return (string) Mage::getStoreConfig('lanot_gridimage/view/image_class', '');
37
- }
38
-
39
- /**
40
- * @return array
41
- */
42
- public function getImageSize()
43
- {
44
- $size = Mage::getStoreConfig('lanot_gridimage/view/image_size', 0);
45
- return @explode('x', strtolower($size));
46
- }
47
-
48
- /**
49
- * @return array
50
- */
51
- public function getImageBigSize()
52
- {
53
- $size = Mage::getStoreConfig('lanot_gridimage/view/image_big_size', 0);
54
- return @explode('x', strtolower($size));
55
- }
56
-
57
- /**
58
- * @return bool
59
- */
60
- public function canShowLightbox()
61
- {
62
- if (!$this->canClick()) {
63
- return false;
64
- }
65
- return (bool) Mage::getStoreConfig('lanot_gridimage/view/lightbox_enabled', 0);
66
- }
67
- }
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category Lanot
16
+ * @package Lanot_GridImage
17
+ * @copyright Copyright (c) 2012 Lanot
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Lanot_GridImage_Helper_Data extends Mage_Core_Helper_Abstract
22
+ {
23
+ /**
24
+ * @return bool
25
+ */
26
+ public function canClick()
27
+ {
28
+ return (bool) Mage::getStoreConfig('lanot_gridimage/view/image_click', 0);
29
+ }
30
+
31
+ /**
32
+ * @return bool
33
+ */
34
+ public function getImageClass()
35
+ {
36
+ return (string) Mage::getStoreConfig('lanot_gridimage/view/image_class', '');
37
+ }
38
+
39
+ /**
40
+ * @return array
41
+ */
42
+ public function getImageSize()
43
+ {
44
+ $size = Mage::getStoreConfig('lanot_gridimage/view/image_size', 0);
45
+ return @explode('x', strtolower($size));
46
+ }
47
+
48
+ /**
49
+ * @return array
50
+ */
51
+ public function getImageBigSize()
52
+ {
53
+ $size = Mage::getStoreConfig('lanot_gridimage/view/image_big_size', 0);
54
+ return @explode('x', strtolower($size));
55
+ }
56
+
57
+ /**
58
+ * @return bool
59
+ */
60
+ public function canShowLightbox()
61
+ {
62
+ if (!$this->canClick()) {
63
+ return false;
64
+ }
65
+ return (bool) Mage::getStoreConfig('lanot_gridimage/view/lightbox_enabled', 0);
66
+ }
67
+ }
app/code/community/Lanot/GridImage/Model/Handler.php CHANGED
@@ -1,107 +1,107 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@magentocommerce.com so we can send you a copy immediately.
14
- *
15
- * @category Lanot
16
- * @package Lanot_GridImage
17
- * @copyright Copyright (c) 2012 Lanot
18
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
- */
20
-
21
- class Lanot_GridImage_Model_Handler
22
- {
23
- const ATTRIBUTE_CODE = 'image';
24
-
25
- /**
26
- * @param Mage_Adminhtml_Block_Widget_Grid $block
27
- * @param array $extraColumnsData
28
- * @return Lanot_GridImage_Model_Handler
29
- */
30
- public function addColumnsToBlock(Mage_Adminhtml_Block_Widget_Grid $block, $extraColumnsData = array())
31
- {
32
- //#1. Add attribute to collection
33
- $this->_addImagesToCollectionResult($block->getCollection());
34
-
35
- //#2.Add new column
36
- $this->_addImageColumn($block, $extraColumnsData);
37
-
38
- //#3. Reorder columns
39
- $block->sortColumnsByOrder();
40
-
41
- return $this;
42
- }
43
-
44
- /**
45
- * @param Mage_Adminhtml_Block_Widget_Grid $grid
46
- * @return Lanot_GridImage_Model_Observer
47
- */
48
- protected function _addImageColumn($grid, $enabledData)
49
- {
50
- $size = Mage::helper('lanot_gridimage')->getImageSize();
51
- $width = !empty($size[0]) ? ((int) $size[0] + 10) . 'px' : null;
52
-
53
- $grid->addColumn('image', array(
54
- 'header' => Mage::helper('lanot_gridimage')->__('Image'),
55
- 'width' => $width,
56
- 'index' => 'image',
57
- 'sortable' => false,
58
- 'filter' => false,
59
- 'renderer' => 'lanot_gridimage/adminhtml_grid_renderer_image'
60
- ));
61
-
62
- if (isset($enabledData['after'])) {
63
- $grid->addColumnsOrder('image', $enabledData['after']);
64
- }
65
-
66
- return $this;
67
- }
68
-
69
- /**
70
- * @return mixed
71
- */
72
- protected function _getStoreId()
73
- {
74
- return Mage::app()->getRequest()->getParam('store', 0);
75
- }
76
-
77
- /**
78
- * @param Mage_Catalog_Model_Resource_Product_Collection $collection
79
- * @return bool
80
- */
81
- protected function _addImagesToCollectionResult(Mage_Catalog_Model_Resource_Product_Collection $collection)
82
- {
83
- $productIds = $collection->getColumnValues('entity_id');
84
- if (empty($productIds)) {
85
- return false;
86
- }
87
-
88
- /** $var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
89
- $attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', self::ATTRIBUTE_CODE);
90
- $attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
91
- if (!$attribute) {
92
- return false;
93
- }
94
-
95
- /** @var $resourceModel Lanot_GridImage_Model_Mysql4_Attribute */
96
- $resourceModel = Mage::getModel('lanot_gridimage/mysql4_attribute');
97
- $productsImages = $resourceModel->getAttributeEntityValues($attribute, $productIds, $this->_getStoreId());
98
-
99
- foreach ($collection as $product) {
100
- if (isset($productsImages[$product->getId()])) {
101
- $product->setData(self::ATTRIBUTE_CODE, $productsImages[$product->getId()]);
102
- }
103
- }
104
-
105
- return true;
106
- }
107
  }
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category Lanot
16
+ * @package Lanot_GridImage
17
+ * @copyright Copyright (c) 2012 Lanot
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Lanot_GridImage_Model_Handler
22
+ {
23
+ const ATTRIBUTE_CODE = 'image';
24
+
25
+ /**
26
+ * @param Mage_Adminhtml_Block_Widget_Grid $block
27
+ * @param array $extraColumnsData
28
+ * @return Lanot_GridImage_Model_Handler
29
+ */
30
+ public function addColumnsToBlock(Mage_Adminhtml_Block_Widget_Grid $block, $extraColumnsData = array())
31
+ {
32
+ //#1. Add attribute to collection
33
+ $this->_addImagesToCollectionResult($block->getCollection());
34
+
35
+ //#2.Add new column
36
+ $this->_addImageColumn($block, $extraColumnsData);
37
+
38
+ //#3. Reorder columns
39
+ $block->sortColumnsByOrder();
40
+
41
+ return $this;
42
+ }
43
+
44
+ /**
45
+ * @param Mage_Adminhtml_Block_Widget_Grid $grid
46
+ * @return Lanot_GridImage_Model_Observer
47
+ */
48
+ protected function _addImageColumn($grid, $enabledData)
49
+ {
50
+ $size = Mage::helper('lanot_gridimage')->getImageSize();
51
+ $width = !empty($size[0]) ? ((int) $size[0] + 10) . 'px' : null;
52
+
53
+ $grid->addColumn('image', array(
54
+ 'header' => Mage::helper('lanot_gridimage')->__('Image'),
55
+ 'width' => $width,
56
+ 'index' => 'image',
57
+ 'sortable' => false,
58
+ 'filter' => false,
59
+ 'renderer' => 'lanot_gridimage/adminhtml_grid_renderer_image'
60
+ ));
61
+
62
+ if (isset($enabledData['after'])) {
63
+ $grid->addColumnsOrder('image', $enabledData['after']);
64
+ }
65
+
66
+ return $this;
67
+ }
68
+
69
+ /**
70
+ * @return mixed
71
+ */
72
+ protected function _getStoreId()
73
+ {
74
+ return Mage::app()->getRequest()->getParam('store', 0);
75
+ }
76
+
77
+ /**
78
+ * @param Mage_Catalog_Model_Resource_Product_Collection $collection
79
+ * @return bool
80
+ */
81
+ protected function _addImagesToCollectionResult(Mage_Catalog_Model_Resource_Product_Collection $collection)
82
+ {
83
+ $productIds = $collection->getColumnValues('entity_id');
84
+ if (empty($productIds)) {
85
+ return false;
86
+ }
87
+
88
+ /** $var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
89
+ $attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', self::ATTRIBUTE_CODE);
90
+ $attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
91
+ if (!$attribute) {
92
+ return false;
93
+ }
94
+
95
+ /** @var $resourceModel Lanot_GridImage_Model_Mysql4_Attribute */
96
+ $resourceModel = Mage::getModel('lanot_gridimage/mysql4_attribute');
97
+ $productsImages = $resourceModel->getAttributeEntityValues($attribute, $productIds, $this->_getStoreId());
98
+
99
+ foreach ($collection as $product) {
100
+ if (isset($productsImages[$product->getId()])) {
101
+ $product->setData(self::ATTRIBUTE_CODE, $productsImages[$product->getId()]);
102
+ }
103
+ }
104
+
105
+ return true;
106
+ }
107
  }
app/code/community/Lanot/GridImage/Model/Mysql4/Attribute.php CHANGED
@@ -1,51 +1,51 @@
1
- <?php
2
- /**
3
- * Banner Category item resource model
4
- *
5
- * @author Lanot
6
- */
7
- class Lanot_GridImage_Model_Mysql4_Attribute
8
- //extends Mage_Core_Model_Resource_Db_Abstract
9
- extends Mage_Core_Model_Mysql4_Abstract
10
- {
11
- /**
12
- * Initialize connection and define main table and primary key
13
- */
14
- protected function _construct()
15
- {
16
- $this->_init('catalog/product', 'entity_id');
17
- }
18
-
19
- public function getAttributeEntityValues(Mage_Catalog_Model_Resource_Eav_Attribute $attribute, $entityIds, $storeId = 0)
20
- {
21
- $attributeValues = array();
22
- if (!is_array($entityIds)) {
23
- $entityIds = array();
24
- }
25
-
26
- if (empty($entityIds)) {
27
- return $attributeValues;
28
- }
29
-
30
- $attributeId = (int) $attribute->getAttributeId();
31
- $storeId = (int) $storeId;
32
-
33
-
34
- $read = $this->getReadConnection();
35
- $select = $read->select()
36
- ->from(array('a' => $attribute->getBackendTable()), array('entity_id', 'value'))
37
- ->where('a.attribute_id = ' . $attributeId)
38
- ->where('a.`entity_id` IN (' . implode(',', $entityIds) .')')
39
- ->where('a.store_id IN (0, ?)', $storeId)
40
- ->where("a.value != 'no_selection'")
41
- ->order('a.store_id');
42
-
43
- //update data
44
- $rowSet = $read->fetchAll($select);
45
- foreach ($rowSet as $row) {
46
- $attributeValues[$row['entity_id']] = $row['value'];
47
- }
48
-
49
- return $attributeValues;
50
- }
51
- }
1
+ <?php
2
+ /**
3
+ * Banner Category item resource model
4
+ *
5
+ * @author Lanot
6
+ */
7
+ class Lanot_GridImage_Model_Mysql4_Attribute
8
+ //extends Mage_Core_Model_Resource_Db_Abstract
9
+ extends Mage_Core_Model_Mysql4_Abstract
10
+ {
11
+ /**
12
+ * Initialize connection and define main table and primary key
13
+ */
14
+ protected function _construct()
15
+ {
16
+ $this->_init('catalog/product', 'entity_id');
17
+ }
18
+
19
+ public function getAttributeEntityValues(Mage_Catalog_Model_Resource_Eav_Attribute $attribute, $entityIds, $storeId = 0)
20
+ {
21
+ $attributeValues = array();
22
+ if (!is_array($entityIds)) {
23
+ $entityIds = array();
24
+ }
25
+
26
+ if (empty($entityIds)) {
27
+ return $attributeValues;
28
+ }
29
+
30
+ $attributeId = (int) $attribute->getAttributeId();
31
+ $storeId = (int) $storeId;
32
+
33
+
34
+ $read = $this->getReadConnection();
35
+ $select = $read->select()
36
+ ->from(array('a' => $attribute->getBackendTable()), array('entity_id', 'value'))
37
+ ->where('a.attribute_id = ' . $attributeId)
38
+ ->where('a.`entity_id` IN (' . implode(',', $entityIds) .')')
39
+ ->where('a.store_id IN (0, ?)', $storeId)
40
+ ->where("a.value != 'no_selection'")
41
+ ->order('a.store_id');
42
+
43
+ //update data
44
+ $rowSet = $read->fetchAll($select);
45
+ foreach ($rowSet as $row) {
46
+ $attributeValues[$row['entity_id']] = $row['value'];
47
+ }
48
+
49
+ return $attributeValues;
50
+ }
51
+ }
app/code/community/Lanot/GridImage/Model/Observer.php CHANGED
@@ -1,141 +1,141 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Open Software License (OSL 3.0)
8
- * that is bundled with this package in the file LICENSE.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/osl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@magentocommerce.com so we can send you a copy immediately.
14
- *
15
- * @category Lanot
16
- * @package Lanot_GridImage
17
- * @copyright Copyright (c) 2012 Lanot
18
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
- */
20
-
21
- class Lanot_GridImage_Model_Observer
22
- {
23
- /**
24
- * @var null|array
25
- */
26
- protected $_rulesEnabled = null;
27
-
28
- /**
29
- * @var null|array
30
- */
31
- protected $_rulesDisabled= null;
32
-
33
- /**
34
- * @var array
35
- */
36
- protected $_layoutHandles = array('INIT_LIGHTBOX');
37
-
38
- /**
39
- * @param Varien_Object $observer
40
- */
41
- public function adminhtmlBlockHtmlBefore($observer)
42
- {
43
- if (!$this->_isViewEnabled()) {
44
- return $this;
45
- }
46
- /** @var $block Mage_Adminhtml_Block_Widget_Grid */
47
- $block = $observer->getEvent()->getBlock();
48
- if (!$block) {
49
- return $this;
50
- }
51
-
52
- if (null === $this->_rulesEnabled) {
53
- $this->_initRules();
54
- }
55
-
56
- $enabledData = $this->_isEnabled($block);
57
- if ((false === $enabledData) ||
58
- $this->_isDisabled($block) ||
59
- !$block->getCollection()->isLoaded() //fix for export - do not export images
60
- ) {
61
- return $this;
62
- }
63
-
64
- Mage::getModel('lanot_gridimage/handler')->addColumnsToBlock($block, $enabledData);
65
- return $this;
66
- }
67
-
68
- /**
69
- * @return bool
70
- */
71
- protected function _isViewEnabled()
72
- {
73
- return (bool) Mage::getStoreConfig('lanot_gridimage/view/enabled', 0);
74
- }
75
-
76
- /**
77
- * Init rules from configuration
78
- *
79
- * @return Lanot_GridImage_Model_Observer
80
- */
81
- protected function _initRules()
82
- {
83
- $this->_rulesEnabled = array();
84
-
85
- /** @var $ruleNode Mage_Core_Model_Config_Element */
86
- if (Mage::getConfig()->getNode('default/lanot_gridimage/rules/enabled')) {
87
- foreach(Mage::getConfig()->getNode('default/lanot_gridimage/rules/enabled')->children() as $ruleClass => $ruleNode) {
88
- $ruleClass = trim($ruleClass);
89
- $this->_rulesEnabled[$ruleClass] = array('after' => $ruleNode->getAttribute('after'));
90
- }
91
- } else {
92
- $this->_rulesEnabled = array();
93
- }
94
-
95
- if (Mage::getConfig()->getNode('default/lanot_gridimage/rules/disabled')) {
96
- foreach(Mage::getConfig()->getNode('default/lanot_gridimage/rules/disabled')->children() as $ruleClass => $ruleNode) {
97
- $ruleClass = trim($ruleClass);
98
- $this->_rulesDisabled[$ruleClass] = $ruleClass;
99
- }
100
- } else {
101
- $this->_rulesDisabled = array();
102
- }
103
-
104
- return $this;
105
- }
106
-
107
- /**
108
- * Check if is block mathed by rules
109
- *
110
- * @param Mage_Adminhtml_Block_Template $block
111
- * @return bool|array
112
- */
113
- protected function _isEnabled($block)
114
- {
115
- //just verify block instance of widget grid and instance of rules
116
- foreach($this->_rulesEnabled as $ruleClass => $ruleData) {
117
- //print get_class($block);
118
- if (($block instanceof Mage_Adminhtml_Block_Widget_Grid) && ($block instanceof $ruleClass)) {
119
- return $ruleData;
120
- }
121
- }
122
- return false;
123
- }
124
-
125
- /**
126
- * Check if is block mathed by rules
127
- *
128
- * @param Mage_Adminhtml_Block_Template $block
129
- * @return bool
130
- */
131
- protected function _isDisabled($block)
132
- {
133
- //just verify block instance of widget grid and instance of rules
134
- foreach($this->_rulesDisabled as $ruleClass) {
135
- if (($block instanceof Mage_Adminhtml_Block_Widget_Grid) && ($block instanceof $ruleClass)) {
136
- return true;
137
- }
138
- }
139
- return false;
140
- }
141
- }
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category Lanot
16
+ * @package Lanot_GridImage
17
+ * @copyright Copyright (c) 2012 Lanot
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Lanot_GridImage_Model_Observer
22
+ {
23
+ /**
24
+ * @var null|array
25
+ */
26
+ protected $_rulesEnabled = null;
27
+
28
+ /**
29
+ * @var null|array
30
+ */
31
+ protected $_rulesDisabled= null;
32
+
33
+ /**
34
+ * @var array
35
+ */
36
+ protected $_layoutHandles = array('INIT_LIGHTBOX');
37
+
38
+ /**
39
+ * @param Varien_Object $observer
40
+ */
41
+ public function adminhtmlBlockHtmlBefore($observer)
42
+ {
43
+ if (!$this->_isViewEnabled()) {
44
+ return $this;
45
+ }
46
+ /** @var $block Mage_Adminhtml_Block_Widget_Grid */
47
+ $block = $observer->getEvent()->getBlock();
48
+ if (!$block) {
49
+ return $this;
50
+ }
51
+
52
+ if (null === $this->_rulesEnabled) {
53
+ $this->_initRules();
54
+ }
55
+
56
+ $enabledData = $this->_isEnabled($block);
57
+ if ((false === $enabledData) ||
58
+ $this->_isDisabled($block) ||
59
+ !$block->getCollection()->isLoaded() //fix for export - do not export images
60
+ ) {
61
+ return $this;
62
+ }
63
+
64
+ Mage::getModel('lanot_gridimage/handler')->addColumnsToBlock($block, $enabledData);
65
+ return $this;
66
+ }
67
+
68
+ /**
69
+ * @return bool
70
+ */
71
+ protected function _isViewEnabled()
72
+ {
73
+ return (bool) Mage::getStoreConfig('lanot_gridimage/view/enabled', 0);
74
+ }
75
+
76
+ /**
77
+ * Init rules from configuration
78
+ *
79
+ * @return Lanot_GridImage_Model_Observer
80
+ */
81
+ protected function _initRules()
82
+ {
83
+ $this->_rulesEnabled = array();
84
+
85
+ /** @var $ruleNode Mage_Core_Model_Config_Element */
86
+ if (Mage::getConfig()->getNode('default/lanot_gridimage/rules/enabled')) {
87
+ foreach(Mage::getConfig()->getNode('default/lanot_gridimage/rules/enabled')->children() as $ruleClass => $ruleNode) {
88
+ $ruleClass = trim($ruleClass);
89
+ $this->_rulesEnabled[$ruleClass] = array('after' => $ruleNode->getAttribute('after'));
90
+ }
91
+ } else {
92
+ $this->_rulesEnabled = array();
93
+ }
94
+
95
+ if (Mage::getConfig()->getNode('default/lanot_gridimage/rules/disabled')) {
96
+ foreach(Mage::getConfig()->getNode('default/lanot_gridimage/rules/disabled')->children() as $ruleClass => $ruleNode) {
97
+ $ruleClass = trim($ruleClass);
98
+ $this->_rulesDisabled[$ruleClass] = $ruleClass;
99
+ }
100
+ } else {
101
+ $this->_rulesDisabled = array();
102
+ }
103
+
104
+ return $this;
105
+ }
106
+
107
+ /**
108
+ * Check if is block mathed by rules
109
+ *
110
+ * @param Mage_Adminhtml_Block_Template $block
111
+ * @return bool|array
112
+ */
113
+ protected function _isEnabled($block)
114
+ {
115
+ //just verify block instance of widget grid and instance of rules
116
+ foreach($this->_rulesEnabled as $ruleClass => $ruleData) {
117
+ //print get_class($block);
118
+ if (($block instanceof Mage_Adminhtml_Block_Widget_Grid) && ($block instanceof $ruleClass)) {
119
+ return $ruleData;
120
+ }
121
+ }
122
+ return false;
123
+ }
124
+
125
+ /**
126
+ * Check if is block mathed by rules
127
+ *
128
+ * @param Mage_Adminhtml_Block_Template $block
129
+ * @return bool
130
+ */
131
+ protected function _isDisabled($block)
132
+ {
133
+ //just verify block instance of widget grid and instance of rules
134
+ foreach($this->_rulesDisabled as $ruleClass) {
135
+ if (($block instanceof Mage_Adminhtml_Block_Widget_Grid) && ($block instanceof $ruleClass)) {
136
+ return true;
137
+ }
138
+ }
139
+ return false;
140
+ }
141
+ }
app/code/community/Lanot/GridImage/etc/adminhtml.xml CHANGED
@@ -1,26 +1,26 @@
1
- <?xml version="1.0"?>
2
- <config>
3
-
4
- <acl>
5
- <resources>
6
- <admin>
7
- <children>
8
-
9
- <system>
10
- <children>
11
- <config>
12
- <children>
13
- <lanot_gridimage translate="title" module="lanot_gridimage">
14
- <title>Lanot Grid Image Settings</title>
15
- </lanot_gridimage>
16
- </children>
17
- </config>
18
- </children>
19
- </system>
20
-
21
- </children>
22
- </admin>
23
- </resources>
24
- </acl>
25
-
26
  </config>
1
+ <?xml version="1.0"?>
2
+ <config>
3
+
4
+ <acl>
5
+ <resources>
6
+ <admin>
7
+ <children>
8
+
9
+ <system>
10
+ <children>
11
+ <config>
12
+ <children>
13
+ <lanot_gridimage translate="title" module="lanot_gridimage">
14
+ <title>Lanot Grid Image Settings</title>
15
+ </lanot_gridimage>
16
+ </children>
17
+ </config>
18
+ </children>
19
+ </system>
20
+
21
+ </children>
22
+ </admin>
23
+ </resources>
24
+ </acl>
25
+
26
  </config>
app/code/community/Lanot/GridImage/etc/config.xml CHANGED
@@ -1,86 +1,86 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <config>
3
-
4
- <modules>
5
- <Lanot_GridImage>
6
- <version>1.0.1.1</version>
7
- </Lanot_GridImage>
8
- </modules>
9
-
10
- <global>
11
- <helpers>
12
- <lanot_gridimage>
13
- <class>Lanot_GridImage_Helper</class>
14
- </lanot_gridimage>
15
- </helpers>
16
-
17
- <blocks>
18
- <lanot_gridimage>
19
- <class>Lanot_GridImage_Block</class>
20
- </lanot_gridimage>
21
- </blocks>
22
-
23
- <models>
24
- <lanot_gridimage>
25
- <class>Lanot_GridImage_Model</class>
26
- <resourceModel>lanot_gridimage_resource</resourceModel>
27
- </lanot_gridimage>
28
- </models>
29
-
30
- <lanot_gridimage_resource>
31
- <class>Lanot_GridImage_Model_Mysql4</class>
32
- </lanot_gridimage_resource>
33
- </global>
34
-
35
- <adminhtml>
36
- <!-- OBSERVER EVENTS -->
37
- <events>
38
- <!-- ADMIN HTML BLOCK EVENTS -->
39
- <adminhtml_block_html_before>
40
- <observers>
41
- <lanot_gridimage>
42
- <type>singleton</type>
43
- <class>lanot_gridimage/observer</class>
44
- <method>adminhtmlBlockHtmlBefore</method>
45
- </lanot_gridimage>
46
- </observers>
47
- </adminhtml_block_html_before>
48
- <!--/ADMIN HTML BLOCK EVENTS -->
49
- </events>
50
- <!--/OBSERVER EVENTS -->
51
-
52
- <layout>
53
- <updates>
54
- <lanot_gridimage>
55
- <file>lanot_gridimage.xml</file>
56
- </lanot_gridimage>
57
- </updates>
58
- </layout>
59
- </adminhtml>
60
-
61
- <default>
62
- <lanot_gridimage>
63
- <view>
64
- <enabled>1</enabled>
65
- <image_click>1</image_click>
66
- <lightbox_enabled>1</lightbox_enabled>
67
- <image_class>product_thumbnail</image_class>
68
- <image_size>120x120</image_size>
69
- <image_big_size>600x600</image_big_size>
70
- </view>
71
-
72
- <!-- rules for matching -->
73
- <rules>
74
- <enabled>
75
- <Mage_Adminhtml_Block_Catalog_Product_Grid after="entity_id"/>
76
- </enabled>
77
-
78
- <disabled>
79
- <Mage_Adminhtml_Block_Review_Product_Grid/>
80
- <Mage_Adminhtml_Block_Urlrewrite_Product_Grid/>
81
- </disabled>
82
- </rules>
83
- <!-- /rules for matching -->
84
- </lanot_gridimage>
85
- </default>
86
  </config>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+
4
+ <modules>
5
+ <Lanot_GridImage>
6
+ <version>1.0.1.2</version>
7
+ </Lanot_GridImage>
8
+ </modules>
9
+
10
+ <global>
11
+ <helpers>
12
+ <lanot_gridimage>
13
+ <class>Lanot_GridImage_Helper</class>
14
+ </lanot_gridimage>
15
+ </helpers>
16
+
17
+ <blocks>
18
+ <lanot_gridimage>
19
+ <class>Lanot_GridImage_Block</class>
20
+ </lanot_gridimage>
21
+ </blocks>
22
+
23
+ <models>
24
+ <lanot_gridimage>
25
+ <class>Lanot_GridImage_Model</class>
26
+ <resourceModel>lanot_gridimage_resource</resourceModel>
27
+ </lanot_gridimage>
28
+ </models>
29
+
30
+ <lanot_gridimage_resource>
31
+ <class>Lanot_GridImage_Model_Mysql4</class>
32
+ </lanot_gridimage_resource>
33
+ </global>
34
+
35
+ <adminhtml>
36
+ <!-- OBSERVER EVENTS -->
37
+ <events>
38
+ <!-- ADMIN HTML BLOCK EVENTS -->
39
+ <adminhtml_block_html_before>
40
+ <observers>
41
+ <lanot_gridimage>
42
+ <type>singleton</type>
43
+ <class>lanot_gridimage/observer</class>
44
+ <method>adminhtmlBlockHtmlBefore</method>
45
+ </lanot_gridimage>
46
+ </observers>
47
+ </adminhtml_block_html_before>
48
+ <!--/ADMIN HTML BLOCK EVENTS -->
49
+ </events>
50
+ <!--/OBSERVER EVENTS -->
51
+
52
+ <layout>
53
+ <updates>
54
+ <lanot_gridimage>
55
+ <file>lanot_gridimage.xml</file>
56
+ </lanot_gridimage>
57
+ </updates>
58
+ </layout>
59
+ </adminhtml>
60
+
61
+ <default>
62
+ <lanot_gridimage>
63
+ <view>
64
+ <enabled>1</enabled>
65
+ <image_click>1</image_click>
66
+ <lightbox_enabled>1</lightbox_enabled>
67
+ <image_class>product_thumbnail</image_class>
68
+ <image_size>120x120</image_size>
69
+ <image_big_size>600x600</image_big_size>
70
+ </view>
71
+
72
+ <!-- rules for matching -->
73
+ <rules>
74
+ <enabled>
75
+ <Mage_Adminhtml_Block_Catalog_Product_Grid after="entity_id"/>
76
+ </enabled>
77
+
78
+ <disabled>
79
+ <Mage_Adminhtml_Block_Review_Product_Grid/>
80
+ <Mage_Adminhtml_Block_Urlrewrite_Product_Grid/>
81
+ </disabled>
82
+ </rules>
83
+ <!-- /rules for matching -->
84
+ </lanot_gridimage>
85
+ </default>
86
  </config>
app/code/community/Lanot/GridImage/etc/system.xml CHANGED
@@ -1,93 +1,93 @@
1
- <?xml version="1.0"?>
2
- <config>
3
- <tabs>
4
- <lanot translate="label">
5
- <label>Lanot Extensions</label>
6
- <sort_order>200</sort_order>
7
- </lanot>
8
- </tabs>
9
- <sections>
10
- <lanot_gridimage>
11
- <class>separator-top</class>
12
- <label>Grid Image</label>
13
- <tab>lanot</tab>
14
- <frontend_type>text</frontend_type>
15
- <sort_order>800</sort_order>
16
- <show_in_default>1</show_in_default>
17
- <show_in_website>0</show_in_website>
18
- <show_in_store>0</show_in_store>
19
- <groups>
20
- <view translate="label">
21
- <label>Easy Grid Image Settings</label>
22
- <frontend_type>text</frontend_type>
23
- <sort_order>10</sort_order>
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
- <enabled translate="label">
29
- <label>Enabled at Products Grid</label>
30
- <frontend_type>select</frontend_type>
31
- <source_model>adminhtml/system_config_source_yesno</source_model>
32
- <sort_order>10</sort_order>
33
- <show_in_default>1</show_in_default>
34
- <show_in_website>0</show_in_website>
35
- <show_in_store>0</show_in_store>
36
- </enabled>
37
-
38
- <image_click translate="label">
39
- <label>Allow open image by on click</label>
40
- <frontend_type>select</frontend_type>
41
- <source_model>adminhtml/system_config_source_yesno</source_model>
42
- <sort_order>20</sort_order>
43
- <show_in_default>1</show_in_default>
44
- <show_in_website>0</show_in_website>
45
- <show_in_store>0</show_in_store>
46
- </image_click>
47
-
48
- <lightbox_enabled translate="label">
49
- <depends><image_click>1</image_click></depends>
50
- <label>Use Ligthbox</label>
51
- <comment>Floating window for showing images</comment>
52
- <frontend_type>select</frontend_type>
53
- <source_model>adminhtml/system_config_source_yesno</source_model>
54
- <sort_order>25</sort_order>
55
- <show_in_default>1</show_in_default>
56
- <show_in_website>0</show_in_website>
57
- <show_in_store>0</show_in_store>
58
- </lightbox_enabled>
59
-
60
- <image_class translate="label">
61
- <label>Image CSS class</label>
62
- <frontend_type>text</frontend_type>
63
- <sort_order>30</sort_order>
64
- <show_in_default>1</show_in_default>
65
- <show_in_website>0</show_in_website>
66
- <show_in_store>0</show_in_store>
67
- </image_class>
68
-
69
- <image_size translate="label">
70
- <label>Image size</label>
71
- <comment>Size (Ex. 100x100) for Product Image</comment>
72
- <frontend_type>text</frontend_type>
73
- <sort_order>40</sort_order>
74
- <show_in_default>1</show_in_default>
75
- <show_in_website>0</show_in_website>
76
- <show_in_store>0</show_in_store>
77
- </image_size>
78
-
79
- <image_big_size translate="label">
80
- <label>Big Image size</label>
81
- <comment>Size (Ex. 600x600) for Product Image, that is opened by click</comment>
82
- <frontend_type>text</frontend_type>
83
- <sort_order>50</sort_order>
84
- <show_in_default>1</show_in_default>
85
- <show_in_website>0</show_in_website>
86
- <show_in_store>0</show_in_store>
87
- </image_big_size>
88
- </fields>
89
- </view>
90
- </groups>
91
- </lanot_gridimage>
92
- </sections>
93
- </config>
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <tabs>
4
+ <lanot translate="label">
5
+ <label>Lanot Extensions</label>
6
+ <sort_order>200</sort_order>
7
+ </lanot>
8
+ </tabs>
9
+ <sections>
10
+ <lanot_gridimage>
11
+ <class>separator-top</class>
12
+ <label>Grid Image</label>
13
+ <tab>lanot</tab>
14
+ <frontend_type>text</frontend_type>
15
+ <sort_order>800</sort_order>
16
+ <show_in_default>1</show_in_default>
17
+ <show_in_website>0</show_in_website>
18
+ <show_in_store>0</show_in_store>
19
+ <groups>
20
+ <view translate="label">
21
+ <label>Easy Grid Image Settings</label>
22
+ <frontend_type>text</frontend_type>
23
+ <sort_order>10</sort_order>
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
+ <enabled translate="label">
29
+ <label>Enabled at Products Grid</label>
30
+ <frontend_type>select</frontend_type>
31
+ <source_model>adminhtml/system_config_source_yesno</source_model>
32
+ <sort_order>10</sort_order>
33
+ <show_in_default>1</show_in_default>
34
+ <show_in_website>0</show_in_website>
35
+ <show_in_store>0</show_in_store>
36
+ </enabled>
37
+
38
+ <image_click translate="label">
39
+ <label>Allow open image by on click</label>
40
+ <frontend_type>select</frontend_type>
41
+ <source_model>adminhtml/system_config_source_yesno</source_model>
42
+ <sort_order>20</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>0</show_in_website>
45
+ <show_in_store>0</show_in_store>
46
+ </image_click>
47
+
48
+ <lightbox_enabled translate="label">
49
+ <depends><image_click>1</image_click></depends>
50
+ <label>Use Ligthbox</label>
51
+ <comment>Floating window for showing images</comment>
52
+ <frontend_type>select</frontend_type>
53
+ <source_model>adminhtml/system_config_source_yesno</source_model>
54
+ <sort_order>25</sort_order>
55
+ <show_in_default>1</show_in_default>
56
+ <show_in_website>0</show_in_website>
57
+ <show_in_store>0</show_in_store>
58
+ </lightbox_enabled>
59
+
60
+ <image_class translate="label">
61
+ <label>Image CSS class</label>
62
+ <frontend_type>text</frontend_type>
63
+ <sort_order>30</sort_order>
64
+ <show_in_default>1</show_in_default>
65
+ <show_in_website>0</show_in_website>
66
+ <show_in_store>0</show_in_store>
67
+ </image_class>
68
+
69
+ <image_size translate="label">
70
+ <label>Image size</label>
71
+ <comment>Size (Ex. 100x100) for Product Image</comment>
72
+ <frontend_type>text</frontend_type>
73
+ <sort_order>40</sort_order>
74
+ <show_in_default>1</show_in_default>
75
+ <show_in_website>0</show_in_website>
76
+ <show_in_store>0</show_in_store>
77
+ </image_size>
78
+
79
+ <image_big_size translate="label">
80
+ <label>Big Image size</label>
81
+ <comment>Size (Ex. 600x600) for Product Image, that is opened by click</comment>
82
+ <frontend_type>text</frontend_type>
83
+ <sort_order>50</sort_order>
84
+ <show_in_default>1</show_in_default>
85
+ <show_in_website>0</show_in_website>
86
+ <show_in_store>0</show_in_store>
87
+ </image_big_size>
88
+ </fields>
89
+ </view>
90
+ </groups>
91
+ </lanot_gridimage>
92
+ </sections>
93
+ </config>
app/design/adminhtml/default/default/layout/lanot_gridimage.xml CHANGED
@@ -1,20 +1,20 @@
1
- <?xml version="1.0"?>
2
- <!--
3
- /**
4
- * Magento backend layout
5
- *
6
- * @author Lanot
7
- */
8
- -->
9
- <layout>
10
- <adminhtml_catalog_product_index>
11
- <reference name="head">
12
- <action method="addJs"><script>lanot/lightbox2/js/lightbox.js</script></action>
13
- <action method="addJs"><script>lanot/lightbox2/js/scriptaculous.js?load=effects,builder</script></action>
14
- <action method="addItem"><type>skin_css</type><name>lanot/lightbox2/css/lightbox.css</name><params/></action>
15
- </reference>
16
- <reference name="content">
17
- <block type="core/template" template="lanot/gridimage/js.phtml" before="-"/>
18
- </reference>
19
- </adminhtml_catalog_product_index>
20
  </layout>
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento backend layout
5
+ *
6
+ * @author Lanot
7
+ */
8
+ -->
9
+ <layout>
10
+ <adminhtml_catalog_product_index>
11
+ <reference name="head">
12
+ <action method="addJs"><script>lanot/lightbox2/js/lightbox.js</script></action>
13
+ <action method="addJs"><script>lanot/lightbox2/js/scriptaculous.js?load=effects,builder</script></action>
14
+ <action method="addItem"><type>skin_css</type><name>lanot/lightbox2/css/lightbox.css</name><params/></action>
15
+ </reference>
16
+ <reference name="content">
17
+ <block type="core/template" template="lanot/gridimage/js.phtml" before="-"/>
18
+ </reference>
19
+ </adminhtml_catalog_product_index>
20
  </layout>
app/design/adminhtml/default/default/template/lanot/gridimage/js.phtml CHANGED
@@ -1,10 +1,10 @@
1
- <?php
2
- $skinUrl = Mage::getDesign()->getSkinBaseUrl(array(
3
- '_package' => Mage_Core_Model_Design_Package::DEFAULT_PACKAGE,
4
- '_theme' => Mage_Core_Model_Design_Package::DEFAULT_THEME,
5
- ));
6
- ?>
7
- <script type="text/javascript">
8
- LightboxOptions.fileLoadingImage = '<?php echo $skinUrl?>lanot/lightbox2/images/loading.gif';
9
- LightboxOptions.fileBottomNavCloseImage = '<?php echo $skinUrl?>lanot/lightbox2/images/closelabel.gif';
10
  </script>
1
+ <?php
2
+ $skinUrl = Mage::getDesign()->getSkinBaseUrl(array(
3
+ '_package' => Mage_Core_Model_Design_Package::DEFAULT_PACKAGE,
4
+ '_theme' => Mage_Core_Model_Design_Package::DEFAULT_THEME,
5
+ ));
6
+ ?>
7
+ <script type="text/javascript">
8
+ LightboxOptions.fileLoadingImage = '<?php echo $skinUrl?>lanot/lightbox2/images/loading.gif';
9
+ LightboxOptions.fileBottomNavCloseImage = '<?php echo $skinUrl?>lanot/lightbox2/images/closelabel.gif';
10
  </script>
app/etc/modules/Lanot_GridImage.xml CHANGED
@@ -1,12 +1,12 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <config>
3
- <modules>
4
- <Lanot_GridImage>
5
- <active>true</active>
6
- <codePool>community</codePool>
7
- <depends>
8
- <Mage_Adminhtml />
9
- </depends>
10
- </Lanot_GridImage>
11
- </modules>
12
  </config>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Lanot_GridImage>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Adminhtml />
9
+ </depends>
10
+ </Lanot_GridImage>
11
+ </modules>
12
  </config>
js/lanot/lightbox2/js/builder.js CHANGED
@@ -1,136 +1,136 @@
1
- // script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
-
3
- // Copyright (c) 2005-2007 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(/"/,'&quot;') + '"');
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
- }
1
+ // script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
+
3
+ // Copyright (c) 2005-2007 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(/"/,'&quot;') + '"');
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/lanot/lightbox2/js/effects.js CHANGED
@@ -1,1122 +1,1122 @@
1
- // script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
-
3
- // Copyright (c) 2005-2007 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) + 0.5;
76
- },
77
- reverse: function(pos) {
78
- return 1-pos;
79
- },
80
- flicker: function(pos) {
81
- var pos = ((-Math.cos(pos*Math.PI)/4) + 0.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) + 0.5;
86
- },
87
- pulse: function(pos, pulses) {
88
- pulses = pulses || 5;
89
- return (
90
- ((pos % (1/pulses)) * pulses).round() == 0 ?
91
- ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
92
- 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
93
- );
94
- },
95
- spring: function(pos) {
96
- return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
97
- },
98
- none: function(pos) {
99
- return 0;
100
- },
101
- full: function(pos) {
102
- return 1;
103
- }
104
- },
105
- DefaultOptions: {
106
- duration: 1.0, // seconds
107
- fps: 100, // 100= assume 66fps max.
108
- sync: false, // true for combining
109
- from: 0.0,
110
- to: 1.0,
111
- delay: 0.0,
112
- queue: 'parallel'
113
- },
114
- tagifyText: function(element) {
115
- var tagifyStyle = 'position:relative';
116
- if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
117
-
118
- element = $(element);
119
- $A(element.childNodes).each( function(child) {
120
- if (child.nodeType==3) {
121
- child.nodeValue.toArray().each( function(character) {
122
- element.insertBefore(
123
- new Element('span', {style: tagifyStyle}).update(
124
- character == ' ' ? String.fromCharCode(160) : character),
125
- child);
126
- });
127
- Element.remove(child);
128
- }
129
- });
130
- },
131
- multiple: function(element, effect) {
132
- var elements;
133
- if (((typeof element == 'object') ||
134
- Object.isFunction(element)) &&
135
- (element.length))
136
- elements = element;
137
- else
138
- elements = $(element).childNodes;
139
-
140
- var options = Object.extend({
141
- speed: 0.1,
142
- delay: 0.0
143
- }, arguments[2] || { });
144
- var masterDelay = options.delay;
145
-
146
- $A(elements).each( function(element, index) {
147
- new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
148
- });
149
- },
150
- PAIRS: {
151
- 'slide': ['SlideDown','SlideUp'],
152
- 'blind': ['BlindDown','BlindUp'],
153
- 'appear': ['Appear','Fade']
154
- },
155
- toggle: function(element, effect) {
156
- element = $(element);
157
- effect = (effect || 'appear').toLowerCase();
158
- var options = Object.extend({
159
- queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
160
- }, arguments[2] || { });
161
- Effect[element.visible() ?
162
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
163
- }
164
- };
165
-
166
- Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
167
-
168
- /* ------------- core effects ------------- */
169
-
170
- Effect.ScopedQueue = Class.create(Enumerable, {
171
- initialize: function() {
172
- this.effects = [];
173
- this.interval = null;
174
- },
175
- _each: function(iterator) {
176
- this.effects._each(iterator);
177
- },
178
- add: function(effect) {
179
- var timestamp = new Date().getTime();
180
-
181
- var position = Object.isString(effect.options.queue) ?
182
- effect.options.queue : effect.options.queue.position;
183
-
184
- switch(position) {
185
- case 'front':
186
- // move unstarted effects after this effect
187
- this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
188
- e.startOn += effect.finishOn;
189
- e.finishOn += effect.finishOn;
190
- });
191
- break;
192
- case 'with-last':
193
- timestamp = this.effects.pluck('startOn').max() || timestamp;
194
- break;
195
- case 'end':
196
- // start effect after last queued effect has finished
197
- timestamp = this.effects.pluck('finishOn').max() || timestamp;
198
- break;
199
- }
200
-
201
- effect.startOn += timestamp;
202
- effect.finishOn += timestamp;
203
-
204
- if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
205
- this.effects.push(effect);
206
-
207
- if (!this.interval)
208
- this.interval = setInterval(this.loop.bind(this), 15);
209
- },
210
- remove: function(effect) {
211
- this.effects = this.effects.reject(function(e) { return e==effect });
212
- if (this.effects.length == 0) {
213
- clearInterval(this.interval);
214
- this.interval = null;
215
- }
216
- },
217
- loop: function() {
218
- var timePos = new Date().getTime();
219
- for(var i=0, len=this.effects.length;i<len;i++)
220
- this.effects[i] && this.effects[i].loop(timePos);
221
- }
222
- });
223
-
224
- Effect.Queues = {
225
- instances: $H(),
226
- get: function(queueName) {
227
- if (!Object.isString(queueName)) return queueName;
228
-
229
- return this.instances.get(queueName) ||
230
- this.instances.set(queueName, new Effect.ScopedQueue());
231
- }
232
- };
233
- Effect.Queue = Effect.Queues.get('global');
234
-
235
- Effect.Base = Class.create({
236
- position: null,
237
- start: function(options) {
238
- function codeForEvent(options,eventName){
239
- return (
240
- (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
241
- (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
242
- );
243
- }
244
- if (options && options.transition === false) options.transition = Effect.Transitions.linear;
245
- this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
246
- this.currentFrame = 0;
247
- this.state = 'idle';
248
- this.startOn = this.options.delay*1000;
249
- this.finishOn = this.startOn+(this.options.duration*1000);
250
- this.fromToDelta = this.options.to-this.options.from;
251
- this.totalTime = this.finishOn-this.startOn;
252
- this.totalFrames = this.options.fps*this.options.duration;
253
-
254
- eval('this.render = function(pos){ '+
255
- 'if (this.state=="idle"){this.state="running";'+
256
- codeForEvent(this.options,'beforeSetup')+
257
- (this.setup ? 'this.setup();':'')+
258
- codeForEvent(this.options,'afterSetup')+
259
- '};if (this.state=="running"){'+
260
- 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
261
- 'this.position=pos;'+
262
- codeForEvent(this.options,'beforeUpdate')+
263
- (this.update ? 'this.update(pos);':'')+
264
- codeForEvent(this.options,'afterUpdate')+
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
- max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
515
-
516
- if (options.offset) elementOffsets[1] += options.offset;
517
-
518
- return new Effect.Tween(null,
519
- scrollOffsets.top,
520
- elementOffsets[1] > max ? max : elementOffsets[1],
521
- options,
522
- function(p){ scrollTo(scrollOffsets.left, p.round()) }
523
- );
524
- };
525
-
526
- /* ------------- combination effects ------------- */
527
-
528
- Effect.Fade = function(element) {
529
- element = $(element);
530
- var oldOpacity = element.getInlineOpacity();
531
- var options = Object.extend({
532
- from: element.getOpacity() || 1.0,
533
- to: 0.0,
534
- afterFinishInternal: function(effect) {
535
- if (effect.options.to!=0) return;
536
- effect.element.hide().setStyle({opacity: oldOpacity});
537
- }
538
- }, arguments[1] || { });
539
- return new Effect.Opacity(element,options);
540
- };
541
-
542
- Effect.Appear = function(element) {
543
- element = $(element);
544
- var options = Object.extend({
545
- from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
546
- to: 1.0,
547
- // force Safari to render floated elements properly
548
- afterFinishInternal: function(effect) {
549
- effect.element.forceRerendering();
550
- },
551
- beforeSetup: function(effect) {
552
- effect.element.setOpacity(effect.options.from).show();
553
- }}, arguments[1] || { });
554
- return new Effect.Opacity(element,options);
555
- };
556
-
557
- Effect.Puff = function(element) {
558
- element = $(element);
559
- var oldStyle = {
560
- opacity: element.getInlineOpacity(),
561
- position: element.getStyle('position'),
562
- top: element.style.top,
563
- left: element.style.left,
564
- width: element.style.width,
565
- height: element.style.height
566
- };
567
- return new Effect.Parallel(
568
- [ new Effect.Scale(element, 200,
569
- { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
570
- new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
571
- Object.extend({ duration: 1.0,
572
- beforeSetupInternal: function(effect) {
573
- Position.absolutize(effect.effects[0].element)
574
- },
575
- afterFinishInternal: function(effect) {
576
- effect.effects[0].element.hide().setStyle(oldStyle); }
577
- }, arguments[1] || { })
578
- );
579
- };
580
-
581
- Effect.BlindUp = function(element) {
582
- element = $(element);
583
- element.makeClipping();
584
- return new Effect.Scale(element, 0,
585
- Object.extend({ scaleContent: false,
586
- scaleX: false,
587
- restoreAfterFinish: true,
588
- afterFinishInternal: function(effect) {
589
- effect.element.hide().undoClipping();
590
- }
591
- }, arguments[1] || { })
592
- );
593
- };
594
-
595
- Effect.BlindDown = function(element) {
596
- element = $(element);
597
- var elementDimensions = element.getDimensions();
598
- return new Effect.Scale(element, 100, Object.extend({
599
- scaleContent: false,
600
- scaleX: false,
601
- scaleFrom: 0,
602
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
603
- restoreAfterFinish: true,
604
- afterSetup: function(effect) {
605
- effect.element.makeClipping().setStyle({height: '0px'}).show();
606
- },
607
- afterFinishInternal: function(effect) {
608
- effect.element.undoClipping();
609
- }
610
- }, arguments[1] || { }));
611
- };
612
-
613
- Effect.SwitchOff = function(element) {
614
- element = $(element);
615
- var oldOpacity = element.getInlineOpacity();
616
- return new Effect.Appear(element, Object.extend({
617
- duration: 0.4,
618
- from: 0,
619
- transition: Effect.Transitions.flicker,
620
- afterFinishInternal: function(effect) {
621
- new Effect.Scale(effect.element, 1, {
622
- duration: 0.3, scaleFromCenter: true,
623
- scaleX: false, scaleContent: false, restoreAfterFinish: true,
624
- beforeSetup: function(effect) {
625
- effect.element.makePositioned().makeClipping();
626
- },
627
- afterFinishInternal: function(effect) {
628
- effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
629
- }
630
- })
631
- }
632
- }, arguments[1] || { }));
633
- };
634
-
635
- Effect.DropOut = function(element) {
636
- element = $(element);
637
- var oldStyle = {
638
- top: element.getStyle('top'),
639
- left: element.getStyle('left'),
640
- opacity: element.getInlineOpacity() };
641
- return new Effect.Parallel(
642
- [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
643
- new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
644
- Object.extend(
645
- { duration: 0.5,
646
- beforeSetup: function(effect) {
647
- effect.effects[0].element.makePositioned();
648
- },
649
- afterFinishInternal: function(effect) {
650
- effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
651
- }
652
- }, arguments[1] || { }));
653
- };
654
-
655
- Effect.Shake = function(element) {
656
- element = $(element);
657
- var options = Object.extend({
658
- distance: 20,
659
- duration: 0.5
660
- }, arguments[1] || {});
661
- var distance = parseFloat(options.distance);
662
- var split = parseFloat(options.duration) / 10.0;
663
- var oldStyle = {
664
- top: element.getStyle('top'),
665
- left: element.getStyle('left') };
666
- return new Effect.Move(element,
667
- { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
668
- new Effect.Move(effect.element,
669
- { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
670
- new Effect.Move(effect.element,
671
- { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
672
- new Effect.Move(effect.element,
673
- { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
674
- new Effect.Move(effect.element,
675
- { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
676
- new Effect.Move(effect.element,
677
- { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
678
- effect.element.undoPositioned().setStyle(oldStyle);
679
- }}) }}) }}) }}) }}) }});
680
- };
681
-
682
- Effect.SlideDown = function(element) {
683
- element = $(element).cleanWhitespace();
684
- // SlideDown need to have the content of the element wrapped in a container element with fixed height!
685
- var oldInnerBottom = element.down().getStyle('bottom');
686
- var elementDimensions = element.getDimensions();
687
- return new Effect.Scale(element, 100, Object.extend({
688
- scaleContent: false,
689
- scaleX: false,
690
- scaleFrom: window.opera ? 0 : 1,
691
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
692
- restoreAfterFinish: true,
693
- afterSetup: function(effect) {
694
- effect.element.makePositioned();
695
- effect.element.down().makePositioned();
696
- if (window.opera) effect.element.setStyle({top: ''});
697
- effect.element.makeClipping().setStyle({height: '0px'}).show();
698
- },
699
- afterUpdateInternal: function(effect) {
700
- effect.element.down().setStyle({bottom:
701
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
702
- },
703
- afterFinishInternal: function(effect) {
704
- effect.element.undoClipping().undoPositioned();
705
- effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
706
- }, arguments[1] || { })
707
- );
708
- };
709
-
710
- Effect.SlideUp = function(element) {
711
- element = $(element).cleanWhitespace();
712
- var oldInnerBottom = element.down().getStyle('bottom');
713
- var elementDimensions = element.getDimensions();
714
- return new Effect.Scale(element, window.opera ? 0 : 1,
715
- Object.extend({ scaleContent: false,
716
- scaleX: false,
717
- scaleMode: 'box',
718
- scaleFrom: 100,
719
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
720
- restoreAfterFinish: true,
721
- afterSetup: function(effect) {
722
- effect.element.makePositioned();
723
- effect.element.down().makePositioned();
724
- if (window.opera) effect.element.setStyle({top: ''});
725
- effect.element.makeClipping().show();
726
- },
727
- afterUpdateInternal: function(effect) {
728
- effect.element.down().setStyle({bottom:
729
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
730
- },
731
- afterFinishInternal: function(effect) {
732
- effect.element.hide().undoClipping().undoPositioned();
733
- effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
734
- }
735
- }, arguments[1] || { })
736
- );
737
- };
738
-
739
- // Bug in opera makes the TD containing this element expand for a instance after finish
740
- Effect.Squish = function(element) {
741
- return new Effect.Scale(element, window.opera ? 1 : 0, {
742
- restoreAfterFinish: true,
743
- beforeSetup: function(effect) {
744
- effect.element.makeClipping();
745
- },
746
- afterFinishInternal: function(effect) {
747
- effect.element.hide().undoClipping();
748
- }
749
- });
750
- };
751
-
752
- Effect.Grow = function(element) {
753
- element = $(element);
754
- var options = Object.extend({
755
- direction: 'center',
756
- moveTransition: Effect.Transitions.sinoidal,
757
- scaleTransition: Effect.Transitions.sinoidal,
758
- opacityTransition: Effect.Transitions.full
759
- }, arguments[1] || { });
760
- var oldStyle = {
761
- top: element.style.top,
762
- left: element.style.left,
763
- height: element.style.height,
764
- width: element.style.width,
765
- opacity: element.getInlineOpacity() };
766
-
767
- var dims = element.getDimensions();
768
- var initialMoveX, initialMoveY;
769
- var moveX, moveY;
770
-
771
- switch (options.direction) {
772
- case 'top-left':
773
- initialMoveX = initialMoveY = moveX = moveY = 0;
774
- break;
775
- case 'top-right':
776
- initialMoveX = dims.width;
777
- initialMoveY = moveY = 0;
778
- moveX = -dims.width;
779
- break;
780
- case 'bottom-left':
781
- initialMoveX = moveX = 0;
782
- initialMoveY = dims.height;
783
- moveY = -dims.height;
784
- break;
785
- case 'bottom-right':
786
- initialMoveX = dims.width;
787
- initialMoveY = dims.height;
788
- moveX = -dims.width;
789
- moveY = -dims.height;
790
- break;
791
- case 'center':
792
- initialMoveX = dims.width / 2;
793
- initialMoveY = dims.height / 2;
794
- moveX = -dims.width / 2;
795
- moveY = -dims.height / 2;
796
- break;
797
- }
798
-
799
- return new Effect.Move(element, {
800
- x: initialMoveX,
801
- y: initialMoveY,
802
- duration: 0.01,
803
- beforeSetup: function(effect) {
804
- effect.element.hide().makeClipping().makePositioned();
805
- },
806
- afterFinishInternal: function(effect) {
807
- new Effect.Parallel(
808
- [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
809
- new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
810
- new Effect.Scale(effect.element, 100, {
811
- scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
812
- sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
813
- ], Object.extend({
814
- beforeSetup: function(effect) {
815
- effect.effects[0].element.setStyle({height: '0px'}).show();
816
- },
817
- afterFinishInternal: function(effect) {
818
- effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
819
- }
820
- }, options)
821
- )
822
- }
823
- });
824
- };
825
-
826
- Effect.Shrink = function(element) {
827
- element = $(element);
828
- var options = Object.extend({
829
- direction: 'center',
830
- moveTransition: Effect.Transitions.sinoidal,
831
- scaleTransition: Effect.Transitions.sinoidal,
832
- opacityTransition: Effect.Transitions.none
833
- }, arguments[1] || { });
834
- var oldStyle = {
835
- top: element.style.top,
836
- left: element.style.left,
837
- height: element.style.height,
838
- width: element.style.width,
839
- opacity: element.getInlineOpacity() };
840
-
841
- var dims = element.getDimensions();
842
- var moveX, moveY;
843
-
844
- switch (options.direction) {
845
- case 'top-left':
846
- moveX = moveY = 0;
847
- break;
848
- case 'top-right':
849
- moveX = dims.width;
850
- moveY = 0;
851
- break;
852
- case 'bottom-left':
853
- moveX = 0;
854
- moveY = dims.height;
855
- break;
856
- case 'bottom-right':
857
- moveX = dims.width;
858
- moveY = dims.height;
859
- break;
860
- case 'center':
861
- moveX = dims.width / 2;
862
- moveY = dims.height / 2;
863
- break;
864
- }
865
-
866
- return new Effect.Parallel(
867
- [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
868
- new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
869
- new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
870
- ], Object.extend({
871
- beforeStartInternal: function(effect) {
872
- effect.effects[0].element.makePositioned().makeClipping();
873
- },
874
- afterFinishInternal: function(effect) {
875
- effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
876
- }, options)
877
- );
878
- };
879
-
880
- Effect.Pulsate = function(element) {
881
- element = $(element);
882
- var options = arguments[1] || { };
883
- var oldOpacity = element.getInlineOpacity();
884
- var transition = options.transition || Effect.Transitions.sinoidal;
885
- var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
886
- reverser.bind(transition);
887
- return new Effect.Opacity(element,
888
- Object.extend(Object.extend({ duration: 2.0, from: 0,
889
- afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
890
- }, options), {transition: reverser}));
891
- };
892
-
893
- Effect.Fold = function(element) {
894
- element = $(element);
895
- var oldStyle = {
896
- top: element.style.top,
897
- left: element.style.left,
898
- width: element.style.width,
899
- height: element.style.height };
900
- element.makeClipping();
901
- return new Effect.Scale(element, 5, Object.extend({
902
- scaleContent: false,
903
- scaleX: false,
904
- afterFinishInternal: function(effect) {
905
- new Effect.Scale(element, 1, {
906
- scaleContent: false,
907
- scaleY: false,
908
- afterFinishInternal: function(effect) {
909
- effect.element.hide().undoClipping().setStyle(oldStyle);
910
- } });
911
- }}, arguments[1] || { }));
912
- };
913
-
914
- Effect.Morph = Class.create(Effect.Base, {
915
- initialize: function(element) {
916
- this.element = $(element);
917
- if (!this.element) throw(Effect._elementDoesNotExistError);
918
- var options = Object.extend({
919
- style: { }
920
- }, arguments[1] || { });
921
-
922
- if (!Object.isString(options.style)) this.style = $H(options.style);
923
- else {
924
- if (options.style.include(':'))
925
- this.style = options.style.parseStyle();
926
- else {
927
- this.element.addClassName(options.style);
928
- this.style = $H(this.element.getStyles());
929
- this.element.removeClassName(options.style);
930
- var css = this.element.getStyles();
931
- this.style = this.style.reject(function(style) {
932
- return style.value == css[style.key];
933
- });
934
- options.afterFinishInternal = function(effect) {
935
- effect.element.addClassName(effect.options.style);
936
- effect.transforms.each(function(transform) {
937
- effect.element.style[transform.style] = '';
938
- });
939
- }
940
- }
941
- }
942
- this.start(options);
943
- },
944
-
945
- setup: function(){
946
- function parseColor(color){
947
- if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
948
- color = color.parseColor();
949
- return $R(0,2).map(function(i){
950
- return parseInt( color.slice(i*2+1,i*2+3), 16 )
951
- });
952
- }
953
- this.transforms = this.style.map(function(pair){
954
- var property = pair[0], value = pair[1], unit = null;
955
-
956
- if (value.parseColor('#zzzzzz') != '#zzzzzz') {
957
- value = value.parseColor();
958
- unit = 'color';
959
- } else if (property == 'opacity') {
960
- value = parseFloat(value);
961
- if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
962
- this.element.setStyle({zoom: 1});
963
- } else if (Element.CSS_LENGTH.test(value)) {
964
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
965
- value = parseFloat(components[1]);
966
- unit = (components.length == 3) ? components[2] : null;
967
- }
968
-
969
- var originalValue = this.element.getStyle(property);
970
- return {
971
- style: property.camelize(),
972
- originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
973
- targetValue: unit=='color' ? parseColor(value) : value,
974
- unit: unit
975
- };
976
- }.bind(this)).reject(function(transform){
977
- return (
978
- (transform.originalValue == transform.targetValue) ||
979
- (
980
- transform.unit != 'color' &&
981
- (isNaN(transform.originalValue) || isNaN(transform.targetValue))
982
- )
983
- )
984
- });
985
- },
986
- update: function(position) {
987
- var style = { }, transform, i = this.transforms.length;
988
- while(i--)
989
- style[(transform = this.transforms[i]).style] =
990
- transform.unit=='color' ? '#'+
991
- (Math.round(transform.originalValue[0]+
992
- (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
993
- (Math.round(transform.originalValue[1]+
994
- (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
995
- (Math.round(transform.originalValue[2]+
996
- (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
997
- (transform.originalValue +
998
- (transform.targetValue - transform.originalValue) * position).toFixed(3) +
999
- (transform.unit === null ? '' : transform.unit);
1000
- this.element.setStyle(style, true);
1001
- }
1002
- });
1003
-
1004
- Effect.Transform = Class.create({
1005
- initialize: function(tracks){
1006
- this.tracks = [];
1007
- this.options = arguments[1] || { };
1008
- this.addTracks(tracks);
1009
- },
1010
- addTracks: function(tracks){
1011
- tracks.each(function(track){
1012
- track = $H(track);
1013
- var data = track.values().first();
1014
- this.tracks.push($H({
1015
- ids: track.keys().first(),
1016
- effect: Effect.Morph,
1017
- options: { style: data }
1018
- }));
1019
- }.bind(this));
1020
- return this;
1021
- },
1022
- play: function(){
1023
- return new Effect.Parallel(
1024
- this.tracks.map(function(track){
1025
- var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1026
- var elements = [$(ids) || $$(ids)].flatten();
1027
- return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1028
- }).flatten(),
1029
- this.options
1030
- );
1031
- }
1032
- });
1033
-
1034
- Element.CSS_PROPERTIES = $w(
1035
- 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1036
- 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1037
- 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1038
- 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1039
- 'fontSize fontWeight height left letterSpacing lineHeight ' +
1040
- 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1041
- 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1042
- 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1043
- 'right textIndent top width wordSpacing zIndex');
1044
-
1045
- Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1046
-
1047
- String.__parseStyleElement = document.createElement('div');
1048
- String.prototype.parseStyle = function(){
1049
- var style, styleRules = $H();
1050
- if (Prototype.Browser.WebKit)
1051
- style = new Element('div',{style:this}).style;
1052
- else {
1053
- String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1054
- style = String.__parseStyleElement.childNodes[0].style;
1055
- }
1056
-
1057
- Element.CSS_PROPERTIES.each(function(property){
1058
- if (style[property]) styleRules.set(property, style[property]);
1059
- });
1060
-
1061
- if (Prototype.Browser.IE && this.include('opacity'))
1062
- styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1063
-
1064
- return styleRules;
1065
- };
1066
-
1067
- if (document.defaultView && document.defaultView.getComputedStyle) {
1068
- Element.getStyles = function(element) {
1069
- var css = document.defaultView.getComputedStyle($(element), null);
1070
- return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1071
- styles[property] = css[property];
1072
- return styles;
1073
- });
1074
- };
1075
- } else {
1076
- Element.getStyles = function(element) {
1077
- element = $(element);
1078
- var css = element.currentStyle, styles;
1079
- styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
1080
- results[property] = css[property];
1081
- return results;
1082
- });
1083
- if (!styles.opacity) styles.opacity = element.getOpacity();
1084
- return styles;
1085
- };
1086
- };
1087
-
1088
- Effect.Methods = {
1089
- morph: function(element, style) {
1090
- element = $(element);
1091
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1092
- return element;
1093
- },
1094
- visualEffect: function(element, effect, options) {
1095
- element = $(element)
1096
- var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1097
- new Effect[klass](element, options);
1098
- return element;
1099
- },
1100
- highlight: function(element, options) {
1101
- element = $(element);
1102
- new Effect.Highlight(element, options);
1103
- return element;
1104
- }
1105
- };
1106
-
1107
- $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1108
- 'pulsate shake puff squish switchOff dropOut').each(
1109
- function(effect) {
1110
- Effect.Methods[effect] = function(element, options){
1111
- element = $(element);
1112
- Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1113
- return element;
1114
- }
1115
- }
1116
- );
1117
-
1118
- $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1119
- function(f) { Effect.Methods[f] = Element[f]; }
1120
- );
1121
-
1122
- Element.addMethods(Effect.Methods);
1
+ // script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
+
3
+ // Copyright (c) 2005-2007 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) + 0.5;
76
+ },
77
+ reverse: function(pos) {
78
+ return 1-pos;
79
+ },
80
+ flicker: function(pos) {
81
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.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) + 0.5;
86
+ },
87
+ pulse: function(pos, pulses) {
88
+ pulses = pulses || 5;
89
+ return (
90
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
91
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
92
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
93
+ );
94
+ },
95
+ spring: function(pos) {
96
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
97
+ },
98
+ none: function(pos) {
99
+ return 0;
100
+ },
101
+ full: function(pos) {
102
+ return 1;
103
+ }
104
+ },
105
+ DefaultOptions: {
106
+ duration: 1.0, // seconds
107
+ fps: 100, // 100= assume 66fps max.
108
+ sync: false, // true for combining
109
+ from: 0.0,
110
+ to: 1.0,
111
+ delay: 0.0,
112
+ queue: 'parallel'
113
+ },
114
+ tagifyText: function(element) {
115
+ var tagifyStyle = 'position:relative';
116
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
117
+
118
+ element = $(element);
119
+ $A(element.childNodes).each( function(child) {
120
+ if (child.nodeType==3) {
121
+ child.nodeValue.toArray().each( function(character) {
122
+ element.insertBefore(
123
+ new Element('span', {style: tagifyStyle}).update(
124
+ character == ' ' ? String.fromCharCode(160) : character),
125
+ child);
126
+ });
127
+ Element.remove(child);
128
+ }
129
+ });
130
+ },
131
+ multiple: function(element, effect) {
132
+ var elements;
133
+ if (((typeof element == 'object') ||
134
+ Object.isFunction(element)) &&
135
+ (element.length))
136
+ elements = element;
137
+ else
138
+ elements = $(element).childNodes;
139
+
140
+ var options = Object.extend({
141
+ speed: 0.1,
142
+ delay: 0.0
143
+ }, arguments[2] || { });
144
+ var masterDelay = options.delay;
145
+
146
+ $A(elements).each( function(element, index) {
147
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
148
+ });
149
+ },
150
+ PAIRS: {
151
+ 'slide': ['SlideDown','SlideUp'],
152
+ 'blind': ['BlindDown','BlindUp'],
153
+ 'appear': ['Appear','Fade']
154
+ },
155
+ toggle: function(element, effect) {
156
+ element = $(element);
157
+ effect = (effect || 'appear').toLowerCase();
158
+ var options = Object.extend({
159
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
160
+ }, arguments[2] || { });
161
+ Effect[element.visible() ?
162
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
163
+ }
164
+ };
165
+
166
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
167
+
168
+ /* ------------- core effects ------------- */
169
+
170
+ Effect.ScopedQueue = Class.create(Enumerable, {
171
+ initialize: function() {
172
+ this.effects = [];
173
+ this.interval = null;
174
+ },
175
+ _each: function(iterator) {
176
+ this.effects._each(iterator);
177
+ },
178
+ add: function(effect) {
179
+ var timestamp = new Date().getTime();
180
+
181
+ var position = Object.isString(effect.options.queue) ?
182
+ effect.options.queue : effect.options.queue.position;
183
+
184
+ switch(position) {
185
+ case 'front':
186
+ // move unstarted effects after this effect
187
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
188
+ e.startOn += effect.finishOn;
189
+ e.finishOn += effect.finishOn;
190
+ });
191
+ break;
192
+ case 'with-last':
193
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
194
+ break;
195
+ case 'end':
196
+ // start effect after last queued effect has finished
197
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
198
+ break;
199
+ }
200
+
201
+ effect.startOn += timestamp;
202
+ effect.finishOn += timestamp;
203
+
204
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
205
+ this.effects.push(effect);
206
+
207
+ if (!this.interval)
208
+ this.interval = setInterval(this.loop.bind(this), 15);
209
+ },
210
+ remove: function(effect) {
211
+ this.effects = this.effects.reject(function(e) { return e==effect });
212
+ if (this.effects.length == 0) {
213
+ clearInterval(this.interval);
214
+ this.interval = null;
215
+ }
216
+ },
217
+ loop: function() {
218
+ var timePos = new Date().getTime();
219
+ for(var i=0, len=this.effects.length;i<len;i++)
220
+ this.effects[i] && this.effects[i].loop(timePos);
221
+ }
222
+ });
223
+
224
+ Effect.Queues = {
225
+ instances: $H(),
226
+ get: function(queueName) {
227
+ if (!Object.isString(queueName)) return queueName;
228
+
229
+ return this.instances.get(queueName) ||
230
+ this.instances.set(queueName, new Effect.ScopedQueue());
231
+ }
232
+ };
233
+ Effect.Queue = Effect.Queues.get('global');
234
+
235
+ Effect.Base = Class.create({
236
+ position: null,
237
+ start: function(options) {
238
+ function codeForEvent(options,eventName){
239
+ return (
240
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
241
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
242
+ );
243
+ }
244
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
245
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
246
+ this.currentFrame = 0;
247
+ this.state = 'idle';
248
+ this.startOn = this.options.delay*1000;
249
+ this.finishOn = this.startOn+(this.options.duration*1000);
250
+ this.fromToDelta = this.options.to-this.options.from;
251
+ this.totalTime = this.finishOn-this.startOn;
252
+ this.totalFrames = this.options.fps*this.options.duration;
253
+
254
+ eval('this.render = function(pos){ '+
255
+ 'if (this.state=="idle"){this.state="running";'+
256
+ codeForEvent(this.options,'beforeSetup')+
257
+ (this.setup ? 'this.setup();':'')+
258
+ codeForEvent(this.options,'afterSetup')+
259
+ '};if (this.state=="running"){'+
260
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
261
+ 'this.position=pos;'+
262
+ codeForEvent(this.options,'beforeUpdate')+
263
+ (this.update ? 'this.update(pos);':'')+
264
+ codeForEvent(this.options,'afterUpdate')+
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
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
515
+
516
+ if (options.offset) elementOffsets[1] += options.offset;
517
+
518
+ return new Effect.Tween(null,
519
+ scrollOffsets.top,
520
+ elementOffsets[1] > max ? max : elementOffsets[1],
521
+ options,
522
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
523
+ );
524
+ };
525
+
526
+ /* ------------- combination effects ------------- */
527
+
528
+ Effect.Fade = function(element) {
529
+ element = $(element);
530
+ var oldOpacity = element.getInlineOpacity();
531
+ var options = Object.extend({
532
+ from: element.getOpacity() || 1.0,
533
+ to: 0.0,
534
+ afterFinishInternal: function(effect) {
535
+ if (effect.options.to!=0) return;
536
+ effect.element.hide().setStyle({opacity: oldOpacity});
537
+ }
538
+ }, arguments[1] || { });
539
+ return new Effect.Opacity(element,options);
540
+ };
541
+
542
+ Effect.Appear = function(element) {
543
+ element = $(element);
544
+ var options = Object.extend({
545
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
546
+ to: 1.0,
547
+ // force Safari to render floated elements properly
548
+ afterFinishInternal: function(effect) {
549
+ effect.element.forceRerendering();
550
+ },
551
+ beforeSetup: function(effect) {
552
+ effect.element.setOpacity(effect.options.from).show();
553
+ }}, arguments[1] || { });
554
+ return new Effect.Opacity(element,options);
555
+ };
556
+
557
+ Effect.Puff = function(element) {
558
+ element = $(element);
559
+ var oldStyle = {
560
+ opacity: element.getInlineOpacity(),
561
+ position: element.getStyle('position'),
562
+ top: element.style.top,
563
+ left: element.style.left,
564
+ width: element.style.width,
565
+ height: element.style.height
566
+ };
567
+ return new Effect.Parallel(
568
+ [ new Effect.Scale(element, 200,
569
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
570
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
571
+ Object.extend({ duration: 1.0,
572
+ beforeSetupInternal: function(effect) {
573
+ Position.absolutize(effect.effects[0].element)
574
+ },
575
+ afterFinishInternal: function(effect) {
576
+ effect.effects[0].element.hide().setStyle(oldStyle); }
577
+ }, arguments[1] || { })
578
+ );
579
+ };
580
+
581
+ Effect.BlindUp = function(element) {
582
+ element = $(element);
583
+ element.makeClipping();
584
+ return new Effect.Scale(element, 0,
585
+ Object.extend({ scaleContent: false,
586
+ scaleX: false,
587
+ restoreAfterFinish: true,
588
+ afterFinishInternal: function(effect) {
589
+ effect.element.hide().undoClipping();
590
+ }
591
+ }, arguments[1] || { })
592
+ );
593
+ };
594
+
595
+ Effect.BlindDown = function(element) {
596
+ element = $(element);
597
+ var elementDimensions = element.getDimensions();
598
+ return new Effect.Scale(element, 100, Object.extend({
599
+ scaleContent: false,
600
+ scaleX: false,
601
+ scaleFrom: 0,
602
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
603
+ restoreAfterFinish: true,
604
+ afterSetup: function(effect) {
605
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
606
+ },
607
+ afterFinishInternal: function(effect) {
608
+ effect.element.undoClipping();
609
+ }
610
+ }, arguments[1] || { }));
611
+ };
612
+
613
+ Effect.SwitchOff = function(element) {
614
+ element = $(element);
615
+ var oldOpacity = element.getInlineOpacity();
616
+ return new Effect.Appear(element, Object.extend({
617
+ duration: 0.4,
618
+ from: 0,
619
+ transition: Effect.Transitions.flicker,
620
+ afterFinishInternal: function(effect) {
621
+ new Effect.Scale(effect.element, 1, {
622
+ duration: 0.3, scaleFromCenter: true,
623
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
624
+ beforeSetup: function(effect) {
625
+ effect.element.makePositioned().makeClipping();
626
+ },
627
+ afterFinishInternal: function(effect) {
628
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
629
+ }
630
+ })
631
+ }
632
+ }, arguments[1] || { }));
633
+ };
634
+
635
+ Effect.DropOut = function(element) {
636
+ element = $(element);
637
+ var oldStyle = {
638
+ top: element.getStyle('top'),
639
+ left: element.getStyle('left'),
640
+ opacity: element.getInlineOpacity() };
641
+ return new Effect.Parallel(
642
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
643
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
644
+ Object.extend(
645
+ { duration: 0.5,
646
+ beforeSetup: function(effect) {
647
+ effect.effects[0].element.makePositioned();
648
+ },
649
+ afterFinishInternal: function(effect) {
650
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
651
+ }
652
+ }, arguments[1] || { }));
653
+ };
654
+
655
+ Effect.Shake = function(element) {
656
+ element = $(element);
657
+ var options = Object.extend({
658
+ distance: 20,
659
+ duration: 0.5
660
+ }, arguments[1] || {});
661
+ var distance = parseFloat(options.distance);
662
+ var split = parseFloat(options.duration) / 10.0;
663
+ var oldStyle = {
664
+ top: element.getStyle('top'),
665
+ left: element.getStyle('left') };
666
+ return new Effect.Move(element,
667
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
668
+ new Effect.Move(effect.element,
669
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
670
+ new Effect.Move(effect.element,
671
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
672
+ new Effect.Move(effect.element,
673
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
674
+ new Effect.Move(effect.element,
675
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
676
+ new Effect.Move(effect.element,
677
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
678
+ effect.element.undoPositioned().setStyle(oldStyle);
679
+ }}) }}) }}) }}) }}) }});
680
+ };
681
+
682
+ Effect.SlideDown = function(element) {
683
+ element = $(element).cleanWhitespace();
684
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
685
+ var oldInnerBottom = element.down().getStyle('bottom');
686
+ var elementDimensions = element.getDimensions();
687
+ return new Effect.Scale(element, 100, Object.extend({
688
+ scaleContent: false,
689
+ scaleX: false,
690
+ scaleFrom: window.opera ? 0 : 1,
691
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
692
+ restoreAfterFinish: true,
693
+ afterSetup: function(effect) {
694
+ effect.element.makePositioned();
695
+ effect.element.down().makePositioned();
696
+ if (window.opera) effect.element.setStyle({top: ''});
697
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
698
+ },
699
+ afterUpdateInternal: function(effect) {
700
+ effect.element.down().setStyle({bottom:
701
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
702
+ },
703
+ afterFinishInternal: function(effect) {
704
+ effect.element.undoClipping().undoPositioned();
705
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
706
+ }, arguments[1] || { })
707
+ );
708
+ };
709
+
710
+ Effect.SlideUp = function(element) {
711
+ element = $(element).cleanWhitespace();
712
+ var oldInnerBottom = element.down().getStyle('bottom');
713
+ var elementDimensions = element.getDimensions();
714
+ return new Effect.Scale(element, window.opera ? 0 : 1,
715
+ Object.extend({ scaleContent: false,
716
+ scaleX: false,
717
+ scaleMode: 'box',
718
+ scaleFrom: 100,
719
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
720
+ restoreAfterFinish: true,
721
+ afterSetup: function(effect) {
722
+ effect.element.makePositioned();
723
+ effect.element.down().makePositioned();
724
+ if (window.opera) effect.element.setStyle({top: ''});
725
+ effect.element.makeClipping().show();
726
+ },
727
+ afterUpdateInternal: function(effect) {
728
+ effect.element.down().setStyle({bottom:
729
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
730
+ },
731
+ afterFinishInternal: function(effect) {
732
+ effect.element.hide().undoClipping().undoPositioned();
733
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
734
+ }
735
+ }, arguments[1] || { })
736
+ );
737
+ };
738
+
739
+ // Bug in opera makes the TD containing this element expand for a instance after finish
740
+ Effect.Squish = function(element) {
741
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
742
+ restoreAfterFinish: true,
743
+ beforeSetup: function(effect) {
744
+ effect.element.makeClipping();
745
+ },
746
+ afterFinishInternal: function(effect) {
747
+ effect.element.hide().undoClipping();
748
+ }
749
+ });
750
+ };
751
+
752
+ Effect.Grow = function(element) {
753
+ element = $(element);
754
+ var options = Object.extend({
755
+ direction: 'center',
756
+ moveTransition: Effect.Transitions.sinoidal,
757
+ scaleTransition: Effect.Transitions.sinoidal,
758
+ opacityTransition: Effect.Transitions.full
759
+ }, arguments[1] || { });
760
+ var oldStyle = {
761
+ top: element.style.top,
762
+ left: element.style.left,
763
+ height: element.style.height,
764
+ width: element.style.width,
765
+ opacity: element.getInlineOpacity() };
766
+
767
+ var dims = element.getDimensions();
768
+ var initialMoveX, initialMoveY;
769
+ var moveX, moveY;
770
+
771
+ switch (options.direction) {
772
+ case 'top-left':
773
+ initialMoveX = initialMoveY = moveX = moveY = 0;
774
+ break;
775
+ case 'top-right':
776
+ initialMoveX = dims.width;
777
+ initialMoveY = moveY = 0;
778
+ moveX = -dims.width;
779
+ break;
780
+ case 'bottom-left':
781
+ initialMoveX = moveX = 0;
782
+ initialMoveY = dims.height;
783
+ moveY = -dims.height;
784
+ break;
785
+ case 'bottom-right':
786
+ initialMoveX = dims.width;
787
+ initialMoveY = dims.height;
788
+ moveX = -dims.width;
789
+ moveY = -dims.height;
790
+ break;
791
+ case 'center':
792
+ initialMoveX = dims.width / 2;
793
+ initialMoveY = dims.height / 2;
794
+ moveX = -dims.width / 2;
795
+ moveY = -dims.height / 2;
796
+ break;
797
+ }
798
+
799
+ return new Effect.Move(element, {
800
+ x: initialMoveX,
801
+ y: initialMoveY,
802
+ duration: 0.01,
803
+ beforeSetup: function(effect) {
804
+ effect.element.hide().makeClipping().makePositioned();
805
+ },
806
+ afterFinishInternal: function(effect) {
807
+ new Effect.Parallel(
808
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
809
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
810
+ new Effect.Scale(effect.element, 100, {
811
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
812
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
813
+ ], Object.extend({
814
+ beforeSetup: function(effect) {
815
+ effect.effects[0].element.setStyle({height: '0px'}).show();
816
+ },
817
+ afterFinishInternal: function(effect) {
818
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
819
+ }
820
+ }, options)
821
+ )
822
+ }
823
+ });
824
+ };
825
+
826
+ Effect.Shrink = function(element) {
827
+ element = $(element);
828
+ var options = Object.extend({
829
+ direction: 'center',
830
+ moveTransition: Effect.Transitions.sinoidal,
831
+ scaleTransition: Effect.Transitions.sinoidal,
832
+ opacityTransition: Effect.Transitions.none
833
+ }, arguments[1] || { });
834
+ var oldStyle = {
835
+ top: element.style.top,
836
+ left: element.style.left,
837
+ height: element.style.height,
838
+ width: element.style.width,
839
+ opacity: element.getInlineOpacity() };
840
+
841
+ var dims = element.getDimensions();
842
+ var moveX, moveY;
843
+
844
+ switch (options.direction) {
845
+ case 'top-left':
846
+ moveX = moveY = 0;
847
+ break;
848
+ case 'top-right':
849
+ moveX = dims.width;
850
+ moveY = 0;
851
+ break;
852
+ case 'bottom-left':
853
+ moveX = 0;
854
+ moveY = dims.height;
855
+ break;
856
+ case 'bottom-right':
857
+ moveX = dims.width;
858
+ moveY = dims.height;
859
+ break;
860
+ case 'center':
861
+ moveX = dims.width / 2;
862
+ moveY = dims.height / 2;
863
+ break;
864
+ }
865
+
866
+ return new Effect.Parallel(
867
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
868
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
869
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
870
+ ], Object.extend({
871
+ beforeStartInternal: function(effect) {
872
+ effect.effects[0].element.makePositioned().makeClipping();
873
+ },
874
+ afterFinishInternal: function(effect) {
875
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
876
+ }, options)
877
+ );
878
+ };
879
+
880
+ Effect.Pulsate = function(element) {
881
+ element = $(element);
882
+ var options = arguments[1] || { };
883
+ var oldOpacity = element.getInlineOpacity();
884
+ var transition = options.transition || Effect.Transitions.sinoidal;
885
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
886
+ reverser.bind(transition);
887
+ return new Effect.Opacity(element,
888
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
889
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
890
+ }, options), {transition: reverser}));
891
+ };
892
+
893
+ Effect.Fold = function(element) {
894
+ element = $(element);
895
+ var oldStyle = {
896
+ top: element.style.top,
897
+ left: element.style.left,
898
+ width: element.style.width,
899
+ height: element.style.height };
900
+ element.makeClipping();
901
+ return new Effect.Scale(element, 5, Object.extend({
902
+ scaleContent: false,
903
+ scaleX: false,
904
+ afterFinishInternal: function(effect) {
905
+ new Effect.Scale(element, 1, {
906
+ scaleContent: false,
907
+ scaleY: false,
908
+ afterFinishInternal: function(effect) {
909
+ effect.element.hide().undoClipping().setStyle(oldStyle);
910
+ } });
911
+ }}, arguments[1] || { }));
912
+ };
913
+
914
+ Effect.Morph = Class.create(Effect.Base, {
915
+ initialize: function(element) {
916
+ this.element = $(element);
917
+ if (!this.element) throw(Effect._elementDoesNotExistError);
918
+ var options = Object.extend({
919
+ style: { }
920
+ }, arguments[1] || { });
921
+
922
+ if (!Object.isString(options.style)) this.style = $H(options.style);
923
+ else {
924
+ if (options.style.include(':'))
925
+ this.style = options.style.parseStyle();
926
+ else {
927
+ this.element.addClassName(options.style);
928
+ this.style = $H(this.element.getStyles());
929
+ this.element.removeClassName(options.style);
930
+ var css = this.element.getStyles();
931
+ this.style = this.style.reject(function(style) {
932
+ return style.value == css[style.key];
933
+ });
934
+ options.afterFinishInternal = function(effect) {
935
+ effect.element.addClassName(effect.options.style);
936
+ effect.transforms.each(function(transform) {
937
+ effect.element.style[transform.style] = '';
938
+ });
939
+ }
940
+ }
941
+ }
942
+ this.start(options);
943
+ },
944
+
945
+ setup: function(){
946
+ function parseColor(color){
947
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
948
+ color = color.parseColor();
949
+ return $R(0,2).map(function(i){
950
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
951
+ });
952
+ }
953
+ this.transforms = this.style.map(function(pair){
954
+ var property = pair[0], value = pair[1], unit = null;
955
+
956
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
957
+ value = value.parseColor();
958
+ unit = 'color';
959
+ } else if (property == 'opacity') {
960
+ value = parseFloat(value);
961
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
962
+ this.element.setStyle({zoom: 1});
963
+ } else if (Element.CSS_LENGTH.test(value)) {
964
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
965
+ value = parseFloat(components[1]);
966
+ unit = (components.length == 3) ? components[2] : null;
967
+ }
968
+
969
+ var originalValue = this.element.getStyle(property);
970
+ return {
971
+ style: property.camelize(),
972
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
973
+ targetValue: unit=='color' ? parseColor(value) : value,
974
+ unit: unit
975
+ };
976
+ }.bind(this)).reject(function(transform){
977
+ return (
978
+ (transform.originalValue == transform.targetValue) ||
979
+ (
980
+ transform.unit != 'color' &&
981
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
982
+ )
983
+ )
984
+ });
985
+ },
986
+ update: function(position) {
987
+ var style = { }, transform, i = this.transforms.length;
988
+ while(i--)
989
+ style[(transform = this.transforms[i]).style] =
990
+ transform.unit=='color' ? '#'+
991
+ (Math.round(transform.originalValue[0]+
992
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
993
+ (Math.round(transform.originalValue[1]+
994
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
995
+ (Math.round(transform.originalValue[2]+
996
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
997
+ (transform.originalValue +
998
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
999
+ (transform.unit === null ? '' : transform.unit);
1000
+ this.element.setStyle(style, true);
1001
+ }
1002
+ });
1003
+
1004
+ Effect.Transform = Class.create({
1005
+ initialize: function(tracks){
1006
+ this.tracks = [];
1007
+ this.options = arguments[1] || { };
1008
+ this.addTracks(tracks);
1009
+ },
1010
+ addTracks: function(tracks){
1011
+ tracks.each(function(track){
1012
+ track = $H(track);
1013
+ var data = track.values().first();
1014
+ this.tracks.push($H({
1015
+ ids: track.keys().first(),
1016
+ effect: Effect.Morph,
1017
+ options: { style: data }
1018
+ }));
1019
+ }.bind(this));
1020
+ return this;
1021
+ },
1022
+ play: function(){
1023
+ return new Effect.Parallel(
1024
+ this.tracks.map(function(track){
1025
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1026
+ var elements = [$(ids) || $$(ids)].flatten();
1027
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1028
+ }).flatten(),
1029
+ this.options
1030
+ );
1031
+ }
1032
+ });
1033
+
1034
+ Element.CSS_PROPERTIES = $w(
1035
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1036
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1037
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1038
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1039
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1040
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1041
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1042
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1043
+ 'right textIndent top width wordSpacing zIndex');
1044
+
1045
+ Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1046
+
1047
+ String.__parseStyleElement = document.createElement('div');
1048
+ String.prototype.parseStyle = function(){
1049
+ var style, styleRules = $H();
1050
+ if (Prototype.Browser.WebKit)
1051
+ style = new Element('div',{style:this}).style;
1052
+ else {
1053
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1054
+ style = String.__parseStyleElement.childNodes[0].style;
1055
+ }
1056
+
1057
+ Element.CSS_PROPERTIES.each(function(property){
1058
+ if (style[property]) styleRules.set(property, style[property]);
1059
+ });
1060
+
1061
+ if (Prototype.Browser.IE && this.include('opacity'))
1062
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1063
+
1064
+ return styleRules;
1065
+ };
1066
+
1067
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1068
+ Element.getStyles = function(element) {
1069
+ var css = document.defaultView.getComputedStyle($(element), null);
1070
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1071
+ styles[property] = css[property];
1072
+ return styles;
1073
+ });
1074
+ };
1075
+ } else {
1076
+ Element.getStyles = function(element) {
1077
+ element = $(element);
1078
+ var css = element.currentStyle, styles;
1079
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
1080
+ results[property] = css[property];
1081
+ return results;
1082
+ });
1083
+ if (!styles.opacity) styles.opacity = element.getOpacity();
1084
+ return styles;
1085
+ };
1086
+ };
1087
+
1088
+ Effect.Methods = {
1089
+ morph: function(element, style) {
1090
+ element = $(element);
1091
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1092
+ return element;
1093
+ },
1094
+ visualEffect: function(element, effect, options) {
1095
+ element = $(element)
1096
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1097
+ new Effect[klass](element, options);
1098
+ return element;
1099
+ },
1100
+ highlight: function(element, options) {
1101
+ element = $(element);
1102
+ new Effect.Highlight(element, options);
1103
+ return element;
1104
+ }
1105
+ };
1106
+
1107
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1108
+ 'pulsate shake puff squish switchOff dropOut').each(
1109
+ function(effect) {
1110
+ Effect.Methods[effect] = function(element, options){
1111
+ element = $(element);
1112
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1113
+ return element;
1114
+ }
1115
+ }
1116
+ );
1117
+
1118
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1119
+ function(f) { Effect.Methods[f] = Element[f]; }
1120
+ );
1121
+
1122
+ Element.addMethods(Effect.Methods);
js/lanot/lightbox2/js/lightbox.js CHANGED
@@ -1,497 +1,497 @@
1
- // -----------------------------------------------------------------------------------
2
- //
3
- // Lightbox v2.04
4
- // by Lokesh Dhakar - http://www.lokeshdhakar.com
5
- // Last Modification: 2/9/08
6
- //
7
- // For more information, visit:
8
- // http://lokeshdhakar.com/projects/lightbox2/
9
- //
10
- // Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
11
- // - Free for use in both personal and commercial projects
12
- // - Attribution requires leaving author name, author link, and the license info intact.
13
- //
14
- // Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
15
- // Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
16
- //
17
- // -----------------------------------------------------------------------------------
18
- /*
19
-
20
- Table of Contents
21
- -----------------
22
- Configuration
23
-
24
- Lightbox Class Declaration
25
- - initialize()
26
- - updateImageList()
27
- - start()
28
- - changeImage()
29
- - resizeImageContainer()
30
- - showImage()
31
- - updateDetails()
32
- - updateNav()
33
- - enableKeyboardNav()
34
- - disableKeyboardNav()
35
- - keyboardAction()
36
- - preloadNeighborImages()
37
- - end()
38
-
39
- Function Calls
40
- - document.observe()
41
-
42
- */
43
- // -----------------------------------------------------------------------------------
44
-
45
- //
46
- // Configurationl
47
- //
48
- LightboxOptions = Object.extend({
49
- fileLoadingImage: 'images/loading.gif',
50
- fileBottomNavCloseImage: 'images/closelabel.gif',
51
-
52
- overlayOpacity: 0.8, // controls transparency of shadow overlay
53
-
54
- animate: true, // toggles resizing animations
55
- resizeSpeed: 7, // controls the speed of the image resizing animations (1=slowest and 10=fastest)
56
-
57
- borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable
58
-
59
- // When grouping images this is used to write: Image # of #.
60
- // Change it for non-english localization
61
- labelImage: "Image",
62
- labelOf: "of"
63
- }, window.LightboxOptions || {});
64
-
65
- // -----------------------------------------------------------------------------------
66
-
67
- var Lightbox = Class.create();
68
-
69
- Lightbox.prototype = {
70
- imageArray: [],
71
- activeImage: undefined,
72
-
73
- // initialize()
74
- // Constructor runs on completion of the DOM loading. Calls updateImageList and then
75
- // the function inserts html at the bottom of the page which is used to display the shadow
76
- // overlay and the image container.
77
- //
78
- initialize: function() {
79
-
80
- this.updateImageList();
81
-
82
- this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
83
-
84
- if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
85
- if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
86
-
87
- this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
88
- this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration
89
-
90
- // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
91
- // If animations are turned off, it will be hidden as to prevent a flicker of a
92
- // white 250 by 250 box.
93
- var size = (LightboxOptions.animate ? 250 : 1) + 'px';
94
-
95
-
96
- // Code inserts html at the bottom of the page that looks similar to this:
97
- //
98
- // <div id="overlay"></div>
99
- // <div id="lightbox">
100
- // <div id="outerImageContainer">
101
- // <div id="imageContainer">
102
- // <img id="lightboxImage">
103
- // <div style="" id="hoverNav">
104
- // <a href="#" id="prevLink"></a>
105
- // <a href="#" id="nextLink"></a>
106
- // </div>
107
- // <div id="loading">
108
- // <a href="#" id="loadingLink">
109
- // <img src="images/loading.gif">
110
- // </a>
111
- // </div>
112
- // </div>
113
- // </div>
114
- // <div id="imageDataContainer">
115
- // <div id="imageData">
116
- // <div id="imageDetails">
117
- // <span id="caption"></span>
118
- // <span id="numberDisplay"></span>
119
- // </div>
120
- // <div id="bottomNav">
121
- // <a href="#" id="bottomNavClose">
122
- // <img src="images/close.gif">
123
- // </a>
124
- // </div>
125
- // </div>
126
- // </div>
127
- // </div>
128
-
129
-
130
- var objBody = $$('body')[0];
131
-
132
- objBody.appendChild(Builder.node('div',{id:'overlay'}));
133
-
134
- objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
135
- Builder.node('div',{id:'outerImageContainer'},
136
- Builder.node('div',{id:'imageContainer'}, [
137
- Builder.node('img',{id:'lightboxImage'}),
138
- Builder.node('div',{id:'hoverNav'}, [
139
- Builder.node('a',{id:'prevLink', href: '#' }),
140
- Builder.node('a',{id:'nextLink', href: '#' })
141
- ]),
142
- Builder.node('div',{id:'loading'},
143
- Builder.node('a',{id:'loadingLink', href: '#' },
144
- Builder.node('img', {src: LightboxOptions.fileLoadingImage})
145
- )
146
- )
147
- ])
148
- ),
149
- Builder.node('div', {id:'imageDataContainer'},
150
- Builder.node('div',{id:'imageData'}, [
151
- Builder.node('div',{id:'imageDetails'}, [
152
- Builder.node('span',{id:'caption'}),
153
- Builder.node('span',{id:'numberDisplay'})
154
- ]),
155
- Builder.node('div',{id:'bottomNav'},
156
- Builder.node('a',{id:'bottomNavClose', href: '#' },
157
- Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
158
- )
159
- )
160
- ])
161
- )
162
- ]));
163
-
164
-
165
- $('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
166
- $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
167
- $('outerImageContainer').setStyle({ width: size, height: size });
168
- $('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
169
- $('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
170
- $('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
171
- $('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
172
-
173
- var th = this;
174
- (function(){
175
- var ids =
176
- 'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
177
- 'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
178
- $w(ids).each(function(id){ th[id] = $(id); });
179
- }).defer();
180
- },
181
-
182
- //
183
- // updateImageList()
184
- // Loops through anchor tags looking for 'lightbox' references and applies onclick
185
- // events to appropriate links. You can rerun after dynamically adding images w/ajax.
186
- //
187
- updateImageList: function() {
188
- this.updateImageList = Prototype.emptyFunction;
189
-
190
- document.observe('click', (function(event){
191
- var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
192
- if (target) {
193
- event.stop();
194
- this.start(target);
195
- }
196
- }).bind(this));
197
- },
198
-
199
- //
200
- // start()
201
- // Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
202
- //
203
- start: function(imageLink) {
204
-
205
- $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
206
-
207
- // stretch overlay to fill page and fade in
208
- var arrayPageSize = this.getPageSize();
209
- $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });
210
-
211
- new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
212
-
213
- this.imageArray = [];
214
- var imageNum = 0;
215
-
216
- if ((imageLink.rel == 'lightbox')){
217
- // if image is NOT part of a set, add single image to imageArray
218
- this.imageArray.push([imageLink.href, imageLink.title]);
219
- } else {
220
- // if image is part of a set..
221
- this.imageArray =
222
- $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
223
- collect(function(anchor){ return [anchor.href, anchor.title]; }).
224
- uniq();
225
-
226
- while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
227
- }
228
-
229
- // calculate top and left offset for the lightbox
230
- var arrayPageScroll = document.viewport.getScrollOffsets();
231
- var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
232
- var lightboxLeft = arrayPageScroll[0];
233
- this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
234
-
235
- this.changeImage(imageNum);
236
- },
237
-
238
- //
239
- // changeImage()
240
- // Hide most elements and preload image in preparation for resizing image container.
241
- //
242
- changeImage: function(imageNum) {
243
-
244
- this.activeImage = imageNum; // update global var
245
-
246
- // hide elements during transition
247
- if (LightboxOptions.animate) this.loading.show();
248
- this.lightboxImage.hide();
249
- this.hoverNav.hide();
250
- this.prevLink.hide();
251
- this.nextLink.hide();
252
- // HACK: Opera9 does not currently support scriptaculous opacity and appear fx
253
- this.imageDataContainer.setStyle({opacity: .0001});
254
- this.numberDisplay.hide();
255
-
256
- var imgPreloader = new Image();
257
-
258
- // once image is preloaded, resize image container
259
-
260
-
261
- imgPreloader.onload = (function(){
262
- this.lightboxImage.src = this.imageArray[this.activeImage][0];
263
- this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
264
- }).bind(this);
265
- imgPreloader.src = this.imageArray[this.activeImage][0];
266
- },
267
-
268
- //
269
- // resizeImageContainer()
270
- //
271
- resizeImageContainer: function(imgWidth, imgHeight) {
272
-
273
- // get current width and height
274
- var widthCurrent = this.outerImageContainer.getWidth();
275
- var heightCurrent = this.outerImageContainer.getHeight();
276
-
277
- // get new width and height
278
- var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
279
- var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
280
-
281
- // scalars based on change from old to new
282
- var xScale = (widthNew / widthCurrent) * 100;
283
- var yScale = (heightNew / heightCurrent) * 100;
284
-
285
- // calculate size difference between new and old image, and resize if necessary
286
- var wDiff = widthCurrent - widthNew;
287
- var hDiff = heightCurrent - heightNew;
288
-
289
- if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
290
- if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});
291
-
292
- // if new and old image are same size and no scaling transition is necessary,
293
- // do a quick pause to prevent image flicker.
294
- var timeout = 0;
295
- if ((hDiff == 0) && (wDiff == 0)){
296
- timeout = 100;
297
- if (Prototype.Browser.IE) timeout = 250;
298
- }
299
-
300
- (function(){
301
- this.prevLink.setStyle({ height: imgHeight + 'px' });
302
- this.nextLink.setStyle({ height: imgHeight + 'px' });
303
- this.imageDataContainer.setStyle({ width: widthNew + 'px' });
304
-
305
- this.showImage();
306
- }).bind(this).delay(timeout / 1000);
307
- },
308
-
309
- //
310
- // showImage()
311
- // Display image and begin preloading neighbors.
312
- //
313
- showImage: function(){
314
- this.loading.hide();
315
- new Effect.Appear(this.lightboxImage, {
316
- duration: this.resizeDuration,
317
- queue: 'end',
318
- afterFinish: (function(){ this.updateDetails(); }).bind(this)
319
- });
320
- this.preloadNeighborImages();
321
- },
322
-
323
- //
324
- // updateDetails()
325
- // Display caption, image number, and bottom nav.
326
- //
327
- updateDetails: function() {
328
-
329
- // if caption is not null
330
- if (this.imageArray[this.activeImage][1] != ""){
331
- this.caption.update(this.imageArray[this.activeImage][1]).show();
332
- }
333
-
334
- // if image is part of set display 'Image x of x'
335
- if (this.imageArray.length > 1){
336
- this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show();
337
- }
338
-
339
- new Effect.Parallel(
340
- [
341
- new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
342
- new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
343
- ],
344
- {
345
- duration: this.resizeDuration,
346
- afterFinish: (function() {
347
- // update overlay size and update nav
348
- var arrayPageSize = this.getPageSize();
349
- this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
350
- this.updateNav();
351
- }).bind(this)
352
- }
353
- );
354
- },
355
-
356
- //
357
- // updateNav()
358
- // Display appropriate previous and next hover navigation.
359
- //
360
- updateNav: function() {
361
-
362
- this.hoverNav.show();
363
-
364
- // if not first image in set, display prev image button
365
- if (this.activeImage > 0) this.prevLink.show();
366
-
367
- // if not last image in set, display next image button
368
- if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
369
-
370
- this.enableKeyboardNav();
371
- },
372
-
373
- //
374
- // enableKeyboardNav()
375
- //
376
- enableKeyboardNav: function() {
377
- document.observe('keydown', this.keyboardAction);
378
- },
379
-
380
- //
381
- // disableKeyboardNav()
382
- //
383
- disableKeyboardNav: function() {
384
- document.stopObserving('keydown', this.keyboardAction);
385
- },
386
-
387
- //
388
- // keyboardAction()
389
- //
390
- keyboardAction: function(event) {
391
- var keycode = event.keyCode;
392
-
393
- var escapeKey;
394
- if (event.DOM_VK_ESCAPE) { // mozilla
395
- escapeKey = event.DOM_VK_ESCAPE;
396
- } else { // ie
397
- escapeKey = 27;
398
- }
399
-
400
- var key = String.fromCharCode(keycode).toLowerCase();
401
-
402
- if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
403
- this.end();
404
- } else if ((key == 'p') || (keycode == 37)){ // display previous image
405
- if (this.activeImage != 0){
406
- this.disableKeyboardNav();
407
- this.changeImage(this.activeImage - 1);
408
- }
409
- } else if ((key == 'n') || (keycode == 39)){ // display next image
410
- if (this.activeImage != (this.imageArray.length - 1)){
411
- this.disableKeyboardNav();
412
- this.changeImage(this.activeImage + 1);
413
- }
414
- }
415
- },
416
-
417
- //
418
- // preloadNeighborImages()
419
- // Preload previous and next images.
420
- //
421
- preloadNeighborImages: function(){
422
- var preloadNextImage, preloadPrevImage;
423
- if (this.imageArray.length > this.activeImage + 1){
424
- preloadNextImage = new Image();
425
- preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
426
- }
427
- if (this.activeImage > 0){
428
- preloadPrevImage = new Image();
429
- preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
430
- }
431
-
432
- },
433
-
434
- //
435
- // end()
436
- //
437
- end: function() {
438
- this.disableKeyboardNav();
439
- this.lightbox.hide();
440
- new Effect.Fade(this.overlay, { duration: this.overlayDuration });
441
- $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
442
- },
443
-
444
- //
445
- // getPageSize()
446
- //
447
- getPageSize: function() {
448
-
449
- var xScroll, yScroll;
450
-
451
- if (window.innerHeight && window.scrollMaxY) {
452
- xScroll = window.innerWidth + window.scrollMaxX;
453
- yScroll = window.innerHeight + window.scrollMaxY;
454
- } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
455
- xScroll = document.body.scrollWidth;
456
- yScroll = document.body.scrollHeight;
457
- } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
458
- xScroll = document.body.offsetWidth;
459
- yScroll = document.body.offsetHeight;
460
- }
461
-
462
- var windowWidth, windowHeight;
463
-
464
- if (self.innerHeight) { // all except Explorer
465
- if(document.documentElement.clientWidth){
466
- windowWidth = document.documentElement.clientWidth;
467
- } else {
468
- windowWidth = self.innerWidth;
469
- }
470
- windowHeight = self.innerHeight;
471
- } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
472
- windowWidth = document.documentElement.clientWidth;
473
- windowHeight = document.documentElement.clientHeight;
474
- } else if (document.body) { // other Explorers
475
- windowWidth = document.body.clientWidth;
476
- windowHeight = document.body.clientHeight;
477
- }
478
-
479
- // for small pages with total height less then height of the viewport
480
- if(yScroll < windowHeight){
481
- pageHeight = windowHeight;
482
- } else {
483
- pageHeight = yScroll;
484
- }
485
-
486
- // for small pages with total width less then width of the viewport
487
- if(xScroll < windowWidth){
488
- pageWidth = xScroll;
489
- } else {
490
- pageWidth = windowWidth;
491
- }
492
-
493
- return [pageWidth,pageHeight];
494
- }
495
- }
496
-
497
  document.observe('dom:loaded', function () { new Lightbox(); });
1
+ // -----------------------------------------------------------------------------------
2
+ //
3
+ // Lightbox v2.04
4
+ // by Lokesh Dhakar - http://www.lokeshdhakar.com
5
+ // Last Modification: 2/9/08
6
+ //
7
+ // For more information, visit:
8
+ // http://lokeshdhakar.com/projects/lightbox2/
9
+ //
10
+ // Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
11
+ // - Free for use in both personal and commercial projects
12
+ // - Attribution requires leaving author name, author link, and the license info intact.
13
+ //
14
+ // Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
15
+ // Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
16
+ //
17
+ // -----------------------------------------------------------------------------------
18
+ /*
19
+
20
+ Table of Contents
21
+ -----------------
22
+ Configuration
23
+
24
+ Lightbox Class Declaration
25
+ - initialize()
26
+ - updateImageList()
27
+ - start()
28
+ - changeImage()
29
+ - resizeImageContainer()
30
+ - showImage()
31
+ - updateDetails()
32
+ - updateNav()
33
+ - enableKeyboardNav()
34
+ - disableKeyboardNav()
35
+ - keyboardAction()
36
+ - preloadNeighborImages()
37
+ - end()
38
+
39
+ Function Calls
40
+ - document.observe()
41
+
42
+ */
43
+ // -----------------------------------------------------------------------------------
44
+
45
+ //
46
+ // Configurationl
47
+ //
48
+ LightboxOptions = Object.extend({
49
+ fileLoadingImage: 'images/loading.gif',
50
+ fileBottomNavCloseImage: 'images/closelabel.gif',
51
+
52
+ overlayOpacity: 0.8, // controls transparency of shadow overlay
53
+
54
+ animate: true, // toggles resizing animations
55
+ resizeSpeed: 7, // controls the speed of the image resizing animations (1=slowest and 10=fastest)
56
+
57
+ borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable
58
+
59
+ // When grouping images this is used to write: Image # of #.
60
+ // Change it for non-english localization
61
+ labelImage: "Image",
62
+ labelOf: "of"
63
+ }, window.LightboxOptions || {});
64
+
65
+ // -----------------------------------------------------------------------------------
66
+
67
+ var Lightbox = Class.create();
68
+
69
+ Lightbox.prototype = {
70
+ imageArray: [],
71
+ activeImage: undefined,
72
+
73
+ // initialize()
74
+ // Constructor runs on completion of the DOM loading. Calls updateImageList and then
75
+ // the function inserts html at the bottom of the page which is used to display the shadow
76
+ // overlay and the image container.
77
+ //
78
+ initialize: function() {
79
+
80
+ this.updateImageList();
81
+
82
+ this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
83
+
84
+ if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
85
+ if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
86
+
87
+ this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
88
+ this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration
89
+
90
+ // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
91
+ // If animations are turned off, it will be hidden as to prevent a flicker of a
92
+ // white 250 by 250 box.
93
+ var size = (LightboxOptions.animate ? 250 : 1) + 'px';
94
+
95
+
96
+ // Code inserts html at the bottom of the page that looks similar to this:
97
+ //
98
+ // <div id="overlay"></div>
99
+ // <div id="lightbox">
100
+ // <div id="outerImageContainer">
101
+ // <div id="imageContainer">
102
+ // <img id="lightboxImage">
103
+ // <div style="" id="hoverNav">
104
+ // <a href="#" id="prevLink"></a>
105
+ // <a href="#" id="nextLink"></a>
106
+ // </div>
107
+ // <div id="loading">
108
+ // <a href="#" id="loadingLink">
109
+ // <img src="images/loading.gif">
110
+ // </a>
111
+ // </div>
112
+ // </div>
113
+ // </div>
114
+ // <div id="imageDataContainer">
115
+ // <div id="imageData">
116
+ // <div id="imageDetails">
117
+ // <span id="caption"></span>
118
+ // <span id="numberDisplay"></span>
119
+ // </div>
120
+ // <div id="bottomNav">
121
+ // <a href="#" id="bottomNavClose">
122
+ // <img src="images/close.gif">
123
+ // </a>
124
+ // </div>
125
+ // </div>
126
+ // </div>
127
+ // </div>
128
+
129
+
130
+ var objBody = $$('body')[0];
131
+
132
+ objBody.appendChild(Builder.node('div',{id:'overlay'}));
133
+
134
+ objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
135
+ Builder.node('div',{id:'outerImageContainer'},
136
+ Builder.node('div',{id:'imageContainer'}, [
137
+ Builder.node('img',{id:'lightboxImage'}),
138
+ Builder.node('div',{id:'hoverNav'}, [
139
+ Builder.node('a',{id:'prevLink', href: '#' }),
140
+ Builder.node('a',{id:'nextLink', href: '#' })
141
+ ]),
142
+ Builder.node('div',{id:'loading'},
143
+ Builder.node('a',{id:'loadingLink', href: '#' },
144
+ Builder.node('img', {src: LightboxOptions.fileLoadingImage})
145
+ )
146
+ )
147
+ ])
148
+ ),
149
+ Builder.node('div', {id:'imageDataContainer'},
150
+ Builder.node('div',{id:'imageData'}, [
151
+ Builder.node('div',{id:'imageDetails'}, [
152
+ Builder.node('span',{id:'caption'}),
153
+ Builder.node('span',{id:'numberDisplay'})
154
+ ]),
155
+ Builder.node('div',{id:'bottomNav'},
156
+ Builder.node('a',{id:'bottomNavClose', href: '#' },
157
+ Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
158
+ )
159
+ )
160
+ ])
161
+ )
162
+ ]));
163
+
164
+
165
+ $('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
166
+ $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
167
+ $('outerImageContainer').setStyle({ width: size, height: size });
168
+ $('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
169
+ $('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
170
+ $('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
171
+ $('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
172
+
173
+ var th = this;
174
+ (function(){
175
+ var ids =
176
+ 'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
177
+ 'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
178
+ $w(ids).each(function(id){ th[id] = $(id); });
179
+ }).defer();
180
+ },
181
+
182
+ //
183
+ // updateImageList()
184
+ // Loops through anchor tags looking for 'lightbox' references and applies onclick
185
+ // events to appropriate links. You can rerun after dynamically adding images w/ajax.
186
+ //
187
+ updateImageList: function() {
188
+ this.updateImageList = Prototype.emptyFunction;
189
+
190
+ document.observe('click', (function(event){
191
+ var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
192
+ if (target) {
193
+ event.stop();
194
+ this.start(target);
195
+ }
196
+ }).bind(this));
197
+ },
198
+
199
+ //
200
+ // start()
201
+ // Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
202
+ //
203
+ start: function(imageLink) {
204
+
205
+ $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
206
+
207
+ // stretch overlay to fill page and fade in
208
+ var arrayPageSize = this.getPageSize();
209
+ $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });
210
+
211
+ new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
212
+
213
+ this.imageArray = [];
214
+ var imageNum = 0;
215
+
216
+ if ((imageLink.rel == 'lightbox')){
217
+ // if image is NOT part of a set, add single image to imageArray
218
+ this.imageArray.push([imageLink.href, imageLink.title]);
219
+ } else {
220
+ // if image is part of a set..
221
+ this.imageArray =
222
+ $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
223
+ collect(function(anchor){ return [anchor.href, anchor.title]; }).
224
+ uniq();
225
+
226
+ while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
227
+ }
228
+
229
+ // calculate top and left offset for the lightbox
230
+ var arrayPageScroll = document.viewport.getScrollOffsets();
231
+ var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
232
+ var lightboxLeft = arrayPageScroll[0];
233
+ this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
234
+
235
+ this.changeImage(imageNum);
236
+ },
237
+
238
+ //
239
+ // changeImage()
240
+ // Hide most elements and preload image in preparation for resizing image container.
241
+ //
242
+ changeImage: function(imageNum) {
243
+
244
+ this.activeImage = imageNum; // update global var
245
+
246
+ // hide elements during transition
247
+ if (LightboxOptions.animate) this.loading.show();
248
+ this.lightboxImage.hide();
249
+ this.hoverNav.hide();
250
+ this.prevLink.hide();
251
+ this.nextLink.hide();
252
+ // HACK: Opera9 does not currently support scriptaculous opacity and appear fx
253
+ this.imageDataContainer.setStyle({opacity: .0001});
254
+ this.numberDisplay.hide();
255
+
256
+ var imgPreloader = new Image();
257
+
258
+ // once image is preloaded, resize image container
259
+
260
+
261
+ imgPreloader.onload = (function(){
262
+ this.lightboxImage.src = this.imageArray[this.activeImage][0];
263
+ this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
264
+ }).bind(this);
265
+ imgPreloader.src = this.imageArray[this.activeImage][0];
266
+ },
267
+
268
+ //
269
+ // resizeImageContainer()
270
+ //
271
+ resizeImageContainer: function(imgWidth, imgHeight) {
272
+
273
+ // get current width and height
274
+ var widthCurrent = this.outerImageContainer.getWidth();
275
+ var heightCurrent = this.outerImageContainer.getHeight();
276
+
277
+ // get new width and height
278
+ var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
279
+ var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
280
+
281
+ // scalars based on change from old to new
282
+ var xScale = (widthNew / widthCurrent) * 100;
283
+ var yScale = (heightNew / heightCurrent) * 100;
284
+
285
+ // calculate size difference between new and old image, and resize if necessary
286
+ var wDiff = widthCurrent - widthNew;
287
+ var hDiff = heightCurrent - heightNew;
288
+
289
+ if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
290
+ if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});
291
+
292
+ // if new and old image are same size and no scaling transition is necessary,
293
+ // do a quick pause to prevent image flicker.
294
+ var timeout = 0;
295
+ if ((hDiff == 0) && (wDiff == 0)){
296
+ timeout = 100;
297
+ if (Prototype.Browser.IE) timeout = 250;
298
+ }
299
+
300
+ (function(){
301
+ this.prevLink.setStyle({ height: imgHeight + 'px' });
302
+ this.nextLink.setStyle({ height: imgHeight + 'px' });
303
+ this.imageDataContainer.setStyle({ width: widthNew + 'px' });
304
+
305
+ this.showImage();
306
+ }).bind(this).delay(timeout / 1000);
307
+ },
308
+
309
+ //
310
+ // showImage()
311
+ // Display image and begin preloading neighbors.
312
+ //
313
+ showImage: function(){
314
+ this.loading.hide();
315
+ new Effect.Appear(this.lightboxImage, {
316
+ duration: this.resizeDuration,
317
+ queue: 'end',
318
+ afterFinish: (function(){ this.updateDetails(); }).bind(this)
319
+ });
320
+ this.preloadNeighborImages();
321
+ },
322
+
323
+ //
324
+ // updateDetails()
325
+ // Display caption, image number, and bottom nav.
326
+ //
327
+ updateDetails: function() {
328
+
329
+ // if caption is not null
330
+ if (this.imageArray[this.activeImage][1] != ""){
331
+ this.caption.update(this.imageArray[this.activeImage][1]).show();
332
+ }
333
+
334
+ // if image is part of set display 'Image x of x'
335
+ if (this.imageArray.length > 1){
336
+ this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show();
337
+ }
338
+
339
+ new Effect.Parallel(
340
+ [
341
+ new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
342
+ new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
343
+ ],
344
+ {
345
+ duration: this.resizeDuration,
346
+ afterFinish: (function() {
347
+ // update overlay size and update nav
348
+ var arrayPageSize = this.getPageSize();
349
+ this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
350
+ this.updateNav();
351
+ }).bind(this)
352
+ }
353
+ );
354
+ },
355
+
356
+ //
357
+ // updateNav()
358
+ // Display appropriate previous and next hover navigation.
359
+ //
360
+ updateNav: function() {
361
+
362
+ this.hoverNav.show();
363
+
364
+ // if not first image in set, display prev image button
365
+ if (this.activeImage > 0) this.prevLink.show();
366
+
367
+ // if not last image in set, display next image button
368
+ if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
369
+
370
+ this.enableKeyboardNav();
371
+ },
372
+
373
+ //
374
+ // enableKeyboardNav()
375
+ //
376
+ enableKeyboardNav: function() {
377
+ document.observe('keydown', this.keyboardAction);
378
+ },
379
+
380
+ //
381
+ // disableKeyboardNav()
382
+ //
383
+ disableKeyboardNav: function() {
384
+ document.stopObserving('keydown', this.keyboardAction);
385
+ },
386
+
387
+ //
388
+ // keyboardAction()
389
+ //
390
+ keyboardAction: function(event) {
391
+ var keycode = event.keyCode;
392
+
393
+ var escapeKey;
394
+ if (event.DOM_VK_ESCAPE) { // mozilla
395
+ escapeKey = event.DOM_VK_ESCAPE;
396
+ } else { // ie
397
+ escapeKey = 27;
398
+ }
399
+
400
+ var key = String.fromCharCode(keycode).toLowerCase();
401
+
402
+ if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
403
+ this.end();
404
+ } else if ((key == 'p') || (keycode == 37)){ // display previous image
405
+ if (this.activeImage != 0){
406
+ this.disableKeyboardNav();
407
+ this.changeImage(this.activeImage - 1);
408
+ }
409
+ } else if ((key == 'n') || (keycode == 39)){ // display next image
410
+ if (this.activeImage != (this.imageArray.length - 1)){
411
+ this.disableKeyboardNav();
412
+ this.changeImage(this.activeImage + 1);
413
+ }
414
+ }
415
+ },
416
+
417
+ //
418
+ // preloadNeighborImages()
419
+ // Preload previous and next images.
420
+ //
421
+ preloadNeighborImages: function(){
422
+ var preloadNextImage, preloadPrevImage;
423
+ if (this.imageArray.length > this.activeImage + 1){
424
+ preloadNextImage = new Image();
425
+ preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
426
+ }
427
+ if (this.activeImage > 0){
428
+ preloadPrevImage = new Image();
429
+ preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
430
+ }
431
+
432
+ },
433
+
434
+ //
435
+ // end()
436
+ //
437
+ end: function() {
438
+ this.disableKeyboardNav();
439
+ this.lightbox.hide();
440
+ new Effect.Fade(this.overlay, { duration: this.overlayDuration });
441
+ $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
442
+ },
443
+
444
+ //
445
+ // getPageSize()
446
+ //
447
+ getPageSize: function() {
448
+
449
+ var xScroll, yScroll;
450
+
451
+ if (window.innerHeight && window.scrollMaxY) {
452
+ xScroll = window.innerWidth + window.scrollMaxX;
453
+ yScroll = window.innerHeight + window.scrollMaxY;
454
+ } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
455
+ xScroll = document.body.scrollWidth;
456
+ yScroll = document.body.scrollHeight;
457
+ } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
458
+ xScroll = document.body.offsetWidth;
459
+ yScroll = document.body.offsetHeight;
460
+ }
461
+
462
+ var windowWidth, windowHeight;
463
+
464
+ if (self.innerHeight) { // all except Explorer
465
+ if(document.documentElement.clientWidth){
466
+ windowWidth = document.documentElement.clientWidth;
467
+ } else {
468
+ windowWidth = self.innerWidth;
469
+ }
470
+ windowHeight = self.innerHeight;
471
+ } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
472
+ windowWidth = document.documentElement.clientWidth;
473
+ windowHeight = document.documentElement.clientHeight;
474
+ } else if (document.body) { // other Explorers
475
+ windowWidth = document.body.clientWidth;
476
+ windowHeight = document.body.clientHeight;
477
+ }
478
+
479
+ // for small pages with total height less then height of the viewport
480
+ if(yScroll < windowHeight){
481
+ pageHeight = windowHeight;
482
+ } else {
483
+ pageHeight = yScroll;
484
+ }
485
+
486
+ // for small pages with total width less then width of the viewport
487
+ if(xScroll < windowWidth){
488
+ pageWidth = xScroll;
489
+ } else {
490
+ pageWidth = windowWidth;
491
+ }
492
+
493
+ return [pageWidth,pageHeight];
494
+ }
495
+ }
496
+
497
  document.observe('dom:loaded', function () { new Lightbox(); });
js/lanot/lightbox2/js/scriptaculous.js CHANGED
@@ -1,58 +1,58 @@
1
- // script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
-
3
- // Copyright (c) 2005-2007 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.8.1',
28
- require: function(libraryName) {
29
- // inserting via DOM fails in Safari 2.0, so brute force approach
30
- document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
31
- },
32
- REQUIRED_PROTOTYPE: '1.6.0',
33
- load: function() {
34
- function convertVersionString(versionString){
35
- var r = versionString.split('.');
36
- return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
37
- }
38
-
39
- if((typeof Prototype=='undefined') ||
40
- (typeof Element == 'undefined') ||
41
- (typeof Element.Methods=='undefined') ||
42
- (convertVersionString(Prototype.Version) <
43
- convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
44
- throw("script.aculo.us requires the Prototype JavaScript framework >= " +
45
- Scriptaculous.REQUIRED_PROTOTYPE);
46
-
47
- $A(document.getElementsByTagName("script")).findAll( function(s) {
48
- return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
49
- }).each( function(s) {
50
- var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
51
- var includes = s.src.match(/\?.*load=([a-z,]*)/);
52
- (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
53
- function(include) { Scriptaculous.require(path+include+'.js') });
54
- });
55
- }
56
- }
57
-
58
  Scriptaculous.load();
1
+ // script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
2
+
3
+ // Copyright (c) 2005-2007 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.8.1',
28
+ require: function(libraryName) {
29
+ // inserting via DOM fails in Safari 2.0, so brute force approach
30
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
31
+ },
32
+ REQUIRED_PROTOTYPE: '1.6.0',
33
+ load: function() {
34
+ function convertVersionString(versionString){
35
+ var r = versionString.split('.');
36
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
37
+ }
38
+
39
+ if((typeof Prototype=='undefined') ||
40
+ (typeof Element == 'undefined') ||
41
+ (typeof Element.Methods=='undefined') ||
42
+ (convertVersionString(Prototype.Version) <
43
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
44
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
45
+ Scriptaculous.REQUIRED_PROTOTYPE);
46
+
47
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
48
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
49
+ }).each( function(s) {
50
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
51
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
52
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
53
+ function(include) { Scriptaculous.require(path+include+'.js') });
54
+ });
55
+ }
56
+ }
57
+
58
  Scriptaculous.load();
package.xml CHANGED
@@ -1,20 +1,20 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lanot_GridImage</name>
4
- <version>1.0.1.1</version>
5
  <stability>stable</stability>
6
  <license>OSL</license>
7
  <channel>community</channel>
8
  <extends/>
9
- <summary>Extension allows admin to show product main image at product grid at admin page. </summary>
10
- <description>Extension allows admin to show product main image at product grid at admin page. </description>
11
  <notes>Added:&#xD;
12
- 1. LightBox2&#xD;
13
- 2. Config option for scaling big image.</notes>
14
- <authors><author><name>Lanot</name><user>Lanot</user><email>lanot.biz@gmail.com</email></author></authors>
15
  <date>2012-11-26</date>
16
- <time>16:26:11</time>
17
- <contents><target name="mageetc"><dir name="modules"><file name="Lanot_GridImage.xml" hash="4b81807f005ed89af286c4741a294c42"/></dir></target><target name="magecommunity"><dir name="Lanot"><dir name="GridImage"><dir name="Block"><dir name="Adminhtml"><dir name="Grid"><dir name="Renderer"><file name="Image.php" hash="ce2dc30a684bd1426afa854152c066ad"/></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="6cbe90d876487a628456ceeaab41ab53"/></dir><dir name="Model"><file name="Handler.php" hash="cc17dc0a7e13ee77059c33fe83ea367c"/><dir name="Mysql4"><file name="Attribute.php" hash="1270912696d2c598495c59605deefcbd"/></dir><file name="Observer.php" hash="2bb44860f9819fc89b0d97b50f7b2a6d"/></dir><dir name="etc"><file name="adminhtml.xml" hash="d4c3ef81446e9ac37f3b4256ca66e63b"/><file name="config.xml" hash="c05f47f569c64fc9f8982fd96c444a17"/><file name="system.xml" hash="dcfe00c1e668f25a3a6fa5cf1e8b7232"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="lanot"><dir name="lightbox2"><dir name="css"><file name="lightbox.css" hash="de501f42d328deb2d67cf8ecdb1c8fe2"/></dir><dir name="images"><file name="bullet.gif" hash="1f7dd21de89bed2cf605ed7bd1276a63"/><file name="close.gif" hash="540f65d2b2f94032d6c3037622843a50"/><file name="closelabel.gif" hash="0e5462b0b4f00432eac4b33d5fa31c5a"/><file name="loading.gif" hash="7e99e1159a3686f6aa4f90043c554483"/><file name="nextlabel.gif" hash="110afaaaf901f67fee2357c5df88a1aa"/><file name="prevlabel.gif" hash="fb5fff30d471cc603589578015d36864"/></dir></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="lanot"><dir name="lightbox2"><dir name="js"><file name="builder.js" hash="c688b3e92102c0ac5736152744ac2241"/><file name="effects.js" hash="3b4efe6405d4fb1ada4a081f4dbef6a9"/><file name="lightbox.js" hash="03822995e455eef118a44efe01211c8f"/><file name="scriptaculous.js" hash="75d1aca2ecf6b32922afd4eb9a146558"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="lanot_gridimage.xml" hash="56f6ce720138a58a57387bab5174e413"/></dir><dir name="template"><dir name="lanot"><dir name="gridimage"><file name="js.phtml" hash="7bc693b04eb742d9b8b9191a5abecd6f"/></dir></dir></dir></dir></dir></dir></target></contents>
18
  <compatible/>
19
- <dependencies><required><php><min>5.2.0</min><max>5.5.0</max></php></required></dependencies>
20
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lanot_GridImage</name>
4
+ <version>1.0.1.2</version>
5
  <stability>stable</stability>
6
  <license>OSL</license>
7
  <channel>community</channel>
8
  <extends/>
9
+ <summary>Extension allows admin to show product main image at product grid at admin page.</summary>
10
+ <description>Extension allows admin to show product main image at product grid at admin page.</description>
11
  <notes>Added:&#xD;
12
+ 1. Support LightBox2&#xD;
13
+ 2. Configuration option for scaling big image.</notes>
14
+ <authors><author><name>Lanot</name><user>auto-converted</user><email>lanot.biz@gmail.com</email></author></authors>
15
  <date>2012-11-26</date>
16
+ <time>21:13:55</time>
17
+ <contents><target name="mageetc"><dir name="modules"><file name="Lanot_GridImage.xml" hash="76cc5fa029c534972d8586b8f3c98eb8"/></dir></target><target name="magecommunity"><dir name="Lanot"><dir name="GridImage"><dir name="Block"><dir name="Adminhtml"><dir name="Grid"><dir name="Renderer"><file name="Image.php" hash="9d9120d3ba2c5b41825a288f57dfbe9f"/></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="819ee8fa4e5fb7eef798dc6bae8cc5c8"/></dir><dir name="Model"><dir name="Mysql4"><file name="Attribute.php" hash="a28f7651baabbb5ea933c8019312ad48"/></dir><file name="Handler.php" hash="fecbcd2e9e91f34b458c330b084aa411"/><file name="Observer.php" hash="69d8cc68170920fe17c8f4603e938c03"/></dir><dir name="etc"><file name="adminhtml.xml" hash="97c86983f8cbc5249d7aecc2114cf067"/><file name="config.xml" hash="48cd1c9cbe2b63a4afb365bccee26490"/><file name="system.xml" hash="e90856347dbaf9000692b1ee0d5c2d41"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="lanot"><dir name="lightbox2"><dir name="css"><file name="lightbox.css" hash="5a91b3d053216c3fa9a27d4b537931cb"/></dir><dir name="images"><file name="bullet.gif" hash="1f7dd21de89bed2cf605ed7bd1276a63"/><file name="close.gif" hash="540f65d2b2f94032d6c3037622843a50"/><file name="closelabel.gif" hash="0e5462b0b4f00432eac4b33d5fa31c5a"/><file name="loading.gif" hash="7e99e1159a3686f6aa4f90043c554483"/><file name="nextlabel.gif" hash="110afaaaf901f67fee2357c5df88a1aa"/><file name="prevlabel.gif" hash="fb5fff30d471cc603589578015d36864"/></dir></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="lanot"><dir name="lightbox2"><dir name="js"><file name="builder.js" hash="ca50ed6390f29ce1ed570e6d58c3369f"/><file name="effects.js" hash="73cebad09f0022dd3a4dabda5ead541a"/><file name="lightbox.js" hash="f1b590efa984a6b1e07246cfe5a805b5"/><file name="scriptaculous.js" hash="2ca37b94d756d7ec020de5cfbfd8a9a1"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="lanot_gridimage.xml" hash="ad9fadc7808af0309935cd436bd41a0c"/></dir><dir name="template"><dir name="lanot"><dir name="gridimage"><file name="js.phtml" hash="bf43c338f5dadcedd39c57fced1126e6"/></dir></dir></dir></dir></dir></dir></target></contents>
18
  <compatible/>
19
+ <dependencies/>
20
  </package>
skin/adminhtml/default/default/lanot/lightbox2/css/lightbox.css CHANGED
@@ -1,27 +1,27 @@
1
- #lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
2
- #lightbox img{ width: auto; height: auto;}
3
- #lightbox a img{ border: none; }
4
-
5
- #outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; }
6
- #imageContainer{ padding: 10px; }
7
-
8
- #loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; }
9
- #hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; }
10
- #imageContainer>#hoverNav{ left: 0;}
11
- #hoverNav a{ outline: none;}
12
-
13
- #prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
14
- #prevLink { left: 0; float: left;}
15
- #nextLink { right: 0; float: right;}
16
- #prevLink:hover, #prevLink:visited:hover { background: url(../images/prevlabel.gif) left 15% no-repeat; }
17
- #nextLink:hover, #nextLink:visited:hover { background: url(../images/nextlabel.gif) right 15% no-repeat; }
18
-
19
- #imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
20
-
21
- #imageData{ padding:0 10px; color: #666; }
22
- #imageData #imageDetails{ width: 70%; float: left; text-align: left; }
23
- #imageData #caption{ font-weight: bold; }
24
- #imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
25
- #imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;}
26
-
27
- #overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; }
1
+ #lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
2
+ #lightbox img{ width: auto; height: auto;}
3
+ #lightbox a img{ border: none; }
4
+
5
+ #outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; }
6
+ #imageContainer{ padding: 10px; }
7
+
8
+ #loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; }
9
+ #hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; }
10
+ #imageContainer>#hoverNav{ left: 0;}
11
+ #hoverNav a{ outline: none;}
12
+
13
+ #prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
14
+ #prevLink { left: 0; float: left;}
15
+ #nextLink { right: 0; float: right;}
16
+ #prevLink:hover, #prevLink:visited:hover { background: url(../images/prevlabel.gif) left 15% no-repeat; }
17
+ #nextLink:hover, #nextLink:visited:hover { background: url(../images/nextlabel.gif) right 15% no-repeat; }
18
+
19
+ #imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
20
+
21
+ #imageData{ padding:0 10px; color: #666; }
22
+ #imageData #imageDetails{ width: 70%; float: left; text-align: left; }
23
+ #imageData #caption{ font-weight: bold; }
24
+ #imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
25
+ #imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;}
26
+
27
+ #overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; }