Minimal Coming Soon & Maintenance Mode - Version 1.45

Version Description

  • 2017-12-13
  • 40k users - early December
  • minor fixes
  • removed mailing list notification
  • added plugin review request notification
Download this release

Release Info

Developer WebFactory
Plugin Icon 128x128 Minimal Coming Soon & Maintenance Mode
Version 1.45
Comparing to
See all releases

Code changes from version 1.40 to 1.45

framework/admin/css/admin.css CHANGED
@@ -35,7 +35,7 @@
35
  }
36
  .signals-header p {
37
  float: left;
38
- font-size: 14px;
39
  margin: 0;
40
  margin-top: 3px;
41
  }
@@ -50,10 +50,11 @@
50
  margin-right: 10px;
51
  }
52
  .signals-body {
53
- padding: 30px 0 30px 20px;
54
  }
55
  .signals-body p {
56
  line-height: 24px;
 
57
  }
58
  .signals-single-section {
59
  padding: 30px;
@@ -187,14 +188,18 @@
187
  border: 1px solid #f1f1f1;
188
  padding: 10px 20px;
189
  margin-bottom: 30px;
 
190
  }
191
  #arrange-items li {
192
  background: #f3f3f3;
193
- padding: 5px 15px;
194
  font-weight: bold;
195
  cursor: move;
196
  cursor: -webkit-grabbing;
197
  }
 
 
 
198
  .sortable-ghost {
199
  border: 1px dashed #333;
200
  }
@@ -618,6 +623,17 @@ textarea.signals-form-input-lg {
618
  }
619
  }
620
 
 
 
 
 
 
 
 
 
 
 
 
621
  #collect_emails {
622
  display: block;
623
  width: 600px;
@@ -662,3 +678,36 @@ textarea.signals-form-input-lg {
662
  font-weight: 600;
663
  }
664
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  .signals-header p {
37
  float: left;
38
+ font-size: 17px;
39
  margin: 0;
40
  margin-top: 3px;
41
  }
50
  margin-right: 10px;
51
  }
52
  .signals-body {
53
+ padding: 30px 20px 30px 20px;
54
  }
55
  .signals-body p {
56
  line-height: 24px;
57
+ font-size: 14px;
58
  }
59
  .signals-single-section {
60
  padding: 30px;
188
  border: 1px solid #f1f1f1;
189
  padding: 10px 20px;
190
  margin-bottom: 30px;
191
+ max-width: 300px;
192
  }
193
  #arrange-items li {
194
  background: #f3f3f3;
195
+ padding: 10px 15px;
196
  font-weight: bold;
197
  cursor: move;
198
  cursor: -webkit-grabbing;
199
  }
200
+ #arrange-items li .dashicons {
201
+ padding-right: 10px;
202
+ }
203
  .sortable-ghost {
204
  border: 1px dashed #333;
205
  }
623
  }
624
  }
625
 
626
+ #rating-notice {
627
+ display: block;
628
+ max-width: 1360px;
629
+ box-sizing: border-box;
630
+ padding: 15px;
631
+ margin: 0px 0 20px 0;
632
+ color: #fff;
633
+ background-color: rgba(243, 89, 88, 0.81);
634
+ position: relative;
635
+ }
636
+
637
  #collect_emails {
638
  display: block;
639
  width: 600px;
678
  font-weight: 600;
679
  }
680
 
681
+ input.color, input.jscolor {
682
+ width: 100px;
683
+ }
684
+
685
+ .signals-admin-form .button-flat {
686
+ box-shadow: none;
687
+ vertical-align: baseline;
688
+ background-color: transparent;
689
+ border: thin solid #fff;
690
+ color: #fff;
691
+ font-weight: bold;
692
+ }
693
+
694
+ .signals-admin-form .button-flat:hover {
695
+ background-color: #fff;
696
+ border: thin solid #fff;
697
+ color: rgba(243, 89, 88, 0.81);
698
+ }
699
+
700
+ #mm_rate_cancel {
701
+ color: #fff;
702
+ padding-left: 25px;
703
+ font-size: small;
704
+ text-decoration: none;
705
+ }
706
+
707
+ #mm_rate_cancel:hover {
708
+ text-decoration: underline;
709
+ }
710
+
711
+ #rating-notice b {
712
+ font-weight: bold;
713
+ }
framework/admin/init.php CHANGED
@@ -67,19 +67,28 @@ function csmm_admin_scripts() {
67
 
68
  // For the upload option using media uploader
69
  wp_enqueue_media();
70
-
71
  }
72
 
73
 
74
-
75
  // Scripts & styles for the plugin
76
  function csmm_load_scripts() {
77
-
78
  add_action( 'admin_enqueue_scripts', 'csmm_admin_scripts' );
79
-
80
  }
81
 
82
-
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
  // Including file for the management panel
85
- require SIGNALS_CSMM_PATH . 'framework/admin/settings.php';
67
 
68
  // For the upload option using media uploader
69
  wp_enqueue_media();
 
70
  }
71
 
72
 
 
73
  // Scripts & styles for the plugin
74
  function csmm_load_scripts() {
 
75
  add_action( 'admin_enqueue_scripts', 'csmm_admin_scripts' );
 
76
  }
77
 
78
+ function csmm_plugin_admin_init() {
79
+ if (!is_admin()) {
80
+ return;
81
+ }
82
+
83
+ $meta = get_option('signals_csmm_meta', array());
84
+ if (!isset($meta['first_version']) || !isset($meta['first_install'])) {
85
+ $meta['first_version'] = csmm_get_plugin_version();
86
+ $meta['first_install_gmt'] = time();
87
+ $meta['first_install'] = current_time('timestamp');
88
+ update_option('signals_csmm_meta', $meta);
89
+ }
90
+ } // csmm_plugin_admin_init
91
+ add_action( 'init', 'csmm_plugin_admin_init' );
92
 
93
  // Including file for the management panel
94
+ require SIGNALS_CSMM_PATH . 'framework/admin/settings.php';
framework/admin/js/admin.js CHANGED
@@ -95,9 +95,6 @@ function getUploader( $text, $target ) {
95
  }
96
 
97
  (function( $ ) {
98
-
99
- 'use strict';
100
-
101
  // css and html editor
102
  function getEditor( $editorID, $textareaID, $mode ) {
103
 
@@ -169,6 +166,15 @@ function getUploader( $text, $target ) {
169
  $('#collect_emails').hide();
170
  $.get(ajaxurl, {'action': 'csmm_subscribe_hide'}, function(){});
171
 
 
 
 
 
 
 
 
 
 
172
  return false;
173
  } );
174
 
@@ -288,4 +294,4 @@ function getUploader( $text, $target ) {
288
 
289
  } );
290
 
291
- } )( jQuery );
95
  }
96
 
97
  (function( $ ) {
 
 
 
98
  // css and html editor
99
  function getEditor( $editorID, $textareaID, $mode ) {
100
 
166
  $('#collect_emails').hide();
167
  $.get(ajaxurl, {'action': 'csmm_subscribe_hide'}, function(){});
168
 
169
+ return false;
170
+ } );
171
+
172
+ $( document ).on( 'click', '#mm_rate_cancel', function(e) {
173
+ e.preventDefault();
174
+
175
+ $('#rating-notice').fadeOut();
176
+ $.get(ajaxurl, {'action': 'csmm_rate_hide'});
177
+
178
  return false;
179
  } );
180
 
294
 
295
  } );
296
 
