Merge lp:~jamesmr/dmedia/browser-merge into lp:dmedia

Proposed by James Raymond
Status: Merged
Merged at revision: 449
Proposed branch: lp:~jamesmr/dmedia/browser-merge
Merge into: lp:dmedia
Diff against target: 470 lines (+406/-8)
3 files modified
ui/browser2.css (+143/-0)
ui/dmedia.js (+244/-2)
ui/index.html (+19/-6)
To merge this branch: bzr merge lp:~jamesmr/dmedia/browser-merge
Reviewer Review Type Date Requested Status
Jason Gerard DeRose Approve
Review via email: mp+120308@code.launchpad.net

Description of the change

Pulled the browser code from the external browser app into the main dmedia window.

To post a comment you must log in.
Revision history for this message
Jason Gerard DeRose (jderose) wrote :

I'm on Quantal testing this, but it seems rather broken. Are you sure all your files are committed?

review: Approve
lp:~jamesmr/dmedia/browser-merge updated
452. By James Raymond

Changed thumbnails to <img> from <div>

Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Looks good, things are working under Quantal now that you're using <img> instead of <div> for the thumbnails. WebKitGtk bug, it seems.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'ui/browser2.css'
2--- ui/browser2.css 1970-01-01 00:00:00 +0000
3+++ ui/browser2.css 2012-08-21 18:23:28 +0000
4@@ -0,0 +1,143 @@
5+#browser_target{
6+ position:fixed;
7+ top:40px;
8+ left:0px;
9+ right:0px;
10+ bottom:0px;
11+}
12+
13+#content {
14+ position: absolute;
15+ top: 40px;
16+ bottom: 170px;
17+ left: 0;
18+ right: 210px;
19+ background-color: black;
20+ overflow-x: auto;
21+ overflow-y: auto;
22+}
23+
24+#lower {
25+ position: absolute;
26+ height: 170px;
27+ bottom: 0;
28+ left: 0;
29+ right: 210px;
30+ overflow-x: auto;
31+ overflow-y: visible;
32+ background: -webkit-linear-gradient(top, #222, #333);
33+ border-top:1px solid #444;
34+}
35+
36+#right {
37+ position: absolute;
38+ top: 40px;
39+ bottom: 0;
40+ width: 210px;
41+ right: 0;
42+ background-color: #333;
43+ border-left: 1px solid #444;
44+ color: white;
45+ overflow-y: scroll;
46+ overflow-x: hidden;
47+ z-index: 200;
48+}
49+
50+img.thumbnail{
51+ font-size:0px;
52+ line-height:0px;
53+}
54+
55+#right .thumbnail {
56+ width: 192px;
57+ height: 108px;
58+ border: 2px solid black;
59+ border-top: 2px solid #111;
60+ overflow: hidden;
61+ background-position: center center;
62+ background-size: cover;
63+}
64+
65+#right .thumbnail.selected {
66+ border-color: #e81f3b;
67+}
68+
69+.large #content {
70+ right: 260px;
71+}
72+
73+.large #lower {
74+ right: 260px;
75+}
76+
77+.large #right {
78+ width: 260px;
79+}
80+
81+.large .thumbnail {
82+ width: 240px;
83+ height: 135px;
84+}
85+
86+#player {
87+ position: absolute;
88+ top: 0px;
89+ left: 0px;
90+ width: 100%;
91+ height: 100%;
92+}
93+
94+ul.matches {
95+ list-style: none;
96+ color: white;
97+ background: -webkit-linear-gradient(top, #666, #555);
98+ box-shadow: 0px 2px 5px 1px rgba(0,0,0,0.3);
99+ border-bottom-left-radius: 3px;
100+ border-bottom-right-radius: 3px;
101+ overflow: hidden;
102+}
103+
104+ul.matches li {
105+ padding: 0px 5px;
106+ white-space: nowrap;
107+ cursor: default;
108+ -webkit-user-select: none;
109+}
110+
111+ul.matches li:hover {
112+ background-color: rgba(255,255,255,0.2);
113+}
114+
115+ul.matches li.selected {
116+ background-color: #e81f3b;
117+}
118+
119+
120+ul.tags {
121+ font-size: 0;
122+ list-style: none;
123+
124+ height: 150px;
125+ padding: 2px;
126+}
127+
128+ul.tags li {
129+ margin-left: 4px;
130+ margin-top:4px;
131+ padding-left: 4px;
132+ background: -webkit-linear-gradient(top, #eee, #ccc);
133+ display: inline-block;
134+ cursor: default;
135+ color:#333;
136+ border-radius: 3px;
137+}
138+
139+ul.tags li a {
140+ text-decoration: none;
141+ display: inline-block;
142+ color: #d12;
143+ font-weight: bold;
144+ text-align: center;
145+ cursor: pointer;
146+ width: 1.5em;
147+}
148
149=== modified file 'ui/dmedia.js'
150--- ui/dmedia.js 2012-02-27 15:03:45 +0000
151+++ ui/dmedia.js 2012-08-21 18:23:28 +0000
152@@ -8,6 +8,9 @@
153 UI.tabinit[id] = true;
154 UI['init_' + id]();
155 }
156+ if (UI.player){
157+ UI.player.pause();
158+ }
159 },
160
161 init_import: function() {
162@@ -19,15 +22,68 @@
163 },
164
165 init_browser: function() {
166- console.log('init_browser');
167+ UI.player = $el('video', {'id': 'player'});
168+ UI.player.addEventListener('click', UI.player_click);
169+ $("content").appendChild(UI.player);
170+ UI.browser = new Browser(UI.importer.project, UI.player, 'right');
171+ //console.log('init_browser');
172 },
173
174 init_storage: function() {
175 console.log('init_storage');
176 },
177+
178+ player_click: function(event){
179+ if (!UI.player.paused) {
180+ UI.player.pause();
181+ }
182+ else {
183+ UI.player.play();
184+ }
185+ },
186
187 }
188
189+function make_tag_li(remove, doc, id) {
190+ var id = id || doc._id;
191+ var li = $el('li', {textContent: doc.value});
192+ var a = $el('a', {textContent: 'x', title: 'Click to remove tag'});
193+ li.appendChild(a);
194+ a.onclick = function() {
195+ remove(id, li);
196+ }
197+ return li;
198+}
199+
200+
201+function wheel_delta(event) {
202+ var delta = event.wheelDeltaY;
203+ if (delta == 0) {
204+ return 0;
205+ }
206+ var scale = (event.shiftKey) ? -10 : -1;
207+ return scale * (delta / Math.abs(delta));
208+}
209+
210+
211+function set_flag(div, review) {
212+ if (!review) {
213+ return;
214+ }
215+ div.appendChild(
216+ $el('img', {'src': review + '.png'})
217+ );
218+}
219+
220+
221+function reset_flag(id, review) {
222+ var div = $(id);
223+ if (!div) {
224+ return;
225+ }
226+ div.innerHTML = null;
227+ set_flag(div, review);
228+}
229
230 function Importer() {
231 this.create_button = $('create_project');
232@@ -133,7 +189,193 @@
233
234 }
235
236-
237+function Browser(project, player, items) {
238+ this.player = $(player);
239+ this.tags = $('tags');
240+ this.doc = null;
241+
242+ this.items = new Items(items);
243+ this.items.onchange = $bind(this.on_item_change, this);
244+ this.items.parent.onmousewheel = $bind(this.on_mousewheel, this);
245+
246+ this.project = project;
247+
248+ this.tagger = new Tagger(this.project, 'tag_form');
249+ this.tagger.ontag = $bind(this.on_tag, this);
250+
251+ window.addEventListener('keydown', $bind(this.on_window_keydown, this));
252+ window.addEventListener('keypress', $bind(this.on_window_keypress, this));
253+
254+ this.load_items();
255+}
256+Browser.prototype = {
257+ _review: function(value) {
258+ this.doc.review = value;
259+ this.project.db.save(this.doc);
260+ reset_flag(this.doc._id, value);
261+ },
262+
263+ accept: function() {
264+ if (!this.doc) {
265+ return;
266+ }
267+ this._review('accept');
268+ },
269+
270+ reject: function() {
271+ if (!this.doc) {
272+ return;
273+ }
274+ this._review('reject');
275+ this.next();
276+ },
277+
278+ next_needing_review: function() {
279+ var rows = this.project.db.view_sync('user', 'video_needsreview', {'limit': 1}).rows;
280+ if (rows.length == 1) {
281+ this.items.select(rows[0].id);
282+ }
283+ },
284+
285+ next: function() {
286+ this.items.next();
287+ },
288+
289+ previous: function() {
290+ this.items.previous();
291+ },
292+
293+ load_items: function() {
294+ var callback = $bind(this.on_items, this);
295+ this.project.db.view(callback, 'user', 'video');
296+ },
297+
298+ on_items: function(req) {
299+ var self = this;
300+ var callback = function(row) {
301+ var id = row.id;
302+ var child = $el('img',
303+ {
304+ 'class': 'thumbnail',
305+ 'id': row.id,
306+ 'src': self.project.att_url(row.id),
307+ //'textContent': row.id,
308+ }
309+ );
310+ child.onclick = function() {
311+ self.items.select(id);
312+ }
313+ //child.style.backgroundImage = self.project.att_css_url(row.id);
314+
315+ child.draggable = true;
316+ child.ondragstart = function(e) {
317+ e.dataTransfer.effectAllowed = 'copy';
318+ e.dataTransfer.setData('Text', self.project.db.name + "/" + id);
319+ var img = $el('img', {'src': self.project.att_url(id)});
320+ e.dataTransfer.setDragImage(img, 0, 0);
321+ }
322+
323+ if (row.value) {
324+ set_flag(child, row.value);
325+ }
326+ return child;
327+ }
328+ this.items.replace(req.read().rows, callback);
329+ this.next_needing_review();
330+ },
331+
332+ on_item_change: function(id) {
333+ if (!id) {
334+ this.doc = null;
335+ this.player.pause();
336+ this.player.src = null;
337+ return;
338+ }
339+ this.player.src = 'dmedia:' + id;
340+ this.player.play();
341+ this.tagger.reset();
342+ this.tags.innerHTML = null;
343+ this.project.db.get($bind(this.on_doc, this), id);
344+ },
345+
346+ on_doc: function(req) {
347+ this.doc = req.read();
348+ var keys = Object.keys(this.doc.tags);
349+ var remove = $bind(this.on_tag_remove, this);
350+ keys.forEach(function(key) {
351+ this.tags.appendChild
352+ (make_tag_li(remove, this.doc.tags[key], key)
353+ );
354+ }, this);
355+ },
356+
357+ on_tag: function(tag) {
358+ //console.log(tag);
359+ if (!this.doc) {
360+ return;
361+ }
362+ if (!this.doc.tags) {
363+ this.doc.tags = {};
364+ }
365+ if (!this.doc.tags[tag._id]) {
366+ var remove = $bind(this.on_tag_remove, this);
367+ $prepend(make_tag_li(remove, tag), this.tags);
368+ this.doc.tags[tag._id] = {key: tag.key, value: tag.value};
369+ }
370+ else {
371+ this.doc.tags[tag._id].key = tag.key;
372+ this.doc.tags[tag._id].value = tag.value;
373+ }
374+ this.project.db.save(this.doc);
375+ },
376+
377+ on_tag_remove: function(id, li) {
378+ this.tags.removeChild(li);
379+ if (this.doc && this.doc.tags) {
380+ delete this.doc.tags[id];
381+ this.project.db.save(this.doc);
382+ }
383+ },
384+
385+ on_mousewheel: function(event) {
386+ event.preventDefault();
387+ var delta = wheel_delta(event) * 112; // 108px height + 2px border
388+ this.items.parent.scrollTop += delta;
389+ },
390+
391+
392+ on_window_keydown: function(event) {
393+ var keyID = event.keyIdentifier;
394+ if (['Up', 'Down', 'Enter', 'U+007F'].indexOf(keyID) > -1 && !this.tagger.input.value) {
395+ event.preventDefault();
396+ event.stopPropagation();
397+ if (keyID == 'Up') {
398+ this.previous();
399+ }
400+ else if (keyID == 'Down') {
401+ this.next();
402+ }
403+ else if (keyID == 'Enter') {
404+ this.accept();
405+ }
406+ else { // Delete
407+ this.reject();
408+ }
409+ }
410+ },
411+
412+ on_window_keypress: function(event) {
413+ //console.log(['window keypress', event.which, event.keyCode].join(', '));
414+ if (this.tagger.isfocused) {
415+ return;
416+ }
417+ // Don't focus on Backspace, Enter, Spacebar, or Delete
418+ if ([8, 13, 32, 127].indexOf(event.keyCode) == -1) {
419+ this.tagger.focus();
420+ }
421+ },
422+
423+}
424
425 window.onload = function() {
426 UI.progressbar = new ProgressBar('progress');
427
428=== modified file 'ui/index.html'
429--- ui/index.html 2012-04-24 11:41:08 +0000
430+++ ui/index.html 2012-08-21 18:23:28 +0000
431@@ -4,6 +4,7 @@
432 <link rel="stylesheet" href="grid.css"></link>
433 <link rel="stylesheet" href="style.css"></link>
434 <link rel="stylesheet" href="common.css"></link>
435+ <link rel="stylesheet" href="browser2.css"></link>
436 <script src="/_apps/userwebkit/couch.js"></script>
437 <script src="/_apps/userwebkit/base.js"></script>
438 <script src="common.js"></script>
439@@ -65,13 +66,25 @@
440 </div>
441 </div>
442 <div id="browser_target" class="hide">
443- <div class="grid_row darkbar">
444- <select id="browser_projects" class="grid_1"></select>
445- <input id="tag" class="grid_2" type="text"></input>
446- <ul id="tag_matches"></ul>
447+ <div class="grid_row darkbar">
448+ <select id="browser_projects" class="grid_1"></select>
449+ <input id="tag" class="grid_2" type="text"></input>
450+ <ul id="tag_matches"></ul>
451+ </div>
452+ <div id="content"></div>
453+
454+ <form id="tag_form">
455+ <div id="lower" class="grid_row">
456+ <div id="add_tag" class="grid_3 grid_cell">
457+ <input id="tag_value"></input>
458+ <ul class="matches" id="tag_matches"></ul>
459+ </div>
460+ <button id="tag_button" class="grid_1 arrow" disabled>Tag &rarr;</button>
461+ <ul id="tags" class="grid_5 tags inset"></ul>
462 </div>
463- <video width="640" height="360" id="player"></video>
464- <div id="tray"></div>
465+ </form>
466+
467+ <div id="right"></div>
468 </div>
469 <div id="storage_target" class="hide">
470 <div class="grid_row darkbar">

Subscribers

People subscribed via source and target branches

to all changes: