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

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: Fixed restart, renamed WebKit 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 sections = [];
6 7
7 Galore.view = { 8 var settings = {}
8 /** @constructor */ 9 settings.priority = "0";
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 10
29 addNotificationButton: function(sectionTitle, 11 function onMainWindowClosed() {
30 buttonTitle, 12 mainWindow = null;
31 iconUrl, 13 sections = [];
32 onClick) { 14 }
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 15
43 showWindow: function() { 16 function createAppWindow(onLoad) {
44 if (this.window) 17 chrome.app.window.create('window.html', {
45 this.window.show(); 18 id: 'window',
46 }, 19 defaultWidth: 440, minWidth: 440, maxWidth: 840,
20 defaultHeight: 640, minHeight: 640, maxHeight: 940,
21 hidden: true
22 }, function(w) {
23 mainWindow = w;
24 mainWindow.contentWindow.onload = function() {
25 setButtonHandlers();
26 getElement("body").dataset.priority = settings.priority;
27 onLoad();
28 };
29 mainWindow.onClosed.addListener(onMainWindowClosed)
30 });
31 }
47 32
48 logEvent: function(message) { 33 function addNotificationButton(sectionTitle,
49 var event = this.getElement_('#templates .event').cloneNode(true); 34 buttonTitle,
50 event.textContent = message; 35 iconUrl,
51 this.getElement_('#events-scroll').appendChild(event).scrollIntoView(); 36 onClickHandler) {
52 }, 37 var button = getElement('#templates .notification').cloneNode(true);
38 var image = button.querySelector('img');
39 image.src = iconUrl;
40 image.alt = buttonTitle;
41 button.name = buttonTitle;
42 button.onclick = onClickHandler;
43 getSection(sectionTitle).appendChild(button);
44 }
53 45
54 logError: function(message) { 46 function showWindow() {
55 var events = this.getElement_('#events-scroll'); 47 if (mainWindow)
56 var error = this.getElement_('#templates .error').cloneNode(true); 48 mainWindow.show();
57 error.textContent = message; 49 }
58 events.appendChild(error).scrollIntoView();
59 },
60 50
61 /** @private */ 51 function logEvent(message) {
62 onLoad_: function() { 52 var event = getElement('#templates .event').cloneNode(true);
63 this.dataset = this.window.contentWindow.document.body.dataset; 53 event.textContent = message;
64 this.dataset.priority = this.settings.priority || '0'; 54 getElement('#events').appendChild(event).scrollIntoView();
65 this.addListener_('body', 'mousedown', 'onBodyMouseDown_'); 55 }
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 56
78 /** 57 function logError(message) {
79 * Handling our own mouse events is fun! It also allows us to keep the cursor 58 var events = getElement('#events');
80 * appropriately indicating whether a button press or window drag is happening 59 var error = getElement('#templates .error').cloneNode(true);
81 * or will happen on mousedown. As a bonus, it allows button to have a 60 error.textContent = message;
82 * highlight-as-you-drag behavior similar to menu items. 61 events.appendChild(error).scrollIntoView();
83 * 62 }
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 63
94 /** 64 function setButtonHandlers() {
95 * See the comment for onButtonMouseDown_() above. 65 setButtonAction('.priority', changePriority);
96 * 66 setButtonAction('#clear-events', clearEvents);
97 * @private */ 67 setButtonAction('#record', onRecord);
98 onButtonMouseMove_: function(event) { 68 setButtonAction('#pause', onPause);
99 // Buttons that support dragging add this as a listener to their mousemove 69 setButtonAction('#stop', onStop);
100 // events so a flag can be set during dragging to prevent their actions from 70 setButtonAction('#play', onPlay);
101 // being fired by the mouseup event that completes the dragging. 71 }
102 this.dragging = true;
103 },
104 72
105 /** 73 function setRecorderStatusText(text) {
106 * See the comment for onButtonMouseDown_() above. 74 getElement("#recording-status").innerText = text;
107 * 75 }
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 76
115 /** 77 function updateRecordingStatsDisplay(text) {
116 * See the comment for onButtonMouseDown_() above. 78 getElement("#recording-stats").innerText = text;
117 * 79 }
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 80
125 /** 81 function changePriority(event) {
126 * See the comment for onButtonMouseDown_() above. 82 settings.priority = event.currentTarget.dataset.priority || '0';
127 * 83 getElement("body").dataset.priority = settings.priority;
128 * @private */ 84 }
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 85
140 /** 86 function clearEvents() {
141 * See the comment for onButtonMouseDown_() above. 87 var events = getElement('#events');
142 * 88 while (events.lastChild)
143 * @private */ 89 events.removeChild(events.lastChild);
144 onBodyMouseUp_: function(event) { 90 }
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 91
151 /** @private */ 92 function getSection(title) {
152 onBodyMouseDown_: function(event) { 93 sections[title] = (sections[title] || makeSection(title));
153 // Prevents the cursor from becoming a text cursor during drags. 94 return sections[title];
154 if (window.getComputedStyle(event.target).cursor != 'text') 95 }
155 event.preventDefault();
156 },
157 96
158 /** @private */ 97 function makeSection(title) {
159 changePriority_: function(event) { 98 var section = getElement('#templates .section').cloneNode(true);
160 this.settings.priority = event.currentTarget.dataset.priority || '0'; 99 section.querySelector('span').textContent = title;
161 this.dataset.priority = this.settings.priority; 100 return getElement('#notifications').appendChild(section);
162 if (this.onsettings) 101 }
163 this.onsettings.call(this, this.settings);
164 },
165 102
166 /** @private */ 103 function setButtonAction(elements, action) {
167 toggleMenu_: function() { 104 getElements(elements).forEach(function(element) {
168 this.dataset.popup = String(this.dataset.popup != 'true'); 105 element.onclick = action;
169 }, 106 });
107 }
170 108
171 /** @private */ 109 function getElement(element) {
172 clearEvents_: function() { 110 return getElements(element)[0];
173 var events = this.getElement_('#events-scroll'); 111 }
174 while (events.lastChild)
175 events.removeChild(events.lastChild);
176 this.dataset.popup = 'false';
177 },
178 112
179 /** @private */ 113 function getElements(elements) {
180 getSection_: function(title) { 114 if (typeof elements === 'string')
181 this.sections[title] = (this.sections[title] || this.makeSection_(title)); 115 elements = mainWindow.contentWindow.document.querySelectorAll(elements);
182 return this.sections[title]; 116 if (String(elements) === '[object NodeList]')
183 }, 117 elements = Array.prototype.slice.call(elements);
184 118 return Array.isArray(elements) ? elements : [elements];
185 /** @private */ 119 }
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