297
+ } )( jQuery );
framework/admin/js/colorpicker/jscolor.js CHANGED
@@ -1,473 +1,1141 @@
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 = 99999999;
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),
@@ -479,23 +1147,36 @@ var jscolor = {
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]);
@@ -507,264 +1188,417 @@ var jscolor = {
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 {
@@ -773,225 +1607,238 @@ var jscolor = {
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();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /**
2
+ * jscolor - JavaScript Color Picker
3
  *
 
 
 
 
 
4
  * @link http://jscolor.com
5
+ * @license For open source use: GPLv3
6
+ * For commercial use: JSColor Commercial License
7
+ * @author Jan Odvarko
8
+ * @version 2.0.4
9
+ *
10
+ * See usage examples at http://jscolor.com/examples/
11
  */
12
 
13
 
14
+ "use strict";
15
+
16
 
17
+ if (!window.jscolor) { window.jscolor = (function () {
18
 
 
 
 
 
19
 
20
+ var jsc = {
21
 
22
+
23
+ register : function () {
24
+ jsc.attachDOMReadyEvent(jsc.init);
25
+ jsc.attachEvent(document, 'mousedown', jsc.onDocumentMouseDown);
26
+ jsc.attachEvent(document, 'touchstart', jsc.onDocumentTouchStart);
27
+ jsc.attachEvent(window, 'resize', jsc.onWindowResize);
28
  },
29
 
30
 
31
+ init : function () {
32
+ if (jsc.jscolor.lookupClass) {
33
+ jsc.jscolor.installByClassName(jsc.jscolor.lookupClass);
34
  }
35
+ },
36
+
37
+
38
+ tryInstallOnElements : function (elms, className) {
39
+ var matchClass = new RegExp('(^|\\s)(' + className + ')(\\s*(\\{[^}]*\\})|\\s|$)', 'i');
40
+
41
+ for (var i = 0; i < elms.length; i += 1) {
42
+ if (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color') {
43
+ if (jsc.isColorAttrSupported) {
44
+ // skip inputs of type 'color' if supported by the browser
45
+ continue;
46
+ }
47
+ }
48
+ var m;
49
+ if (!elms[i].jscolor && elms[i].className && (m = elms[i].className.match(matchClass))) {
50
+ var targetElm = elms[i];
51
+ var optsStr = null;
52
+
53
+ var dataOptions = jsc.getDataAttr(targetElm, 'jscolor');
54
+ if (dataOptions !== null) {
55
+ optsStr = dataOptions;
56
+ } else if (m[4]) {
57
+ optsStr = m[4];
58
+ }
59
+
60
+ var opts = {};
61
+ if (optsStr) {
62
+ try {
63
+ opts = (new Function ('return (' + optsStr + ')'))();
64
+ } catch(eParseError) {
65
+ jsc.warn('Error parsing jscolor options: ' + eParseError + ':\n' + optsStr);
66
+ }
67
+ }
68
+ targetElm.jscolor = new jsc.jscolor(targetElm, opts);
69
+ }
70
  }
71
  },
72
 
73
 
74
+ isColorAttrSupported : (function () {
75
+ var elm = document.createElement('input');
76
+ if (elm.setAttribute) {
77
+ elm.setAttribute('type', 'color');
78
+ if (elm.type.toLowerCase() == 'color') {
79
+ return true;
80
+ }
81
  }
82
+ return false;
83
+ })(),
84
+
85
+
86
+ isCanvasSupported : (function () {
87
+ var elm = document.createElement('canvas');
88
+ return !!(elm.getContext && elm.getContext('2d'));
89
+ })(),
90
+
91
+
92
+ fetchElement : function (mixed) {
93
+ return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
94
  },
95
 
96
 
97
+ isElementType : function (elm, type) {
98
+ return elm.nodeName.toLowerCase() === type.toLowerCase();
99
+ },
100
+
101
 
102
+ getDataAttr : function (el, name) {
103
+ var attrName = 'data-' + name;
104
+ var attrValue = el.getAttribute(attrName);
105
+ if (attrValue !== null) {
106
+ return attrValue;
107
  }
108
+ return null;
109
+ },
110
 
111
+
112
+ attachEvent : function (el, evnt, func) {
113
+ if (el.addEventListener) {
114
+ el.addEventListener(evnt, func, false);
115
+ } else if (el.attachEvent) {
116
+ el.attachEvent('on' + evnt, func);
 
 
 
 
117
  }
 
118
  },
119
 
120
 
121
+ detachEvent : function (el, evnt, func) {
122
+ if (el.removeEventListener) {
123
+ el.removeEventListener(evnt, func, false);
124
+ } else if (el.detachEvent) {
125
+ el.detachEvent('on' + evnt, func);
 
 
 
 
 
 
 
 
 
126
  }
127
  },
128
 
129
 
130
+ _attachedGroupEvents : {},
131
+
132
+
133
+ attachGroupEvent : function (groupName, el, evnt, func) {
134
+ if (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
135
+ jsc._attachedGroupEvents[groupName] = [];
136
  }
137
+ jsc._attachedGroupEvents[groupName].push([el, evnt, func]);
138
+ jsc.attachEvent(el, evnt, func);
139
  },
140
 
141
 
142
+ detachGroupEvents : function (groupName) {
143
+ if (jsc._attachedGroupEvents.hasOwnProperty(groupName)) {
144
+ for (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) {
145
+ var evt = jsc._attachedGroupEvents[groupName][i];
146
+ jsc.detachEvent(evt[0], evt[1], evt[2]);
147
+ }
148
+ delete jsc._attachedGroupEvents[groupName];
149
+ }
150
  },
151
 
152
 
153
+ attachDOMReadyEvent : function (func) {
154
+ var fired = false;
155
+ var fireOnce = function () {
156
+ if (!fired) {
157
+ fired = true;
158
+ func();
159
+ }
160
+ };
161
+
162
+ if (document.readyState === 'complete') {
163
+ setTimeout(fireOnce, 1); // async
164
+ return;
165
+ }
166
+
167
+ if (document.addEventListener) {
168
+ document.addEventListener('DOMContentLoaded', fireOnce, false);
169
+
170
+ // Fallback
171
+ window.addEventListener('load', fireOnce, false);
172
+
173
+ } else if (document.attachEvent) {
174
+ // IE
175
+ document.attachEvent('onreadystatechange', function () {
176
+ if (document.readyState === 'complete') {
177
+ document.detachEvent('onreadystatechange', arguments.callee);
178
+ fireOnce();
179
+ }
180
+ })
181
 
182
+ // Fallback
183
+ window.attachEvent('onload', fireOnce);
184
 
185
+ // IE7/8
186
+ if (document.documentElement.doScroll && window == window.top) {
187
+ var tryScroll = function () {
188
+ if (!document.body) { return; }
189
+ try {
190
+ document.documentElement.doScroll('left');
191
+ fireOnce();
192
+ } catch (e) {
193
+ setTimeout(tryScroll, 1);
194
+ }
195
+ };
196
+ tryScroll();
197
+ }
198
+ }
199
  },
200
 
201
 
202
+ warn : function (msg) {
203
+ if (window.console && window.console.warn) {
204
+ window.console.warn(msg);
 
205
  }
206
  },
207
 
208
 
209
+ preventDefault : function (e) {
210
+ if (e.preventDefault) { e.preventDefault(); }
211
+ e.returnValue = false;
212
  },
213
 
214
 
215
+ captureTarget : function (target) {
216
+ // IE
217
+ if (target.setCapture) {
218
+ jsc._capturedTarget = target;
219
+ jsc._capturedTarget.setCapture();
220
  }
221
  },
222
 
223
 
224
+ releaseTarget : function () {
225
+ // IE
226
+ if (jsc._capturedTarget) {
227
+ jsc._capturedTarget.releaseCapture();
228
+ jsc._capturedTarget = null;
229
+ }
230
+ },
231
+
232
+
233
+ fireEvent : function (el, evnt) {
234
+ if (!el) {
235
  return;
236
  }
237
+ if (document.createEvent) {
238
  var ev = document.createEvent('HTMLEvents');
239
  ev.initEvent(evnt, true, true);
240
  el.dispatchEvent(ev);
241
+ } else if (document.createEventObject) {
242
  var ev = document.createEventObject();
243
+ el.fireEvent('on' + evnt, ev);
244
+ } else if (el['on' + evnt]) { // alternatively use the traditional event model
245
+ el['on' + evnt]();
246
  }
247
  },
248
 
249
 
250
+ classNameToList : function (className) {
251
+ return className.replace(/^\s+|\s+$/g, '').split(/\s+/);
252
+ },
253
+
254
+
255
+ // The className parameter (str) can only contain a single class name
256
+ hasClass : function (elm, className) {
257
+ if (!className) {
258
+ return false;
259
  }
260
+ return -1 != (' ' + elm.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' ');
261
+ },
262
+
263
+
264
+ // The className parameter (str) can contain multiple class names separated by whitespace
265
+ setClass : function (elm, className) {
266
+ var classList = jsc.classNameToList(className);
267
+ for (var i = 0; i < classList.length; i += 1) {
268
+ if (!jsc.hasClass(elm, classList[i])) {
269
+ elm.className += (elm.className ? ' ' : '') + classList[i];
270
+ }
271
+ }
272
+ },
273
+
274
+
275
+ // The className parameter (str) can contain multiple class names separated by whitespace
276
+ unsetClass : function (elm, className) {
277
+ var classList = jsc.classNameToList(className);
278
+ for (var i = 0; i < classList.length; i += 1) {
279
+ var repl = new RegExp(
280
+ '^\\s*' + classList[i] + '\\s*|' +
281
+ '\\s*' + classList[i] + '\\s*$|' +
282
+ '\\s+' + classList[i] + '(\\s+)',
283
+ 'g'
284
+ );
285
+ elm.className = elm.className.replace(repl, '$1');
286
+ }
287
+ },
288
+
289
+
290
+ getStyle : function (elm) {
291
+ return window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle;
292
+ },
293
+
294
+
295
+ setStyle : (function () {
296
+ var helper = document.createElement('div');
297
+ var getSupportedProp = function (names) {
298
+ for (var i = 0; i < names.length; i += 1) {
299
+ if (names[i] in helper.style) {
300
+ return names[i];
301
+ }
302
+ }
303
+ };
304
+ var props = {
305
+ borderRadius: getSupportedProp(['borderRadius', 'MozBorderRadius', 'webkitBorderRadius']),
306
+ boxShadow: getSupportedProp(['boxShadow', 'MozBoxShadow', 'webkitBoxShadow'])
307
+ };
308
+ return function (elm, prop, value) {
309
+ switch (prop.toLowerCase()) {
310
+ case 'opacity':
311
+ var alphaOpacity = Math.round(parseFloat(value) * 100);
312
+ elm.style.opacity = value;
313
+ elm.style.filter = 'alpha(opacity=' + alphaOpacity + ')';
314
+ break;
315
+ default:
316
+ elm.style[props[prop]] = value;
317
+ break;
318
+ }
319
+ };
320
+ })(),
321
+
322
+
323
+ setBorderRadius : function (elm, value) {
324
+ jsc.setStyle(elm, 'borderRadius', value || '0');
325
+ },
326
+
327
+
328
+ setBoxShadow : function (elm, value) {
329
+ jsc.setStyle(elm, 'boxShadow', value || 'none');
330
+ },
331
+
332
+
333
+ getElementPos : function (e, relativeToViewport) {
334
+ var x=0, y=0;
335
+ var rect = e.getBoundingClientRect();
336
+ x = rect.left;
337
+ y = rect.top;
338
+ if (!relativeToViewport) {
339
+ var viewPos = jsc.getViewPos();
340
+ x += viewPos[0];
341
+ y += viewPos[1];
342
  }
343
  return [x, y];
344
  },
345
 
346
 
347
+ getElementSize : function (e) {
348
  return [e.offsetWidth, e.offsetHeight];
349
  },
350
 
351
 
352
+ // get pointer's X/Y coordinates relative to viewport
353
+ getAbsPointerPos : function (e) {
354
+ if (!e) { e = window.event; }
355
  var x = 0, y = 0;
356
+ if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
357
+ // touch devices
358
+ x = e.changedTouches[0].clientX;
359
+ y = e.changedTouches[0].clientY;
360
+ } else if (typeof e.clientX === 'number') {
361
+ x = e.clientX;
362
+ y = e.clientY;
363
+ }
364
+ return { x: x, y: y };
365
+ },
366
+
367
+
368
+ // get pointer's X/Y coordinates relative to target element
369
+ getRelPointerPos : function (e) {
370
  if (!e) { e = window.event; }
371
+ var target = e.target || e.srcElement;
372
+ var targetRect = target.getBoundingClientRect();
373
+
374
+ var x = 0, y = 0;
375
+
376
+ var clientX = 0, clientY = 0;
377
+ if (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {
378
+ // touch devices
379
+ clientX = e.changedTouches[0].clientX;
380
+ clientY = e.changedTouches[0].clientY;
381
+ } else if (typeof e.clientX === 'number') {
382
+ clientX = e.clientX;
383
+ clientY = e.clientY;
384
  }
385
+
386
+ x = clientX - targetRect.left;
387
+ y = clientY - targetRect.top;
388
  return { x: x, y: y };
389
  },
390
 
391
 
392
+ getViewPos : function () {
393
+ var doc = document.documentElement;
394
+ return [
395
+ (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
396
+ (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
397
+ ];
398
+ },
399
+
400
+
401
+ getViewSize : function () {
402
+ var doc = document.documentElement;
403
+ return [
404
+ (window.innerWidth || doc.clientWidth),
405
+ (window.innerHeight || doc.clientHeight),
406
+ ];
407
+ },
408
+
409
+
410
+ redrawPosition : function () {
411
+
412
+ if (jsc.picker && jsc.picker.owner) {
413
+ var thisObj = jsc.picker.owner;
414
+
415
+ var tp, vp;
416
+
417
+ if (thisObj.fixed) {
418
+ // Fixed elements are positioned relative to viewport,
419
+ // therefore we can ignore the scroll offset
420
+ tp = jsc.getElementPos(thisObj.targetElement, true); // target pos
421
+ vp = [0, 0]; // view pos
422
+ } else {
423
+ tp = jsc.getElementPos(thisObj.targetElement); // target pos
424
+ vp = jsc.getViewPos(); // view pos
425
+ }
426
+
427
+ var ts = jsc.getElementSize(thisObj.targetElement); // target size
428
+ var vs = jsc.getViewSize(); // view size
429
+ var ps = jsc.getPickerOuterDims(thisObj); // picker size
430
+ var a, b, c;
431
+ switch (thisObj.position.toLowerCase()) {
432
+ case 'left': a=1; b=0; c=-1; break;
433
+ case 'right':a=1; b=0; c=1; break;
434
+ case 'top': a=0; b=1; c=-1; break;
435
+ default: a=0; b=1; c=1; break;
436
+ }
437
+ var l = (ts[b]+ps[b])/2;
438
+
439
+ // compute picker position
440
+ if (!thisObj.smartPosition) {
441
+ var pp = [
442
+ tp[a],
443
+ tp[b]+ts[b]-l+l*c
444
+ ];
445
+ } else {
446
+ var pp = [
447
+ -vp[a]+tp[a]+ps[a] > vs[a] ?
448
+ (-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]) :
449
+ tp[a],
450
+ -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
451
+ (-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) :
452
+ (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
453
+ ];
454
+ }
455
+
456
+ var x = pp[a];
457
+ var y = pp[b];
458
+ var positionValue = thisObj.fixed ? 'fixed' : 'absolute';
459
+ var contractShadow =
460
+ (pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) &&
461
+ (pp[1] + ps[1] < tp[1] + ts[1]);
462
+
463
+ jsc._drawPosition(thisObj, x, y, positionValue, contractShadow);
464
+ }
465
+ },
466
+
467
+
468
+ _drawPosition : function (thisObj, x, y, positionValue, contractShadow) {
469
+ var vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px
470
+
471
+ jsc.picker.wrap.style.position = positionValue;
472
+ jsc.picker.wrap.style.left = x + 'px';
473
+ jsc.picker.wrap.style.top = y + 'px';
474
+
475
+ jsc.setBoxShadow(
476
+ jsc.picker.boxS,
477
+ thisObj.shadow ?
478
+ new jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) :
479
+ null);
480
+ },
481
+
482
+
483
+ getPickerDims : function (thisObj) {
484
+ var displaySlider = !!jsc.getSliderComponent(thisObj);
485
+ var dims = [
486
+ 2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.width +
487
+ (displaySlider ? 2 * thisObj.insetWidth + jsc.getPadToSliderPadding(thisObj) + thisObj.sliderSize : 0),
488
+ 2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.height +
489
+ (thisObj.closable ? 2 * thisObj.insetWidth + thisObj.padding + thisObj.buttonHeight : 0)
490
+ ];
491
+ return dims;
492
+ },
493
+
494
+
495
+ getPickerOuterDims : function (thisObj) {
496
+ var dims = jsc.getPickerDims(thisObj);
497
+ return [
498
+ dims[0] + 2 * thisObj.borderWidth,
499
+ dims[1] + 2 * thisObj.borderWidth
500
+ ];
501
+ },
502
+
503
+
504
+ getPadToSliderPadding : function (thisObj) {
505
+ return Math.max(thisObj.padding, 1.5 * (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness));
506
+ },
507
+
508
+
509
+ getPadYComponent : function (thisObj) {
510
+ switch (thisObj.mode.charAt(1).toLowerCase()) {
511
+ case 'v': return 'v'; break;
512
+ }
513
+ return 's';
514
+ },
515
+
516
+
517
+ getSliderComponent : function (thisObj) {
518
+ if (thisObj.mode.length > 2) {
519
+ switch (thisObj.mode.charAt(2).toLowerCase()) {
520
+ case 's': return 's'; break;
521
+ case 'v': return 'v'; break;
522
+ }
523
+ }
524
+ return null;
525
+ },
526
+
527
+
528
+ onDocumentMouseDown : function (e) {
529
+ if (!e) { e = window.event; }
530
+ var target = e.target || e.srcElement;
531
+
532
+ if (target._jscLinkedInstance) {
533
+ if (target._jscLinkedInstance.showOnClick) {
534
+ target._jscLinkedInstance.show();
535
+ }
536
+ } else if (target._jscControlName) {
537
+ jsc.onControlPointerStart(e, target, target._jscControlName, 'mouse');
538
  } else {
539
+ // Mouse is outside the picker controls -> hide the color picker!
540
+ if (jsc.picker && jsc.picker.owner) {
541
+ jsc.picker.owner.hide();
542
+ }
543
  }
544
  },
545
 
546
 
547
+ onDocumentTouchStart : function (e) {
548
+ if (!e) { e = window.event; }
549
+ var target = e.target || e.srcElement;
550
+
551
+ if (target._jscLinkedInstance) {
552
+ if (target._jscLinkedInstance.showOnClick) {
553
+ target._jscLinkedInstance.show();
554
+ }
555
+ } else if (target._jscControlName) {
556
+ jsc.onControlPointerStart(e, target, target._jscControlName, 'touch');
557
  } else {
558
+ if (jsc.picker && jsc.picker.owner) {
559
+ jsc.picker.owner.hide();
560
+ }
561
  }
562
  },
563
 
564
 
565
+ onWindowResize : function (e) {
566
+ jsc.redrawPosition();
567
+ },
568
 
 
 
 
 
 
569
 
570
+ onParentScroll : function (e) {
571
+ // hide the picker when one of the parent elements is scrolled
572
+ if (jsc.picker && jsc.picker.owner) {
573
+ jsc.picker.owner.hide();
574
+ }
575
+ },
576
+
577
+
578
+ _pointerMoveEvent : {
579
+ mouse: 'mousemove',
580
+ touch: 'touchmove'
581
+ },
582
+ _pointerEndEvent : {
583
+ mouse: 'mouseup',
584
+ touch: 'touchend'
585
+ },
586
+
587
+
588
+ _pointerOrigin : null,
589
+ _capturedTarget : null,
590
+
591
+
592
+ onControlPointerStart : function (e, target, controlName, pointerType) {
593
+ var thisObj = target._jscInstance;
594
+
595
+ jsc.preventDefault(e);
596
+ jsc.captureTarget(target);
597
+
598
+ var registerDragEvents = function (doc, offset) {
599
+ jsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType],
600
+ jsc.onDocumentPointerMove(e, target, controlName, pointerType, offset));
601
+ jsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType],
602
+ jsc.onDocumentPointerEnd(e, target, controlName, pointerType));
603
  };
604
 
605
+ registerDragEvents(document, [0, 0]);
606
+
607
+ if (window.parent && window.frameElement) {
608
+ var rect = window.frameElement.getBoundingClientRect();
609
+ var ofs = [-rect.left, -rect.top];
610
+ registerDragEvents(window.parent.window.document, ofs);
611
+ }
612
+
613
+ var abs = jsc.getAbsPointerPos(e);
614
+ var rel = jsc.getRelPointerPos(e);
615
+ jsc._pointerOrigin = {
616
+ x: abs.x - rel.x,
617
+ y: abs.y - rel.y
618
  };
619
 
620
+ switch (controlName) {
621
+ case 'pad':
622
+ // if the slider is at the bottom, move it up
623
+ switch (jsc.getSliderComponent(thisObj)) {
624
+ case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break;
625
+ case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break;
626
+ }
627
+ jsc.setPad(thisObj, e, 0, 0);
628
+ break;
629
+
630
+ case 'sld':
631
+ jsc.setSld(thisObj, e, 0);
632
+ break;
633
+ }
634
+
635
+ jsc.dispatchFineChange(thisObj);
636
+ },
637
 
 
638
 
639
+ onDocumentPointerMove : function (e, target, controlName, pointerType, offset) {
640
+ return function (e) {
641
+ var thisObj = target._jscInstance;
642
+ switch (controlName) {
643
+ case 'pad':
644
+ if (!e) { e = window.event; }
645
+ jsc.setPad(thisObj, e, offset[0], offset[1]);
646
+ jsc.dispatchFineChange(thisObj);
647
+ break;
648
+
649
+ case 'sld':
650
+ if (!e) { e = window.event; }
651
+ jsc.setSld(thisObj, e, offset[1]);
652
+ jsc.dispatchFineChange(thisObj);
653
+ break;
654
  }
655
+ }
656
+ },
657
+
658
+
659
+ onDocumentPointerEnd : function (e, target, controlName, pointerType) {
660
+ return function (e) {
661
+ var thisObj = target._jscInstance;
662
+ jsc.detachGroupEvents('drag');
663
+ jsc.releaseTarget();
664
+ // Always dispatch changes after detaching outstanding mouse handlers,
665
+ // in case some user interaction will occur in user's onchange callback
666
+ // that would intrude with current mouse events
667
+ jsc.dispatchChange(thisObj);
668
+ };
669
+ },
670
+
671
+
672
+ dispatchChange : function (thisObj) {
673
+ if (thisObj.valueElement) {
674
+ if (jsc.isElementType(thisObj.valueElement, 'input')) {
675
+ jsc.fireEvent(thisObj.valueElement, 'change');
676
+ }
677
+ }
678
+ },
679
 
680
+
681
+ dispatchFineChange : function (thisObj) {
682
+ if (thisObj.onFineChange) {
683
+ var callback;
684
+ if (typeof thisObj.onFineChange === 'string') {
685
+ callback = new Function (thisObj.onFineChange);
686
  } else {
687
+ callback = thisObj.onFineChange;
688
+ }
689
+ callback.call(thisObj);
690
+ }
691
+ },
692
+
693
+
694
+ setPad : function (thisObj, e, ofsX, ofsY) {
695
+ var pointerAbs = jsc.getAbsPointerPos(e);
696
+ var x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.insetWidth;
697
+ var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
698
+
699
+ var xVal = x * (360 / (thisObj.width - 1));
700
+ var yVal = 100 - (y * (100 / (thisObj.height - 1)));
701
+
702
+ switch (jsc.getPadYComponent(thisObj)) {
703
+ case 's': thisObj.fromHSV(xVal, yVal, null, jsc.leaveSld); break;
704
+ case 'v': thisObj.fromHSV(xVal, null, yVal, jsc.leaveSld); break;
705
+ }
706
+ },
707
+
708
+
709
+ setSld : function (thisObj, e, ofsY) {
710
+ var pointerAbs = jsc.getAbsPointerPos(e);
711
+ var y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;
712
+
713
+ var yVal = 100 - (y * (100 / (thisObj.height - 1)));
714
+
715
+ switch (jsc.getSliderComponent(thisObj)) {
716
+ case 's': thisObj.fromHSV(null, yVal, null, jsc.leavePad); break;
717
+ case 'v': thisObj.fromHSV(null, null, yVal, jsc.leavePad); break;
718
+ }
719
+ },
720
+
721
+
722
+ _vmlNS : 'jsc_vml_',
723
+ _vmlCSS : 'jsc_vml_css_',
724
+ _vmlReady : false,
725
+
726
+
727
+ initVML : function () {
728
+ if (!jsc._vmlReady) {
729
+ // init VML namespace
730
+ var doc = document;
731
+ if (!doc.namespaces[jsc._vmlNS]) {
732
+ doc.namespaces.add(jsc._vmlNS, 'urn:schemas-microsoft-com:vml');
733
+ }
734
+ if (!doc.styleSheets[jsc._vmlCSS]) {
735
+ var tags = ['shape', 'shapetype', 'group', 'background', 'path', 'formulas', 'handles', 'fill', 'stroke', 'shadow', 'textbox', 'textpath', 'imagedata', 'line', 'polyline', 'curve', 'rect', 'roundrect', 'oval', 'arc', 'image'];
736
+ var ss = doc.createStyleSheet();
737
+ ss.owningElement.id = jsc._vmlCSS;
738
+ for (var i = 0; i < tags.length; i += 1) {
739
+ ss.addRule(jsc._vmlNS + '\\:' + tags[i], 'behavior:url(#default#VML);');
740
  }
 
741
  }
742
+ jsc._vmlReady = true;
743
+ }
744
+ },
745
 
746
+
747
+ createPalette : function () {
748
+
749
+ var paletteObj = {
750
+ elm: null,
751
+ draw: null
752
  };
753
 
754
+ if (jsc.isCanvasSupported) {
755
+ // Canvas implementation for modern browsers
756
+
757
+ var canvas = document.createElement('canvas');
758
+ var ctx = canvas.getContext('2d');
759
+
760
+ var drawFunc = function (width, height, type) {
761
+ canvas.width = width;
762
+ canvas.height = height;
763
+
764
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
765
+
766
+ var hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0);
767
+ hGrad.addColorStop(0 / 6, '#F00');
768
+ hGrad.addColorStop(1 / 6, '#FF0');
769
+ hGrad.addColorStop(2 / 6, '#0F0');
770
+ hGrad.addColorStop(3 / 6, '#0FF');
771
+ hGrad.addColorStop(4 / 6, '#00F');
772
+ hGrad.addColorStop(5 / 6, '#F0F');
773
+ hGrad.addColorStop(6 / 6, '#F00');
774
+
775
+ ctx.fillStyle = hGrad;
776
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
777
+
778
+ var vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height);
779
+ switch (type.toLowerCase()) {
780
+ case 's':
781
+ vGrad.addColorStop(0, 'rgba(255,255,255,0)');
782
+ vGrad.addColorStop(1, 'rgba(255,255,255,1)');
783
+ break;
784
+ case 'v':
785
+ vGrad.addColorStop(0, 'rgba(0,0,0,0)');
786
+ vGrad.addColorStop(1, 'rgba(0,0,0,1)');
787
+ break;
788
  }
789
+ ctx.fillStyle = vGrad;
790
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
791
+ };
792
+
793
+ paletteObj.elm = canvas;
794
+ paletteObj.draw = drawFunc;
795
+
796
+ } else {
797
+ // VML fallback for IE 7 and 8
798
+
799
+ jsc.initVML();
800
+
801
+ var vmlContainer = document.createElement('div');
802
+ vmlContainer.style.position = 'relative';
803
+ vmlContainer.style.overflow = 'hidden';
804
+
805
+ var hGrad = document.createElement(jsc._vmlNS + ':fill');
806
+ hGrad.type = 'gradient';
807
+ hGrad.method = 'linear';
808
+ hGrad.angle = '90';
809
+ hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0'
810
+
811
+ var hRect = document.createElement(jsc._vmlNS + ':rect');
812
+ hRect.style.position = 'absolute';
813
+ hRect.style.left = -1 + 'px';
814
+ hRect.style.top = -1 + 'px';
815
+ hRect.stroked = false;
816
+ hRect.appendChild(hGrad);
817
+ vmlContainer.appendChild(hRect);
818
+
819
+ var vGrad = document.createElement(jsc._vmlNS + ':fill');
820
+ vGrad.type = 'gradient';
821
+ vGrad.method = 'linear';
822
+ vGrad.angle = '180';
823
+ vGrad.opacity = '0';
824
+
825
+ var vRect = document.createElement(jsc._vmlNS + ':rect');
826
+ vRect.style.position = 'absolute';
827
+ vRect.style.left = -1 + 'px';
828
+ vRect.style.top = -1 + 'px';
829
+ vRect.stroked = false;
830
+ vRect.appendChild(vGrad);
831
+ vmlContainer.appendChild(vRect);
832
+
833
+ var drawFunc = function (width, height, type) {
834
+ vmlContainer.style.width = width + 'px';
835
+ vmlContainer.style.height = height + 'px';
836
+
837
+ hRect.style.width =
838
+ vRect.style.width =
839
+ (width + 1) + 'px';
840
+ hRect.style.height =
841
+ vRect.style.height =
842
+ (height + 1) + 'px';
843
+
844
+ // Colors must be specified during every redraw, otherwise IE won't display
845
+ // a full gradient during a subsequential redraw
846
+ hGrad.color = '#F00';
847
+ hGrad.color2 = '#F00';
848
+
849
+ switch (type.toLowerCase()) {
850
+ case 's':
851
+ vGrad.color = vGrad.color2 = '#FFF';
852
+ break;
853
+ case 'v':
854
+ vGrad.color = vGrad.color2 = '#000';
855
+ break;
856
+ }
857
+ };
858
+
859
+ paletteObj.elm = vmlContainer;
860
+ paletteObj.draw = drawFunc;
861
  }
862
 
863
+ return paletteObj;
864
+ },
865
+
866
+
867
+ createSliderGradient : function () {
868
+
869
+ var sliderObj = {
870
+ elm: null,
871
+ draw: null
872
+ };
873
+
874
+ if (jsc.isCanvasSupported) {
875
+ // Canvas implementation for modern browsers
876
+
877
+ var canvas = document.createElement('canvas');
878
+ var ctx = canvas.getContext('2d');
879
+
880
+ var drawFunc = function (width, height, color1, color2) {
881
+ canvas.width = width;
882
+ canvas.height = height;
883
+
884
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
885
+
886
+ var grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
887
+ grad.addColorStop(0, color1);
888
+ grad.addColorStop(1, color2);
889
+
890
+ ctx.fillStyle = grad;
891
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
892
+ };
893
+
894
+ sliderObj.elm = canvas;
895
+ sliderObj.draw = drawFunc;
896
+
897
+ } else {
898
+ // VML fallback for IE 7 and 8
899
+
900
+ jsc.initVML();
901
+
902
+ var vmlContainer = document.createElement('div');
903
+ vmlContainer.style.position = 'relative';
904
+ vmlContainer.style.overflow = 'hidden';
905
+
906
+ var grad = document.createElement(jsc._vmlNS + ':fill');
907
+ grad.type = 'gradient';
908
+ grad.method = 'linear';
909
+ grad.angle = '180';
910
+
911
+ var rect = document.createElement(jsc._vmlNS + ':rect');
912
+ rect.style.position = 'absolute';
913
+ rect.style.left = -1 + 'px';
914
+ rect.style.top = -1 + 'px';
915
+ rect.stroked = false;
916
+ rect.appendChild(grad);
917
+ vmlContainer.appendChild(rect);
918
+
919
+ var drawFunc = function (width, height, color1, color2) {
920
+ vmlContainer.style.width = width + 'px';
921
+ vmlContainer.style.height = height + 'px';
922
+
923
+ rect.style.width = (width + 1) + 'px';
924
+ rect.style.height = (height + 1) + 'px';
925
+
926
+ grad.color = color1;
927
+ grad.color2 = color2;
928
+ };
929
+
930
+ sliderObj.elm = vmlContainer;
931
+ sliderObj.draw = drawFunc;
932
  }
933
 
934
+ return sliderObj;
935
  },
936
 
937
 
938
+ leaveValue : 1<<0,
939
+ leaveStyle : 1<<1,
940
+ leavePad : 1<<2,
941
+ leaveSld : 1<<3,
942
+
943
+
944
+ BoxShadow : (function () {
945
+ var BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) {
946
+ this.hShadow = hShadow;
947
+ this.vShadow = vShadow;
948
+ this.blur = blur;
949
+ this.spread = spread;
950
+ this.color = color;
951
+ this.inset = !!inset;
952
+ };
953
+
954
+ BoxShadow.prototype.toString = function () {
955
+ var vals = [
956
+ Math.round(this.hShadow) + 'px',
957
+ Math.round(this.vShadow) + 'px',
958
+ Math.round(this.blur) + 'px',
959
+ Math.round(this.spread) + 'px',
960
+ this.color
961
+ ];
962
+ if (this.inset) {
963
+ vals.push('inset');
964
+ }
965
+ return vals.join(' ');
966
+ };
967
+
968
+ return BoxShadow;
969
+ })(),
970
+
971
+
972
  //
973
+ // Usage:
974
+ // var myColor = new jscolor(<targetElement> [, <options>])
975
  //
976
 
977
+ jscolor : function (targetElement, options) {
978
+
979
+ // General options
980
+ //
981
+ this.value = null; // initial HEX color. To change it later, use methods fromString(), fromHSV() and fromRGB()
982
+ this.valueElement = targetElement; // element that will be used to display and input the color code
983
+ this.styleElement = targetElement; // element that will preview the picked color using CSS backgroundColor
984
+ this.required = true; // whether the associated text <input> can be left empty
985
+ this.refine = true; // whether to refine the entered color code (e.g. uppercase it and remove whitespace)
986
+ this.hash = false; // whether to prefix the HEX color code with # symbol
987
+ this.uppercase = true; // whether to uppercase the color code
988
+ this.onFineChange = null; // called instantly every time the color changes (value can be either a function or a string with javascript code)
989
+ this.activeClass = 'jscolor-active'; // class to be set to the target element when a picker window is open on it
990
+ this.minS = 0; // min allowed saturation (0 - 100)
991
+ this.maxS = 100; // max allowed saturation (0 - 100)
992
+ this.minV = 0; // min allowed value (brightness) (0 - 100)
993
+ this.maxV = 100; // max allowed value (brightness) (0 - 100)
994
+
995
+ // Accessing the picked color
996
+ //
997
+ this.hsv = [0, 0, 100]; // read-only [0-360, 0-100, 0-100]
998
+ this.rgb = [255, 255, 255]; // read-only [0-255, 0-255, 0-255]
999
+
1000
+ // Color Picker options
1001
+ //
1002
+ this.width = 181; // width of color palette (in px)
1003
+ this.height = 101; // height of color palette (in px)
1004
+ this.showOnClick = true; // whether to display the color picker when user clicks on its target element
1005
+ this.mode = 'HSV'; // HSV | HVS | HS | HV - layout of the color picker controls
1006
+ this.position = 'bottom'; // left | right | top | bottom - position relative to the target element
1007
+ this.smartPosition = true; // automatically change picker position when there is not enough space for it
1008
+ this.sliderSize = 16; // px
1009
+ this.crossSize = 8; // px
1010
+ this.closable = false; // whether to display the Close button
1011
+ this.closeText = 'Close';
1012
+ this.buttonColor = '#000000'; // CSS color
1013
+ this.buttonHeight = 18; // px
1014
+ this.padding = 12; // px
1015
+ this.backgroundColor = '#FFFFFF'; // CSS color
1016
+ this.borderWidth = 1; // px
1017
+ this.borderColor = '#F1F1F1'; // CSS color
1018
+ this.borderRadius = 3; // px
1019
+ this.insetWidth = 1; // px
1020
+ this.insetColor = '#BBBBBB'; // CSS color
1021
+ this.shadow = true; // whether to display shadow
1022
+ this.shadowBlur = 15; // px
1023
+ this.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color
1024
+ this.pointerColor = '#4C4C4C'; // px
1025
+ this.pointerBorderColor = '#FFFFFF'; // px
1026
+ this.pointerBorderWidth = 1; // px
1027
+ this.pointerThickness = 2; // px
1028
+ this.zIndex = 1000;
1029
+ this.container = null; // where to append the color picker (BODY element by default)
1030
+
1031
+
1032
+ for (var opt in options) {
1033
+ if (options.hasOwnProperty(opt)) {
1034
+ this[opt] = options[opt];
1035
+ }
1036
+ }
1037
+
1038
+
1039
+ this.hide = function () {
1040
+ if (isPickerOwner()) {
1041
+ detachPicker();
1042
  }
1043
  };
1044
 
1045
 
1046
+ this.show = function () {
1047
+ drawPicker();
1048
+ };
 
 
 
 
 
 
 
 
 
 
 
 
1049
 
1050
+
1051
+ this.redraw = function () {
1052
+ if (isPickerOwner()) {
1053
+ drawPicker();
 
 
 
 
 
 
 
 
 
 
 
 
 
1054
  }
1055
  };
1056
 
1057
 
1058
+ this.importColor = function () {
1059
+ if (!this.valueElement) {
1060
  this.exportColor();
1061
  } else {
1062
+ if (jsc.isElementType(this.valueElement, 'input')) {
1063
+ if (!this.refine) {
1064
+ if (!this.fromString(this.valueElement.value, jsc.leaveValue)) {
1065
+ if (this.styleElement) {
1066
+ this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
1067
+ this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
1068
+ this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
1069
+ }
1070
+ this.exportColor(jsc.leaveValue | jsc.leaveStyle);
1071
+ }
1072
+ } else if (!this.required && /^\s*$/.test(this.valueElement.value)) {
1073
+ this.valueElement.value = '';
1074
+ if (this.styleElement) {
1075
+ this.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;
1076
+ this.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;
1077
+ this.styleElement.style.color = this.styleElement._jscOrigStyle.color;
1078
+ }
1079
+ this.exportColor(jsc.leaveValue | jsc.leaveStyle);
1080
+
1081
+ } else if (this.fromString(this.valueElement.value)) {
1082
+ // managed to import color successfully from the value -> OK, don't do anything
1083
+ } else {
1084
+ this.exportColor();
1085
  }
 
 
 
 
 
 
 
 
 
1086
  } else {
1087
+ // not an input element -> doesn't have any value
1088
  this.exportColor();
1089
  }
1090
  }
1091
  };
1092
 
1093
 
1094
+ this.exportColor = function (flags) {
1095
+ if (!(flags & jsc.leaveValue) && this.valueElement) {
1096
  var value = this.toString();
1097
+ if (this.uppercase) { value = value.toUpperCase(); }
1098
+ if (this.hash) { value = '#' + value; }
1099
+
1100
+ if (jsc.isElementType(this.valueElement, 'input')) {
1101
+ this.valueElement.value = value;
1102
+ } else {
1103
+ this.valueElement.innerHTML = value;
1104
+ }
1105
+ }
1106
+ if (!(flags & jsc.leaveStyle)) {
1107
+ if (this.styleElement) {
1108
+ this.styleElement.style.backgroundImage = 'none';
1109
+ this.styleElement.style.backgroundColor = '#' + this.toString();
1110
+ this.styleElement.style.color = this.isLight() ? '#000' : '#FFF';
1111
+ }
1112
+ }
1113
+ if (!(flags & jsc.leavePad) && isPickerOwner()) {
1114
  redrawPad();
1115
  }
1116
+ if (!(flags & jsc.leaveSld) && isPickerOwner()) {
1117
  redrawSld();
1118
  }
1119
  };
1120
 
1121
 
1122
+ // h: 0-360
1123
+ // s: 0-100
1124
+ // v: 0-100
1125
+ //
1126
+ this.fromHSV = function (h, s, v, flags) { // null = don't change
1127
+ if (h !== null) {
1128
+ if (isNaN(h)) { return false; }
1129
+ h = Math.max(0, Math.min(360, h));
1130
+ }
1131
+ if (s !== null) {
1132
+ if (isNaN(s)) { return false; }
1133
+ s = Math.max(0, Math.min(100, this.maxS, s), this.minS);
1134
+ }
1135
+ if (v !== null) {
1136
+ if (isNaN(v)) { return false; }
1137
+ v = Math.max(0, Math.min(100, this.maxV, v), this.minV);
1138
+ }
1139
 
1140
  this.rgb = HSV_RGB(
1141
  h===null ? this.hsv[0] : (this.hsv[0]=h),
1147
  };
1148
 
1149
 
1150
+ // r: 0-255
1151
+ // g: 0-255
1152
+ // b: 0-255
1153
+ //
1154
+ this.fromRGB = function (r, g, b, flags) { // null = don't change
1155
+ if (r !== null) {
1156
+ if (isNaN(r)) { return false; }
1157
+ r = Math.max(0, Math.min(255, r));
1158
+ }
1159
+ if (g !== null) {
1160
+ if (isNaN(g)) { return false; }
1161
+ g = Math.max(0, Math.min(255, g));
1162
+ }
1163
+ if (b !== null) {
1164
+ if (isNaN(b)) { return false; }
1165
+ b = Math.max(0, Math.min(255, b));
1166
+ }
1167
 
1168
  var hsv = RGB_HSV(
1169
  r===null ? this.rgb[0] : r,
1170
  g===null ? this.rgb[1] : g,
1171
  b===null ? this.rgb[2] : b
1172
  );
1173
+ if (hsv[0] !== null) {
1174
+ this.hsv[0] = Math.max(0, Math.min(360, hsv[0]));
1175
  }
1176
+ if (hsv[2] !== 0) {
1177
+ this.hsv[1] = hsv[1]===null ? null : Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1]));
1178
  }
1179
+ this.hsv[2] = hsv[2]===null ? null : Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2]));
1180
 
