TheExtensionLab_StatusColors - Version 1.0.1

Version Notes

Add missing files.

Download this release

Release Info

Developer James Anelay
Extension TheExtensionLab_StatusColors
Version 1.0.1
Comparing to
See all releases


Code changes from version 1.0.0 to 1.0.1

Files changed (23) hide show
  1. app/code/community/TheExtensionLab/StatusColors/Block/Adminhtml/System/Config/ExtensionInfo.php +48 -0
  2. app/code/community/TheExtensionLab/StatusColors/Helper/Data.php +98 -0
  3. app/code/community/TheExtensionLab/StatusColors/Model/Observer.php +152 -0
  4. app/code/community/TheExtensionLab/StatusColors/Model/Resource/Setup.php +4 -0
  5. app/code/community/TheExtensionLab/StatusColors/Test/Config/Main.php +51 -0
  6. app/code/community/TheExtensionLab/StatusColors/Test/Model/Observer.php +13 -0
  7. app/code/community/TheExtensionLab/StatusColors/etc/adminhtml.xml +30 -0
  8. app/code/community/TheExtensionLab/StatusColors/etc/config.xml +98 -0
  9. app/code/community/TheExtensionLab/StatusColors/etc/system.xml +60 -0
  10. app/code/community/TheExtensionLab/StatusColors/sql/theextensionlab_statuscolors_setup/install-0.1.0.php +18 -0
  11. app/design/adminhtml/default/default/layout/theextensionlab/statuscolors.xml +0 -0
  12. app/design/adminhtml/default/default/template/theextensionlab/statuscolors/sales/order/view/history/js-update.phtml +0 -0
  13. app/design/adminhtml/default/default/template/theextensionlab/statuscolors/system/config/extension-info.phtml +0 -0
  14. app/etc/modules/TheExtensionLab_StatusColors.xml +0 -0
  15. js/theextensionlab/adminhtml/jscolor/arrow.gif +0 -0
  16. js/theextensionlab/adminhtml/jscolor/cross.gif +0 -0
  17. js/theextensionlab/adminhtml/jscolor/hs.png +0 -0
  18. js/theextensionlab/adminhtml/jscolor/hv.png +0 -0
  19. js/theextensionlab/adminhtml/jscolor/jscolor.js +1010 -1010
  20. js/theextensionlab/statuscolors/adminhtml/grid-row.js +0 -0
  21. package.xml +5 -5
  22. skin/adminhtml/default/default/theextensionlab/statuscolors/grid.css +0 -0
  23. skin/adminhtml/default/default/theextensionlab/statuscolors/system-config.css +0 -0
