Lanot_GridImage - Version 1.0.1.0

Version Notes

Added:
1. LightBox2
2. Config option for scaling big image.

Download this release

Release Info

Developer Lanot
Extension Lanot_GridImage
Version 1.0.1.0
Comparing to
See all releases


Code changes from version 1.0.0.0 to 1.0.1.0

app/code/community/Lanot/GridImage/Block/Adminhtml/Grid/Renderer/Image.php CHANGED
@@ -25,6 +25,10 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
25
  * @var bool
26
  */
27
  protected $_canClick = false;
 
 
 
 
28
  /**
29
  * @var string
30
  */
@@ -37,6 +41,14 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
37
  * @var null
38
  */
39
  protected $_imageSizeHeight = null;
 
 
 
 
 
 
 
 
40
 
41
  /**
42
  *
@@ -50,16 +62,26 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
50
 
51
  //define configuration
52
  $this->_canClick = $helper->canClick();
 
53
  $this->_imageClass = $helper->getImageClass();
54
  $size = $helper->getImageSize();
 
55
 
 
56
  if (isset($size[0]) && !empty($size[0])) {
57
  $this->_imageSizeWidth = $size[0];
58
  }
59
-
60
  if (isset($size[1]) && !empty($size[1])) {
61
  $this->_imageSizeHeight = $size[1];
62
  }
 
 
 
 
 
 
 
 
63
  }
64
 
65
  /**
@@ -76,6 +98,7 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
76
  /** @var $imageHelper Mage_Catalog_Helper_Image */
77
  $imageHelper = Mage::helper('catalog/image')->init($row, 'lanot_gridimage', $value);
78
 
 
79
  $widthAndHeightTags = '';
80
  if($this->_imageSizeWidth && $this->_imageSizeHeight) {
81
  $imageHelper->resize($this->_imageSizeWidth, $this->_imageSizeHeight);
@@ -89,16 +112,27 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
89
  $widthAndHeightTags .= ' heigth="' . $this->_imageSizeHeight . '"';
90
  }
91
 
 
 
 
 
 
 
 
 
 
92
  if ($this->_canClick) {
93
- $href = Mage::getSingleton('catalog/product_media_config')->getMediaUrl($value);
94
- return sprintf('<a href="%s" class="%s" target="_blank"><img src="%s" border="0" alt="" %s />',
95
  $href,
96
  $this->_imageClass,
 
 
97
  $imageHelper,
98
  $widthAndHeightTags
99
  );
100
  } else {
101
- return sprintf('<img src="%s" class="%s" border="0" alt="" %s />',
102
  $imageHelper,
103
  $this->_imageClass,
104
  $widthAndHeightTags
@@ -106,4 +140,25 @@ class Lanot_GridImage_Block_Adminhtml_Grid_Renderer_Image
106
  }
107
  }
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
25
  * @var bool
26
  */
27
  protected $_canClick = false;
28
+ /**
29
+ * @var bool
30
+ */
31
+ protected $_canShowLightbox = false;
32
  /**
33
  * @var string
34
  */
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
  *
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
  /**
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);
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
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
@@ -44,4 +44,24 @@ class Lanot_GridImage_Helper_Data extends Mage_Core_Helper_Abstract
44
  $size = Mage::getStoreConfig('lanot_gridimage/view/image_size', 0);
45
  return @explode('x', strtolower($size));
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
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,28 +1,25 @@
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
- /**
24
- *
25
- */
26
  const ATTRIBUTE_CODE = 'image';
27
 
28
  /**
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
  /**
app/code/community/Lanot/GridImage/Model/Observer.php CHANGED
@@ -30,6 +30,11 @@ class Lanot_GridImage_Model_Observer
30
  */
31
  protected $_rulesDisabled= null;
32
 
 
 
 
 
 
33
  /**
34
  * @param Varien_Object $observer
35
  */
@@ -56,9 +61,7 @@ class Lanot_GridImage_Model_Observer
56
  return $this;
57
  }
58
 
59
-
60
  Mage::getModel('lanot_gridimage/handler')->addColumnsToBlock($block, $enabledData);
61
-
62
  return $this;
63
  }
64
 
@@ -135,4 +138,4 @@ class Lanot_GridImage_Model_Observer
135
  }
136
  return false;
137
  }
138
- }
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
  */
61
  return $this;
62
  }
63
 
 
64
  Mage::getModel('lanot_gridimage/handler')->addColumnsToBlock($block, $enabledData);
 
65
  return $this;
66
  }
67
 
138
  }
139
  return false;
140
  }
141
+ }
app/code/community/Lanot/GridImage/etc/config.xml CHANGED
@@ -3,7 +3,7 @@
3
 
4
  <modules>
5
  <Lanot_GridImage>
6
- <version>1.0.0.0</version>
7
  </Lanot_GridImage>
8
  </modules>
9
 