1181
  // update RGB according to final HSV, as some values might be trimmed
1182
  var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
1188
  };
1189
 
1190
 
1191
+ this.fromString = function (str, flags) {
1192
+ var m;
1193
+ if (m = str.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)) {
1194
+ // HEX notation
1195
+ //
1196
+
1197
+ if (m[1].length === 6) {
1198
+ // 6-char notation
1199
  this.fromRGB(
1200
+ parseInt(m[1].substr(0,2),16),
1201
+ parseInt(m[1].substr(2,2),16),
1202
+ parseInt(m[1].substr(4,2),16),
1203
  flags
1204
  );
1205
+ } else {
1206
+ // 3-char notation
1207
  this.fromRGB(
1208
+ parseInt(m[1].charAt(0) + m[1].charAt(0),16),
1209
+ parseInt(m[1].charAt(1) + m[1].charAt(1),16),
1210
+ parseInt(m[1].charAt(2) + m[1].charAt(2),16),
1211
  flags
1212
  );
1213
  }
1214
  return true;
1215
+
1216
+ } else if (m = str.match(/^\W*rgba?\(([^)]*)\)\W*$/i)) {
1217
+ var params = m[1].split(',');
1218
+ var re = /^\s*(\d*)(\.\d+)?\s*$/;
1219
+ var mR, mG, mB;
1220
+ if (
1221
+ params.length >= 3 &&
1222
+ (mR = params[0].match(re)) &&
1223
+ (mG = params[1].match(re)) &&
1224
+ (mB = params[2].match(re))
1225
+ ) {
1226
+ var r = parseFloat((mR[1] || '0') + (mR[2] || ''));
1227
+ var g = parseFloat((mG[1] || '0') + (mG[2] || ''));
1228
+ var b = parseFloat((mB[1] || '0') + (mB[2] || ''));
1229
+ this.fromRGB(r, g, b, flags);
1230
+ return true;
1231
+ }
1232
  }