app/code/community/TheExtensionLab/StatusColors/Block/Adminhtml/System/Config/ExtensionInfo.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Extension Information System Config Block
5
+ *
6
+ * @category TheExtensionLab
7
+ * @package TheExtensionLab_StatusColors
8
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
9
+ * @license Open Software License (OSL 3.0)
10
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
11
+ */
12
+
13
+ class TheExtensionLab_StatusColors_Block_Adminhtml_System_Config_ExtensionInfo
14
+ extends Mage_Adminhtml_Block_Abstract
15
+ implements Varien_Data_Form_Element_Renderer_Interface
16
+ {
17
+
18
+ /**
19
+ * Sets this renderer to use a template
20
+ */
21
+ protected function _construct()
22
+ {
23
+ parent::_construct();
24
+ $this->setTemplate('theextensionlab/statuscolors/system/config/extension-info.phtml');
25
+ }
26
+
27
+ /**
28
+ * Add renderView() to our render function so that a template is used.
29
+ *
30
+ * @param Varien_Data_Form_Element_Abstract $element
31
+ * @return string
32
+ */
33
+ public function render(Varien_Data_Form_Element_Abstract $element)
34
+ {
35
+ $html = $this->renderView();
36
+ return $html;
37
+ }
38
+
39
+ /**
40
+ * Get current extension version to be displayed in the admin
41
+ *
42
+ * @return Mage_Core_Model_Config_Element
43
+ */
44
+ public function getExtensionVersion()
45
+ {
46
+ return Mage::getConfig()->getNode('modules/TheExtensionLab_StatusColors/version');
47
+ }
48
+ }
app/code/community/TheExtensionLab/StatusColors/Helper/Data.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * StatusColors Data Helper
4
+ *
5
+ * @category TheExtensionLab
6
+ * @package TheExtensionLab_StatusColors
7
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
8
+ * @license Open Software License (OSL 3.0)
9
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
10
+ */
11
+ class TheExtensionLab_StatusColors_Helper_Data extends Mage_Core_Helper_Abstract
12
+ {
13
+ protected $_statusCollection = null;
14
+
15
+ /**
16
+ * @return array
17
+ *
18
+ * Note: This is called from layout XML <arguments helper="theextensionlab_statuscolors/data/getStatusColorColumn"/>
19
+ */
20
+ public function getStatusColorColumn()
21
+ {
22
+ $column = array(
23
+ 'header' => Mage::helper('sales')->__('Status Color'),
24
+ 'type' => 'text',
25
+ 'index' => 'color',
26
+ 'width' => '200px',
27
+ 'frame_callback' => array($this, 'decorateStatusUsingRowData')
28
+ );
29
+
30
+ return $column;
31
+ }
32
+
33
+ /**
34
+ * Decorate status column values - but don't load collection as we don't need to.
35
+ * @return string
36
+ */
37
+ public function decorateStatusUsingRowData($value)
38
+ {
39
+ $statusHtml = '<span class="custom-color" style="background-color:'.$value.';">
40
+ <span>'.$value.'</span>
41
+ </span>';
42
+ return $statusHtml;
43
+ }
44
+
45
+ /**
46
+ * Decorate status column values
47
+ *
48
+ * @return string
49
+ */
50
+ public function decorateStatus($value, $row)
51
+ {
52
+ //Get the status of this row
53
+ $rowStatus = $row->getStatus();
54
+
55
+ //Get full collection of statuses (cached)
56
+ $statusCollection = $this->_getStatusCollection();
57
+
58
+ //Run through status collection and when it matches the current row set $customColor
59
+ foreach ($statusCollection as $status) {
60
+ if ($status->getStatus() == $rowStatus) {
61
+ $customColor = $status->getColor();
62
+ }
63
+ }
64
+
65
+ //Wrap our status within a span to be styled with css
66
+ $statusHtml = '<span class="custom-color" style="background-color:'.$customColor.';">
67
+ <span>'.$value.'</span>
68
+ </span>';
69
+
70
+ return $statusHtml;
71
+ }
72
+
73
+ /**
74
+ * Retrieve status color
75
+ *
76
+ * @param string $code
77
+ * @return string
78
+ */
79
+ public function getStatusColor($code)
80
+ {
81
+ $status = Mage::getModel('sales/order_status')
82
+ ->load($code);
83
+ return $status->getColor();
84
+ }
85
+
86
+ /**
87
+ * @return Mage_Sales_Model_Resource_Order_Status_Collection|null
88
+ */
89
+ protected function _getStatusCollection()
90
+ {
91
+ if ($this->_statusCollection === null) {
92
+ $this->_statusCollection = Mage::getModel('sales/order_status')->getCollection();
93
+ }
94
+
95
+ return $this->_statusCollection;
96
+ }
97
+
98
+ }
app/code/community/TheExtensionLab/StatusColors/Model/Observer.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * StatusColors Observer Model
5
+ *
6
+ * @category TheExtensionLab
7
+ * @package TheExtensionLab_
8
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
9
+ * @license Open Software License (OSL 3.0)
10
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
11
+ */
12
+
13
+ class TheExtensionLab_StatusColors_Model_Observer
14
+ {
15
+ /**
16
+ * @param Varien_Event_Observer $observer
17
+ * @return $this
18
+ */
19
+ public function adminhtmlBlockHtmlBefore(Varien_Event_Observer $observer)
20
+ {
21
+ $block = $observer->getEvent()->getBlock();
22
+
23
+ if ($block instanceof Mage_Adminhtml_Block_Sales_Order_Grid) {
24
+
25
+ //Get the status column and add a frame_callback which adds the colour to the html
26
+ $column = $block->getColumn('status');
27
+ $column->setFrameCallback(array($this->getHelper(), 'decorateStatus'));
28
+ return $this;
29
+ }
30
+
31
+ //Adds a new feild to the new/edit status forms
32
+ if ($block instanceof Mage_Adminhtml_Block_Sales_Order_Status_Edit_Form) {
33
+ $form = $block->getForm();
34
+ $elements = $form->getElements();
35
+ foreach ($elements as $element) {
36
+ switch($element->getId()){
37
+ case "base_fieldset":
38
+ //Add a color field to the fieldset
39
+ $element->addField('color', 'text',
40
+ array(
41
+ 'name' => 'color',
42
+ 'label' => Mage::helper('sales')->__('Status Color'),
43
+ 'class' => 'color {hash:true,adjust:false}'
44
+ )
45
+ );
46
+
47
+ //Once we have added a new field we need to set the form values again to populate this feild
48
+ $model = Mage::registry('current_status');
49
+ if ($model) {
50
+ $form->addValues($model->getData());
51
+ }
52
+
53
+ break;
54
+ }
55
+ }
56
+ }
57
+
58
+ return $this;
59
+ }
60
+
61
+ /**
62
+ * This function adds the span (color) around the status using preg_replace
63
+ * could have used a template but that would mean if the template was edited
64
+ * we would need manually update it, using preg_replace there isn't a need for that.
65
+ *
66
+ * @param Varien_Event_Observer $observer
67
+ * @return $this
68
+ */
69
+ public function coreBlockAbstractToHtmlAfter(Varien_Event_Observer $observer)
70
+ {
71
+ $block = $observer->getEvent()->getBlock();
72
+
73
+ switch($block->getNameInLayout()) {
74
+ case "order_info":
75
+ $transport = $observer->getEvent()->getTransport();
76
+ $html = $transport->getHtml();
77
+ $customColor = Mage::helper('theextensionlab_statuscolors')->getStatusColor($block->getOrder()->getStatus());
78
+ $html = preg_replace(
79
+ '/id="order_status"/',
80
+ '${1} class="custom-color" style="background-color:'.$customColor.';"',
81
+ $html
82
+ );
83
+
84
+ $transport->setHtml($html);
85
+ break;
86
+ }
87
+
88
+ return $this;
89
+ }
90
+
91
+ /**
92
+ * This section stops the 404 page when extension is newly installed and the admin session doesn't
93
+ * have permission to view the system section. (We refresh the ACL before load if the section was
94
+ * previously now allowed)
95
+ *
96
+ * @param Varien_Event_Observer $observer
97
+ * @return $this
98
+ */
99
+ public function controllerActionPredispatchAdminhtmlSystemConfigEdit(Varien_Event_Observer $observer)
100
+ {
101
+ $section = $observer->getEvent()->getControllerAction()->getRequest()->getParam('section');
102
+
103
+ switch($section){
104
+ case "theextensionlab_statuscolors":
105
+ if (!$this->_isSectionAllowed($section)) {
106
+ //Credit to @schmengler for making our idea easy to implement
107
+ //https://github.com/schmengler/AclReload
108
+ $session = Mage::getSingleton('admin/session');
109
+ $session->setAcl(Mage::getResourceModel('admin/acl')->loadAcl());
110
+ }
111
+ break;
112
+ }
113
+
114
+ return $this;
115
+ }
116
+
117
+ /**
118
+ * Checks if the admin user has permissions to view the page
119
+ *
120
+ * @param $section
121
+ * @return bool
122
+ */
123
+ protected function _isSectionAllowed($section)
124
+ {
125
+ try {
126
+ $session = Mage::getSingleton('admin/session');
127
+ $resourceLookup = "admin/system/config/{$section}";
128
+ if ($session->getData('acl') instanceof Mage_Admin_Model_Acl) {
129
+ $resourceId = $session->getData('acl')->get($resourceLookup)->getResourceId();
130
+ if (!$session->isAllowed($resourceId)) {
131
+ throw new Exception('');
132
+ }
133
+ return true;
134
+ }
135
+ }
136
+ catch (Zend_Acl_Exception $e) {
137
+ return false;
138
+ }
139
+ catch (Exception $e) {
140
+ return false;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @return TheExtensionLab_StatusColors_Helper_Data
146
+ */
147
+ public function getHelper()
148
+ {
149
+ return Mage::helper('theextensionlab_statuscolors');
150
+ }
151
+
152
+ }
app/code/community/TheExtensionLab/StatusColors/Model/Resource/Setup.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php class TheExtensionLab_StatusColors_Model_Resource_Setup extends Mage_Sales_Model_Resource_Setup
2
+ {
3
+
4
+ }
app/code/community/TheExtensionLab/StatusColors/Test/Config/Main.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class TheExtensionLab_StatusColors_Test_Config_Main extends EcomDev_PHPUnit_Test_Case_Config
4
+ {
5
+
6
+ public function testSetupResources()
7
+ {
8
+ $this->assertSetupResourceDefined();
9
+ $this->assertSetupResourceExists();
10
+ $this->assertSetupScriptVersions();
11
+ }
12
+
13
+ public function testClassAliases()
14
+ {
15
+ $this->assertModelAlias('theextensionlab_statuscolors/observer','TheExtensionLab_StatusColors_Model_Observer');
16
+ $this->assertResourceModelAlias('theextensionlab_statuscolors/setup','TheExtensionLab_StatusColors_Model_Resource_Setup');
17
+ $this->assertHelperAlias('theextensionlab_statuscolors','TheExtensionLab_StatusColors_Helper_Data');
18
+ $this->assertBlockAlias('theextensionlab_statuscolors/example','TheExtensionLab_StatusColors_Block_Example');
19
+ }
20
+
21
+ public function testLayoutFiles()
22
+ {
23
+ $this->assertLayoutFileDefined('adminhtml','theextensionlab/statuscolors.xml');
24
+ $this->assertLayoutFileExists('adminhtml','theextensionlab/statuscolors.xml');
25
+ }
26
+
27
+ public function testObserverConfig()
28
+ {
29
+ $this->assertEventObserverDefined(
30
+ 'adminhtml',
31
+ 'adminhtml_block_html_before',
32
+ 'TheExtensionLab_StatusColors_Model_Observer',
33
+ 'adminhtmlBlockHtmlBefore'
34
+ );
35
+
36
+ $this->assertEventObserverDefined(
37
+ 'adminhtml',
38
+ 'core_block_abstract_to_html_after',
39
+ 'TheExtensionLab_StatusColors_Model_Observer',
40
+ 'coreBlockAbstractToHtmlAfter'
41
+ );
42
+
43
+ $this->assertEventObserverDefined(
44
+ 'adminhtml',
45
+ 'controller_action_predispatch_adminhtml_system_config_edit',
46
+ 'TheExtensionLab_StatusColors_Model_Observer',
47
+ 'controllerActionPredispatchAdminhtmlSystemConfigEdit'
48
+ );
49
+ }
50
+
51
+ }
app/code/community/TheExtensionLab/StatusColors/Test/Model/Observer.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php class TheExtensionLab_StatusColors_Test_Model_Observer extends EcomDev_PHPUnit_Test_Case
2
+ {
3
+ /**
4
+ * @test
5
+ * @return TheExtensionLab_StatusColors_Model_Observer
6
+ */
7
+ public function checkObserverClass()
8
+ {
9
+ $observer = Mage::getModel('theextensionlab_statuscolors/observer');
10
+ $this->assertInstanceOf('TheExtensionLab_StatusColors_Model_Observer', $observer);
11
+ return $observer;
12
+ }
13
+ }
app/code/community/TheExtensionLab/StatusColors/etc/adminhtml.xml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ * @category TheExtensionLab
4
+ * @package TheExtensionLab_StatusColors
5
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
6
+ * @license Open Software License (OSL 3.0)
7
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
8
+ *
9
+ -->
10
+ <config>
11
+ <acl>
12
+ <resources>
13
+ <admin>
14
+ <children>
15
+ <system>
16
+ <children>
17
+ <config>
18
+ <children>
19
+ <theextensionlab_statuscolors>
20
+ <title>Status Colors</title>
21
+ </theextensionlab_statuscolors>
22
+ </children>
23
+ </config>
24
+ </children>
25
+ </system>
26
+ </children>
27
+ </admin>
28
+ </resources>
29
+ </acl>
30
+ </config>
app/code/community/TheExtensionLab/StatusColors/etc/config.xml ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ * @category TheExtensionLab
4
+ * @package TheExtensionLab_StatusColors
5
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
6
+ * @license Open Software License (OSL 3.0)
7
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
8
+ *
9
+ -->
10
+ <config>
11
+ <modules>
12
+ <TheExtensionLab_StatusColors>
13
+ <version>1.0.1</version>
14
+ </TheExtensionLab_StatusColors>
15
+ </modules>
16
+
17
+ <global>
18
+ <blocks>
19
+ <theextensionlab_statuscolors>
20
+ <class>TheExtensionLab_StatusColors_Block</class>
21
+ </theextensionlab_statuscolors>
22
+ </blocks>
23
+
24
+ <helpers>
25
+ <theextensionlab_statuscolors>
26
+ <class>TheExtensionLab_StatusColors_Helper</class>
27
+ </theextensionlab_statuscolors>
28
+ </helpers>
29
+
30
+ <models>
31
+ <theextensionlab_statuscolors>
32
+ <class>TheExtensionLab_StatusColors_Model</class>
33
+ <resourceModel>theextensionlab_statuscolors_resource</resourceModel>
34
+ </theextensionlab_statuscolors>
35
+
36
+ <theextensionlab_statuscolors_resource>
37
+ <class>TheExtensionLab_StatusColors_Model_Resource</class>
38
+ </theextensionlab_statuscolors_resource>
39
+ </models>
40
+
41
+ <resources>
42
+ <theextensionlab_statuscolors_setup>
43
+ <setup>
44
+ <module>TheExtensionLab_StatusColors</module>
45
+ <class>TheExtensionLab_StatusColors_Model_Resource_Setup</class>
46
+ </setup>
47
+ </theextensionlab_statuscolors_setup>
48
+ </resources>
49
+ </global>
50
+
51
+ <adminhtml>
52
+ <layout>
53
+ <updates>
54
+ <theextensionlab_statuscolors>
55
+ <file>theextensionlab/statuscolors.xml</file>
56
+ </theextensionlab_statuscolors>
57
+ </updates>
58
+ </layout>
59
+
60
+ <events>
61
+ <adminhtml_block_html_before>
62
+ <observers>
63
+ <theextensionlab_statuscolors>
64
+ <class>TheExtensionLab_StatusColors_Model_Observer</class>
65
+ <method>adminhtmlBlockHtmlBefore</method>
66
+ </theextensionlab_statuscolors>
67
+ </observers>
68
+ </adminhtml_block_html_before>
69
+
70
+ <core_block_abstract_to_html_after>
71
+ <observers>
72
+ <theextensionlab_statuscolors>
73
+ <class>TheExtensionLab_StatusColors_Model_Observer</class>
74
+ <method>coreBlockAbstractToHtmlAfter</method>
75
+ </theextensionlab_statuscolors>
76
+ </observers>
77
+ </core_block_abstract_to_html_after>
78
+
79
+ <controller_action_predispatch_adminhtml_system_config_edit>
80
+ <observers>
81
+ <theextensionlab_statuscolors>
82
+ <class>TheExtensionLab_StatusColors_Model_Observer</class>
83
+ <method>controllerActionPredispatchAdminhtmlSystemConfigEdit</method>
84
+ </theextensionlab_statuscolors>
85
+ </observers>
86
+ </controller_action_predispatch_adminhtml_system_config_edit>
87
+ </events>
88
+ </adminhtml>
89
+
90
+ <phpunit>
91
+ <suite>
92
+ <modules>
93
+ <TheExtensionLab_StatusColors/>
94
+ </modules>
95
+ </suite>
96
+ </phpunit>
97
+
98
+ </config>
app/code/community/TheExtensionLab/StatusColors/etc/system.xml ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ * @category TheExtensionLab
4
+ * @package TheExtensionLab_StatusColors
5
+ * @copyright Copyright (c) TheExtensionLab (http://www.theextensionlab.com)
6
+ * @license Open Software License (OSL 3.0)
7
+ * @author James Anelay @ TheExtensionLab <james@theextensionlab.com>
8
+ *
9
+ -->
10
+ <config>
11
+ <tabs>
12
+ <theextensionlab_tab>
13
+ <label>TheExtensionLab</label>
14
+ <sort_order>150</sort_order>
15
+ </theextensionlab_tab>
16
+ </tabs>
17
+
18
+ <sections>
19
+ <theextensionlab_statuscolors>
20
+ <label>Status Colors</label>
21
+ <tab>theextensionlab_tab</tab>
22
+ <frontend_type>text</frontend_type>
23
+ <sort_order>10</sort_order>
24
+ <show_in_default>1</show_in_default>
25
+ <show_in_website>0</show_in_website>
26
+ <show_in_store>0</show_in_store>
27
+ <groups>
28
+ <!-- Display informatio about the extension e.g version number, github link etc. -->
29
+ <extension_information>
30
+ <label>Frontend Information</label>
31
+ <frontend_model>theextensionlab_statuscolors/adminhtml_system_config_extensionInfo</frontend_model>
32
+ <sort_order>1</sort_order>
33
+ <show_in_default>1</show_in_default>
34
+ <show_in_website>1</show_in_website>
35
+ <show_in_store>1</show_in_store>
36
+ </extension_information>
37
+ <grid_style>
38
+ <label>Grid Style</label>
39
+ <frontend_type>text</frontend_type>
40
+ <sort_order>10</sort_order>
41
+ <show_in_default>1</show_in_default>
42
+ <show_in_website>1</show_in_website>
43
+ <show_in_store>1</show_in_store>
44
+ <fields>
45
+ <color_whole_row>
46
+ <label>Color Whole Row</label>
47
+ <frontend_type>select</frontend_type>
48
+ <source_model>adminhtml/system_config_source_yesno</source_model>
49
+ <sort_order>10</sort_order>
50
+ <show_in_default>1</show_in_default>
51
+ <show_in_website>0</show_in_website>
52
+ <show_in_store>0</show_in_store>
53
+ <tooltip><![CDATA[Turning on this option will colour the background of the whole row rather than just the status label.]]></tooltip>
54
+ </color_whole_row>
55
+ </fields>
56
+ </grid_style>
57
+ </groups>
58
+ </theextensionlab_statuscolors>
59
+ </sections>
60
+ </config>
app/code/community/TheExtensionLab/StatusColors/sql/theextensionlab_statuscolors_setup/install-0.1.0.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /** @var $installer TheExtensionLab_StatusColors_Model_Resource_Setup */
4
+ $installer = $this;
5
+
6
+ $installer->startSetup();
7
+ $installer->getConnection()
8
+ ->addColumn($installer->getTable('sales/order_status'),
9
+ 'color',
10
+ array(
11
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
12
+ 'nullable' => true,
13
+ 'default' => null,
14
+ 'comment' => 'Color'
15
+ )
16
+ );
17
+
18
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/theextensionlab/statuscolors.xml CHANGED
File without changes
app/design/adminhtml/default/default/template/theextensionlab/statuscolors/sales/order/view/history/js-update.phtml CHANGED
File without changes
app/design/adminhtml/default/default/template/theextensionlab/statuscolors/system/config/extension-info.phtml CHANGED
File without changes
app/etc/modules/TheExtensionLab_StatusColors.xml CHANGED
File without changes
js/theextensionlab/adminhtml/jscolor/arrow.gif CHANGED
File without changes
js/theextensionlab/adminhtml/jscolor/cross.gif CHANGED
File without changes
js/theextensionlab/adminhtml/jscolor/hs.png CHANGED
File without changes
js/theextensionlab/adminhtml/jscolor/hv.png CHANGED
File without changes
js/theextensionlab/adminhtml/jscolor/jscolor.js CHANGED
@@ -1,1010 +1,1010 @@
1
- /**
2
- * jscolor, JavaScript Color Picker
3
- *
4
- * @version 1.4.4
5
- * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
6
- * @author Jan Odvarko, http://odvarko.cz
7
- * @created 2008-06-15
8
- * @updated 2014-12-09
9
- * @link http://jscolor.com
10
- */
11
-
12
-
13
- var jscolor = {
14
-
15
-
16
- dir : '', // location of jscolor directory (leave empty to autodetect)
17
- bindClass : 'color', // class name
18
- binding : true, // automatic binding via <input class="...">
19
- preloading : true, // use image preloading?
20
-
21
-
22
- install : function() {
23
- jscolor.addEvent(window, 'load', jscolor.init);
24
- },
25
-
26
-
27
- init : function() {
28
- if(jscolor.binding) {
29
- jscolor.bind();
30
- }
31
- if(jscolor.preloading) {
32
- jscolor.preload();
33
- }
34
- },
35
-
36
-
37
- getDir : function() {
38
- if(!jscolor.dir) {
39
- var detected = jscolor.detectDir();
40
- jscolor.dir = detected!==false ? detected : 'jscolor/';
41
- }
42
- return jscolor.dir;
43
- },
44
-
45
-
46
- detectDir : function() {
47
- var base = location.href;
48
-
49
- var e = document.getElementsByTagName('base');
50
- for(var i=0; i<e.length; i+=1) {
51
- if(e[i].href) { base = e[i].href; }
52
- }
53
-
54
- var e = document.getElementsByTagName('script');
55
- for(var i=0; i<e.length; i+=1) {
56
- if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
57
- var src = new jscolor.URI(e[i].src);
58
- var srcAbs = src.toAbsolute(base);
59
- srcAbs.path = srcAbs.path.replace(/[^\/]+$/, ''); // remove filename
60
- srcAbs.query = null;
61
- srcAbs.fragment = null;
62
- return srcAbs.toString();
63
- }
64
- }
65
- return false;
66
- },
67
-
68
-
69
- bind : function() {
70
- var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')(\\s*(\\{[^}]*\\})|\\s|$)', 'i');
71
- var e = document.getElementsByTagName('input');
72
- for(var i=0; i<e.length; i+=1) {
73
- if(jscolor.isColorAttrSupported && e[i].type.toLowerCase() == 'color') {
74
- // skip inputs of type 'color' if the browser supports this feature
75
- continue;
76
- }
77
- var m;
78
- if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
79
- var prop = {};
80
- if(m[4]) {
81
- try {
82
- prop = (new Function ('return (' + m[4] + ')'))();
83
- } catch(eInvalidProp) {}
84
- }
85
- e[i].color = new jscolor.color(e[i], prop);
86
- }
87
- }
88
- },
89
-
90
-
91
- preload : function() {
92
- for(var fn in jscolor.imgRequire) {
93
- if(jscolor.imgRequire.hasOwnProperty(fn)) {
94
- jscolor.loadImage(fn);
95
- }
96
- }
97
- },
98
-
99
-
100
- images : {
101
- pad : [ 181, 101 ],
102
- sld : [ 16, 101 ],
103
- cross : [ 15, 15 ],
104
- arrow : [ 7, 11 ]
105
- },
106
-
107
-
108
- imgRequire : {},
109
- imgLoaded : {},
110
-
111
-
112
- requireImage : function(filename) {
113
- jscolor.imgRequire[filename] = true;
114
- },
115
-
116
-
117
- loadImage : function(filename) {
118
- if(!jscolor.imgLoaded[filename]) {
119
- jscolor.imgLoaded[filename] = new Image();
120
- jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
121
- }
122
- },
123
-
124
-
125
- fetchElement : function(mixed) {
126
- return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
127
- },
128
-
129
-
130
- addEvent : function(el, evnt, func) {
131
- if(el.addEventListener) {
132
- el.addEventListener(evnt, func, false);
133
- } else if(el.attachEvent) {
134
- el.attachEvent('on'+evnt, func);
135
- }
136
- },
137
-
138
-
139
- fireEvent : function(el, evnt) {
140
- if(!el) {
141
- return;
142
- }
143
- if(document.createEvent) {
144
- var ev = document.createEvent('HTMLEvents');
145
- ev.initEvent(evnt, true, true);
146
- el.dispatchEvent(ev);
147
- } else if(document.createEventObject) {
148
- var ev = document.createEventObject();
149
- el.fireEvent('on'+evnt, ev);
150
- } else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
151
- el['on'+evnt]();
152
- }
153
- },
154
-
155
-
156
- getElementPos : function(e) {
157
- var e1=e, e2=e;
158
- var x=0, y=0;
159
- if(e1.offsetParent) {
160
- do {
161
- x += e1.offsetLeft;
162
- y += e1.offsetTop;
163
- } while(e1 = e1.offsetParent);
164
- }
165
- while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
166
- x -= e2.scrollLeft;
167
- y -= e2.scrollTop;
168
- }
169
- return [x, y];
170
- },
171
-
172
-
173
- getElementSize : function(e) {
174
- return [e.offsetWidth, e.offsetHeight];
175
- },
176
-
177
-
178
- getRelMousePos : function(e) {
179
- var x = 0, y = 0;
180
- if (!e) { e = window.event; }
181
- if (typeof e.offsetX === 'number') {
182
- x = e.offsetX;
183
- y = e.offsetY;
184
- } else if (typeof e.layerX === 'number') {
185
- x = e.layerX;
186
- y = e.layerY;
187
- }
188
- return { x: x, y: y };
189
- },
190
-
191
-
192
- getViewPos : function() {
193
- if(typeof window.pageYOffset === 'number') {
194
- return [window.pageXOffset, window.pageYOffset];
195
- } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
196
- return [document.body.scrollLeft, document.body.scrollTop];
197
- } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
198
- return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
199
- } else {
200
- return [0, 0];
201
- }
202
- },
203
-
204
-
205
- getViewSize : function() {
206
- if(typeof window.innerWidth === 'number') {
207
- return [window.innerWidth, window.innerHeight];
208
- } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
209
- return [document.body.clientWidth, document.body.clientHeight];
210
- } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
211
- return [document.documentElement.clientWidth, document.documentElement.clientHeight];
212
- } else {
213
- return [0, 0];
214
- }
215
- },
216
-
217
-
218
- URI : function(uri) { // See RFC3986
219
-
220
- this.scheme = null;
221
- this.authority = null;
222
- this.path = '';
223
- this.query = null;
224
- this.fragment = null;
225
-
226
- this.parse = function(uri) {
227
- var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
228
- this.scheme = m[3] ? m[2] : null;
229
- this.authority = m[5] ? m[6] : null;
230
- this.path = m[7];
231
- this.query = m[9] ? m[10] : null;
232
- this.fragment = m[12] ? m[13] : null;
233
- return this;
234
- };
235
-
236
- this.toString = function() {
237
- var result = '';
238
- if(this.scheme !== null) { result = result + this.scheme + ':'; }
239
- if(this.authority !== null) { result = result + '//' + this.authority; }
240
- if(this.path !== null) { result = result + this.path; }
241
- if(this.query !== null) { result = result + '?' + this.query; }
242
- if(this.fragment !== null) { result = result + '#' + this.fragment; }
243
- return result;
244
- };
245
-
246
- this.toAbsolute = function(base) {
247
- var base = new jscolor.URI(base);
248
- var r = this;
249
- var t = new jscolor.URI;
250
-
251
- if(base.scheme === null) { return false; }
252
-
253
- if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
254
- r.scheme = null;
255
- }
256
-
257
- if(r.scheme !== null) {
258
- t.scheme = r.scheme;
259
- t.authority = r.authority;
260
- t.path = removeDotSegments(r.path);
261
- t.query = r.query;
262
- } else {
263
- if(r.authority !== null) {
264
- t.authority = r.authority;
265
- t.path = removeDotSegments(r.path);
266
- t.query = r.query;
267
- } else {
268
- if(r.path === '') {
269
- t.path = base.path;
270
- if(r.query !== null) {
271
- t.query = r.query;
272
- } else {
273
- t.query = base.query;
274
- }
275
- } else {
276
- if(r.path.substr(0,1) === '/') {
277
- t.path = removeDotSegments(r.path);
278
- } else {
279
- if(base.authority !== null && base.path === '') {
280
- t.path = '/'+r.path;
281
- } else {
282
- t.path = base.path.replace(/[^\/]+$/,'')+r.path;
283
- }
284
- t.path = removeDotSegments(t.path);
285
- }
286
- t.query = r.query;
287
- }
288
- t.authority = base.authority;
289
- }
290
- t.scheme = base.scheme;
291
- }
292
- t.fragment = r.fragment;
293
-
294
- return t;
295
- };
296
-
297
- function removeDotSegments(path) {
298
- var out = '';
299
- while(path) {
300
- if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
301
- path = path.replace(/^\.+/,'').substr(1);
302
- } else if(path.substr(0,3)==='/./' || path==='/.') {
303
- path = '/'+path.substr(3);
304
- } else if(path.substr(0,4)==='/../' || path==='/..') {
305
- path = '/'+path.substr(4);
306
- out = out.replace(/\/?[^\/]*$/, '');
307
- } else if(path==='.' || path==='..') {
308
- path = '';
309
- } else {
310
- var rm = path.match(/^\/?[^\/]*/)[0];
311
- path = path.substr(rm.length);
312
- out = out + rm;
313
- }
314
- }
315
- return out;
316
- }
317
-
318
- if(uri) {
319
- this.parse(uri);
320
- }
321
-
322
- },
323
-
324
-
325
- //
326
- // Usage example:
327
- // var myColor = new jscolor.color(myInputElement)
328
- //
329
-
330
- color : function(target, prop) {
331
-
332
-
333
- this.required = true; // refuse empty values?
334
- this.adjust = true; // adjust value to uniform notation?
335
- this.hash = false; // prefix color with # symbol?
336
- this.caps = true; // uppercase?
337
- this.slider = true; // show the value/saturation slider?
338
- this.valueElement = target; // value holder
339
- this.styleElement = target; // where to reflect current color
340
- this.onImmediateChange = null; // onchange callback (can be either string or function)
341
- this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1
342
- this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1
343
- this.minH = 0; // read-only 0-6
344
- this.maxH = 6; // read-only 0-6
345
- this.minS = 0; // read-only 0-1
346
- this.maxS = 1; // read-only 0-1
347
- this.minV = 0; // read-only 0-1
348
- this.maxV = 1; // read-only 0-1
349
-
350
- this.pickerOnfocus = true; // display picker on focus?
351
- this.pickerMode = 'HSV'; // HSV | HVS
352
- this.pickerPosition = 'bottom'; // left | right | top | bottom
353
- this.pickerSmartPosition = true; // automatically adjust picker position when necessary
354
- this.pickerButtonHeight = 20; // px
355
- this.pickerClosable = false;
356
- this.pickerCloseText = 'Close';
357
- this.pickerButtonColor = 'ButtonText'; // px
358
- this.pickerFace = 10; // px
359
- this.pickerFaceColor = 'ThreeDFace'; // CSS color
360
- this.pickerBorder = 1; // px
361
- this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
362
- this.pickerInset = 1; // px
363
- this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
364
- this.pickerZIndex = 10000;
365
-
366
-
367
- for(var p in prop) {
368
- if(prop.hasOwnProperty(p)) {
369
- this[p] = prop[p];
370
- }
371
- }
372
-
373
-
374
- this.hidePicker = function() {
375
- if(isPickerOwner()) {
376
- removePicker();
377
- }
378
- };
379
-
380
-
381
- this.showPicker = function() {
382
- if(!isPickerOwner()) {
383
- var tp = jscolor.getElementPos(target); // target pos
384
- var ts = jscolor.getElementSize(target); // target size
385
- var vp = jscolor.getViewPos(); // view pos
386
- var vs = jscolor.getViewSize(); // view size
387
- var ps = getPickerDims(this); // picker size
388
- var a, b, c;
389
- switch(this.pickerPosition.toLowerCase()) {
390
- case 'left': a=1; b=0; c=-1; break;
391
- case 'right':a=1; b=0; c=1; break;
392
- case 'top': a=0; b=1; c=-1; break;
393
- default: a=0; b=1; c=1; break;
394
- }
395
- var l = (ts[b]+ps[b])/2;
396
-
397
- // picker pos
398
- if (!this.pickerSmartPosition) {
399
- var pp = [
400
- tp[a],
401
- tp[b]+ts[b]-l+l*c
402
- ];
403
- } else {
404
- var pp = [
405
- -vp[a]+tp[a]+ps[a] > vs[a] ?
406
- (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
407
- tp[a],
408
- -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
409
- (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
410
- (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
411
- ];
412
- }
413
- drawPicker(pp[a], pp[b]);
414
- }
415
- };
416
-
417
-
418
- this.importColor = function() {
419
- if(!valueElement) {
420
- this.exportColor();
421
- } else {
422
- if(!this.adjust) {
423
- if(!this.fromString(valueElement.value, leaveValue)) {
424
- styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
425
- styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
426
- styleElement.style.color = styleElement.jscStyle.color;
427
- this.exportColor(leaveValue | leaveStyle);
428
- }
429
- } else if(!this.required && /^\s*$/.test(valueElement.value)) {
430
- valueElement.value = '';
431
- styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
432
- styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
433
- styleElement.style.color = styleElement.jscStyle.color;
434
- this.exportColor(leaveValue | leaveStyle);
435
-
436
- } else if(this.fromString(valueElement.value)) {
437
- // OK
438
- } else {
439
- this.exportColor();
440
- }
441
- }
442
- };
443
-
444
-
445
- this.exportColor = function(flags) {
446
- if(!(flags & leaveValue) && valueElement) {
447
- var value = this.toString();
448
- if(this.caps) { value = value.toUpperCase(); }
449
- if(this.hash) { value = '#'+value; }
450
- valueElement.value = value;
451
- }
452
- if(!(flags & leaveStyle) && styleElement) {
453
- styleElement.style.backgroundImage = "none";
454
- styleElement.style.backgroundColor =
455
- '#'+this.toString();
456
- styleElement.style.color =
457
- 0.213 * this.rgb[0] +
458
- 0.715 * this.rgb[1] +
459
- 0.072 * this.rgb[2]
460
- < 0.5 ? '#FFF' : '#000';
461
- }
462
- if(!(flags & leavePad) && isPickerOwner()) {
463
- redrawPad();
464
- }
465
- if(!(flags & leaveSld) && isPickerOwner()) {
466
- redrawSld();
467
- }
468
- };
469
-
470
-
471
- this.fromHSV = function(h, s, v, flags) { // null = don't change
472
- if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); }
473
- if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); }
474
- if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); }
475
-
476
- this.rgb = HSV_RGB(
477
- h===null ? this.hsv[0] : (this.hsv[0]=h),
478
- s===null ? this.hsv[1] : (this.hsv[1]=s),
479
- v===null ? this.hsv[2] : (this.hsv[2]=v)
480
- );
481
-
482
- this.exportColor(flags);
483
- };
484
-
485
-
486
- this.fromRGB = function(r, g, b, flags) { // null = don't change
487
- if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); }
488
- if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); }
489
- if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); }
490
-
491
- var hsv = RGB_HSV(
492
- r===null ? this.rgb[0] : r,
493
- g===null ? this.rgb[1] : g,
494
- b===null ? this.rgb[2] : b
495
- );
496
- if(hsv[0] !== null) {
497
- this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0]));
498
- }
499
- if(hsv[2] !== 0) {
500
- this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1]));
501
- }
502
- this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2]));
503
-
504
- // update RGB according to final HSV, as some values might be trimmed
505
- var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
506
- this.rgb[0] = rgb[0];
507
- this.rgb[1] = rgb[1];
508
- this.rgb[2] = rgb[2];
509
-
510
- this.exportColor(flags);
511
- };
512
-
513
-
514
- this.fromString = function(hex, flags) {
515
- var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
516
- if(!m) {
517
- return false;
518
- } else {
519
- if(m[1].length === 6) { // 6-char notation
520
- this.fromRGB(
521
- parseInt(m[1].substr(0,2),16) / 255,
522
- parseInt(m[1].substr(2,2),16) / 255,
523
- parseInt(m[1].substr(4,2),16) / 255,
524
- flags
525
- );
526
- } else { // 3-char notation
527
- this.fromRGB(
528
- parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
529
- parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
530
- parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
531
- flags
532
- );
533
- }
534
- return true;
535
- }
536
- };
537
-
538
-
539
- this.toString = function() {
540
- return (
541
- (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
542
- (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
543
- (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
544
- );
545
- };
546
-
547
-
548
- function RGB_HSV(r, g, b) {
549
- var n = Math.min(Math.min(r,g),b);
550
- var v = Math.max(Math.max(r,g),b);
551
- var m = v - n;
552
- if(m === 0) { return [ null, 0, v ]; }
553
- var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
554
- return [ h===6?0:h, m/v, v ];
555
- }
556
-
557
-
558
- function HSV_RGB(h, s, v) {
559
- if(h === null) { return [ v, v, v ]; }
560
- var i = Math.floor(h);
561
- var f = i%2 ? h-i : 1-(h-i);
562
- var m = v * (1 - s);
563
- var n = v * (1 - s*f);
564
- switch(i) {
565
- case 6:
566
- case 0: return [v,n,m];
567
- case 1: return [n,v,m];
568
- case 2: return [m,v,n];
569
- case 3: return [m,n,v];
570
- case 4: return [n,m,v];
571
- case 5: return [v,m,n];
572
- }
573
- }
574
-
575
-
576
- function removePicker() {
577
- delete jscolor.picker.owner;
578
- document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
579
- }
580
-
581
-
582
- function drawPicker(x, y) {
583
- if(!jscolor.picker) {
584
- jscolor.picker = {
585
- box : document.createElement('div'),
586
- boxB : document.createElement('div'),
587
- pad : document.createElement('div'),
588
- padB : document.createElement('div'),
589
- padM : document.createElement('div'),
590
- sld : document.createElement('div'),
591
- sldB : document.createElement('div'),
592
- sldM : document.createElement('div'),
593
- btn : document.createElement('div'),
594
- btnS : document.createElement('span'),
595
- btnT : document.createTextNode(THIS.pickerCloseText)
596
- };
597
- for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
598
- var seg = document.createElement('div');
599
- seg.style.height = segSize+'px';
600
- seg.style.fontSize = '1px';
601
- seg.style.lineHeight = '0';
602
- jscolor.picker.sld.appendChild(seg);
603
- }
604
- jscolor.picker.sldB.appendChild(jscolor.picker.sld);
605
- jscolor.picker.box.appendChild(jscolor.picker.sldB);
606
- jscolor.picker.box.appendChild(jscolor.picker.sldM);
607
- jscolor.picker.padB.appendChild(jscolor.picker.pad);
608
- jscolor.picker.box.appendChild(jscolor.picker.padB);
609
- jscolor.picker.box.appendChild(jscolor.picker.padM);
610
- jscolor.picker.btnS.appendChild(jscolor.picker.btnT);
611
- jscolor.picker.btn.appendChild(jscolor.picker.btnS);
612
- jscolor.picker.box.appendChild(jscolor.picker.btn);
613
- jscolor.picker.boxB.appendChild(jscolor.picker.box);
614
- }
615
-
616
- var p = jscolor.picker;
617
-
618
- // controls interaction
619
- p.box.onmouseup =
620
- p.box.onmouseout = function() { target.focus(); };
621
- p.box.onmousedown = function() { abortBlur=true; };
622
- p.box.onmousemove = function(e) {
623
- if (holdPad || holdSld) {
624
- holdPad && setPad(e);
625
- holdSld && setSld(e);
626
- if (document.selection) {
627
- document.selection.empty();
628
- } else if (window.getSelection) {
629
- window.getSelection().removeAllRanges();
630
- }
631
- dispatchImmediateChange();
632
- }
633
- };
634
- if('ontouchstart' in window) { // if touch device
635
- var handle_touchmove = function(e) {
636
- var event={
637
- 'offsetX': e.touches[0].pageX-touchOffset.X,
638
- 'offsetY': e.touches[0].pageY-touchOffset.Y
639
- };
640
- if (holdPad || holdSld) {
641
- holdPad && setPad(event);
642
- holdSld && setSld(event);
643
- dispatchImmediateChange();
644
- }
645
- e.stopPropagation(); // prevent move "view" on broswer
646
- e.preventDefault(); // prevent Default - Android Fix (else android generated only 1-2 touchmove events)
647
- };
648
- p.box.removeEventListener('touchmove', handle_touchmove, false)
649
- p.box.addEventListener('touchmove', handle_touchmove, false)
650
- }
651
- p.padM.onmouseup =
652
- p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } };
653
- p.padM.onmousedown = function(e) {
654
- // if the slider is at the bottom, move it up
655
- switch(modeID) {
656
- case 0: if (THIS.hsv[2] === 0) { THIS.fromHSV(null, null, 1.0); }; break;
657
- case 1: if (THIS.hsv[1] === 0) { THIS.fromHSV(null, 1.0, null); }; break;
658
- }
659
- holdSld=false;
660
- holdPad=true;
661
- setPad(e);
662
- dispatchImmediateChange();
663
- };
664
- if('ontouchstart' in window) {
665
- p.padM.addEventListener('touchstart', function(e) {
666
- touchOffset={
667
- 'X': e.target.offsetParent.offsetLeft,
668
- 'Y': e.target.offsetParent.offsetTop
669
- };
670
- this.onmousedown({
671
- 'offsetX':e.touches[0].pageX-touchOffset.X,
672
- 'offsetY':e.touches[0].pageY-touchOffset.Y
673
- });
674
- });
675
- }
676
- p.sldM.onmouseup =
677
- p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } };
678
- p.sldM.onmousedown = function(e) {
679
- holdPad=false;
680
- holdSld=true;
681
- setSld(e);
682
- dispatchImmediateChange();
683
- };
684
- if('ontouchstart' in window) {
685
- p.sldM.addEventListener('touchstart', function(e) {
686
- touchOffset={
687
- 'X': e.target.offsetParent.offsetLeft,
688
- 'Y': e.target.offsetParent.offsetTop
689
- };
690
- this.onmousedown({
691
- 'offsetX':e.touches[0].pageX-touchOffset.X,
692
- 'offsetY':e.touches[0].pageY-touchOffset.Y
693
- });
694
- });
695
- }
696
-
697
- // picker
698
- var dims = getPickerDims(THIS);
699
- p.box.style.width = dims[0] + 'px';
700
- p.box.style.height = dims[1] + 'px';
701
-
702
- // picker border
703
- p.boxB.style.position = 'absolute';
704
- p.boxB.style.clear = 'both';
705
- p.boxB.style.left = x+'px';
706
- p.boxB.style.top = y+'px';
707
- p.boxB.style.zIndex = THIS.pickerZIndex;
708
- p.boxB.style.border = THIS.pickerBorder+'px solid';
709
- p.boxB.style.borderColor = THIS.pickerBorderColor;
710
- p.boxB.style.background = THIS.pickerFaceColor;
711
-
712
- // pad image
713
- p.pad.style.width = jscolor.images.pad[0]+'px';
714
- p.pad.style.height = jscolor.images.pad[1]+'px';
715
-
716
- // pad border
717
- p.padB.style.position = 'absolute';
718
- p.padB.style.left = THIS.pickerFace+'px';
719
- p.padB.style.top = THIS.pickerFace+'px';
720
- p.padB.style.border = THIS.pickerInset+'px solid';
721
- p.padB.style.borderColor = THIS.pickerInsetColor;
722
-
723
- // pad mouse area
724
- p.padM.style.position = 'absolute';
725
- p.padM.style.left = '0';
726
- p.padM.style.top = '0';
727
- p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
728
- p.padM.style.height = p.box.style.height;
729
- p.padM.style.cursor = 'crosshair';
730
-
731
- // slider image
732
- p.sld.style.overflow = 'hidden';
733
- p.sld.style.width = jscolor.images.sld[0]+'px';
734
- p.sld.style.height = jscolor.images.sld[1]+'px';
735
-
736
- // slider border
737
- p.sldB.style.display = THIS.slider ? 'block' : 'none';
738
- p.sldB.style.position = 'absolute';
739
- p.sldB.style.right = THIS.pickerFace+'px';
740
- p.sldB.style.top = THIS.pickerFace+'px';
741
- p.sldB.style.border = THIS.pickerInset+'px solid';
742
- p.sldB.style.borderColor = THIS.pickerInsetColor;
743
-
744
- // slider mouse area
745
- p.sldM.style.display = THIS.slider ? 'block' : 'none';
746
- p.sldM.style.position = 'absolute';
747
- p.sldM.style.right = '0';
748
- p.sldM.style.top = '0';
749
- p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
750
- p.sldM.style.height = p.box.style.height;
751
- try {
752
- p.sldM.style.cursor = 'pointer';
753
- } catch(eOldIE) {
754
- p.sldM.style.cursor = 'hand';
755
- }
756
-
757
- // "close" button
758
- function setBtnBorder() {
759
- var insetColors = THIS.pickerInsetColor.split(/\s+/);
760
- var pickerOutsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
761
- p.btn.style.borderColor = pickerOutsetColor;
762
- }
763
- p.btn.style.display = THIS.pickerClosable ? 'block' : 'none';
764
- p.btn.style.position = 'absolute';
765
- p.btn.style.left = THIS.pickerFace + 'px';
766
- p.btn.style.bottom = THIS.pickerFace + 'px';
767
- p.btn.style.padding = '0 15px';
768
- p.btn.style.height = '18px';
769
- p.btn.style.border = THIS.pickerInset + 'px solid';
770
- setBtnBorder();
771
- p.btn.style.color = THIS.pickerButtonColor;
772
- p.btn.style.font = '12px sans-serif';
773
- p.btn.style.textAlign = 'center';
774
- try {
775
- p.btn.style.cursor = 'pointer';
776
- } catch(eOldIE) {
777
- p.btn.style.cursor = 'hand';
778
- }
779
- p.btn.onmousedown = function () {
780
- THIS.hidePicker();
781
- };
782
- p.btnS.style.lineHeight = p.btn.style.height;
783
-
784
- // load images in optimal order
785
- switch(modeID) {
786
- case 0: var padImg = 'hs.png'; break;
787
- case 1: var padImg = 'hv.png'; break;
788
- }
789
- p.padM.style.backgroundImage = "url('"+jscolor.getDir()+"cross.gif')";
790
- p.padM.style.backgroundRepeat = "no-repeat";
791
- p.sldM.style.backgroundImage = "url('"+jscolor.getDir()+"arrow.gif')";
792
- p.sldM.style.backgroundRepeat = "no-repeat";
793
- p.pad.style.backgroundImage = "url('"+jscolor.getDir()+padImg+"')";
794
- p.pad.style.backgroundRepeat = "no-repeat";
795
- p.pad.style.backgroundPosition = "0 0";
796
-
797
- // place pointers
798
- redrawPad();
799
- redrawSld();
800
-
801
- jscolor.picker.owner = THIS;
802
- document.getElementsByTagName('body')[0].appendChild(p.boxB);
803
- }
804
-
805
-
806
- function getPickerDims(o) {
807
- var dims = [
808
- 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[0] +
809
- (o.slider ? 2*o.pickerInset + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] : 0),
810
- o.pickerClosable ?
811
- 4*o.pickerInset + 3*o.pickerFace + jscolor.images.pad[1] + o.pickerButtonHeight :
812
- 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[1]
813
- ];
814
- return dims;
815
- }
816
-
817
-
818
- function redrawPad() {
819
- // redraw the pad pointer
820
- switch(modeID) {
821
- case 0: var yComponent = 1; break;
822
- case 1: var yComponent = 2; break;
823
- }
824
- var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
825
- var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
826
- jscolor.picker.padM.style.backgroundPosition =
827
- (THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
828
- (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';
829
-
830
- // redraw the slider image
831
- var seg = jscolor.picker.sld.childNodes;
832
-
833
- switch(modeID) {
834
- case 0:
835
- var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
836
- for(var i=0; i<seg.length; i+=1) {
837
- seg[i].style.backgroundColor = 'rgb('+
838
- (rgb[0]*(1-i/seg.length)*100)+'%,'+
839
- (rgb[1]*(1-i/seg.length)*100)+'%,'+
840
- (rgb[2]*(1-i/seg.length)*100)+'%)';
841
- }
842
- break;
843
- case 1:
844
- var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
845
- var i = Math.floor(THIS.hsv[0]);
846
- var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
847
- switch(i) {
848
- case 6:
849
- case 0: rgb=[0,1,2]; break;
850
- case 1: rgb=[1,0,2]; break;
851
- case 2: rgb=[2,0,1]; break;
852
- case 3: rgb=[2,1,0]; break;
853
- case 4: rgb=[1,2,0]; break;
854
- case 5: rgb=[0,2,1]; break;
855
- }
856
- for(var i=0; i<seg.length; i+=1) {
857
- s = 1 - 1/(seg.length-1)*i;
858
- c[1] = c[0] * (1 - s*f);
859
- c[2] = c[0] * (1 - s);
860
- seg[i].style.backgroundColor = 'rgb('+
861
- (c[rgb[0]]*100)+'%,'+
862
- (c[rgb[1]]*100)+'%,'+
863
- (c[rgb[2]]*100)+'%)';
864
- }
865
- break;
866
- }
867
- }
868
-
869
-
870
- function redrawSld() {
871
- // redraw the slider pointer
872
- switch(modeID) {
873
- case 0: var yComponent = 2; break;
874
- case 1: var yComponent = 1; break;
875
- }
876
- var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
877
- jscolor.picker.sldM.style.backgroundPosition =
878
- '0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
879
- }
880
-
881
-
882
- function isPickerOwner() {
883
- return jscolor.picker && jscolor.picker.owner === THIS;
884
- }
885
-
886
-
887
- function blurTarget() {
888
- if(valueElement === target) {
889
- THIS.importColor();
890
- }
891
- if(THIS.pickerOnfocus) {
892
- THIS.hidePicker();
893
- }
894
- }
895
-
896
-
897
- function blurValue() {
898
- if(valueElement !== target) {
899
- THIS.importColor();
900
- }
901
- }
902
-
903
-
904
- function setPad(e) {
905
- var mpos = jscolor.getRelMousePos(e);
906
- var x = mpos.x - THIS.pickerFace - THIS.pickerInset;
907
- var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
908
- switch(modeID) {
909
- case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
910
- case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
911
- }
912
- }
913
-
914
-
915
- function setSld(e) {
916
- var mpos = jscolor.getRelMousePos(e);
917
- var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
918
- switch(modeID) {
919
- case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
920
- case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
921
- }
922
- }
923
-
924
-
925
- function dispatchImmediateChange() {
926
- if (THIS.onImmediateChange) {
927
- var callback;
928
- if (typeof THIS.onImmediateChange === 'string') {
929
- callback = new Function (THIS.onImmediateChange);
930
- } else {
931
- callback = THIS.onImmediateChange;
932
- }
933
- callback.call(THIS);
934
- }
935
- }
936
-
937
-
938
- var THIS = this;
939
- var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
940
- var abortBlur = false;
941
- var
942
- valueElement = jscolor.fetchElement(this.valueElement),
943
- styleElement = jscolor.fetchElement(this.styleElement);
944
- var
945
- holdPad = false,
946
- holdSld = false,
947
- touchOffset = {};
948
- var
949
- leaveValue = 1<<0,
950
- leaveStyle = 1<<1,
951
- leavePad = 1<<2,
952
- leaveSld = 1<<3;
953
-
954
- jscolor.isColorAttrSupported = false;
955
- var el = document.createElement('input');
956
- if(el.setAttribute) {
957
- el.setAttribute('type', 'color');
958
- if(el.type.toLowerCase() == 'color') {
959
- jscolor.isColorAttrSupported = true;
960
- }
961
- }
962
-
963
- // target
964
- jscolor.addEvent(target, 'focus', function() {
965
- if(THIS.pickerOnfocus) { THIS.showPicker(); }
966
- });
967
- jscolor.addEvent(target, 'blur', function() {
968
- if(!abortBlur) {
969
- window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
970
- } else {
971
- abortBlur = false;
972
- }
973
- });
974
-
975
- // valueElement
976
- if(valueElement) {
977
- var updateField = function() {
978
- THIS.fromString(valueElement.value, leaveValue);
979
- dispatchImmediateChange();
980
- };
981
- jscolor.addEvent(valueElement, 'keyup', updateField);
982
- jscolor.addEvent(valueElement, 'input', updateField);
983
- jscolor.addEvent(valueElement, 'blur', blurValue);
984
- valueElement.setAttribute('autocomplete', 'off');
985
- }
986
-
987
- // styleElement
988
- if(styleElement) {
989
- styleElement.jscStyle = {
990
- backgroundImage : styleElement.style.backgroundImage,
991
- backgroundColor : styleElement.style.backgroundColor,
992
- color : styleElement.style.color
993
- };
994
- }
995
-
996
- // require images
997
- switch(modeID) {
998
- case 0: jscolor.requireImage('hs.png'); break;
999
- case 1: jscolor.requireImage('hv.png'); break;
1000
- }
1001
- jscolor.requireImage('cross.gif');
1002
- jscolor.requireImage('arrow.gif');
1003
-
1004
- this.importColor();
1005
- }
1006
-
1007
- };
1008
-
1009
-
1010
- jscolor.install();
1
+ /**
2
+ * jscolor, JavaScript Color Picker
3
+ *
4
+ * @version 1.4.4
5
+ * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
6
+ * @author Jan Odvarko, http://odvarko.cz
7
+ * @created 2008-06-15
8
+ * @updated 2014-12-09
9
+ * @link http://jscolor.com
10
+ */
11
+
12
+
13
+ var jscolor = {
14
+
15
+
16
+ dir : '', // location of jscolor directory (leave empty to autodetect)
17
+ bindClass : 'color', // class name
18
+ binding : true, // automatic binding via <input class="...">
19
+ preloading : true, // use image preloading?
20
+
21
+
22
+ install : function() {
23
+ jscolor.addEvent(window, 'load', jscolor.init);
24
+ },
25
+
26
+
27
+ init : function() {
28
+ if(jscolor.binding) {
29
+ jscolor.bind();
30
+ }
31
+ if(jscolor.preloading) {
32
+ jscolor.preload();
33
+ }
34
+ },
35
+
36
+
37
+ getDir : function() {
38
+ if(!jscolor.dir) {
39
+ var detected = jscolor.detectDir();
40
+ jscolor.dir = detected!==false ? detected : 'jscolor/';
41
+ }
42
+ return jscolor.dir;
43
+ },
44
+
45
+
46
+ detectDir : function() {
47
+ var base = location.href;
48
+
49
+ var e = document.getElementsByTagName('base');
50
+ for(var i=0; i<e.length; i+=1) {
51
+ if(e[i].href) { base = e[i].href; }
52
+ }
53
+
54
+ var e = document.getElementsByTagName('script');
55
+ for(var i=0; i<e.length; i+=1) {
56
+ if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
57
+ var src = new jscolor.URI(e[i].src);
58
+ var srcAbs = src.toAbsolute(base);
59
+ srcAbs.path = srcAbs.path.replace(/[^\/]+$/, ''); // remove filename
60
+ srcAbs.query = null;
61
+ srcAbs.fragment = null;
62
+ return srcAbs.toString();
63
+ }
64
+ }
65
+ return false;
66
+ },
67
+
68
+
69
+ bind : function() {
70
+ var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')(\\s*(\\{[^}]*\\})|\\s|$)', 'i');
71
+ var e = document.getElementsByTagName('input');
72
+ for(var i=0; i<e.length; i+=1) {
73
+ if(jscolor.isColorAttrSupported && e[i].type.toLowerCase() == 'color') {
74
+ // skip inputs of type 'color' if the browser supports this feature
75
+ continue;
76
+ }
77
+ var m;
78
+ if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
79
+ var prop = {};
80
+ if(m[4]) {
81
+ try {
82
+ prop = (new Function ('return (' + m[4] + ')'))();
83
+ } catch(eInvalidProp) {}
84
+ }
85
+ e[i].color = new jscolor.color(e[i], prop);
86
+ }
87
+ }
88
+ },
89
+
90
+
91
+ preload : function() {
92
+ for(var fn in jscolor.imgRequire) {
93
+ if(jscolor.imgRequire.hasOwnProperty(fn)) {
94
+ jscolor.loadImage(fn);
95
+ }
96
+ }
97
+ },
98
+
99
+
100
+ images : {
101
+ pad : [ 181, 101 ],
102
+ sld : [ 16, 101 ],
103
+ cross : [ 15, 15 ],
104
+ arrow : [ 7, 11 ]
105
+ },
106
+
107
+
108
+ imgRequire : {},
109
+ imgLoaded : {},
110
+
111
+
112
+ requireImage : function(filename) {
113
+ jscolor.imgRequire[filename] = true;
114
+ },
115
+
116
+
117
+ loadImage : function(filename) {
118
+ if(!jscolor.imgLoaded[filename]) {
119
+ jscolor.imgLoaded[filename] = new Image();
120
+ jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
121
+ }
122
+ },
123
+
124
+
125
+ fetchElement : function(mixed) {
126
+ return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
127
+ },
128
+
129
+
130
+ addEvent : function(el, evnt, func) {
131
+ if(el.addEventListener) {
132
+ el.addEventListener(evnt, func, false);
133
+ } else if(el.attachEvent) {
134
+ el.attachEvent('on'+evnt, func);
135
+ }
136
+ },
137
+
138
+
139
+ fireEvent : function(el, evnt) {
140
+ if(!el) {
141
+ return;
142
+ }
143
+ if(document.createEvent) {
144
+ var ev = document.createEvent('HTMLEvents');
145
+ ev.initEvent(evnt, true, true);
146
+ el.dispatchEvent(ev);
147
+ } else if(document.createEventObject) {
148
+ var ev = document.createEventObject();
149
+ el.fireEvent('on'+evnt, ev);
150
+ } else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
151
+ el['on'+evnt]();
152
+ }
153
+ },
154
+
155
+
156
+ getElementPos : function(e) {
157
+ var e1=e, e2=e;
158
+ var x=0, y=0;
159
+ if(e1.offsetParent) {
160
+ do {
161
+ x += e1.offsetLeft;
162
+ y += e1.offsetTop;
163
+ } while(e1 = e1.offsetParent);
164
+ }
165
+ while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
166
+ x -= e2.scrollLeft;
167
+ y -= e2.scrollTop;
168
+ }
169
+ return [x, y];
170
+ },
171
+
172
+
173
+ getElementSize : function(e) {
174
+ return [e.offsetWidth, e.offsetHeight];
175
+ },
176
+
177
+
178
+ getRelMousePos : function(e) {
179
+ var x = 0, y = 0;
180
+ if (!e) { e = window.event; }
181
+ if (typeof e.offsetX === 'number') {
182
+ x = e.offsetX;
183
+ y = e.offsetY;
184
+ } else if (typeof e.layerX === 'number') {
185
+ x = e.layerX;
186
+ y = e.layerY;
187
+ }
188
+ return { x: x, y: y };
189
+ },
190
+
191
+
192
+ getViewPos : function() {
193
+ if(typeof window.pageYOffset === 'number') {
194
+ return [window.pageXOffset, window.pageYOffset];
195
+ } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
196
+ return [document.body.scrollLeft, document.body.scrollTop];
197
+ } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
198
+ return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
199
+ } else {
200
+ return [0, 0];
201
+ }
202
+ },
203
+
204
+
205
+ getViewSize : function() {
206
+ if(typeof window.innerWidth === 'number') {
207
+ return [window.innerWidth, window.innerHeight];
208
+ } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
209
+ return [document.body.clientWidth, document.body.clientHeight];
210
+ } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
211
+ return [document.documentElement.clientWidth, document.documentElement.clientHeight];
212
+ } else {
213
+ return [0, 0];
214
+ }
215
+ },
216
+
217
+
218
+ URI : function(uri) { // See RFC3986
219
+
220
+ this.scheme = null;
221
+ this.authority = null;
222
+ this.path = '';
223
+ this.query = null;
224
+ this.fragment = null;
225
+
226
+ this.parse = function(uri) {
227
+ var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
228
+ this.scheme = m[3] ? m[2] : null;
229
+ this.authority = m[5] ? m[6] : null;
230
+ this.path = m[7];
231
+ this.query = m[9] ? m[10] : null;
232
+ this.fragment = m[12] ? m[13] : null;
233
+ return this;
234
+ };
235
+
236
+ this.toString = function() {
237
+ var result = '';
238
+ if(this.scheme !== null) { result = result + this.scheme + ':'; }
239
+ if(this.authority !== null) { result = result + '//' + this.authority; }
240
+ if(this.path !== null) { result = result + this.path; }
241
+ if(this.query !== null) { result = result + '?' + this.query; }
242
+ if(this.fragment !== null) { result = result + '#' + this.fragment; }
243
+ return result;
244
+ };
245
+
246
+ this.toAbsolute = function(base) {
247
+ var base = new jscolor.URI(base);
248
+ var r = this;
249
+ var t = new jscolor.URI;
250
+
251
+ if(base.scheme === null) { return false; }
252
+
253
+ if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
254
+ r.scheme = null;
255
+ }
256
+
257
+ if(r.scheme !== null) {
258
+ t.scheme = r.scheme;
259
+ t.authority = r.authority;
260
+ t.path = removeDotSegments(r.path);
261
+ t.query = r.query;
262
+ } else {
263
+ if(r.authority !== null) {
264
+ t.authority = r.authority;
265
+ t.path = removeDotSegments(r.path);
266
+ t.query = r.query;
267
+ } else {
268
+ if(r.path === '') {
269
+ t.path = base.path;
270
+ if(r.query !== null) {
271
+ t.query = r.query;
272
+ } else {
273
+ t.query = base.query;
274
+ }
275
+ } else {
276
+ if(r.path.substr(0,1) === '/') {
277
+ t.path = removeDotSegments(r.path);
278
+ } else {
279
+ if(base.authority !== null && base.path === '') {
280
+ t.path = '/'+r.path;
281
+ } else {
282
+ t.path = base.path.replace(/[^\/]+$/,'')+r.path;
283
+ }
284
+ t.path = removeDotSegments(t.path);
285
+ }
286
+ t.query = r.query;
287
+ }
288
+ t.authority = base.authority;
289
+ }
290
+ t.scheme = base.scheme;
291
+ }
292
+ t.fragment = r.fragment;
293
+
294
+ return t;
295
+ };
296
+
297
+ function removeDotSegments(path) {
298
+ var out = '';
299
+ while(path) {
300
+ if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
301
+ path = path.replace(/^\.+/,'').substr(1);
302
+ } else if(path.substr(0,3)==='/./' || path==='/.') {
303
+ path = '/'+path.substr(3);
304
+ } else if(path.substr(0,4)==='/../' || path==='/..') {
305
+ path = '/'+path.substr(4);
306
+ out = out.replace(/\/?[^\/]*$/, '');
307
+ } else if(path==='.' || path==='..') {
308
+ path = '';
309
+ } else {
310
+ var rm = path.match(/^\/?[^\/]*/)[0];
311
+ path = path.substr(rm.length);
312
+ out = out + rm;
313
+ }
314
+ }
315
+ return out;
316
+ }
317
+
318
+ if(uri) {
319
+ this.parse(uri);
320
+ }
321
+
322
+ },
323
+
324
+
325
+ //
326
+ // Usage example:
327
+ // var myColor = new jscolor.color(myInputElement)
328
+ //
329
+
330
+ color : function(target, prop) {
331
+
332
+
333
+ this.required = true; // refuse empty values?
334
+ this.adjust = true; // adjust value to uniform notation?
335
+ this.hash = false; // prefix color with # symbol?
336
+ this.caps = true; // uppercase?
337
+ this.slider = true; // show the value/saturation slider?
338
+ this.valueElement = target; // value holder
339
+ this.styleElement = target; // where to reflect current color
340
+ this.onImmediateChange = null; // onchange callback (can be either string or function)
341
+ this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1
342
+ this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1
343
+ this.minH = 0; // read-only 0-6
344
+ this.maxH = 6; // read-only 0-6
345
+ this.minS = 0; // read-only 0-1
346
+ this.maxS = 1; // read-only 0-1
347
+ this.minV = 0; // read-only 0-1
348
+ this.maxV = 1; // read-only 0-1
349
+
350
+ this.pickerOnfocus = true; // display picker on focus?
351
+ this.pickerMode = 'HSV'; // HSV | HVS
352
+ this.pickerPosition = 'bottom'; // left | right | top | bottom
353
+ this.pickerSmartPosition = true; // automatically adjust picker position when necessary
354
+ this.pickerButtonHeight = 20; // px
355
+ this.pickerClosable = false;
356
+ this.pickerCloseText = 'Close';
357
+ this.pickerButtonColor = 'ButtonText'; // px
358
+ this.pickerFace = 10; // px
359
+ this.pickerFaceColor = 'ThreeDFace'; // CSS color
360
+ this.pickerBorder = 1; // px
361
+ this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
362
+ this.pickerInset = 1; // px
363
+ this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
364
+ this.pickerZIndex = 10000;
365
+
366
+
367
+ for(var p in prop) {
368
+ if(prop.hasOwnProperty(p)) {
369
+ this[p] = prop[p];
370
+ }
371
+ }
372
+
373
+
374
+ this.hidePicker = function() {
375
+ if(isPickerOwner()) {
376
+ removePicker();
377
+ }
378
+ };
379
+
380
+
381
+ this.showPicker = function() {
382
+ if(!isPickerOwner()) {
383
+ var tp = jscolor.getElementPos(target); // target pos
384
+ var ts = jscolor.getElementSize(target); // target size
385
+ var vp = jscolor.getViewPos(); // view pos
386
+ var vs = jscolor.getViewSize(); // view size
387
+ var ps = getPickerDims(this); // picker size
388
+ var a, b, c;
389
+ switch(this.pickerPosition.toLowerCase()) {
390
+ case 'left': a=1; b=0; c=-1; break;
391
+ case 'right':a=1; b=0; c=1; break;
392
+ case 'top': a=0; b=1; c=-1; break;
393
+ default: a=0; b=1; c=1; break;
394
+ }
395
+ var l = (ts[b]+ps[b])/2;
396
+
397
+ // picker pos
398
+ if (!this.pickerSmartPosition) {
399
+ var pp = [
400
+ tp[a],
401
+ tp[b]+ts[b]-l+l*c
402
+ ];
403
+ } else {
404
+ var pp = [
405
+ -vp[a]+tp[a]+ps[a] > vs[a] ?
406
+ (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
407
+ tp[a],
408
+ -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
409
+ (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
410
+ (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
411
+ ];
412
+ }
413
+ drawPicker(pp[a], pp[b]);
414
+ }
415
+ };
416
+
417
+
418
+ this.importColor = function() {
419
+ if(!valueElement) {
420
+ this.exportColor();
421
+ } else {
422
+ if(!this.adjust) {
423
+ if(!this.fromString(valueElement.value, leaveValue)) {
424
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
425
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
426
+ styleElement.style.color = styleElement.jscStyle.color;
427
+ this.exportColor(leaveValue | leaveStyle);
428
+ }
429
+ } else if(!this.required && /^\s*$/.test(valueElement.value)) {
430
+ valueElement.value = '';
431
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
432
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
433
+ styleElement.style.color = styleElement.jscStyle.color;
434
+ this.exportColor(leaveValue | leaveStyle);
435
+
436
+ } else if(this.fromString(valueElement.value)) {
437
+ // OK
438
+ } else {
439
+ this.exportColor();
440
+ }
441
+ }
442
+ };
443
+
444
+
445
+ this.exportColor = function(flags) {
446
+ if(!(flags & leaveValue) && valueElement) {
447
+ var value = this.toString();
448
+ if(this.caps) { value = value.toUpperCase(); }
449
+ if(this.hash) { value = '#'+value; }
450
+ valueElement.value = value;
451
+ }
452
+ if(!(flags & leaveStyle) && styleElement) {
453
+ styleElement.style.backgroundImage = "none";
454
+ styleElement.style.backgroundColor =
455
+ '#'+this.toString();
456
+ styleElement.style.color =
457
+ 0.213 * this.rgb[0] +
458
+ 0.715 * this.rgb[1] +
459
+ 0.072 * this.rgb[2]
460
+ < 0.5 ? '#FFF' : '#000';
461
+ }
462
+ if(!(flags & leavePad) && isPickerOwner()) {
463
+ redrawPad();
464
+ }
465
+ if(!(flags & leaveSld) && isPickerOwner()) {
466
+ redrawSld();
467
+ }
468
+ };
469
+
470
+
471
+ this.fromHSV = function(h, s, v, flags) { // null = don't change
472
+ if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); }
473
+ if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); }
474
+ if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); }
475
+
476
+ this.rgb = HSV_RGB(
477
+ h===null ? this.hsv[0] : (this.hsv[0]=h),
478
+ s===null ? this.hsv[1] : (this.hsv[1]=s),
479
+ v===null ? this.hsv[2] : (this.hsv[2]=v)
480
+ );
481
+
482
+ this.exportColor(flags);
483
+ };
484
+
485
+
486
+ this.fromRGB = function(r, g, b, flags) { // null = don't change
487
+ if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); }
488
+ if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); }
489
+ if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); }
490
+
491
+ var hsv = RGB_HSV(
492
+ r===null ? this.rgb[0] : r,
493
+ g===null ? this.rgb[1] : g,
494
+ b===null ? this.rgb[2] : b
495
+ );
496
+ if(hsv[0] !== null) {
497
+ this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0]));
498
+ }
499
+ if(hsv[2] !== 0) {
500
+ this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1]));
501
+ }
502
+ this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2]));
503
+
504
+ // update RGB according to final HSV, as some values might be trimmed
505
+ var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
506
+ this.rgb[0] = rgb[0];
507
+ this.rgb[1] = rgb[1];
508
+ this.rgb[2] = rgb[2];
509
+
510
+ this.exportColor(flags);
511
+ };
512
+
513
+
514
+ this.fromString = function(hex, flags) {
515
+ var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
516
+ if(!m) {
517
+ return false;
518
+ } else {
519
+ if(m[1].length === 6) { // 6-char notation
520
+ this.fromRGB(
521
+ parseInt(m[1].substr(0,2),16) / 255,
522
+ parseInt(m[1].substr(2,2),16) / 255,
523
+ parseInt(m[1].substr(4,2),16) / 255,
524
+ flags
525
+ );
526
+ } else { // 3-char notation
527
+ this.fromRGB(
528
+ parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
529
+ parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
530
+ parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
531
+ flags
532
+ );
533
+ }
534
+ return true;
535
+ }
536
+ };
537
+
538
+
539
+ this.toString = function() {
540
+ return (
541
+ (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
542
+ (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
543
+ (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
544
+ );
545
+ };
546
+
547
+
548
+ function RGB_HSV(r, g, b) {
549
+ var n = Math.min(Math.min(r,g),b);
550
+ var v = Math.max(Math.max(r,g),b);
551
+ var m = v - n;
552
+ if(m === 0) { return [ null, 0, v ]; }
553
+ var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
554
+ return [ h===6?0:h, m/v, v ];
555
+ }
556
+
557
+
558
+ function HSV_RGB(h, s, v) {
559
+ if(h === null) { return [ v, v, v ]; }
560
+ var i = Math.floor(h);
561
+ var f = i%2 ? h-i : 1-(h-i);
562
+ var m = v * (1 - s);
563
+ var n = v * (1 - s*f);
564
+ switch(i) {
565
+ case 6:
566
+ case 0: return [v,n,m];
567
+ case 1: return [n,v,m];
568
+ case 2: return [m,v,n];
569
+ case 3: return [m,n,v];
570
+ case 4: return [n,m,v];
571
+ case 5: return [v,m,n];
572
+ }
573
+ }
574
+
575
+
576
+ function removePicker() {
577
+ delete jscolor.picker.owner;
578
+ document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
579
+ }
580
+
581
+
582
+ function drawPicker(x, y) {
583
+ if(!jscolor.picker) {
584
+ jscolor.picker = {
585
+ box : document.createElement('div'),
586
+ boxB : document.createElement('div'),
587
+ pad : document.createElement('div'),
588
+ padB : document.createElement('div'),
589
+ padM : document.createElement('div'),
590
+ sld : document.createElement('div'),
591
+ sldB : document.createElement('div'),
592
+ sldM : document.createElement('div'),
593
+ btn : document.createElement('div'),
594
+ btnS : document.createElement('span'),
595
+ btnT : document.createTextNode(THIS.pickerCloseText)
596
+ };
597
+ for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
598
+ var seg = document.createElement('div');
599
+ seg.style.height = segSize+'px';
600
+ seg.style.fontSize = '1px';
601
+ seg.style.lineHeight = '0';
602
+ jscolor.picker.sld.appendChild(seg);
603
+ }
604
+ jscolor.picker.sldB.appendChild(jscolor.picker.sld);
605
+ jscolor.picker.box.appendChild(jscolor.picker.sldB);
606
+ jscolor.picker.box.appendChild(jscolor.picker.sldM);
607
+ jscolor.picker.padB.appendChild(jscolor.picker.pad);
608
+ jscolor.picker.box.appendChild(jscolor.picker.padB);
609
+ jscolor.picker.box.appendChild(jscolor.picker.padM);
610
+ jscolor.picker.btnS.appendChild(jscolor.picker.btnT);
611
+ jscolor.picker.btn.appendChild(jscolor.picker.btnS);
612
+ jscolor.picker.box.appendChild(jscolor.picker.btn);
613
+ jscolor.picker.boxB.appendChild(jscolor.picker.box);
614
+ }
615
+
616
+ var p = jscolor.picker;
617
+
618
+ // controls interaction
619
+ p.box.onmouseup =
620
+ p.box.onmouseout = function() { target.focus(); };
621
+ p.box.onmousedown = function() { abortBlur=true; };
622
+ p.box.onmousemove = function(e) {
623
+ if (holdPad || holdSld) {
624
+ holdPad && setPad(e);
625
+ holdSld && setSld(e);
626
+ if (document.selection) {
627
+ document.selection.empty();
628
+ } else if (window.getSelection) {
629
+ window.getSelection().removeAllRanges();
630
+ }
631
+ dispatchImmediateChange();
632
+ }
633
+ };
634
+ if('ontouchstart' in window) { // if touch device
635
+ var handle_touchmove = function(e) {
636
+ var event={
637
+ 'offsetX': e.touches[0].pageX-touchOffset.X,
638
+ 'offsetY': e.touches[0].pageY-touchOffset.Y
639
+ };
640
+ if (holdPad || holdSld) {
641
+ holdPad && setPad(event);
642
+ holdSld && setSld(event);
643
+ dispatchImmediateChange();
644
+ }
645
+ e.stopPropagation(); // prevent move "view" on broswer
646
+ e.preventDefault(); // prevent Default - Android Fix (else android generated only 1-2 touchmove events)
647
+ };
648
+ p.box.removeEventListener('touchmove', handle_touchmove, false)
649
+ p.box.addEventListener('touchmove', handle_touchmove, false)
650
+ }
651
+ p.padM.onmouseup =
652
+ p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } };
653
+ p.padM.onmousedown = function(e) {
654
+ // if the slider is at the bottom, move it up
655
+ switch(modeID) {
656
+ case 0: if (THIS.hsv[2] === 0) { THIS.fromHSV(null, null, 1.0); }; break;
657
+ case 1: if (THIS.hsv[1] === 0) { THIS.fromHSV(null, 1.0, null); }; break;
658
+ }
659
+ holdSld=false;
660
+ holdPad=true;
661
+ setPad(e);
662
+ dispatchImmediateChange();
663
+ };
664
+ if('ontouchstart' in window) {
665
+ p.padM.addEventListener('touchstart', function(e) {
666
+ touchOffset={
667
+ 'X': e.target.offsetParent.offsetLeft,
668
+ 'Y': e.target.offsetParent.offsetTop
669
+ };
670
+ this.onmousedown({
671
+ 'offsetX':e.touches[0].pageX-touchOffset.X,
672
+ 'offsetY':e.touches[0].pageY-touchOffset.Y
673
+ });
674
+ });
675
+ }
676
+ p.sldM.onmouseup =
677
+ p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } };
678
+ p.sldM.onmousedown = function(e) {
679
+ holdPad=false;
680
+ holdSld=true;
681
+ setSld(e);
682
+ dispatchImmediateChange();
683
+ };
684
+ if('ontouchstart' in window) {
685
+ p.sldM.addEventListener('touchstart', function(e) {
686
+ touchOffset={
687
+ 'X': e.target.offsetParent.offsetLeft,
688
+ 'Y': e.target.offsetParent.offsetTop
689
+ };
690
+ this.onmousedown({
691
+ 'offsetX':e.touches[0].pageX-touchOffset.X,
692
+ 'offsetY':e.touches[0].pageY-touchOffset.Y
693
+ });
694
+ });
695
+ }
696
+
697
+ // picker
698
+ var dims = getPickerDims(THIS);
699
+ p.box.style.width = dims[0] + 'px';
700
+ p.box.style.height = dims[1] + 'px';
701
+
702
+ // picker border
703
+ p.boxB.style.position = 'absolute';
704
+ p.boxB.style.clear = 'both';
705
+ p.boxB.style.left = x+'px';
706
+ p.boxB.style.top = y+'px';
707
+ p.boxB.style.zIndex = THIS.pickerZIndex;
708
+ p.boxB.style.border = THIS.pickerBorder+'px solid';
709
+ p.boxB.style.borderColor = THIS.pickerBorderColor;
710
+ p.boxB.style.background = THIS.pickerFaceColor;
711
+
712
+ // pad image
713
+ p.pad.style.width = jscolor.images.pad[0]+'px';
714
+ p.pad.style.height = jscolor.images.pad[1]+'px';
715
+
716
+ // pad border
717
+ p.padB.style.position = 'absolute';
718
+ p.padB.style.left = THIS.pickerFace+'px';
719
+ p.padB.style.top = THIS.pickerFace+'px';
720
+ p.padB.style.border = THIS.pickerInset+'px solid';
721
+ p.padB.style.borderColor = THIS.pickerInsetColor;
722
+
723
+ // pad mouse area
724
+ p.padM.style.position = 'absolute';
725
+ p.padM.style.left = '0';
726
+ p.padM.style.top = '0';
727
+ p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
728
+ p.padM.style.height = p.box.style.height;
729
+ p.padM.style.cursor = 'crosshair';
730
+
731
+ // slider image
732
+ p.sld.style.overflow = 'hidden';
733
+ p.sld.style.width = jscolor.images.sld[0]+'px';
734
+ p.sld.style.height = jscolor.images.sld[1]+'px';
735
+
736
+ // slider border
737
+ p.sldB.style.display = THIS.slider ? 'block' : 'none';
738
+ p.sldB.style.position = 'absolute';
739
+ p.sldB.style.right = THIS.pickerFace+'px';
740
+ p.sldB.style.top = THIS.pickerFace+'px';
741
+ p.sldB.style.border = THIS.pickerInset+'px solid';
742
+ p.sldB.style.borderColor = THIS.pickerInsetColor;
743
+
744
+ // slider mouse area
745
+ p.sldM.style.display = THIS.slider ? 'block' : 'none';
746
+ p.sldM.style.position = 'absolute';
747
+ p.sldM.style.right = '0';
748
+ p.sldM.style.top = '0';
749
+ p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
750
+ p.sldM.style.height = p.box.style.height;
751
+ try {
752
+ p.sldM.style.cursor = 'pointer';
753
+ } catch(eOldIE) {
754
+ p.sldM.style.cursor = 'hand';
755
+ }
756
+
757
+ // "close" button
758
+ function setBtnBorder() {
759
+ var insetColors = THIS.pickerInsetColor.split(/\s+/);
760
+ var pickerOutsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
761
+ p.btn.style.borderColor = pickerOutsetColor;
762
+ }
763
+ p.btn.style.display = THIS.pickerClosable ? 'block' : 'none';
764
+ p.btn.style.position = 'absolute';
765
+ p.btn.style.left = THIS.pickerFace + 'px';
766
+ p.btn.style.bottom = THIS.pickerFace + 'px';
767
+ p.btn.style.padding = '0 15px';
768
+ p.btn.style.height = '18px';
769
+ p.btn.style.border = THIS.pickerInset + 'px solid';
770
+ setBtnBorder();
771
+ p.btn.style.color = THIS.pickerButtonColor;
772
+ p.btn.style.font = '12px sans-serif';
773
+ p.btn.style.textAlign = 'center';
774
+ try {
775
+ p.btn.style.cursor = 'pointer';
776
+ } catch(eOldIE) {
777
+ p.btn.style.cursor = 'hand';
778
+ }
779
+ p.btn.onmousedown = function () {
780
+ THIS.hidePicker();
781
+ };
782
+ p.btnS.style.lineHeight = p.btn.style.height;
783
+
784
+ // load images in optimal order
785
+ switch(modeID) {
786
+ case 0: var padImg = 'hs.png'; break;
787
+ case 1: var padImg = 'hv.png'; break;
788
+ }
789
+ p.padM.style.backgroundImage = "url('"+jscolor.getDir()+"cross.gif')";
790
+ p.padM.style.backgroundRepeat = "no-repeat";
791
+ p.sldM.style.backgroundImage = "url('"+jscolor.getDir()+"arrow.gif')";
792
+ p.sldM.style.backgroundRepeat = "no-repeat";
793
+ p.pad.style.backgroundImage = "url('"+jscolor.getDir()+padImg+"')";
794
+ p.pad.style.backgroundRepeat = "no-repeat";
795
+ p.pad.style.backgroundPosition = "0 0";
796
+
797
+ // place pointers
798
+ redrawPad();
799
+ redrawSld();
800
+
801
+ jscolor.picker.owner = THIS;
802
+ document.getElementsByTagName('body')[0].appendChild(p.boxB);
803
+ }
804
+
805
+
806
+ function getPickerDims(o) {
807
+ var dims = [
808
+ 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[0] +
809
+ (o.slider ? 2*o.pickerInset + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] : 0),
810
+ o.pickerClosable ?
811
+ 4*o.pickerInset + 3*o.pickerFace + jscolor.images.pad[1] + o.pickerButtonHeight :
812
+ 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[1]
813
+ ];
814
+ return dims;
815
+ }
816
+
817
+
818
+ function redrawPad() {
819
+ // redraw the pad pointer
820
+ switch(modeID) {
821
+ case 0: var yComponent = 1; break;
822
+ case 1: var yComponent = 2; break;
823
+ }
824
+ var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
825
+ var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
826
+ jscolor.picker.padM.style.backgroundPosition =
827
+ (THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
828
+ (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';
829
+
830
+ // redraw the slider image
831
+ var seg = jscolor.picker.sld.childNodes;
832
+
833
+ switch(modeID) {
834
+ case 0:
835
+ var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
836
+ for(var i=0; i<seg.length; i+=1) {
837
+ seg[i].style.backgroundColor = 'rgb('+
838
+ (rgb[0]*(1-i/seg.length)*100)+'%,'+
839
+ (rgb[1]*(1-i/seg.length)*100)+'%,'+
840
+ (rgb[2]*(1-i/seg.length)*100)+'%)';
841
+ }
842
+ break;
843
+ case 1:
844
+ var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
845
+ var i = Math.floor(THIS.hsv[0]);
846
+ var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
847
+ switch(i) {
848
+ case 6:
849
+ case 0: rgb=[0,1,2]; break;
850
+ case 1: rgb=[1,0,2]; break;
851
+ case 2: rgb=[2,0,1]; break;
852
+ case 3: rgb=[2,1,0]; break;
853
+ case 4: rgb=[1,2,0]; break;
854
+ case 5: rgb=[0,2,1]; break;
855
+ }
856
+ for(var i=0; i<seg.length; i+=1) {
857
+ s = 1 - 1/(seg.length-1)*i;
858
+ c[1] = c[0] * (1 - s*f);
859
+ c[2] = c[0] * (1 - s);
860
+ seg[i].style.backgroundColor = 'rgb('+
861
+ (c[rgb[0]]*100)+'%,'+
862
+ (c[rgb[1]]*100)+'%,'+
863
+ (c[rgb[2]]*100)+'%)';
864
+ }
865
+ break;
866
+ }
867
+ }
868
+
869
+
870
+ function redrawSld() {
871
+ // redraw the slider pointer
872
+ switch(modeID) {
873
+ case 0: var yComponent = 2; break;
874
+ case 1: var yComponent = 1; break;
875
+ }
876
+ var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
877
+ jscolor.picker.sldM.style.backgroundPosition =
878
+ '0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
879
+ }
880
+
881
+
882
+ function isPickerOwner() {
883
+ return jscolor.picker && jscolor.picker.owner === THIS;
884
+ }
885
+
886
+
887
+ function blurTarget() {
888
+ if(valueElement === target) {
889
+ THIS.importColor();
890
+ }
891
+ if(THIS.pickerOnfocus) {
892
+ THIS.hidePicker();
893
+ }
894
+ }
895
+
896
+
897
+ function blurValue() {
898
+ if(valueElement !== target) {
899
+ THIS.importColor();
900
+ }
901
+ }
902
+
903
+
904
+ function setPad(e) {
905
+ var mpos = jscolor.getRelMousePos(e);
906
+ var x = mpos.x - THIS.pickerFace - THIS.pickerInset;
907
+ var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
908
+ switch(modeID) {
909
+ case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
910
+ case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
911
+ }
912
+ }
913
+
914
+
915
+ function setSld(e) {
916
+ var mpos = jscolor.getRelMousePos(e);
917
+ var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
918
+ switch(modeID) {
919
+ case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
920
+ case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
921
+ }
922
+ }
923
+
924
+
925
+ function dispatchImmediateChange() {
926
+ if (THIS.onImmediateChange) {
927
+ var callback;
928
+ if (typeof THIS.onImmediateChange === 'string') {
929
+ callback = new Function (THIS.onImmediateChange);
930
+ } else {
931
+ callback = THIS.onImmediateChange;
932
+ }
933
+ callback.call(THIS);
934
+ }
935
+ }
936
+
937
+
938
+ var THIS = this;
939
+ var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
940
+ var abortBlur = false;
941
+ var
942
+ valueElement = jscolor.fetchElement(this.valueElement),
943
+ styleElement = jscolor.fetchElement(this.styleElement);
944
+ var
945
+ holdPad = false,
946
+ holdSld = false,
947
+ touchOffset = {};
948
+ var
949
+ leaveValue = 1<<0,
950
+ leaveStyle = 1<<1,
951
+ leavePad = 1<<2,
952
+ leaveSld = 1<<3;
953
+
954
+ jscolor.isColorAttrSupported = false;
955
+ var el = document.createElement('input');
956
+ if(el.setAttribute) {
957
+ el.setAttribute('type', 'color');
958
+ if(el.type.toLowerCase() == 'color') {
959
+ jscolor.isColorAttrSupported = true;
960
+ }
961
+ }
962
+
963
+ // target
964
+ jscolor.addEvent(target, 'focus', function() {
965
+ if(THIS.pickerOnfocus) { THIS.showPicker(); }
966
+ });
967
+ jscolor.addEvent(target, 'blur', function() {
968
+ if(!abortBlur) {
969
+ window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
970
+ } else {
971
+ abortBlur = false;
972
+ }
973
+ });
974
+
975
+ // valueElement
976
+ if(valueElement) {
977
+ var updateField = function() {
978
+ THIS.fromString(valueElement.value, leaveValue);
979
+ dispatchImmediateChange();
980
+ };
981
+ jscolor.addEvent(valueElement, 'keyup', updateField);
982
+ jscolor.addEvent(valueElement, 'input', updateField);
983
+ jscolor.addEvent(valueElement, 'blur', blurValue);
984
+ valueElement.setAttribute('autocomplete', 'off');
985
+ }
986
+
987
+ // styleElement
988
+ if(styleElement) {
989
+ styleElement.jscStyle = {
990
+ backgroundImage : styleElement.style.backgroundImage,
991
+ backgroundColor : styleElement.style.backgroundColor,
992
+ color : styleElement.style.color
993
+ };
994
+ }
995
+
996
+ // require images
997
+ switch(modeID) {
998
+ case 0: jscolor.requireImage('hs.png'); break;
999
+ case 1: jscolor.requireImage('hv.png'); break;
1000
+ }
1001
+ jscolor.requireImage('cross.gif');
1002
+ jscolor.requireImage('arrow.gif');
1003
+
1004
+ this.importColor();
1005
+ }
1006
+
1007
+ };
1008
+
1009
+
1010
+ jscolor.install();
js/theextensionlab/statuscolors/adminhtml/grid-row.js CHANGED
File without changes
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>TheExtensionLab_StatusColors</name>
4
- <version>1.0.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/OSL-3.0">Open Software License v3.0 (OSL-3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>An extension to add colors to your Magento Order grid to enable to you to see the status of orders in a glance.</summary>
10
  <description>With multiple orders on multiple statuses it can be hard (especially for example on a mobile) to see the status of your orders and single out the ones that still require action. With this extension you can add colors either to the whole row or to the individual status blocks to enable you to quickly see what status an order has.</description>