@@ -30,7 +30,9 @@
30
  <lanot_gridimage_resource>
31
  <class>Lanot_GridImage_Model_Mysql4</class>
32
  </lanot_gridimage_resource>
 
33
 
 
34
  <!-- OBSERVER EVENTS -->
35
  <events>
36
  <!-- ADMIN HTML BLOCK EVENTS -->
@@ -47,26 +49,35 @@
47
  </events>
48
  <!--/OBSERVER EVENTS -->
49
 
50
- </global>
 
 
 
 
 
 
 
51
 
52
  <default>
53
  <lanot_gridimage>
54
  <view>
55
  <enabled>1</enabled>
56
  <image_click>1</image_click>
 
57
  <image_class>product_thumbnail</image_class>
58
  <image_size>120x120</image_size>
 
59
  </view>
60
 
61
  <!-- rules for matching -->
62
  <rules>
63
  <enabled>
64
- <Mage_Adminhtml_Block_Catalog_Product_Grid after="entity_id" />
65
  </enabled>
66
 
67
  <disabled>
68
- <Mage_Adminhtml_Block_Review_Product_Grid />
69
- <Mage_Adminhtml_Block_Urlrewrite_Product_Grid />
70
  </disabled>
71
  </rules>
72
  <!-- /rules for matching -->
3
 
4
  <modules>
5
  <Lanot_GridImage>
6
+ <version>1.0.1.0</version>
7
  </Lanot_GridImage>
8
  </modules>
9
 
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 -->
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 -->
app/code/community/Lanot/GridImage/etc/system.xml CHANGED
@@ -45,6 +45,18 @@
45
  <show_in_store>0</show_in_store>
46
  </image_click>
47
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  <image_class translate="label">
49
  <label>Image CSS class</label>
50
  <frontend_type>text</frontend_type>
@@ -63,6 +75,16 @@
63
  <show_in_website>0</show_in_website>
64
  <show_in_store>0</show_in_store>
65
  </image_size>
 
 
 
 
 
 
 
 
 
 
66
  </fields>
67
  </view>
68
  </groups>
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>
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>
app/design/adminhtml/default/default/layout/lanot_gridimage.xml ADDED
@@ -0,0 +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>
app/design/adminhtml/default/default/template/lanot/gridimage/js.phtml ADDED
@@ -0,0 +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>
js/lanot/lightbox2/js/builder.js ADDED
@@ -0,0 +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
+ }
js/lanot/lightbox2/js/effects.js ADDED
@@ -0,0 +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);
js/lanot/lightbox2/js/lightbox.js ADDED
@@ -0,0 +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(); });
js/lanot/lightbox2/js/scriptaculous.js ADDED
@@ -0,0 +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();
package.xml CHANGED
@@ -1,18 +1,20 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lanot_GridImage</name>
4
- <version>1.0.0.0</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>The First Release - added ability to show product image at product listing grid.</notes>
12
- <authors><author><name>Lanot</name><user>auto-converted</user><email>lanot.biz@gmail.com</email></author></authors>
13
- <date>2012-10-21</date>
14
- <time>14:09:10</time>
15
- <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="7d6413134e6a8549582fb0c088479c98"/></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="8c633be70e107c166450d7a8d08023f6"/></dir><dir name="Model"><dir name="Mysql4"><file name="Attribute.php" hash="1270912696d2c598495c59605deefcbd"/></dir><file name="Handler.php" hash="93959c2ec955fb37906bbfae33c6baa6"/><file name="Observer.php" hash="4eed1c221091ce485cc7de34b5ab648b"/></dir><dir name="etc"><file name="adminhtml.xml" hash="d4c3ef81446e9ac37f3b4256ca66e63b"/><file name="config.xml" hash="489452c49c906d3221b4772f6f3a4086"/><file name="system.xml" hash="9673a12788657635225b9c791556f506"/></dir></dir></dir></target></contents>
 
 
16
  <compatible/>
17
- <dependencies/>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lanot_GridImage</name>
4
+ <version>1.0.1.0</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:24:36</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="34532e7ab0744bef0be6c6ffce7370f0"/><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>
skin/adminhtml/default/default/lanot/lightbox2/css/lightbox.css ADDED
@@ -0,0 +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; }
skin/adminhtml/default/default/lanot/lightbox2/images/bullet.gif ADDED
Binary file
skin/adminhtml/default/default/lanot/lightbox2/images/close.gif ADDED
Binary file
skin/adminhtml/default/default/lanot/lightbox2/images/closelabel.gif ADDED
Binary file
skin/adminhtml/default/default/lanot/lightbox2/images/loading.gif ADDED
Binary file
skin/adminhtml/default/default/lanot/lightbox2/images/nextlabel.gif ADDED
Binary file
skin/adminhtml/default/default/lanot/lightbox2/images/prevlabel.gif ADDED
Binary file