1233
+ return false;
1234
+ };
1235
+
1236
+
1237
+ this.toString = function () {
1238
+ return (
1239
+ (0x100 | Math.round(this.rgb[0])).toString(16).substr(1) +
1240
+ (0x100 | Math.round(this.rgb[1])).toString(16).substr(1) +
1241
+ (0x100 | Math.round(this.rgb[2])).toString(16).substr(1)
1242
+ );
1243
+ };
1244
+
1245
+
1246
+ this.toHEXString = function () {
1247
+ return '#' + this.toString().toUpperCase();
1248
+ };
1249
+
1250
+
1251
+ this.toRGBString = function () {
1252
+ return ('rgb(' +
1253
+ Math.round(this.rgb[0]) + ',' +
1254
+ Math.round(this.rgb[1]) + ',' +
1255
+ Math.round(this.rgb[2]) + ')'
1256
+ );
1257
  };
1258
 
1259
 
1260
+ this.isLight = function () {
1261
  return (
1262
+ 0.213 * this.rgb[0] +
1263
+ 0.715 * this.rgb[1] +
1264
+ 0.072 * this.rgb[2] >
1265
+ 255 / 2
1266
  );
1267
  };
1268
 
1269
 
1270
+ this._processParentElementsInDOM = function () {
1271
+ if (this._linkedElementsProcessed) { return; }
1272
+ this._linkedElementsProcessed = true;
1273
+
1274
+ var elm = this.targetElement;
1275
+ do {
1276
+ // If the target element or one of its parent nodes has fixed position,
1277
+ // then use fixed positioning instead
1278
+ //
1279
+ // Note: In Firefox, getComputedStyle returns null in a hidden iframe,
1280
+ // that's why we need to check if the returned style object is non-empty
1281
+ var currStyle = jsc.getStyle(elm);
1282
+ if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
1283
+ this.fixed = true;
1284
+ }
1285
+
1286
+ if (elm !== this.targetElement) {
1287
+ // Ensure to attach onParentScroll only once to each parent element
1288
+ // (multiple targetElements can share the same parent nodes)
1289
+ //
1290
+ // Note: It's not just offsetParents that can be scrollable,
1291
+ // that's why we loop through all parent nodes
1292
+ if (!elm._jscEventsAttached) {
1293
+ jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
1294
+ elm._jscEventsAttached = true;
1295
+ }
1296
+ }
1297
+ } while ((elm = elm.parentNode) && !jsc.isElementType(elm, 'body'));
1298
+ };
1299
+
1300
+
1301
+ // r: 0-255
1302
+ // g: 0-255
1303
+ // b: 0-255
1304
+ //
1305
+ // returns: [ 0-360, 0-100, 0-100 ]
1306
+ //
1307
+ function RGB_HSV (r, g, b) {
1308
+ r /= 255;
1309
+ g /= 255;
1310
+ b /= 255;
1311
  var n = Math.min(Math.min(r,g),b);
1312
  var v = Math.max(Math.max(r,g),b);
1313
  var m = v - n;
1314
+ if (m === 0) { return [ null, 0, 100 * v ]; }
1315
  var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
1316
+ return [
1317
+ 60 * (h===6?0:h),
1318
+ 100 * (m/v),
1319
+ 100 * v
1320
+ ];
1321
  }
1322
 
1323
 
1324
+ // h: 0-360
1325
+ // s: 0-100
1326
+ // v: 0-100
1327
+ //
1328
+ // returns: [ 0-255, 0-255, 0-255 ]
1329
+ //
1330
+ function HSV_RGB (h, s, v) {
1331
+ var u = 255 * (v / 100);
1332
+
1333
+ if (h === null) {
1334
+ return [ u, u, u ];
1335
+ }
1336
+
1337
+ h /= 60;
1338
+ s /= 100;
1339
+
1340
  var i = Math.floor(h);
1341
  var f = i%2 ? h-i : 1-(h-i);
1342
+ var m = u * (1 - s);
1343
+ var n = u * (1 - s * f);
1344
+ switch (i) {
1345
  case 6:
1346
+ case 0: return [u,n,m];
1347
+ case 1: return [n,u,m];
1348
+ case 2: return [m,u,n];
1349
+ case 3: return [m,n,u];
1350
+ case 4: return [n,m,u];
1351
+ case 5: return [u,m,n];
1352
  }
1353
  }
1354
 
1355
 
1356
+ function detachPicker () {
1357
+ jsc.unsetClass(THIS.targetElement, THIS.activeClass);
1358
+ jsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap);
1359
+ delete jsc.picker.owner;
1360
  }
1361
 
1362
 
1363
+ function drawPicker () {
1364
+
1365
+ // At this point, when drawing the picker, we know what the parent elements are
1366
+ // and we can do all related DOM operations, such as registering events on them
1367
+ // or checking their positioning
1368
+ THIS._processParentElementsInDOM();
1369
+
1370
+ if (!jsc.picker) {
1371
+ jsc.picker = {
1372
+ owner: null,
1373
+ wrap : document.createElement('div'),
1374
  box : document.createElement('div'),
1375
+ boxS : document.createElement('div'), // shadow area
1376
+ boxB : document.createElement('div'), // border
1377
  pad : document.createElement('div'),
1378
+ padB : document.createElement('div'), // border
1379
+ padM : document.createElement('div'), // mouse/touch area
1380
+ padPal : jsc.createPalette(),
1381
+ cross : document.createElement('div'),
1382
+ crossBY : document.createElement('div'), // border Y
1383
+ crossBX : document.createElement('div'), // border X
1384
+ crossLY : document.createElement('div'), // line Y
1385
+ crossLX : document.createElement('div'), // line X
1386
  sld : document.createElement('div'),
1387
+ sldB : document.createElement('div'), // border
1388
+ sldM : document.createElement('div'), // mouse/touch area
1389
+ sldGrad : jsc.createSliderGradient(),
1390
+ sldPtrS : document.createElement('div'), // slider pointer spacer
1391
+ sldPtrIB : document.createElement('div'), // slider pointer inner border
1392
+ sldPtrMB : document.createElement('div'), // slider pointer middle border
1393
+ sldPtrOB : document.createElement('div'), // slider pointer outer border
1394
  btn : document.createElement('div'),
1395
+ btnT : document.createElement('span') // text
 
1396
  };
1397
+
1398
+ jsc.picker.pad.appendChild(jsc.picker.padPal.elm);
1399
+ jsc.picker.padB.appendChild(jsc.picker.pad);
1400
+ jsc.picker.cross.appendChild(jsc.picker.crossBY);
1401
+ jsc.picker.cross.appendChild(jsc.picker.crossBX);
1402
+ jsc.picker.cross.appendChild(jsc.picker.crossLY);
1403
+ jsc.picker.cross.appendChild(jsc.picker.crossLX);
1404
+ jsc.picker.padB.appendChild(jsc.picker.cross);
1405
+ jsc.picker.box.appendChild(jsc.picker.padB);
1406
+ jsc.picker.box.appendChild(jsc.picker.padM);
1407
+
1408
+ jsc.picker.sld.appendChild(jsc.picker.sldGrad.elm);
1409
+ jsc.picker.sldB.appendChild(jsc.picker.sld);
1410
+ jsc.picker.sldB.appendChild(jsc.picker.sldPtrOB);
1411
+ jsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB);
1412
+ jsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB);
1413
+ jsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS);
1414
+ jsc.picker.box.appendChild(jsc.picker.sldB);
1415
+ jsc.picker.box.appendChild(jsc.picker.sldM);
1416
+
1417
+ jsc.picker.btn.appendChild(jsc.picker.btnT);
1418
+ jsc.picker.box.appendChild(jsc.picker.btn);
1419
+
1420
+ jsc.picker.boxB.appendChild(jsc.picker.box);
1421
+ jsc.picker.wrap.appendChild(jsc.picker.boxS);
1422
+ jsc.picker.wrap.appendChild(jsc.picker.boxB);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1423
  }
1424
 
1425
+ var p = jsc.picker;
1426
+
1427
+ var displaySlider = !!jsc.getSliderComponent(THIS);
1428
+ var dims = jsc.getPickerDims(THIS);
1429
+ var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
1430
+ var padToSliderPadding = jsc.getPadToSliderPadding(THIS);
1431
+ var borderRadius = Math.min(
1432
+ THIS.borderRadius,
1433
+ Math.round(THIS.padding * Math.PI)); // px
1434
+ var padCursor = 'crosshair';
1435
+
1436
+ // wrap
1437
+ p.wrap.style.clear = 'both';
1438
+ p.wrap.style.width = (dims[0] + 2 * THIS.borderWidth) + 'px';
1439
+ p.wrap.style.height = (dims[1] + 2 * THIS.borderWidth) + 'px';
1440
+ p.wrap.style.zIndex = THIS.zIndex;
1441
+
1442
  // picker
 
1443
  p.box.style.width = dims[0] + 'px';
1444
  p.box.style.height = dims[1] + 'px';
1445
 
1446
+ p.boxS.style.position = 'absolute';
1447
+ p.boxS.style.left = '0';
1448
+ p.boxS.style.top = '0';
1449
+ p.boxS.style.width = '100%';
1450
+ p.boxS.style.height = '100%';
1451
+ jsc.setBorderRadius(p.boxS, borderRadius + 'px');
1452
+
1453
  // picker border
1454
+ p.boxB.style.position = 'relative';
1455
+ p.boxB.style.border = THIS.borderWidth + 'px solid';
1456
+ p.boxB.style.borderColor = THIS.borderColor;
1457
+ p.boxB.style.background = THIS.backgroundColor;
1458
+ jsc.setBorderRadius(p.boxB, borderRadius + 'px');
1459
+
1460
+ // IE hack:
1461
+ // If the element is transparent, IE will trigger the event on the elements under it,
1462
+ // e.g. on Canvas or on elements with border
1463
+ p.padM.style.background =
1464
+ p.sldM.style.background =
1465
+ '#FFF';
1466
+ jsc.setStyle(p.padM, 'opacity', '0');
1467
+ jsc.setStyle(p.sldM, 'opacity', '0');
1468
+
1469
+ // pad
1470
+ p.pad.style.position = 'relative';
1471
+ p.pad.style.width = THIS.width + 'px';
1472
+ p.pad.style.height = THIS.height + 'px';
1473
+
1474
+ // pad palettes (HSV and HVS)
1475
+ p.padPal.draw(THIS.width, THIS.height, jsc.getPadYComponent(THIS));
1476
 
1477
  // pad border
1478
  p.padB.style.position = 'absolute';
1479
+ p.padB.style.left = THIS.padding + 'px';
1480
+ p.padB.style.top = THIS.padding + 'px';
1481
+ p.padB.style.border = THIS.insetWidth + 'px solid';
1482
+ p.padB.style.borderColor = THIS.insetColor;
1483
 
1484
  // pad mouse area
1485
+ p.padM._jscInstance = THIS;
1486
+ p.padM._jscControlName = 'pad';
1487
  p.padM.style.position = 'absolute';
1488
  p.padM.style.left = '0';
1489
  p.padM.style.top = '0';
