Altima_lookbook_free - Version 0.1.0

Version Notes

Altima Lookbook Free extension provides online merchants with an ability to show their product in nice and compelling way, close to the way it is shown in print catalogues, but with interactive link to product pages. For example you can show your dresses and accessories on sexy models and furniture in well designed living room. Each element of lookbook image can be tagged as a hotspot and linked to specific product page of your Magento online store.

Download this release

Release Info

Developer Magento Core Team
Extension Altima_lookbook_free
Version 0.1.0
Comparing to
See all releases


Version 0.1.0

Files changed (59) hide show
  1. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook.php +32 -0
  2. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit.php +56 -0
  3. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form.php +38 -0
  4. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form/Element/Hotspots.php +108 -0
  5. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form/Element/Lookbookimage.php +121 -0
  6. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Tab/Form.php +81 -0
  7. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Tabs.php +43 -0
  8. app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Grid.php +144 -0
  9. app/code/local/Altima/Lookbook/Block/Adminhtml/Template/Grid/Renderer/Image.php +44 -0
  10. app/code/local/Altima/Lookbook/Block/Lookbook.php +47 -0
  11. app/code/local/Altima/Lookbook/Helper/Data.php +222 -0
  12. app/code/local/Altima/Lookbook/Model/Fileuploader.php +152 -0
  13. app/code/local/Altima/Lookbook/Model/Layout/Generate/Observer.php +46 -0
  14. app/code/local/Altima/Lookbook/Model/Lookbook.php +33 -0
  15. app/code/local/Altima/Lookbook/Model/Mysql4/Lookbook.php +29 -0
  16. app/code/local/Altima/Lookbook/Model/Mysql4/Lookbook/Collection.php +29 -0
  17. app/code/local/Altima/Lookbook/Model/Status.php +34 -0
  18. app/code/local/Altima/Lookbook/Model/Uploadedfileform.php +44 -0
  19. app/code/local/Altima/Lookbook/Model/Uploadedfilexhr.php +52 -0
  20. app/code/local/Altima/Lookbook/controllers/Adminhtml/LookbookController.php +256 -0
  21. app/code/local/Altima/Lookbook/controllers/IndexController.php +48 -0
  22. app/code/local/Altima/Lookbook/etc/config.xml +174 -0
  23. app/code/local/Altima/Lookbook/etc/system.xml +117 -0
  24. app/code/local/Altima/Lookbook/sql/lookbook_setup/mysql4-install-0.1.0.php +45 -0
  25. app/design/adminhtml/default/default/layout/lookbook.xml +42 -0
  26. app/design/frontend/base/default/layout/lookbook.xml +38 -0
  27. app/design/frontend/base/default/template/lookbook/lookbook.phtml +201 -0
  28. app/etc/modules/Altima_Lookbook.xml +36 -0
  29. js/jquery/jquery-1.7.min.js +4 -0
  30. js/jquery/jquery.noconflict.js +1 -0
  31. js/lookbook/fileuploader.js +1251 -0
  32. js/lookbook/jquery-ui-1.8.17.js +11827 -0
  33. js/lookbook/jquery.annotate.js +536 -0
  34. js/lookbook/json2.min.js +1 -0
  35. js/lookbook/slides.min.jquery.js +20 -0
  36. media/lookbook/icons/default/hotspot-icon.png +0 -0
  37. package.xml +18 -0
  38. skin/adminhtml/default/default/lookbook/css/annotation.css +288 -0
  39. skin/adminhtml/default/default/lookbook/css/fileuploader.css +75 -0
  40. skin/adminhtml/default/default/lookbook/images/btn_bg.gif +0 -0
  41. skin/adminhtml/default/default/lookbook/images/btn_gray_bg.gif +0 -0
  42. skin/adminhtml/default/default/lookbook/images/btn_over_bg.gif +0 -0
  43. skin/adminhtml/default/default/lookbook/images/cancel_btn_icon.png +0 -0
  44. skin/adminhtml/default/default/lookbook/images/cross.png +0 -0
  45. skin/adminhtml/default/default/lookbook/images/delete_btn_icon.png +0 -0
  46. skin/adminhtml/default/default/lookbook/images/icon_btn_add.png +0 -0
  47. skin/adminhtml/default/default/lookbook/images/link_external.png +0 -0
  48. skin/adminhtml/default/default/lookbook/images/loading.gif +0 -0
  49. skin/adminhtml/default/default/lookbook/images/ok_btn_icon.png +0 -0
  50. skin/adminhtml/default/default/lookbook/images/upload_btn_icon.png +0 -0
  51. skin/frontend/base/default/lookbook/css/hotspots.css +141 -0
  52. skin/frontend/base/default/lookbook/images/adv-bg.png +0 -0
  53. skin/frontend/base/default/lookbook/images/arrow-next.png +0 -0
  54. skin/frontend/base/default/lookbook/images/arrow-prev.png +0 -0
  55. skin/frontend/base/default/lookbook/images/background.png +0 -0
  56. skin/frontend/base/default/lookbook/images/caption-bg.png +0 -0
  57. skin/frontend/base/default/lookbook/images/info-bg.png +0 -0
  58. skin/frontend/base/default/lookbook/images/loading.gif +0 -0
  59. skin/frontend/base/default/lookbook/images/pagination.png +0 -0
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook extends Mage_Adminhtml_Block_Widget_Grid_Container
23
+ {
24
+ public function __construct()
25
+ {
26
+ $this->_controller = 'adminhtml_lookbook';
27
+ $this->_blockGroup = 'lookbook';
28
+ $this->_headerText = Mage::helper('lookbook')->__('Lookbook slides manager');
29
+ $this->_addButtonLabel = Mage::helper('lookbook')->__('Add slide');
30
+ parent::__construct();
31
+ }
32
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
23
+ {
24
+ public function __construct()
25
+ {
26
+ parent::__construct();
27
+
28
+ $this->_objectId = 'id';
29
+ $this->_blockGroup = 'lookbook';
30
+ $this->_controller = 'adminhtml_lookbook';
31
+
32
+ $this->_updateButton('save', 'label', Mage::helper('lookbook')->__('Save slide'));
33
+ $this->_updateButton('delete', 'label', Mage::helper('lookbook')->__('Delete slide'));
34
+
35
+ $this->_addButton('saveandcontinue', array(
36
+ 'label' => Mage::helper('adminhtml')->__('Save And Continue Edit'),
37
+ 'onclick' => 'saveAndContinueEdit()',
38
+ 'class' => 'save',
39
+ ), -100);
40
+
41
+ $this->_formScripts[] = "
42
+ function saveAndContinueEdit(){
43
+ editForm.submit($('edit_form').action+'back/edit/');
44
+ }
45
+ ";
46
+ }
47
+
48
+ public function getHeaderText()
49
+ {
50
+ if( Mage::registry('lookbook_data') && Mage::registry('lookbook_data')->getId() ) {
51
+ return Mage::helper('lookbook')->__("Edit slide '%s'", $this->htmlEscape(Mage::registry('lookbook_data')->getName()));
52
+ } else {
53
+ return Mage::helper('lookbook')->__('Add slide');
54
+ }
55
+ }
56
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
23
+ {
24
+ protected function _prepareForm()
25
+ {
26
+ $form = new Varien_Data_Form(array(
27
+ 'id' => 'edit_form',
28
+ 'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
29
+ 'method' => 'post',
30
+ 'enctype' => 'multipart/form-data'
31
+ )
32
+ );
33
+
34
+ $form->setUseContainer(true);
35
+ $this->setForm($form);
36
+ return parent::_prepareForm();
37
+ }
38
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form/Element/Hotspots.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Form_Element_Hotspots extends Varien_Data_Form_Element_Abstract
23
+ {
24
+ public function __construct($data)
25
+ {
26
+ parent::__construct($data);
27
+ $this->setType('hidden');
28
+ }
29
+
30
+ public function getElementHtml()
31
+ {
32
+ $hotspot_icon = Mage::getBaseUrl('media').'lookbook/icons/default/hotspot-icon.png';
33
+ $products_link = Mage::helper("adminhtml")->getUrl('adminhtml/catalog_product/');
34
+ $helper = Mage::helper('lookbook');
35
+
36
+ $html = '
37
+ <style>
38
+ .image-annotate-area, .image-annotate-edit-area {
39
+ background: url('.$hotspot_icon.') no-repeat center center;
40
+ }
41
+ </style>
42
+ <script type="text/javascript">
43
+ //<![CDATA[
44
+ function InitHotspotBtn() {
45
+ if ($j("img#LookbookImage").attr("id")) {
46
+ var annotObj = $j("img#LookbookImage").annotateImage({
47
+ editable: true,
48
+ useAjax: false,';
49
+ if ($this->getValue()) $html .= 'notes: '. $this->getValue() . ',';
50
+
51
+ $html .= ' input_field_id: "hotspots"
52
+ });
53
+
54
+ $j("img#LookbookImage").before(\'<div class="products-link"><a href="'.$products_link.'" title="'.$helper->__('Products List').'" target="_blank">'. $helper->__('Products List').'</a></div>\');
55
+
56
+ var top = Math.round($j("img#LookbookImage").height()/2);
57
+ $j(".image-annotate-canvas").append(\'<div class="hotspots-msg" style="top:\' + top + \'px;">'. $helper->__('Rollover on the image to see hotspots').'</div>\');
58
+
59
+ $j(".image-annotate-canvas").hover(
60
+ function () {
61
+ ShowHideHotspotsMsg();
62
+ },
63
+ function () {
64
+ ShowHideHotspotsMsg();
65
+ }
66
+ );
67
+
68
+ return annotObj;
69
+ }
70
+ else
71
+ {
72
+ return false;
73
+ }
74
+ };
75
+
76
+ function checkSKU(){
77
+ result = "";
78
+ request = new Ajax.Request(
79
+ "'. Mage::getUrl("lookbook/adminhtml_lookbook/getproduct").'",
80
+ {
81
+ method: \'post\',
82
+ asynchronous: false,
83
+ onComplete: function(transport){
84
+ if (200 == transport.status) {
85
+ result = transport.responseText;
86
+ return result;
87
+ }
88
+ if (result.error) {
89
+ alert("Unable to check product SKU");
90
+ return false;
91
+ }
92
+ },
93
+ parameters: Form.serialize($("annotate-edit-form"))
94
+ }
95
+ );
96
+ return result;
97
+ };
98
+ //]]>
99
+ </script>';
100
+
101
+ $html.= parent::getElementHtml();
102
+
103
+ return $html;
104
+ }
105
+ }
106
+
107
+
108
+
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Form/Element/Lookbookimage.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Form_Element_Lookbookimage extends Varien_Data_Form_Element_Abstract
23
+ {
24
+ public function __construct($data)
25
+ {
26
+ parent::__construct($data);
27
+ $this->setType('hidden');
28
+ }
29
+
30
+ public function getElementHtml()
31
+ {
32
+ $block_class = Mage::getBlockSingleton('lookbook/adminhtml_lookbook');
33
+ $upload_action = Mage::getUrl('lookbook/adminhtml_lookbook/upload').'?isAjax=true';
34
+ $media_url = Mage::getBaseUrl('media');
35
+ $upload_folder_path = str_replace("/",DS, Mage::getBaseDir("media").DS);
36
+ $helper = Mage::helper('lookbook');
37
+ $min_image_width = $helper->getMinImageWidth();
38
+ $min_image_height = $helper->getMinImageHeight();
39
+ $sizeLimit = $helper->getMaxUploadFilesize();
40
+ $allowed_extensions = implode('","',explode(',',$helper->getAllowedExtensions()));
41
+
42
+ $html = '<script type="text/javascript">
43
+ //<![CDATA[
44
+
45
+ $j(document).ready(function() {
46
+
47
+ InitHotspotBtn();
48
+
49
+ img_uploader = new qq.FileUploader({
50
+ element: document.getElementById(\'maket_image\'),
51
+ action: "'.$upload_action.'",
52
+ params: {"form_key":"'.$block_class->getFormKey().'"},
53
+ multiple: false,
54
+ allowedExtensions: ["'.$allowed_extensions.'"],
55
+ sizeLimit: '. $sizeLimit .',
56
+ onComplete: function(id, fileName, responseJSON){
57
+ if (responseJSON.success)
58
+ {
59
+ if ($j(\'#LookbookImageBlock\'))
60
+ {
61
+ $j.each($j(\'#LookbookImageBlock\').children(),function(index) {
62
+ $j(this).remove();
63
+ });
64
+ }
65
+ $j(\'#LookbookImageBlock\').append(\'<img id="LookbookImage"';
66
+ $html .= ' src="'.$media_url.'lookbook/\'+responseJSON.filename+\'" alt="\'+responseJSON.filename+\'"';
67
+ $html .= ' width="\'+responseJSON.dimensions.width+\'" height="\'+responseJSON.dimensions.height+\'"/>\');
68
+
69
+ if ($j(\'#advice-required-entry-image\'))
70
+ {
71
+ $j(\'#advice-required-entry-image\').remove();
72
+ }
73
+ $j(\'#LookbookImage\').load(function(){
74
+ $j(this).attr(\'width\',responseJSON.dimensions.width);
75
+ $j(this).attr(\'height\',responseJSON.dimensions.height);
76
+ InitHotspotBtn();
77
+ });
78
+ $j(\'#image\').val(\'lookbook/\'+responseJSON.filename);
79
+ $j(\'#image\').removeClass(\'validation-failed\');
80
+ }
81
+
82
+ }
83
+ });
84
+ });
85
+ //]]>
86
+ </script>
87
+ <div id="LookbookImageBlock">';
88
+
89
+ if ($this->getValue()) {
90
+ $img_src = $media_url.$this->getValue();
91
+ $img_path = $upload_folder_path.$this->getValue();
92
+ if (file_exists($img_path)) {
93
+
94
+ $dimensions = Mage::helper('lookbook')->getImageDimensions($img_path);
95
+
96
+ $html .= '<img id="LookbookImage" src="'.$img_src.'" alt="'.basename($img_src).'" width="'.$dimensions['width'].'" height="'.$dimensions['height'].'"/>';
97
+ }
98
+ else
99
+ {
100
+ $html .= '<h4 id="LookbookImage" style="color:red;">File '.$img_src.' doesn\'t exists.</h4>';
101
+ }
102
+ }
103
+
104
+ $html .= '</div>
105
+ <div id="maket_image">
106
+ <noscript>
107
+ <p>Please enable JavaScript to use file uploader.</p>
108
+ <!-- or put a simple form for upload here -->
109
+ </noscript>
110
+ </div>';
111
+
112
+ $html.= parent::getElementHtml();
113
+
114
+ if ($min_image_width!=0 && $min_image_height!=0){
115
+ $html.= '<p class="note" style="clear:both; float:left;">Please make sure that the image your load is at least '
116
+ .$min_image_width.'x'.$min_image_height.' pixels</p>';
117
+ }
118
+
119
+ return $html;
120
+ }
121
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Tab/Form.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
23
+ {
24
+ protected function _prepareForm()
25
+ {
26
+ $form = new Varien_Data_Form();
27
+
28
+ $this->setForm($form);
29
+
30
+ $fieldset = $form->addFieldset('lookbook_form', array('legend'=>Mage::helper('lookbook')->__('Lookbook slide information')));
31
+
32
+ $fieldset->addField('name', 'text', array(
33
+ 'label' => Mage::helper('lookbook')->__('Name'),
34
+ 'required' => true,
35
+ 'name' => 'name',
36
+ ));
37
+
38
+ $fieldset->addField('position', 'text', array(
39
+ 'label' => Mage::helper('lookbook')->__('Order'),
40
+ 'required' => false,
41
+ 'name' => 'position',
42
+ ));
43
+
44
+ $fieldset->addField('status', 'select', array(
45
+ 'label' => Mage::helper('lookbook')->__('Status'),
46
+ 'name' => 'status',
47
+ 'values' => array(
48
+ array(
49
+ 'value' => 1,
50
+ 'label' => Mage::helper('lookbook')->__('Enabled'),
51
+ ),
52
+
53
+ array(
54
+ 'value' => 2,
55
+ 'label' => Mage::helper('lookbook')->__('Disabled'),
56
+ ),
57
+ ),
58
+ ));
59
+
60
+ $fieldset->addType('lookbookimage','Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Form_Element_Lookbookimage');
61
+ $fieldset->addField('image', 'lookbookimage', array(
62
+ 'label' => Mage::helper('lookbook')->__('Image'),
63
+ 'name' => 'image',
64
+ 'required' => true,
65
+ ));
66
+
67
+ $fieldset->addType('hotspots','Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Form_Element_Hotspots');
68
+ $fieldset->addField('hotspots', 'hotspots', array(
69
+ 'name' => 'hotspots',
70
+ ));
71
+
72
+ if ( Mage::getSingleton('adminhtml/session')->getLookbookData() )
73
+ {
74
+ $form->setValues(Mage::getSingleton('adminhtml/session')->getLookbookData());
75
+ Mage::getSingleton('adminhtml/session')->setLookbookData(null);
76
+ } elseif ( Mage::registry('lookbook_data') ) {
77
+ $form->setValues(Mage::registry('lookbook_data')->getData());
78
+ }
79
+ return parent::_prepareForm();
80
+ }
81
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Edit/Tabs.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
23
+ {
24
+
25
+ public function __construct()
26
+ {
27
+ parent::__construct();
28
+ $this->setId('lookbook_tabs');
29
+ $this->setDestElementId('edit_form');
30
+ $this->setTitle(Mage::helper('lookbook')->__('Lookbook slide information'));
31
+ }
32
+
33
+ protected function _beforeToHtml()
34
+ {
35
+ $this->addTab('form_section', array(
36
+ 'label' => Mage::helper('lookbook')->__('Lookbook slide information'),
37
+ 'title' => Mage::helper('lookbook')->__('Lookbook slide information'),
38
+ 'content' => $this->getLayout()->createBlock('lookbook/adminhtml_lookbook_edit_tab_form')->toHtml(),
39
+ ));
40
+
41
+ return parent::_beforeToHtml();
42
+ }
43
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Lookbook/Grid.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Lookbook_Grid extends Mage_Adminhtml_Block_Widget_Grid
23
+ {
24
+ public function __construct()
25
+ {
26
+ parent::__construct();
27
+ $this->setId('lookbookGrid');
28
+ $this->setDefaultSort('lookbook_id');
29
+ $this->setDefaultDir('ASC');
30
+ $this->setSaveParametersInSession(true);
31
+ }
32
+
33
+ protected function _prepareCollection()
34
+ {
35
+ $collection = Mage::getModel('lookbook/lookbook')->getCollection();
36
+ $this->setCollection($collection);
37
+ return parent::_prepareCollection();
38
+ }
39
+
40
+ protected function _prepareColumns()
41
+ {
42
+ $this->addColumn('lookbook_id', array(
43
+ 'header' => Mage::helper('lookbook')->__('ID'),
44
+ 'align' =>'right',
45
+ 'width' => '50px',
46
+ 'index' => 'lookbook_id',
47
+ ));
48
+
49
+ $this->addColumn( 'image', array(
50
+ 'header' => Mage::helper( 'lookbook' )->__( 'Image' ),
51
+ 'type' => 'image',
52
+ 'width' => '75px',
53
+ 'index' => 'image',
54
+ 'filter' => false,
55
+ 'sortable' => false,
56
+ 'renderer' => 'lookbook/adminhtml_template_grid_renderer_image',
57
+ ));
58
+
59
+ $this->addColumn('name', array(
60
+ 'header' => Mage::helper('lookbook')->__('Name'),
61
+ 'align' =>'left',
62
+ 'index' => 'name',
63
+ ));
64
+
65
+ $this->addColumn('position', array(
66
+ 'header' => Mage::helper('lookbook')->__('Order'),
67
+ 'align' =>'left',
68
+ 'width' => '50px',
69
+ 'index' => 'position',
70
+ ));
71
+
72
+ $this->addColumn('status', array(
73
+ 'header' => Mage::helper('lookbook')->__('Status'),
74
+ 'align' => 'left',
75
+ 'width' => '80px',
76
+ 'index' => 'status',
77
+ 'type' => 'options',
78
+ 'options' => array(
79
+ 1 => 'Enabled',
80
+ 2 => 'Disabled',
81
+ ),
82
+ ));
83
+
84
+ $this->addColumn('action',
85
+ array(
86
+ 'header' => Mage::helper('lookbook')->__('Action'),
87
+ 'width' => '100',
88
+ 'type' => 'action',
89
+ 'getter' => 'getId',
90
+ 'actions' => array(
91
+ array(
92
+ 'caption' => Mage::helper('lookbook')->__('Edit'),
93
+ 'url' => array('base'=> '*/*/edit'),
94
+ 'field' => 'id'
95
+ )
96
+ ),
97
+ 'filter' => false,
98
+ 'sortable' => false,
99
+ 'index' => 'stores',
100
+ 'is_system' => true,
101
+ ));
102
+
103
+ $this->addExportType('*/*/exportCsv', Mage::helper('lookbook')->__('CSV'));
104
+ $this->addExportType('*/*/exportXml', Mage::helper('lookbook')->__('XML'));
105
+
106
+ return parent::_prepareColumns();
107
+ }
108
+
109
+ protected function _prepareMassaction()
110
+ {
111
+ $this->setMassactionIdField('lookbook_id');
112
+ $this->getMassactionBlock()->setFormFieldName('lookbook');
113
+
114
+ $this->getMassactionBlock()->addItem('delete', array(
115
+ 'label' => Mage::helper('lookbook')->__('Delete'),
116
+ 'url' => $this->getUrl('*/*/massDelete'),
117
+ 'confirm' => Mage::helper('lookbook')->__('Are you sure?')
118
+ ));
119
+
120
+ $statuses = Mage::getSingleton('lookbook/status')->getOptionArray();
121
+
122
+ array_unshift($statuses, array('label'=>'', 'value'=>''));
123
+ $this->getMassactionBlock()->addItem('status', array(
124
+ 'label'=> Mage::helper('lookbook')->__('Change status'),
125
+ 'url' => $this->getUrl('*/*/massStatus', array('_current'=>true)),
126
+ 'additional' => array(
127
+ 'visibility' => array(
128
+ 'name' => 'status',
129
+ 'type' => 'select',
130
+ 'class' => 'required-entry',
131
+ 'label' => Mage::helper('lookbook')->__('Status'),
132
+ 'values' => $statuses
133
+ )
134
+ )
135
+ ));
136
+ return $this;
137
+ }
138
+
139
+ public function getRowUrl($row)
140
+ {
141
+ return $this->getUrl('*/*/edit', array('id' => $row->getId()));
142
+ }
143
+
144
+ }
app/code/local/Altima/Lookbook/Block/Adminhtml/Template/Grid/Renderer/Image.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Adminhtml_Template_Grid_Renderer_Image extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Action
23
+ {
24
+ public function render(Varien_Object $row)
25
+ {
26
+ return $this->_getValue($row);
27
+ }
28
+
29
+ public function _getValue(Varien_Object $row)
30
+ {
31
+ if ($getter = $this->getColumn()->getGetter()) {
32
+ $val = $row->$getter();
33
+ }
34
+ $width = str_replace('px','',$this->getColumn()->getWidth());
35
+ $val = $row->getData($this->getColumn()->getIndex());
36
+ $url = Mage::helper('lookbook')->getResizedUrl($val,$width);
37
+ $out = '<center>';
38
+ $out .= "<img src=" . $url . " />";
39
+ $out .= '</center>';
40
+
41
+ return $out;
42
+
43
+ }
44
+ }
app/code/local/Altima/Lookbook/Block/Lookbook.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Block_Lookbook extends Mage_Core_Block_Template
23
+ {
24
+ protected function _construct()
25
+ {
26
+ $this->addData(array(
27
+ 'cache_lifetime' => false,
28
+ 'cache_tags' => array(Altima_Lookbook_Model_Lookbook::CACHE_TAG),
29
+ 'cache_key' => 'slider',
30
+ ));
31
+ }
32
+
33
+ public function _prepareLayout()
34
+ {
35
+ return parent::_prepareLayout();
36
+ }
37
+
38
+ public function getCollection()
39
+ {
40
+ $collection = Mage::getModel('lookbook/lookbook')
41
+ ->getCollection()
42
+ ->addFieldToFilter('status', 1)
43
+ ->setOrder('position', 'ASC');
44
+ return $collection;
45
+ }
46
+
47
+ }
app/code/local/Altima/Lookbook/Helper/Data.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Helper_Data extends Mage_Core_Helper_Abstract
23
+ {
24
+ public function getEnabled()
25
+ {
26
+ return Mage::getStoreConfig('lookbook/general/enabled');
27
+ }
28
+
29
+ public function getMaxImageWidth()
30
+ {
31
+ return intval(Mage::getStoreConfig('lookbook/general/max_image_width'));
32
+ }
33
+
34
+ public function getMaxImageHeight()
35
+ {
36
+ return intval(Mage::getStoreConfig('lookbook/general/max_image_height'));
37
+ }
38
+
39
+ public function getMinImageWidth()
40
+ {
41
+ return intval(Mage::getStoreConfig('lookbook/general/min_image_width'));
42
+ }
43
+
44
+ public function getMinImageHeight()
45
+ {
46
+ return intval(Mage::getStoreConfig('lookbook/general/min_image_height'));
47
+ }
48
+
49
+ public function getMaxUploadFilesize()
50
+ {
51
+ return intval(Mage::getStoreConfig('lookbook/general/max_upload_filesize'));
52
+ }
53
+
54
+ public function getAllowedExtensions()
55
+ {
56
+ return Mage::getStoreConfig('lookbook/general/allowed_extensions');
57
+ }
58
+ /**
59
+ * Returns the resized Image URL
60
+ *
61
+ * @param string $imgUrl - This is relative to the the media folder (custom/module/images/example.jpg)
62
+ * @param int $x Width
63
+ * @param int $y Height
64
+ *Remember your base image or big image must be in Root/media/lookbook/example.jpg
65
+ *
66
+ * echo Mage::helper('lookbook')->getResizedUrl("lookbook/example.jpg",101,65)
67
+ *
68
+ *By doing this new image will be created in Root/media/lookbook/101X65/example.jpg
69
+ */
70
+
71
+ public function getResizedUrl($imgUrl,$x,$y=NULL){
72
+
73
+ $imgPath=$this->splitImageValue($imgUrl,"path");
74
+ $imgName=$this->splitImageValue($imgUrl,"name");
75
+
76
+ /**
77
+ * Path with Directory Seperator
78
+ */
79
+ $imgPath=str_replace("/",DS,$imgPath);
80
+
81
+ /**
82
+ * Absolute full path of Image
83
+ */
84
+ $imgPathFull=Mage::getBaseDir("media").DS.$imgPath.DS.$imgName;
85
+
86
+ /**
87
+ * If Y is not set set it to as X
88
+ */
89
+ $width=$x;
90
+ $y?$height=$y:$height=$x;
91
+
92
+ /**
93
+ * Resize folder is widthXheight
94
+ */
95
+ $resizeFolder=$width."X".$height;
96
+
97
+ /**
98
+ * Image resized path will then be
99
+ */
100
+ $imageResizedPath=Mage::getBaseDir("media").DS.$imgPath.DS.$resizeFolder.DS.$imgName;
101
+
102
+ /**
103
+ * First check in cache i.e image resized path
104
+ * If not in cache then create image of the width=X and height = Y
105
+ */
106
+ if (!file_exists($imageResizedPath) && file_exists($imgPathFull)) :
107
+ $imageObj = new Varien_Image($imgPathFull);
108
+ $imageObj->constrainOnly(TRUE);
109
+ $imageObj->keepAspectRatio(TRUE);
110
+ $imageObj->keepTransparency(TRUE);
111
+ $imageObj->resize($width,$height);
112
+ $imageObj->save($imageResizedPath);
113
+ endif;
114
+
115
+ /**
116
+ * Else image is in cache replace the Image Path with / for http path.
117
+ */
118
+ $imgUrl=str_replace(DS,"/",$imgPath);
119
+
120
+ /**
121
+ * Return full http path of the image
122
+ */
123
+ return Mage::getBaseUrl("media").$imgUrl."/".$resizeFolder."/".$imgName;
124
+ }
125
+
126
+ /**
127
+ * Splits images Path and Name
128
+ *
129
+ * Path=lookbook/
130
+ * Name=example.jpg
131
+ *
132
+ * @param string $imageValue
133
+ * @param string $attr
134
+ * @return string
135
+ */
136
+ public function splitImageValue($imageValue,$attr="name"){
137
+ $imArray=explode("/",$imageValue);
138
+
139
+ $name=$imArray[count($imArray)-1];
140
+ $path=implode("/",array_diff($imArray,array($name)));
141
+ if($attr=="path"){
142
+ return $path;
143
+ }
144
+ else
145
+ return $name;
146
+
147
+ }
148
+
149
+ /**
150
+ * Splits images Path and Name
151
+ *
152
+ * img_path=lookbook/example.jpg
153
+ *
154
+ * @param string $img_path
155
+ * @return array('width'=>$width, 'height'=>$height)
156
+ */
157
+ public function getImageDimensions($img_path){
158
+ $imageObj = new Varien_Image($img_path);
159
+ $width = $imageObj->getOriginalWidth();
160
+ $height = $imageObj->getOriginalHeight();
161
+ $result = array('width'=>$width, 'height'=>$height);
162
+ return $result;
163
+ }
164
+
165
+ /**
166
+ * Change SKU to product information into Json array
167
+ *
168
+ * img_path=lookbook/example.jpg
169
+ *
170
+ * @param json array $array
171
+ * @return json array('width'=>$width, 'height'=>$height)
172
+ */
173
+ public function getHotspotsWithProductDetails($hotspots_json){
174
+ if ($hotspots_json=='') return '';
175
+ $decoded_array = json_decode($hotspots_json,true);
176
+ $img_width = intval(Mage::getStoreConfig('lookbook/general/max_image_width'));
177
+ $hotspot_icon = Mage::getBaseUrl('media').'lookbook/icons/default/hotspot-icon.png';
178
+ $hotspot_icon_path = Mage::getBaseDir('media').DS.'lookbook'.DS.'icons'.DS.'default'.DS.'hotspot-icon.png';
179
+ $icon_dimensions = $this->getImageDimensions($hotspot_icon_path);
180
+ $_coreHelper = Mage::helper('core');
181
+ foreach($decoded_array as $key => $value){
182
+ $product_details = Mage::getModel('catalog/product')->loadByAttribute('sku',$decoded_array[$key]['text']);
183
+
184
+ $html_content = '<img class="hotspot-icon" src="'.$hotspot_icon.'" alt="" style="
185
+ left:'. (round($value['width']/2)-round($icon_dimensions['width']/2)) .'px;
186
+ top:'. (round($value['height']/2)-round($icon_dimensions['height']/2)) .'px;
187
+ "/><div class="product-info" style="';
188
+ $html_content .= 'left:'.round($value['width']/2).'px;';
189
+ $html_content .= 'top:'.round($value['height']/2).'px;';
190
+
191
+ if ($product_details) {
192
+ $_p_name = $product_details->getName();
193
+ $html_content .= 'width: '. strlen($_p_name)*8 .'px;';
194
+ }
195
+ else
196
+ {
197
+ $html_content .= 'width: 200px;';
198
+ }
199
+
200
+ $html_content .= '">';
201
+ if ($product_details) {
202
+ $_p_price = $_coreHelper->currency($product_details->getPrice(),true,false);
203
+ $_p_url = $product_details->getProductUrl();
204
+ $html_content .= '<div><a href=\''.$_p_url.'\'>'.$_p_name.'</a></div>';
205
+ if($product_details->getPrice()){
206
+ $html_content .= '<div class="price">'.$_p_price.'</div>';
207
+ }
208
+ }
209
+ else
210
+ {
211
+ $html_content .= '<div>Product with SKU "'.$decoded_array[$key]['text'].'" doesn\'t exists.</div>';
212
+ }
213
+ $html_content .= '
214
+ </div>
215
+ ';
216
+
217
+ $decoded_array[$key]['text'] = $html_content;
218
+ }
219
+ $result = $decoded_array;
220
+ return $result;
221
+ }
222
+ }
app/code/local/Altima/Lookbook/Model/Fileuploader.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Fileuploader {
23
+
24
+ private $allowedExtensions = array();
25
+ private $sizeLimit = 10485760;
26
+ private $min_image_width = 0;
27
+ private $min_image_height = 0;
28
+ private $max_image_width = 0;
29
+ private $max_image_height = 0;
30
+ private $filemodel;
31
+
32
+ function __construct(){
33
+
34
+ $helper = Mage::helper('lookbook');
35
+ $sizeLimit = $helper->getMaxUploadFilesize();
36
+ $this->min_image_width = $helper->getMinImageWidth();
37
+ $this->min_image_height = $helper->getMinImageHeight();
38
+ $this->max_image_width = $helper->getMaxImageWidth();
39
+ $this->max_image_height = $helper->getMaxImageHeight();
40
+ $allowed_extensions = explode(',',$helper->getAllowedExtensions());
41
+
42
+ $this->allowedExtensions = array_map("strtolower", $allowed_extensions);
43
+ if ($sizeLimit>0) $this->sizeLimit = $sizeLimit;
44
+
45
+ if (isset($_GET['qqfile'])) {
46
+ $this->filemodel = Mage::getModel('lookbook/uploadedfilexhr');
47
+ } elseif (isset($_FILES['qqfile'])) {
48
+ $this->filemodel = Mage::getModel('lookbook/uploadedfileform');
49
+ } else {
50
+ $this->filemodel = false;
51
+ }
52
+
53
+ }
54
+
55
+ public function checkServerSettings(){
56
+ $postSize = $this->toBytes(ini_get('post_max_size'));
57
+ $uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
58
+
59
+ if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
60
+ $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
61
+ return array('error' => 'increase post_max_size and upload_max_filesize to $size');
62
+ }
63
+
64
+ if ($this->max_image_width < $this->min_image_width || $this->max_image_height < $this->min_image_height){
65
+ return array('error' => 'File was not uploaded. Minimal image width (height) can\'t be greater then maximal. Please, check settings.');
66
+ }
67
+ return true;
68
+
69
+ }
70
+
71
+ private function toBytes($str){
72
+ $val = trim($str);
73
+ $last = strtolower($str[strlen($str)-1]);
74
+ switch($last) {
75
+ case 'g': $val *= 1024;
76
+ case 'm': $val *= 1024;
77
+ case 'k': $val *= 1024;
78
+ }
79
+ return $val;
80
+ }
81
+
82
+ /**
83
+ * Returns array('success'=>true) or array('error'=>'error message')
84
+ */
85
+ function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
86
+ if (!is_writable($uploadDirectory)){
87
+ return array('error' => "Server error. Upload directory isn't writable.");
88
+ }
89
+
90
+ if (!$this->filemodel){
91
+ return array('error' => 'No files were uploaded.');
92
+ }
93
+
94
+ $size = $this->filemodel->getSize();
95
+
96
+ if ($size == 0) {
97
+ return array('error' => 'File is empty');
98
+ }
99
+
100
+ if ($size > $this->sizeLimit) {
101
+ return array('error' => 'File is too large');
102
+ }
103
+
104
+ $pathinfo = pathinfo($this->filemodel->getName());
105
+ $filename = $pathinfo['filename'];
106
+ //$filename = md5(uniqid());
107
+ $filename = uniqid();
108
+ $ext = $pathinfo['extension'];
109
+
110
+ if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
111
+ $these = implode(', ', $this->allowedExtensions);
112
+ return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
113
+ }
114
+
115
+ if(!$replaceOldFile){
116
+ /// don't overwrite previous files that were uploaded
117
+ while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
118
+ $filename .= rand(10, 99);
119
+ }
120
+ }
121
+
122
+ if ($this->filemodel->save($uploadDirectory . $filename . '.' . $ext)){
123
+ $imgPathFull = $uploadDirectory . $filename . '.' . $ext;
124
+ $dimensions = Mage::helper('lookbook')->getImageDimensions($imgPathFull);
125
+ if ($this->min_image_width!=0 && $this->min_image_height!=0) {
126
+ if ($dimensions['width'] < $this->min_image_width || $dimensions['height'] < $this->min_image_height)
127
+ {
128
+ unlink($imgPathFull);
129
+ return array('error'=> 'Uploaded file dimensions are less than those specified in the configuration.');
130
+ }
131
+ }
132
+
133
+ if ($this->max_image_width!=0 && $this->max_image_height!=0) {
134
+ if ($dimensions['width'] > $this->max_image_width || $dimensions['height'] > $this->max_image_heigh)
135
+ {
136
+ $resized_image = new Varien_Image($imgPathFull);
137
+ $resized_image->constrainOnly(TRUE);
138
+ $resized_image->keepAspectRatio(TRUE);
139
+ $resized_image->keepTransparency(TRUE);
140
+ $resized_image->resize($this->max_image_width,$this->max_image_height);
141
+ $resized_image->save($imgPathFull);
142
+ $dimensions = Mage::helper('lookbook')->getImageDimensions($imgPathFull);
143
+ }
144
+ }
145
+ return array('success'=>true, 'filename'=>$filename . '.' . $ext, 'dimensions' => $dimensions);
146
+ } else {
147
+ return array('error'=> 'Could not save uploaded file.' .
148
+ 'The upload was cancelled, or server error encountered');
149
+ }
150
+
151
+ }
152
+ }
app/code/local/Altima/Lookbook/Model/Layout/Generate/Observer.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Layout_Generate_Observer {
23
+
24
+ public function addHeadItems($observer) {
25
+ if (Mage::helper('lookbook')->getEnabled()) {
26
+ $data = $observer->getData();
27
+ $page = $data['page'];
28
+ if ($page) {
29
+ $pagecontent = $page->getContent();
30
+ $search_string = '{{block type="lookbook/lookbook" template="lookbook/lookbook.phtml"}}';
31
+ if (preg_match($search_string, $pagecontent)) {
32
+ $updates = $page->getLayoutUpdateXml();
33
+ $newupdates = '<reference name="head">
34
+ <action method="addCss"><stylesheet>lookbook/css/hotspots.css</stylesheet></action>
35
+ <action method="addJs"><script>jquery/jquery-1.7.min.js</script></action>
36
+ <action method="addJs"><script>jquery/jquery.noconflict.js</script></action>
37
+ <action method="addJs"><script>lookbook/slides.min.jquery.js</script></action>
38
+ </reference>';
39
+ $page->setLayoutUpdateXml($updates.$newupdates);
40
+ }
41
+
42
+ }
43
+ }
44
+ }
45
+
46
+ }
app/code/local/Altima/Lookbook/Model/Lookbook.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Lookbook extends Mage_Core_Model_Abstract
23
+ {
24
+ const CACHE_TAG = 'lookbook_free';
25
+ protected $_cacheTag = 'lookbook_free';
26
+
27
+ public function _construct()
28
+ {
29
+ parent::_construct();
30
+ $this->_init('lookbook/lookbook');
31
+ }
32
+
33
+ }
app/code/local/Altima/Lookbook/Model/Mysql4/Lookbook.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Mysql4_Lookbook extends Mage_Core_Model_Mysql4_Abstract
23
+ {
24
+ public function _construct()
25
+ {
26
+ // Note that the lookbook_id refers to the key field in your database table.
27
+ $this->_init('lookbook/lookbook', 'lookbook_id');
28
+ }
29
+ }
app/code/local/Altima/Lookbook/Model/Mysql4/Lookbook/Collection.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Mysql4_Lookbook_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
23
+ {
24
+ public function _construct()
25
+ {
26
+ parent::_construct();
27
+ $this->_init('lookbook/lookbook');
28
+ }
29
+ }
app/code/local/Altima/Lookbook/Model/Status.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Status extends Varien_Object
23
+ {
24
+ const STATUS_ENABLED = 1;
25
+ const STATUS_DISABLED = 2;
26
+
27
+ static public function getOptionArray()
28
+ {
29
+ return array(
30
+ self::STATUS_ENABLED => Mage::helper('lookbook')->__('Enabled'),
31
+ self::STATUS_DISABLED => Mage::helper('lookbook')->__('Disabled')
32
+ );
33
+ }
34
+ }
app/code/local/Altima/Lookbook/Model/Uploadedfileform.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ /**
23
+ * Handle file uploads via regular form post (uses the $_FILES array)
24
+ */
25
+ class Altima_Lookbook_Model_Uploadedfileform {
26
+ /**
27
+ * Save the file to the specified path
28
+ * @return boolean TRUE on success
29
+ */
30
+ function save($path) {
31
+ if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
32
+ return false;
33
+ }
34
+ return true;
35
+ }
36
+ function getName() {
37
+ return $_FILES['qqfile']['name'];
38
+ }
39
+ function getSize() {
40
+ return (int)$_FILES['qqfile']['size'];
41
+ }
42
+ }
43
+
44
+
app/code/local/Altima/Lookbook/Model/Uploadedfilexhr.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Model_Uploadedfilexhr {
23
+
24
+ function save($path) {
25
+ $input = fopen("php://input", "r");
26
+ $temp = tmpfile();
27
+ $realSize = stream_copy_to_stream($input, $temp);
28
+ fclose($input);
29
+
30
+ if ($realSize != $this->getSize()){
31
+ return false;
32
+ }
33
+
34
+ $target = fopen($path, "w");
35
+ fseek($temp, 0, SEEK_SET);
36
+ stream_copy_to_stream($temp, $target);
37
+ fclose($target);
38
+
39
+ return true;
40
+ }
41
+ function getName() {
42
+ return $_GET['qqfile'];
43
+ }
44
+ function getSize() {
45
+ if (isset($_SERVER["CONTENT_LENGTH"])){
46
+ return (int)$_SERVER["CONTENT_LENGTH"];
47
+ } else {
48
+ throw new Exception('Getting content length is not supported.');
49
+ }
50
+ }
51
+ }
52
+
app/code/local/Altima/Lookbook/controllers/Adminhtml/LookbookController.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_Adminhtml_LookbookController extends Mage_Adminhtml_Controller_Action
23
+ {
24
+
25
+ protected function _initAction() {
26
+ $this->loadLayout()
27
+ ->_setActiveMenu('cms')
28
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('Lookbook slides manager'), Mage::helper('adminhtml')->__('Lookbook slides manager'));
29
+
30
+ return $this;
31
+ }
32
+
33
+ public function indexAction() {
34
+ $this->_initAction()
35
+ ->renderLayout();
36
+ }
37
+
38
+ public function editAction() {
39
+ $slides_count = Mage::getModel('lookbook/lookbook')->getCollection()
40
+ ->getSize();
41
+ $id = $this->getRequest()->getParam('id');
42
+ if ($slides_count<5 || $id) {
43
+
44
+ $model = Mage::getModel('lookbook/lookbook')->load($id);
45
+
46
+ if ($model->getId() || $id == 0) {
47
+ $data = Mage::getSingleton('adminhtml/session')->getFormData(true);
48
+ if (!empty($data)) {
49
+ $model->setData($data);
50
+ }
51
+
52
+ Mage::register('lookbook_data', $model);
53
+
54
+ $this->loadLayout();
55
+ $this->_setActiveMenu('cms');
56
+
57
+ $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Lookbook slides manager'), Mage::helper('adminhtml')->__('Lookbook slides manager'));
58
+
59
+ $this->_addContent($this->getLayout()->createBlock('lookbook/adminhtml_lookbook_edit'))
60
+ ->_addLeft($this->getLayout()->createBlock('lookbook/adminhtml_lookbook_edit_tabs'));
61
+
62
+ $this->renderLayout();
63
+ } else {
64
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('lookbook')->__('Slide does not exist'));
65
+ $this->_redirect('*/*/');
66
+ }
67
+ }
68
+ else
69
+ {
70
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('lookbook')->__('Only up to 5 slides could be uploaded in Free Lookbook extension.'));
71
+ $this->_redirect('*/*/');
72
+ }
73
+ }
74
+
75
+ public function newAction() {
76
+ $this->_forward('edit');
77
+ }
78
+
79
+ public function saveAction() {
80
+ if ($data = $this->getRequest()->getPost()) {
81
+
82
+ $model = Mage::getModel('lookbook/lookbook');
83
+ $model->setData($data)
84
+ ->setId($this->getRequest()->getParam('id'));
85
+
86
+ try {
87
+
88
+ if ($model->getId() && isset($data['identifier_create_redirect']))
89
+ {
90
+ $model->setData('save_rewrites_history', (bool)$data['identifier_create_redirect']);
91
+ }
92
+
93
+ $model->save();
94
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('lookbook')->__('Lookbook slide was successfully saved'));
95
+ Mage::getSingleton('adminhtml/session')->setFormData(false);
96
+
97
+ if ($this->getRequest()->getParam('back')) {
98
+ $this->_redirect('*/*/edit', array('id' => $model->getId()));
99
+ return;
100
+ }
101
+ $this->_redirect('*/*/');
102
+ return;
103
+ } catch (Exception $e) {
104
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
105
+ Mage::getSingleton('adminhtml/session')->setFormData($data);
106
+ $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
107
+ return;
108
+ }
109
+ }
110
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('lookbook')->__('Unable to find lookbook slide to save'));
111
+ $this->_redirect('*/*/');
112
+ }
113
+
114
+ public function deleteAction() {
115
+ if( $this->getRequest()->getParam('id') > 0 ) {
116
+ try {
117
+ $model = Mage::getModel('lookbook/lookbook');
118
+
119
+ $model->setId($this->getRequest()->getParam('id'))
120
+ ->delete();
121
+
122
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Lookbook slide was successfully deleted'));
123
+ $this->_redirect('*/*/');
124
+ } catch (Exception $e) {
125
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
126
+ $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
127
+ }
128
+ }
129
+ $this->_redirect('*/*/');
130
+ }
131
+
132
+ public function uploadAction()
133
+ {
134
+
135
+ $upload_dir = Mage::getBaseDir('media').'/lookbook/';
136
+ if (!file_exists($upload_dir)) mkdir($upload_dir, 0755, true);
137
+
138
+ $uploader = Mage::getModel('lookbook/fileuploader');
139
+
140
+ $config_check = $uploader->checkServerSettings();
141
+
142
+ if ($config_check === true){
143
+ $result = $uploader->handleUpload($upload_dir);
144
+ }
145
+ else
146
+ {
147
+ $result = $config_check;
148
+ }
149
+
150
+ // to pass data through iframe you will need to encode all html tags
151
+ $this->getResponse()->setBody(htmlspecialchars(json_encode($result), ENT_NOQUOTES));
152
+ }
153
+
154
+
155
+ public function getproductAction(){
156
+ $sku = $this->getRequest()->getParam('text');
157
+ $product_id = Mage::getModel('catalog/product')->getIdBySku($sku);
158
+ $status = Mage::getModel('catalog/product')->load($product_id)->getStatus();
159
+ if ($product_id) {
160
+ if ($status==1)
161
+ {
162
+ $result= 1;
163
+ }
164
+ else
165
+ {
166
+ $result = "is disabled";
167
+ }
168
+
169
+ }
170
+ else
171
+ {
172
+ $result = "doesn't exists";
173
+ }
174
+ $this->getResponse()->setBody($result);
175
+ }
176
+
177
+ public function massDeleteAction() {
178
+ $lookbookIds = $this->getRequest()->getParam('lookbook');
179
+ if(!is_array($lookbookIds)) {
180
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select slide(s)'));
181
+ } else {
182
+ try {
183
+ foreach ($lookbookIds as $lookbookId) {
184
+ $lookbook = Mage::getModel('lookbook/lookbook')->load($lookbookId);
185
+ $lookbook->delete();
186
+ }
187
+ Mage::getSingleton('adminhtml/session')->addSuccess(
188
+ Mage::helper('adminhtml')->__(
189
+ 'Total of %d record(s) were successfully deleted', count($lookbookIds)
190
+ )
191
+ );
192
+ } catch (Exception $e) {
193
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
194
+ }
195
+ }
196
+ $this->_redirect('*/*/index');
197
+ }
198
+
199
+ public function massStatusAction()
200
+ {
201
+ $lookbookIds = $this->getRequest()->getParam('lookbook');
202
+ if(!is_array($lookbookIds)) {
203
+ Mage::getSingleton('adminhtml/session')->addError($this->__('Please select slide(s)'));
204
+ } else {
205
+ try {
206
+ foreach ($lookbookIds as $lookbookId) {
207
+ $lookbook = Mage::getSingleton('lookbook/lookbook')
208
+ ->load($lookbookId)
209
+ ->setStatus($this->getRequest()->getParam('status'))
210
+ ->setIsMassupdate(true)
211
+ ->save();
212
+ }
213
+ $this->_getSession()->addSuccess(
214
+ $this->__('Total of %d record(s) were successfully updated', count($lookbookIds))
215
+ );
216
+ } catch (Exception $e) {
217
+ $this->_getSession()->addError($e->getMessage());
218
+ }
219
+ }
220
+ $this->_redirect('*/*/index');
221
+ }
222
+
223
+ public function exportCsvAction()
224
+ {
225
+ $fileName = 'lookbook.csv';
226
+ $content = $this->getLayout()->createBlock('lookbook/adminhtml_lookbook_grid')
227
+ ->getCsv();
228
+
229
+ $this->_sendUploadResponse($fileName, $content);
230
+ }
231
+
232
+ public function exportXmlAction()
233
+ {
234
+ $fileName = 'lookbook.xml';
235
+ $content = $this->getLayout()->createBlock('lookbook/adminhtml_lookbook_grid')
236
+ ->getXml();
237
+
238
+ $this->_sendUploadResponse($fileName, $content);
239
+ }
240
+
241
+ protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream')
242
+ {
243
+ $response = $this->getResponse();
244
+ $response->setHeader('HTTP/1.1 200 OK','');
245
+ $response->setHeader('Pragma', 'public', true);
246
+ $response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true);
247
+ $response->setHeader('Content-Disposition', 'attachment; filename='.$fileName);
248
+ $response->setHeader('Last-Modified', date('r'));
249
+ $response->setHeader('Accept-Ranges', 'bytes');
250
+ $response->setHeader('Content-Length', strlen($content));
251
+ $response->setHeader('Content-type', $contentType);
252
+ $response->setBody($content);
253
+ $response->sendResponse();
254
+ die;
255
+ }
256
+ }
app/code/local/Altima/Lookbook/controllers/IndexController.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ class Altima_Lookbook_IndexController extends Mage_Core_Controller_Front_Action
23
+ {
24
+ public function indexAction()
25
+ {
26
+ if (Mage::helper('lookbook')->getEnabled()) {
27
+ $this->loadLayout();
28
+ $this->renderLayout();
29
+ }
30
+ else
31
+ {
32
+ $this->_forward('*/*/noRouteAction');
33
+ }
34
+
35
+ }
36
+
37
+ public function noRouteAction($coreRoute = null)
38
+ {
39
+ //modify this method as you need
40
+ $this->getResponse()->setHeader('HTTP/1.1','404 Not Found');
41
+ $this->getResponse()->setHeader('Status','404 File not found');
42
+ $pageId = Mage::getStoreConfig('web/default/cms_no_route');
43
+ if (!Mage::helper('cms/page')->renderPage($this, $pageId)) {
44
+ $this->_forward('defaultNoRoute');
45
+ }
46
+ }
47
+
48
+ }
app/code/local/Altima/Lookbook/etc/config.xml ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Altima Lookbook Free Extension
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category Altima
17
+ * @package Altima_LookbookFree
18
+ * @author Altima Web Systems http://altimawebsystems.com/
19
+ * @email support@altima.net.au
20
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
21
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
22
+ */
23
+ -->
24
+ <config>
25
+ <modules>
26
+ <Altima_Lookbook>
27
+ <version>0.1.0</version>
28
+ </Altima_Lookbook>
29
+ </modules>
30
+ <frontend>
31
+ <routers>
32
+ <lookbook>
33
+ <use>standard</use>
34
+ <args>
35
+ <module>Altima_Lookbook</module>
36
+ <frontName>lookbook</frontName>
37
+ </args>
38
+ </lookbook>
39
+ </routers>
40
+ <layout>
41
+ <updates>
42
+ <lookbook>
43
+ <file>lookbook.xml</file>
44
+ </lookbook>
45
+ </updates>
46
+ </layout>
47
+ </frontend>
48
+ <admin>
49
+ <routers>
50
+ <lookbook>
51
+ <use>admin</use>
52
+ <args>
53
+ <module>Altima_Lookbook</module>
54
+ <frontName>lookbook</frontName>
55
+ </args>
56
+ </lookbook>
57
+ </routers>
58
+ </admin>
59
+ <adminhtml>
60
+ <menu>
61
+ <cms>
62
+ <children>
63
+ <lookbook translate="title" module="lookbook">
64
+ <title>LookBook Free</title>
65
+ <action>lookbook/adminhtml_lookbook</action>
66
+ </lookbook>
67
+ </children>
68
+ </cms>
69
+ </menu>
70
+ <acl>
71
+ <resources>
72
+ <admin>
73
+ <children>
74
+ <cms>
75
+ <children>
76
+ <lookbook>
77
+ <title>LookBook Free</title>
78
+ </lookbook>
79
+ </children>
80
+ </cms>
81
+ <system>
82
+ <children>
83
+ <config>
84
+ <children>
85
+ <lookbook>
86
+ <title>LookBook Free</title>
87
+ </lookbook>
88
+ </children>
89
+ </config>
90
+ </children>
91
+ </system>
92
+ </children>
93
+ </admin>
94
+ </resources>
95
+ </acl>
96
+ <layout>
97
+ <updates>
98
+ <lookbook>
99
+ <file>lookbook.xml</file>
100
+ </lookbook>
101
+ </updates>
102
+ </layout>
103
+ </adminhtml>
104
+ <default>
105
+ <lookbook>
106
+ <general>
107
+ <enabled>1</enabled>
108
+ <min_image_width>300</min_image_width>
109
+ <min_image_height>400</min_image_height>
110
+ <max_image_width>450</max_image_width>
111
+ <max_image_height>600</max_image_height>
112
+ <max_upload_filesize>2097152</max_upload_filesize>
113
+ <allowed_extensions>jpg,jpeg,png,gif</allowed_extensions>
114
+ </general>
115
+ </lookbook>
116
+ </default>
117
+ <global>
118
+ <models>
119
+ <lookbook>
120
+ <class>Altima_Lookbook_Model</class>
121
+ <resourceModel>lookbook_mysql4</resourceModel>
122
+ </lookbook>
123
+ <lookbook_mysql4>
124
+ <class>Altima_Lookbook_Model_Mysql4</class>
125
+ <entities>
126
+ <lookbook>
127
+ <table>lookbook</table>
128
+ </lookbook>
129
+ </entities>
130
+ </lookbook_mysql4>
131
+ </models>
132
+ <resources>
133
+ <lookbook_setup>
134
+ <setup>
135
+ <module>Altima_Lookbook</module>
136
+ </setup>
137
+ <connection>
138
+ <use>core_setup</use>
139
+ </connection>
140
+ </lookbook_setup>
141
+ <lookbook_write>
142
+ <connection>
143
+ <use>core_write</use>
144
+ </connection>
145
+ </lookbook_write>
146
+ <lookbook_read>
147
+ <connection>
148
+ <use>core_read</use>
149
+ </connection>
150
+ </lookbook_read>
151
+ </resources>
152
+ <blocks>
153
+ <lookbook>
154
+ <class>Altima_Lookbook_Block</class>
155
+ </lookbook>
156
+ </blocks>
157
+ <helpers>
158
+ <lookbook>
159
+ <class>Altima_Lookbook_Helper</class>
160
+ </lookbook>
161
+ </helpers>
162
+ <events>
163
+ <cms_page_render>
164
+ <observers>
165
+ <lookbook_layout_generate_observer>
166
+ <type>singleton</type>
167
+ <class>lookbook/layout_generate_observer</class>
168
+ <method>addHeadItems</method>
169
+ </lookbook_layout_generate_observer>
170
+ </observers>
171
+ </cms_page_render>
172
+ </events>
173
+ </global>
174
+ </config>
app/code/local/Altima/Lookbook/etc/system.xml ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Altima Lookbook Free Extension
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category Altima
17
+ * @package Altima_LookbookFree
18
+ * @author Altima Web Systems http://altimawebsystems.com/
19
+ * @email support@altima.net.au
20
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
21
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
22
+ */
23
+ -->
24
+ <config>
25
+ <tabs>
26
+ <altima translate="label comment" module="lookbook">
27
+ <label>Altima</label>
28
+ <sort_order>500</sort_order>
29
+ </altima>
30
+ </tabs>
31
+ <sections>
32
+ <lookbook translate="label comment" module="lookbook">
33
+ <tab>altima</tab>
34
+ <label>LookBook Free</label>
35
+ <frontend_type>text</frontend_type>
36
+ <sort_order>800</sort_order>
37
+ <show_in_default>1</show_in_default>
38
+ <show_in_website>1</show_in_website>
39
+ <show_in_store>1</show_in_store>
40
+ <groups>
41
+ <general translate="label comment" module="lookbook">
42
+ <label>General Settings</label>
43
+ <frontend_type>text</frontend_type>
44
+ <sort_order>10</sort_order>
45
+ <show_in_default>1</show_in_default>
46
+ <show_in_website>1</show_in_website>
47
+ <show_in_store>1</show_in_store>
48
+ <fields>
49
+ <enabled translate="label">
50
+ <label>Enabled</label>
51
+ <frontend_type>select</frontend_type>
52
+ <source_model>adminhtml/system_config_source_yesno</source_model>
53
+ <sort_order>10</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>1</show_in_store>
57
+ </enabled>
58
+ <min_image_width translate="label">
59
+ <label>Minimal Image Width (px)</label>
60
+ <frontend_type>text</frontend_type>
61
+ <sort_order>20</sort_order>
62
+ <show_in_default>1</show_in_default>
63
+ <show_in_website>1</show_in_website>
64
+ <show_in_store>1</show_in_store>
65
+ <comment><![CDATA[Integer value. Must be less then Maximal Image Width.]]></comment>
66
+ </min_image_width>
67
+ <min_image_height translate="label">
68
+ <label>Minimal Image Height (px)</label>
69
+ <frontend_type>text</frontend_type>
70
+ <sort_order>30</sort_order>
71
+ <show_in_default>1</show_in_default>
72
+ <show_in_website>1</show_in_website>
73
+ <show_in_store>1</show_in_store>
74
+ <comment><![CDATA[Integer value. Must be less then Maximal Image Height.]]></comment>
75
+ </min_image_height>
76
+ <max_image_width translate="label">
77
+ <label>Maximal Image Width (px)</label>
78
+ <frontend_type>text</frontend_type>
79
+ <sort_order>40</sort_order>
80
+ <show_in_default>1</show_in_default>
81
+ <show_in_website>1</show_in_website>
82
+ <show_in_store>1</show_in_store>
83
+ <comment><![CDATA[Integer value. Must be greater then Minimal Image Width.]]></comment>
84
+ </max_image_width>
85
+ <max_image_height translate="label">
86
+ <label>Maximal Image Height (px)</label>
87
+ <frontend_type>text</frontend_type>
88
+ <sort_order>50</sort_order>
89
+ <show_in_default>1</show_in_default>
90
+ <show_in_website>1</show_in_website>
91
+ <show_in_store>1</show_in_store>
92
+ <comment><![CDATA[Integer value. Must be greater then Minimal Image Height.]]></comment>
93
+ </max_image_height>
94
+ <max_upload_filesize translate="label">
95
+ <label>Uploaded file max size (bytes)</label>
96
+ <frontend_type>text</frontend_type>
97
+ <sort_order>60</sort_order>
98
+ <show_in_default>1</show_in_default>
99
+ <show_in_website>1</show_in_website>
100
+ <show_in_store>1</show_in_store>
101
+ <comment><![CDATA[Integer value. Must be less then upload_max_filesize and post_max_size in php.ini]]></comment>
102
+ </max_upload_filesize>
103
+ <allowed_extensions translate="label">
104
+ <label>Allowed extensions</label>
105
+ <frontend_type>text</frontend_type>
106
+ <sort_order>70</sort_order>
107
+ <show_in_default>1</show_in_default>
108
+ <show_in_website>1</show_in_website>
109
+ <show_in_store>1</show_in_store>
110
+ <comment><![CDATA[Comma separated file extensions. Example, "jpg,gif,png"]]></comment>
111
+ </allowed_extensions>
112
+ </fields>
113
+ </general>
114
+ </groups>
115
+ </lookbook>
116
+ </sections>
117
+ </config>
app/code/local/Altima/Lookbook/sql/lookbook_setup/mysql4-install-0.1.0.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+
23
+ $installer = $this;
24
+
25
+ $installer->startSetup();
26
+
27
+ $installer->run("
28
+
29
+ -- DROP TABLE IF EXISTS {$this->getTable('lookbook')};
30
+ CREATE TABLE {$this->getTable('lookbook')} (
31
+ `lookbook_id` int(11) unsigned NOT NULL auto_increment,
32
+ `name` varchar(255) NOT NULL default '',
33
+ `image` varchar(255) NOT NULL default '',
34
+ `hotspots` text NOT NULL default '',
35
+ `position` smallint(5) unsigned NOT NULL,
36
+ `status` smallint(6) NOT NULL default '0',
37
+ PRIMARY KEY (`lookbook_id`),
38
+ KEY `IDX_LOOKBOOK_LOOKBOOK_ID` (`lookbook_id`)
39
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
40
+
41
+ ");
42
+
43
+ $installer->setConfigData('lookbook/general/hotspot_icon/','default/hotspot-icon.png');
44
+
45
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/lookbook.xml ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Altima Lookbook Free Extension
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category Altima
17
+ * @package Altima_LookbookFree
18
+ * @author Altima Web Systems http://altimawebsystems.com/
19
+ * @email support@altima.net.au
20
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
21
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
22
+ */
23
+ -->
24
+ <layout version="0.1.0">
25
+ <lookbook_adminhtml_lookbook_index>
26
+ <reference name="content">
27
+ <block type="lookbook/adminhtml_lookbook" name="lookbook" />
28
+ </reference>
29
+ </lookbook_adminhtml_lookbook_index>
30
+ <lookbook_adminhtml_lookbook_edit>
31
+ <reference name="head">
32
+ <action method="addCss"><stylesheet>lookbook/css/annotation.css</stylesheet></action>
33
+ <action method="addCss"><stylesheet>lookbook/css/fileuploader.css</stylesheet></action>
34
+ <action method="addJs"><script>jquery/jquery-1.7.min.js</script></action>
35
+ <action method="addJs"><script>jquery/jquery.noconflict.js</script></action>
36
+ <action method="addJs"><script>lookbook/jquery-ui-1.8.17.js</script></action>
37
+ <action method="addJs"><script>lookbook/jquery.annotate.js</script></action>
38
+ <action method="addJs"><script>lookbook/fileuploader.js</script></action>
39
+ <action method="addJs"><script>lookbook/json2.min.js</script></action>
40
+ </reference>
41
+ </lookbook_adminhtml_lookbook_edit>
42
+ </layout>
app/design/frontend/base/default/layout/lookbook.xml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Altima Lookbook Free Extension
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category Altima
17
+ * @package Altima_LookbookFree
18
+ * @author Altima Web Systems http://altimawebsystems.com/
19
+ * @email support@altima.net.au
20
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
21
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
22
+ */
23
+ -->
24
+ <layout version="0.1.0">
25
+ <default>
26
+ </default>
27
+ <lookbook_index_index>
28
+ <reference name="head">
29
+ <action method="addCss"><stylesheet>lookbook/css/hotspots.css</stylesheet></action>
30
+ <action method="addJs"><script>jquery/jquery-1.7.min.js</script></action>
31
+ <action method="addJs"><script>jquery/jquery.noconflict.js</script></action>
32
+ <action method="addJs"><script>lookbook/slides.min.jquery.js</script></action>
33
+ </reference>
34
+ <reference name="content">
35
+ <block type="lookbook/lookbook" name="lookbook" template="lookbook/lookbook.phtml" />
36
+ </reference>
37
+ </lookbook_index_index>
38
+ </layout>
app/design/frontend/base/default/template/lookbook/lookbook.phtml ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Altima Lookbook Free Extension
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 Altima
16
+ * @package Altima_LookbookFree
17
+ * @author Altima Web Systems http://altimawebsystems.com/
18
+ * @email support@altima.net.au
19
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
20
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
21
+ */
22
+ $helper = Mage::helper('lookbook');
23
+
24
+ if ($helper->getEnabled()) :
25
+
26
+ $makets = $this->getCollection();
27
+
28
+ $width = $helper->getMaxImageWidth();
29
+ $height = $helper->getMaxImageHeight();
30
+ $skin_img_folder = $this->getSkinUrl('lookbook/images/');
31
+ $hotspots = array();
32
+
33
+ if ($makets->getSize()) :
34
+ ?>
35
+ <style type="text/css">
36
+ #lookbook {
37
+ width:<?php echo $width+40;?>px;
38
+ height:<?php echo $height+70;?>px;
39
+ }
40
+
41
+ .slides_container {
42
+ width:<?php echo $width?>px;
43
+ }
44
+
45
+ .slides_container div.slide {
46
+ width:<?php echo $width?>px;
47
+ height:<?php echo $height?>px;
48
+ }
49
+
50
+ #slides .next,#slides .prev {
51
+ top:<?php echo $height/2-21?>px;
52
+ left:-24px;
53
+ }
54
+
55
+ #slides .next {
56
+ left:<?php echo $width?>px;
57
+ }
58
+
59
+ .caption {
60
+ width:<?php echo $width?>px;
61
+ }
62
+
63
+ .pagination {
64
+ width:<?php echo 16*$makets->getSize()?>px;
65
+ }
66
+ </style>
67
+ <div id="lookbook">
68
+ <div id="slides" class="slides">
69
+ <div class="slides_container">
70
+ <?php foreach ($makets as $image): ?>
71
+ <div class="slide">
72
+ <?php echo base64_decode('PGRpdiBpZD0iYWR2X2xpbmsiPjxkaXY+UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vYWx0aW1hd2Vic3lzdGVtcy5jb20vIj5BbHRpbWE8L2E+PC9kaXY+PC9kaXY+');?>
73
+ <img src="<?php echo $helper->getResizedUrl($image->getImage(), $width, $height);?>" alt="Slide <?php echo $image->getId();?>"/>
74
+ <div class="caption" style="bottom:0;">
75
+ <p><?php echo $image->getName();?></p>
76
+ </div>
77
+ </div>
78
+ <?php $hotspots[] = $helper->getHotspotsWithProductDetails($image->getHotspots()); ?>
79
+ <?php endforeach; ?>
80
+ </div>
81
+ <a href="#" class="prev"><img src="<?php echo $skin_img_folder;?>arrow-prev.png" width="24" height="43" alt="Arrow Prev"/></a>
82
+ <a href="#" class="next"><img src="<?php echo $skin_img_folder;?>arrow-next.png" width="24" height="43" alt="Arrow Next"/></a>
83
+ </div>
84
+ </div>
85
+ <script type="text/javascript">
86
+ //<![CDATA[
87
+ $j(document).ready(function(){
88
+ $j('#lookbook .slides').slides({
89
+ preload: true,
90
+ preloadImage: '<?php echo $skin_img_folder;?>loading.gif',
91
+ play: 5000,
92
+ pause: 2500,
93
+ hoverPause: true,
94
+ hotspots:<?php echo json_encode($hotspots);?>,
95
+ animationStart: function(current){
96
+ $j('#lookbook .caption').animate({
97
+ bottom:-35
98
+ },100);
99
+ $j('#lookbook .hotspot:visible').each(function() {
100
+ $j(this).remove();
101
+ });
102
+ },
103
+ animationComplete: function(current){
104
+ $j('#lookbook .caption').animate({
105
+ bottom:0
106
+ },200);
107
+ var spots = this.hotspots[current-1];
108
+ SetHotspots(spots);
109
+ },
110
+ slidesLoaded: function() {
111
+ $j('#lookbook .caption').animate({
112
+ bottom:0
113
+ },200);
114
+ var spots = this.hotspots[0];
115
+ SetHotspots(spots);
116
+ }
117
+ });
118
+
119
+ function SetHotspots(hotspots) {
120
+ if (!hotspots) return false;
121
+ var i=0;
122
+ hotspots.each(function() {
123
+ if (!document.getElementById(hotspots[i].id)) {
124
+ $j('#lookbook .slide:visible').append('<div class="hotspot" id="'+hotspots[i].id+'" style="left:'+hotspots[i].left+'px; top:'+hotspots[i].top+'px; width:'+hotspots[i].width+'px; height:'+hotspots[i].height+'px;">'+hotspots[i].text+'</div>');
125
+
126
+ var infoblock = $j('#lookbook .slide:visible #'+hotspots[i].id).find('.product-info');
127
+ var slide = $j('#lookbook .slide:visible');
128
+ var imgwidth = slide.width();
129
+ var infowidth = infoblock.width();
130
+ var hspt_width_hf = parseInt(hotspots[i].width/2);
131
+ var leftposition = hotspots[i].left+hspt_width_hf+7;
132
+ infoblock.find('.info-icon').css('left',hspt_width_hf+'px');
133
+ if (((leftposition + infowidth + 10)> imgwidth) && (leftposition>(imgwidth-leftposition)))
134
+ {
135
+ if ( $j.browser.msie && $j.browser.version=='8.0') {
136
+ if (leftposition-5<infowidth) {
137
+ infoblock.css('width', leftposition-20 +'px');
138
+ infowidth = infoblock.width();
139
+ }
140
+ infoblock.css('left', hspt_width_hf-7-infowidth-2*parseInt(infoblock.css('padding-left'))+'px');
141
+ }
142
+ else
143
+ {
144
+ infoblock.css('left', '');
145
+ infoblock.css('right', hspt_width_hf+7+'px');
146
+ }
147
+ if (leftposition-5<infowidth) {
148
+ infoblock.css('width', leftposition-20 +'px');
149
+ infowidth = infoblock.width();
150
+ }
151
+ }
152
+ else
153
+ {
154
+ infoblock.css('left', hspt_width_hf+7 + 'px');
155
+ if ((imgwidth-leftposition-5)<infowidth) {
156
+ infoblock.css('width', imgwidth-leftposition-20 +'px');
157
+ infowidth = infoblock.width();
158
+ }
159
+ }
160
+
161
+ var imgheight = slide.height();
162
+ var infoheight = infoblock.height();
163
+ var hspt_height_hf = parseInt(hotspots[i].height/2);
164
+ var topposition = hotspots[i].top+hspt_height_hf;
165
+ if (((topposition + infoheight + 20)> imgheight) && (topposition>(imgheight-topposition)))
166
+ {
167
+ if ( $j.browser.msie && $j.browser.version=='8.0') {
168
+ if (topposition-5<infoheight) {
169
+ infoblock.css('height', topposition-10 +'px');
170
+ infoheight = infoblock.height();
171
+ }
172
+ infoblock.css('top', hspt_height_hf-infoheight-2*parseInt(infoblock.css('padding-top'))+'px');
173
+ }
174
+ else
175
+ {
176
+ infoblock.css('top', '');
177
+ infoblock.css('bottom', hspt_height_hf+'px');
178
+ }
179
+ if (topposition-5<infoheight) {
180
+ infoblock.css('height', topposition-10 +'px');
181
+ infoheight = infoblock.height();
182
+ }
183
+ }
184
+ else
185
+ {
186
+ infoblock.css('top', hspt_height_hf + 'px');
187
+ if ((imgheight-topposition-5)<infoheight) {
188
+ infoblock.css('height', imgheight-topposition-10 +'px');
189
+ infoheight = infoblock.height();
190
+ }
191
+ }
192
+ i++;
193
+ }
194
+ });
195
+ };
196
+ });
197
+ //]]>
198
+ </script>
199
+ <?php endif;?>
200
+ <?php endif;?>
201
+
app/etc/modules/Altima_Lookbook.xml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Altima Lookbook Free Extension
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category Altima
17
+ * @package Altima_LookbookFree
18
+ * @author Altima Web Systems http://altimawebsystems.com/
19
+ * @email support@altima.net.au
20
+ * @copyright Copyright (c) 2012 Altima Web Systems (http://altimawebsystems.com/)
21
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
22
+ */
23
+ -->
24
+ <config>
25
+ <modules>
26
+ <Altima_Lookbook>
27
+ <active>true</active>
28
+ <codePool>local</codePool>
29
+ <depends>
30
+ <Mage_Core/>
31
+ <Mage_Adminhtml/>
32
+ <Mage_Catalog/>
33
+ </depends>
34
+ </Altima_Lookbook>
35
+ </modules>
36
+ </config>
js/jquery/jquery-1.7.min.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*! jQuery v1.7 jquery.com | jquery.org/license */
2
+ (function(a,b){function cA(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cx(a){if(!cm[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cn||(cn=c.createElement("iframe"),cn.frameBorder=cn.width=cn.height=0),b.appendChild(cn);if(!co||!cn.createElement)co=(cn.contentWindow||cn.contentDocument).document,co.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),co.close();d=co.createElement(a),co.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cn)}cm[a]=e}return cm[a]}function cw(a,b){var c={};f.each(cs.concat.apply([],cs.slice(0,b)),function(){c[this]=a});return c}function cv(){ct=b}function cu(){setTimeout(cv,0);return ct=f.now()}function cl(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ck(){try{return new a.XMLHttpRequest}catch(b){}}function ce(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cd(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function cc(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bG.test(a)?d(a,e):cc(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)cc(a+"["+e+"]",b[e],c,d);else d(a,b)}function cb(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function ca(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bV,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=ca(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=ca(a,c,d,e,"*",g));return l}function b_(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bR),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bE(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bz:bA;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bB(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function br(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bi,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bq(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bp(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bp)}function bp(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bo(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bn(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bm(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bl(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a){var b=Y.split(" "),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(){return!0}function M(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.add(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return a!=null&&m.test(a)&&!isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(I)return I.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())}),typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return e});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){return i.done.apply(i,arguments).fail.apply(i,arguments)},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,unknownElems:!!a.getElementsByTagName("nav").length,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",enctype:!!c.createElement("form").enctype,submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.lastChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-999px",top:"-999px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;f(function(){var a,b,d,e,g,h,i=1,j="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",l="visibility:hidden;border:0;",n="style='"+j+"border:5px solid #000;padding:0;'",p="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>";m=c.getElementsByTagName("body")[0];!m||(a=c.createElement("div"),a.style.cssText=l+"width:0;height:0;position:static;top:0;margin-top:"+i+"px",m.insertBefore(a,m.firstChild),o=c.createElement("div"),o.style.cssText=j+l,o.innerHTML=p,a.appendChild(o),b=o.firstChild,d=b.firstChild,g=b.nextSibling.firstChild.firstChild,h={doesNotAddBorder:d.offsetTop!==5,doesAddBorderForTableAndCells:g.offsetTop===5},d.style.position="fixed",d.style.top="20px",h.fixedPosition=d.offsetTop===20||d.offsetTop===15,d.style.position=d.style.top="",b.style.overflow="hidden",b.style.position="relative",h.subtractsBorderForOverflowNotVisible=d.offsetTop===-5,h.doesNotIncludeMarginInBodyOffset=m.offsetTop!==i,m.removeChild(a),o=a=null,f.extend(k,h))}),o.innerHTML="",n.removeChild(o),o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[f.expando]:a[f.expando]&&f.expando,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[f.expando]=n=++f.uuid:n=f.expando),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[f.expando]:f.expando;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)?b=b:b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" "));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];if(!arguments.length){if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}return b}e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!a||j===3||j===8||j===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g},removeAttr:function(a,b){var c,d,e,g,h=0;if(a.nodeType===1){d=(b||"").split(p),g=d.length;for(;h<g;h++)e=d[h].toLowerCase(),c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1)}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return b;h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/\.(.*)$/,A=/^(?:textarea|input|select)$/i,B=/\./g,C=/ /g,D=/[^\w\s.|`]/g,E=/^([^\.]*)?(?:\.(.+))?$/,F=/\bhover(\.\S+)?/,G=/^key/,H=/^(?:mouse|contextmenu)|click/,I=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,J=function(a){var b=I.exec(a);b&&
3
+ (b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},K=function(a,b){return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||a.id===b[2])&&(!b[3]||b[3].test(a.className))},L=function(a){return f.event.special.hover?a:a.replace(F,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=L(c).split(" ");for(k=0;k<c.length;k++){l=E.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,namespace:n.join(".")},p),g&&(o.quick=J(g),!o.quick&&f.expr.match.POS.test(g)&&(o.isPositional=!0)),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d){var e=f.hasData(a)&&f._data(a),g,h,i,j,k,l,m,n,o,p,q;if(!!e&&!!(m=e.events)){b=L(b||"").split(" ");for(g=0;g<b.length;g++){h=E.exec(b[g])||[],i=h[1],j=h[2];if(!i){j=j?"."+j:"";for(l in m)f.event.remove(a,l+j,c,d);return}n=f.event.special[i]||{},i=(d?n.delegateType:n.bindType)||i,p=m[i]||[],k=p.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;if(c||j||d||n.remove)for(l=0;l<p.length;l++){q=p[l];if(!c||c.guid===q.guid)if(!j||j.test(q.namespace))if(!d||d===q.selector||d==="**"&&q.selector)p.splice(l--,1),q.selector&&p.delegateCount--,n.remove&&n.remove.call(a,q)}else p.length=0;p.length===0&&k!==p.length&&((!n.teardown||n.teardown.call(a,j)===!1)&&f.removeEvent(a,i,e.handle),delete m[i])}f.isEmptyObject(m)&&(o=e.handle,o&&(o.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"",(g||!e)&&c.preventDefault();if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,n=null;for(m=e.parentNode;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length;l++){m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d);if(c.isPropagationStopped())break}c.type=h,c.isDefaultPrevented()||(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=(f.event.special[c.type]||{}).handle,j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click"))for(m=c.target;m!=this;m=m.parentNode||this){o={},q=[];for(k=0;k<e;k++)r=d[k],s=r.selector,t=o[s],r.isPositional?t=(t||(o[s]=f(s))).index(m)>=0:t===b&&(t=o[s]=r.quick?K(m,r.quick):f(m).is(s)),t&&q.push(r);q.length&&j.push({elem:m,matches:q})}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){p=j[k],c.currentTarget=p.elem;for(l=0;l<p.matches.length&&!c.isImmediatePropagationStopped();l++){r=p.matches[l];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=(i||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},focus:{delegateType:"focusin",noBubble:!0},blur:{delegateType:"focusout",noBubble:!0},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?N:M):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=N;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=N;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=N,this.stopPropagation()},isDefaultPrevented:M,isPropagationStopped:M,isImmediatePropagationStopped:M},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]=f.event.special[b]={delegateType:b,bindType:b,handle:function(a){var b=this,c=a.relatedTarget,d=a.handleObj,e=d.selector,g,h;if(!c||d.origType===a.type||c!==b&&!f.contains(b,c))g=a.type,a.type=d.origType,h=d.handler.apply(this,arguments),a.type=g;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(A.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;A.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return A.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=M;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=M);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),G.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),H.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw"Syntax error, unrecognized expression: "+a};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?T.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",Z=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,_=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,ba=/<([\w:]+)/,bb=/<tbody/i,bc=/<|&#?\w+;/,bd=/<(?:script|style)/i,be=/<(?:script|object|embed|option|style)/i,bf=new RegExp("<(?:"+Y.replace(" ","|")+")","i"),bg=/checked\s*(?:[^=]|=\s*.checked.)/i,bh=/\/(java|ecma)script/i,bi=/^\s*<!(?:\[CDATA\[|\-\-)/,bj={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bk=X(c);bj.optgroup=bj.option,bj.tbody=bj.tfoot=bj.colgroup=bj.caption=bj.thead,bj.th=bj.td,f.support.htmlSerialize||(bj._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after"
4
+ ,arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Z,""):null;if(typeof a=="string"&&!bd.test(a)&&(f.support.leadingWhitespace||!$.test(a))&&!bj[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(_,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bg.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bl(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,br)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!be.test(j)&&(f.support.checkClone||!bg.test(j))&&!f.support.unknownElems&&bf.test(j)&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bn(a,d),e=bo(a),g=bo(d);for(h=0;e[h];++h)g[h]&&bn(e[h],g[h])}if(b){bm(a,d);if(c){e=bo(a),g=bo(d);for(h=0;e[h];++h)bm(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bc.test(k))k=b.createTextNode(k);else{k=k.replace(_,"<$1></$2>");var l=(ba.exec(k)||["",""])[1].toLowerCase(),m=bj[l]||bj._default,n=m[0],o=b.createElement("div");b===c?bk.appendChild(o):X(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=bb.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&$.test(k)&&o.insertBefore(b.createTextNode($.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bq(k[i]);else bq(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bh.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bs=/alpha\([^)]*\)/i,bt=/opacity=([^)]*)/,bu=/([A-Z]|^ms)/g,bv=/^-?\d+(?:px)?$/i,bw=/^-?\d/,bx=/^([\-+])=([\-+.\de]+)/,by={position:"absolute",visibility:"hidden",display:"block"},bz=["Left","Right"],bA=["Top","Bottom"],bB,bC,bD;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bB(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bx.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bB)return bB(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bE(a,b,d);f.swap(a,by,function(){e=bE(a,b,d)});return e}},set:function(a,b){if(!bv.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bt.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bs,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bs.test(g)?g.replace(bs,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bB(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bC=function(a,c){var d,e,g;c=c.replace(bu,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bD=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bv.test(f)&&bw.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bB=bC||bD,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bF=/%20/g,bG=/\[\]$/,bH=/\r?\n/g,bI=/#.*$/,bJ=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bK=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bL=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bM=/^(?:GET|HEAD)$/,bN=/^\/\//,bO=/\?/,bP=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bQ=/^(?:select|textarea)/i,bR=/\s+/,bS=/([?&])_=[^&]*/,bT=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bU=f.fn.load,bV={},bW={},bX,bY,bZ=["*/"]+["*"];try{bX=e.href}catch(b$){bX=c.createElement("a"),bX.href="",bX=bX.href}bY=bT.exec(bX.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bU)return bU.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bP,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bQ.test(this.nodeName)||bK.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bH,"\r\n")}}):{name:b.name,value:c.replace(bH,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?cb(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),cb(a,b);return a},ajaxSettings:{url:bX,isLocal:bL.test(bY[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bZ},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:b_(bV),ajaxTransport:b_(bW),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cd(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=ce(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bJ.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bI,"").replace(bN,bY[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bR),d.crossDomain==null&&(r=bT.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bY[1]&&r[2]==bY[2]&&(r[3]||(r[1]==="http:"?80:443))==(bY[3]||(bY[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),ca(bV,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bM.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bO.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bS,"$1_="+x);d.url=y+(y===d.url?(bO.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bZ+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=ca(bW,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)cc(g,a[g],c,e);return d.join("&").replace(bF,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cf=f.now(),cg=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cf++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cg.test(b.url)||e&&cg.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cg,l),b.url===j&&(e&&(k=k.replace(cg,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ch=a.ActiveXObject?function(){for(var a in cj)cj[a](0,1)}:!1,ci=0,cj;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ck()||cl()}:ck,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ch&&delete cj[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++ci,ch&&(cj||(cj={},f(a).unload(ch)),cj[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cm={},cn,co,cp=/^(?:toggle|show|hide)$/,cq=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cr,cs=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],ct;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cw("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cx(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cw("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cw("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cx(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cp.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=cq.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cw("show",1),slideUp:cw("hide",1),slideToggle:cw("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=ct||cu(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cr&&(cr=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=ct||cu(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cr),cr=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now))}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cy=/^t(?:able|d|h)$/i,cz=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cA(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cy.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cz.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cz.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cA(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cA(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
js/jquery/jquery.noconflict.js ADDED
@@ -0,0 +1 @@
 
1
+ var $j = jQuery.noConflict();
js/lookbook/fileuploader.js ADDED
@@ -0,0 +1,1251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * http://github.com/valums/file-uploader
3
+ *
4
+ * Multiple file upload component with progress-bar, drag-and-drop.
5
+ * © 2010 Andrew Valums ( andrew(at)valums.com )
6
+ *
7
+ * Licensed under GNU GPL 2 or later and GNU LGPL 2 or later, see license.txt.
8
+ */
9
+
10
+ //
11
+ // Helper functions
12
+ //
13
+
14
+ var qq = qq || {};
15
+
16
+ /**
17
+ * Adds all missing properties from second obj to first obj
18
+ */
19
+ qq.extend = function(first, second){
20
+ for (var prop in second){
21
+ first[prop] = second[prop];
22
+ }
23
+ };
24
+
25
+ /**
26
+ * Searches for a given element in the array, returns -1 if it is not present.
27
+ * @param {Number} [from] The index at which to begin the search
28
+ */
29
+ qq.indexOf = function(arr, elt, from){
30
+ if (arr.indexOf) return arr.indexOf(elt, from);
31
+
32
+ from = from || 0;
33
+ var len = arr.length;
34
+
35
+ if (from < 0) from += len;
36
+
37
+ for (; from < len; from++){
38
+ if (from in arr && arr[from] === elt){
39
+ return from;
40
+ }
41
+ }
42
+ return -1;
43
+ };
44
+
45
+ qq.getUniqueId = (function(){
46
+ var id = 0;
47
+ return function(){ return id++; };
48
+ })();
49
+
50
+ //
51
+ // Events
52
+
53
+ qq.attach = function(element, type, fn){
54
+ if (element.addEventListener){
55
+ element.addEventListener(type, fn, false);
56
+ } else if (element.attachEvent){
57
+ element.attachEvent('on' + type, fn);
58
+ }
59
+ };
60
+ qq.detach = function(element, type, fn){
61
+ if (element.removeEventListener){
62
+ element.removeEventListener(type, fn, false);
63
+ } else if (element.attachEvent){
64
+ element.detachEvent('on' + type, fn);
65
+ }
66
+ };
67
+
68
+ qq.preventDefault = function(e){
69
+ if (e.preventDefault){
70
+ e.preventDefault();
71
+ } else{
72
+ e.returnValue = false;
73
+ }
74
+ };
75
+
76
+ //
77
+ // Node manipulations
78
+
79
+ /**
80
+ * Insert node a before node b.
81
+ */
82
+ qq.insertBefore = function(a, b){
83
+ b.parentNode.insertBefore(a, b);
84
+ };
85
+ qq.remove = function(element){
86
+ element.parentNode.removeChild(element);
87
+ };
88
+
89
+ qq.contains = function(parent, descendant){
90
+ // compareposition returns false in this case
91
+ if (parent == descendant) return true;
92
+
93
+ if (parent.contains){
94
+ return parent.contains(descendant);
95
+ } else {
96
+ return !!(descendant.compareDocumentPosition(parent) & 8);
97
+ }
98
+ };
99
+
100
+ /**
101
+ * Creates and returns element from html string
102
+ * Uses innerHTML to create an element
103
+ */
104
+ qq.toElement = (function(){
105
+ var div = document.createElement('div');
106
+ return function(html){
107
+ div.innerHTML = html;
108
+ var element = div.firstChild;
109
+ div.removeChild(element);
110
+ return element;
111
+ };
112
+ })();
113
+
114
+ //
115
+ // Node properties and attributes
116
+
117
+ /**
118
+ * Sets styles for an element.
119
+ * Fixes opacity in IE6-8.
120
+ */
121
+ qq.css = function(element, styles){
122
+ if (styles.opacity != null){
123
+ if (typeof element.style.opacity != 'string' && typeof(element.filters) != 'undefined'){
124
+ styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')';
125
+ }
126
+ }
127
+ qq.extend(element.style, styles);
128
+ };
129
+ qq.hasClass = function(element, name){
130
+ var re = new RegExp('(^| )' + name + '( |$)');
131
+ return re.test(element.className);
132
+ };
133
+ qq.addClass = function(element, name){
134
+ if (!qq.hasClass(element, name)){
135
+ element.className += ' ' + name;
136
+ }
137
+ };
138
+ qq.removeClass = function(element, name){
139
+ var re = new RegExp('(^| )' + name + '( |$)');
140
+ element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, "");
141
+ };
142
+ qq.setText = function(element, text){
143
+ element.innerText = text;
144
+ element.textContent = text;
145
+ };
146
+
147
+ //
148
+ // Selecting elements
149
+
150
+ qq.children = function(element){
151
+ var children = [],
152
+ child = element.firstChild;
153
+
154
+ while (child){
155
+ if (child.nodeType == 1){
156
+ children.push(child);
157
+ }
158
+ child = child.nextSibling;
159
+ }
160
+
161
+ return children;
162
+ };
163
+
164
+ qq.getByClass = function(element, className){
165
+ if (element.querySelectorAll){
166
+ return element.querySelectorAll('.' + className);
167
+ }
168
+
169
+ var result = [];
170
+ var candidates = element.getElementsByTagName("*");
171
+ var len = candidates.length;
172
+
173
+ for (var i = 0; i < len; i++){
174
+ if (qq.hasClass(candidates[i], className)){
175
+ result.push(candidates[i]);
176
+ }
177
+ }
178
+ return result;
179
+ };
180
+
181
+ /**
182
+ * obj2url() takes a json-object as argument and generates
183
+ * a querystring. pretty much like jQuery.param()
184
+ *
185
+ * how to use:
186
+ *
187
+ * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');`
188
+ *
189
+ * will result in:
190
+ *
191
+ * `http://any.url/upload?otherParam=value&a=b&c=d`
192
+ *
193
+ * @param Object JSON-Object
194
+ * @param String current querystring-part
195
+ * @return String encoded querystring
196
+ */
197
+ qq.obj2url = function(obj, temp, prefixDone){
198
+ var uristrings = [],
199
+ prefix = '&',
200
+ add = function(nextObj, i){
201
+ var nextTemp = temp
202
+ ? (/\[\]$/.test(temp)) // prevent double-encoding
203
+ ? temp
204
+ : temp+'['+i+']'
205
+ : i;
206
+ if ((nextTemp != 'undefined') && (i != 'undefined')) {
207
+ uristrings.push(
208
+ (typeof nextObj === 'object')
209
+ ? qq.obj2url(nextObj, nextTemp, true)
210
+ : (Object.prototype.toString.call(nextObj) === '[object Function]')
211
+ ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj())
212
+ : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj)
213
+ );
214
+ }
215
+ };
216
+
217
+ if (!prefixDone && temp) {
218
+ prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?';
219
+ uristrings.push(temp);
220
+ uristrings.push(qq.obj2url(obj));
221
+ } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj != 'undefined') ) {
222
+ // we wont use a for-in-loop on an array (performance)
223
+ for (var i = 0, len = obj.length; i < len; ++i){
224
+ add(obj[i], i);
225
+ }
226
+ } else if ((typeof obj != 'undefined') && (obj !== null) && (typeof obj === "object")){
227
+ // for anything else but a scalar, we will use for-in-loop
228
+ for (var i in obj){
229
+ add(obj[i], i);
230
+ }
231
+ } else {
232
+ uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj));
233
+ }
234
+
235
+ return uristrings.join(prefix)
236
+ .replace(/^&/, '')
237
+ .replace(/%20/g, '+');
238
+ };
239
+
240
+ //
241
+ //
242
+ // Uploader Classes
243
+ //
244
+ //
245
+
246
+ var qq = qq || {};
247
+
248
+ /**
249
+ * Creates upload button, validates upload, but doesn't create file list or dd.
250
+ */
251
+ qq.FileUploaderBasic = function(o){
252
+ this._options = {
253
+ // set to true to see the server response
254
+ debug: false,
255
+ action: '/server/upload',
256
+ params: {},
257
+ button: null,
258
+ buttontext: 'Upload file',
259
+ multiple: true,
260
+ maxConnections: 3,
261
+ // validation
262
+ allowedExtensions: [],
263
+ sizeLimit: 0,
264
+ minSizeLimit: 0,
265
+ // events
266
+ // return false to cancel submit
267
+ onSubmit: function(id, fileName){},
268
+ onProgress: function(id, fileName, loaded, total){},
269
+ onComplete: function(id, fileName, responseJSON){},
270
+ onCancel: function(id, fileName){},
271
+ // messages
272
+ messages: {
273
+ typeError: "{file} has invalid extension. Only {extensions} are allowed.",
274
+ sizeError: "{file} is too large, maximum file size is {sizeLimit}.",
275
+ minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.",
276
+ emptyError: "{file} is empty, please select files again without it.",
277
+ onLeave: "The files are being uploaded, if you leave now the upload will be cancelled."
278
+ },
279
+ showMessage: function(message){
280
+ alert(message);
281
+ }
282
+ };
283
+ qq.extend(this._options, o);
284
+
285
+ // number of files being uploaded
286
+ this._filesInProgress = 0;
287
+ this._handler = this._createUploadHandler();
288
+
289
+ if (this._options.button){
290
+ this._button = this._createUploadButton(this._options.button);
291
+ }
292
+
293
+ this._preventLeaveInProgress();
294
+ };
295
+
296
+ qq.FileUploaderBasic.prototype = {
297
+ setParams: function(params){
298
+ this._options.params = params;
299
+ },
300
+ getInProgress: function(){
301
+ return this._filesInProgress;
302
+ },
303
+ _createUploadButton: function(element){
304
+ var self = this;
305
+
306
+ return new qq.UploadButton({
307
+ element: element,
308
+ multiple: this._options.multiple && qq.UploadHandlerXhr.isSupported(),
309
+ onChange: function(input){
310
+ self._onInputChange(input);
311
+ }
312
+ });
313
+ },
314
+ _createUploadHandler: function(){
315
+ var self = this,
316
+ handlerClass;
317
+
318
+ if(qq.UploadHandlerXhr.isSupported()){
319
+ handlerClass = 'UploadHandlerXhr';
320
+ } else {
321
+ handlerClass = 'UploadHandlerForm';
322
+ }
323
+
324
+ var handler = new qq[handlerClass]({
325
+ debug: this._options.debug,
326
+ action: this._options.action,
327
+ maxConnections: this._options.maxConnections,
328
+ onProgress: function(id, fileName, loaded, total){
329
+ self._onProgress(id, fileName, loaded, total);
330
+ self._options.onProgress(id, fileName, loaded, total);
331
+ },
332
+ onComplete: function(id, fileName, result){
333
+ self._onComplete(id, fileName, result);
334
+ self._options.onComplete(id, fileName, result);
335
+ },
336
+ onCancel: function(id, fileName){
337
+ self._onCancel(id, fileName);
338
+ self._options.onCancel(id, fileName);
339
+ }
340
+ });
341
+
342
+ return handler;
343
+ },
344
+ _preventLeaveInProgress: function(){
345
+ var self = this;
346
+
347
+ qq.attach(window, 'beforeunload', function(e){
348
+ if (!self._filesInProgress){return;}
349
+
350
+ var e = e || window.event;
351
+ // for ie, ff
352
+ e.returnValue = self._options.messages.onLeave;
353
+ // for webkit
354
+ return self._options.messages.onLeave;
355
+ });
356
+ },
357
+ _onSubmit: function(id, fileName){
358
+ this._filesInProgress++;
359
+ },
360
+ _onProgress: function(id, fileName, loaded, total){
361
+ },
362
+ _onComplete: function(id, fileName, result){
363
+ this._filesInProgress--;
364
+ if (result.error){
365
+ this._options.showMessage(result.error);
366
+ }
367
+ },
368
+ _onCancel: function(id, fileName){
369
+ this._filesInProgress--;
370
+ },
371
+ _onInputChange: function(input){
372
+ if (this._handler instanceof qq.UploadHandlerXhr){
373
+ this._uploadFileList(input.files);
374
+ } else {
375
+ if (this._validateFile(input)){
376
+ this._uploadFile(input);
377
+ }
378
+ }
379
+ this._button.reset();
380
+ },
381
+ _uploadFileList: function(files){
382
+ for (var i=0; i<files.length; i++){
383
+ if ( !this._validateFile(files[i])){
384
+ return;
385
+ }
386
+ }
387
+
388
+ for (var i=0; i<files.length; i++){
389
+ this._uploadFile(files[i]);
390
+ }
391
+ },
392
+ _uploadFile: function(fileContainer){
393
+ var id = this._handler.add(fileContainer);
394
+ var fileName = this._handler.getName(id);
395
+
396
+ if (this._options.onSubmit(id, fileName) !== false){
397
+ this._onSubmit(id, fileName);
398
+ this._handler.upload(id, this._options.params);
399
+ }
400
+ },
401
+ _validateFile: function(file){
402
+ var name, size;
403
+
404
+ if (file.value){
405
+ // it is a file input
406
+ // get input value and remove path to normalize
407
+ name = file.value.replace(/.*(\/|\\)/, "");
408
+ } else {
409
+ // fix missing properties in Safari
410
+ name = file.fileName != null ? file.fileName : file.name;
411
+ size = file.fileSize != null ? file.fileSize : file.size;
412
+ }
413
+
414
+ if (! this._isAllowedExtension(name)){
415
+ this._error('typeError', name);
416
+ return false;
417
+
418
+ } else if (size === 0){
419
+ this._error('emptyError', name);
420
+ return false;
421
+
422
+ } else if (size && this._options.sizeLimit && size > this._options.sizeLimit){
423
+ this._error('sizeError', name);
424
+ return false;
425
+
426
+ } else if (size && size < this._options.minSizeLimit){
427
+ this._error('minSizeError', name);
428
+ return false;
429
+ }
430
+
431
+ return true;
432
+ },
433
+ _error: function(code, fileName){
434
+ var message = this._options.messages[code];
435
+ function r(name, replacement){ message = message.replace(name, replacement); }
436
+
437
+ r('{file}', this._formatFileName(fileName));
438
+ r('{extensions}', this._options.allowedExtensions.join(', '));
439
+ r('{sizeLimit}', this._formatSize(this._options.sizeLimit));
440
+ r('{minSizeLimit}', this._formatSize(this._options.minSizeLimit));
441
+
442
+ this._options.showMessage(message);
443
+ },
444
+ _formatFileName: function(name){
445
+ if (name.length > 33){
446
+ name = name.slice(0, 19) + '...' + name.slice(-13);
447
+ }
448
+ return name;
449
+ },
450
+ _isAllowedExtension: function(fileName){
451
+ var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : '';
452
+ var allowed = this._options.allowedExtensions;
453
+
454
+ if (!allowed.length){return true;}
455
+
456
+ for (var i=0; i<allowed.length; i++){
457
+ if (allowed[i].toLowerCase() == ext){ return true;}
458
+ }
459
+
460
+ return false;
461
+ },
462
+ _formatSize: function(bytes){
463
+ var i = -1;
464
+ do {
465
+ bytes = bytes / 1024;
466
+ i++;
467
+ } while (bytes > 99);
468
+
469
+ return Math.max(bytes, 0.1).toFixed(1) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i];
470
+ }
471
+ };
472
+
473
+
474
+ /**
475
+ * Class that creates upload widget with drag-and-drop and file list
476
+ * @inherits qq.FileUploaderBasic
477
+ */
478
+ qq.FileUploader = function(o){
479
+ // call parent constructor
480
+ qq.FileUploaderBasic.apply(this, arguments);
481
+
482
+ // additional options
483
+ qq.extend(this._options, {
484
+ element: null,
485
+ // if set, will be used instead of qq-upload-list in template
486
+ listElement: null,
487
+
488
+ template: '<div class="qq-uploader">' +
489
+ '<div class="qq-upload-drop-area"><span>Drop files here to upload</span></div>' +
490
+ '<div class="qq-upload-button"><span>'+this._options.buttontext+'</span></div>' +
491
+ '<ul class="qq-upload-list"></ul>' +
492
+ '</div>',
493
+
494
+ // template for one item in file list
495
+ fileTemplate: '<li>' +
496
+ '<span class="qq-upload-file"></span>' +
497
+ '<span class="qq-upload-spinner"></span>' +
498
+ '<span class="qq-upload-size"></span>' +
499
+ '<a class="qq-upload-cancel" href="#">Cancel</a>' +
500
+ '<span class="qq-upload-failed-text">Failed</span>' +
501
+ '</li>',
502
+
503
+ classes: {
504
+ // used to get elements from templates
505
+ button: 'qq-upload-button',
506
+ drop: 'qq-upload-drop-area',
507
+ dropActive: 'qq-upload-drop-area-active',
508
+ list: 'qq-upload-list',
509
+
510
+ file: 'qq-upload-file',
511
+ spinner: 'qq-upload-spinner',
512
+ size: 'qq-upload-size',
513
+ cancel: 'qq-upload-cancel',
514
+
515
+ // added to list item when upload completes
516
+ // used in css to hide progress spinner
517
+ success: 'qq-upload-success',
518
+ fail: 'qq-upload-fail'
519
+ }
520
+ });
521
+ // overwrite options with user supplied
522
+ qq.extend(this._options, o);
523
+
524
+ this._element = this._options.element;
525
+ this._element.innerHTML = this._options.template;
526
+ this._listElement = this._options.listElement || this._find(this._element, 'list');
527
+
528
+ this._classes = this._options.classes;
529
+
530
+ this._button = this._createUploadButton(this._find(this._element, 'button'));
531
+
532
+ this._bindCancelEvent();
533
+ this._setupDragDrop();
534
+ };
535
+
536
+ // inherit from Basic Uploader
537
+ qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype);
538
+
539
+ qq.extend(qq.FileUploader.prototype, {
540
+ /**
541
+ * Gets one of the elements listed in this._options.classes
542
+ **/
543
+ _find: function(parent, type){
544
+ var element = qq.getByClass(parent, this._options.classes[type])[0];
545
+ if (!element){
546
+ throw new Error('element not found ' + type);
547
+ }
548
+
549
+ return element;
550
+ },
551
+ _setupDragDrop: function(){
552
+ var self = this,
553
+ dropArea = this._find(this._element, 'drop');
554
+
555
+ var dz = new qq.UploadDropZone({
556
+ element: dropArea,
557
+ onEnter: function(e){
558
+ qq.addClass(dropArea, self._classes.dropActive);
559
+ e.stopPropagation();
560
+ },
561
+ onLeave: function(e){
562
+ e.stopPropagation();
563
+ },
564
+ onLeaveNotDescendants: function(e){
565
+ qq.removeClass(dropArea, self._classes.dropActive);
566
+ },
567
+ onDrop: function(e){
568
+ dropArea.style.display = 'none';
569
+ qq.removeClass(dropArea, self._classes.dropActive);
570
+ self._uploadFileList(e.dataTransfer.files);
571
+ }
572
+ });
573
+
574
+ dropArea.style.display = 'none';
575
+
576
+ qq.attach(document, 'dragenter', function(e){
577
+ if (!dz._isValidFileDrag(e)) return;
578
+
579
+ dropArea.style.display = 'block';
580
+ });
581
+ qq.attach(document, 'dragleave', function(e){
582
+ if (!dz._isValidFileDrag(e)) return;
583
+
584
+ var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
585
+ // only fire when leaving document out
586
+ if ( ! relatedTarget || relatedTarget.nodeName == "HTML"){
587
+ dropArea.style.display = 'none';
588
+ }
589
+ });
590
+ },
591
+ _onSubmit: function(id, fileName){
592
+ qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments);
593
+ this._addToList(id, fileName);
594
+ },
595
+ _onProgress: function(id, fileName, loaded, total){
596
+ qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments);
597
+
598
+ var item = this._getItemByFileId(id);
599
+ var size = this._find(item, 'size');
600
+ size.style.display = 'inline';
601
+
602
+ var text;
603
+ if (loaded != total){
604
+ text = Math.round(loaded / total * 100) + '% from ' + this._formatSize(total);
605
+ } else {
606
+ text = this._formatSize(total);
607
+ }
608
+
609
+ qq.setText(size, text);
610
+ },
611
+ _onComplete: function(id, fileName, result){
612
+ qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments);
613
+
614
+ // mark completed
615
+ var item = this._getItemByFileId(id);
616
+ qq.remove(this._find(item, 'cancel'));
617
+ qq.remove(this._find(item, 'spinner'));
618
+
619
+ if (result.success){
620
+ qq.addClass(item, this._classes.success);
621
+ } else {
622
+ qq.addClass(item, this._classes.fail);
623
+ }
624
+ },
625
+ _addToList: function(id, fileName){
626
+ var item = qq.toElement(this._options.fileTemplate);
627
+ item.qqFileId = id;
628
+
629
+ var fileElement = this._find(item, 'file');
630
+ qq.setText(fileElement, this._formatFileName(fileName));
631
+ this._find(item, 'size').style.display = 'none';
632
+
633
+ if( this._options.multiple || this._listElement.childNodes.length == 0 )
634
+ this._listElement.appendChild(item);
635
+ else
636
+ this._listElement.replaceChild(item, this._listElement.firstChild);
637
+ },
638
+ _getItemByFileId: function(id){
639
+ var item = this._listElement.firstChild;
640
+
641
+ // there can't be txt nodes in dynamically created list
642
+ // and we can use nextSibling
643
+ while (item){
644
+ if (item.qqFileId == id) return item;
645
+ item = item.nextSibling;
646
+ }
647
+ },
648
+ /**
649
+ * delegate click event for cancel link
650
+ **/
651
+ _bindCancelEvent: function(){
652
+ var self = this,
653
+ list = this._listElement;
654
+
655
+ qq.attach(list, 'click', function(e){
656
+ e = e || window.event;
657
+ var target = e.target || e.srcElement;
658
+
659
+ if (qq.hasClass(target, self._classes.cancel)){
660
+ qq.preventDefault(e);
661
+
662
+ var item = target.parentNode;
663
+ self._handler.cancel(item.qqFileId);
664
+ qq.remove(item);
665
+ }
666
+ });
667
+ }
668
+ });
669
+
670
+ qq.UploadDropZone = function(o){
671
+ this._options = {
672
+ element: null,
673
+ onEnter: function(e){},
674
+ onLeave: function(e){},
675
+ // is not fired when leaving element by hovering descendants
676
+ onLeaveNotDescendants: function(e){},
677
+ onDrop: function(e){}
678
+ };
679
+ qq.extend(this._options, o);
680
+
681
+ this._element = this._options.element;
682
+
683
+ this._disableDropOutside();
684
+ this._attachEvents();
685
+ };
686
+
687
+ qq.UploadDropZone.prototype = {
688
+ _disableDropOutside: function(e){
689
+ // run only once for all instances
690
+ if (!qq.UploadDropZone.dropOutsideDisabled ){
691
+
692
+ qq.attach(document, 'dragover', function(e){
693
+ if (e.dataTransfer){
694
+ e.dataTransfer.dropEffect = 'none';
695
+ e.preventDefault();
696
+ }
697
+ });
698
+
699
+ qq.UploadDropZone.dropOutsideDisabled = true;
700
+ }
701
+ },
702
+ _attachEvents: function(){
703
+ var self = this;
704
+
705
+ qq.attach(self._element, 'dragover', function(e){
706
+ if (!self._isValidFileDrag(e)) return;
707
+
708
+ var effect = e.dataTransfer.effectAllowed;
709
+ if (effect == 'move' || effect == 'linkMove'){
710
+ e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed)
711
+ } else {
712
+ e.dataTransfer.dropEffect = 'copy'; // for Chrome
713
+ }
714
+
715
+ e.stopPropagation();
716
+ e.preventDefault();
717
+ });
718
+
719
+ qq.attach(self._element, 'dragenter', function(e){
720
+ if (!self._isValidFileDrag(e)) return;
721
+
722
+ self._options.onEnter(e);
723
+ });
724
+
725
+ qq.attach(self._element, 'dragleave', function(e){
726
+ if (!self._isValidFileDrag(e)) return;
727
+
728
+ self._options.onLeave(e);
729
+
730
+ var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
731
+ // do not fire when moving a mouse over a descendant
732
+ if (qq.contains(this, relatedTarget)) return;
733
+
734
+ self._options.onLeaveNotDescendants(e);
735
+ });
736
+
737
+ qq.attach(self._element, 'drop', function(e){
738
+ if (!self._isValidFileDrag(e)) return;
739
+
740
+ e.preventDefault();
741
+ self._options.onDrop(e);
742
+ });
743
+ },
744
+ _isValidFileDrag: function(e){
745
+ var dt = e.dataTransfer,
746
+ // do not check dt.types.contains in webkit, because it crashes safari 4
747
+ isWebkit = navigator.userAgent.indexOf("AppleWebKit") > -1;
748
+
749
+ // dt.effectAllowed is none in Safari 5
750
+ // dt.types.contains check is for firefox
751
+ return dt && dt.effectAllowed != 'none' &&
752
+ (dt.files || (!isWebkit && dt.types.contains && dt.types.contains('Files')));
753
+
754
+ }
755
+ };
756
+
757
+ qq.UploadButton = function(o){
758
+ this._options = {
759
+ element: null,
760
+ // if set to true adds multiple attribute to file input
761
+ multiple: false,
762
+ // name attribute of file input
763
+ name: 'file',
764
+ onChange: function(input){},
765
+ hoverClass: 'qq-upload-button-hover',
766
+ focusClass: 'qq-upload-button-focus'
767
+ };
768
+
769
+ qq.extend(this._options, o);
770
+
771
+ this._element = this._options.element;
772
+
773
+ // make button suitable container for input
774
+ qq.css(this._element, {
775
+ position: 'relative',
776
+ overflow: 'hidden',
777
+ // Make sure browse button is in the right side
778
+ // in Internet Explorer
779
+ direction: 'ltr'
780
+ });
781
+
782
+ this._input = this._createInput();
783
+ };
784
+
785
+ qq.UploadButton.prototype = {
786
+ /* returns file input element */
787
+ getInput: function(){
788
+ return this._input;
789
+ },
790
+ /* cleans/recreates the file input */
791
+ reset: function(){
792
+ if (this._input.parentNode){
793
+ qq.remove(this._input);
794
+ }
795
+
796
+ qq.removeClass(this._element, this._options.focusClass);
797
+ this._input = this._createInput();
798
+ },
799
+ _createInput: function(){
800
+ var input = document.createElement("input");
801
+
802
+ if (this._options.multiple){
803
+ input.setAttribute("multiple", "multiple");
804
+ }
805
+
806
+ input.setAttribute("type", "file");
807
+ input.setAttribute("name", this._options.name);
808
+
809
+ qq.css(input, {
810
+ position: 'absolute',
811
+ // in Opera only 'browse' button
812
+ // is clickable and it is located at
813
+ // the right side of the input
814
+ right: 0,
815
+ top: 0,
816
+ fontFamily: 'Arial',
817
+ // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118
818
+ fontSize: '118px',
819
+ margin: 0,
820
+ padding: 0,
821
+ cursor: 'pointer',
822
+ opacity: 0
823
+ });
824
+
825
+ this._element.appendChild(input);
826
+
827
+ var self = this;
828
+ qq.attach(input, 'change', function(){
829
+ self._options.onChange(input);
830
+ });
831
+
832
+ qq.attach(input, 'mouseover', function(){
833
+ qq.addClass(self._element, self._options.hoverClass);
834
+ });
835
+ qq.attach(input, 'mouseout', function(){
836
+ qq.removeClass(self._element, self._options.hoverClass);
837
+ });
838
+ qq.attach(input, 'focus', function(){
839
+ qq.addClass(self._element, self._options.focusClass);
840
+ });
841
+ qq.attach(input, 'blur', function(){
842
+ qq.removeClass(self._element, self._options.focusClass);
843
+ });
844
+
845
+ // IE and Opera, unfortunately have 2 tab stops on file input
846
+ // which is unacceptable in our case, disable keyboard access
847
+ if (window.attachEvent){
848
+ // it is IE or Opera
849
+ input.setAttribute('tabIndex', "-1");
850
+ }
851
+
852
+ return input;
853
+ }
854
+ };
855
+
856
+ /**
857
+ * Class for uploading files, uploading itself is handled by child classes
858
+ */
859
+ qq.UploadHandlerAbstract = function(o){
860
+ this._options = {
861
+ debug: false,
862
+ action: '/upload.php',
863
+ // maximum number of concurrent uploads
864
+ maxConnections: 999,
865
+ onProgress: function(id, fileName, loaded, total){},
866
+ onComplete: function(id, fileName, response){},
867
+ onCancel: function(id, fileName){}
868
+ };
869
+ qq.extend(this._options, o);
870
+
871
+ this._queue = [];
872
+ // params for files in queue
873
+ this._params = [];
874
+ };
875
+ qq.UploadHandlerAbstract.prototype = {
876
+ log: function(str){
877
+ if (this._options.debug && window.console) console.log('[uploader] ' + str);
878
+ },
879
+ /**
880
+ * Adds file or file input to the queue
881
+ * @returns id
882
+ **/
883
+ add: function(file){},
884
+ /**
885
+ * Sends the file identified by id and additional query params to the server
886
+ */
887
+ upload: function(id, params){
888
+ var len = this._queue.push(id);
889
+
890
+ var copy = {};
891
+ qq.extend(copy, params);
892
+ this._params[id] = copy;
893
+
894
+ // if too many active uploads, wait...
895
+ if (len <= this._options.maxConnections){
896
+ this._upload(id, this._params[id]);
897
+ }
898
+ },
899
+ /**
900
+ * Cancels file upload by id
901
+ */
902
+ cancel: function(id){
903
+ this._cancel(id);
904
+ this._dequeue(id);
905
+ },
906
+ /**
907
+ * Cancells all uploads
908
+ */
909
+ cancelAll: function(){
910
+ for (var i=0; i<this._queue.length; i++){
911
+ this._cancel(this._queue[i]);
912
+ }
913
+ this._queue = [];
914
+ },
915
+ /**
916
+ * Returns name of the file identified by id
917
+ */
918
+ getName: function(id){},
919
+ /**
920
+ * Returns size of the file identified by id
921
+ */
922
+ getSize: function(id){},
923
+ /**
924
+ * Returns id of files being uploaded or
925
+ * waiting for their turn
926
+ */
927
+ getQueue: function(){
928
+ return this._queue;
929
+ },
930
+ /**
931
+ * Actual upload method
932
+ */
933
+ _upload: function(id){},
934
+ /**
935
+ * Actual cancel method
936
+ */
937
+ _cancel: function(id){},
938
+ /**
939
+ * Removes element from queue, starts upload of next
940
+ */
941
+ _dequeue: function(id){
942
+ var i = qq.indexOf(this._queue, id);
943
+ this._queue.splice(i, 1);
944
+
945
+ var max = this._options.maxConnections;
946
+
947
+ if (this._queue.length >= max && i < max){
948
+ var nextId = this._queue[max-1];
949
+ this._upload(nextId, this._params[nextId]);
950
+ }
951
+ }
952
+ };
953
+
954
+ /**
955
+ * Class for uploading files using form and iframe
956
+ * @inherits qq.UploadHandlerAbstract
957
+ */
958
+ qq.UploadHandlerForm = function(o){
959
+ qq.UploadHandlerAbstract.apply(this, arguments);
960
+
961
+ this._inputs = {};
962
+ };
963
+ // @inherits qq.UploadHandlerAbstract
964
+ qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype);
965
+
966
+ qq.extend(qq.UploadHandlerForm.prototype, {
967
+ add: function(fileInput){
968
+ fileInput.setAttribute('name', 'qqfile');
969
+ var id = 'qq-upload-handler-iframe' + qq.getUniqueId();
970
+
971
+ this._inputs[id] = fileInput;
972
+
973
+ // remove file input from DOM
974
+ if (fileInput.parentNode){
975
+ qq.remove(fileInput);
976
+ }
977
+
978
+ return id;
979
+ },
980
+ getName: function(id){
981
+ // get input value and remove path to normalize
982
+ return this._inputs[id].value.replace(/.*(\/|\\)/, "");
983
+ },
984
+ _cancel: function(id){
985
+ this._options.onCancel(id, this.getName(id));
986
+
987
+ delete this._inputs[id];
988
+
989
+ var iframe = document.getElementById(id);
990
+ if (iframe){
991
+ // to cancel request set src to something else
992
+ // we use src="javascript:false;" because it doesn't
993
+ // trigger ie6 prompt on https
994
+ iframe.setAttribute('src', 'javascript:false;');
995
+
996
+ qq.remove(iframe);
997
+ }
998
+ },
999
+ _upload: function(id, params){
1000
+ var input = this._inputs[id];
1001
+
1002
+ if (!input){
1003
+ throw new Error('file with passed id was not added, or already uploaded or cancelled');
1004
+ }
1005
+
1006
+ var fileName = this.getName(id);
1007
+
1008
+ var iframe = this._createIframe(id);
1009
+ var form = this._createForm(iframe, params);
1010
+ form.appendChild(input);
1011
+
1012
+ var self = this;
1013
+ this._attachLoadEvent(iframe, function(){
1014
+ self.log('iframe loaded');
1015
+
1016
+ var response = self._getIframeContentJSON(iframe);
1017
+
1018
+ self._options.onComplete(id, fileName, response);
1019
+ self._dequeue(id);
1020
+
1021
+ delete self._inputs[id];
1022
+ // timeout added to fix busy state in FF3.6
1023
+ setTimeout(function(){
1024
+ qq.remove(iframe);
1025
+ }, 1);
1026
+ });
1027
+
1028
+ form.submit();
1029
+ qq.remove(form);
1030
+
1031
+ return id;
1032
+ },
1033
+ _attachLoadEvent: function(iframe, callback){
1034
+ qq.attach(iframe, 'load', function(){
1035
+ // when we remove iframe from dom
1036
+ // the request stops, but in IE load
1037
+ // event fires
1038
+ if (!iframe.parentNode){
1039
+ return;
1040
+ }
1041
+
1042
+ // fixing Opera 10.53
1043
+ if (iframe.contentDocument &&
1044
+ iframe.contentDocument.body &&
1045
+ iframe.contentDocument.body.innerHTML == "false"){
1046
+ // In Opera event is fired second time
1047
+ // when body.innerHTML changed from false
1048
+ // to server response approx. after 1 sec
1049
+ // when we upload file with iframe
1050
+ return;
1051
+ }
1052
+
1053
+ callback();
1054
+ });
1055
+ },
1056
+ /**
1057
+ * Returns json object received by iframe from server.
1058
+ */
1059
+ _getIframeContentJSON: function(iframe){
1060
+ // iframe.contentWindow.document - for IE<7
1061
+ var doc = iframe.contentDocument ? iframe.contentDocument: iframe.contentWindow.document,
1062
+ response;
1063
+
1064
+ this.log("converting iframe's innerHTML to JSON");
1065
+ this.log("innerHTML = " + doc.body.innerHTML);
1066
+
1067
+ try {
1068
+ response = eval("(" + doc.body.innerHTML + ")");
1069
+ } catch(err){
1070
+ response = {};
1071
+ }
1072
+
1073
+ return response;
1074
+ },
1075
+ /**
1076
+ * Creates iframe with unique name
1077
+ */
1078
+ _createIframe: function(id){
1079
+ // We can't use following code as the name attribute
1080
+ // won't be properly registered in IE6, and new window
1081
+ // on form submit will open
1082
+ // var iframe = document.createElement('iframe');
1083
+ // iframe.setAttribute('name', id);
1084
+
1085
+ var iframe = qq.toElement('<iframe src="javascript:false;" name="' + id + '" />');
1086
+ // src="javascript:false;" removes ie6 prompt on https
1087
+
1088
+ iframe.setAttribute('id', id);
1089
+
1090
+ iframe.style.display = 'none';
1091
+ document.body.appendChild(iframe);
1092
+
1093
+ return iframe;
1094
+ },
1095
+ /**
1096
+ * Creates form, that will be submitted to iframe
1097
+ */
1098
+ _createForm: function(iframe, params){
1099
+ // We can't use the following code in IE6
1100
+ // var form = document.createElement('form');
1101
+ // form.setAttribute('method', 'post');
1102
+ // form.setAttribute('enctype', 'multipart/form-data');
1103
+ // Because in this case file won't be attached to request
1104
+ var form = qq.toElement('<form method="post" enctype="multipart/form-data"></form>');
1105
+
1106
+ var queryString = qq.obj2url(params, this._options.action);
1107
+
1108
+ form.setAttribute('action', queryString);
1109
+ form.setAttribute('target', iframe.name);
1110
+ form.style.display = 'none';
1111
+ document.body.appendChild(form);
1112
+
1113
+ return form;
1114
+ }
1115
+ });
1116
+
1117
+ /**
1118
+ * Class for uploading files using xhr
1119
+ * @inherits qq.UploadHandlerAbstract
1120
+ */
1121
+ qq.UploadHandlerXhr = function(o){
1122
+ qq.UploadHandlerAbstract.apply(this, arguments);
1123
+
1124
+ this._files = [];
1125
+ this._xhrs = [];
1126
+
1127
+ // current loaded size in bytes for each file
1128
+ this._loaded = [];
1129
+ };
1130
+
1131
+ // static method
1132
+ qq.UploadHandlerXhr.isSupported = function(){
1133
+ var input = document.createElement('input');
1134
+ input.type = 'file';
1135
+
1136
+ return (
1137
+ 'multiple' in input &&
1138
+ typeof File != "undefined" &&
1139
+ typeof (new XMLHttpRequest()).upload != "undefined" );
1140
+ };
1141
+
1142
+ // @inherits qq.UploadHandlerAbstract
1143
+ qq.extend(qq.UploadHandlerXhr.prototype, qq.UploadHandlerAbstract.prototype)
1144
+
1145
+ qq.extend(qq.UploadHandlerXhr.prototype, {
1146
+ /**
1147
+ * Adds file to the queue
1148
+ * Returns id to use with upload, cancel
1149
+ **/
1150
+ add: function(file){
1151
+ if (!(file instanceof File)){
1152
+ throw new Error('Passed obj in not a File (in qq.UploadHandlerXhr)');
1153
+ }
1154
+
1155
+ return this._files.push(file) - 1;
1156
+ },
1157
+ getName: function(id){
1158
+ var file = this._files[id];
1159
+ // fix missing name in Safari 4
1160
+ return file.fileName != null ? file.fileName : file.name;
1161
+ },
1162
+ getSize: function(id){
1163
+ var file = this._files[id];
1164
+ return file.fileSize != null ? file.fileSize : file.size;
1165
+ },
1166
+ /**
1167
+ * Returns uploaded bytes for file identified by id
1168
+ */
1169
+ getLoaded: function(id){
1170
+ return this._loaded[id] || 0;
1171
+ },
1172
+ /**
1173
+ * Sends the file identified by id and additional query params to the server
1174
+ * @param {Object} params name-value string pairs
1175
+ */
1176
+ _upload: function(id, params){
1177
+ var file = this._files[id],
1178
+ name = this.getName(id),
1179
+ size = this.getSize(id);
1180
+
1181
+ this._loaded[id] = 0;
1182
+
1183
+ var xhr = this._xhrs[id] = new XMLHttpRequest();
1184
+ var self = this;
1185
+
1186
+ xhr.upload.onprogress = function(e){
1187
+ if (e.lengthComputable){
1188
+ self._loaded[id] = e.loaded;
1189
+ self._options.onProgress(id, name, e.loaded, e.total);
1190
+ }
1191
+ };
1192
+
1193
+ xhr.onreadystatechange = function(){
1194
+ if (xhr.readyState == 4){
1195
+ self._onComplete(id, xhr);
1196
+ }
1197
+ };
1198
+
1199
+ // build query string
1200
+ params = params || {};
1201
+ params['qqfile'] = name;
1202
+ var queryString = qq.obj2url(params, this._options.action);
1203
+
1204
+ xhr.open("POST", queryString, true);
1205
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1206
+ xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
1207
+ xhr.setRequestHeader("Content-Type", "application/octet-stream");
1208
+ xhr.send(file);
1209
+ },
1210
+ _onComplete: function(id, xhr){
1211
+ // the request was aborted/cancelled
1212
+ if (!this._files[id]) return;
1213
+
1214
+ var name = this.getName(id);
1215
+ var size = this.getSize(id);
1216
+
1217
+ this._options.onProgress(id, name, size, size);
1218
+
1219
+ if (xhr.status == 200){
1220
+ this.log("xhr - server response received");
1221
+ this.log("responseText = " + xhr.responseText);
1222
+
1223
+ var response;
1224
+
1225
+ try {
1226
+ response = eval("(" + xhr.responseText + ")");
1227
+ } catch(err){
1228
+ response = {};
1229
+ }
1230
+
1231
+ this._options.onComplete(id, name, response);
1232
+
1233
+ } else {
1234
+ this._options.onComplete(id, name, {});
1235
+ }
1236
+
1237
+ this._files[id] = null;
1238
+ this._xhrs[id] = null;
1239
+ this._dequeue(id);
1240
+ },
1241
+ _cancel: function(id){
1242
+ this._options.onCancel(id, this.getName(id));
1243
+
1244
+ this._files[id] = null;
1245
+
1246
+ if (this._xhrs[id]){
1247
+ this._xhrs[id].abort();
1248
+ this._xhrs[id] = null;
1249
+ }
1250
+ }
1251
+ });
js/lookbook/jquery-ui-1.8.17.js ADDED
@@ -0,0 +1,11827 @@