NightlyDev_FaviconBadge - Version 1.0.0.0

Version Notes

Highly customizable favicon badges for customers (frontend) and administrators or developers (backend).

Download this release

Release Info

Developer Carles Tubio
Extension NightlyDev_FaviconBadge
Version 1.0.0.0
Comparing to
See all releases


Version 1.0.0.0

Files changed (24) hide show
  1. app/code/community/NightlyDev/FaviconBadge/Block/Adminhtml/System/Config/Source/Date.php +76 -0
  2. app/code/community/NightlyDev/FaviconBadge/Helper/Data.php +174 -0
  3. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Alerts.php +47 -0
  4. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Anims.php +41 -0
  5. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Downs.php +35 -0
  6. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Pos.php +38 -0
  7. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Shapes.php +32 -0
  8. app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Types.php +47 -0
  9. app/code/community/NightlyDev/FaviconBadge/etc/config.xml +60 -0
  10. app/code/community/NightlyDev/FaviconBadge/etc/system.xml +157 -0
  11. app/code/community/NightlyDev/LICENSE +674 -0
  12. app/design/adminhtml/default/default/layout/nightlydevfaviconbadge.xml +11 -0
  13. app/design/adminhtml/default/default/template/nightlydevfaviconbadge/faviconbadge.phtml +28 -0
  14. app/design/frontend/base/default/layout/nightlydevfaviconbadge.xml +9 -0
  15. app/design/frontend/base/default/template/nightlydevfaviconbadge/faviconbadge.phtml +18 -0
  16. app/etc/modules/NightlyDev_FaviconBadge.xml +12 -0
  17. js/nightlydev/faviconbadge/favico-0.3.4.min.js +7 -0
  18. js/nightlydev/faviconbadge/favico.js +873 -0
  19. js/nightlydev/jscolor/arrow.gif +0 -0
  20. js/nightlydev/jscolor/cross.gif +0 -0
  21. js/nightlydev/jscolor/hs.png +0 -0
  22. js/nightlydev/jscolor/hv.png +0 -0
  23. js/nightlydev/jscolor/jscolor.js +997 -0
  24. package.xml +18 -0
