Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: chrome/test/data/extensions/api_test/notifications/galore/app/view.js

Issue 315053006: Refactor Notifications Galore to simplify, amke more hackable and add 'recording'. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 var Galore = Galore || {}; 5 var mainWindow;
6 var settings = {}
7 settings.priority = "0";
8 var sections = [];
6 9
7 Galore.view = { 10 function createAppWindow(onLoad) {
8 /** @constructor */ 11 chrome.app.window.create('window.html', {
9 create: function(settings, onload, onSettingsChange) { 12 id: 'window',
10 var view = Object.create(this); 13 defaultWidth: 440, minWidth: 440, maxWidth: 840,
11 view.actions = []; 14 defaultHeight: 640, minHeight: 640, maxHeight: 940,
12 view.sections = {}; 15 hidden: true
13 view.settings = settings; 16 }, function(w) {
14 view.onload = onload; 17 mainWindow = w;
15 view.onsettings = onSettingsChange; 18 mainWindow.contentWindow.onload = function() {
16 chrome.app.window.create('window.html', { 19 setButtonHandlers();
17 id: 'window', 20 onLoad();
18 frame: 'none', 21 };
19 defaultWidth: 440, minWidth: 440, maxWidth: 440, 22 });
20 defaultHeight: 640, minHeight: 640, maxHeight: 640, 23 }
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 24
29 addNotificationButton: function(sectionTitle, 25 function addNotificationButton(sectionTitle,
30 buttonTitle, 26 buttonTitle,
31 iconUrl, 27 iconUrl,
32 onClick) { 28 onClickHandler) {
33 var button = this.getElement_('#templates .notification').cloneNode(true); 29 var button = getElement('#templates .notification').cloneNode(true);
34 var image = button.querySelector('img'); 30 var image = button.querySelector('img');
35 image.src = iconUrl; 31 image.src = iconUrl;
36 image.alt = buttonTitle; 32 image.alt = buttonTitle;
37 button.name = buttonTitle; 33 button.name = buttonTitle;
38 button.dataset.actionIndex = this.actions.push(onClick) - 1; 34 button.onclick = onClickHandler;
39 this.addButtonListeners_(button); 35 getSection(sectionTitle).appendChild(button);
40 this.getSection_(sectionTitle).appendChild(button); 36 }
41 },
42 37
43 showWindow: function() { 38 function showWindow() {
44 if (this.window) 39 if (mainWindow)
45 this.window.show(); 40 mainWindow.show();
46 }, 41 }
47 42
48 logEvent: function(message) { 43 function logEvent(message) {
49 var event = this.getElement_('#templates .event').cloneNode(true); 44 var event = getElement('#templates .event').cloneNode(true);
50 event.textContent = message; 45 event.textContent = message;
51 this.getElement_('#events-scroll').appendChild(event).scrollIntoView(); 46 getElement('#events').appendChild(event).scrollIntoView();
52 }, 47 }
53 48
54 logError: function(message) { 49 function logError(message) {
55 var events = this.getElement_('#events-scroll'); 50 var events = getElement('#events');
56 var error = this.getElement_('#templates .error').cloneNode(true); 51 var error = getElement('#templates .error').cloneNode(true);
57 error.textContent = message; 52 error.textContent = message;
58 events.appendChild(error).scrollIntoView(); 53 events.appendChild(error).scrollIntoView();
59 }, 54 }
60 55
61 /** @private */ 56 function setButtonHandlers() {
62 onLoad_: function() { 57 setButtonAction('.priority', changePriority);
63 this.dataset = this.window.contentWindow.document.body.dataset; 58 setButtonAction('#clear-events', clearEvents);
64 this.dataset.priority = this.settings.priority || '0'; 59 setButtonAction('#record', onRecord);
65 this.addListener_('body', 'mousedown', 'onBodyMouseDown_'); 60 setButtonAction('#pause', onPause);
66 this.addListener_('body', 'mouseup', 'onBodyMouseUp_'); 61 setButtonAction('#stop', onStop);
67 this.addListener_('#shadow', 'mousemove', 'onButtonMouseMove_'); 62 setButtonAction('#play', onPlay);
68 this.addButtonListeners_('button, #shadow'); 63 }
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 64
78 /** 65 function setRecorderStatusText(text) {
79 * Handling our own mouse events is fun! It also allows us to keep the cursor 66 getElement("#recording-status").innerText = text;
80 * appropriately indicating whether a button press or window drag is happening 67 }
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 68
94 /** 69 function changePriority(event) {
95 * See the comment for onButtonMouseDown_() above. 70 settings.priority = event.currentTarget.dataset.priority || '0';
96 * 71 getElement("body").dataset.priority = settings.priority;
97 * @private */ 72 }
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 73
105 /** 74 function clearEvents() {
106 * See the comment for onButtonMouseDown_() above. 75 var events = getElement('#events');
107 * 76 while (events.lastChild)
108 * @private */ 77 events.removeChild(events.lastChild);
109 onButtonMouseOut_: function(event) { 78 }
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 79
115 /** 80 function getSection(title) {
116 * See the comment for onButtonMouseDown_() above. 81 sections[title] = (sections[title] || makeSection(title));
117 * 82 return sections[title];
118 * @private */ 83 }
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 84
125 /** 85 function makeSection(title) {
126 * See the comment for onButtonMouseDown_() above. 86 var section = getElement('#templates .section').cloneNode(true);
127 * 87 section.querySelector('span').textContent = title;
128 * @private */ 88 return getElement('#notifications').appendChild(section);
129 onButtonMouseUp_: function(event) { 89 }
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 90
140 /** 91 function setButtonAction(elements, action) {
141 * See the comment for onButtonMouseDown_() above. 92 getElements(elements).forEach(function(element) {
142 * 93 element.onclick = action;
143 * @private */ 94 });
144 onBodyMouseUp_: function(event) { 95 }
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 96
151 /** @private */ 97 function getElement(element) {
152 onBodyMouseDown_: function(event) { 98 return getElements(element)[0];
153 // Prevents the cursor from becoming a text cursor during drags. 99 }
154 if (window.getComputedStyle(event.target).cursor != 'text')
155 event.preventDefault();
156 },
157 100
158 /** @private */ 101 function getElements(elements) {
159 changePriority_: function(event) { 102 if (typeof elements === 'string')
160 this.settings.priority = event.currentTarget.dataset.priority || '0'; 103 elements = mainWindow.contentWindow.document.querySelectorAll(elements);
161 this.dataset.priority = this.settings.priority; 104 if (String(elements) === '[object NodeList]')
162 if (this.onsettings) 105 elements = Array.prototype.slice.call(elements);
163 this.onsettings.call(this, this.settings); 106 return Array.isArray(elements) ? elements : [elements];
164 }, 107 }
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698