]> git.wh0rd.org - tt-rss.git/blob - lib/dijit/_PaletteMixin.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dijit / _PaletteMixin.js.uncompressed.js
1 define("dijit/_PaletteMixin", [
2 "dojo/_base/declare", // declare
3 "dojo/dom-attr", // domAttr.set
4 "dojo/dom-class", // domClass.add domClass.remove
5 "dojo/dom-construct", // domConstruct.create domConstruct.place
6 "dojo/_base/event", // event.stop
7 "dojo/keys", // keys
8 "dojo/_base/lang", // lang.getObject
9 "./_CssStateMixin",
10 "./focus",
11 "./typematic"
12 ], function(declare, domAttr, domClass, domConstruct, event, keys, lang, _CssStateMixin, focus, typematic){
13
14 // module:
15 // dijit/_PaletteMixin
16
17 return declare("dijit._PaletteMixin", [_CssStateMixin], {
18 // summary:
19 // A keyboard accessible palette, for picking a color/emoticon/etc.
20 // description:
21 // A mixin for a grid showing various entities, so the user can pick a certain entity.
22
23 // defaultTimeout: Number
24 // Number of milliseconds before a held key or button becomes typematic
25 defaultTimeout: 500,
26
27 // timeoutChangeRate: Number
28 // Fraction of time used to change the typematic timer between events
29 // 1.0 means that each typematic event fires at defaultTimeout intervals
30 // Less than 1.0 means that each typematic event fires at an increasing faster rate
31 timeoutChangeRate: 0.90,
32
33 // value: String
34 // Currently selected color/emoticon/etc.
35 value: "",
36
37 // _selectedCell: [private] Integer
38 // Index of the currently selected cell. Initially, none selected
39 _selectedCell: -1,
40
41 /*=====
42 // _currentFocus: [private] DomNode
43 // The currently focused cell (if the palette itself has focus), or otherwise
44 // the cell to be focused when the palette itself gets focus.
45 // Different from value, which represents the selected (i.e. clicked) cell.
46 _currentFocus: null,
47 =====*/
48
49 /*=====
50 // _xDim: [protected] Integer
51 // This is the number of cells horizontally across.
52 _xDim: null,
53 =====*/
54
55 /*=====
56 // _yDim: [protected] Integer
57 // This is the number of cells vertically down.
58 _yDim: null,
59 =====*/
60
61 // tabIndex: String
62 // Widget tab index.
63 tabIndex: "0",
64
65 // cellClass: [protected] String
66 // CSS class applied to each cell in the palette
67 cellClass: "dijitPaletteCell",
68
69 // dyeClass: [protected] Constructor
70 // Constructor for Object created for each cell of the palette.
71 // dyeClass should implements dijit.Dye interface
72 dyeClass: null,
73
74 // summary: String
75 // Localized summary for the palette table
76 summary: '',
77 _setSummaryAttr: "paletteTableNode",
78
79 _dyeFactory: function(value /*===== , row, col, title =====*/){
80 // summary:
81 // Return instance of dijit.Dye for specified cell of palette
82 // tags:
83 // extension
84
85 // Remove string support for 2.0
86 var dyeClassObj = typeof this.dyeClass == "string" ? lang.getObject(this.dyeClass) : this.dyeClass;
87 return new dyeClassObj(value);
88 },
89
90 _preparePalette: function(choices, titles) {
91 // summary:
92 // Subclass must call _preparePalette() from postCreate(), passing in the tooltip
93 // for each cell
94 // choices: String[][]
95 // id's for each cell of the palette, used to create Dye JS object for each cell
96 // titles: String[]
97 // Localized tooltip for each cell
98
99 this._cells = [];
100 var url = this._blankGif;
101
102 this.connect(this.gridNode, "ondijitclick", "_onCellClick");
103
104 for(var row=0; row < choices.length; row++){
105 var rowNode = domConstruct.create("tr", {tabIndex: "-1"}, this.gridNode);
106 for(var col=0; col < choices[row].length; col++){
107 var value = choices[row][col];
108 if(value){
109 var cellObject = this._dyeFactory(value, row, col, titles[value]);
110
111 var cellNode = domConstruct.create("td", {
112 "class": this.cellClass,
113 tabIndex: "-1",
114 title: titles[value],
115 role: "gridcell"
116 }, rowNode);
117
118 // prepare cell inner structure
119 cellObject.fillCell(cellNode, url);
120
121 cellNode.idx = this._cells.length;
122
123 // save cell info into _cells
124 this._cells.push({node:cellNode, dye:cellObject});
125 }
126 }
127 }
128 this._xDim = choices[0].length;
129 this._yDim = choices.length;
130
131 // Now set all events
132 // The palette itself is navigated to with the tab key on the keyboard
133 // Keyboard navigation within the Palette is with the arrow keys
134 // Spacebar selects the cell.
135 // For the up key the index is changed by negative the x dimension.
136
137 var keyIncrementMap = {
138 UP_ARROW: -this._xDim,
139 // The down key the index is increase by the x dimension.
140 DOWN_ARROW: this._xDim,
141 // Right and left move the index by 1.
142 RIGHT_ARROW: this.isLeftToRight() ? 1 : -1,
143 LEFT_ARROW: this.isLeftToRight() ? -1 : 1
144 };
145 for(var key in keyIncrementMap){
146 this.own(
147 typematic.addKeyListener(
148 this.domNode,
149 {charOrCode:keys[key], ctrlKey:false, altKey:false, shiftKey:false},
150 this,
151 function(){
152 var increment = keyIncrementMap[key];
153 return function(count){ this._navigateByKey(increment, count); };
154 }(),
155 this.timeoutChangeRate,
156 this.defaultTimeout
157 )
158 );
159 }
160 },
161
162 postCreate: function(){
163 this.inherited(arguments);
164
165 // Set initial navigable node.
166 this._setCurrent(this._cells[0].node);
167 },
168
169 focus: function(){
170 // summary:
171 // Focus this widget. Puts focus on the most recently focused cell.
172
173 // The cell already has tabIndex set, just need to set CSS and focus it
174 focus.focus(this._currentFocus);
175 },
176
177 _onCellClick: function(/*Event*/ evt){
178 // summary:
179 // Handler for click, enter key & space key. Selects the cell.
180 // evt:
181 // The event.
182 // tags:
183 // private
184
185 var target = evt.target;
186
187 // Find TD associated with click event. For ColorPalette user likely clicked IMG inside of TD
188 while(target.tagName != "TD"){
189 if(!target.parentNode || target == this.gridNode){ // probably can never happen, but just in case
190 return;
191 }
192 target = target.parentNode;
193 }
194
195 var value = this._getDye(target).getValue();
196
197 // First focus the clicked cell, and then send onChange() notification.
198 // onChange() (via _setValueAttr) must be after the focus call, because
199 // it may trigger a refocus to somewhere else (like the Editor content area), and that
200 // second focus should win.
201 this._setCurrent(target);
202 focus.focus(target);
203 this._setValueAttr(value, true);
204
205 event.stop(evt);
206 },
207
208 _setCurrent: function(/*DomNode*/ node){
209 // summary:
210 // Sets which node is the focused cell.
211 // description:
212 // At any point in time there's exactly one
213 // cell with tabIndex != -1. If focus is inside the palette then
214 // focus is on that cell.
215 //
216 // After calling this method, arrow key handlers and mouse click handlers
217 // should focus the cell in a setTimeout().
218 // tags:
219 // protected
220 if("_currentFocus" in this){
221 // Remove tabIndex on old cell
222 domAttr.set(this._currentFocus, "tabIndex", "-1");
223 }
224
225 // Set tabIndex of new cell
226 this._currentFocus = node;
227 if(node){
228 domAttr.set(node, "tabIndex", this.tabIndex);
229 }
230 },
231
232 _setValueAttr: function(value, priorityChange){
233 // summary:
234 // This selects a cell. It triggers the onChange event.
235 // value: String
236 // Value of the cell to select
237 // tags:
238 // protected
239 // priorityChange: Boolean?
240 // Optional parameter used to tell the select whether or not to fire
241 // onChange event.
242
243 // clear old selected cell
244 if(this._selectedCell >= 0){
245 domClass.remove(this._cells[this._selectedCell].node, this.cellClass + "Selected");
246 }
247 this._selectedCell = -1;
248
249 // search for cell matching specified value
250 if(value){
251 for(var i = 0; i < this._cells.length; i++){
252 if(value == this._cells[i].dye.getValue()){
253 this._selectedCell = i;
254 domClass.add(this._cells[i].node, this.cellClass + "Selected");
255 break;
256 }
257 }
258 }
259
260 // record new value, or null if no matching cell
261 this._set("value", this._selectedCell >= 0 ? value : null);
262
263 if(priorityChange || priorityChange === undefined){
264 this.onChange(value);
265 }
266 },
267
268 onChange: function(/*===== value =====*/){
269 // summary:
270 // Callback when a cell is selected.
271 // value: String
272 // Value corresponding to cell.
273 },
274
275 _navigateByKey: function(increment, typeCount){
276 // summary:
277 // This is the callback for typematic.
278 // It changes the focus and the highlighed cell.
279 // increment:
280 // How much the key is navigated.
281 // typeCount:
282 // How many times typematic has fired.
283 // tags:
284 // private
285
286 // typecount == -1 means the key is released.
287 if(typeCount == -1){ return; }
288
289 var newFocusIndex = this._currentFocus.idx + increment;
290 if(newFocusIndex < this._cells.length && newFocusIndex > -1){
291 var focusNode = this._cells[newFocusIndex].node;
292 this._setCurrent(focusNode);
293
294 // Actually focus the node, for the benefit of screen readers.
295 // Use defer because IE doesn't like changing focus inside of an event handler
296 this.defer(lang.hitch(focus, "focus", focusNode));
297 }
298 },
299
300 _getDye: function(/*DomNode*/ cell){
301 // summary:
302 // Get JS object for given cell DOMNode
303
304 return this._cells[cell.idx].dye;
305 }
306 });
307
308 /*=====
309 declare("dijit.Dye",
310 null,
311 {
312 // summary:
313 // Interface for the JS Object associated with a palette cell (i.e. DOMNode)
314
315 constructor: function(alias, row, col){
316 // summary:
317 // Initialize according to value or alias like "white"
318 // alias: String
319 },
320
321 getValue: function(){
322 // summary:
323 // Return "value" of cell; meaning of "value" varies by subclass.
324 // description:
325 // For example color hex value, emoticon ascii value etc, entity hex value.
326 },
327
328 fillCell: function(cell, blankGif){
329 // summary:
330 // Add cell DOMNode inner structure
331 // cell: DomNode
332 // The surrounding cell
333 // blankGif: String
334 // URL for blank cell image
335 }
336 }
337 );
338 =====*/
339
340 });