1490
+ p.padM.style.width = (THIS.padding + 2 * THIS.insetWidth + THIS.width + padToSliderPadding / 2) + 'px';
1491
+ p.padM.style.height = dims[1] + 'px';
1492
+ p.padM.style.cursor = padCursor;
1493
+
1494
+ // pad cross
1495
+ p.cross.style.position = 'absolute';
1496
+ p.cross.style.left =
1497
+ p.cross.style.top =
1498
+ '0';
1499
+ p.cross.style.width =
1500
+ p.cross.style.height =
1501
+ crossOuterSize + 'px';
1502
+
1503
+ // pad cross border Y and X
1504
+ p.crossBY.style.position =
1505
+ p.crossBX.style.position =
1506
+ 'absolute';
1507
+ p.crossBY.style.background =
1508
+ p.crossBX.style.background =
1509
+ THIS.pointerBorderColor;
1510
+ p.crossBY.style.width =
1511
+ p.crossBX.style.height =
1512
+ (2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
1513
+ p.crossBY.style.height =
1514
+ p.crossBX.style.width =
1515
+ crossOuterSize + 'px';
1516
+ p.crossBY.style.left =
1517
+ p.crossBX.style.top =
1518
+ (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px';
1519
+ p.crossBY.style.top =
1520
+ p.crossBX.style.left =
1521
+ '0';
1522
+
1523
+ // pad cross line Y and X
1524
+ p.crossLY.style.position =
1525
+ p.crossLX.style.position =
1526
+ 'absolute';
1527
+ p.crossLY.style.background =
1528
+ p.crossLX.style.background =
1529
+ THIS.pointerColor;
1530
+ p.crossLY.style.height =
1531
+ p.crossLX.style.width =
1532
+ (crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px';
1533
+ p.crossLY.style.width =
1534
+ p.crossLX.style.height =
1535
+ THIS.pointerThickness + 'px';
1536
+ p.crossLY.style.left =
1537
+ p.crossLX.style.top =
1538
+ (Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px';
1539
+ p.crossLY.style.top =
1540
+ p.crossLX.style.left =
1541
+ THIS.pointerBorderWidth + 'px';
1542
+
1543
+ // slider
1544
  p.sld.style.overflow = 'hidden';
1545
+ p.sld.style.width = THIS.sliderSize + 'px';
1546
+ p.sld.style.height = THIS.height + 'px';
1547
+
1548
+ // slider gradient
1549
+ p.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000');
1550
 
1551
  // slider border
1552
+ p.sldB.style.display = displaySlider ? 'block' : 'none';
1553
  p.sldB.style.position = 'absolute';
1554
+ p.sldB.style.right = THIS.padding + 'px';
1555
+ p.sldB.style.top = THIS.padding + 'px';
1556
+ p.sldB.style.border = THIS.insetWidth + 'px solid';
1557
+ p.sldB.style.borderColor = THIS.insetColor;
1558
 
1559
  // slider mouse area
1560
+ p.sldM._jscInstance = THIS;
1561
+ p.sldM._jscControlName = 'sld';
1562
+ p.sldM.style.display = displaySlider ? 'block' : 'none';
1563
  p.sldM.style.position = 'absolute';
1564
  p.sldM.style.right = '0';
1565
  p.sldM.style.top = '0';
1566
+ p.sldM.style.width = (THIS.sliderSize + padToSliderPadding / 2 + THIS.padding + 2 * THIS.insetWidth) + 'px';
1567
+ p.sldM.style.height = dims[1] + 'px';
1568
+ p.sldM.style.cursor = 'default';
1569
+
1570
+ // slider pointer inner and outer border
1571
+ p.sldPtrIB.style.border =
1572
+ p.sldPtrOB.style.border =
1573
+ THIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor;
1574
+
1575
+ // slider pointer outer border
1576
+ p.sldPtrOB.style.position = 'absolute';
1577
+ p.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';
1578
+ p.sldPtrOB.style.top = '0';
1579
+
1580
+ // slider pointer middle border
1581
+ p.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor;
1582
+
1583
+ // slider pointer spacer
1584
+ p.sldPtrS.style.width = THIS.sliderSize + 'px';
1585
+ p.sldPtrS.style.height = sliderPtrSpace + 'px';
1586
+
1587
+ // the Close button
1588
+ function setBtnBorder () {
1589
+ var insetColors = THIS.insetColor.split(/\s+/);
1590
+ var outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
1591
+ p.btn.style.borderColor = outsetColor;
1592
  }
1593
+ p.btn.style.display = THIS.closable ? 'block' : 'none';
1594
  p.btn.style.position = 'absolute';
1595
+ p.btn.style.left = THIS.padding + 'px';
1596
+ p.btn.style.bottom = THIS.padding + 'px';
1597
  p.btn.style.padding = '0 15px';
1598
+ p.btn.style.height = THIS.buttonHeight + 'px';
1599
+ p.btn.style.border = THIS.insetWidth + 'px solid';
1600
  setBtnBorder();
1601
+ p.btn.style.color = THIS.buttonColor;
1602
  p.btn.style.font = '12px sans-serif';
1603
  p.btn.style.textAlign = 'center';
1604
  try {
1607
  p.btn.style.cursor = 'hand';
1608
  }
1609
  p.btn.onmousedown = function () {
1610
+ THIS.hide();
1611
  };
1612
+ p.btnT.style.lineHeight = THIS.buttonHeight + 'px';
1613
+ p.btnT.innerHTML = '';
1614
+ p.btnT.appendChild(document.createTextNode(THIS.closeText));
 
 
 
 
 
 
 
 
 
 
 
1615
 
1616
  // place pointers
1617
  redrawPad();
1618
  redrawSld();
1619
 
1620
+ // If we are changing the owner without first closing the picker,
1621
+ // make sure to first deal with the old owner
1622
+ if (jsc.picker.owner && jsc.picker.owner !== THIS) {
1623
+ jsc.unsetClass(jsc.picker.owner.targetElement, THIS.activeClass);
1624
+ }
1625
 
1626
+ // Set the new picker owner
1627
+ jsc.picker.owner = THIS;
1628
 
1629
+ // The redrawPosition() method needs picker.owner to be set, that's why we call it here,
1630
+ // after setting the owner
1631
+ if (jsc.isElementType(container, 'body')) {
1632
+ jsc.redrawPosition();
1633
+ } else {
1634
+ jsc._drawPosition(THIS, 0, 0, 'relative', false);
1635
+ }
1636
+
1637
+ if (p.wrap.parentNode != container) {
1638
+ container.appendChild(p.wrap);
1639
+ }
1640
+
1641
+ jsc.setClass(THIS.targetElement, THIS.activeClass);
1642
  }
1643
 
1644
 
1645
+ function redrawPad () {
1646
  // redraw the pad pointer
1647
+ switch (jsc.getPadYComponent(THIS)) {
1648
+ case 's': var yComponent = 1; break;
1649
+ case 'v': var yComponent = 2; break;
1650
+ }
1651
+ var x = Math.round((THIS.hsv[0] / 360) * (THIS.width - 1));
1652
+ var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
1653
+ var crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);
1654
+ var ofs = -Math.floor(crossOuterSize / 2);
1655
+ jsc.picker.cross.style.left = (x + ofs) + 'px';
1656
+ jsc.picker.cross.style.top = (y + ofs) + 'px';
1657
+
1658
+ // redraw the slider
1659
+ switch (jsc.getSliderComponent(THIS)) {
1660
+ case 's':
1661
+ var rgb1 = HSV_RGB(THIS.hsv[0], 100, THIS.hsv[2]);
1662
+ var rgb2 = HSV_RGB(THIS.hsv[0], 0, THIS.hsv[2]);
1663
+ var color1 = 'rgb(' +
1664
+ Math.round(rgb1[0]) + ',' +
1665
+ Math.round(rgb1[1]) + ',' +
1666
+ Math.round(rgb1[2]) + ')';
1667
+ var color2 = 'rgb(' +
1668
+ Math.round(rgb2[0]) + ',' +
1669
+ Math.round(rgb2[1]) + ',' +
1670
+ Math.round(rgb2[2]) + ')';
1671
+ jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
1672
+ break;
1673
+ case 'v':
1674
+ var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 100);
1675
+ var color1 = 'rgb(' +
1676
+ Math.round(rgb[0]) + ',' +
1677
+ Math.round(rgb[1]) + ',' +
1678
+ Math.round(rgb[2]) + ')';
1679
+ var color2 = '#000';
1680
+ jsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);
1681
+ break;
 
 
 
 
 
 
 
 
 
 
 
1682
  }
1683
  }
1684
 
1685
 
1686
+ function redrawSld () {
1687
+ var sldComponent = jsc.getSliderComponent(THIS);
1688
+ if (sldComponent) {
1689
+ // redraw the slider pointer
1690
+ switch (sldComponent) {
1691
+ case 's': var yComponent = 1; break;
1692
+ case 'v': var yComponent = 2; break;
1693
+ }
1694
+ var y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));
1695
+ jsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(sliderPtrSpace / 2)) + 'px';
1696
  }
 
 
 
1697
  }
1698
 
1699
 
1700
+ function isPickerOwner () {
1701
+ return jsc.picker && jsc.picker.owner === THIS;
1702
  }
1703
 
1704
 
1705
+ function blurValue () {
1706
+ THIS.importColor();
 
 
 
 
 
1707
  }
1708
 
1709
 
1710
+ // Find the target element
1711
+ if (typeof targetElement === 'string') {
1712
+ var id = targetElement;
1713
+ var elm = document.getElementById(id);
1714
+ if (elm) {
1715
+ this.targetElement = elm;
1716
+ } else {
1717
+ jsc.warn('Could not find target element with ID \'' + id + '\'');
1718
  }
1719
+ } else if (targetElement) {
1720
+ this.targetElement = targetElement;
1721
+ } else {
1722
+ jsc.warn('Invalid target element: \'' + targetElement + '\'');
1723
  }
1724
 
1725
+ if (this.targetElement._jscLinkedInstance) {
1726
+ jsc.warn('Cannot link jscolor twice to the same element. Skipping.');
1727
+ return;
 
 
 
 
 
 
1728
  }
1729
+ this.targetElement._jscLinkedInstance = this;
1730
 
1731
+ // Find the value element
1732
+ this.valueElement = jsc.fetchElement(this.valueElement);
1733
+ // Find the style element
1734
+ this.styleElement = jsc.fetchElement(this.styleElement);
1735
 
1736
+ var THIS = this;
1737
+ var container =
1738
+ this.container ?
1739
+ jsc.fetchElement(this.container) :
1740
+ document.getElementsByTagName('body')[0];
1741
+ var sliderPtrSpace = 3; // px
1742
+
1743
+ // For BUTTON elements it's important to stop them from sending the form when clicked
1744
+ // (e.g. in Safari)
1745
+ if (jsc.isElementType(this.targetElement, 'button')) {
1746
+ if (this.targetElement.onclick) {
1747
+ var origCallback = this.targetElement.onclick;
1748
+ this.targetElement.onclick = function (evt) {
1749
+ origCallback.call(this, evt);
1750
+ return false;
1751
+ };
1752
+ } else {
1753
+ this.targetElement.onclick = function () { return false; };
1754
  }
1755
  }
1756
 
1757
+ /*
1758
+ var elm = this.targetElement;
1759
+ do {
1760
+ // If the target element or one of its offsetParents has fixed position,
1761
+ // then use fixed positioning instead
1762
+ //
1763
+ // Note: In Firefox, getComputedStyle returns null in a hidden iframe,
1764
+ // that's why we need to check if the returned style object is non-empty
1765
+ var currStyle = jsc.getStyle(elm);
1766
+ if (currStyle && currStyle.position.toLowerCase() === 'fixed') {
1767
+ this.fixed = true;
1768
  }
 
1769
 
1770
+ if (elm !== this.targetElement) {
1771
+ // attach onParentScroll so that we can recompute the picker position
1772
+ // when one of the offsetParents is scrolled
1773
+ if (!elm._jscEventsAttached) {
1774
+ jsc.attachEvent(elm, 'scroll', jsc.onParentScroll);
1775
+ elm._jscEventsAttached = true;
1776
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1777
  }
1778
+ } while ((elm = elm.offsetParent) && !jsc.isElementType(elm, 'body'));
1779
+ */
1780
 
1781
  // valueElement
1782
+ if (this.valueElement) {
1783
+ if (jsc.isElementType(this.valueElement, 'input')) {
1784
+ var updateField = function () {
1785
+ THIS.fromString(THIS.valueElement.value, jsc.leaveValue);
1786
+ jsc.dispatchFineChange(THIS);
1787
+ };
1788
+ jsc.attachEvent(this.valueElement, 'keyup', updateField);
1789
+ jsc.attachEvent(this.valueElement, 'input', updateField);
1790
+ jsc.attachEvent(this.valueElement, 'blur', blurValue);
1791
+ this.valueElement.setAttribute('autocomplete', 'off');
1792
+ }
1793
  }
1794
 
1795
  // styleElement
1796
+ if (this.styleElement) {
1797
+ this.styleElement._jscOrigStyle = {
1798
+ backgroundImage : this.styleElement.style.backgroundImage,
1799
+ backgroundColor : this.styleElement.style.backgroundColor,
1800
+ color : this.styleElement.style.color
1801
  };
1802
  }
1803
 
1804
+ if (this.value) {
1805
+ // Try to set the color from the .value option and if unsuccessful,
1806
+ // export the current color
1807
+ this.fromString(this.value) || this.exportColor();
1808
+ } else {
1809
+ this.importColor();
1810
  }
 
 
 
 
1811
  }
1812
 
1813
  };
1814
 
1815
 
1816
+ //================================
1817
+ // Public properties and methods
1818
+ //================================
1819
+
1820
+
1821
+ // By default, search for all elements with class="jscolor" and install a color picker on them.
1822
+ //
1823
+ // You can change what class name will be looked for by setting the property jscolor.lookupClass
1824
+ // anywhere in your HTML document. To completely disable the automatic lookup, set it to null.
1825
+ //
1826
+ jsc.jscolor.lookupClass = 'jscolor';
1827
+
1828
+
1829
+ jsc.jscolor.installByClassName = function (className) {
1830
+ var inputElms = document.getElementsByTagName('input');
1831
+ var buttonElms = document.getElementsByTagName('button');
1832
+
1833
+ jsc.tryInstallOnElements(inputElms, className);
1834
+ jsc.tryInstallOnElements(buttonElms, className);
1835
+ };
1836
+
1837
+
1838
+ jsc.register();
1839
+
1840
+
1841
+ return jsc.jscolor;
1842
+
1843
+
1844
+ })(); }
framework/admin/preview.php CHANGED
@@ -20,7 +20,7 @@ require_once '../public/include/functions.php';
20
 
21
 
22
  // Plugin options from the database
23
- $signals_csmm_options = get_option( 'signals_csmm_options' );
24
 
25
 
26
  // Localization
20
 
21
 
22
  // Plugin options from the database
23
+ $signals_csmm_options = csmm_get_options();
24
 
25
 
26
  // Localization
