- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / api_test / notifications / galore / app / view.js
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var Galore = Galore || {};
6
7 Galore.view = {
8   /** @constructor */
9   create: function(settings, onload, onSettingsChange) {
10     var view = Object.create(this);
11     view.actions = [];
12     view.sections = {};
13     view.settings = settings;
14     view.onload = onload;
15     view.onsettings = onSettingsChange;
16     chrome.app.window.create('window.html', {
17       id: 'window',
18       frame: 'none',
19       defaultWidth: 440, minWidth: 440, maxWidth: 440,
20       defaultHeight: 640, minHeight: 640, maxHeight: 640,
21       hidden: true
22     }, function(appWindow) {
23       view.window = appWindow;
24       view.addListener_(appWindow.contentWindow, 'load', 'onLoad_');
25     }.bind(this));
26     return view;
27   },
28
29   addNotificationButton: function(sectionTitle,
30                                   buttonTitle,
31                                   iconUrl,
32                                   onClick) {
33     var button = this.getElement_('#templates .notification').cloneNode(true);
34     var image = button.querySelector('img');
35     image.src = iconUrl;
36     image.alt = buttonTitle;
37     button.name = buttonTitle;
38     button.dataset.actionIndex = this.actions.push(onClick) - 1;
39     this.addButtonListeners_(button);
40     this.getSection_(sectionTitle).appendChild(button);
41   },
42
43   showWindow: function() {
44     if (this.window)
45       this.window.show();
46   },
47
48   logEvent: function(message) {
49     var event = this.getElement_('#templates .event').cloneNode(true);
50     event.textContent = message;
51     this.getElement_('#events-scroll').appendChild(event).scrollIntoView();
52   },
53
54   logError: function(message) {
55     var events = this.getElement_('#events-scroll');
56     var error = this.getElement_('#templates .error').cloneNode(true);
57     error.textContent = message;
58     events.appendChild(error).scrollIntoView();
59   },
60
61   /** @private */
62   onLoad_: function() {
63     this.dataset = this.window.contentWindow.document.body.dataset;
64     this.dataset.priority = this.settings.priority || '0';
65     this.addListener_('body', 'mousedown', 'onBodyMouseDown_');
66     this.addListener_('body', 'mouseup', 'onBodyMouseUp_');
67     this.addListener_('#shadow', 'mousemove', 'onButtonMouseMove_');
68     this.addButtonListeners_('button, #shadow');
69     this.setButtonAction_('.priority', 'changePriority_');
70     this.setButtonAction_('#shadow', 'toggleMenu_');
71     this.setButtonAction_('#clear-events', 'clearEvents_');
72     this.setButtonAction_('#show-menu', 'toggleMenu_');
73     this.setButtonAction_('#close', 'close', this.window.contentWindow);
74     if (this.onload)
75       this.onload.call(this, this);
76   },
77
78   /**
79    * Handling our own mouse events is fun! It also allows us to keep the cursor
80    * appropriately indicating whether a button press or window drag is happening
81    * or will happen on mousedown. As a bonus, it allows button to have a
82    * highlight-as-you-drag behavior similar to menu items.
83    *
84    * @private */
85   onButtonMouseDown_: function(event) {
86     // Record the fact that a button in this button's group is active, which
87     // allows onButtonMouseUp_ to do the right thing and CSS rules to correctly
88     // set cursor types and button highlighting.
89     var element = event.currentTarget;
90     this.dataset.active = element.classList[0] || '';
91     this.dragging = false;
92   },
93
94   /**
95     * See the comment for onButtonMouseDown_() above.
96     *
97     * @private */
98   onButtonMouseMove_: function(event) {
99     // Buttons that support dragging add this as a listener to their mousemove
100     // events so a flag can be set during dragging to prevent their actions from
101     // being fired by the mouseup event that completes the dragging.
102     this.dragging = true;
103   },
104
105   /**
106     * See the comment for onButtonMouseDown_() above.
107     *
108     * @private */
109   onButtonMouseOut_: function(event) {
110     // Record the fact that the mouse is not over this button any more to allow
111     // CSS rules to stop highlighting it.
112     event.currentTarget.dataset.hover = 'false';
113   },
114
115   /**
116     * See the comment for onButtonMouseDown_() above.
117     *
118     * @private */
119   onButtonMouseOver_: function(event) {
120     // Record the fact that the mouse is over this button to allow CSS rules to
121     // highlight it if appropriate.
122     event.currentTarget.dataset.hover = 'true';
123   },
124
125   /**
126     * See the comment for onButtonMouseDown_() above.
127     *
128     * @private */
129   onButtonMouseUp_: function(event) {
130     // Send a button action if the button in which the mouseup happened is in
131     // the same group as the one in which the mousedown happened. The regular
132     // click handling which this replaces would send the action only if the
133     // mouseup happened in the same button as the mousedown.
134     var element = event.currentTarget;
135     var group = (element.classList[0] || 'x');
136     if (group == this.dataset.active && !this.dragging)
137       this.actions[element.dataset.actionIndex].call(element, event);
138   },
139
140   /**
141     * See the comment for onButtonMouseDown_() above.
142     *
143     * @private */
144   onBodyMouseUp_: function(event) {
145     // Record the fact that no button is active, which allows onButtonMouseUp_
146     // to do the right thing and CSS rules to correctly set cursor types and
147     // button highlighting.
148     this.dataset.active = '';
149   },
150
151   /** @private */
152   onBodyMouseDown_: function(event) {
153     // Prevents the cursor from becoming a text cursor during drags.
154     if (window.getComputedStyle(event.target).cursor != 'text')
155       event.preventDefault();
156   },
157
158   /** @private */
159   changePriority_: function(event) {
160     this.settings.priority = event.currentTarget.dataset.priority || '0';
161     this.dataset.priority = this.settings.priority;
162     if (this.onsettings)
163       this.onsettings.call(this, this.settings);
164   },
165
166   /** @private */
167   toggleMenu_: function() {
168     this.dataset.popup = String(this.dataset.popup != 'true');
169   },
170
171   /** @private */
172   clearEvents_: function() {
173     var events = this.getElement_('#events-scroll');
174     while (events.lastChild)
175       events.removeChild(events.lastChild);
176     this.dataset.popup = 'false';
177   },
178
179   /** @private */
180   getSection_: function(title) {
181     this.sections[title] = (this.sections[title] || this.makeSection_(title));
182     return this.sections[title];
183   },
184
185   /** @private */
186   makeSection_: function(title) {
187     var section = this.getElement_('#templates .section').cloneNode(true);
188     section.querySelector('span').textContent = title;
189     return this.getElement_('#notifications').appendChild(section);
190   },
191
192   /** @private */
193   addButtonListeners_: function(buttons) {
194     this.addListener_(buttons, 'mousedown', 'onButtonMouseDown_');
195     this.addListener_(buttons, 'mouseout', 'onButtonMouseOut_');
196     this.addListener_(buttons, 'mouseover', 'onButtonMouseOver_');
197     this.addListener_(buttons, 'mouseup', 'onButtonMouseUp_');
198   },
199
200   /** @private */
201   setButtonAction_: function(elements, action, target) {
202     var index = this.actions.push(this.bind_(action, target)) - 1;
203     this.getElements_(elements).forEach(function(element) {
204       element.dataset.actionIndex = index;
205     });
206   },
207
208   /** @private */
209   addListener_: function(elements, event, action, target) {
210     var listener = this.bind_(action, target);
211     this.getElements_(elements).forEach(function(element) {
212       element.addEventListener(event, listener);
213     });
214   },
215
216   /** @private */
217   bind_: function(action, target) {
218     return (target || this)[action].bind(target || this);
219   },
220
221   /** @private */
222   getElement_: function(element) {
223     return this.getElements_(element)[0];
224   },
225
226   /** @private */
227   getElements_: function(elements) {
228     if (typeof elements === 'string')
229       elements = this.window.contentWindow.document.querySelectorAll(elements);
230     if (String(elements) === '[object NodeList]')
231       elements = Array.prototype.slice.call(elements);
232     return Array.isArray(elements) ? elements : [elements];
233   }
234 };