app/code/community/NightlyDev/FaviconBadge/Block/Adminhtml/System/Config/Source/Date.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Block_Adminhtml_System_Config_Source_Date extends Mage_Adminhtml_Block_System_Config_Form_Field
3
+ {
4
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
5
+ {
6
+ $date = new Varien_Data_Form_Element_Date;
7
+ $format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT);
8
+
9
+ $data = array(
10
+ 'name' => $element->getName(),
11
+ 'html_id' => $element->getId(),
12
+ 'image' => $this->getSkinUrl('images/grid-cal.gif'),
13
+ );
14
+ $date->setData($data);
15
+ $date->setValue($element->getValue(), $format);
16
+ $date->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT));
17
+ #$date->setClass($element->getFieldConfig()->validate->asArray());
18
+ $date->setForm($element->getForm());
19
+
20
+ $store_id = 0;
21
+ if (strlen($code = Mage::getSingleton('adminhtml/config_data')->getStore()))
22
+ $store_id = Mage::getModel('core/store')->load($code)->getId();
23
+ elseif (strlen($code = Mage::getSingleton('adminhtml/config_data')->getWebsite())) {
24
+ $website_id = Mage::getModel('core/website')->load($code)->getId();
25
+ $store_id = Mage::app()->getWebsite($website_id)->getDefaultStore()->getId();
26
+ }
27
+ $folderName = Mage_Adminhtml_Model_System_Config_Backend_Image_Favicon::UPLOAD_DIR;
28
+ $storeConfig = Mage::getStoreConfig('design/head/shortcut_icon', $store_id);
29
+ $faviconFile = Mage::getBaseUrl('media') . $folderName . '/' . $storeConfig;
30
+ $absolutePath = Mage::getBaseDir('media') . '/' . $folderName . '/' . $storeConfig;
31
+ if(!is_null($storeConfig) && $this->_isFile($absolutePath)) $favicon = $faviconFile;
32
+ else $favicon = Mage::getDesign()->getSkinUrl('favicon.ico');
33
+ return $date->getElementHtml()
34
+ .'<div id="badgeMirror" style="padding:5px;"></ br></ br> </ br>'
35
+ .'<button style="" onclick="javascript:toggle_nightlydevfaviconbadget_preview();" class="scalable" type="button" id="refrsh_favicon_badge_preview"><span><span><span>Refresh Example</span></span></span></button>'
36
+ .'</ br><center><img id="badgePreview" width="32" src="'.$favicon.'" height="32"></center></div>'
37
+ .'<script type="text/javascript" src="/js/nightlydev/jscolor/jscolor.js"></script>'
38
+ .'<script type="text/javascript" src="/js/nightlydev/faviconbadge/favico.js"></script>'
39
+ .'<script type="text/javascript">'
40
+ .'function toggle_nightlydevfaviconbadget_show_order() {$("row_design_nightlydevfaviconbadge_order")[($("design_nightlydevfaviconbadge_type").value=='.NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ORDERS.' && $("design_nightlydevfaviconbadge_enabled").value=="1")?"show":"hide"]();}Event.observe($("design_nightlydevfaviconbadge_enabled"), "change", function(){toggle_nightlydevfaviconbadget_show_order();});'
41
+ .'function toggle_nightlydevfaviconbadget_show_downs() {$("row_design_nightlydevfaviconbadge_downs")[($("design_nightlydevfaviconbadge_type").value=='.NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DOWNS.' && $("design_nightlydevfaviconbadge_enabled").value=="1")?"show":"hide"]();}Event.observe($("design_nightlydevfaviconbadge_enabled"), "change", function(){toggle_nightlydevfaviconbadget_show_downs();});'
42
+ .'function toggle_nightlydevfaviconbadget_show_date() {$("row_design_nightlydevfaviconbadge_date")[($("design_nightlydevfaviconbadge_type").value=='.NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DATE.' && $("design_nightlydevfaviconbadge_enabled").value=="1")?"show":"hide"]();}Event.observe($("design_nightlydevfaviconbadge_enabled"), "change", function(){toggle_nightlydevfaviconbadget_show_date();});'
43
+ .'function toggle_nightlydevfaviconbadget_show_num() {$("row_design_nightlydevfaviconbadge_num")[($("design_nightlydevfaviconbadge_type").value=='.NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_NUM.' && $("design_nightlydevfaviconbadge_enabled").value=="1")?"show":"hide"]();}Event.observe($("design_nightlydevfaviconbadge_enabled"), "change", function(){toggle_nightlydevfaviconbadget_show_num();});'
44
+ .'function toggle_nightlydevfaviconbadget_show_badgeMirror() {$("badgeMirror")[($("design_nightlydevfaviconbadge_enabled").value=="1")?"show":"hide"]();}Event.observe($("design_nightlydevfaviconbadge_enabled"), "change", function(){toggle_nightlydevfaviconbadget_show_badgeMirror();});'
45
+ .'window.faviconMirror = false; function toggle_nightlydevfaviconbadget_preview() {if (window.faviconMirror) window.faviconMirror.badge(0); window.faviconMirror = new nightlydevFavico({bgColor:$("design_nightlydevfaviconbadge_bc").value,textColor:$("design_nightlydevfaviconbadge_tc").value,type:$("design_nightlydevfaviconbadge_shape").value,position:$("design_nightlydevfaviconbadge_pos").value,animation : $("design_nightlydevfaviconbadge_anim").value,elementId : "badgePreview"});window.faviconMirror.badge(Math.floor(Math.random() * 12) + 1);};'
46
+ .'Event.observe(window, "load", function(){'
47
+ .'toggle_nightlydevfaviconbadget_show_order();'
48
+ .'toggle_nightlydevfaviconbadget_show_downs();'
49
+ .'toggle_nightlydevfaviconbadget_show_date();'
50
+ .'toggle_nightlydevfaviconbadget_show_num();'
51
+ .'toggle_nightlydevfaviconbadget_show_badgeMirror();'
52
+ .'document.getElementById("design_nightlydevfaviconbadge").appendChild(document.getElementById("badgeMirror"));'
53
+ .'toggle_nightlydevfaviconbadget_preview();'
54
+ .'});'
55
+ .'Event.observe($("design_nightlydevfaviconbadge_tc"), "change", function(){toggle_nightlydevfaviconbadget_preview();});'
56
+ .'Event.observe($("design_nightlydevfaviconbadge_bc"), "change", function(){toggle_nightlydevfaviconbadget_preview();});'
57
+ .'Event.observe($("design_nightlydevfaviconbadge_pos"), "change", function(){toggle_nightlydevfaviconbadget_preview();});'
58
+ .'Event.observe($("design_nightlydevfaviconbadge_anim"), "change", function(){toggle_nightlydevfaviconbadget_preview();});'
59
+ .'Event.observe($("design_nightlydevfaviconbadge_shape"), "change", function(){toggle_nightlydevfaviconbadget_preview();});'
60
+ .'</script>';
61
+ }
62
+
63
+ /**
64
+ * If DB file storage is on - find there, otherwise - just file_exists
65
+ *
66
+ * @param string $filename
67
+ * @return bool
68
+ */
69
+
70
+ protected function _isFile($filename) {
71
+ if (Mage::helper('core/file_storage_database')->checkDbUsage() && !is_file($filename)) {
72
+ Mage::helper('core/file_storage_database')->saveFileToFilesystem($filename);
73
+ }
74
+ return is_file($filename);
75
+ }
76
+ }
app/code/community/NightlyDev/FaviconBadge/Helper/Data.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Helper_Data extends Mage_Core_Helper_Abstract
3
+ {
4
+ const XML_PATH_FAVBADGE_ENABLED = 'design/nightlydevfaviconbadge/enabled';
5
+ const XML_PATH_FAVBADGE_BC = 'design/nightlydevfaviconbadge/bc';
6
+ const XML_PATH_FAVBADGE_TC = 'design/nightlydevfaviconbadge/tc';
7
+ const XML_PATH_FAVBADGE_POS = 'design/nightlydevfaviconbadge/pos';
8
+ const XML_PATH_FAVBADGE_ANIM = 'design/nightlydevfaviconbadge/anim';
9
+ const XML_PATH_FAVBADGE_SHAPE = 'design/nightlydevfaviconbadge/shape';
10
+ const XML_PATH_FAVBADGE_TYPE = 'design/nightlydevfaviconbadge/type';
11
+ const XML_PATH_FAVBADGE_ORDER = 'design/nightlydevfaviconbadge/order';
12
+ const XML_PATH_FAVBADGE_DOWN = 'design/nightlydevfaviconbadge/downs';
13
+ const XML_PATH_FAVBADGE_DATE = 'design/nightlydevfaviconbadge/date';
14
+ const XML_PATH_FAVBADGE_NUM = 'design/nightlydevfaviconbadge/num';
15
+
16
+ const XML_PATH_FAVBADGE_ADMIN_ENABLED = 'design/nightlydevfaviconbadge_admin/enabled';
17
+ const XML_PATH_FAVBADGE_ADMIN_ALERT = 'design/nightlydevfaviconbadge_admin/alert';
18
+
19
+ const POS_UP = 'up';
20
+ const POS_DOWN = 'down';
21
+ const POS_LEFT = 'left';
22
+ const POS_UPLEFT = 'upleft';
23
+
24
+ const SHAPE_CIRCLE = 'circle';
25
+ const SHAPE_RECTANGLE = 'rectangle';
26
+
27
+ const ANIM_NONE = 'none';
28
+ const ANIM_FADE = 'fade';
29
+ const ANIM_POP = 'pop';
30
+ const ANIM_POPFADE = 'popFade';
31
+ const ANIM_SLIDE = 'slide';
32
+
33
+ const TYPE_CART_ITEMS = 1;
34
+ const TYPE_CART_QTYS = 2;
35
+ const TYPE_CART_ERRORS = 4;
36
+ const TYPE_CART_ORDERS = 8;
37
+ const TYPE_CART_DOWNS = 16;
38
+ const TYPE_CART_DATE = 32;
39
+ const TYPE_CART_NUM = 64;
40
+
41
+ const DOWN_TODO = 1;
42
+ const DOWN_LIVE = 2;
43
+ const DOWN_DONE = 4;
44
+
45
+ const ALERT_PENDING = 1;
46
+ const ALERT_PROCESSING = 2;
47
+ const ALERT_REPORTS = 4;
48
+ const ALERT_EXCEPTIONS = 8;
49
+
50
+ public function getBadge() {
51
+ $badge = 0;
52
+ switch(Mage::getStoreConfig(self::XML_PATH_FAVBADGE_TYPE)) {
53
+ case self::TYPE_CART_ITEMS:
54
+ $badge = Mage::getModel('checkout/cart')->getQuote()->getItemsCount();
55
+ break;
56
+ case self::TYPE_CART_QTYS:
57
+ $badge = Mage::getModel('checkout/cart')->getQuote()->getItemsQty();
58
+ break;
59
+ case self::TYPE_CART_ORDERS:
60
+ if (Mage::getSingleton('customer/session')->isLoggedIn()) {
61
+ $badge = Mage::getResourceModel('sales/order_collection')
62
+ ->addFieldToSelect('entity_id')
63
+ ->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getCustomer()->getId())
64
+ ->addFieldToFilter('status', Mage::getStoreConfig(self::XML_PATH_FAVBADGE_ORDER))
65
+ ->count();
66
+ }
67
+ break;
68
+ case self::TYPE_CART_DOWNS:
69
+ if (Mage::getSingleton('customer/session')->isLoggedIn()) {
70
+ $purchased_ids = array();
71
+ foreach(Mage::getModel('downloadable/link_purchased')->getCollection()->addFieldToSelect('purchased_id')->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getCustomer()->getId())->load() as $down)
72
+ $purchased_ids[] = $down->getPurchasedId();
73
+ switch(Mage::getStoreConfig(self::XML_PATH_FAVBADGE_DOWN)){
74
+ case DOWN_TODO:
75
+ $badge = Mage::getModel('downloadable/link_purchased_item')->getCollection()
76
+ ->addFieldToSelect('item_id')
77
+ ->addFieldToFilter('number_of_downloads_used', '0')
78
+ ->addFieldToFilter('status', 'available')
79
+ ->addFieldToFilter('purchased_id', array('in'=>$purchased_ids))
80
+ ->count();
81
+ break;
82
+ case DOWN_LIVE:
83
+ $badge = Mage::getModel('downloadable/link_purchased_item')->getCollection()
84
+ ->addFieldToSelect('item_id')
85
+ ->addFieldToFilter('status', 'available')
86
+ ->addFieldToFilter('purchased_id', array('in'=>$purchased_ids))
87
+ ->count();
88
+ break;
89
+ case DOWN_DONE:
90
+ foreach(
91
+ Mage::getModel('downloadable/link_purchased_item')->getCollection()
92
+ ->addFieldToSelect('number_of_downloads_used')
93
+ ->addFieldToFilter('number_of_downloads_used', array('nin'=>'0'))
94
+ ->addFieldToFilter('status', 'available')
95
+ ->addFieldToFilter('purchased_id', array('in'=>$purchased_ids))
96
+ ->load()
97
+ as $down)
98
+ $badge += $down->getNumberOfDownloadsUsed();
99
+ break;
100
+ }
101
+ }
102
+ break;
103
+ case self::TYPE_CART_DATE:
104
+ $diff = strtotime(Mage::getStoreConfig(self::XML_PATH_FAVBADGE_DATE)) - time();
105
+ $badge = ($diff < 0) ? 0 : ceil($diff/60/60/24);
106
+ break;
107
+ case self::TYPE_CART_NUM:
108
+ $badge = Mage::getStoreConfig(self::XML_PATH_FAVBADGE_NUM);
109
+ break;
110
+ }
111
+ return (int)$badge;
112
+ }
113
+
114
+ public function getAdminBadges() {
115
+ $errors = 0;
116
+ $orders = 0;
117
+ $config = Mage::getStoreConfig(self::XML_PATH_FAVBADGE_ADMIN_ALERT);
118
+ if ($config & self::ALERT_PENDING)
119
+ $orders += Mage::getResourceModel('sales/order_collection')
120
+ ->addFieldToSelect('entity_id')
121
+ ->addFieldToFilter('state', Mage_Sales_Model_Order::STATE_NEW)
122
+ ->count();
123
+ if ($config & self::ALERT_PROCESSING)
124
+ $orders += Mage::getResourceModel('sales/order_collection')
125
+ ->addFieldToSelect('entity_id')
126
+ ->addFieldToFilter('state', Mage_Sales_Model_Order::STATE_PROCESSING)
127
+ ->count();
128
+ if ($config & self::ALERT_REPORTS)
129
+ $errors += count(
130
+ glob(
131
+ Mage::getBaseDir('var')
132
+ .DIRECTORY_SEPARATOR
133
+ .'report'
134
+ .DIRECTORY_SEPARATOR
135
+ .'*'
136
+ )
137
+ );
138
+ if ($config & self::ALERT_EXCEPTIONS)
139
+ $errors += substr_count(
140
+ file_get_contents(
141
+ Mage::getBaseDir('var')
142
+ .DIRECTORY_SEPARATOR
143
+ .'log'
144
+ .DIRECTORY_SEPARATOR
145
+ .Mage::getStoreConfig('dev/log/exception_file')
146
+ ),
147
+ 'Stack trace:'
148
+ );
149
+ return new Varien_Object(array(
150
+ 'errors' => $errors,
151
+ 'orders' => $orders
152
+ ));
153
+ }
154
+
155
+ public function getBc() {
156
+ return Mage::getStoreConfig(self::XML_PATH_FAVBADGE_BC);
157
+ }
158
+
159
+ public function getTc() {
160
+ return Mage::getStoreConfig(self::XML_PATH_FAVBADGE_TC);
161
+ }
162
+
163
+ public function getPos() {
164
+ return Mage::getStoreConfig(self::XML_PATH_FAVBADGE_POS);
165
+ }
166
+
167
+ public function getAnim() {
168
+ return Mage::getStoreConfig(self::XML_PATH_FAVBADGE_ANIM);
169
+ }
170
+
171
+ public function getShape() {
172
+ return Mage::getStoreConfig(self::XML_PATH_FAVBADGE_SHAPE);
173
+ }
174
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Alerts.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Alerts
3
+ {
4
+ const ALERT_PENDING = 'New Orders';
5
+ const ALERT_PROCESSING = 'Orders in Processing state';
6
+ const ALERT_PENDING_PROCESSING = 'New Orders and Orders in Processing state';
7
+ const ALERT_REPORTS = 'Errors in /var/report';
8
+ const ALERT_EXCEPTIONS = 'Errors in /var/log/';
9
+ const ALERT_REPORT_EXCEPTIONS = 'Errors in /var/report and /var/log/';
10
+ const ALERT_ORDERS_ERRORS = 'All not completed Orders and all Errors.';
11
+ /**
12
+ * Options getter
13
+ *
14
+ * @return array
15
+ */
16
+ public function toOptionArray()
17
+ {
18
+ return array(
19
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_PENDING)),
20
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_PROCESSING)),
21
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING | NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_PENDING_PROCESSING)),
22
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_REPORTS)),
23
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_EXCEPTIONS.Mage::getStoreConfig('dev/log/exception_file'))),
24
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS | NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_REPORT_EXCEPTIONS.Mage::getStoreConfig('dev/log/exception_file'))),
25
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING | NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING | NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS | NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS, 'label'=>Mage::helper('adminhtml')->__(self::ALERT_ORDERS_ERRORS)),
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Get options in "key-value" format
31
+ *
32
+ * @return array
33
+ */
34
+ public function toArray()
35
+ {
36
+ return array(
37
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING=>Mage::helper('adminhtml')->__(self::ALERT_PENDING),
38
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING=>Mage::helper('adminhtml')->__(self::ALERT_PROCESSING),
39
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING | NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING=>Mage::helper('adminhtml')->__(self::ALERT_PENDING_PROCESSING),
40
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS=>Mage::helper('adminhtml')->__(self::ALERT_REPORTS),
41
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS=>Mage::helper('adminhtml')->__(self::ALERT_EXCEPTIONS.Mage::getStoreConfig('dev/log/exception_file')),
42
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS | NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS=>Mage::helper('adminhtml')->__(self::ALERT_REPORT_EXCEPTIONS.Mage::getStoreConfig('dev/log/exception_file')),
43
+ NightlyDev_FaviconBadge_Helper_Data::ALERT_PENDING | NightlyDev_FaviconBadge_Helper_Data::ALERT_PROCESSING | NightlyDev_FaviconBadge_Helper_Data::ALERT_REPORTS | NightlyDev_FaviconBadge_Helper_Data::ALERT_EXCEPTIONS=>Mage::helper('adminhtml')->__(self::ALERT_ORDERS_ERRORS),
44
+ );
45
+ }
46
+
47
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Anims.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Anims
3
+ {
4
+ const ANIM_NONE = 'None';
5
+ const ANIM_FADE = 'Fade';
6
+ const ANIM_POP = 'Pop';
7
+ const ANIM_POPFADE = 'Pop with Fade';
8
+ const ANIM_SLIDE = 'Slide';
9
+ /**
10
+ * Options getter
11
+ *
12
+ * @return array
13
+ */
14
+ public function toOptionArray()
15
+ {
16
+ return array(
17
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ANIM_NONE, 'label'=>Mage::helper('adminhtml')->__(self::ANIM_NONE)),
18
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ANIM_FADE, 'label'=>Mage::helper('adminhtml')->__(self::ANIM_FADE)),
19
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ANIM_POP, 'label'=>Mage::helper('adminhtml')->__(self::ANIM_POP)),
20
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ANIM_POPFADE, 'label'=>Mage::helper('adminhtml')->__(self::ANIM_POPFADE)),
21
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::ANIM_SLIDE, 'label'=>Mage::helper('adminhtml')->__(self::ANIM_SLIDE)),
22
+ );
23
+ }
24
+
25
+ /**
26
+ * Get options in "key-value" format
27
+ *
28
+ * @return array
29
+ */
30
+ public function toArray()
31
+ {
32
+ return array(
33
+ NightlyDev_FaviconBadge_Helper_Data::ANIM_NONE=>Mage::helper('adminhtml')->__(self::ANIM_NONE),
34
+ NightlyDev_FaviconBadge_Helper_Data::ANIM_FADE=>Mage::helper('adminhtml')->__(self::ANIM_FADE),
35
+ NightlyDev_FaviconBadge_Helper_Data::ANIM_POP=>Mage::helper('adminhtml')->__(self::ANIM_POP),
36
+ NightlyDev_FaviconBadge_Helper_Data::ANIM_POPFADE=>Mage::helper('adminhtml')->__(self::ANIM_POPFADE),
37
+ NightlyDev_FaviconBadge_Helper_Data::ANIM_SLIDE=>Mage::helper('adminhtml')->__(self::ANIM_SLIDE),
38
+ );
39
+ }
40
+
41
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Downs.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Downs
3
+ {
4
+ const DOWN_TODO = 'Downloads not downloaded yet';
5
+ const DOWN_LIVE = 'Downloads not expired yet';
6
+ const DOWN_DONE = 'Downloads already done';
7
+ /**
8
+ * Options getter
9
+ *
10
+ * @return array
11
+ */
12
+ public function toOptionArray()
13
+ {
14
+ return array(
15
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::DOWN_TODO, 'label'=>Mage::helper('adminhtml')->__(self::DOWN_TODO)),
16
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::DOWN_LIVE, 'label'=>Mage::helper('adminhtml')->__(self::DOWN_LIVE)),
17
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::DOWN_DONE, 'label'=>Mage::helper('adminhtml')->__(self::DOWN_DONE)),
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Get options in "key-value" format
23
+ *
24
+ * @return array
25
+ */
26
+ public function toArray()
27
+ {
28
+ return array(
29
+ NightlyDev_FaviconBadge_Helper_Data::DOWN_TODO=>Mage::helper('adminhtml')->__(self::DOWN_TODO),
30
+ NightlyDev_FaviconBadge_Helper_Data::DOWN_LIVE=>Mage::helper('adminhtml')->__(self::DOWN_LIVE),
31
+ NightlyDev_FaviconBadge_Helper_Data::DOWN_DONE=>Mage::helper('adminhtml')->__(self::DOWN_DONE),
32
+ );
33
+ }
34
+
35
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Pos.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Pos
3
+ {
4
+ const POS_UP = 'Top Right corner';
5
+ const POS_DOWN = 'Bottom Right corner';
6
+ const POS_LEFT = 'Bottom Left corner';
7
+ const POS_UPLEFT = 'Top Left corner';
8
+ /**
9
+ * Options getter
10
+ *
11
+ * @return array
12
+ */
13
+ public function toOptionArray()
14
+ {
15
+ return array(
16
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::POS_UP, 'label'=>Mage::helper('adminhtml')->__(self::POS_UP)),
17
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::POS_DOWN, 'label'=>Mage::helper('adminhtml')->__(self::POS_DOWN)),
18
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::POS_UPLEFT, 'label'=>Mage::helper('adminhtml')->__(self::POS_UPLEFT)),
19
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::POS_LEFT, 'label'=>Mage::helper('adminhtml')->__(self::POS_LEFT)),
20
+ );
21
+ }
22
+
23
+ /**
24
+ * Get options in "key-value" format
25
+ *
26
+ * @return array
27
+ */
28
+ public function toArray()
29
+ {
30
+ return array(
31
+ NightlyDev_FaviconBadge_Helper_Data::POS_UP=>Mage::helper('adminhtml')->__(self::POS_UP),
32
+ NightlyDev_FaviconBadge_Helper_Data::POS_DOWN=>Mage::helper('adminhtml')->__(self::POS_DOWN),
33
+ NightlyDev_FaviconBadge_Helper_Data::POS_UPLEFT=>Mage::helper('adminhtml')->__(self::POS_UPLEFT),
34
+ NightlyDev_FaviconBadge_Helper_Data::POS_LEFT=>Mage::helper('adminhtml')->__(self::POS_LEFT),
35
+ );
36
+ }
37
+
38
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Shapes.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Shapes
3
+ {
4
+ const SHAPE_CIRCLE = 'Circle';
5
+ const SHAPE_RECTANGLE = 'Rectangle';
6
+ /**
7
+ * Options getter
8
+ *
9
+ * @return array
10
+ */
11
+ public function toOptionArray()
12
+ {
13
+ return array(
14
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::SHAPE_CIRCLE, 'label'=>Mage::helper('adminhtml')->__(self::SHAPE_CIRCLE)),
15
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::SHAPE_RECTANGLE, 'label'=>Mage::helper('adminhtml')->__(self::SHAPE_RECTANGLE)),
16
+ );
17
+ }
18
+
19
+ /**
20
+ * Get options in "key-value" format
21
+ *
22
+ * @return array
23
+ */
24
+ public function toArray()
25
+ {
26
+ return array(
27
+ NightlyDev_FaviconBadge_Helper_Data::SHAPE_CIRCLE=>Mage::helper('adminhtml')->__(self::SHAPE_CIRCLE),
28
+ NightlyDev_FaviconBadge_Helper_Data::SHAPE_RECTANGLE=>Mage::helper('adminhtml')->__(self::SHAPE_RECTANGLE),
29
+ );
30
+ }
31
+
32
+ }
app/code/community/NightlyDev/FaviconBadge/Model/Adminhtml/System/Config/Source/Types.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class NightlyDev_FaviconBadge_Model_Adminhtml_System_Config_Source_Types
3
+ {
4
+ const TYPE_CART_ITEMS = 'Items in Cart.';
5
+ const TYPE_CART_QTYS = 'Quantity of Items in Cart.';
6
+ const TYPE_CART_ERRORS = 'Validation failures in forms.';
7
+ const TYPE_CART_ORDERS = 'Customer\'s Orders with Status.. (below)';
8
+ const TYPE_CART_DOWNS = 'Customer\'s Downloads with Status.. (below)';
9
+ const TYPE_CART_DATE = 'Days left until Date.. (below)';
10
+ const TYPE_CART_NUM = 'Fixed Number.. (below)';
11
+ /**
12
+ * Options getter
13
+ *
14
+ * @return array
15
+ */
16
+ public function toOptionArray()
17
+ {
18
+ return array(
19
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ITEMS, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_ITEMS)),
20
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_QTYS, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_QTYS)),
21
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ERRORS, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_ERRORS)),
22
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ORDERS, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_ORDERS)),
23
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DOWNS, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_DOWNS)),
24
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DATE, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_DATE)),
25
+ array('value' => NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_NUM, 'label'=>Mage::helper('adminhtml')->__(self::TYPE_CART_NUM)),
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Get options in "key-value" format
31
+ *
32
+ * @return array
33
+ */
34
+ public function toArray()
35
+ {
36
+ return array(
37
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ITEMS=>Mage::helper('adminhtml')->__(self::TYPE_CART_ITEMS),
38
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_QTYS=>Mage::helper('adminhtml')->__(self::TYPE_CART_QTYS),
39
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ERRORS=>Mage::helper('adminhtml')->__(self::TYPE_CART_ERRORS),
40
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ORDERS=>Mage::helper('adminhtml')->__(self::TYPE_CART_ORDERS),
41
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DOWNS=>Mage::helper('adminhtml')->__(self::TYPE_CART_DOWNS),
42
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_DATE=>Mage::helper('adminhtml')->__(self::TYPE_CART_DATE),
43
+ NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_NUM=>Mage::helper('adminhtml')->__(self::TYPE_CART_NUM),
44
+ );
45
+ }
46
+
47
+ }
app/code/community/NightlyDev/FaviconBadge/etc/config.xml ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <NightlyDev_FaviconBadge>
5
+ <version>1.0.0.0</version>
6
+ </NightlyDev_FaviconBadge>
7
+ </modules>
8
+ <global>
9
+ <blocks>
10
+ <nightlydevfaviconbadge>
11
+ <class>NightlyDev_FaviconBadge_Block</class>
12
+ </nightlydevfaviconbadge>
13
+ </blocks>
14
+ <helpers>
15
+ <nightlydevfaviconbadge>
16
+ <class>NightlyDev_FaviconBadge_Helper</class>
17
+ </nightlydevfaviconbadge>
18
+ </helpers>
19
+ <models>
20
+ <nightlydevfaviconbadge>
21
+ <class>NightlyDev_FaviconBadge_Model</class>
22
+ </nightlydevfaviconbadge>
23
+ </models>
24
+ </global>
25
+ <frontend>
26
+ <layout>
27
+ <updates>
28
+ <nightlydevfaviconbadge>
29
+ <file>nightlydevfaviconbadge.xml</file>
30
+ </nightlydevfaviconbadge>
31
+ </updates>
32
+ </layout>
33
+ </frontend>
34
+ <adminhtml>
35
+ <layout>
36
+ <updates>
37
+ <nightlydevfaviconbadge>
38
+ <file>nightlydevfaviconbadge.xml</file>
39
+ </nightlydevfaviconbadge>
40
+ </updates>
41
+ </layout>
42
+ </adminhtml>
43
+ <default>
44
+ <design>
45
+ <nightlydevfaviconbadge>
46
+ <enabled>0</enabled>
47
+ <type>1</type>
48
+ <bc>#5CB85C</bc>
49
+ <tc>#ff0</tc>
50
+ <pos>down</pos>
51
+ <anim>popFade</anim>
52
+ <shape>circle</shape>
53
+ </nightlydevfaviconbadge>
54
+ <nightlydevfaviconbadge_admin>
55
+ <enabled>0</enabled>
56
+ <alert>1</alert>
57
+ </nightlydevfaviconbadge_admin>
58
+ </design>
59
+ </default>
60
+ </config>
app/code/community/NightlyDev/FaviconBadge/etc/system.xml ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <design>
5
+ <groups>
6
+ <nightlydevfaviconbadge translate="label">
7
+ <label>Favicon Badges in Frontend pages</label>
8
+ <sort_order>5580</sort_order>
9
+ <show_in_default>1</show_in_default>
10
+ <show_in_website>1</show_in_website>
11
+ <show_in_store>1</show_in_store>
12
+ <fields>
13
+ <enabled translate="label">
14
+ <label>Favicon Badges in Frontend</label>
15
+ <frontend_type>select</frontend_type>
16
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
17
+ <sort_order>10</sort_order>
18
+ <show_in_default>1</show_in_default>
19
+ <show_in_website>1</show_in_website>
20
+ <show_in_store>1</show_in_store>
21
+ </enabled>
22
+ <bc translate="label">
23
+ <label>Background Color</label>
24
+ <frontend_type>text</frontend_type>
25
+ <sort_order>30</sort_order>
26
+ <show_in_default>1</show_in_default>
27
+ <show_in_website>1</show_in_website>
28
+ <show_in_store>1</show_in_store>
29
+ <validate>color {required:true, adjust:false, hash:true}</validate>
30
+ <depends><enabled>1</enabled></depends>
31
+ </bc>
32
+ <tc translate="label">
33
+ <label>Numeric Text Color</label>
34
+ <frontend_type>text</frontend_type>
35
+ <sort_order>20</sort_order>
36
+ <show_in_default>1</show_in_default>
37
+ <show_in_website>1</show_in_website>
38
+ <show_in_store>1</show_in_store>
39
+ <validate>color {required:true, adjust:false, hash:true}</validate>
40
+ <depends><enabled>1</enabled></depends>
41
+ </tc>
42
+ <pos translate="label">
43
+ <label>Position</label>
44
+ <frontend_type>select</frontend_type>
45
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_pos</source_model>
46
+ <sort_order>100</sort_order>
47
+ <show_in_default>1</show_in_default>
48
+ <show_in_website>1</show_in_website>
49
+ <show_in_store>1</show_in_store>
50
+ <depends><enabled>1</enabled></depends>
51
+ </pos>
52
+ <anim translate="label">
53
+ <label>Animation</label>
54
+ <frontend_type>select</frontend_type>
55
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_anims</source_model>
56
+ <sort_order>110</sort_order>
57
+ <show_in_default>1</show_in_default>
58
+ <show_in_website>1</show_in_website>
59
+ <show_in_store>1</show_in_store>
60
+ <depends><enabled>1</enabled></depends>
61
+ </anim>
62
+ <shape translate="label">
63
+ <label>Shape</label>
64
+ <frontend_type>select</frontend_type>
65
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_shapes</source_model>
66
+ <sort_order>120</sort_order>
67
+ <show_in_default>1</show_in_default>
68
+ <show_in_website>1</show_in_website>
69
+ <show_in_store>1</show_in_store>
70
+ <depends><enabled>1</enabled></depends>
71
+ </shape>
72
+ <type translate="label">
73
+ <label>Show number of</label>
74
+ <frontend_type>select</frontend_type>
75
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_types</source_model>
76
+ <sort_order>200</sort_order>
77
+ <show_in_default>1</show_in_default>
78
+ <show_in_website>1</show_in_website>
79
+ <show_in_store>1</show_in_store>
80
+ <depends><enabled>1</enabled></depends>
81
+ </type>
82
+ <order translate="label">
83
+ <label>Show number of Status</label>
84
+ <frontend_type>select</frontend_type>
85
+ <source_model>adminhtml/system_config_source_order_status</source_model>
86
+ <sort_order>210</sort_order>
87
+ <show_in_default>1</show_in_default>
88
+ <show_in_website>1</show_in_website>
89
+ <show_in_store>1</show_in_store>
90
+ <depends><type>8</type></depends>
91
+ </order>
92
+ <downs translate="label">
93
+ <label>Show number of Status</label>
94
+ <frontend_type>select</frontend_type>
95
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_downs</source_model>
96
+ <sort_order>220</sort_order>
97
+ <show_in_default>1</show_in_default>
98
+ <show_in_website>1</show_in_website>
99
+ <show_in_store>1</show_in_store>
100
+ <depends><type>16</type></depends>
101
+ </downs>
102
+ <num translate="label comment">
103
+ <label>Show number</label>
104
+ <frontend_type>text</frontend_type>
105
+ <validate>validate-digits</validate>
106
+ <sort_order>220</sort_order>
107
+ <show_in_default>1</show_in_default>
108
+ <show_in_website>1</show_in_website>
109
+ <show_in_store>1</show_in_store>
110
+ <depends><type>64</type></depends>
111
+ </num>
112
+ <date translate="label">
113
+ <label>Show number of days until</label>
114
+ <frontend_type>text</frontend_type>
115
+ <frontend_model>nightlydevfaviconbadge/adminhtml_system_config_source_date</frontend_model>
116
+ <sort_order>220</sort_order>
117
+ <show_in_default>1</show_in_default>
118
+ <show_in_website>1</show_in_website>
119
+ <show_in_store>1</show_in_store>
120
+ <format>yyyy-MM-dd</format>
121
+ <depends><type>32</type></depends>
122
+ </date>
123
+ </fields>
124
+ </nightlydevfaviconbadge>
125
+ <nightlydevfaviconbadge_admin translate="label">
126
+ <label>Favicon Badges in Admin pages</label>
127
+ <sort_order>5590</sort_order>
128
+ <show_in_default>1</show_in_default>
129
+ <show_in_website>0</show_in_website>
130
+ <show_in_store>0</show_in_store>
131
+ <fields>
132
+ <enabled translate="label">
133
+ <label>Favicon Badges for Admins</label>
134
+ <frontend_type>select</frontend_type>
135
+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
136
+ <sort_order>10</sort_order>
137
+ <show_in_default>1</show_in_default>
138
+ <show_in_website>0</show_in_website>
139
+ <show_in_store>0</show_in_store>
140
+ </enabled>
141
+ <alert translate="label">
142
+ <label>Alert admins about the number of</label>
143
+ <frontend_type>select</frontend_type>
144
+ <comment>Orders will have green background, and Errors red.</comment>
145
+ <source_model>nightlydevfaviconbadge/adminhtml_system_config_source_alerts</source_model>
146
+ <sort_order>20</sort_order>
147
+ <show_in_default>1</show_in_default>
148
+ <show_in_website>0</show_in_website>
149
+ <show_in_store>0</show_in_store>
150
+ <depends><enabled>1</enabled></depends>
151
+ </alert>
152
+ </fields>
153
+ </nightlydevfaviconbadge_admin>
154
+ </groups>
155
+ </design>
156
+ </sections>
157
+ </config>
app/code/community/NightlyDev/LICENSE ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <http://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <http://www.gnu.org/philosophy/why-not-lgpl.html>.
app/design/adminhtml/default/default/layout/nightlydevfaviconbadge.xml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <default>
4
+ <reference name="head">
5
+ <action ifconfig="design/nightlydevfaviconbadge_admin/enabled" method="addJs"><script>nightlydev/faviconbadge/favico-0.3.4.min.js</script></action>
6
+ </reference>
7
+ <reference name="js">
8
+ <block name="nightlydevfaviconbadge" type="core/template" template="nightlydevfaviconbadge/faviconbadge.phtml" />
9
+ </reference>
10
+ </default>
11
+ </layout>
app/design/adminhtml/default/default/template/nightlydevfaviconbadge/faviconbadge.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!Mage::getStoreConfig(NightlyDev_FaviconBadge_Helper_Data::XML_PATH_FAVBADGE_ADMIN_ENABLED)) return; ?>
2
+ <?php $badge = Mage::helper('nightlydevfaviconbadge')->getAdminBadges(); ?>
3
+ <?php if (!$badge->getOrders() and !$badge->getErrors()) return; ?>
4
+ <script type="text/javascript"><!--
5
+ Event.observe(window, "load", function(){
6
+ <?php if($badge->getOrders()): ?>
7
+ (new nightlydevFavico({
8
+ bgColor : '#009414',
9
+ textColor : '#FF0',
10
+ position : 'upleft',
11
+ animation : 'popFade',
12
+ type : 'circle'
13
+ })).badge(<?php echo $badge->getOrders(); ?>);
14
+ <?php endif; ?>
15
+ <?php if($badge->getErrors()): ?>
16
+ <?php if($badge->getOrders()): ?>setTimeout(function(){<?php endif; ?>
17
+ (new nightlydevFavico({
18
+ bgColor : '#F00',
19
+ textColor : '#FF0',
20
+ position : 'down',
21
+ animation : 'popFade',
22
+ type : 'circle'
23
+ })).badge(<?php echo $badge->getErrors(); ?>);
24
+ <?php if($badge->getOrders()): ?>},1000);<?php endif; ?>
25
+ <?php endif; ?>
26
+ });
27
+ //-->
28
+ </script>
app/design/frontend/base/default/layout/nightlydevfaviconbadge.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <default>
4
+ <reference name="head">
5
+ <action ifconfig="design/nightlydevfaviconbadge/enabled" method="addJs"><script>nightlydev/faviconbadge/favico-0.3.4.min.js</script></action>
6
+ <block name="nightlydevfaviconbadge" type="core/template" template="nightlydevfaviconbadge/faviconbadge.phtml" />
7
+ </reference>
8
+ </default>
9
+ </layout>
app/design/frontend/base/default/template/nightlydevfaviconbadge/faviconbadge.phtml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!Mage::getStoreConfig(NightlyDev_FaviconBadge_Helper_Data::XML_PATH_FAVBADGE_ENABLED)) return; ?>
2
+ <script type="text/javascript"><!--
3
+ Event.observe(window, "load", function(){
4
+ window.nightlydevBadge = new nightlydevFavico({
5
+ bgColor : '<?php echo Mage::helper('nightlydevfaviconbadge')->getBc(); ?>',
6
+ textColor : '<?php echo Mage::helper('nightlydevfaviconbadge')->getTc(); ?>',
7
+ position : '<?php echo Mage::helper('nightlydevfaviconbadge')->getPos(); ?>',
8
+ animation : '<?php echo Mage::helper('nightlydevfaviconbadge')->getAnim(); ?>',
9
+ type : '<?php echo Mage::helper('nightlydevfaviconbadge')->getShape(); ?>'
10
+ });
11
+ window.nightlydevBadge.badge(<?php echo Mage::helper('nightlydevfaviconbadge')->getBadge(); ?>);
12
+ <?php if ((int)Mage::getStoreConfig(NightlyDev_FaviconBadge_Helper_Data::XML_PATH_FAVBADGE_TYPE)===NightlyDev_FaviconBadge_Helper_Data::TYPE_CART_ERRORS): ?>
13
+ window.nightlydevbadgeerror = 0;
14
+ setInterval(function(){if(document.getElementsByClassName('validation-failed').length!=window.nightlydevbadgeerror){window.nightlydevbadgeerror=document.getElementsByClassName('validation-failed').length;window.nightlydevBadge.badge(window.nightlydevbadgeerror)}}, 500);
15
+ <?php endif; ?>
16
+ });
17
+ //-->
18
+ </script>
app/etc/modules/NightlyDev_FaviconBadge.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <NightlyDev_FaviconBadge>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Core />
9
+ </depends>
10
+ </NightlyDev_FaviconBadge>
11
+ </modules>
12
+ </config>
js/nightlydev/faviconbadge/favico-0.3.4.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /**
2
+ * @license MIT
3
+ * @fileOverview nightlydevFavico animations
4
+ * @author Miroslav Magda, http://blog.ejci.net
5
+ * @version 0.3.4
6
+ */
7
+ !function(){var e=function(e){"use strict";function t(e){if(e.paused||e.ended||w)return!1;try{d.clearRect(0,0,h,s),d.drawImage(e,0,0,h,s)}catch(o){}setTimeout(t,U.duration,e),L.setIcon(c)}function o(e){var t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(t,function(e,t,o,n){return t+t+o+o+n+n});var o=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return o?{r:parseInt(o[1],16),g:parseInt(o[2],16),b:parseInt(o[3],16)}:!1}function n(e,t){var o,n={};for(o in e)n[o]=e[o];for(o in t)n[o]=t[o];return n}function r(){return document.hidden||document.msHidden||document.webkitHidden||document.mozHidden}e=e?e:{};var i,a,s,h,c,d,f,l,u,g,y,w,x,m={bgColor:"#d00",textColor:"#fff",fontFamily:"sans-serif",fontStyle:"bold",type:"circle",position:"down",animation:"slide",elementId:!1};x={},x.ff=/firefox/i.test(navigator.userAgent.toLowerCase()),x.chrome=/chrome/i.test(navigator.userAgent.toLowerCase()),x.opera=/opera/i.test(navigator.userAgent.toLowerCase()),x.ie=/msie/i.test(navigator.userAgent.toLowerCase())||/trident/i.test(navigator.userAgent.toLowerCase()),x.supported=x.chrome||x.ff||x.opera;var p=[];y=function(){},l=w=!1;var v=function(){i=n(m,e),i.bgColor=o(i.bgColor),i.textColor=o(i.textColor),i.position=i.position.toLowerCase(),i.animation=U.types[""+i.animation]?i.animation:m.animation;var t=i.position.indexOf("up")>-1,r=i.position.indexOf("left")>-1;if(t||r)for(var l=0;l<U.types[""+i.animation].length;l++){var u=U.types[""+i.animation][l];t&&(u.y=u.y<.6?u.y-.4:u.y-2*u.y+(1-u.w)),r&&(u.x=u.x<.6?u.x-.4:u.x-2*u.x+(1-u.h)),U.types[""+i.animation][l]=u}i.type=C[""+i.type]?i.type:m.type;try{a=L.getIcon(),c=document.createElement("canvas"),f=document.createElement("img"),a.hasAttribute("href")?(f.setAttribute("src",a.getAttribute("href")),f.onload=function(){s=f.height>0?f.height:32,h=f.width>0?f.width:32,c.height=s,c.width=h,d=c.getContext("2d"),b.ready()}):(f.setAttribute("src",""),s=32,h=32,f.height=s,f.width=h,c.height=s,c.width=h,d=c.getContext("2d"),b.ready())}catch(g){throw"Error initializing favico. Message: "+g.message}},b={};b.ready=function(){l=!0,b.reset(),y()},b.reset=function(){p=[],u=!1,d.clearRect(0,0,h,s),d.drawImage(f,0,0,h,s),L.setIcon(c)},b.start=function(){if(l&&!g){var e=function(){u=p[0],g=!1,p.length>0&&(p.shift(),b.start())};p.length>0&&(g=!0,u?U.run(u.options,function(){U.run(p[0].options,function(){e()},!1)},!0):U.run(p[0].options,function(){e()},!1))}};var C={},M=function(e){return e.n=Math.abs(e.n),e.x=h*e.x,e.y=s*e.y,e.w=h*e.w,e.h=s*e.h,e};C.circle=function(e){e=M(e);var t=!1;e.n>9&&e.n<100?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.n>=100&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),d.clearRect(0,0,h,s),d.drawImage(f,0,0,h,s),d.beginPath(),d.font=i.fontStyle+" "+Math.floor(e.h*(e.n>99?.85:1))+"px "+i.fontFamily,d.textAlign="center",t?(d.moveTo(e.x+e.w/2,e.y),d.lineTo(e.x+e.w-e.h/2,e.y),d.quadraticCurveTo(e.x+e.w,e.y,e.x+e.w,e.y+e.h/2),d.lineTo(e.x+e.w,e.y+e.h-e.h/2),d.quadraticCurveTo(e.x+e.w,e.y+e.h,e.x+e.w-e.h/2,e.y+e.h),d.lineTo(e.x+e.h/2,e.y+e.h),d.quadraticCurveTo(e.x,e.y+e.h,e.x,e.y+e.h-e.h/2),d.lineTo(e.x,e.y+e.h/2),d.quadraticCurveTo(e.x,e.y,e.x+e.h/2,e.y)):d.arc(e.x+e.w/2,e.y+e.h/2,e.h/2,0,2*Math.PI),d.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",d.fill(),d.closePath(),d.beginPath(),d.stroke(),d.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")",e.n>999?d.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):d.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),d.closePath()},C.rectangle=function(e){e=M(e);var t=!1;e.n>9&&e.n<100?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.n>=100&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),d.clearRect(0,0,h,s),d.drawImage(f,0,0,h,s),d.beginPath(),d.font="bold "+Math.floor(e.h*(e.n>99?.9:1))+"px sans-serif",d.textAlign="center",d.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",d.fillRect(e.x,e.y,e.w,e.h),d.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")",e.n>999?d.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):d.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),d.closePath()};var I=function(e,t){y=function(){try{if(e>0){if(U.types[""+t]&&(i.animation=t),p.push({type:"badge",options:{n:e}}),p.length>100)throw"Too many badges requests in queue.";b.start()}else b.reset()}catch(o){throw"Error setting badge. Message: "+o.message}},l&&y()},A=function(e){y=function(){try{var t=e.width,o=e.height,n=document.createElement("img"),r=o/s>t/h?t/h:o/s;n.setAttribute("src",e.getAttribute("src")),n.height=o/r,n.width=t/r,d.clearRect(0,0,h,s),d.drawImage(n,0,0,h,s),L.setIcon(c)}catch(i){throw"Error setting image. Message: "+i.message}},l&&y()},E=function(e){y=function(){try{if("stop"===e)return w=!0,b.reset(),w=!1,void 0;e.addEventListener("play",function(){t(this)},!1)}catch(o){throw"Error setting video. Message: "+o.message}},l&&y()},T=function(e){if(window.URL&&window.URL.createObjectURL||(window.URL=window.URL||{},window.URL.createObjectURL=function(e){return e}),x.supported){var o=!1;navigator.getUserMedia=navigator.getUserMedia||navigator.oGetUserMedia||navigator.msGetUserMedia||navigator.mozGetUserMedia||navigator.webkitGetUserMedia,y=function(){try{if("stop"===e)return w=!0,b.reset(),w=!1,void 0;o=document.createElement("video"),o.width=h,o.height=s,navigator.getUserMedia({video:!0,audio:!1},function(e){o.src=URL.createObjectURL(e),o.play(),t(o)},function(){})}catch(n){throw"Error setting webcam. Message: "+n.message}},l&&y()}},L={};L.getIcon=function(){var e=!1,t="",o=function(){for(var e=document.getElementsByTagName("head")[0].getElementsByTagName("link"),t=e.length,o=t-1;o>=0;o--)if(/icon/i.test(e[o].getAttribute("rel")))return e[o];return!1};if(i.elementId?(e=document.getElementById(i.elementId),e.setAttribute("href",e.getAttribute("src"))):(e=o(),e===!1&&(e=document.createElement("link"),e.setAttribute("rel","icon"),document.getElementsByTagName("head")[0].appendChild(e))),t=i.elementId?e.src:e.href,-1===t.indexOf(document.location.hostname))throw new Error("Error setting favicon. Favicon image is on different domain (Icon: "+t+", Domain: "+document.location.hostname+")");return e.setAttribute("type","image/png"),e},L.setIcon=function(e){var t=e.toDataURL("image/png");if(i.elementId)document.getElementById(i.elementId).setAttribute("src",t);else if(x.ff||x.opera){var o=a;a=document.createElement("link"),x.opera&&a.setAttribute("rel","icon"),a.setAttribute("rel","icon"),a.setAttribute("type","image/png"),document.getElementsByTagName("head")[0].appendChild(a),a.setAttribute("href",t),o.parentNode&&o.parentNode.removeChild(o)}else a.setAttribute("href",t)};var U={};return U.duration=40,U.types={},U.types.fade=[{x:.4,y:.4,w:.6,h:.6,o:0},{x:.4,y:.4,w:.6,h:.6,o:.1},{x:.4,y:.4,w:.6,h:.6,o:.2},{x:.4,y:.4,w:.6,h:.6,o:.3},{x:.4,y:.4,w:.6,h:.6,o:.4},{x:.4,y:.4,w:.6,h:.6,o:.5},{x:.4,y:.4,w:.6,h:.6,o:.6},{x:.4,y:.4,w:.6,h:.6,o:.7},{x:.4,y:.4,w:.6,h:.6,o:.8},{x:.4,y:.4,w:.6,h:.6,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],U.types.none=[{x:.4,y:.4,w:.6,h:.6,o:1}],U.types.pop=[{x:1,y:1,w:0,h:0,o:1},{x:.9,y:.9,w:.1,h:.1,o:1},{x:.8,y:.8,w:.2,h:.2,o:1},{x:.7,y:.7,w:.3,h:.3,o:1},{x:.6,y:.6,w:.4,h:.4,o:1},{x:.5,y:.5,w:.5,h:.5,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],U.types.popFade=[{x:.75,y:.75,w:0,h:0,o:0},{x:.65,y:.65,w:.1,h:.1,o:.2},{x:.6,y:.6,w:.2,h:.2,o:.4},{x:.55,y:.55,w:.3,h:.3,o:.6},{x:.5,y:.5,w:.4,h:.4,o:.8},{x:.45,y:.45,w:.5,h:.5,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],U.types.slide=[{x:.4,y:1,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.8,w:.6,h:.6,o:1},{x:.4,y:.7,w:.6,h:.6,o:1},{x:.4,y:.6,w:.6,h:.6,o:1},{x:.4,y:.5,w:.6,h:.6,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],U.run=function(e,t,o,a){var s=U.types[r()?"none":i.animation];return a=o===!0?"undefined"!=typeof a?a:s.length-1:"undefined"!=typeof a?a:0,t=t?t:function(){},a<s.length&&a>=0?(C[i.type](n(e,s[a])),setTimeout(function(){o?a-=1:a+=1,U.run(e,t,o,a)},U.duration),L.setIcon(c),void 0):(t(),void 0)},v(),{badge:I,video:E,image:A,webcam:T,reset:b.reset}};"undefined"!=typeof define&&define.amd?define([],function(){return e}):"undefined"!=typeof module&&module.exports?module.exports=e:this.nightlydevFavico=e}();
js/nightlydev/faviconbadge/favico.js ADDED
@@ -0,0 +1,873 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license MIT
3
+ * @fileOverview nightlydevFavico animations
4
+ * @author Miroslav Magda, http://blog.ejci.net
5
+ * @version .4.0
6
+ */
7
+
8
+ /**
9
+ * Create new favico instance
10
+ * @param {Object} Options
11
+ * @return {Object} nightlydevFavico object
12
+ * @example
13
+ * var favico = new nightlydevFavico ({
14
+ * bgColor : '#d00',
15
+ * textColor : '#fff',
16
+ * fontFamily : 'sans-serif',
17
+ * fontStyle : 'bold',
18
+ * position : 'down',
19
+ * type : 'circle',
20
+ * animation : 'slide',
21
+ * });
22
+ */
23
+ (function() {
24
+
25
+ var nightlydevFavico = (function(params) {'use strict';
26
+ var VERSION = '.4.0';
27
+ var defaultParams = {
28
+ bgColor : '#d00',
29
+ textColor : '#fff',
30
+ fontFamily : 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
31
+ fontStyle : 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
32
+ type : 'circle',
33
+ position : 'down', // down, up, left, leftup (upleft)
34
+ animation : 'slide',
35
+ fallbackUrl : '//favico.jit.su/image',
36
+ elementId : false
37
+ };
38
+ var element, height, width, canvas, ctx, tempImg, isReady, isLastFrame, isRunning, isReadyCb, stop, browser, animationTimer, drawTimer;
39
+
40
+ var queue = [];
41
+
42
+ params = (params) ? params : {};
43
+ isReadyCb = function() {
44
+ };
45
+ isReady = stop = false;
46
+
47
+ browser = {};
48
+ browser.ff = (/firefox/i.test(navigator.userAgent.toLowerCase()));
49
+ browser.chrome = (/chrome/i.test(navigator.userAgent.toLowerCase()));
50
+ browser.opera = (/opera/i.test(navigator.userAgent.toLowerCase()));
51
+ browser.ie = (/msie/i.test(navigator.userAgent.toLowerCase())) || (/trident/i.test(navigator.userAgent.toLowerCase()));
52
+ browser.safari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
53
+ browser.supported = (browser.chrome || browser.ff || browser.opera);
54
+
55
+ /**
56
+ * Initialize favico
57
+ */
58
+ var init = function() {
59
+ //merge initial options
60
+ params = merge(defaultParams, params);
61
+
62
+ params.position = params.position.toLowerCase();
63
+ params.animation = (animation.types['' + params.animation]) ? params.animation : defaultParams.animation;
64
+
65
+ var isUp = params.position.indexOf('up') > -1;
66
+ var isLeft = params.position.indexOf('left') > -1;
67
+
68
+ //transform animation frames coordinates (default)
69
+ if (isUp || isLeft) {
70
+ for (var i = 0; i < animation.types['' + params.animation].length; i++) {
71
+ var frame = animation.types['' + params.animation][i];
72
+ if (isUp) {
73
+ if (frame.y < .6) {
74
+ frame.y = frame.y - .4;
75
+ } else {
76
+ frame.y = frame.y - 2 * frame.y + (1 - frame.w);
77
+ }
78
+ }
79
+ if (isLeft) {
80
+ if (frame.x < .6) {
81
+ frame.x = frame.x - .4;
82
+ } else {
83
+ frame.x = frame.x - 2 * frame.x + (1 - frame.h);
84
+ }
85
+ }
86
+ animation.types['' + params.animation][i] = frame;
87
+ }
88
+ }
89
+ params.type = (type['' + params.type]) ? params.type : defaultParams.type;
90
+
91
+ try {
92
+ element = link.getIcon();
93
+ if (browser.supported) {
94
+ /**
95
+ * Create temporary elements
96
+ */
97
+ canvas = document.createElement('canvas');
98
+ tempImg = document.createElement('img');
99
+ if (element.hasAttribute('href')) {
100
+ tempImg.setAttribute('src', element.getAttribute('href'));
101
+ /**
102
+ * Get width and height of image
103
+ */
104
+ tempImg.onload = function() {
105
+ height = (tempImg.height > 0) ? tempImg.height : 32;
106
+ width = (tempImg.width > 0) ? tempImg.width : 32;
107
+ canvas.height = height;
108
+ canvas.width = width;
109
+ ctx = canvas.getContext('2d');
110
+ icon.ready();
111
+ };
112
+ } else {
113
+ /**
114
+ * Create default empty image
115
+ */
116
+ tempImg.setAttribute('src', '');
117
+ height = 32;
118
+ width = 32;
119
+ tempImg.height = height;
120
+ tempImg.width = width;
121
+ canvas.height = height;
122
+ canvas.width = width;
123
+ ctx = canvas.getContext('2d');
124
+ icon.ready();
125
+ }
126
+ } else {
127
+ /**
128
+ * Fallback
129
+ */
130
+ icon.ready();
131
+ }
132
+ } catch(e) {
133
+ throw 'Error initializing favico. Message: ' + e.message;
134
+ }
135
+
136
+ };
137
+ /**
138
+ * Icon namespace
139
+ */
140
+ var icon = {};
141
+ /**
142
+ * Icon is ready (reset icon) and start animation (if ther is any)
143
+ */
144
+ icon.ready = function() {
145
+ isReady = true;
146
+ icon.reset();
147
+ isReadyCb();
148
+ };
149
+
150
+ /**
151
+ * Reset icon to default state
152
+ */
153
+ icon.reset = function() {
154
+ queue = [];
155
+ isRunning = false;
156
+ isLastFrame = false;
157
+ if (browser.supported) {
158
+ ctx.clearRect(0, 0, width, height);
159
+ ctx.drawImage(tempImg, 0, 0, width, height);
160
+ link.setIcon(canvas);
161
+ } else {
162
+ link.setIcon();
163
+ }
164
+ window.clearTimeout(animationTimer);
165
+ window.clearTimeout(drawTimer);
166
+ };
167
+ /**
168
+ * Start animation
169
+ */
170
+ icon.start = function() {
171
+ if (!isReady || isRunning) {
172
+ return;
173
+ }
174
+ var finished = function() {
175
+ isLastFrame = queue[0];
176
+ isRunning = false;
177
+ if (queue.length > 0) {
178
+ queue.shift();
179
+ icon.start();
180
+ } else {
181
+
182
+ }
183
+ };
184
+ if (queue.length > 0) {
185
+ isRunning = true;
186
+ var run = function() {
187
+ animation.run(queue[0].options, function() {
188
+ finished();
189
+ }, false);
190
+ };
191
+ if (isLastFrame) {
192
+ animation.run(isLastFrame.options, function() {
193
+ run();
194
+ }, true);
195
+ } else {
196
+ run();
197
+ }
198
+ }
199
+ };
200
+
201
+ /**
202
+ * Badge types
203
+ */
204
+ var type = {};
205
+ var options = function(opt) {
206
+ opt.n = (( typeof opt.n) === 'number') ? Math.abs(opt.n | 0) : opt.n;
207
+ opt.x = width * opt.x;
208
+ opt.y = height * opt.y;
209
+ opt.w = width * opt.w;
210
+ opt.h = height * opt.h;
211
+ opt.len = ("" + opt.n).length;
212
+ return opt;
213
+ };
214
+ /**
215
+ * Generate circle
216
+ * @param {Object} opt Badge options
217
+ */
218
+ type.circle = function(opt) {
219
+ opt = options(opt);
220
+ var badgeParams = merge(params,opt);
221
+ var more = false;
222
+ if (opt.len === 2) {
223
+ opt.x = opt.x - opt.w * .4;
224
+ opt.w = opt.w * 1.4;
225
+ more = true;
226
+ } else if (opt.len >= 3) {
227
+ opt.x = opt.x - opt.w * .65;
228
+ opt.w = opt.w * 1.65;
229
+ more = true;
230
+ }
231
+ var bgColor = hexToRgb(badgeParams.bgColor);
232
+ var textColor = hexToRgb(badgeParams.textColor);
233
+
234
+ ctx.clearRect(0, 0, width, height);
235
+ ctx.drawImage(tempImg, 0, 0, width, height);
236
+ ctx.beginPath();
237
+ ctx.font = badgeParams.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? .85 : 1)) + "px " + badgeParams.fontFamily;
238
+ ctx.textAlign = 'center';
239
+ if (more) {
240
+ ctx.moveTo(opt.x + opt.w / 2, opt.y);
241
+ ctx.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
242
+ ctx.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
243
+ ctx.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
244
+ ctx.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
245
+ ctx.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
246
+ ctx.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
247
+ ctx.lineTo(opt.x, opt.y + opt.h / 2);
248
+ ctx.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
249
+ } else {
250
+ ctx.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
251
+ }
252
+ ctx.fillStyle = 'rgba(' + bgColor.r + ',' + bgColor.g + ',' + bgColor.b + ',' + opt.o + ')';
253
+ ctx.fill();
254
+ ctx.closePath();
255
+ ctx.beginPath();
256
+ ctx.stroke();
257
+ ctx.fillStyle = 'rgba(' + textColor.r + ',' + textColor.g + ',' + textColor.b + ',' + opt.o + ')';
258
+ if (( typeof opt.n) === 'number' && opt.n > 999) {
259
+ ctx.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * .2));
260
+ } else {
261
+ ctx.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * .15));
262
+ }
263
+ ctx.closePath();
264
+ };
265
+ /**
266
+ * Generate rectangle
267
+ * @param {Object} opt Badge options
268
+ */
269
+ type.rectangle = function(opt) {
270
+ opt = options(opt);
271
+ var badgeParams = merge(params,opt);
272
+
273
+ var more = false;
274
+ if (opt.len === 2) {
275
+ opt.x = opt.x - opt.w * .4;
276
+ opt.w = opt.w * 1.4;
277
+ more = true;
278
+ } else if (opt.len >= 3) {
279
+ opt.x = opt.x - opt.w * .65;
280
+ opt.w = opt.w * 1.65;
281
+ more = true;
282
+ }
283
+ var bgColor = hexToRgb(badgeParams.bgColor);
284
+ var textColor = hexToRgb(badgeParams.textColor);
285
+
286
+ ctx.clearRect(0, 0, width, height);
287
+ ctx.drawImage(tempImg, 0, 0, width, height);
288
+ ctx.beginPath();
289
+ ctx.font = badgeParams.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? .9 : 1)) + "px " + badgeParams.fontFamily;
290
+ ctx.textAlign = 'center';
291
+ ctx.fillStyle = 'rgba(' + bgColor.r + ',' + bgColor.g + ',' + bgColor.b + ',' + opt.o + ')';
292
+ ctx.fillRect(opt.x, opt.y, opt.w, opt.h);
293
+ ctx.fillStyle = 'rgba(' + textColor.r + ',' + textColor.g + ',' + textColor.b + ',' + opt.o + ')';
294
+ if (( typeof opt.n) === 'number' && opt.n > 999) {
295
+ ctx.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * .2));
296
+ } else {
297
+ ctx.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * .15));
298
+ }
299
+ ctx.closePath();
300
+ };
301
+
302
+ /**
303
+ * Set badge
304
+ */
305
+ var badge = function(number, opts) {
306
+ opts = (( typeof opts) === 'string' ? {
307
+ animation : opts
308
+ } : opts) || {};
309
+ isReadyCb = function() {
310
+ try {
311
+ if ( typeof (number) === 'number' ? (number > 0) : (number !== '')) {
312
+ var q = {
313
+ type : 'badge',
314
+ options : {
315
+ }
316
+ };
317
+ q.options = merge(params, opts);
318
+ q.options.n=number;
319
+ queue.push(q);
320
+ if (queue.length > 100) {
321
+ throw 'Too many badges requests in queue.';
322
+ }
323
+ icon.start();
324
+ } else {
325
+ icon.reset();
326
+ }
327
+ } catch(e) {
328
+ throw 'Error setting badge. Message: ' + e.message;
329
+ }
330
+ };
331
+ if (browser.supported) {
332
+ if (isReady) {
333
+ isReadyCb();
334
+ }
335
+ } else {
336
+ var badgeParams = params;
337
+ badgeParams.url = element.getAttribute('x-orig-src');
338
+ badgeParams.badge = number;
339
+ badgeParams = merge(params, opts);
340
+ element.href = params.fallbackUrl + '?options=' + encodeURIComponent(JSON.stringify(badgeParams)) + '&v=' + VERSION;
341
+ element.src = element.href;
342
+ }
343
+ };
344
+
345
+ /**
346
+ * Set image as icon
347
+ */
348
+ var image = function(imageElement) {
349
+ isReadyCb = function() {
350
+ try {
351
+ var w = imageElement.width;
352
+ var h = imageElement.height;
353
+ var newImg = document.createElement('img');
354
+ var ratio = (w / width < h / height) ? (w / width) : (h / height);
355
+ newImg.setAttribute('src', imageElement.getAttribute('src'));
356
+ newImg.height = (h / ratio);
357
+ newImg.width = (w / ratio);
358
+ ctx.clearRect(0, 0, width, height);
359
+ ctx.drawImage(newImg, 0, 0, width, height);
360
+ link.setIcon(canvas);
361
+ } catch(e) {
362
+ throw 'Error setting image. Message: ' + e.message;
363
+ }
364
+ };
365
+ if (browser.supported) {
366
+ if (isReady) {
367
+ isReadyCb();
368
+ }
369
+ } else {
370
+ params.url = element.getAttribute('x-orig-src');
371
+ params.badge = number;
372
+ merge(params, opt);
373
+ imageElement.src = params.fallbackUrl + '?options=' + encodeURIComponent(JSON.stringify(params)) + '&v=' + VERSION;
374
+ }
375
+ };
376
+ /**
377
+ * Set video as icon
378
+ */
379
+ var video = function(videoElement) {
380
+ if (browser.supported) {
381
+ isReadyCb = function() {
382
+ try {
383
+ if (videoElement === 'stop') {
384
+ stop = true;
385
+ icon.reset();
386
+ stop = false;
387
+ return;
388
+ }
389
+
390
+ videoElement.addEventListener('play', function() {
391
+ drawVideo(this);
392
+ }, false);
393
+
394
+ } catch(e) {
395
+ throw 'Error setting video. Message: ' + e.message;
396
+ }
397
+ };
398
+ if (isReady) {
399
+ isReadyCb();
400
+ }
401
+ }
402
+ };
403
+ /**
404
+ * Set video as icon
405
+ */
406
+ var webcam = function(action) {
407
+ if (browser.supported) {
408
+ var newVideo = false;
409
+ if (!window.URL || !window.URL.createObjectURL) {
410
+ window.URL = window.URL || {};
411
+ window.URL.createObjectURL = function(obj) {
412
+ return obj;
413
+ };
414
+ }
415
+ navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
416
+ isReadyCb = function() {
417
+ try {
418
+ if (action === 'stop') {
419
+ stop = true;
420
+ icon.reset();
421
+ stop = false;
422
+ return;
423
+ }
424
+ newVideo = document.createElement('video');
425
+ newVideo.width = width;
426
+ newVideo.height = height;
427
+ navigator.getUserMedia({
428
+ video : true,
429
+ audio : false
430
+ }, function(stream) {
431
+ newVideo.src = URL.createObjectURL(stream);
432
+ newVideo.play();
433
+ drawVideo(newVideo);
434
+ }, function() {
435
+ });
436
+ } catch(e) {
437
+ throw 'Error setting webcam. Message: ' + e.message;
438
+ }
439
+ };
440
+ if (isReady) {
441
+ isReadyCb();
442
+ }
443
+ }
444
+
445
+ };
446
+
447
+ /**
448
+ * Draw video to context and repeat :)
449
+ */
450
+ function drawVideo(video) {
451
+ if (video.paused || video.ended || stop) {
452
+ return false;
453
+ }
454
+ //nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
455
+ try {
456
+ ctx.clearRect(0, 0, width, height);
457
+ ctx.drawImage(video, 0, 0, width, height);
458
+ } catch(e) {
459
+
460
+ }
461
+ drawTimer = setTimeout(drawVideo, animation.duration, video);
462
+ link.setIcon(canvas);
463
+ }
464
+
465
+ var link = {};
466
+ /**
467
+ * Get icon from HEAD tag or create a new <link> element
468
+ */
469
+ link.getIcon = function() {
470
+ var elm = false;
471
+ var url = '';
472
+ //get link element
473
+ var getLink = function() {
474
+ var link = document.getElementsByTagName('head')[0].getElementsByTagName('link');
475
+ for (var l = link.length, i = (l - 1); i >= 0; i--) {
476
+ if ((/(^|\s)icon(\s|$)/i).test(link[i].getAttribute('rel'))) {
477
+ return link[i];
478
+ }
479
+ }
480
+ return false;
481
+ };
482
+ if (params.elementId) {
483
+ //if img element identified by elementId
484
+ elm = document.getElementById(params.elementId);
485
+ elm.setAttribute('href', elm.src);
486
+ elm.setAttribute('x-orig-src', elm.src);
487
+ } else {
488
+ //if link element
489
+ elm = getLink();
490
+ if (elm === false) {
491
+ elm = document.createElement('link');
492
+ elm.setAttribute('rel', 'icon');
493
+ document.getElementsByTagName('head')[0].appendChild(elm);
494
+ }
495
+ elm.setAttribute('x-orig-src', elm.href);
496
+ }
497
+ //check if image and link url is on same domain. if not raise error
498
+ url = (params.elementId) ? elm.src : elm.href;
499
+ if (browser.supported && url.substr(0, 5) !== 'data:' && url.indexOf(document.location.hostname) === -1) {
500
+ throw new Error('Error setting favicon. Favicon image is on different domain (Icon: ' + url + ', Domain: ' + document.location.hostname + ')');
501
+ }
502
+ elm.setAttribute('type', 'image/png');
503
+ return elm;
504
+ };
505
+ link.setIcon = function(canvas) {
506
+ if (canvas) {
507
+ var url = canvas.toDataURL('image/png');
508
+ if (params.elementId) {
509
+ //if is attached to element (image)
510
+ element.setAttribute('src', url);
511
+ } else {
512
+ //if is attached to fav icon
513
+ if (browser.ff || browser.opera) {
514
+ //for FF we need to "recreate" element, atach to dom and remove old <link>
515
+ var old = element;
516
+ element = document.createElement('link');
517
+ if (browser.opera) {
518
+ element.setAttribute('rel', 'icon');
519
+ }
520
+ element.setAttribute('rel', 'icon');
521
+ element.setAttribute('type', 'image/png');
522
+ document.getElementsByTagName('head')[0].appendChild(element);
523
+ element.setAttribute('href', url);
524
+ if (old.parentNode) {
525
+ old.parentNode.removeChild(old);
526
+ }
527
+ } else {
528
+ element.setAttribute('href', url);
529
+ }
530
+ }
531
+ } else {
532
+ //it will reset the default state
533
+ element.setAttribute('href', element.getAttribute('x-orig-src'));
534
+ element.setAttribute('src', element.getAttribute('x-orig-src'));
535
+ }
536
+ };
537
+
538
+ //http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
539
+ //HEX to RGB convertor
540
+ function hexToRgb(hex) {
541
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
542
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
543
+ return r + r + g + g + b + b;
544
+ });
545
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
546
+ return result ? {
547
+ r : parseInt(result[1], 16),
548
+ g : parseInt(result[2], 16),
549
+ b : parseInt(result[3], 16)
550
+ } : false;
551
+ }
552
+
553
+ /**
554
+ * Merge options
555
+ */
556
+ function merge(def, opt) {
557
+ var mergedOpt = {};
558
+ var attrname;
559
+ for (attrname in def) {
560
+ mergedOpt[attrname] = def[attrname];
561
+ }
562
+ for (attrname in opt) {
563
+ mergedOpt[attrname] = opt[attrname];
564
+ }
565
+ return mergedOpt;
566
+ }
567
+
568
+ /**
569
+ * Cross-browser page visibility shim
570
+ * http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
571
+ */
572
+ function isPageHidden() {
573
+ return document.hidden || document.msHidden || document.webkitHidden || document.mozHidden;
574
+ }
575
+
576
+ /**
577
+ * For each method (for older browsers)
578
+ */
579
+ function forEach(array, fn) {
580
+ for (var i = 0; i < array.length; i++)
581
+ fn(array[i], i);
582
+ }
583
+
584
+ /**
585
+ * @namespace animation
586
+ */
587
+ var animation = {};
588
+ /**
589
+ * Animation "frame" duration
590
+ */
591
+ animation.duration = 40;
592
+ /**
593
+ * Animation types (none,fade,pop,slide)
594
+ */
595
+ animation.types = {};
596
+ animation.types.fade = [{
597
+ x : .4,
598
+ y : .4,
599
+ w : .6,
600
+ h : .6,
601
+ o : .0
602
+ }, {
603
+ x : .4,
604
+ y : .4,
605
+ w : .6,
606
+ h : .6,
607
+ o : .1
608
+ }, {
609
+ x : .4,
610
+ y : .4,
611
+ w : .6,
612
+ h : .6,
613
+ o : .2
614
+ }, {
615
+ x : .4,
616
+ y : .4,
617
+ w : .6,
618
+ h : .6,
619
+ o : .3
620
+ }, {
621
+ x : .4,
622
+ y : .4,
623
+ w : .6,
624
+ h : .6,
625
+ o : .4
626
+ }, {
627
+ x : .4,
628
+ y : .4,
629
+ w : .6,
630
+ h : .6,
631
+ o : .5
632
+ }, {
633
+ x : .4,
634
+ y : .4,
635
+ w : .6,
636
+ h : .6,
637
+ o : .6
638
+ }, {
639
+ x : .4,
640
+ y : .4,
641
+ w : .6,
642
+ h : .6,
643
+ o : .7
644
+ }, {
645
+ x : .4,
646
+ y : .4,
647
+ w : .6,
648
+ h : .6,
649
+ o : .8
650
+ }, {
651
+ x : .4,
652
+ y : .4,
653
+ w : .6,
654
+ h : .6,
655
+ o : .9
656
+ }, {
657
+ x : .4,
658
+ y : .4,
659
+ w : .6,
660
+ h : .6,
661
+ o : 1.0
662
+ }];
663
+ animation.types.none = [{
664
+ x : .4,
665
+ y : .4,
666
+ w : .6,
667
+ h : .6,
668
+ o : 1
669
+ }];
670
+ animation.types.pop = [{
671
+ x : 1,
672
+ y : 1,
673
+ w : 0,
674
+ h : 0,
675
+ o : 1
676
+ }, {
677
+ x : .9,
678
+ y : .9,
679
+ w : .1,
680
+ h : .1,
681
+ o : 1
682
+ }, {
683
+ x : .8,
684
+ y : .8,
685
+ w : .2,
686
+ h : .2,
687
+ o : 1
688
+ }, {
689
+ x : .7,
690
+ y : .7,
691
+ w : .3,
692
+ h : .3,
693
+ o : 1
694
+ }, {
695
+ x : .6,
696
+ y : .6,
697
+ w : .4,
698
+ h : .4,
699
+ o : 1
700
+ }, {
701
+ x : .5,
702
+ y : .5,
703
+ w : .5,
704
+ h : .5,
705
+ o : 1
706
+ }, {
707
+ x : .4,
708
+ y : .4,
709
+ w : .6,
710
+ h : .6,
711
+ o : 1
712
+ }];
713
+ animation.types.popFade = [{
714
+ x : .75,
715
+ y : .75,
716
+ w : 0,
717
+ h : 0,
718
+ o : 0
719
+ }, {
720
+ x : .65,
721
+ y : .65,
722
+ w : .1,
723
+ h : .1,
724
+ o : .2
725
+ }, {
726
+ x : .6,
727
+ y : .6,
728
+ w : .2,
729
+ h : .2,
730
+ o : .4
731
+ }, {
732
+ x : .55,
733
+ y : .55,
734
+ w : .3,
735
+ h : .3,
736
+ o : .6
737
+ }, {
738
+ x : .50,
739
+ y : .50,
740
+ w : .4,
741
+ h : .4,
742
+ o : .8
743
+ }, {
744
+ x : .45,
745
+ y : .45,
746
+ w : .5,
747
+ h : .5,
748
+ o : .9
749
+ }, {
750
+ x : .4,
751
+ y : .4,
752
+ w : .6,
753
+ h : .6,
754
+ o : 1
755
+ }];
756
+ animation.types.slide = [{
757
+ x : .4,
758
+ y : 1,
759
+ w : .6,
760
+ h : .6,
761
+ o : 1
762
+ }, {
763
+ x : .4,
764
+ y : .9,
765
+ w : .6,
766
+ h : .6,
767
+ o : 1
768
+ }, {
769
+ x : .4,
770
+ y : .9,
771
+ w : .6,
772
+ h : .6,
773
+ o : 1
774
+ }, {
775
+ x : .4,
776
+ y : .8,
777
+ w : .6,
778
+ h : .6,
779
+ o : 1
780
+ }, {
781
+ x : .4,
782
+ y : .7,
783
+ w : .6,
784
+ h : .6,
785
+ o : 1
786
+ }, {
787
+ x : .4,
788
+ y : .6,
789
+ w : .6,
790
+ h : .6,
791
+ o : 1
792
+ }, {
793
+ x : .4,
794
+ y : .5,
795
+ w : .6,
796
+ h : .6,
797
+ o : 1
798
+ }, {
799
+ x : .4,
800
+ y : .4,
801
+ w : .6,
802
+ h : .6,
803
+ o : 1
804
+ }];
805
+ /**
806
+ * Run animation
807
+ * @param {Object} opt Animation options
808
+ * @param {Object} cb Callbak after all frames are done
809
+ * @param {Object} revert Reverse order? true|false
810
+ * @param {Object} frame Optional frame number
811
+ */
812
+ animation.run = function(opt, cb, revert, frame) {
813
+ var animationType = animation.types[isPageHidden() ? 'none' : params.animation];
814
+ if (revert === true) {
815
+ frame = ( typeof frame !== 'undefined') ? frame : animationType.length - 1;
816
+ } else {
817
+ frame = ( typeof frame !== 'undefined') ? frame : 0;
818
+ }
819
+ cb = (cb) ? cb : function() {
820
+ };
821
+ if ((frame < animationType.length) && (frame >= 0)) {
822
+ type[params.type](merge(opt, animationType[frame]));
823
+ animationTimer = setTimeout(function() {
824
+ if (revert) {
825
+ frame = frame - 1;
826
+ } else {
827
+ frame = frame + 1;
828
+ }
829
+ animation.run(opt, cb, revert, frame);
830
+ }, animation.duration);
831
+
832
+ link.setIcon(canvas);
833
+ } else {
834
+ cb();
835
+ }
836
+ };
837
+
838
+ /**
839
+ * Auto init
840
+ */
841
+ init();
842
+ /**
843
+ * Public methods
844
+ */
845
+ return {
846
+ badge : badge,
847
+ video : video,
848
+ image : image,
849
+ webcam : webcam,
850
+ reset : icon.reset,
851
+ browser : {
852
+ supported : browser.supported
853
+ }
854
+ };
855
+ });
856
+
857
+ // AMD / RequireJS
858
+ if ( typeof define !== 'undefined' && define.amd) {
859
+ define([], function() {
860
+ return nightlydevFavico ;
861
+ });
862
+ }
863
+ // CommonJS
864
+ else if ( typeof module !== 'undefined' && module.exports) {
865
+ module.exports = nightlydevFavico ;
866
+ }
867
+ // included directly via <script> tag
868
+ else {
869
+ this.nightlydevFavico = nightlydevFavico ;
870
+ }
871
+
872
+ })();
873
+
js/nightlydev/jscolor/arrow.gif ADDED
Binary file
js/nightlydev/jscolor/cross.gif ADDED
Binary file
js/nightlydev/jscolor/hs.png ADDED
Binary file
js/nightlydev/jscolor/hv.png ADDED
Binary file
js/nightlydev/jscolor/jscolor.js ADDED
@@ -0,0 +1,997 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * jscolor, JavaScript Color Picker
3
+ *
4
+ * @version 1.4.2
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 2013-11-25
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*(\\{[^}]*\\})?', 'i');
71
+ var e = document.getElementsByTagName('input');
72
+ for(var i=0; i<e.length; i+=1) {
73
+ var m;
74
+ if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
75
+ var prop = {};
76
+ if(m[3]) {
77
+ try {
78
+ prop = (new Function ('return (' + m[3] + ')'))();
79
+ } catch(eInvalidProp) {}
80
+ }
81
+ e[i].color = new jscolor.color(e[i], prop);
82
+ }
83
+ }
84
+ },
85
+
86
+
87
+ preload : function() {
88
+ for(var fn in jscolor.imgRequire) {
89
+ if(jscolor.imgRequire.hasOwnProperty(fn)) {
90
+ jscolor.loadImage(fn);
91
+ }
92
+ }
93
+ },
94
+
95
+
96
+ images : {
97
+ pad : [ 181, 101 ],
98
+ sld : [ 16, 101 ],
99
+ cross : [ 15, 15 ],
100
+ arrow : [ 7, 11 ]
101
+ },
102
+
103
+
104
+ imgRequire : {},
105
+ imgLoaded : {},
106
+
107
+
108
+ requireImage : function(filename) {
109
+ jscolor.imgRequire[filename] = true;
110
+ },
111
+
112
+
113
+ loadImage : function(filename) {
114
+ if(!jscolor.imgLoaded[filename]) {
115
+ jscolor.imgLoaded[filename] = new Image();
116
+ jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
117
+ }
118
+ },
119
+
120
+
121
+ fetchElement : function(mixed) {
122
+ return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
123
+ },
124
+
125
+
126
+ addEvent : function(el, evnt, func) {
127
+ if(el.addEventListener) {
128
+ el.addEventListener(evnt, func, false);
129
+ } else if(el.attachEvent) {
130
+ el.attachEvent('on'+evnt, func);
131
+ }
132
+ },
133
+
134
+
135
+ fireEvent : function(el, evnt) {
136
+ if(!el) {
137
+ return;
138
+ }
139
+ if(document.createEvent) {
140
+ var ev = document.createEvent('HTMLEvents');
141
+ ev.initEvent(evnt, true, true);
142
+ el.dispatchEvent(ev);
143
+ } else if(document.createEventObject) {
144
+ var ev = document.createEventObject();
145
+ el.fireEvent('on'+evnt, ev);
146
+ } else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
147
+ el['on'+evnt]();
148
+ }
149
+ },
150
+
151
+
152
+ getElementPos : function(e) {
153
+ var e1=e, e2=e;
154
+ var x=0, y=0;
155
+ if(e1.offsetParent) {
156
+ do {
157
+ x += e1.offsetLeft;
158
+ y += e1.offsetTop;
159
+ } while(e1 = e1.offsetParent);
160
+ }
161
+ while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
162
+ x -= e2.scrollLeft;
163
+ y -= e2.scrollTop;
164
+ }
165
+ return [x, y];
166
+ },
167
+
168
+
169
+ getElementSize : function(e) {
170
+ return [e.offsetWidth, e.offsetHeight];
171
+ },
172
+
173
+
174
+ getRelMousePos : function(e) {
175
+ var x = 0, y = 0;
176
+ if (!e) { e = window.event; }
177
+ if (typeof e.offsetX === 'number') {
178
+ x = e.offsetX;
179
+ y = e.offsetY;
180
+ } else if (typeof e.layerX === 'number') {
181
+ x = e.layerX;
182
+ y = e.layerY;
183
+ }
184
+ return { x: x, y: y };
185
+ },
186
+
187
+
188
+ getViewPos : function() {
189
+ if(typeof window.pageYOffset === 'number') {
190
+ return [window.pageXOffset, window.pageYOffset];
191
+ } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
192
+ return [document.body.scrollLeft, document.body.scrollTop];
193
+ } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
194
+ return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
195
+ } else {
196
+ return [0, 0];
197
+ }
198
+ },
199
+
200
+
201
+ getViewSize : function() {
202
+ if(typeof window.innerWidth === 'number') {
203
+ return [window.innerWidth, window.innerHeight];
204
+ } else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
205
+ return [document.body.clientWidth, document.body.clientHeight];
206
+ } else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
207
+ return [document.documentElement.clientWidth, document.documentElement.clientHeight];
208
+ } else {
209
+ return [0, 0];
210
+ }
211
+ },
212
+
213
+
214
+ URI : function(uri) { // See RFC3986
215
+
216
+ this.scheme = null;
217
+ this.authority = null;
218
+ this.path = '';
219
+ this.query = null;
220
+ this.fragment = null;
221
+
222
+ this.parse = function(uri) {
223
+ var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
224
+ this.scheme = m[3] ? m[2] : null;
225
+ this.authority = m[5] ? m[6] : null;
226
+ this.path = m[7];
227
+ this.query = m[9] ? m[10] : null;
228
+ this.fragment = m[12] ? m[13] : null;
229
+ return this;
230
+ };
231
+
232
+ this.toString = function() {
233
+ var result = '';
234
+ if(this.scheme !== null) { result = result + this.scheme + ':'; }
235
+ if(this.authority !== null) { result = result + '//' + this.authority; }
236
+ if(this.path !== null) { result = result + this.path; }
237
+ if(this.query !== null) { result = result + '?' + this.query; }
238
+ if(this.fragment !== null) { result = result + '#' + this.fragment; }
239
+ return result;
240
+ };
241
+
242
+ this.toAbsolute = function(base) {
243
+ var base = new jscolor.URI(base);
244
+ var r = this;
245
+ var t = new jscolor.URI;
246
+
247
+ if(base.scheme === null) { return false; }
248
+
249
+ if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
250
+ r.scheme = null;
251
+ }
252
+
253
+ if(r.scheme !== null) {
254
+ t.scheme = r.scheme;
255
+ t.authority = r.authority;
256
+ t.path = removeDotSegments(r.path);
257
+ t.query = r.query;
258
+ } else {
259
+ if(r.authority !== null) {
260
+ t.authority = r.authority;
261
+ t.path = removeDotSegments(r.path);
262
+ t.query = r.query;
263
+ } else {
264
+ if(r.path === '') {
265
+ t.path = base.path;
266
+ if(r.query !== null) {
267
+ t.query = r.query;
268
+ } else {
269
+ t.query = base.query;
270
+ }
271
+ } else {
272
+ if(r.path.substr(0,1) === '/') {
273
+ t.path = removeDotSegments(r.path);
274
+ } else {
275
+ if(base.authority !== null && base.path === '') {
276
+ t.path = '/'+r.path;
277
+ } else {
278
+ t.path = base.path.replace(/[^\/]+$/,'')+r.path;
279
+ }
280
+ t.path = removeDotSegments(t.path);
281
+ }
282
+ t.query = r.query;
283
+ }
284
+ t.authority = base.authority;
285
+ }
286
+ t.scheme = base.scheme;
287
+ }
288
+ t.fragment = r.fragment;
289
+
290
+ return t;
291
+ };
292
+
293
+ function removeDotSegments(path) {
294
+ var out = '';
295
+ while(path) {
296
+ if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
297
+ path = path.replace(/^\.+/,'').substr(1);
298
+ } else if(path.substr(0,3)==='/./' || path==='/.') {
299
+ path = '/'+path.substr(3);
300
+ } else if(path.substr(0,4)==='/../' || path==='/..') {
301
+ path = '/'+path.substr(4);
302
+ out = out.replace(/\/?[^\/]*$/, '');
303
+ } else if(path==='.' || path==='..') {
304
+ path = '';
305
+ } else {
306
+ var rm = path.match(/^\/?[^\/]*/)[0];
307
+ path = path.substr(rm.length);
308
+ out = out + rm;
309
+ }
310
+ }
311
+ return out;
312
+ }
313
+
314
+ if(uri) {
315
+ this.parse(uri);
316
+ }
317
+
318
+ },
319
+
320
+
321
+ //
322
+ // Usage example:
323
+ // var myColor = new jscolor.color(myInputElement)
324
+ //
325
+
326
+ color : function(target, prop) {
327
+
328
+
329
+ this.required = true; // refuse empty values?
330
+ this.adjust = true; // adjust value to uniform notation?
331
+ this.hash = false; // prefix color with # symbol?
332
+ this.caps = true; // uppercase?
333
+ this.slider = true; // show the value/saturation slider?
334
+ this.valueElement = target; // value holder
335
+ this.styleElement = target; // where to reflect current color
336
+ this.onImmediateChange = null; // onchange callback (can be either string or function)
337
+ this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1
338
+ this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1
339
+ this.minH = 0; // read-only 0-6
340
+ this.maxH = 6; // read-only 0-6
341
+ this.minS = 0; // read-only 0-1
342
+ this.maxS = 1; // read-only 0-1
343
+ this.minV = 0; // read-only 0-1
344
+ this.maxV = 1; // read-only 0-1
345
+
346
+ this.pickerOnfocus = true; // display picker on focus?
347
+ this.pickerMode = 'HSV'; // HSV | HVS
348
+ this.pickerPosition = 'bottom'; // left | right | top | bottom
349
+ this.pickerSmartPosition = true; // automatically adjust picker position when necessary
350
+ this.pickerButtonHeight = 20; // px
351
+ this.pickerClosable = false;
352
+ this.pickerCloseText = 'Close';
353
+ this.pickerButtonColor = 'ButtonText'; // px
354
+ this.pickerFace = 10; // px
355
+ this.pickerFaceColor = 'ThreeDFace'; // CSS color
356
+ this.pickerBorder = 1; // px
357
+ this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
358
+ this.pickerInset = 1; // px
359
+ this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
360
+ this.pickerZIndex = 10000;
361
+
362
+
363
+ for(var p in prop) {
364
+ if(prop.hasOwnProperty(p)) {
365
+ this[p] = prop[p];
366
+ }
367
+ }
368
+
369
+
370
+ this.hidePicker = function() {
371
+ if(isPickerOwner()) {
372
+ removePicker();
373
+ }
374
+ };
375
+
376
+
377
+ this.showPicker = function() {
378
+ if(!isPickerOwner()) {
379
+ var tp = jscolor.getElementPos(target); // target pos
380
+ var ts = jscolor.getElementSize(target); // target size
381
+ var vp = jscolor.getViewPos(); // view pos
382
+ var vs = jscolor.getViewSize(); // view size
383
+ var ps = getPickerDims(this); // picker size
384
+ var a, b, c;
385
+ switch(this.pickerPosition.toLowerCase()) {
386
+ case 'left': a=1; b=0; c=-1; break;
387
+ case 'right':a=1; b=0; c=1; break;
388
+ case 'top': a=0; b=1; c=-1; break;
389
+ default: a=0; b=1; c=1; break;
390
+ }
391
+ var l = (ts[b]+ps[b])/2;
392
+
393
+ // picker pos
394
+ if (!this.pickerSmartPosition) {
395
+ var pp = [
396
+ tp[a],
397
+ tp[b]+ts[b]-l+l*c
398
+ ];
399
+ } else {
400
+ var pp = [
401
+ -vp[a]+tp[a]+ps[a] > vs[a] ?
402
+ (-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]) :
403
+ tp[a],
404
+ -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
405
+ (-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) :
406
+ (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
407
+ ];
408
+ }
409
+ drawPicker(pp[a], pp[b]);
410
+ }
411
+ };
412
+
413
+
414
+ this.importColor = function() {
415
+ if(!valueElement) {
416
+ this.exportColor();
417
+ } else {
418
+ if(!this.adjust) {
419
+ if(!this.fromString(valueElement.value, leaveValue)) {
420
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
421
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
422
+ styleElement.style.color = styleElement.jscStyle.color;
423
+ this.exportColor(leaveValue | leaveStyle);
424
+ }
425
+ } else if(!this.required && /^\s*$/.test(valueElement.value)) {
426
+ valueElement.value = '';
427
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
428
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
429
+ styleElement.style.color = styleElement.jscStyle.color;
430
+ this.exportColor(leaveValue | leaveStyle);
431
+
432
+ } else if(this.fromString(valueElement.value)) {
433
+ // OK
434
+ } else {
435
+ this.exportColor();
436
+ }
437
+ }
438
+ };
439
+
440
+
441
+ this.exportColor = function(flags) {
442
+ if(!(flags & leaveValue) && valueElement) {
443
+ var value = this.toString();
444
+ if(this.caps) { value = value.toUpperCase(); }
445
+ if(this.hash) { value = '#'+value; }
446
+ valueElement.value = value;
447
+ }
448
+ if(!(flags & leaveStyle) && styleElement) {
449
+ styleElement.style.backgroundImage = "none";
450
+ styleElement.style.backgroundColor =
451
+ '#'+this.toString();
452
+ styleElement.style.color =
453
+ 0.213 * this.rgb[0] +
454
+ 0.715 * this.rgb[1] +
455
+ 0.072 * this.rgb[2]
456
+ < 0.5 ? '#FFF' : '#000';
457
+ }
458
+ if(!(flags & leavePad) && isPickerOwner()) {
459
+ redrawPad();
460
+ }
461
+ if(!(flags & leaveSld) && isPickerOwner()) {
462
+ redrawSld();
463
+ }
464
+ };
465
+
466
+
467
+ this.fromHSV = function(h, s, v, flags) { // null = don't change
468
+ if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); }
469
+ if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); }
470
+ if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); }
471
+
472
+ this.rgb = HSV_RGB(
473
+ h===null ? this.hsv[0] : (this.hsv[0]=h),
474
+ s===null ? this.hsv[1] : (this.hsv[1]=s),
475
+ v===null ? this.hsv[2] : (this.hsv[2]=v)
476
+ );
477
+
478
+ this.exportColor(flags);
479
+ };
480
+
481
+
482
+ this.fromRGB = function(r, g, b, flags) { // null = don't change
483
+ if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); }
484
+ if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); }
485
+ if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); }
486
+
487
+ var hsv = RGB_HSV(
488
+ r===null ? this.rgb[0] : r,
489
+ g===null ? this.rgb[1] : g,
490
+ b===null ? this.rgb[2] : b
491
+ );
492
+ if(hsv[0] !== null) {
493
+ this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0]));
494
+ }
495
+ if(hsv[2] !== 0) {
496
+ this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1]));
497
+ }
498
+ this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2]));
499
+
500
+ // update RGB according to final HSV, as some values might be trimmed
501
+ var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
502
+ this.rgb[0] = rgb[0];
503
+ this.rgb[1] = rgb[1];
504
+ this.rgb[2] = rgb[2];
505
+
506
+ this.exportColor(flags);
507
+ };
508
+
509
+
510
+ this.fromString = function(hex, flags) {
511
+ var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
512
+ if(!m) {
513
+ return false;
514
+ } else {
515
+ if(m[1].length === 6) { // 6-char notation
516
+ this.fromRGB(
517
+ parseInt(m[1].substr(0,2),16) / 255,
518
+ parseInt(m[1].substr(2,2),16) / 255,
519
+ parseInt(m[1].substr(4,2),16) / 255,
520
+ flags
521
+ );
522
+ } else { // 3-char notation
523
+ this.fromRGB(
524
+ parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
525
+ parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
526
+ parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
527
+ flags
528
+ );
529
+ }
530
+ return true;
531
+ }
532
+ };
533
+
534
+
535
+ this.toString = function() {
536
+ return (
537
+ (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
538
+ (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
539
+ (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
540
+ );
541
+ };
542
+
543
+
544
+ function RGB_HSV(r, g, b) {
545
+ var n = Math.min(Math.min(r,g),b);
546
+ var v = Math.max(Math.max(r,g),b);
547
+ var m = v - n;
548
+ if(m === 0) { return [ null, 0, v ]; }
549
+ var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
550
+ return [ h===6?0:h, m/v, v ];
551
+ }
552
+
553
+
554
+ function HSV_RGB(h, s, v) {
555
+ if(h === null) { return [ v, v, v ]; }
556
+ var i = Math.floor(h);
557
+ var f = i%2 ? h-i : 1-(h-i);
558
+ var m = v * (1 - s);
559
+ var n = v * (1 - s*f);
560
+ switch(i) {
561
+ case 6:
562
+ case 0: return [v,n,m];
563
+ case 1: return [n,v,m];
564
+ case 2: return [m,v,n];
565
+ case 3: return [m,n,v];
566
+ case 4: return [n,m,v];
567
+ case 5: return [v,m,n];
568
+ }
569
+ }
570
+
571
+
572
+ function removePicker() {
573
+ delete jscolor.picker.owner;
574
+ document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
575
+ }
576
+
577
+
578
+ function drawPicker(x, y) {
579
+ if(!jscolor.picker) {
580
+ jscolor.picker = {
581
+ box : document.createElement('div'),
582
+ boxB : document.createElement('div'),
583
+ pad : document.createElement('div'),
584
+ padB : document.createElement('div'),
585
+ padM : document.createElement('div'),
586
+ sld : document.createElement('div'),
587
+ sldB : document.createElement('div'),
588
+ sldM : document.createElement('div'),
589
+ btn : document.createElement('div'),
590
+ btnS : document.createElement('span'),
591
+ btnT : document.createTextNode(THIS.pickerCloseText)
592
+ };
593
+ for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
594
+ var seg = document.createElement('div');
595
+ seg.style.height = segSize+'px';
596
+ seg.style.fontSize = '1px';
597
+ seg.style.lineHeight = '0';
598
+ jscolor.picker.sld.appendChild(seg);
599
+ }
600
+ jscolor.picker.sldB.appendChild(jscolor.picker.sld);
601
+ jscolor.picker.box.appendChild(jscolor.picker.sldB);
602
+ jscolor.picker.box.appendChild(jscolor.picker.sldM);
603
+ jscolor.picker.padB.appendChild(jscolor.picker.pad);
604
+ jscolor.picker.box.appendChild(jscolor.picker.padB);
605
+ jscolor.picker.box.appendChild(jscolor.picker.padM);
606
+ jscolor.picker.btnS.appendChild(jscolor.picker.btnT);
607
+ jscolor.picker.btn.appendChild(jscolor.picker.btnS);
608
+ jscolor.picker.box.appendChild(jscolor.picker.btn);
609
+ jscolor.picker.boxB.appendChild(jscolor.picker.box);
610
+ }
611
+
612
+ var p = jscolor.picker;
613
+
614
+ // controls interaction
615
+ p.box.onmouseup =
616
+ p.box.onmouseout = function() { target.focus(); };
617
+ p.box.onmousedown = function() { abortBlur=true; };
618
+ p.box.onmousemove = function(e) {
619
+ if (holdPad || holdSld) {
620
+ holdPad && setPad(e);
621
+ holdSld && setSld(e);
622
+ if (document.selection) {
623
+ document.selection.empty();
624
+ } else if (window.getSelection) {
625
+ window.getSelection().removeAllRanges();
626
+ }
627
+ dispatchImmediateChange();
628
+ }
629
+ };
630
+ if('ontouchstart' in window) { // if touch device
631
+ var handle_touchmove = function(e) {
632
+ var event={
633
+ 'offsetX': e.touches[0].pageX-touchOffset.X,
634
+ 'offsetY': e.touches[0].pageY-touchOffset.Y
635
+ };
636
+ if (holdPad || holdSld) {
637
+ holdPad && setPad(event);
638
+ holdSld && setSld(event);
639
+ dispatchImmediateChange();
640
+ }
641
+ e.stopPropagation(); // prevent move "view" on broswer
642
+ e.preventDefault(); // prevent Default - Android Fix (else android generated only 1-2 touchmove events)
643
+ };
644
+ p.box.removeEventListener('touchmove', handle_touchmove, false)
645
+ p.box.addEventListener('touchmove', handle_touchmove, false)
646
+ }
647
+ p.padM.onmouseup =
648
+ p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } };
649
+ p.padM.onmousedown = function(e) {
650
+ // if the slider is at the bottom, move it up
651
+ switch(modeID) {
652
+ case 0: if (THIS.hsv[2] === 0) { THIS.fromHSV(null, null, 1.0); }; break;
653
+ case 1: if (THIS.hsv[1] === 0) { THIS.fromHSV(null, 1.0, null); }; break;
654
+ }
655
+ holdSld=false;
656
+ holdPad=true;
657
+ setPad(e);
658
+ dispatchImmediateChange();
659
+ };
660
+ if('ontouchstart' in window) {
661
+ p.padM.addEventListener('touchstart', function(e) {
662
+ touchOffset={
663
+ 'X': e.target.offsetParent.offsetLeft,
664
+ 'Y': e.target.offsetParent.offsetTop
665
+ };
666
+ this.onmousedown({
667
+ 'offsetX':e.touches[0].pageX-touchOffset.X,
668
+ 'offsetY':e.touches[0].pageY-touchOffset.Y
669
+ });
670
+ });
671
+ }
672
+ p.sldM.onmouseup =
673
+ p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } };
674
+ p.sldM.onmousedown = function(e) {
675
+ holdPad=false;
676
+ holdSld=true;
677
+ setSld(e);
678
+ dispatchImmediateChange();
679
+ };
680
+ if('ontouchstart' in window) {
681
+ p.sldM.addEventListener('touchstart', function(e) {
682
+ touchOffset={
683
+ 'X': e.target.offsetParent.offsetLeft,
684
+ 'Y': e.target.offsetParent.offsetTop
685
+ };
686
+ this.onmousedown({
687
+ 'offsetX':e.touches[0].pageX-touchOffset.X,
688
+ 'offsetY':e.touches[0].pageY-touchOffset.Y
689
+ });
690
+ });
691
+ }
692
+
693
+ // picker
694
+ var dims = getPickerDims(THIS);
695
+ p.box.style.width = dims[0] + 'px';
696
+ p.box.style.height = dims[1] + 'px';
697
+
698
+ // picker border
699
+ p.boxB.style.position = 'absolute';
700
+ p.boxB.style.clear = 'both';
701
+ p.boxB.style.left = x+'px';
702
+ p.boxB.style.top = y+'px';
703
+ p.boxB.style.zIndex = THIS.pickerZIndex;
704
+ p.boxB.style.border = THIS.pickerBorder+'px solid';
705
+ p.boxB.style.borderColor = THIS.pickerBorderColor;
706
+ p.boxB.style.background = THIS.pickerFaceColor;
707
+
708
+ // pad image
709
+ p.pad.style.width = jscolor.images.pad[0]+'px';
710
+ p.pad.style.height = jscolor.images.pad[1]+'px';
711
+
712
+ // pad border
713
+ p.padB.style.position = 'absolute';
714
+ p.padB.style.left = THIS.pickerFace+'px';
715
+ p.padB.style.top = THIS.pickerFace+'px';
716
+ p.padB.style.border = THIS.pickerInset+'px solid';
717
+ p.padB.style.borderColor = THIS.pickerInsetColor;
718
+
719
+ // pad mouse area
720
+ p.padM.style.position = 'absolute';
721
+ p.padM.style.left = '0';
722
+ p.padM.style.top = '0';
723
+ p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
724
+ p.padM.style.height = p.box.style.height;
725
+ p.padM.style.cursor = 'crosshair';
726
+
727
+ // slider image
728
+ p.sld.style.overflow = 'hidden';
729
+ p.sld.style.width = jscolor.images.sld[0]+'px';
730
+ p.sld.style.height = jscolor.images.sld[1]+'px';
731
+
732
+ // slider border
733
+ p.sldB.style.display = THIS.slider ? 'block' : 'none';
734
+ p.sldB.style.position = 'absolute';
735
+ p.sldB.style.right = THIS.pickerFace+'px';
736
+ p.sldB.style.top = THIS.pickerFace+'px';
737
+ p.sldB.style.border = THIS.pickerInset+'px solid';
738
+ p.sldB.style.borderColor = THIS.pickerInsetColor;
739
+
740
+ // slider mouse area
741
+ p.sldM.style.display = THIS.slider ? 'block' : 'none';
742
+ p.sldM.style.position = 'absolute';
743
+ p.sldM.style.right = '0';
744
+ p.sldM.style.top = '0';
745
+ p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
746
+ p.sldM.style.height = p.box.style.height;
747
+ try {
748
+ p.sldM.style.cursor = 'pointer';
749
+ } catch(eOldIE) {
750
+ p.sldM.style.cursor = 'hand';
751
+ }
752
+
753
+ // "close" button
754
+ function setBtnBorder() {
755
+ var insetColors = THIS.pickerInsetColor.split(/\s+/);
756
+ var pickerOutsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
757
+ p.btn.style.borderColor = pickerOutsetColor;
758
+ }
759
+ p.btn.style.display = THIS.pickerClosable ? 'block' : 'none';
760
+ p.btn.style.position = 'absolute';
761
+ p.btn.style.left = THIS.pickerFace + 'px';
762
+ p.btn.style.bottom = THIS.pickerFace + 'px';
763
+ p.btn.style.padding = '0 15px';
764
+ p.btn.style.height = '18px';
765
+ p.btn.style.border = THIS.pickerInset + 'px solid';
766
+ setBtnBorder();
767
+ p.btn.style.color = THIS.pickerButtonColor;
768
+ p.btn.style.font = '12px sans-serif';
769
+ p.btn.style.textAlign = 'center';
770
+ try {
771
+ p.btn.style.cursor = 'pointer';
772
+ } catch(eOldIE) {
773
+ p.btn.style.cursor = 'hand';
774
+ }
775
+ p.btn.onmousedown = function () {
776
+ THIS.hidePicker();
777
+ };
778
+ p.btnS.style.lineHeight = p.btn.style.height;
779
+
780
+ // load images in optimal order
781
+ switch(modeID) {
782
+ case 0: var padImg = 'hs.png'; break;
783
+ case 1: var padImg = 'hv.png'; break;
784
+ }
785
+ p.padM.style.backgroundImage = "url('"+jscolor.getDir()+"cross.gif')";
786
+ p.padM.style.backgroundRepeat = "no-repeat";
787
+ p.sldM.style.backgroundImage = "url('"+jscolor.getDir()+"arrow.gif')";
788
+ p.sldM.style.backgroundRepeat = "no-repeat";
789
+ p.pad.style.backgroundImage = "url('"+jscolor.getDir()+padImg+"')";
790
+ p.pad.style.backgroundRepeat = "no-repeat";
791
+ p.pad.style.backgroundPosition = "0 0";
792
+
793
+ // place pointers
794
+ redrawPad();
795
+ redrawSld();
796
+
797
+ jscolor.picker.owner = THIS;
798
+ document.getElementsByTagName('body')[0].appendChild(p.boxB);
799
+ }
800
+
801
+
802
+ function getPickerDims(o) {
803
+ var dims = [
804
+ 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[0] +
805
+ (o.slider ? 2*o.pickerInset + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] : 0),
806
+ o.pickerClosable ?
807
+ 4*o.pickerInset + 3*o.pickerFace + jscolor.images.pad[1] + o.pickerButtonHeight :
808
+ 2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[1]
809
+ ];
810
+ return dims;
811
+ }
812
+
813
+
814
+ function redrawPad() {
815
+ // redraw the pad pointer
816
+ switch(modeID) {
817
+ case 0: var yComponent = 1; break;
818
+ case 1: var yComponent = 2; break;
819
+ }
820
+ var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
821
+ var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
822
+ jscolor.picker.padM.style.backgroundPosition =
823
+ (THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
824
+ (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';
825
+
826
+ // redraw the slider image
827
+ var seg = jscolor.picker.sld.childNodes;
828
+
829
+ switch(modeID) {
830
+ case 0:
831
+ var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
832
+ for(var i=0; i<seg.length; i+=1) {
833
+ seg[i].style.backgroundColor = 'rgb('+
834
+ (rgb[0]*(1-i/seg.length)*100)+'%,'+
835
+ (rgb[1]*(1-i/seg.length)*100)+'%,'+
836
+ (rgb[2]*(1-i/seg.length)*100)+'%)';
837
+ }
838
+ break;
839
+ case 1:
840
+ var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
841
+ var i = Math.floor(THIS.hsv[0]);
842
+ var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
843
+ switch(i) {
844
+ case 6:
845
+ case 0: rgb=[0,1,2]; break;
846
+ case 1: rgb=[1,0,2]; break;
847
+ case 2: rgb=[2,0,1]; break;
848
+ case 3: rgb=[2,1,0]; break;
849
+ case 4: rgb=[1,2,0]; break;
850
+ case 5: rgb=[0,2,1]; break;
851
+ }
852
+ for(var i=0; i<seg.length; i+=1) {
853
+ s = 1 - 1/(seg.length-1)*i;
854
+ c[1] = c[0] * (1 - s*f);
855
+ c[2] = c[0] * (1 - s);
856
+ seg[i].style.backgroundColor = 'rgb('+
857
+ (c[rgb[0]]*100)+'%,'+
858
+ (c[rgb[1]]*100)+'%,'+
859
+ (c[rgb[2]]*100)+'%)';
860
+ }
861
+ break;
862
+ }
863
+ }
864
+
865
+
866
+ function redrawSld() {
867
+ // redraw the slider pointer
868
+ switch(modeID) {
869
+ case 0: var yComponent = 2; break;
870
+ case 1: var yComponent = 1; break;
871
+ }
872
+ var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
873
+ jscolor.picker.sldM.style.backgroundPosition =
874
+ '0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
875
+ }
876
+
877
+
878
+ function isPickerOwner() {
879
+ return jscolor.picker && jscolor.picker.owner === THIS;
880
+ }
881
+
882
+
883
+ function blurTarget() {
884
+ if(valueElement === target) {
885
+ THIS.importColor();
886
+ }
887
+ if(THIS.pickerOnfocus) {
888
+ THIS.hidePicker();
889
+ }
890
+ }
891
+
892
+
893
+ function blurValue() {
894
+ if(valueElement !== target) {
895
+ THIS.importColor();
896
+ }
897
+ }
898
+
899
+
900
+ function setPad(e) {
901
+ var mpos = jscolor.getRelMousePos(e);
902
+ var x = mpos.x - THIS.pickerFace - THIS.pickerInset;
903
+ var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
904
+ switch(modeID) {
905
+ case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
906
+ case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
907
+ }
908
+ }
909
+
910
+
911
+ function setSld(e) {
912
+ var mpos = jscolor.getRelMousePos(e);
913
+ var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
914
+ switch(modeID) {
915
+ case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
916
+ case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
917
+ }
918
+ }
919
+
920
+
921
+ function dispatchImmediateChange() {
922
+ if (THIS.onImmediateChange) {
923
+ var callback;
924
+ if (typeof THIS.onImmediateChange === 'string') {
925
+ callback = new Function (THIS.onImmediateChange);
926
+ } else {
927
+ callback = THIS.onImmediateChange;
928
+ }
929
+ callback.call(THIS);
930
+ }
931
+ }
932
+
933
+
934
+ var THIS = this;
935
+ var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
936
+ var abortBlur = false;
937
+ var
938
+ valueElement = jscolor.fetchElement(this.valueElement),
939
+ styleElement = jscolor.fetchElement(this.styleElement);
940
+ var
941
+ holdPad = false,
942
+ holdSld = false,
943
+ touchOffset = {};
944
+ var
945
+ leaveValue = 1<<0,
946
+ leaveStyle = 1<<1,
947
+ leavePad = 1<<2,
948
+ leaveSld = 1<<3;
949
+
950
+ // target
951
+ jscolor.addEvent(target, 'focus', function() {
952
+ if(THIS.pickerOnfocus) { THIS.showPicker(); }
953
+ });
954
+ jscolor.addEvent(target, 'blur', function() {
955
+ if(!abortBlur) {
956
+ window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
957
+ } else {
958
+ abortBlur = false;
959
+ }
960
+ });
961
+
962
+ // valueElement
963
+ if(valueElement) {
964
+ var updateField = function() {
965
+ THIS.fromString(valueElement.value, leaveValue);
966
+ dispatchImmediateChange();
967
+ };
968
+ jscolor.addEvent(valueElement, 'keyup', updateField);
969
+ jscolor.addEvent(valueElement, 'input', updateField);
970
+ jscolor.addEvent(valueElement, 'blur', blurValue);
971
+ valueElement.setAttribute('autocomplete', 'off');
972
+ }
973
+
974
+ // styleElement
975
+ if(styleElement) {
976
+ styleElement.jscStyle = {
977
+ backgroundImage : styleElement.style.backgroundImage,
978
+ backgroundColor : styleElement.style.backgroundColor,
979
+ color : styleElement.style.color
980
+ };
981
+ }
982
+
983
+ // require images
984
+ switch(modeID) {
985
+ case 0: jscolor.requireImage('hs.png'); break;
986
+ case 1: jscolor.requireImage('hv.png'); break;
987
+ }
988
+ jscolor.requireImage('cross.gif');
989
+ jscolor.requireImage('arrow.gif');
990
+
991
+ this.importColor();
992
+ }
993
+
994
+ };
995
+
996
+
997
+ jscolor.install();
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>NightlyDev_FaviconBadge</name>
4
+ <version>1.0.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://license.nightlydev.org">GNU General Public License (GPLv3)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Highly customizable favicon badges for customers (frontend) and administrators or developers (backend).</summary>
10
+ <description>Highly customizable favicon badges for customers (frontend) and administrators or developers (backend).</description>
11
+ <notes>Highly customizable favicon badges for customers (frontend) and administrators or developers (backend).</notes>
12
+ <authors><author><name>Carles Tubio</name><user>nightlydev</user><email>input@nightlydev.org</email></author></authors>
13
+ <date>2014-06-14</date>
14
+ <time>19:47:20</time>
15
+ <contents><target name="magecommunity"><dir name="NightlyDev"><file name="LICENSE" hash="d32239bcb673463ab874e80d47fae504"/><dir name="FaviconBadge"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Source"><file name="Date.php" hash="32eab3307f79990713d4efe80be3936b"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="e2df67eb56cb8e9d7b257a059e6b24de"/></dir><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Source"><file name="Alerts.php" hash="e1d3824fc0aa2f9af0f4087d5098defb"/><file name="Anims.php" hash="bd09ecb13553bb5722c36b83e86b452d"/><file name="Downs.php" hash="b0cf19646df162f23eeb2f3d61ed10ab"/><file name="Pos.php" hash="db8b17daf9c65efd937469600cf7bd87"/><file name="Shapes.php" hash="9e4ddb29ad14d79208fada9a29263ce5"/><file name="Types.php" hash="30db3202a857953419dc4f2f9dfb2cd8"/></dir></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="d215db3f2ec57769894e67ed036ca131"/><file name="system.xml" hash="6d31238fd8f75d24a9cafe2da072aab3"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="NightlyDev_FaviconBadge.xml" hash="ebbfca18b7ea3dc9aa6c0d1146b07010"/></dir></target><target name="mageweb"><dir name="js"><dir name="nightlydev"><dir name="faviconbadge"><file name="favico-0.3.4.min.js" hash="81a113b850d797c7d2ccb2e0f8bf6af0"/><file name="favico.js" hash="2d93d5730523e4da4455899ebce14eea"/></dir><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="3afd625d05b34532e4122663b5cf21a9"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="nightlydevfaviconbadge.xml" hash="e6d475f2d1c84fd764caac259037003b"/></dir><dir name="template"><dir name="nightlydevfaviconbadge"><file name="faviconbadge.phtml" hash="ea4c32319b3274251e4327fdc96e0b5a"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="nightlydevfaviconbadge.xml" hash="531398761321f4464e8aac42ce69a49b"/></dir><dir name="template"><dir name="nightlydevfaviconbadge"><file name="faviconbadge.phtml" hash="4f7e9287d1440cad730439c4779e53d0"/></dir></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.0.0</min><max>5.5.5</max></php></required></dependencies>
18
+ </package>