05c3cc9df77e7590a8160b23212b9b1a4473454e
[platform/framework/web/web-ui-fw.git] / src / widgets / colorpicker / js / jquery.mobile.tizen.colorpicker.js
1 /*
2  * jQuery Mobile Widget @VERSION
3  *
4  * This software is licensed under the MIT licence (as defined by the OSI at
5  * http://www.opensource.org/licenses/mit-license.php)
6  * 
7  * ***************************************************************************
8  * Copyright (C) 2011 by Intel Corporation Ltd.
9  * 
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  * 
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  * 
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  * ***************************************************************************
28  *
29  * Authors: Gabriel Schulhof <gabriel.schulhof@intel.com>
30  */
31
32 // Displays a 2D hue/saturation spectrum and a lightness slider.
33 //
34 // To apply, add the attribute data-role="colorpicker" to a <div>
35 // element inside a page. Alternatively, call colorpicker() 
36 // on an element (see below).
37 //
38 // Options:
39 //     color: String; can be specified in html using the
40 //            data-color="#ff00ff" attribute or when constructed
41 //                $("#mycolorpicker").colorpicker({ color: "#ff00ff" });
42 //            where the html might be :
43 //                <div id="mycolorpicker"/>
44
45 (function( $, undefined ) {
46
47 $.widget( "tizen.colorpicker", $.tizen.colorwidget, {
48     options: {
49         initSelector: ":jqmData(role='colorpicker')"
50     },
51
52     _htmlProto: {
53         ui: {
54             clrpicker: "#colorpicker",
55             hs: {
56                 hueGradient: "#colorpicker-hs-hue-gradient",
57                 gradient:    "#colorpicker-hs-sat-gradient",
58                 eventSource: "[data-event-source='hs']",
59                 valMask:     "#colorpicker-hs-val-mask",
60                 selector:    "#colorpicker-hs-selector"
61             },
62             l: {
63                 gradient:    "#colorpicker-l-gradient",
64                 eventSource: "[data-event-source='l']",
65                 selector:    "#colorpicker-l-selector"
66             }
67         }
68     },
69
70     _create: function() {
71         var self = this;
72
73         this.element
74             .css("display", "none")
75             .after(this._ui.clrpicker);
76
77         this._ui.hs.hueGradient.huegradient();
78
79         $.extend( self, {
80             dragging: false,
81             draggingHS: false,
82             selectorDraggingOffset: {
83                 x : -1,
84                 y : -1
85             },
86             dragging_hsl: undefined
87         });
88
89         $( document )
90             .bind( "vmousemove", function( event ) {
91                 if ( self.dragging ) {
92                     event.stopPropagation();
93                     event.preventDefault();
94                 }
95             })
96             .bind( "vmouseup", function( event ) {
97                 if ( self.dragging )
98                     self.dragging = false;
99             });
100
101         this._bindElements("hs");
102         this._bindElements("l");
103     },
104
105     _bindElements: function(which) {
106         var self = this,
107             stopDragging = function(event) {
108                 self.dragging = false;
109                 event.stopPropagation();
110                 event.preventDefault();
111             };
112
113         this._ui[which].eventSource
114             .bind( "vmousedown mousedown", function (event) { self._handleMouseDown(event, which, false); })
115             .bind( "vmousemove"          , function (event) { self._handleMouseMove(event, which, false); })
116             .bind( "vmouseup"            , stopDragging);
117
118         this._ui[which].selector
119             .bind( "vmousedown mousedown", function (event) { self._handleMouseDown(event, which, true); })
120             .bind( "touchmove vmousemove", function (event) { self._handleMouseMove(event, which, true); })
121             .bind( "vmouseup"            , stopDragging);
122     },
123
124     _handleMouseDown: function(event, containerStr, isSelector) {
125         var coords = $.mobile.tizen.targetRelativeCoordsFromEvent(event),
126             widgetStr = isSelector ? "selector" : "eventSource";
127         if ((coords.x >= 0 && coords.x <= this._ui[containerStr][widgetStr].width() &&
128              coords.y >= 0 && coords.y <= this._ui[containerStr][widgetStr].height()) || isSelector) {
129             this.dragging = true;
130             this.draggingHS = ("hs" === containerStr);
131
132             if (isSelector) {
133                 this.selectorDraggingOffset.x = coords.x;
134                 this.selectorDraggingOffset.y = coords.y;
135             }
136
137             this._handleMouseMove(event, containerStr, isSelector, coords);
138         }
139     },
140
141     _handleMouseMove: function(event, containerStr, isSelector, coords) {
142         if (this.dragging &&
143             !(( this.draggingHS && containerStr === "l") || 
144               (!this.draggingHS && containerStr === "hs"))) {
145             coords = (coords || $.mobile.tizen.targetRelativeCoordsFromEvent(event));
146
147             if (this.draggingHS) {
148                 var potential_h = isSelector
149                       ? this.dragging_hsl[0] / 360 + (coords.x - this.selectorDraggingOffset.x) / this._ui[containerStr].eventSource.width()
150                       : coords.x / this._ui[containerStr].eventSource.width(),
151                     potential_s = isSelector
152                       ? this.dragging_hsl[1]       + (coords.y - this.selectorDraggingOffset.y) / this._ui[containerStr].eventSource.height()
153                       : coords.y / this._ui[containerStr].eventSource.height();
154
155                 this.dragging_hsl[0] = Math.min(1.0, Math.max(0.0, potential_h)) * 360;
156                 this.dragging_hsl[1] = Math.min(1.0, Math.max(0.0, potential_s));
157             }
158             else {
159                 var potential_l = isSelector
160                       ? this.dragging_hsl[2]       + (coords.y - this.selectorDraggingOffset.y) / this._ui[containerStr].eventSource.height()
161                       : coords.y / this._ui[containerStr].eventSource.height();
162
163                 this.dragging_hsl[2] = Math.min(1.0, Math.max(0.0, potential_l));
164             }
165
166             if (!isSelector) {
167                 this.selectorDraggingOffset.x = Math.ceil(this._ui[containerStr].selector.outerWidth()  / 2.0);
168                 this.selectorDraggingOffset.y = Math.ceil(this._ui[containerStr].selector.outerHeight() / 2.0);
169             }
170
171             this._updateSelectors(this.dragging_hsl);
172             event.stopPropagation();
173             event.preventDefault();
174         }
175     },
176
177     _updateSelectors: function(hsl) {
178         var clr = $.tizen.colorwidget.prototype._setElementColor.call(this, this._ui.hs.selector, [hsl[0], 1.0 - hsl[1], hsl[2]], "background").clr,
179             gray = $.tizen.colorwidget.clrlib.RGBToHTML([hsl[2], hsl[2], hsl[2]]);
180
181         this._ui.hs.valMask.css((hsl[2] < 0.5)
182             ? { background : "#000000" , opacity : (1.0 - hsl[2] * 2.0)   }
183             : { background : "#ffffff" , opacity : ((hsl[2] - 0.5) * 2.0) });
184         this._ui.hs.selector.css({
185             left       : (hsl[0] / 360 * this._ui.hs.eventSource.width()),
186             top        : (hsl[1] * this._ui.hs.eventSource.height()),
187         });
188         this._ui.l.selector.css({
189             top        : (hsl[2] * this._ui.l.eventSource.height()),
190             background : gray
191         });
192         $.tizen.colorwidget.prototype._setColor.call(this, clr);
193     },
194
195     widget: function() { return this._ui.clrpicker; },
196
197     _setDisabled: function(value) {
198         $.tizen.widgetex.prototype._setDisabled.call(this, value);
199         this._ui.hs.hueGradient.huegradient("option", "disabled", value);
200         this._ui.clrpicker[value ? "addClass" : "removeClass"]("ui-disabled");
201         $.tizen.colorwidget.prototype._displayDisabledState.call(this, this._ui.clrpicker);
202     },
203
204     _setColor: function(clr) {
205         if ($.tizen.colorwidget.prototype._setColor.call(this, clr)) {
206             this.dragging_hsl = $.tizen.colorwidget.clrlib.RGBToHSL($.tizen.colorwidget.clrlib.HTMLToRGB(this.options.color));
207             this.dragging_hsl[1] = 1.0 - this.dragging_hsl[1];
208             this._updateSelectors(this.dragging_hsl);
209         }
210     }
211 });
212
213 $(document).bind("pagecreate create", function(e) {
214     $($.tizen.colorpicker.prototype.options.initSelector, e.target)
215         .not(":jqmData(role='none'), :jqmData(role='nojs')")
216         .colorpicker();
217 });
218
219 })(jQuery);