framework/admin/settings.php CHANGED
@@ -147,8 +147,7 @@ function csmm_admin_settings() {
147
 
148
 
149
  // Grab options from the database
150
- $signals_csmm_options = get_option( 'signals_csmm_options' );
151
-
152
 
153
 
154
  // Grabbing admin_email from the database
@@ -158,9 +157,7 @@ function csmm_admin_settings() {
158
 
159
  // View template for the settings panel
160
  require 'views/settings.php';
161
-
162
- }
163
-
164
 
165
 
166
  // AJAX request for user support
@@ -175,12 +172,23 @@ function csmm_ajax_support() {
175
 
176
  // Filtering and sanitizing the support issue
177
  if ( ! empty( $_POST['signals_support_email'] ) && ! empty( $_POST['signals_support_issue'] ) ) {
178
- $admin_email = sanitize_text_field( $_POST['signals_support_email'] );
 
179
  $issue = $_POST['signals_support_issue'];
 
180
 
181
  $subject = '[Maintenance Mode Ticket] by '. $admin_email;
182
  $body = "Email: $admin_email \r\nIssue: $issue";
183
  $headers = 'From: ' . $admin_email . "\r\n" . 'Reply-To: ' . $admin_email;
 
 
 
 
 
 
 
 
 
184
 
185
 
186
  // Sending the mail to the support email
@@ -210,3 +218,10 @@ function csmm_ajax_support() {
210
 
211
  }
212
  add_action( 'wp_ajax_signals_csmm_support', 'csmm_ajax_support' );
 
 
 
 
 
 
 
147
 
148
 
149
  // Grab options from the database
150
+ $signals_csmm_options = csmm_get_options();
 
151
 
152
 
153
  // Grabbing admin_email from the database
157
 
158
  // View template for the settings panel
159
  require 'views/settings.php';
160
+ } // csmm_admin_settings
 
 
161
 
162
 
163
  // AJAX request for user support
172
 
173
  // Filtering and sanitizing the support issue
174
  if ( ! empty( $_POST['signals_support_email'] ) && ! empty( $_POST['signals_support_issue'] ) ) {
175
+ $theme = wp_get_theme();
176
+ $admin_email = sanitize_text_field( $_POST['signals_support_email'] );
177
  $issue = $_POST['signals_support_issue'];
178
+ $options = get_option('signals_csmm_options');
179
 
180
  $subject = '[Maintenance Mode Ticket] by '. $admin_email;
181
  $body = "Email: $admin_email \r\nIssue: $issue";
182
  $headers = 'From: ' . $admin_email . "\r\n" . 'Reply-To: ' . $admin_email;
183
+
184
+ $body .= "\r\n\r\nSite details:\r\n";
185
+ $body .= ' WordPress version: ' . get_bloginfo('version') . "\r\n";
186
+ $body .= ' MM version: ' . csmm_get_plugin_version() . "\r\n";
187
+ $body .= ' PHP version: ' . PHP_VERSION . "\r\n";
188
+ $body .= ' Site URL: ' . get_bloginfo('url') . "\r\n";
189
+ $body .= ' WordPress URL: ' . get_bloginfo('wpurl') . "\r\n";
190
+ $body .= ' Theme: ' . $theme->get('Name') . ' v' . $theme->get('Version') . "\r\n";
191
+ $body .= ' Options: ' . "\r\n" . serialize($options) . "\r\n";
192
 
193
 
194
  // Sending the mail to the support email
218
 
219
  }
220
  add_action( 'wp_ajax_signals_csmm_support', 'csmm_ajax_support' );
221
+ add_action( 'wp_ajax_csmm_rate_hide', 'csmm_rate_hide' );
222
+
223
+ function csmm_rate_hide() {
224
+ set_transient('csmm_rate_hide', true, DAY_IN_SECONDS * 700);
225
+
226
+ wp_send_json_success();
227
+ } // csmm_rate_hide
framework/admin/views/settings-basic.php CHANGED
@@ -12,7 +12,7 @@
12
  <div class="signals-tile" id="basic">
13
  <div class="signals-tile-body">
14
  <div class="signals-tile-title"><?php _e( 'BASIC', 'signals' ); ?></div>
15
- <p><?php _e( 'Configure the core settings. Make sure you configure these options carefully as they are important for the working of the plugin.', 'signals' ); ?></p>
16
 
17
  <div class="signals-section-content">
18
  <div class="signals-double-group signals-clearfix">
@@ -91,9 +91,9 @@
91
  // list items
92
  foreach ( $signals_arrange as $signals_item ) {
93
  if ( 'html' == $signals_item ) {
94
- echo '<li data-id="' . $signals_item . '"><span class="dashicons dashicons-sort"></span> ' . __( 'Custom HTML', 'signals' ) . '</li>';
95
  } else {
96
- echo '<li data-id="' . $signals_item . '"><span class="dashicons dashicons-sort"></span> ' . ucfirst( $signals_item ) . '</li>';
97
  }
98
  }
99
  } else {
12
  <div class="signals-tile" id="basic">
13
  <div class="signals-tile-body">
14
  <div class="signals-tile-title"><?php _e( 'BASIC', 'signals' ); ?></div>
15
+ <p><?php _e( 'Configure the core settings. Make sure you configure these options carefully as they are important for the proper functioning of the plugin.', 'signals' ); ?></p>
16
 
17
  <div class="signals-section-content">
18
  <div class="signals-double-group signals-clearfix">
91
  // list items
92
  foreach ( $signals_arrange as $signals_item ) {
93
  if ( 'html' == $signals_item ) {
94
+ echo '<li data-id="' . $signals_item . '"><span class="dashicons dashicons-menu"></span> ' . __( 'Custom HTML', 'signals' ) . '</li>';
95
  } else {
96
+ echo '<li data-id="' . $signals_item . '"><span class="dashicons dashicons-menu"></span> ' . ucfirst( $signals_item ) . '</li>';
97
  }
98
  }
99
  } else {
framework/admin/views/settings-design.php CHANGED
@@ -97,7 +97,7 @@
97
 
98
  <div class="signals-form-group">
99
  <label for="signals_csmm_color" class="signals-strong"><?php _e( 'Background Color', 'signals' ); ?></label>
100
- <input type="text" name="signals_csmm_color" id="signals_csmm_color" value="<?php esc_attr_e( $signals_csmm_options['bg_color'] ); ?>" placeholder="<?php _e( 'Background color for the page', 'signals' ); ?>" class="signals-form-control color {required:false}">
101
 
102
  <p class="signals-form-help-block"><?php _e( 'Select background color for the page. If the background cover image is set, this option will be ignored.', 'signals' ); ?></p>
103
  </div>
@@ -150,7 +150,7 @@
150
  ?>
151
  </select>
152
 
153
- <h3><?php _e( 'This is how this font is going to look!', 'signals' ); ?></h3>
154
  <p class="signals-form-help-block"><?php _e( 'Font for the header text. Listing a total of 668 Google web fonts.', 'signals' ); ?></p>
155
  </div>
156
 
@@ -176,7 +176,7 @@
176
  ?>
177
  </select>
178
 
179
- <h3><?php _e( 'This is how this font is going to look!', 'signals' ); ?></h3>
180
  <p class="signals-form-help-block"><?php _e( 'Font for the secondary text. Listing a total of 668 Google web fonts.', 'signals' ); ?></p>
181
  </div>
182
  </div>
@@ -220,14 +220,14 @@
220
  <div class="signals-double-group signals-clearfix">
221
  <div class="signals-form-group">
222
  <label for="signals_csmm_header_color" class="signals-strong"><?php _e( 'Header Text Color', 'signals' ); ?></label>
223
- <input type="text" name="signals_csmm_header_color" id="signals_csmm_header_color" value="<?php esc_attr_e( $signals_csmm_options['header_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Header text', 'signals' ); ?>" class="signals-form-control color {required:false}">
224
 
225
  <p class="signals-form-help-block"><?php _e( 'Select font color for the header text.', 'signals' ); ?></p>
226
  </div>
227
 
228
  <div class="signals-form-group">
229
  <label for="signals_csmm_secondary_color" class="signals-strong"><?php _e( 'Secondary Text Color', 'signals' ); ?></label>
230
- <input type="text" name="signals_csmm_secondary_color" id="signals_csmm_secondary_color" value="<?php esc_attr_e( $signals_csmm_options['secondary_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Secondary text', 'signals' ); ?>" class="signals-form-control color {required:false}">
231
 
232
  <p class="signals-form-help-block"><?php _e( 'Select font color for the secondary text.', 'signals' ); ?></p>
233
  </div>
@@ -253,7 +253,7 @@
253
 
254
  <div class="signals-form-group">
255
  <label for="signals_csmm_antispam_color" class="signals-strong"><?php _e( 'Antispam Text Color', 'signals' ); ?></label>
256
- <input type="text" name="signals_csmm_antispam_color" id="signals_csmm_antispam_color" value="<?php esc_attr_e( $signals_csmm_options['antispam_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Antispam text', 'signals' ); ?>" class="signals-form-control color {required:false}">
257
 
258
  <p class="signals-form-help-block"><?php _e( 'Select font color for the antispam text.', 'signals' ); ?></p>
259
  </div>
97
 
98
  <div class="signals-form-group">
99
  <label for="signals_csmm_color" class="signals-strong"><?php _e( 'Background Color', 'signals' ); ?></label>
100
+ <input type="text" name="signals_csmm_color" id="signals_csmm_color" value="<?php esc_attr_e( $signals_csmm_options['bg_color'] ); ?>" placeholder="<?php _e( 'Background color for the page', 'signals' ); ?>" class="jscolor signals-form-control color {required:false}">
101
 
102
  <p class="signals-form-help-block"><?php _e( 'Select background color for the page. If the background cover image is set, this option will be ignored.', 'signals' ); ?></p>
103
  </div>
150
  ?>
151
  </select>
152
 
153
+ <h3><?php _e( 'This is how the header font is going to look!', 'signals' ); ?></h3>
154
  <p class="signals-form-help-block"><?php _e( 'Font for the header text. Listing a total of 668 Google web fonts.', 'signals' ); ?></p>
155
  </div>
156
 
176
  ?>
177
  </select>
178
 
179
+ <h3><?php _e( 'This is how the secondary font is going to look!', 'signals' ); ?></h3>
180
  <p class="signals-form-help-block"><?php _e( 'Font for the secondary text. Listing a total of 668 Google web fonts.', 'signals' ); ?></p>
181
  </div>
182
  </div>
220
  <div class="signals-double-group signals-clearfix">
221
  <div class="signals-form-group">
222
  <label for="signals_csmm_header_color" class="signals-strong"><?php _e( 'Header Text Color', 'signals' ); ?></label>
223
+ <input type="text" name="signals_csmm_header_color" id="signals_csmm_header_color" value="<?php esc_attr_e( $signals_csmm_options['header_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Header text', 'signals' ); ?>" class="jscolor signals-form-control color {required:false}">
224
 
225
  <p class="signals-form-help-block"><?php _e( 'Select font color for the header text.', 'signals' ); ?></p>
226
  </div>
227
 
228
  <div class="signals-form-group">
229
  <label for="signals_csmm_secondary_color" class="signals-strong"><?php _e( 'Secondary Text Color', 'signals' ); ?></label>
230
+ <input type="text" name="signals_csmm_secondary_color" id="signals_csmm_secondary_color" value="<?php esc_attr_e( $signals_csmm_options['secondary_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Secondary text', 'signals' ); ?>" class="jscolor signals-form-control color {required:false}">
231
 
232
  <p class="signals-form-help-block"><?php _e( 'Select font color for the secondary text.', 'signals' ); ?></p>
233
  </div>
253
 
254
  <div class="signals-form-group">
255
  <label for="signals_csmm_antispam_color" class="signals-strong"><?php _e( 'Antispam Text Color', 'signals' ); ?></label>
256
+ <input type="text" name="signals_csmm_antispam_color" id="signals_csmm_antispam_color" value="<?php esc_attr_e( $signals_csmm_options['antispam_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Antispam text', 'signals' ); ?>" class="jscolor signals-form-control color {required:false}">
257
 
258
  <p class="signals-form-help-block"><?php _e( 'Select font color for the antispam text.', 'signals' ); ?></p>
259
  </div>
framework/admin/views/settings-email.php CHANGED
@@ -12,7 +12,7 @@
12
  <div class="signals-tile" id="email">
13
  <div class="signals-tile-body">
14
  <div class="signals-tile-title"><?php _e( 'EMAIL', 'signals' ); ?></div>
15
- <p><?php _e( 'Email settings for the plugin. You can configure your MailChimp account API with this plugin to store collected emails in an list.', 'signals' ); ?></p>
16
 
17
  <div class="signals-section-content">
18
  <div class="signals-form-group">
12
  <div class="signals-tile" id="email">
13
  <div class="signals-tile-body">
14
  <div class="signals-tile-title"><?php _e( 'EMAIL', 'signals' ); ?></div>
15
+ <p><?php _e( 'Email settings for the plugin. You can configure your MailChimp account API to store collected emails in a list.', 'signals' ); ?></p>
16
 
17
  <div class="signals-section-content">
18
  <div class="signals-form-group">
framework/admin/views/settings-form.php CHANGED
@@ -77,14 +77,14 @@
77
  <div class="signals-double-group signals-clearfix">
78
  <div class="signals-form-group">
79
  <label for="signals_csmm_input_color" class="signals-strong"><?php _e( 'Input Text Color', 'signals' ); ?></label>
80
- <input type="text" name="signals_csmm_input_color" id="signals_csmm_input_color" value="<?php esc_attr_e( $signals_csmm_options['input_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Input text', 'signals' ); ?>" class="signals-form-control color {required:false}">
81
 
82
  <p class="signals-form-help-block"><?php _e( 'Select font color for the input text field.', 'signals' ); ?></p>
83
  </div>
84
 
85
  <div class="signals-form-group">
86
  <label for="signals_csmm_button_color" class="signals-strong"><?php _e( 'Button Text Color', 'signals' ); ?></label>
87
- <input type="text" name="signals_csmm_button_color" id="signals_csmm_button_color" value="<?php esc_attr_e( $signals_csmm_options['button_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Button text', 'signals' ); ?>" class="signals-form-control color {required:false}">
88
 
89
  <p class="signals-form-help-block"><?php _e( 'Select font color for the button text.', 'signals' ); ?></p>
90
  </div>
@@ -93,14 +93,14 @@
93
  <div class="signals-double-group signals-clearfix">
94
  <div class="signals-form-group">
95
  <label for="signals_csmm_input_bg" class="signals-strong"><?php _e( 'Input Background Color', 'signals' ); ?></label>
96
- <input type="text" name="signals_csmm_input_bg" id="signals_csmm_input_bg" value="<?php esc_attr_e( $signals_csmm_options['input_bg'] ); ?>" placeholder="<?php _e( 'Background color for the Input field', 'signals' ); ?>" class="signals-form-control color {required:false}">
97
 
98
  <p class="signals-form-help-block"><?php _e( 'Select background color for the input text field.', 'signals' ); ?></p>
99
  </div>
100
 
101
  <div class="signals-form-group">
102
  <label for="signals_csmm_button_bg" class="signals-strong"><?php _e( 'Button Background Color', 'signals' ); ?></label>
103
- <input type="text" name="signals_csmm_button_bg" id="signals_csmm_button_bg" value="<?php esc_attr_e( $signals_csmm_options['button_bg'] ); ?>" placeholder="<?php _e( 'Background color for the Button', 'signals' ); ?>" class="signals-form-control color {required:false}">
104
 
105
  <p class="signals-form-help-block"><?php _e( 'Select background color for the button.', 'signals' ); ?></p>
106
  </div>
@@ -108,15 +108,15 @@
108
 
109
  <div class="signals-double-group signals-clearfix">
110
  <div class="signals-form-group">
111
- <label for="signals_csmm_input_bg_hover" class="signals-strong"><?php _e( 'Input Background Color', 'signals' ); ?> <span class="signals-red-color"><?php _e( 'FOCUS', 'signals' ); ?></span></label>
112
- <input type="text" name="signals_csmm_input_bg_hover" id="signals_csmm_input_bg_hover" value="<?php esc_attr_e( $signals_csmm_options['input_bg_hover'] ); ?>" placeholder="<?php _e( 'Background color for the Input field when it gets clicked', 'signals' ); ?>" class="signals-form-control color {required:false}">
113
 
114
  <p class="signals-form-help-block"><?php _e( 'Select background color for the input text field when it gets clicked.', 'signals' ); ?></p>
115
  </div>
116
 
117
  <div class="signals-form-group">
118
- <label for="signals_csmm_button_bg_hover" class="signals-strong"><?php _e( 'Button Background Color', 'signals' ); ?> <span class="signals-red-color"><?php _e( 'HOVER', 'signals' ); ?></span></label>
119
- <input type="text" name="signals_csmm_button_bg_hover" id="signals_csmm_button_bg_hover" value="<?php esc_attr_e( $signals_csmm_options['button_bg_hover'] ); ?>" placeholder="<?php _e( 'Background color for the Button on hover', 'signals' ); ?>" class="signals-form-control color {required:false}">
120
 
121
  <p class="signals-form-help-block"><?php _e( 'Select background color for the button on mouse hover.', 'signals' ); ?></p>
122
  </div>
@@ -125,14 +125,14 @@
125
  <div class="signals-double-group signals-clearfix">
126
  <div class="signals-form-group">
127
  <label for="signals_csmm_input_border" class="signals-strong"><?php _e( 'Input Border Color', 'signals' ); ?></label>
128
- <input type="text" name="signals_csmm_input_border" id="signals_csmm_input_border" value="<?php esc_attr_e( $signals_csmm_options['input_border'] ); ?>" placeholder="<?php _e( 'Border color for the Input field', 'signals' ); ?>" class="signals-form-control color {required:false}">
129
 
130
  <p class="signals-form-help-block"><?php _e( 'Select border color for the input field.', 'signals' ); ?></p>
131
  </div>
132
 
133
  <div class="signals-form-group">
134
  <label for="signals_csmm_button_border" class="signals-strong"><?php _e( 'Button Border Color', 'signals' ); ?></label>
135
- <input type="text" name="signals_csmm_button_border" id="signals_csmm_button_border" value="<?php esc_attr_e( $signals_csmm_options['button_border'] ); ?>" placeholder="<?php _e( 'Border color for the Button', 'signals' ); ?>" class="signals-form-control color {required:false}">
136
 
137
  <p class="signals-form-help-block"><?php _e( 'Select border color for the button.', 'signals' ); ?></p>
138
  </div>
@@ -140,15 +140,15 @@
140
 
141
  <div class="signals-double-group signals-clearfix">
142
  <div class="signals-form-group">
143
- <label for="signals_csmm_input_border_hover" class="signals-strong"><?php _e( 'Input Border Color', 'signals' ); ?> <span class="signals-red-color"><?php _e( 'FOCUS', 'signals' ); ?></span></label>
144
- <input type="text" name="signals_csmm_input_border_hover" id="signals_csmm_input_border_hover" value="<?php esc_attr_e( $signals_csmm_options['input_border_hover'] ); ?>" placeholder="<?php _e( 'Border color for the Input field when it gets clicked', 'signals' ); ?>" class="signals-form-control color {required:false}">
145
 
146
  <p class="signals-form-help-block"><?php _e( 'Select border color for the input field when it gets clicked.', 'signals' ); ?></p>
147
  </div>
148
 
149
  <div class="signals-form-group">
150
- <label for="signals_csmm_button_border_hover" class="signals-strong"><?php _e( 'Button Border Color', 'signals' ); ?> <span class="signals-red-color"><?php _e( 'HOVER', 'signals' ); ?></span></label>
151
- <input type="text" name="signals_csmm_button_border_hover" id="signals_csmm_button_border_hover" value="<?php esc_attr_e( $signals_csmm_options['button_border_hover'] ); ?>" placeholder="<?php _e( 'Border color for the Button on hover', 'signals' ); ?>" class="signals-form-control color {required:false}">
152
 
153
  <p class="signals-form-help-block"><?php _e( 'Select border color for the button on mouse hover.', 'signals' ); ?></p>
154
  </div>
@@ -157,14 +157,14 @@
157
  <div class="signals-double-group signals-clearfix">
158
  <div class="signals-form-group">
159
  <label for="signals_csmm_success_bg" class="signals-strong"><?php _e( 'Success Message Background Color', 'signals' ); ?></span></label>
160
- <input type="text" name="signals_csmm_success_bg" id="signals_csmm_success_bg" value="<?php esc_attr_e( $signals_csmm_options['success_background'] ); ?>" placeholder="<?php _e( 'Background color for the success message', 'signals' ); ?>" class="signals-form-control color {required:false}">
161
 
162
  <p class="signals-form-help-block"><?php _e( 'Select background color for the success message.', 'signals' ); ?></p>
163
  </div>
164
 
165
  <div class="signals-form-group">
166
- <label for="signals_csmm_success_color" class="signals-strong"><?php _e( 'Success Message Text Color', 'signals' ); ?> <span class="signals-red-color"></span></label>
167
- <input type="text" name="signals_csmm_success_color" id="signals_csmm_success_color" value="<?php esc_attr_e( $signals_csmm_options['success_color'] ); ?>" placeholder="<?php _e( 'Text color for the success message', 'signals' ); ?>" class="signals-form-control color {required:false}">
168
 
169
  <p class="signals-form-help-block"><?php _e( 'Select text color for the success message.', 'signals' ); ?></p>
170
  </div>
@@ -173,14 +173,14 @@
173
  <div class="signals-double-group signals-clearfix">
174
  <div class="signals-form-group">
175
  <label for="signals_csmm_error_bg" class="signals-strong"><?php _e( 'Error Message Background Color', 'signals' ); ?></span></label>
176
- <input type="text" name="signals_csmm_error_bg" id="signals_csmm_error_bg" value="<?php esc_attr_e( $signals_csmm_options['error_background'] ); ?>" placeholder="<?php _e( 'Background color for the error message', 'signals' ); ?>" class="signals-form-control color {required:false}">
177
 
178
  <p class="signals-form-help-block"><?php _e( 'Select background color for the error message.', 'signals' ); ?></p>
179
  </div>
180
 
181
  <div class="signals-form-group">
182
- <label for="signals_csmm_error_color" class="signals-strong"><?php _e( 'Error Message Text Color', 'signals' ); ?> <span class="signals-red-color"></span></label>
183
- <input type="text" name="signals_csmm_error_color" id="signals_csmm_error_color" value="<?php esc_attr_e( $signals_csmm_options['error_color'] ); ?>" placeholder="<?php _e( 'Text color for the error message', 'signals' ); ?>" class="signals-form-control color {required:false}">
184
 
185
  <p class="signals-form-help-block"><?php _e( 'Select text color for the error message.', 'signals' ); ?></p>
186
  </div>
77
  <div class="signals-double-group signals-clearfix">
78
  <div class="signals-form-group">
79
  <label for="signals_csmm_input_color" class="signals-strong"><?php _e( 'Input Text Color', 'signals' ); ?></label>
80
+ <input type="text" name="signals_csmm_input_color" id="signals_csmm_input_color" value="<?php esc_attr_e( $signals_csmm_options['input_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Input text', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
81
 
82
  <p class="signals-form-help-block"><?php _e( 'Select font color for the input text field.', 'signals' ); ?></p>
83
  </div>
84
 
85
  <div class="signals-form-group">
86
  <label for="signals_csmm_button_color" class="signals-strong"><?php _e( 'Button Text Color', 'signals' ); ?></label>
87
+ <input type="text" name="signals_csmm_button_color" id="signals_csmm_button_color" value="<?php esc_attr_e( $signals_csmm_options['button_font_color'] ); ?>" placeholder="<?php _e( 'Font color for the Button text', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
88
 
89
  <p class="signals-form-help-block"><?php _e( 'Select font color for the button text.', 'signals' ); ?></p>
90
  </div>
93
  <div class="signals-double-group signals-clearfix">
94
  <div class="signals-form-group">
95
  <label for="signals_csmm_input_bg" class="signals-strong"><?php _e( 'Input Background Color', 'signals' ); ?></label>
96
+ <input type="text" name="signals_csmm_input_bg" id="signals_csmm_input_bg" value="<?php esc_attr_e( $signals_csmm_options['input_bg'] ); ?>" placeholder="<?php _e( 'Background color for the Input field', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
97
 
98
  <p class="signals-form-help-block"><?php _e( 'Select background color for the input text field.', 'signals' ); ?></p>
99
  </div>
100
 
101
  <div class="signals-form-group">
102
  <label for="signals_csmm_button_bg" class="signals-strong"><?php _e( 'Button Background Color', 'signals' ); ?></label>
103
+ <input type="text" name="signals_csmm_button_bg" id="signals_csmm_button_bg" value="<?php esc_attr_e( $signals_csmm_options['button_bg'] ); ?>" placeholder="<?php _e( 'Background color for the Button', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
104
 
105
  <p class="signals-form-help-block"><?php _e( 'Select background color for the button.', 'signals' ); ?></p>
106
  </div>
108
 
109
  <div class="signals-double-group signals-clearfix">
110
  <div class="signals-form-group">
111
+ <label for="signals_csmm_input_bg_hover" class="signals-strong"><?php _e( 'Input Focus Background Color', 'signals' ); ?></label>
112
+ <input type="text" name="signals_csmm_input_bg_hover" id="signals_csmm_input_bg_hover" value="<?php esc_attr_e( $signals_csmm_options['input_bg_hover'] ); ?>" placeholder="<?php _e( 'Background color for the Input field when it gets clicked', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
113
 
114
  <p class="signals-form-help-block"><?php _e( 'Select background color for the input text field when it gets clicked.', 'signals' ); ?></p>
115
  </div>
116
 
117
  <div class="signals-form-group">
118
+ <label for="signals_csmm_button_bg_hover" class="signals-strong"><?php _e( 'Button Hover Background Color', 'signals' ); ?></label>
119
+ <input type="text" name="signals_csmm_button_bg_hover" id="signals_csmm_button_bg_hover" value="<?php esc_attr_e( $signals_csmm_options['button_bg_hover'] ); ?>" placeholder="<?php _e( 'Background color for the Button on hover', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
120
 
121
  <p class="signals-form-help-block"><?php _e( 'Select background color for the button on mouse hover.', 'signals' ); ?></p>
122
  </div>
125
  <div class="signals-double-group signals-clearfix">
126
  <div class="signals-form-group">
127
  <label for="signals_csmm_input_border" class="signals-strong"><?php _e( 'Input Border Color', 'signals' ); ?></label>
128
+ <input type="text" name="signals_csmm_input_border" id="signals_csmm_input_border" value="<?php esc_attr_e( $signals_csmm_options['input_border'] ); ?>" placeholder="<?php _e( 'Border color for the Input field', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
129
 
130
  <p class="signals-form-help-block"><?php _e( 'Select border color for the input field.', 'signals' ); ?></p>
131
  </div>
132
 
133
  <div class="signals-form-group">
134
  <label for="signals_csmm_button_border" class="signals-strong"><?php _e( 'Button Border Color', 'signals' ); ?></label>
135
+ <input type="text" name="signals_csmm_button_border" id="signals_csmm_button_border" value="<?php esc_attr_e( $signals_csmm_options['button_border'] ); ?>" placeholder="<?php _e( 'Border color for the Button', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
136
 
137
  <p class="signals-form-help-block"><?php _e( 'Select border color for the button.', 'signals' ); ?></p>
138
  </div>
140
 
141
  <div class="signals-double-group signals-clearfix">
142
  <div class="signals-form-group">
143
+ <label for="signals_csmm_input_border_hover" class="signals-strong"><?php _e( 'Input Focus Border Color', 'signals' ); ?> </label>
144
+ <input type="text" name="signals_csmm_input_border_hover" id="signals_csmm_input_border_hover" value="<?php esc_attr_e( $signals_csmm_options['input_border_hover'] ); ?>" placeholder="<?php _e( 'Border color for the Input field when it gets clicked', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
145
 
146
  <p class="signals-form-help-block"><?php _e( 'Select border color for the input field when it gets clicked.', 'signals' ); ?></p>
147
  </div>
148
 
149
  <div class="signals-form-group">
150
+ <label for="signals_csmm_button_border_hover" class="signals-strong"><?php _e( 'Button Hover Border Color', 'signals' ); ?> </label>
151
+ <input type="text" name="signals_csmm_button_border_hover" id="signals_csmm_button_border_hover" value="<?php esc_attr_e( $signals_csmm_options['button_border_hover'] ); ?>" placeholder="<?php _e( 'Border color for the Button on hover', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
152
 
153
  <p class="signals-form-help-block"><?php _e( 'Select border color for the button on mouse hover.', 'signals' ); ?></p>
154
  </div>
157
  <div class="signals-double-group signals-clearfix">
158
  <div class="signals-form-group">
159
  <label for="signals_csmm_success_bg" class="signals-strong"><?php _e( 'Success Message Background Color', 'signals' ); ?></span></label>
160
+ <input type="text" name="signals_csmm_success_bg" id="signals_csmm_success_bg" value="<?php esc_attr_e( $signals_csmm_options['success_background'] ); ?>" placeholder="<?php _e( 'Background color for the success message', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
161
 
162
  <p class="signals-form-help-block"><?php _e( 'Select background color for the success message.', 'signals' ); ?></p>
163
  </div>
164
 
165
  <div class="signals-form-group">
166
+ <label for="signals_csmm_success_color" class="signals-strong"><?php _e( 'Success Message Text Color', 'signals' ); ?> </label>
167
+ <input type="text" name="signals_csmm_success_color" id="signals_csmm_success_color" value="<?php esc_attr_e( $signals_csmm_options['success_color'] ); ?>" placeholder="<?php _e( 'Text color for the success message', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
168
 
169
  <p class="signals-form-help-block"><?php _e( 'Select text color for the success message.', 'signals' ); ?></p>
170
  </div>
173
  <div class="signals-double-group signals-clearfix">
174
  <div class="signals-form-group">
175
  <label for="signals_csmm_error_bg" class="signals-strong"><?php _e( 'Error Message Background Color', 'signals' ); ?></span></label>
176
+ <input type="text" name="signals_csmm_error_bg" id="signals_csmm_error_bg" value="<?php esc_attr_e( $signals_csmm_options['error_background'] ); ?>" placeholder="<?php _e( 'Background color for the error message', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
177
 
178
  <p class="signals-form-help-block"><?php _e( 'Select background color for the error message.', 'signals' ); ?></p>
179
  </div>
180
 
181
  <div class="signals-form-group">
182
+ <label for="signals_csmm_error_color" class="signals-strong"><?php _e( 'Error Message Text Color', 'signals' ); ?></label>
183
+ <input type="text" name="signals_csmm_error_color" id="signals_csmm_error_color" value="<?php esc_attr_e( $signals_csmm_options['error_color'] ); ?>" placeholder="<?php _e( 'Text color for the error message', 'signals' ); ?>" class="signals-form-control color jscolor {required:false}">
184
 
185
  <p class="signals-form-help-block"><?php _e( 'Select text color for the error message.', 'signals' ); ?></p>
186
  </div>
framework/admin/views/settings-support.php CHANGED
@@ -21,7 +21,7 @@
21
  <label for="signals_support_email" class="signals-strong"><?php _e( 'Email Address', 'signals' ); ?></label>
22
  <input type="text" name="signals_support_email" id="signals_support_email" value="<?php echo esc_attr_e( $signals_admin_email ); ?>" placeholder="<?php _e( 'Please provide your email address', 'signals' ); ?>" class="signals-form-control">
23
 
24
- <p class="signals-form-help-block"><?php _e( 'You will receive support response at this email address.', 'signals' ); ?></p>
25
  </div>
26
 
27
  <div class="signals-form-group" style="border-bottom: none; padding-bottom: 0">
@@ -30,6 +30,22 @@
30
 
31
  <p class="signals-form-help-block"><?php _e( 'Please explain the issue you are facing with the plugin. Provide as much detail as possible.', 'signals' ); ?></p>
32
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  <button class="signals-btn signals-create-ticket"><strong><?php _e( 'Ask for Support', 'signals' ); ?></strong></button>
35
  </div>
21
  <label for="signals_support_email" class="signals-strong"><?php _e( 'Email Address', 'signals' ); ?></label>
22
  <input type="text" name="signals_support_email" id="signals_support_email" value="<?php echo esc_attr_e( $signals_admin_email ); ?>" placeholder="<?php _e( 'Please provide your email address', 'signals' ); ?>" class="signals-form-control">
23
 
24
+ <p class="signals-form-help-block"><?php _e( 'You will receive support response on this email address.', 'signals' ); ?></p>
25
  </div>
26
 
27
  <div class="signals-form-group" style="border-bottom: none; padding-bottom: 0">
30
 
31
  <p class="signals-form-help-block"><?php _e( 'Please explain the issue you are facing with the plugin. Provide as much detail as possible.', 'signals' ); ?></p>
32
  </div>
33
+
34
+ <div class="signals-form-group" style="border-bottom: none; padding-bottom: 0">
35
+ <label for="" class="signals-strong">Additional data</label>
36
+ <?php
37
+ $theme = wp_get_theme();
38
+ echo '<p>WordPress version: <code>' . get_bloginfo('version') . '</code><br>';
39
+ echo 'MM Version: <code>' . csmm_get_plugin_version() . '</code><br>';
40
+ echo 'PHP Version: <code>' . PHP_VERSION . '</code><br>';
41
+ echo 'Site URL: <code>' . get_bloginfo('url') . '</code><br>';
42
+ echo 'WordPress URL: <code>' . get_bloginfo('wpurl') . '</code><br>';
43
+ echo 'Theme: <code>' . $theme->get('Name') . ' v' . $theme->get('Version') . '</code><br>';
44
+ echo 'MM Options: <i>all option values will be sent to support to ease debugging</i>';
45
+ echo '</p>';
46
+ ?>
47
+ <p class="signals-form-help-block">Our support agents need this info to provide faster &amp; better support. The data above will be added to your message.</p>
48
+ </div>
49
 
50
  <button class="signals-btn signals-create-ticket"><strong><?php _e( 'Ask for Support', 'signals' ); ?></strong></button>
51
  </div>
framework/admin/views/settings.php CHANGED
@@ -17,16 +17,25 @@ require_once 'header.php';
17
  <?php
18
 
19
  // Display the message if $signals_csmm_err is set
20
- if ( isset( $signals_csmm_err ) ) {
21
  echo $signals_csmm_err;
22
  }
23
 
24
- $user = wp_get_current_user();
25
-
26
- if (!get_transient('csmm_subscribe_hide')) {
27
- echo '<div id="collect_emails"><p><b>Get new templates &amp; premium updates straight to your inbox - for FREE!</b></p><p><input id="mm_name" value="' . $user->display_name . '" placeholder="How shall we call you?" type="text"> <input value="' . $user->user_email . '" id="mm_email" placeholder="Your best email address" type="email"><a href="#" id="mm_subscribe" class="button button-primary">Give me the free stuff</a> <a href="#" id="mm_subscribe_cancel"><span class="dashicons dashicons-no"></span></a></p></div>';
28
- } // if not hidden
29
-
 
 
 
 
 
 
 
 
 
30
  ?>
31
 
32
  <div class="signals-float-left">
@@ -72,4 +81,4 @@ require_once 'header.php';
72
 
73
  <?php
74
 
75
- require_once 'footer.php';
17
  <?php
18
 
19
  // Display the message if $signals_csmm_err is set
20
+ if ( !empty( $signals_csmm_err ) ) {
21
  echo $signals_csmm_err;
22
  }
23
 
24
+ $current_user = wp_get_current_user();
25
+ $name = '';
26
+ if (!empty($current_user->user_firstname)) {
27
+ $name = ' ' . $current_user->user_firstname;
28
+ }
29
+ $meta = get_option('signals_csmm_meta', false);
30
+
31
+ if (!get_transient('csmm_rate_hide')
32
+ && (time() - $meta['first_install_gmt']) > (DAY_IN_SECONDS * 1)) {
33
+ echo '<div id="rating-notice"><p>';
34
+ echo '<b>Hi' . $name . '!</b><br>We saw you\'ve been using the <b>Maintenance Mode</b> plugin for a few days (that\'s awesome!) and wanted to ask for your help to <b>make the plugin better</b>.<br>It just takes a minute of your time to rate the plugin. It helps us out a lot!</p>';
35
+ echo '<p><a href="https://wordpress.org/support/plugin/minimal-coming-soon-maintenance-mode/reviews/?rate=5&filter=5#new-post" target="_blank" class="button button-flat">Rate the plugin</a>';
36
+ echo '<a href="#" id="mm_rate_cancel">I\'ve already rated the plugin</a>';
37
+ echo '</p></div>';
38
+ }
39
  ?>
40
 
41
  <div class="signals-float-left">
81
 
82
  <?php
83
 
84
+ require_once 'footer.php';
framework/public/init.php CHANGED
@@ -27,8 +27,7 @@ function csmm_plugin_init() {
27
  add_action('wp_ajax_csmm_subscribe_hide', 'csmm_subscribe_hide');
28
 
29
  // Plugin options from the database
30
- $signals_csmm_options = get_option( 'signals_csmm_options' );
31
-
32
 
33
  // Localization
34
  load_plugin_textdomain( 'signals', false, SIGNALS_CSMM_PATH . 'framework/langs' );
@@ -129,3 +128,4 @@ function csmm_subscribe_hide() {
129
 
130
  wp_send_json_success();
131
  } // csmm_subscribe_hide
 
27
  add_action('wp_ajax_csmm_subscribe_hide', 'csmm_subscribe_hide');
28
 
29
  // Plugin options from the database
30
+ $signals_csmm_options = csmm_get_options();
 
31
 
32
  // Localization
33
  load_plugin_textdomain( 'signals', false, SIGNALS_CSMM_PATH . 'framework/langs' );
128
 
129
  wp_send_json_success();
130
  } // csmm_subscribe_hide
131
+
minimal-coming-soon-maintenance-mode.php CHANGED
@@ -4,13 +4,12 @@
4
  * Plugin Name: Minimal Coming Soon & Maintenance Mode
5
  * Plugin URI: https://wordpress.org/plugins/minimal-coming-soon-maintenance-mode/
6
  * Description: Simply awesome coming soon & maintenance mode plugin for WordPress. Super-simple to use. MailChimp support built-in.
7
- * Version: 1.40
8
  * Author: WebFactory
9
  * Author URI: http://www.webfactoryltd.com
10
  * License: GPLv3
11
  * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
12
  * Text Domain: signals
13
- * Domain Path: /framework/langs/
14
  *
15
  *
16
  * Minimal Coming Soon & Maintenance Mode Plugin
@@ -43,6 +42,79 @@ define( 'SIGNALS_CSMM_URL', plugins_url('', __FILE__ ) );
43
  define( 'SIGNALS_CSMM_PATH', plugin_dir_path( __FILE__ ) );
44
 
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * For the plugin activation & de-activation.
48
  * We are doing nothing over here.
@@ -54,79 +126,28 @@ function csmm_plugin_activation() {
54
  $signals_csmm_options = get_option( 'signals_csmm_options' );
55
 
56
  // Default options for the plugin on activation
57
- $default_options = array(
58
- 'status' => '2',
59
- 'title' => 'Site is under maintenance',
60
- 'header_text' => 'Sorry, we\'re doing some maintenance',
61
- 'secondary_text' => 'We are doing some maintenance on our site. It won\'t take long, we promise. Come back and visit us again in a few days. Thank you for your patience!',
62
- 'antispam_text' => 'And yes, we hate spam too!',
63
- 'custom_login_url' => '',
64
- 'show_logged_in' => '1',
65
- 'exclude_se' => '1',
66
- 'arrange' => 'logo,header,secondary,form,html',
67
- 'analytics' => '',
68
-
69
- 'mailchimp_api' => '',
70
- 'mailchimp_list' => '',
71
- 'message_noemail' => 'Please provide a valid email address.',
72
- 'message_subscribed' => 'You are already subscribed!',
73
- 'message_wrong' => 'Oops! Something went wrong.',
74
- 'message_done' => 'Thank you! We\'ll be in touch!',
75
-
76
- 'logo' => SIGNALS_CSMM_URL . '/framework/public/img/mm-logo.jpg',
77
- 'favicon' => SIGNALS_CSMM_URL . '/framework/public/img/mm-favicon.png',
78
- 'bg_cover' => SIGNALS_CSMM_URL . '/framework/public/img/mountain-bg.jpg',
79
- 'content_overlay' => 1,
80
- 'content_width' => '600',
81
- 'bg_color' => 'ffffff',
82
- 'content_position' => 'center',
83
- 'content_alignment' => 'left',
84
- 'header_font' => 'Karla',
85
- 'secondary_font' => 'Karla',
86
- 'header_font_size' => '28',
87
- 'secondary_font_size' => '14',
88
- 'header_font_color' => 'FFFFFF',
89
- 'secondary_font_color' => 'FFFFFF',
90
- 'antispam_font_size' => '13',
91
- 'antispam_font_color' => 'bbbbbb',
92
-
93
- 'input_text' => 'Enter your best email address',
94
- 'button_text' => 'Subscribe',
95
- 'ignore_form_styles' => 1,
96
- 'input_font_size' => '13',
97
- 'button_font_size' => '12',
98
- 'input_font_color' => 'ffffff',
99
- 'button_font_color' => 'ffffff',
100
- 'input_bg' => '',
101
- 'button_bg' => '0f0f0f',
102
- 'input_bg_hover' => '',
103
- 'button_bg_hover' => '0a0a0a',
104
- 'input_border' => 'eeeeee',
105
- 'button_border' => '0f0f0f',
106
- 'input_border_hover' => 'bbbbbb',
107
- 'button_border_hover' => '0a0a0a',
108
- 'success_background' => '90c695',
109
- 'success_color' => 'ffffff',
110
- 'error_background' => 'e08283',
111
- 'error_color' => 'ffffff',
112
-
113
- 'disable_settings' => '2',
114
- 'custom_html' => '',
115
- 'custom_css' => ''
116
- );
117
 
118
  // If the options are not there in the database, then create the default options for the plugin
119
  if ( ! $signals_csmm_options ) {
120
  update_option( 'signals_csmm_options', $default_options );
121
  } else {
122
  // If present in the database, merge with the default ones
123
- // This is to provide compatibility with earlier versions. Although this doesn't solves the purpose completely
124
  $default_options = array_merge( $default_options, $signals_csmm_options );
125
  update_option( 'signals_csmm_options', $default_options );
126
  }
127
-
128
- }
129
- register_activation_hook( __FILE__, 'csmm_plugin_activation' );
 
 
 
 
 
 
 
 
130
 
131
 
132
  /* Hook for the plugin deactivation. */
4
  * Plugin Name: Minimal Coming Soon & Maintenance Mode
5
  * Plugin URI: https://wordpress.org/plugins/minimal-coming-soon-maintenance-mode/
6
  * Description: Simply awesome coming soon & maintenance mode plugin for WordPress. Super-simple to use. MailChimp support built-in.
7
+ * Version: 1.45
8
  * Author: WebFactory
9
  * Author URI: http://www.webfactoryltd.com
10
  * License: GPLv3
11
  * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
12
  * Text Domain: signals
 
13
  *
14
  *
15
  * Minimal Coming Soon & Maintenance Mode Plugin
42
  define( 'SIGNALS_CSMM_PATH', plugin_dir_path( __FILE__ ) );
43
 
44
 
45
+ function csmm_default_options() {
46
+ $default_options = array(
47
+ 'status' => '2',
48
+ 'title' => 'Site is under maintenance',
49
+ 'header_text' => 'Sorry, we\'re doing some maintenance',
50
+ 'secondary_text' => 'We are doing some maintenance on our site. It won\'t take long, we promise. Come back and visit us again in a few days. Thank you for your patience!',
51
+ 'antispam_text' => 'And yes, we hate spam too!',
52
+ 'custom_login_url' => '',
53
+ 'show_logged_in' => '1',
54
+ 'exclude_se' => '1',
55
+ 'arrange' => 'logo,header,secondary,form,html',
56
+ 'analytics' => '',
57
+
58
+ 'mailchimp_api' => '',
59
+ 'mailchimp_list' => '',
60
+ 'message_noemail' => 'Please provide a valid email address.',
61
+ 'message_subscribed' => 'You are already subscribed!',
62
+ 'message_wrong' => 'Oops! Something went wrong.',
63
+ 'message_done' => 'Thank you! We\'ll be in touch!',
64
+
65
+ 'logo' => SIGNALS_CSMM_URL . '/framework/public/img/mm-logo.jpg',
66
+ 'favicon' => SIGNALS_CSMM_URL . '/framework/public/img/mm-favicon.png',
67
+ 'bg_cover' => SIGNALS_CSMM_URL . '/framework/public/img/mountain-bg.jpg',
68
+ 'content_overlay' => 1,
69
+ 'content_width' => '600',
70
+ 'bg_color' => 'ffffff',
71
+ 'content_position' => 'center',
72
+ 'content_alignment' => 'left',
73
+ 'header_font' => 'Karla',
74
+ 'secondary_font' => 'Karla',
75
+ 'header_font_size' => '28',
76
+ 'secondary_font_size' => '14',
77
+ 'header_font_color' => 'FFFFFF',
78
+ 'secondary_font_color' => 'FFFFFF',
79
+ 'antispam_font_size' => '13',
80
+ 'antispam_font_color' => 'bbbbbb',
81
+
82
+ 'input_text' => 'Enter your best email address',
83
+ 'button_text' => 'Subscribe',
84
+ 'ignore_form_styles' => 1,
85
+ 'input_font_size' => '13',
86
+ 'button_font_size' => '12',
87
+ 'input_font_color' => 'ffffff',
88
+ 'button_font_color' => 'ffffff',
89
+ 'input_bg' => '',
90
+ 'button_bg' => '0f0f0f',
91
+ 'input_bg_hover' => '',
92
+ 'button_bg_hover' => '0a0a0a',
93
+ 'input_border' => 'eeeeee',
94
+ 'button_border' => '0f0f0f',
95
+ 'input_border_hover' => 'bbbbbb',
96
+ 'button_border_hover' => '0a0a0a',
97
+ 'success_background' => '90c695',
98
+ 'success_color' => 'ffffff',
99
+ 'error_background' => 'e08283',
100
+ 'error_color' => 'ffffff',
101
+
102
+ 'disable_settings' => '2',
103
+ 'custom_html' => '',
104
+ 'custom_css' => ''
105
+ );
106
+
107
+ return $default_options;
108
+ } // csmm_default_options
109
+
110
+ function csmm_get_options() {
111
+ $signals_csmm_options = get_option('signals_csmm_options', array());
112
+ $signals_csmm_options = array_merge(csmm_default_options(), $signals_csmm_options);
113
+
114
+ return $signals_csmm_options;
115
+ } // csmm_get_options
116
+
117
+
118
  /**
119
  * For the plugin activation & de-activation.
120
  * We are doing nothing over here.
126
  $signals_csmm_options = get_option( 'signals_csmm_options' );
127
 
128
  // Default options for the plugin on activation
129
+ $default_options = csmm_default_options();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  // If the options are not there in the database, then create the default options for the plugin
132
  if ( ! $signals_csmm_options ) {
133
  update_option( 'signals_csmm_options', $default_options );
134
  } else {
135
  // If present in the database, merge with the default ones
136
+ // This is to provide compatibility with earlier versions. Although it doesn't serve the purpose completely
137
  $default_options = array_merge( $default_options, $signals_csmm_options );
138
  update_option( 'signals_csmm_options', $default_options );
139
  }
140
+
141
+ // set some meta data
142
+ $meta = get_option('signals_csmm_meta', array());
143
+ if (!isset($meta['first_version']) || !isset($meta['first_install'])) {
144
+ $meta['first_version'] = csmm_get_plugin_version();
145
+ $meta['first_install_gmt'] = time();
146
+ $meta['first_install'] = current_time('timestamp');
147
+ update_option('signals_csmm_meta', $meta);
148
+ }
149
+ } // csmm_plugin_activation
150
+ register_activation_hook( __FILE__, 'csmm_plugin_activation');
151
 
152
 
153
  /* Hook for the plugin deactivation. */
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: coming soon, coming soon page, launch page, maintenance mode, mailchimp
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
  Tested up to: 4.9
7
- Stable tag: 1.40
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -12,9 +12,9 @@ Simple & flexible Coming Soon & Maintenance Mode plugin - sets up in under a min
12
 
13
 
14
  == Description ==
15
- The Minimal Coming Soon & Maintenance Mode plugin allows you to **quickly & easily** set up a Coming Soon or Launch Page for your website.
16
 
17
- It's simple + flexible and works with any WordPress theme & plugin, plus you'll have full control over the frontend of the website and can modify almost every aspect of it per your preference. Easily conncets with MailChimp so that you can collect emails from visitors.
18
 
19
 
20
  = Plugin Features =
@@ -74,6 +74,13 @@ Yes and no. When activated it enables itself across the entire WP-MU network.
74
 
75
  == Changelog ==
76
 
 
 
 
 
 
 
 
77
  = 1.40 =
78
  * 2017-11-19
79
  * 30k users - 21/09/2017
4
  Requires at least: 4.0
5
  Requires PHP: 5.2
6
  Tested up to: 4.9
7
+ Stable tag: 1.45
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
12
 
13
 
14
  == Description ==
15
+ The Minimal Coming Soon & Maintenance Mode plugin allows you to **quickly & easily** set up a Coming Soon, Maintenance Mode or Launch Page for your website.
16
 
17
+ It's simple + flexible and works with any WordPress theme & plugin, plus you'll have full control over the frontend of the website and can modify almost every aspect of it per your preference. Easily connects with MailChimp so that you can **collect emails** from visitors.
18
 
19
 
20
  = Plugin Features =
74
 
75
  == Changelog ==
76
 
77
+ = 1.45 =
78
+ * 2017-12-13
79
+ * 40k users - early December
80
+ * minor fixes
81
+ * removed mailing list notification
82
+ * added plugin review request notification
83
+
84
  = 1.40 =
85
  * 2017-11-19
86
  * 30k users - 21/09/2017