11
- <notes>Initial Release</notes>
12
  <authors><author><name>James Anelay</name><user>TheExtensionLab</user><email>james@theextensionlab.com</email></author></authors>
13
- <date>2015-03-11</date>
14
- <time>20:04:23</time>
15
- <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="theextensionlab"><file name="statuscolors.xml" hash="9ffc8ac3eef9ea5a7d678f31962416a3"/></dir></dir><dir name="template"><dir name="theextensionlab"><dir name="statuscolors"><dir><dir name="sales"><dir name="order"><dir name="view"><dir name="history"><file name="js-update.phtml" hash="c215f739d36440747b80079333341be1"/></dir></dir></dir></dir><dir name="system"><dir name="config"><file name="extension-info.phtml" hash="ec9102149dba6093363df26ce6b2cdf6"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="TheExtensionLab_StatusColors.xml" hash="4c15e58ee68e865e66ab006bf676f663"/></dir></target><target name="mageweb"><dir name="js"><dir name="theextensionlab"><dir name="adminhtml"><dir name="jscolor"><file name="arrow.gif" hash="5034704a76cd55c1cbcbc58ea6bf523f"/><file name="cross.gif" hash="ba9a274b9323753cd95bc3b1eb2f4e5f"/><file name="hs.png" hash="fefa1a03d92ebad25c88dca94a0b63db"/><file name="hv.png" hash="990d71cada17da100653636cf8490884"/><file name="jscolor.js" hash="a26701f49bf33da8dc48f3431e5f4f42"/></dir></dir><dir name="statuscolors"><dir><dir name="adminhtml"><file name="grid-row.js" hash="3c43db2dfb19e86bfb9f8066b1693e74"/></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="theextensionlab"><dir name="statuscolors"><file name="grid.css" hash="ccaefc16d8f399350c61cc897d5bee97"/><file name="system-config.css" hash="263d66b21332ac07726bd912830d4207"/></dir></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>TheExtensionLab_StatusColors</name>
4
+ <version>1.0.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/OSL-3.0">Open Software License v3.0 (OSL-3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>An extension to add colors to your Magento Order grid to enable to you to see the status of orders in a glance.</summary>
10
  <description>With multiple orders on multiple statuses it can be hard (especially for example on a mobile) to see the status of your orders and single out the ones that still require action. With this extension you can add colors either to the whole row or to the individual status blocks to enable you to quickly see what status an order has.</description>
11
+ <notes>Add missing files.</notes>
12
  <authors><author><name>James Anelay</name><user>TheExtensionLab</user><email>james@theextensionlab.com</email></author></authors>
13
+ <date>2015-04-01</date>
14
+ <time>16:25:44</time>
15
+ <contents><target name="mageetc"><dir name="modules"><file name="TheExtensionLab_StatusColors.xml" hash="4c15e58ee68e865e66ab006bf676f663"/></dir></target><target name="magecommunity"><dir name="TheExtensionLab"><dir name="StatusColors"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><file name="ExtensionInfo.php" hash="c6d4b0c4248e66e60dd5773d48cc1378"/></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="265a36f3218f30786f08fc1ca44e5f4c"/></dir><dir name="Model"><file name="Observer.php" hash="ca10da5dbf708d19026b944050cc8076"/><dir name="Resource"><file name="Setup.php" hash="794a31b09dcf0af1057b9ddb4857f4c9"/></dir></dir><dir name="Test"><dir name="Config"><file name="Main.php" hash="b68cf121a50c3f8b35f571cc235c1192"/></dir><dir name="Model"><file name="Observer.php" hash="9b7f6571ae41fd0dba1d76ce2268d480"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="1631d6dc69406ea8a300bd047645c228"/><file name="config.xml" hash="8264d8365a69ffee505cbc78cb9ea9ae"/><file name="system.xml" hash="5d952aac47f87567f684cd9a7d41bb70"/></dir><dir name="sql"><dir name="theextensionlab_statuscolors_setup"><file name="install-0.1.0.php" hash="7750e5ebead36ca11bd835563c88241a"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="theextensionlab"><file name="statuscolors.xml" hash="9ffc8ac3eef9ea5a7d678f31962416a3"/></dir></dir><dir name="template"><dir name="theextensionlab"><dir name="statuscolors"><dir name="sales"><dir name="order"><dir name="view"><dir name="history"><file name="js-update.phtml" hash="c215f739d36440747b80079333341be1"/></dir></dir></dir></dir><dir name="system"><dir name="config"><file name="extension-info.phtml" hash="ec9102149dba6093363df26ce6b2cdf6"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="theextensionlab"><dir name="adminhtml"><dir name="jscolor"><file name="arrow.gif" hash="5034704a76cd55c1cbcbc58ea6bf523f"/><file name="cross.gif" hash="ba9a274b9323753cd95bc3b1eb2f4e5f"/><file name="hs.png" hash="fefa1a03d92ebad25c88dca94a0b63db"/><file name="hv.png" hash="990d71cada17da100653636cf8490884"/><file name="jscolor.js" hash="24de4d9c2297cd9b803e16bc7389786e"/></dir></dir><dir name="statuscolors"><dir name="adminhtml"><file name="grid-row.js" hash="3c43db2dfb19e86bfb9f8066b1693e74"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="theextensionlab"><dir name="statuscolors"><file name="grid.css" hash="ccaefc16d8f399350c61cc897d5bee97"/><file name="system-config.css" hash="263d66b21332ac07726bd912830d4207"/></dir></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
skin/adminhtml/default/default/theextensionlab/statuscolors/grid.css CHANGED
File without changes
skin/adminhtml/default/default/theextensionlab/statuscolors/system-config.css CHANGED
File without changes