Merge lp:~mttronchetti/novacut/container into lp:novacut
- container
- Merge into trunk
Proposed by
Matteo Ronchetti
Status: | Merged |
---|---|
Merged at revision: | 286 |
Proposed branch: | lp:~mttronchetti/novacut/container |
Merge into: | lp:novacut |
Diff against target: |
3825 lines (+3806/-0) 4 files modified
ui/bucket2.css (+640/-0) ui/bucket2.html (+94/-0) ui/bucket2.js (+2656/-0) ui/novacut2.js (+416/-0) |
To merge this branch: | bzr merge lp:~mttronchetti/novacut/container |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Novacut Dev | Pending | ||
Review via email:
|
Commit message
Description of the change
My work on the container
it is accessible with novacut-gtk --page=
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'ui/bucket2.css' |
2 | --- ui/bucket2.css 1970-01-01 00:00:00 +0000 |
3 | +++ ui/bucket2.css 2012-08-14 17:10:21 +0000 |
4 | @@ -0,0 +1,640 @@ |
5 | +* { |
6 | + font-family: Ubuntu; |
7 | + line-height: 24px; |
8 | + -webkit-user-select: none; |
9 | +} |
10 | + |
11 | +img { |
12 | + -webkit-user-select: none; |
13 | +} |
14 | + |
15 | +.fgrid_row { |
16 | + white-space: nowrap; |
17 | + font-size: 0; |
18 | + line-height: 0; |
19 | +} |
20 | + |
21 | +.fgrid_row > * { |
22 | + font-size: 15px; |
23 | + display: inline-block; |
24 | + margin: 8px; |
25 | + box-sizing: border-box !important; |
26 | + vertical-align: top; |
27 | +} |
28 | + |
29 | + |
30 | +.fgrid_cell > * { |
31 | + display: block; |
32 | + width: 100%; |
33 | + box-sizing: border-box !important; |
34 | +} |
35 | + |
36 | +.fgrid_1 { |
37 | + width: 50px; |
38 | +} |
39 | + |
40 | +.fgrid_2 { |
41 | + width: 116px; |
42 | +} |
43 | + |
44 | +.fgrid_3 { |
45 | + width: 182px; |
46 | +} |
47 | + |
48 | +.fgrid_4 { |
49 | + width: 248px; |
50 | +} |
51 | + |
52 | +.fgrid_5 { |
53 | + width: 314px; |
54 | +} |
55 | + |
56 | +.fgrid_6 { |
57 | + width: 380px; |
58 | +} |
59 | + |
60 | +.fgrid_7 { |
61 | + width: 446px; |
62 | +} |
63 | + |
64 | +.fgrid_8 { |
65 | + width: 512px; |
66 | +} |
67 | + |
68 | +.fgrid_9 { |
69 | + width: 578px; |
70 | +} |
71 | + |
72 | +.fgrid_10 { |
73 | + width: 644px; |
74 | +} |
75 | + |
76 | +.fgrid_11 { |
77 | + width: 710px; |
78 | +} |
79 | + |
80 | +.fgrid_12 { |
81 | + width: 776px; |
82 | +} |
83 | + |
84 | +#flyout .version { |
85 | + text-shadow: 0px 0px 10px #e81f3b; |
86 | +} |
87 | + |
88 | + |
89 | +#flyout_capture { |
90 | + position: fixed; |
91 | + z-index: 10; |
92 | + top: 0; |
93 | + right: 0; |
94 | + bottom: 0; |
95 | + left: 0; |
96 | + /* |
97 | + background: rgba(0,0,0,0.5); |
98 | + */ |
99 | +} |
100 | + |
101 | + |
102 | +#flyout { |
103 | + position: absolute; |
104 | + top: 18px; |
105 | + right: 18px; |
106 | + width: 800px; |
107 | + height: 448px; |
108 | + /* |
109 | + background: -webkit-linear-gradient(top, #333, #2a2a2a); |
110 | + */ |
111 | + background-color: rgba(15, 15, 15, 0.9); |
112 | + box-shadow: 0px 0px 10px 0px #e81f3b; |
113 | + border-radius: 12px; |
114 | + font-size: 16px; |
115 | + color: #ddd; |
116 | + box-sizing: border-box !important; |
117 | + padding: 4px; |
118 | +} |
119 | + |
120 | +#flyout a { |
121 | + color: #e81f3b; |
122 | + text-decoration: none; |
123 | +} |
124 | + |
125 | +#flyout a:hover { |
126 | + color: #f82f4b; |
127 | + text-decoration: underline; |
128 | +} |
129 | + |
130 | +#logo { |
131 | + position: fixed; |
132 | + z-index: 11; |
133 | + right: 6px; |
134 | + top: 6px; |
135 | + width: 48px; |
136 | + height: 48px; |
137 | + -webkit-transition: -webkit-transform 300ms linear; |
138 | +} |
139 | + |
140 | +#logo.open { |
141 | + -webkit-transform: rotate(-180deg); |
142 | +} |
143 | + |
144 | +#open_clips { |
145 | + z-index: 4; |
146 | + position: fixed; |
147 | + top: 0; |
148 | + right: 50%; |
149 | + width: 80px; |
150 | + color: #ddd; |
151 | + padding-left: 6px; |
152 | + padding-right: 6px; |
153 | + cursor: default; |
154 | + box-shadow: 0px 1px 4px 0px rgba(0,0,0,0.6); |
155 | + text-align: center; |
156 | + border-radius: 0 0 2px 2px; |
157 | + border:1px solid transparent; |
158 | + border-top:none; |
159 | + border-bottom:1px solid #383838; |
160 | + background: -webkit-linear-gradient(top, #444, #333); |
161 | + text-shadow: 0px -1px 0px rgba(0,0,0,0.5); |
162 | +} |
163 | + |
164 | +#clips_outer { |
165 | + z-index: 3; |
166 | + position: fixed; |
167 | + top: -140px; |
168 | + height: 139px; |
169 | + left: 0; |
170 | + right: 0; |
171 | + overflow: hidden; |
172 | + -webkit-transition: top 250ms ease-in-out; |
173 | + box-shadow: 0px 2px 6px 0px rgba(0,0,0,0.6); |
174 | +} |
175 | + |
176 | + |
177 | +#clips_outer.open { |
178 | + top: 0px; |
179 | +} |
180 | + |
181 | +.grid_row { |
182 | + font-size: 0; |
183 | + white-space: nowrap; |
184 | + font-size: 0; |
185 | +} |
186 | + |
187 | +#clips_nav { |
188 | + height: 41px; |
189 | +} |
190 | + |
191 | +#clips_nav label, #clips_nav select { |
192 | + margin: 8px; |
193 | +} |
194 | + |
195 | + |
196 | +#clips { |
197 | + width: 100%; |
198 | + overflow-y: hidden; |
199 | + overflow-x: scroll; |
200 | + white-space: nowrap; |
201 | + font-size: 0; |
202 | + line-height: 0; |
203 | + height: 97px; |
204 | + |
205 | + /* |
206 | + Dear James, you are looking especially tall today, and tough and handsome. |
207 | + Could you please make this scrollbar less horible looking? |
208 | + |
209 | + Love, |
210 | + Jason |
211 | + */ |
212 | +} |
213 | + |
214 | +::-webkit-scrollbar{ |
215 | + width:5px; |
216 | + height:5px; |
217 | + background:#222; |
218 | +} |
219 | + |
220 | +::-webkit-scrollbar-thumb{ |
221 | + border-radius:2px; |
222 | + background:#999; |
223 | +} |
224 | + |
225 | +#clips img { |
226 | + width: 160px; |
227 | + height: 90px; |
228 | + display: inline-block; |
229 | + border: 1px solid #333; |
230 | + -webkit-user-select: none; |
231 | +} |
232 | + |
233 | +#clips img.selected { |
234 | + border-color: #e81f3b; |
235 | +} |
236 | + |
237 | +#bucket { |
238 | + position: fixed; |
239 | + top: 0px; |
240 | + bottom: 246px; |
241 | + left: 0; |
242 | + right: 0; |
243 | + /* |
244 | + background: #333; |
245 | + */ |
246 | + background: #301438; |
247 | + overflow: hidden; |
248 | +} |
249 | + |
250 | +.seq-preview { |
251 | + position: fixed; |
252 | + top: 0; |
253 | + left: 0; |
254 | + right: 0; |
255 | + bottom: 246px; |
256 | + z-index: 3; |
257 | + background-color: black; |
258 | +} |
259 | + |
260 | +.seq-preview video { |
261 | + position: absolute; |
262 | + top: 0px; |
263 | + left: 0px; |
264 | + width: 100%; |
265 | + height: 100%; |
266 | +} |
267 | + |
268 | + |
269 | +#sequence { |
270 | + position: fixed; |
271 | + height: 221px; |
272 | + bottom: 0; |
273 | + left: 0; |
274 | + right: 0; |
275 | + background-color: #eee; |
276 | + |
277 | + overflow: hidden; |
278 | + white-space: nowrap; |
279 | + font-size: 0; |
280 | + line-height: 0; |
281 | + |
282 | + padding-top: 25px; |
283 | + background-image: url(grip-short.png); |
284 | + /* |
285 | + background-image: url(grip-short.png), -webkit-linear-gradient(top, #222, #333); |
286 | + */ |
287 | + background-repeat: repeat-x; |
288 | +} |
289 | + |
290 | +.slice { |
291 | + border-top: 1px solid #666; |
292 | + border-left: 1px solid #555; |
293 | + border-right: 1px solid #444; |
294 | + border-bottom:1px solid #333; |
295 | +} |
296 | + |
297 | +.slice.selected { |
298 | + border-color: #e81f3b; |
299 | + z-index: 1; |
300 | +} |
301 | + |
302 | +.slice, .slice * { |
303 | + -webkit-user-select: none; |
304 | +} |
305 | + |
306 | +#bucket .slice { |
307 | + position: absolute; |
308 | + box-shadow: 0px 2px 5px 1px rgba(0,0,0,0.5); |
309 | + |
310 | + -webkit-transition-timing-function: ease; |
311 | + -webkit-transition-duration: 250ms; |
312 | + -webkit-transition-property: left, top; |
313 | +} |
314 | + |
315 | +#sequence .slice { |
316 | + display: inline-block; |
317 | +} |
318 | + |
319 | + |
320 | +.frame { |
321 | + position: relative; |
322 | +} |
323 | + |
324 | +.frame div { |
325 | + position: absolute; |
326 | + top: 0; |
327 | + right: 0; |
328 | + padding: 2px 6px; |
329 | + |
330 | + cursor: default; |
331 | + text-align: right; |
332 | + font-family: "Ubuntu Mono"; |
333 | + font-size: 14px; |
334 | + line-height: 1.6em; |
335 | + font-weight: bold; |
336 | + color: white; |
337 | + text-shadow: 0 0 2px black; |
338 | + /* |
339 | + -webkit-text-stroke: 1px #000; |
340 | + */ |
341 | +} |
342 | + |
343 | +.frame img { |
344 | + margin: 0; |
345 | + padding: 0; |
346 | + border: none; |
347 | + display: block; |
348 | + background-color: white; |
349 | +} |
350 | + |
351 | +/* |
352 | +Interesting 16:9 thumbnail sizes we might want to use: |
353 | + 112 63 |
354 | + 128 72 |
355 | + 144 81 |
356 | + 160 90 |
357 | + 176 99 |
358 | + 192 108 |
359 | + 208 117 |
360 | + 224 126 |
361 | +*/ |
362 | + |
363 | +#bucket img { |
364 | + width: 128px; |
365 | + height: 72px; |
366 | +} |
367 | + |
368 | +#sequence img { |
369 | + width: 192px; |
370 | + height: 108px; |
371 | +} |
372 | + |
373 | + |
374 | +.indicator { |
375 | + height: 3px; |
376 | + /*background:-webkit-linear-gradient(top, #111, #222);*/ |
377 | + background-color: #333; |
378 | + position: relative; |
379 | + pointer-events: none; |
380 | +} |
381 | + |
382 | +.indicator div { |
383 | + position: absolute; |
384 | + top: 1px; |
385 | + bottom: 1px; |
386 | + left: 0%; |
387 | + right: 0%; |
388 | + background:-webkit-linear-gradient(top, #ddd, #fff); |
389 | +} |
390 | + |
391 | +.indicator div:before{ |
392 | + position:absolute; |
393 | + top:-1px; |
394 | + bottom:-1px; |
395 | + left:0px; |
396 | + width:1px; |
397 | + background:white; |
398 | + content:""; |
399 | +} |
400 | + |
401 | +.indicator div:after{ |
402 | + position:absolute; |
403 | + top:-1px; |
404 | + bottom:-1px; |
405 | + right:0px; |
406 | + width:1px; |
407 | + background:white; |
408 | + content:""; |
409 | +} |
410 | + |
411 | + |
412 | + |
413 | +.over { |
414 | + margin-left: 194px; |
415 | +} |
416 | + |
417 | +.over-right { |
418 | + margin-right: 194px; |
419 | +} |
420 | + |
421 | + |
422 | +.right { |
423 | + position: relative; |
424 | + left: 194px; |
425 | +} |
426 | + |
427 | +.left { |
428 | + position: relative; |
429 | + left: -194px; |
430 | +} |
431 | + |
432 | +.animated { |
433 | + position: relative; |
434 | + -webkit-transition: left 150ms ease; |
435 | +} |
436 | + |
437 | +.grabbed { |
438 | + -webkit-transition-property: none !important; |
439 | + position: fixed !important; |
440 | +} |
441 | + |
442 | + |
443 | +#roughcut { |
444 | + position: fixed; |
445 | + top: 139px; |
446 | + bottom: 0; |
447 | + left: 0; |
448 | + right: 0; |
449 | + background-color: black; |
450 | + z-index: 4; |
451 | +} |
452 | + |
453 | + |
454 | + |
455 | +#roughcut .frames { |
456 | + position: absolute; |
457 | + left: 0; |
458 | + right: 0; |
459 | + bottom: 30px; |
460 | + font-size: 0px; |
461 | + line-height: 0px; |
462 | +} |
463 | + |
464 | +.videoframe { |
465 | + display: inline-block; |
466 | + width: 50%; |
467 | + position: relative; |
468 | +} |
469 | + |
470 | + |
471 | +.videoframe video { |
472 | + pointer-events: none; |
473 | + width: 100%; |
474 | + margin: 0; |
475 | + display: block; |
476 | +} |
477 | + |
478 | +.videoframe div { |
479 | + position: absolute; |
480 | + top: 0; |
481 | + right: 0; |
482 | + padding: 2px 6px; |
483 | + |
484 | + cursor: default; |
485 | + text-align: right; |
486 | + font-family: "Ubuntu Mono"; |
487 | + font-size: 16px; |
488 | + line-height: 1.6em; |
489 | + font-weight: bold; |
490 | + color: white; |
491 | + text-shadow: 0 0 2px black; |
492 | +} |
493 | + |
494 | + |
495 | + |
496 | +#roughcut .scrubber { |
497 | + position: absolute; |
498 | + bottom: 0; |
499 | + height: 30px; |
500 | + left: 0; |
501 | + right: 0; |
502 | + background-color: #999; |
503 | +} |
504 | + |
505 | + |
506 | +#roughcut .scrubber * { |
507 | + pointer-events: none; |
508 | +} |
509 | + |
510 | +#roughcut .bar { |
511 | + position: absolute; |
512 | + top: 4px; |
513 | + bottom: 4px; |
514 | + background-color: #e81f3b; |
515 | +} |
516 | + |
517 | +#roughcut .playhead { |
518 | + position: absolute; |
519 | + top: 0; |
520 | + bottom: 0; |
521 | + width: 2px; |
522 | + background-color: green; |
523 | + /* |
524 | + -webkit-transition: left 150ms linear; |
525 | + */ |
526 | +} |
527 | + |
528 | +#player { |
529 | + position: fixed; |
530 | + z-index: 20; |
531 | + background-color: black; |
532 | + top: 0; |
533 | + bottom: 246px; |
534 | + left: 0; |
535 | + right: 0; |
536 | +} |
537 | + |
538 | +#player video { |
539 | + position: absolute; |
540 | + bottom: 0; |
541 | + width: 100%; |
542 | + height: 100%; |
543 | + margin: 0; |
544 | + pointer-events: none; |
545 | +} |
546 | + |
547 | +#shortcuts{ |
548 | + position:fixed; |
549 | + background-color: rgba(15, 15, 15, 0.85); |
550 | +text-shadow: 2px 2px 3px rgba(255, 0, 0, 0.5); |
551 | + box-shadow: 0px 0px 10px 0px #e81f3b; |
552 | + border-radius: 12px; |
553 | + font-size: 16px; |
554 | + display:none; |
555 | + z-index:999; |
556 | +} |
557 | +#shortcuts table{ |
558 | + padding: 20px; |
559 | +} |
560 | +#shortcuts td{ |
561 | + padding-top :4px; |
562 | + padding-left: 15px; |
563 | + padding-right: 15px; |
564 | +} |
565 | + |
566 | +.cont{ |
567 | +border-top: 1px solid rgb(102, 102, 102); |
568 | +border-left: 1px solid rgb(85, 85, 85); |
569 | +border-right: 1px solid rgb(68, 68, 68); |
570 | +border-bottom: 1px solid rgb(51, 51, 51); |
571 | +} |
572 | + |
573 | +#bucket .cont{ |
574 | +position: absolute; |
575 | +min-width:128px; |
576 | +height:147px; |
577 | +} |
578 | + |
579 | +.cont ,.cont * { |
580 | +-webkit-user-select: none; |
581 | +} |
582 | + |
583 | +.cont{ |
584 | +/*-webkit-animation-duration: 0.2s; |
585 | +-webkit-animation-iteration-count: 1; |
586 | +-webkit-animation-timing-function: ease;*/ |
587 | +background:gray; |
588 | +/*position: fixed;*/ |
589 | +} |
590 | + |
591 | + |
592 | +/*#sequence .cont{ |
593 | +height: 219px !important; |
594 | +}*/ |
595 | + |
596 | +/*#sequence .comp div{ |
597 | +height: 109px; |
598 | +}*/ |
599 | + |
600 | + |
601 | +.cont .slice{ |
602 | +position: relative !important; |
603 | +float: left; |
604 | +} |
605 | + |
606 | +#sequence .cont{ |
607 | +display: inline-block; |
608 | +height:219px !important; |
609 | +} |
610 | + |
611 | +.top{ |
612 | +height: 75px; |
613 | +} |
614 | + |
615 | +.bot{ |
616 | +height: 72px; |
617 | +} |
618 | + |
619 | +#sequence .top{ |
620 | +height: 111px; |
621 | +} |
622 | + |
623 | +#sequence .bot{ |
624 | +height: 108px; |
625 | +} |
626 | + |
627 | +.cont.selected{ |
628 | +border-color: rgb(232, 31, 59); |
629 | +z-index: 1; |
630 | +} |
631 | + |
632 | +@-webkit-keyframes enter{ |
633 | +from{-webkit-transform: translateX(-200px) translateY(-200px) scale(0.3);} |
634 | +to{-webkit-transform: translateX(0px) translateY(0px) scale(1);} |
635 | +} |
636 | + |
637 | +.selector{ |
638 | +border: 1px solid red; |
639 | +position:absolute; |
640 | +box-shadow: inset 0px 0px 10px rgba(255,0,0,0.5); |
641 | +border-radius: 5px; |
642 | +background-color: rgba(255, 0, 0, 0.13); |
643 | +z-index: 10; |
644 | +} |
645 | |
646 | === added file 'ui/bucket2.html' |
647 | --- ui/bucket2.html 1970-01-01 00:00:00 +0000 |
648 | +++ ui/bucket2.html 2012-08-14 17:10:21 +0000 |
649 | @@ -0,0 +1,94 @@ |
650 | +<!DOCTYPE html> |
651 | +<html> |
652 | + |
653 | +<head> |
654 | + <link rel="stylesheet" href="/_apps/userwebkit/base.css" /> |
655 | + <link rel="stylesheet" href="/_apps/dmedia/common.css" /> |
656 | + <link rel="stylesheet" href="/_apps/dmedia/grid.css" /> |
657 | + <link rel="stylesheet" href="bucket2.css" /> |
658 | + <script src="/_apps/userwebkit/couch.js"></script> |
659 | + <script src="/_apps/userwebkit/base.js"></script> |
660 | + <script src="novacut2.js"></script> |
661 | + <script src="bucket2.js"></script> |
662 | +</head> |
663 | + |
664 | +<body> |
665 | +<div id="open_clips">Clips</div> |
666 | +<div id="clips_outer" class="bar"> |
667 | + <div id="clips_nav"> |
668 | + <label>Dmedia Project: <select id="dmedia_project"></select></lable> |
669 | + </div> |
670 | + <div id="clips"></div> |
671 | +</div> |
672 | + |
673 | +<div id="flyout_capture" class="hide"> |
674 | +<div id="flyout"> |
675 | + <div class="fgrid_row"> |
676 | + <a class="fgrid_4" href="projects.html"><strong>Projects</strong></a> |
677 | + <button class="fgrid_3" id="render-btn" onclick="UI.render()">Render</button> |
678 | + </div> |
679 | + <div class="fgrid_row"> |
680 | + <a class="fgrid_4" href="projects.html">(Most recent project)</a> |
681 | + </div> |
682 | + <div class="fgrid_row"> |
683 | + <a class="fgrid_4" href="projects.html">(2nd most recent project)</a> |
684 | + </div> |
685 | + <div class="fgrid_row"> |
686 | + <a class="fgrid_4" href="projects.html">(3rd most recent project)</a> |
687 | + </div> |
688 | + |
689 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
690 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
691 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
692 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
693 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
694 | + <div class="fgrid_row"><strong class="fgrid_2">.</strong></div> |
695 | + |
696 | + <div class="fgrid_row"> |
697 | + <strong class="fgrid_4 version">Novacut 12.08.0</strong> |
698 | +<a onclick="showShort(event);" style="cursor: pointer; margin-right:135px;">Keyboard Shortcuts</a> |
699 | + <a href="http://www.kickstarter.com/projects/novacut/novacut-pro-video-editor/backers" class="fgrid_5">Thanks to our Kickstarter backers!</a> |
700 | + </div> |
701 | +</div> |
702 | +</div> |
703 | + |
704 | +<div id="bucket"> |
705 | +<div id="shortcuts" > |
706 | +<table border="0"> |
707 | + <tr> |
708 | + <td>D</td> |
709 | + <td>Duplicate slice</td> |
710 | + </tr> |
711 | + <tr> |
712 | + <td>Del</td> |
713 | + <td>Delete slice</td> |
714 | + </tr> |
715 | + <tr> |
716 | + <td>Space bar</td> |
717 | + <td>Play/Pause</td> |
718 | + </tr> |
719 | + <tr> |
720 | + <td>Esc</td> |
721 | + <td>Close</td> |
722 | + </tr> |
723 | + <tr> |
724 | + <td>Mouse wheel</td> |
725 | + <td>Move of one frame</td> |
726 | + </tr> |
727 | + <tr> |
728 | + <td>Shift+Mouse Wheel</td> |
729 | + <td>Move of ten frames</td> |
730 | + </tr> |
731 | +</table> |
732 | +</div> |
733 | +</div> |
734 | +<div id="sequence" clas="lower"></div> |
735 | +<div id="roughcut" class="hide"> |
736 | + <div class="grid_row"> |
737 | + <button class="grid_2" id="close_roughcut">Done</button> |
738 | + <button class="grid_2" id="create_slice">New Slice</button> |
739 | + </div> |
740 | +</div> |
741 | +</body> |
742 | + |
743 | +</html> |
744 | |
745 | === added file 'ui/bucket2.js' |
746 | --- ui/bucket2.js 1970-01-01 00:00:00 +0000 |
747 | +++ ui/bucket2.js 2012-08-14 17:10:21 +0000 |
748 | @@ -0,0 +1,2656 @@ |
749 | +"use strict"; |
750 | + |
751 | + |
752 | +var Thumbs = { |
753 | + db: new couch.Database('thumbnails'), |
754 | + |
755 | + docs: {}, |
756 | + |
757 | + has_frame: function(file_id, index) { |
758 | + if (!Thumbs.docs[file_id]) { |
759 | + try { |
760 | + Thumbs.docs[file_id] = Thumbs.db.get_sync(file_id); |
761 | + } |
762 | + catch (e) { |
763 | + return false; |
764 | + } |
765 | + } |
766 | + if (Thumbs.docs[file_id]._attachments[index]) { |
767 | + return true; |
768 | + } |
769 | + return false; |
770 | + }, |
771 | + |
772 | + q: {}, |
773 | + |
774 | + active: {}, |
775 | + |
776 | + need_init: true, |
777 | + |
778 | + init: function() { |
779 | + console.assert(Thumbs.need_init); |
780 | + Thumbs.need_init = false; |
781 | + var ids = Object.keys(Thumbs.q); |
782 | + if (ids.length == 0) { |
783 | + Thumbs.frozen = false; |
784 | + return; |
785 | + } |
786 | + Thumbs.db.post(Thumbs.on_docs, {keys: ids}, '_all_docs', {include_docs: true}); |
787 | + }, |
788 | + |
789 | + on_docs: function(req) { |
790 | + try { |
791 | + var rows = req.read().rows; |
792 | + rows.forEach(function(row) { |
793 | + var id = row.key; |
794 | + if (row.doc) { |
795 | + Thumbs.docs[id] = row.doc; |
796 | + } |
797 | + else { |
798 | + Thumbs.docs[id] = {'_id': id, '_attachments': {}}; |
799 | + } |
800 | + }); |
801 | + } |
802 | + catch (e) { |
803 | + var ids = Object.keys(Thumbs.q); |
804 | + ids.forEach(function(id) { |
805 | + Thumbs.docs[id] = {'_id': id, '_attachments': {}}; |
806 | + }); |
807 | + } |
808 | + Thumbs.unfreeze(); |
809 | + }, |
810 | + |
811 | + enqueue: function(frame) { |
812 | + if (!Thumbs.q[frame.file_id]) { |
813 | + Thumbs.q[frame.file_id] = {}; |
814 | + } |
815 | + Thumbs.q[frame.file_id][frame.key] = frame; |
816 | + }, |
817 | + |
818 | + frozen: false, |
819 | + |
820 | + freeze: function() { |
821 | + Thumbs.frozen = true; |
822 | + }, |
823 | + |
824 | + unfreeze: function() { |
825 | + console.log('unfreeze'); |
826 | + if (this.need_init) { |
827 | + this.init(); |
828 | + return; |
829 | + } |
830 | + Thumbs.frozen = false; |
831 | + Thumbs.flush(); |
832 | + }, |
833 | + |
834 | + flush: function() { |
835 | + if (Thumbs.frozen) { |
836 | + return; |
837 | + } |
838 | + var ids = Object.keys(Thumbs.q); |
839 | + if (ids.length == 0) { |
840 | + console.log('no thumbnails in queue'); |
841 | + return; |
842 | + } |
843 | + while (ids.length > 0 && Object.keys(Thumbs.active).length <= 4) { |
844 | + var id = ids.shift(); |
845 | + if (Thumbs.active[id]) { |
846 | + console.log('already waiting for ' + id); |
847 | + continue; |
848 | + } |
849 | + var frames = Thumbs.q[id]; |
850 | + delete Thumbs.q[id]; |
851 | + |
852 | + var needed = []; |
853 | + var key, frame; |
854 | + for (key in frames) { |
855 | + frame = frames[key]; |
856 | + if (Thumbs.has_frame(id, frame.index)) { |
857 | + frame.request_thumbnail.call(frame); |
858 | + } |
859 | + else { |
860 | + needed.push(frame.index); |
861 | + } |
862 | + } |
863 | + if (needed.length > 0) { |
864 | + Thumbs.active[id] = frames; |
865 | + Hub.send('thumbnail', id, needed); |
866 | + } |
867 | + } |
868 | + }, |
869 | + |
870 | + on_thumbnail_finished: function(file_id) { |
871 | + if (!Thumbs.active[file_id]) { |
872 | + return; |
873 | + } |
874 | + var frames = Thumbs.active[file_id]; |
875 | + delete Thumbs.active[file_id]; |
876 | + Thumbs.docs[file_id] = Thumbs.db.get_sync(file_id); |
877 | + |
878 | + var key, frame; |
879 | + for (key in frames) { |
880 | + frame = frames[key]; |
881 | + if (Thumbs.has_frame(file_id, frame.index)) { |
882 | + frame.request_thumbnail.call(frame); |
883 | + } |
884 | + } |
885 | + Thumbs.flush(); |
886 | + }, |
887 | +} |
888 | + |
889 | +Hub.connect('thumbnail_finished', Thumbs.on_thumbnail_finished); |
890 | + |
891 | + |
892 | +function $halt(event) { |
893 | + event.preventDefault(); |
894 | + event.stopPropagation(); |
895 | +} |
896 | + |
897 | + |
898 | +function $unparent(id) { |
899 | + var child = $(id); |
900 | + if (child && child.parentNode) { |
901 | + child.parentNode.removeChild(child); |
902 | + } |
903 | + return child; |
904 | +} |
905 | + |
906 | + |
907 | +function $position(element) { |
908 | + element = $(element); |
909 | + var pos = { |
910 | + left: element.offsetLeft, |
911 | + top: element.offsetTop, |
912 | + width: element.offsetWidth, |
913 | + height: element.offsetHeight, |
914 | + }; |
915 | + while (element.offsetParent) { |
916 | + element = element.offsetParent; |
917 | + pos.left += (element.offsetLeft - element.scrollLeft); |
918 | + pos.top += (element.offsetTop - element.scrollTop); |
919 | + } |
920 | + pos.right = pos.left + pos.width; |
921 | + pos.bottom = pos.top + pos.height; |
922 | + return pos; |
923 | +} |
924 | + |
925 | + |
926 | +function $hscroll(child, center) { |
927 | + child = $(child); |
928 | + if (!child.parentNode) { |
929 | + return; |
930 | + } |
931 | + var parent = child.parentNode |
932 | + //var mid = child.offsetLeft + (child.offsetWidth - parent.clientWidth) / 2; |
933 | + if (child.offsetLeft < parent.scrollLeft) { |
934 | + parent.scrollLeft = child.offsetLeft; |
935 | + } |
936 | + else if (child.offsetLeft + child.offsetWidth > parent.scrollLeft + parent.clientWidth) { |
937 | + parent.scrollLeft = child.offsetLeft + child.offsetWidth - parent.clientWidth; |
938 | + } |
939 | +} |
940 | + |
941 | + |
942 | + |
943 | +var DragEvent = function(event, element) { |
944 | + $halt(event); |
945 | + this.x = event.clientX; |
946 | + this.y = event.clientY; |
947 | + this.ox = this.x; |
948 | + this.oy = this.y; |
949 | + this.dx = 0; |
950 | + this.dy = 0; |
951 | + |
952 | + if (element) { |
953 | + var pos = $position(element); |
954 | + this.offsetX = this.x - pos.left; |
955 | + this.offsetY = this.y - pos.top; |
956 | + } |
957 | + else { |
958 | + this.offsetX = event.offsetX; |
959 | + this.offsetY = event.offsetY; |
960 | + } |
961 | + |
962 | + this.ondragstart = null; |
963 | + this.ondragcancel = null; |
964 | + this.ondrag = null; |
965 | + this.ondrop = null; |
966 | + this.started = false; |
967 | + |
968 | + var self = this; |
969 | + var tmp = {}; |
970 | + tmp.on_mousemove = function(event) { |
971 | + self.on_mousemove(event); |
972 | + } |
973 | + tmp.on_mouseup = function(event) { |
974 | + window.removeEventListener('mousemove', tmp.on_mousemove); |
975 | + window.removeEventListener('mouseup', tmp.on_mouseup); |
976 | + self.on_mouseup(event); |
977 | + } |
978 | + window.addEventListener('mousemove', tmp.on_mousemove); |
979 | + window.addEventListener('mouseup', tmp.on_mouseup); |
980 | +} |
981 | +DragEvent.prototype = { |
982 | + update: function(event) { |
983 | + $halt(event); |
984 | + this.event = event; |
985 | + var html = document.body.parentNode; |
986 | + this.x = Math.max(0, Math.min(event.clientX, html.clientWidth)); |
987 | + this.y = Math.max(0, Math.min(event.clientY, html.clientHeight)); |
988 | +// this.x = event.clientX; |
989 | +// this.y = event.clientY; |
990 | + this.dx = this.x - this.ox; |
991 | + this.dy = this.y - this.oy; |
992 | + }, |
993 | + |
994 | + on_mousemove: function(event) { |
995 | + this.update(event); |
996 | + if (!this.started) { |
997 | + if (Math.max(Math.abs(this.dx), Math.abs(this.dy)) > 3) { |
998 | + this.started = true; |
999 | + if (this.ondragstart) { |
1000 | + this.ondragstart(this); |
1001 | + } |
1002 | + } |
1003 | + else { |
1004 | + return; |
1005 | + } |
1006 | + } |
1007 | + if (this.ondrag) { |
1008 | + this.ondrag(this); |
1009 | + } |
1010 | + }, |
1011 | + |
1012 | + on_mouseup: function(event) { |
1013 | + if (!this.started) { |
1014 | + if (this.ondragcancel) { |
1015 | + this.ondragcancel(this); |
1016 | + } |
1017 | + return; |
1018 | + } |
1019 | + if (this.ondrop) { |
1020 | + this.update(event); |
1021 | + this.ondrop(this); |
1022 | + } |
1023 | + }, |
1024 | +} |
1025 | + |
1026 | + |
1027 | +var Frame = function(file_id, key) { |
1028 | + this.file_id = file_id; |
1029 | + this.key = key; |
1030 | + this.index = null; |
1031 | + this.element = $el('div', {'class': 'frame'}); |
1032 | + this.img = $el('img'); |
1033 | + this.element.appendChild(this.img); |
1034 | + this.info = $el('div'); |
1035 | + this.element.appendChild(this.info); |
1036 | +} |
1037 | +Frame.prototype = { |
1038 | + destroy: function() { |
1039 | + $unparent(this.info); |
1040 | + $unparent(this.img); |
1041 | + $unparent(this.element); |
1042 | + delete this.info; |
1043 | + delete this.img; |
1044 | + delete this.element; |
1045 | + }, |
1046 | + |
1047 | + set_index: function(index) { |
1048 | + if (index === this.index) { |
1049 | + return; |
1050 | + } |
1051 | + this.index = index; |
1052 | + this.info.textContent = index + 1; |
1053 | + Thumbs.enqueue(this); |
1054 | + }, |
1055 | + |
1056 | + request_thumbnail: function() { |
1057 | + this.img.src = Thumbs.db.att_url(this.file_id, this.index.toString()); |
1058 | + }, |
1059 | + |
1060 | +} |
1061 | + |
1062 | + |
1063 | +function SliceIndicator() { |
1064 | + this.element = $el('div', {'class': 'indicator'}); |
1065 | + this.bar = $el('div'); |
1066 | + this.element.appendChild(this.bar); |
1067 | +} |
1068 | +SliceIndicator.prototype = { |
1069 | + destroy: function() { |
1070 | + $unparent(this.bar); |
1071 | + $unparent(this.element); |
1072 | + delete this.bar; |
1073 | + delete this.element; |
1074 | + }, |
1075 | + |
1076 | + update: function(start, stop, count) { |
1077 | + var left = 100 * start / count; |
1078 | + var right = 100 - (100 * stop / count); |
1079 | + this.bar.style.left = left.toFixed(1) + '%'; |
1080 | + this.bar.style.right = right.toFixed(1) + '%'; |
1081 | + }, |
1082 | +} |
1083 | + |
1084 | + |
1085 | +function wheel_delta(event) { |
1086 | + var delta = event.wheelDeltaY; |
1087 | + if (delta == 0) { |
1088 | + return 0; |
1089 | + } |
1090 | + var scale = (event.shiftKey) ? -10 : -1; |
1091 | + return scale * (delta / Math.abs(delta)); |
1092 | +} |
1093 | + |
1094 | +function addCont(){ |
1095 | + var doc = create_cont(); |
1096 | + console.log(UI.session.save(doc)); |
1097 | + console.log(doc); |
1098 | + var cont = new Cont(UI.session,doc); |
1099 | + UI.bucket.appendChild(cont.element); |
1100 | + UI.sequence.do_reorder(); |
1101 | +} |
1102 | + |
1103 | +//TODO:HERE |
1104 | +var Cont = function(session,doc){ |
1105 | + session.subscribe(doc._id, this.on_change, this); |
1106 | + UI.conts.push(this); |
1107 | + this.doc = doc; |
1108 | + this.id = doc._id; |
1109 | + this.session=session; |
1110 | + this.element = $el('div', {'class': 'cont','id': doc._id}); |
1111 | + this.list = $el('ul', {'style': 'display = "none"'}); |
1112 | + this.comp = $el('div', {'class': 'comp'}) |
1113 | + this.element.appendChild(this.list); |
1114 | + this.element.appendChild(this.comp); |
1115 | + this.element.onmousedown = $bind(this.on_mousedown, this); |
1116 | + this.element.ondblclick = $bind(this.on_dblclick, this); |
1117 | + this.element.onclick = $bind(this.on_click, this); |
1118 | + this.expanded = true; |
1119 | + this.over = null; |
1120 | + this.x = 150; |
1121 | + this.y = 150; |
1122 | + this.width = 192 + 2; |
1123 | + this.threshold = this.width * 0.65; |
1124 | + this.on_change(doc); |
1125 | + this.close(); |
1126 | +} |
1127 | + |
1128 | +Cont.prototype = { |
1129 | + set x(value) { |
1130 | + if (typeof value == 'number') { |
1131 | + this.element.style.left = value + 'px'; |
1132 | + } |
1133 | + else { |
1134 | + this.element.style.left = null; |
1135 | + } |
1136 | + }, |
1137 | + |
1138 | + set y(value) { |
1139 | + if (typeof value == 'number') { |
1140 | + this.element.style.top = value + 'px'; |
1141 | + } |
1142 | + else { |
1143 | + this.element.style.top = null; |
1144 | + } |
1145 | + }, |
1146 | + |
1147 | + get x() { |
1148 | + if(this.element)return parseInt(this.element.style.left); |
1149 | + else return -1; |
1150 | + }, |
1151 | + |
1152 | + get y() { |
1153 | + if(this.element)return parseInt(this.element.style.top); |
1154 | + else return -1; |
1155 | + }, |
1156 | + |
1157 | + get inbucket() { |
1158 | + return this.element.parentNode.id == 'bucket'; |
1159 | + }, |
1160 | + |
1161 | + get frombucket() { |
1162 | + return this.parent.id == 'bucket'; |
1163 | + }, |
1164 | + |
1165 | + save: function(){ |
1166 | + this.doc.node.src = Array(); |
1167 | + for(var a in this.list.childNodes){ |
1168 | + if(this.list.childNodes[a].id)this.doc.node.src.push(this.list.childNodes[a].id); |
1169 | + } |
1170 | + this.session.save(this.doc,true); |
1171 | + }, |
1172 | + |
1173 | + refresh: function(){ |
1174 | + this.comp.innerHTML = '<div class="top">' + this.list.firstChild.firstChild.firstChild.outerHTML + '</div>'; |
1175 | + this.comp.innerHTML += '<div class="bot">'+ this.list.lastChild.lastChild.firstChild.outerHTML + '</div>'; |
1176 | + }, |
1177 | + |
1178 | + expand: function(){ |
1179 | + this.expanded = true; |
1180 | + this.list.style.display = 'block'; |
1181 | + this.comp.style.display = 'none'; |
1182 | + }, |
1183 | + close: function(){ |
1184 | + if(!this.expanded)return; |
1185 | + this.expanded = false; |
1186 | + console.log("close"); |
1187 | + this.comp.innerHTML = ""; |
1188 | + var len = this.list.childNodes.length; |
1189 | + console.log(len); |
1190 | + if(len){ |
1191 | + this.refresh(); |
1192 | + }else{ |
1193 | + if(len == 1){ |
1194 | + console.log("save frist child"); |
1195 | + var el = this.list.childNodes[0]; |
1196 | + el.style.top = this.y + 'px'; |
1197 | + el.style.left = this.x + 'px'; |
1198 | + el.style.marginLeft = '0px'; |
1199 | + el.style.marginRight = '0px'; |
1200 | + $unparent(el); |
1201 | + UI.bucket.appendChild(el); |
1202 | + } |
1203 | + UI.bucket.removeChild(this.element); |
1204 | + UI.sequence.do_reorder(); |
1205 | + for(var a in UI.conts)if(UI.conts[a].id == this.id)UI.conts.splice(a,1); |
1206 | + return; |
1207 | + } |
1208 | + this.list.style.display = 'none'; |
1209 | + this.comp.style.display = 'block'; |
1210 | + |
1211 | + }, |
1212 | + reset_margin: function(){ |
1213 | + for(var a = 0;a<this.list.childNodes.length;a++){ |
1214 | + this.list.childNodes[a].style.marginLeft = 0 + 'px'; |
1215 | + this.list.childNodes[a].style.marginRight = 0 + 'px'; |
1216 | + } |
1217 | + }, |
1218 | + slice_on: function(x){ |
1219 | + if(this.list.childNodes.length == 0){ |
1220 | + this.pos = -1; |
1221 | + return; |
1222 | + } |
1223 | + this.reset_margin(); |
1224 | + this.pos = parseInt(x/130); |
1225 | + if(this.pos >= this.list.childNodes.length) this.list.lastChild.style.marginRight = 130 + 'px'; |
1226 | + else if(this.list.childNodes[this.pos].classList[1] != 'selected') this.list.childNodes[this.pos].style.marginLeft = 130 + 'px'; |
1227 | + }, |
1228 | + on_dblclick: function(event) { |
1229 | + this.expand(); |
1230 | + }, |
1231 | + on_mousedown: function(event) { |
1232 | + UI.select(this.doc._id); |
1233 | + if (UI.player.active) { |
1234 | + UI.player.hold(); |
1235 | + } |
1236 | + this.pos = $position(this.element); |
1237 | + this.dnd = new DragEvent(event, this.element); |
1238 | + this.dnd.ondragcancel = $bind(this.on_dragcancel, this); |
1239 | + this.dnd.ondragstart = $bind(this.on_dragstart, this); |
1240 | + this.dnd.ondrag = $bind(this.on_drag, this); |
1241 | + this.dnd.ondrop = $bind(this.on_drop, this); |
1242 | + }, |
1243 | + |
1244 | + on_dragcancel: function(dnd) { |
1245 | + console.log('dragcancel'); |
1246 | + if (UI.player.active) { |
1247 | + UI.player.resume(); |
1248 | + } |
1249 | + this.stop_scrolling(); |
1250 | + if (this.inbucket && UI.bucket.lastChild != this.element) { |
1251 | + console.log('moving to end of bucket'); |
1252 | + $unparent(this.element); |
1253 | + UI.bucket.appendChild(this.element); |
1254 | + UI.sequence.do_reorder(); |
1255 | + } |
1256 | + }, |
1257 | + |
1258 | + on_dragstart: function(dnd) { |
1259 | + console.log('dragstart'); |
1260 | + this.offsetX = this.dnd.offsetX; |
1261 | + this.offsetY = this.dnd.offsetY; |
1262 | + this.offsetWidth = this.element.offsetWidth; |
1263 | + this.offsetHeight = this.element.offsetHeight; |
1264 | + |
1265 | + this.parent = this.element.parentNode; |
1266 | + this.x = dnd.x - this.offsetX; |
1267 | + if (this.inbucket) { |
1268 | + this.y = dnd.y - this.offsetY; |
1269 | + } |
1270 | + else { |
1271 | + this.nextSibling = this.element.nextSibling; |
1272 | + if (this.element.nextSibling) { |
1273 | + this.over = this.element.nextSibling; |
1274 | + this.over.classList.add('over'); |
1275 | + } |
1276 | + else if (this.element.previousSibling) { |
1277 | + this.over = this.element.previousSibling; |
1278 | + this.over.classList.add('over-right'); |
1279 | + } |
1280 | + this.target = this.element; |
1281 | + var seq = this.element.parentNode; |
1282 | + var i, child; |
1283 | + for (i=0; i<seq.children.length; i++) { |
1284 | + child = seq.children[i]; |
1285 | + if (child == this.element) { |
1286 | + this.i = i; |
1287 | + this.orig_i = i; |
1288 | + } |
1289 | + } |
1290 | + this.y = UI.sequence.top - 14; |
1291 | + } |
1292 | + this.element.classList.add('grabbed'); |
1293 | + }, |
1294 | + |
1295 | + on_drag: function(dnd) { |
1296 | + var top = UI.sequence.top; |
1297 | + var height = this.element.clientHeight; |
1298 | + var y = dnd.y - this.offsetY; |
1299 | + var f = 0.65; |
1300 | + if (this.inbucket) { |
1301 | + if (y > top - height * (1 - f)) { |
1302 | + this.move_into_sequence(dnd); |
1303 | + } |
1304 | + } |
1305 | + else { |
1306 | + if (y < top - height * f) { |
1307 | + this.move_into_bucket(dnd); |
1308 | + } |
1309 | + } |
1310 | + if (this.inbucket) { |
1311 | + this.on_mousemove_bucket(dnd); |
1312 | + } |
1313 | + else { |
1314 | + this.on_mousemove_sequence(dnd); |
1315 | + } |
1316 | + this.on_mousemove_bucket(dnd); |
1317 | + }, |
1318 | + on_click: function(dnd){ |
1319 | + dnd.stopPropagation(); |
1320 | + }, |
1321 | + |
1322 | + on_drop: function(dnd) { |
1323 | + this.stop_scrolling(); |
1324 | + this.element.classList.remove('grabbed'); |
1325 | + this.clear_over(); |
1326 | + UI.sequence.reset(); |
1327 | + if (this.inbucket) { |
1328 | + if (UI.player.active) { |
1329 | + UI.player.hide(); |
1330 | + } |
1331 | + if (UI.bucket.lastChild != this.element) { |
1332 | + $unparent(this.element); |
1333 | + UI.bucket.appendChild(this.element); |
1334 | + } |
1335 | + var pos = $position(UI.bucket); |
1336 | + this.x = Math.max(0, dnd.x - this.offsetX - pos.left); |
1337 | + this.y = Math.max(0, dnd.y - this.offsetY - pos.top); |
1338 | + } |
1339 | + else { |
1340 | + console.log(this.orig_i + ' => ' + this.i); |
1341 | + this.x = null; |
1342 | + this.y = null; |
1343 | + var seq = $('sequence'); |
1344 | + if (this.i == this.orig_i) { |
1345 | + console.assert(seq.children[this.i] == this.element); |
1346 | + } |
1347 | + else { |
1348 | + if (this.i < this.orig_i) { |
1349 | + var ref = seq.children[this.i]; |
1350 | + } |
1351 | + else { |
1352 | + var ref = seq.children[this.i].nextSibling; |
1353 | + } |
1354 | + $unparent(this.element); |
1355 | + seq.insertBefore(this.element, ref); |
1356 | + } |
1357 | + } |
1358 | + UI.sequence.do_reorder(); |
1359 | + if (UI.player.active) { |
1360 | + UI.player.resume(); |
1361 | + } |
1362 | + }, |
1363 | + on_mousemove_bucket: function(dnd) { |
1364 | + this.x = dnd.x - this.offsetX; |
1365 | + this.y = dnd.y - this.offsetY; |
1366 | + }, |
1367 | + move_into_bucket: function(dnd) { |
1368 | + if (UI.player.active) { |
1369 | + UI.player.soft_hide(); |
1370 | + } |
1371 | + this.stop_scrolling(); |
1372 | + $unparent(this.element); |
1373 | + $('bucket').appendChild(this.element); |
1374 | + if (this.frombucket) { |
1375 | + this.clear_over(); |
1376 | + UI.sequence.reset(); |
1377 | + } |
1378 | + this.update_offset(); |
1379 | + }, |
1380 | + on_mousemove_sequence: function(dnd) { |
1381 | + var mid_x = dnd.x - this.offsetX + (this.element.offsetWidth / 2); |
1382 | + var width = UI.sequence.element.clientWidth; |
1383 | + var left = Math.min(dnd.x, mid_x); |
1384 | + var right = Math.max(dnd.x, mid_x); |
1385 | + |
1386 | + if (this.scrolling) { |
1387 | + if (left > 0 && right < width) { |
1388 | + this.stop_scrolling(); |
1389 | + } |
1390 | + else { |
1391 | + return; |
1392 | + } |
1393 | + } |
1394 | + else { |
1395 | + if (left <= 0) { |
1396 | + this.start_scrolling('left'); |
1397 | + } |
1398 | + else if (right >= width) { |
1399 | + this.start_scrolling('right'); |
1400 | + } |
1401 | + } |
1402 | + this.do_mousemove_sequence(); |
1403 | + }, |
1404 | + |
1405 | + do_mousemove_sequence: function() { |
1406 | + var x = this.dnd.x - this.offsetX; |
1407 | + var parent = UI.sequence.element; |
1408 | + var scroll_x = x + parent.scrollLeft; |
1409 | + var ix = this.i * this.width; |
1410 | + var dx = scroll_x - ix; |
1411 | + |
1412 | + this.x = x; |
1413 | + this.y = UI.sequence.top - 14; |
1414 | + |
1415 | + if (dx < -this.threshold) { |
1416 | + this.shift_right(); |
1417 | + } |
1418 | + else if (dx > this.threshold) { |
1419 | + this.shift_left(); |
1420 | + } |
1421 | + }, |
1422 | + move_into_sequence: function(dnd) { |
1423 | + if (UI.player.active) { |
1424 | + UI.player.soft_show(); |
1425 | + } |
1426 | + if (!this.frombucket) { |
1427 | + this.clear_over(); |
1428 | + UI.sequence.reset(); |
1429 | + } |
1430 | + var seq = UI.sequence.element; |
1431 | + if (seq.children.length == 0) { |
1432 | + this.i = 0; |
1433 | + this.orig_i = 0; |
1434 | + this.target = this.element; |
1435 | + seq.appendChild(this.element); |
1436 | + this.update_offset(); |
1437 | + return; |
1438 | + } |
1439 | + |
1440 | + var x = this.pos.left + dnd.dx; |
1441 | + |
1442 | + var scroll_x = x + seq.scrollLeft; |
1443 | + |
1444 | + var unclamped = Math.round(scroll_x / this.width); |
1445 | + this.i = Math.max(0, Math.min(unclamped, seq.children.length)); |
1446 | + this.orig_i = this.i; |
1447 | + if (this.i == seq.children.length) { |
1448 | + this.over = seq.children[this.i - 1]; |
1449 | + this.over.classList.add('over-right'); |
1450 | + } |
1451 | + else { |
1452 | + this.over = seq.children[this.i]; |
1453 | + this.over.classList.add('over'); |
1454 | + } |
1455 | + |
1456 | + var ref = seq.children[this.i]; |
1457 | + $unparent(this.element); |
1458 | + seq.insertBefore(this.element, ref); |
1459 | + if (!ref) { |
1460 | + seq.scrollLeft += this.width; |
1461 | + } |
1462 | + this.target = this.element; |
1463 | + this.update_offset(); |
1464 | + }, |
1465 | + update_offset: function() { |
1466 | + this.offsetX = Math.round(this.dnd.offsetX * this.element.offsetWidth / this.offsetWidth); |
1467 | + this.offsetY = Math.round(this.dnd.offsetY * this.element.offsetHeight / this.offsetHeight); |
1468 | + }, |
1469 | + clear_over: function() { |
1470 | + if (this.over) { |
1471 | + this.over.classList.remove('over'); |
1472 | + this.over.classList.remove('over-right'); |
1473 | + this.over = null; |
1474 | + } |
1475 | + UI.animate(null); |
1476 | + }, |
1477 | + |
1478 | + start_scrolling: function(direction) { |
1479 | + this.direction = direction; |
1480 | + this.scrolling = true; |
1481 | + this.interval_id = setInterval($bind(this.on_interval, this), 300); |
1482 | + }, |
1483 | + stop_scrolling: function() { |
1484 | + this.scrolling = false; |
1485 | + clearInterval(this.interval_id); |
1486 | + this.interval_id = null; |
1487 | + }, |
1488 | + on_interval: function() { |
1489 | + var d = (this.direction == 'left') ? -1 : 1; |
1490 | + UI.sequence.element.scrollLeft += (d * this.width); |
1491 | + this.do_mousemove_sequence(); |
1492 | + }, |
1493 | + shift_right: function() { |
1494 | + if (!this.target.previousSibling) { |
1495 | + return; |
1496 | + } |
1497 | + this.i -= 1; |
1498 | + if (this.target.classList.contains('left')) { |
1499 | + this.target.classList.remove('left'); |
1500 | + UI.animate(this.target); |
1501 | + } |
1502 | + else { |
1503 | + this.target.previousSibling.classList.add('right'); |
1504 | + UI.animate(this.target.previousSibling); |
1505 | + } |
1506 | + this.target = this.target.previousSibling; |
1507 | + }, |
1508 | + |
1509 | + shift_left: function() { |
1510 | + if (!this.target.nextSibling) { |
1511 | + return; |
1512 | + } |
1513 | + this.i += 1; |
1514 | + if (this.target.classList.contains('right')) { |
1515 | + this.target.classList.remove('right'); |
1516 | + UI.animate(this.target); |
1517 | + } |
1518 | + else { |
1519 | + this.target.nextSibling.classList.add('left'); |
1520 | + UI.animate(this.target.nextSibling); |
1521 | + } |
1522 | + this.target = this.target.nextSibling; |
1523 | + |
1524 | + }, |
1525 | + destroy: function() { |
1526 | + $unparent(this.element); |
1527 | + delete this.element; |
1528 | + }, |
1529 | + on_change: function(doc) { |
1530 | + if (doc._deleted) { |
1531 | + console.log('deleted ' + doc._id); |
1532 | + this.destroy(); |
1533 | + UI.sequence.do_reorder(); |
1534 | + return; |
1535 | + } |
1536 | + this.doc = doc; |
1537 | + for(var a in doc.node.src){ |
1538 | + console.log(doc.node.src[a]); |
1539 | + var tdoc = UI.session.get_doc(doc.node.src[a]); |
1540 | + var slice = new Slice(UI.session, tdoc); |
1541 | + slice.start.request_thumbnail(); |
1542 | + slice.end.request_thumbnail(); |
1543 | + $unparent(slice.element); |
1544 | + this.list.appendChild(slice.element); |
1545 | + } |
1546 | + }, |
1547 | +} |
1548 | + |
1549 | +var Slice = function(session, doc) { |
1550 | + session.subscribe(doc._id, this.on_change, this); |
1551 | + this.session = session; |
1552 | + this.element = $el('div', {'class': 'slice', 'id': doc._id}); |
1553 | + |
1554 | + var file_id = doc.node.src; |
1555 | + |
1556 | + this.start = new Frame(file_id, doc._id + '.start'); |
1557 | + this.element.appendChild(this.start.element); |
1558 | + |
1559 | + this.indicator = new SliceIndicator(); |
1560 | + this.element.appendChild(this.indicator.element); |
1561 | + |
1562 | + this.end = new Frame(file_id, doc._id + '.end'); |
1563 | + this.element.appendChild(this.end.element); |
1564 | + |
1565 | + this.start.element.onmousewheel = $bind(this.on_mousewheel_start, this); |
1566 | + this.end.element.onmousewheel = $bind(this.on_mousewheel_end, this); |
1567 | + this.element.onmousedown = $bind(this.on_mousedown, this); |
1568 | + this.element.ondblclick = $bind(this.on_dblclick, this); |
1569 | + |
1570 | + this.frames = session.get_doc(doc.node.src).duration.frames; |
1571 | + this.on_change(doc); |
1572 | + |
1573 | + this.i = null; |
1574 | + this.over = null; |
1575 | + this.width = 192 + 2; |
1576 | + this.threshold = this.width * 0.65; |
1577 | + this.timeout_id = null; |
1578 | + |
1579 | + this.oncont = false; |
1580 | + this.contn = 0; |
1581 | + this.id = doc._id; |
1582 | + UI.slices.push(this); |
1583 | +} |
1584 | +Slice.prototype = { |
1585 | + destroy: function() { |
1586 | + this.start.destroy(); |
1587 | + delete this.start; |
1588 | + this.end.destroy(); |
1589 | + delete this.end; |
1590 | + this.indicator.destroy(); |
1591 | + delete this.indicator; |
1592 | + $unparent(this.element); |
1593 | + delete this.element; |
1594 | + }, |
1595 | + |
1596 | + set x(value) { |
1597 | + if (typeof value == 'number') { |
1598 | + this.element.style.left = value + 'px'; |
1599 | + } |
1600 | + else { |
1601 | + this.element.style.left = null; |
1602 | + } |
1603 | + }, |
1604 | + |
1605 | + set y(value) { |
1606 | + if (typeof value == 'number') { |
1607 | + this.element.style.top = value + 'px'; |
1608 | + } |
1609 | + else { |
1610 | + this.element.style.top = null; |
1611 | + } |
1612 | + }, |
1613 | + |
1614 | + get x() { |
1615 | + if(this.element)return parseInt(this.element.style.left); |
1616 | + else return -1; |
1617 | + }, |
1618 | + |
1619 | + get y() { |
1620 | + return parseInt(this.element.style.top); |
1621 | + }, |
1622 | + |
1623 | + get inbucket() { |
1624 | + return this.element.parentNode.id == 'bucket'; |
1625 | + }, |
1626 | + |
1627 | + get frombucket() { |
1628 | + return this.parent.id == 'bucket'; |
1629 | + }, |
1630 | + |
1631 | + on_change: function(doc) { |
1632 | + if (doc._deleted) { |
1633 | + console.log('deleted ' + doc._id); |
1634 | + this.destroy(); |
1635 | + UI.sequence.do_reorder(); |
1636 | + return; |
1637 | + } |
1638 | + this.doc = doc; |
1639 | + var node = doc.node; |
1640 | + this.start.set_index(node.start.frame); |
1641 | + this.end.set_index(node.stop.frame - 1); |
1642 | + this.indicator.update(node.start.frame, node.stop.frame, this.frames); |
1643 | + Thumbs.flush(); |
1644 | + }, |
1645 | + |
1646 | + reset_adjustment_ux: function() { |
1647 | + if (this.timeout_id == null) { |
1648 | + UI.player.hold(); |
1649 | + UI.select(this.doc._id); |
1650 | + } |
1651 | + clearTimeout(this.timeout_id); |
1652 | + this.timeout_id = setTimeout($bind(this.on_timeout, this), 750); |
1653 | + }, |
1654 | + |
1655 | + on_timeout: function() { |
1656 | + console.log('timeout'); |
1657 | + this.timeout_id = null; |
1658 | + UI.player.resume(); |
1659 | + }, |
1660 | + |
1661 | + on_mousewheel_start: function(event) { |
1662 | + $halt(event); |
1663 | + if (UI.player.active) { |
1664 | + this.reset_adjustment_ux(); |
1665 | + } |
1666 | + var delta = wheel_delta(event); |
1667 | + var start = this.doc.node.start.frame; |
1668 | + var stop = this.doc.node.stop.frame; |
1669 | + var proposed = Math.max(0, Math.min(start + delta, stop - 1)); |
1670 | + if (start != proposed) { |
1671 | + this.doc.node.start.frame = proposed; |
1672 | + this.session.save(this.doc); |
1673 | + this.session.delayed_commit(); |
1674 | + } |
1675 | + }, |
1676 | + |
1677 | + on_mousewheel_end: function(event) { |
1678 | + $halt(event); |
1679 | + if (UI.player.active) { |
1680 | + this.reset_adjustment_ux(); |
1681 | + } |
1682 | + var delta = wheel_delta(event); |
1683 | + var start = this.doc.node.start.frame; |
1684 | + var stop = this.doc.node.stop.frame; |
1685 | + var proposed = Math.max(start + 1, Math.min(stop + delta, this.frames)); |
1686 | + if (stop != proposed) { |
1687 | + this.doc.node.stop.frame = proposed; |
1688 | + this.session.save(this.doc); |
1689 | + this.session.delayed_commit(); |
1690 | + } |
1691 | + }, |
1692 | + |
1693 | + on_mousedown: function(event) { |
1694 | + UI.select(this.doc._id); |
1695 | + if (UI.player.active) { |
1696 | + UI.player.hold(); |
1697 | + } |
1698 | + this.pos = $position(this.element); |
1699 | + this.dnd = new DragEvent(event, this.element); |
1700 | + this.dnd.ondragcancel = $bind(this.on_dragcancel, this); |
1701 | + this.dnd.ondragstart = $bind(this.on_dragstart, this); |
1702 | + this.dnd.ondrag = $bind(this.on_drag, this); |
1703 | + this.dnd.ondrop = $bind(this.on_drop, this); |
1704 | + }, |
1705 | + |
1706 | + on_dblclick: function(event) { |
1707 | + $halt(event); |
1708 | + if (UI.player.active) { |
1709 | + return; |
1710 | + } |
1711 | + UI.edit_slice(this.doc); |
1712 | + }, |
1713 | + |
1714 | + on_dragcancel: function(dnd) { |
1715 | + console.log('dragcancel'); |
1716 | + if (UI.player.active) { |
1717 | + UI.player.resume(); |
1718 | + } |
1719 | + this.stop_scrolling(); |
1720 | + if (this.inbucket && UI.bucket.lastChild != this.element) { |
1721 | + console.log('moving to end of bucket'); |
1722 | + $unparent(this.element); |
1723 | + UI.bucket.appendChild(this.element); |
1724 | + UI.sequence.do_reorder(); |
1725 | + } |
1726 | + }, |
1727 | + |
1728 | + on_dragstart: function(dnd) { |
1729 | + console.log('dragstart'); |
1730 | + UI.dragging = true; |
1731 | + this.offsetX = this.dnd.offsetX; |
1732 | + this.offsetY = this.dnd.offsetY; |
1733 | + this.offsetWidth = this.element.offsetWidth; |
1734 | + this.offsetHeight = this.element.offsetHeight; |
1735 | + |
1736 | + this.parent = this.element.parentNode; |
1737 | + this.x = dnd.x - this.offsetX; |
1738 | + if (this.inbucket) { |
1739 | + this.y = dnd.y - this.offsetY; |
1740 | + } |
1741 | + else { |
1742 | + this.nextSibling = this.element.nextSibling; |
1743 | + if (this.element.nextSibling) { |
1744 | + this.over = this.element.nextSibling; |
1745 | + this.over.classList.add('over'); |
1746 | + } |
1747 | + else if (this.element.previousSibling) { |
1748 | + this.over = this.element.previousSibling; |
1749 | + this.over.classList.add('over-right'); |
1750 | + } |
1751 | + this.target = this.element; |
1752 | + var seq = this.element.parentNode; |
1753 | + var i, child; |
1754 | + for (i=0; i<seq.children.length; i++) { |
1755 | + child = seq.children[i]; |
1756 | + if (child == this.element) { |
1757 | + this.i = i; |
1758 | + this.orig_i = i; |
1759 | + } |
1760 | + } |
1761 | + this.y = UI.sequence.top - 14; |
1762 | + } |
1763 | + this.element.classList.add('grabbed'); |
1764 | + }, |
1765 | + |
1766 | + on_drag: function(dnd) { |
1767 | + var top = UI.sequence.top; |
1768 | + var height = this.element.clientHeight; |
1769 | + var y = dnd.y - this.offsetY; |
1770 | + var x = dnd.x - this.offsetX; |
1771 | + var f = 0.65; |
1772 | + //if(this.oncont)UI.conts[oncontn].reset_margin(); |
1773 | + this.oncont = false; |
1774 | + for(var a in UI.conts){ |
1775 | + var b = UI.conts[a]; |
1776 | + if(b.element && b.x < x && b.y < y && b.x+parseInt(b.element.offsetWidth) > x && b.y+parseInt(b.element.offsetHeight) > y){ |
1777 | + b.expand(); |
1778 | + this.oncont = true; |
1779 | + this.oncontn = a; |
1780 | + } |
1781 | + else b.close(); |
1782 | + } |
1783 | + |
1784 | + if(this.oncont) UI.conts[this.oncontn].slice_on(x-UI.conts[this.oncontn].x); |
1785 | + |
1786 | + if (this.inbucket) { |
1787 | + if (y > top - height * (1 - f)) { |
1788 | + this.move_into_sequence(dnd); |
1789 | + } |
1790 | + } |
1791 | + else { |
1792 | + if (y < top - height * f) { |
1793 | + this.move_into_bucket(dnd); |
1794 | + } |
1795 | + } |
1796 | + if (this.inbucket) { |
1797 | + this.on_mousemove_bucket(dnd); |
1798 | + } |
1799 | + else { |
1800 | + this.on_mousemove_sequence(dnd); |
1801 | + } |
1802 | + }, |
1803 | + |
1804 | + move_into_sequence: function(dnd) { |
1805 | + if (UI.player.active) { |
1806 | + UI.player.soft_show(); |
1807 | + } |
1808 | + if (!this.frombucket) { |
1809 | + this.clear_over(); |
1810 | + UI.sequence.reset(); |
1811 | + } |
1812 | + var seq = UI.sequence.element; |
1813 | + if (seq.children.length == 0) { |
1814 | + this.i = 0; |
1815 | + this.orig_i = 0; |
1816 | + this.target = this.element; |
1817 | + seq.appendChild(this.element); |
1818 | + this.update_offset(); |
1819 | + return; |
1820 | + } |
1821 | + |
1822 | + var x = this.pos.left + dnd.dx; |
1823 | + |
1824 | + var scroll_x = x + seq.scrollLeft; |
1825 | + |
1826 | + var unclamped = Math.round(scroll_x / this.width); |
1827 | + this.i = Math.max(0, Math.min(unclamped, seq.children.length)); |
1828 | + this.orig_i = this.i; |
1829 | + if (this.i == seq.children.length) { |
1830 | + this.over = seq.children[this.i - 1]; |
1831 | + this.over.classList.add('over-right'); |
1832 | + } |
1833 | + else { |
1834 | + this.over = seq.children[this.i]; |
1835 | + this.over.classList.add('over'); |
1836 | + } |
1837 | + |
1838 | + var ref = seq.children[this.i]; |
1839 | + $unparent(this.element); |
1840 | + seq.insertBefore(this.element, ref); |
1841 | + if (!ref) { |
1842 | + seq.scrollLeft += this.width; |
1843 | + } |
1844 | + this.target = this.element; |
1845 | + this.update_offset(); |
1846 | + }, |
1847 | + |
1848 | + move_into_bucket: function(dnd) { |
1849 | + if (UI.player.active) { |
1850 | + UI.player.soft_hide(); |
1851 | + } |
1852 | + this.stop_scrolling(); |
1853 | + $unparent(this.element); |
1854 | + $('bucket').appendChild(this.element); |
1855 | + if (this.frombucket) { |
1856 | + this.clear_over(); |
1857 | + UI.sequence.reset(); |
1858 | + } |
1859 | + this.update_offset(); |
1860 | + }, |
1861 | + |
1862 | + update_offset: function() { |
1863 | + this.offsetX = Math.round(this.dnd.offsetX * this.element.offsetWidth / this.offsetWidth); |
1864 | + this.offsetY = Math.round(this.dnd.offsetY * this.element.offsetHeight / this.offsetHeight); |
1865 | + }, |
1866 | + |
1867 | + on_mousemove_bucket: function(dnd) { |
1868 | + this.x = dnd.x - this.offsetX; |
1869 | + this.y = dnd.y - this.offsetY; |
1870 | + }, |
1871 | + |
1872 | + start_scrolling: function(direction) { |
1873 | + this.direction = direction; |
1874 | + this.scrolling = true; |
1875 | + this.interval_id = setInterval($bind(this.on_interval, this), 300); |
1876 | + }, |
1877 | + |
1878 | + stop_scrolling: function() { |
1879 | + this.scrolling = false; |
1880 | + clearInterval(this.interval_id); |
1881 | + this.interval_id = null; |
1882 | + }, |
1883 | + |
1884 | + on_interval: function() { |
1885 | + var d = (this.direction == 'left') ? -1 : 1; |
1886 | + UI.sequence.element.scrollLeft += (d * this.width); |
1887 | + this.do_mousemove_sequence(); |
1888 | + }, |
1889 | + |
1890 | + on_mousemove_sequence: function(dnd) { |
1891 | + var mid_x = dnd.x - this.offsetX + (this.element.offsetWidth / 2); |
1892 | + var width = UI.sequence.element.clientWidth; |
1893 | + var left = Math.min(dnd.x, mid_x); |
1894 | + var right = Math.max(dnd.x, mid_x); |
1895 | + |
1896 | + if (this.scrolling) { |
1897 | + if (left > 0 && right < width) { |
1898 | + this.stop_scrolling(); |
1899 | + } |
1900 | + else { |
1901 | + return; |
1902 | + } |
1903 | + } |
1904 | + else { |
1905 | + if (left <= 0) { |
1906 | + this.start_scrolling('left'); |
1907 | + } |
1908 | + else if (right >= width) { |
1909 | + this.start_scrolling('right'); |
1910 | + } |
1911 | + } |
1912 | + this.do_mousemove_sequence(); |
1913 | + }, |
1914 | + |
1915 | + do_mousemove_sequence: function() { |
1916 | + var x = this.dnd.x - this.offsetX; |
1917 | + var parent = UI.sequence.element; |
1918 | + var scroll_x = x + parent.scrollLeft; |
1919 | + var ix = this.i * this.width; |
1920 | + var dx = scroll_x - ix; |
1921 | + |
1922 | + this.x = x; |
1923 | + this.y = UI.sequence.top - 14; |
1924 | + |
1925 | + if (dx < -this.threshold) { |
1926 | + this.shift_right(); |
1927 | + } |
1928 | + else if (dx > this.threshold) { |
1929 | + this.shift_left(); |
1930 | + } |
1931 | + }, |
1932 | + |
1933 | + shift_right: function() { |
1934 | + if (!this.target.previousSibling) { |
1935 | + return; |
1936 | + } |
1937 | + this.i -= 1; |
1938 | + if (this.target.classList.contains('left')) { |
1939 | + this.target.classList.remove('left'); |
1940 | + UI.animate(this.target); |
1941 | + } |
1942 | + else { |
1943 | + this.target.previousSibling.classList.add('right'); |
1944 | + UI.animate(this.target.previousSibling); |
1945 | + } |
1946 | + this.target = this.target.previousSibling; |
1947 | + }, |
1948 | + |
1949 | + shift_left: function() { |
1950 | + if (!this.target.nextSibling) { |
1951 | + return; |
1952 | + } |
1953 | + this.i += 1; |
1954 | + if (this.target.classList.contains('right')) { |
1955 | + this.target.classList.remove('right'); |
1956 | + UI.animate(this.target); |
1957 | + } |
1958 | + else { |
1959 | + this.target.nextSibling.classList.add('left'); |
1960 | + UI.animate(this.target.nextSibling); |
1961 | + } |
1962 | + this.target = this.target.nextSibling; |
1963 | + |
1964 | + }, |
1965 | + |
1966 | + clear_over: function() { |
1967 | + if (this.over) { |
1968 | + this.over.classList.remove('over'); |
1969 | + this.over.classList.remove('over-right'); |
1970 | + this.over = null; |
1971 | + } |
1972 | + UI.animate(null); |
1973 | + }, |
1974 | + |
1975 | + on_drop: function(dnd) { |
1976 | + UI.dragging = false; |
1977 | + this.stop_scrolling(); |
1978 | + this.element.classList.remove('grabbed'); |
1979 | + this.clear_over(); |
1980 | + if(this.oncont){ |
1981 | + this.x = null; |
1982 | + this.y = null; |
1983 | + var pos = UI.conts[this.contn].pos; |
1984 | + console.log(pos); |
1985 | + $unparent(this.element); |
1986 | + $unselect(UI.selected); |
1987 | + if(pos == -1) UI.conts[this.contn].list.appendChild(this.element); |
1988 | + else UI.conts[this.contn].list.insertBefore(this.element,UI.conts[this.contn].list.childNodes[pos]); |
1989 | + //UI.conts[this.contn].list.appendChild(this.element); |
1990 | + //UI.conts[this.contn].doc.node.src.push(this.id); |
1991 | + //this.session.save( UI.conts[this.contn].doc,true); |
1992 | + UI.conts[this.contn].reset_margin(); |
1993 | + UI.conts[this.contn].save(); |
1994 | + UI.sequence.do_reorder(); |
1995 | + for(var a in UI.slices)if(UI.slices[a].id == this.id)UI.slices.splice(a,1); |
1996 | + return; |
1997 | + } |
1998 | + UI.sequence.reset(); |
1999 | + if (this.inbucket) { |
2000 | + if (UI.player.active) { |
2001 | + UI.player.hide(); |
2002 | + } |
2003 | + if (UI.bucket.lastChild != this.element) { |
2004 | + $unparent(this.element); |
2005 | + UI.bucket.appendChild(this.element); |
2006 | + } |
2007 | + var pos = $position(UI.bucket); |
2008 | + this.x = Math.max(0, dnd.x - this.offsetX - pos.left); |
2009 | + this.y = Math.max(0, dnd.y - this.offsetY - pos.top); |
2010 | + } |
2011 | + else { |
2012 | + console.log(this.orig_i + ' => ' + this.i); |
2013 | + this.x = null; |
2014 | + this.y = null; |
2015 | + var seq = $('sequence'); |
2016 | + if (this.i == this.orig_i) { |
2017 | + console.assert(seq.children[this.i] == this.element); |
2018 | + } |
2019 | + else { |
2020 | + if (this.i < this.orig_i) { |
2021 | + var ref = seq.children[this.i]; |
2022 | + } |
2023 | + else { |
2024 | + var ref = seq.children[this.i].nextSibling; |
2025 | + } |
2026 | + $unparent(this.element); |
2027 | + seq.insertBefore(this.element, ref); |
2028 | + } |
2029 | + } |
2030 | + if(UI.conts[this.contn]) UI.conts[this.contn].save(); |
2031 | + UI.sequence.do_reorder(); |
2032 | + if (UI.player.active) { |
2033 | + UI.player.resume(); |
2034 | + } |
2035 | + }, |
2036 | +} |
2037 | + |
2038 | + |
2039 | +function $compare(one, two) { |
2040 | + if (! (one instanceof Array && two instanceof Array)) { |
2041 | + return false; |
2042 | + } |
2043 | + if (one.length != two.length) { |
2044 | + return false; |
2045 | + } |
2046 | + var i; |
2047 | + for (i in one) { |
2048 | + if (one[i] != two[i]) { |
2049 | + return false; |
2050 | + } |
2051 | + } |
2052 | + return true; |
2053 | +} |
2054 | + |
2055 | + |
2056 | +var Sequence = function(session, doc) { |
2057 | + this.element = $('sequence'); |
2058 | + this.bucket = $('bucket'); |
2059 | + session.subscribe(doc._id, this.on_change, this); |
2060 | + this.session = session; |
2061 | + this.on_change(doc); |
2062 | + |
2063 | + this.element.onmousedown = $bind(this.on_mousedown, this); |
2064 | + this.element.onscroll = $bind(this.on_scroll, this); |
2065 | + this.element.onchildselect = $bind(this.on_childselect, this); |
2066 | +} |
2067 | +Sequence.prototype = { |
2068 | + get top() { |
2069 | + return this.element.offsetTop + 24; |
2070 | + }, |
2071 | + |
2072 | + on_childselect: function(id) { |
2073 | + console.log('childselect ' + id); |
2074 | + $hscroll($(id)); |
2075 | + }, |
2076 | + |
2077 | + on_change: function(doc) { |
2078 | + console.log('Sequence.on_change()'); |
2079 | + this.doc = doc; |
2080 | + |
2081 | + Thumbs.freeze(); |
2082 | + |
2083 | + var i, _id, child, element; |
2084 | + for (i in doc.node.src) { |
2085 | + _id = doc.node.src[i]; |
2086 | + child = this.element.children[i]; |
2087 | + if (!child || child.id != _id) { |
2088 | + element = UI.get_slice(_id); |
2089 | + if (element) { |
2090 | + this.element.insertBefore(element, child); |
2091 | + } |
2092 | + } |
2093 | + } |
2094 | + |
2095 | + if (! doc.doodle instanceof Array) { |
2096 | + UI.sequence.doc.doodle = []; |
2097 | + } |
2098 | + |
2099 | + var obj; |
2100 | + for (i in doc.doodle) { |
2101 | + obj = doc.doodle[i]; |
2102 | + child = this.bucket.children[i]; |
2103 | + if (!child || child.id != obj.id) { |
2104 | + element = UI.get_slice(obj.id); |
2105 | + if (element) { |
2106 | + this.bucket.insertBefore(element, child); |
2107 | + } |
2108 | + child = element; |
2109 | + } |
2110 | + if (child) { |
2111 | + child.style.left = obj.x + 'px'; |
2112 | + child.style.top = obj.y + 'px'; |
2113 | + } |
2114 | + } |
2115 | + |
2116 | + UI.select(doc.selected); |
2117 | + |
2118 | + Thumbs.unfreeze(); |
2119 | + |
2120 | + console.assert( |
2121 | + $compare(this.doc.node.src, this.get_src()) |
2122 | + ); |
2123 | + }, |
2124 | + |
2125 | + on_scroll: function(event) { |
2126 | + this.element.style.setProperty('background-position', -this.element.scrollLeft + 'px 0px'); |
2127 | + }, |
2128 | + |
2129 | + on_mousedown: function(event) { |
2130 | + console.log('sequence mousedown'); |
2131 | + this.dnd = new DragEvent(event, this.element); |
2132 | + this.dnd.ondrag = $bind(this.on_drag, this); |
2133 | + this.dnd.scrollLeft = this.element.scrollLeft; |
2134 | + }, |
2135 | + |
2136 | + on_drag: function(dnd) { |
2137 | + this.element.scrollLeft = dnd.scrollLeft - dnd.dx; |
2138 | + }, |
2139 | + |
2140 | + get_src: function() { |
2141 | + var i; |
2142 | + var src = []; |
2143 | + for (i=0; i<this.element.children.length; i++) { |
2144 | + src.push(this.element.children[i].id); |
2145 | + } |
2146 | + return src; |
2147 | + }, |
2148 | + |
2149 | + get_doodle: function() { |
2150 | + var i, child; |
2151 | + var doodle = []; |
2152 | + for (i=0; i<this.bucket.children.length; i++) { |
2153 | + var child = this.bucket.children[i]; |
2154 | + doodle.push({ |
2155 | + id: child.id, |
2156 | + x: parseInt(child.style.left), |
2157 | + y: parseInt(child.style.top), |
2158 | + }); |
2159 | + } |
2160 | + return doodle; |
2161 | + }, |
2162 | + |
2163 | + do_reorder: function() { |
2164 | + console.log('do_reorder'); |
2165 | + var src = this.get_src(); |
2166 | + var doodle = this.get_doodle(); |
2167 | + this.doc.node.src = src; |
2168 | + this.doc.doodle = doodle; |
2169 | + this.session.save(this.doc, true); // no_emit=true |
2170 | + this.session.commit(); |
2171 | + }, |
2172 | + |
2173 | + reset: function() { |
2174 | + console.log('Sequence.reset()'); |
2175 | + var i, child; |
2176 | + for (i=0; i<this.element.children.length; i++) { |
2177 | + child = this.element.children[i]; |
2178 | + if (!child.classList.contains('grabbed')) { |
2179 | + child.classList.remove('left'); |
2180 | + child.classList.remove('right'); |
2181 | + } |
2182 | + } |
2183 | + }, |
2184 | +} |
2185 | + |
2186 | +var VideoFrame = function(which) { |
2187 | + this.element = $el('div', {'class': 'videoframe ' + which}); |
2188 | + this.video = $el('video'); |
2189 | + this.element.appendChild(this.video); |
2190 | + this.info = $el('div'); |
2191 | + this.element.appendChild(this.info); |
2192 | + this.ready = false; |
2193 | + this.pending = null; |
2194 | + this.video.addEventListener('canplaythrough', |
2195 | + $bind(this.on_canplaythrough, this) |
2196 | + ); |
2197 | + this.video.addEventListener('seeked', |
2198 | + $bind(this.on_seeked, this) |
2199 | + ); |
2200 | +} |
2201 | +VideoFrame.prototype = { |
2202 | + set_index: function(index) { |
2203 | + this.info.textContent = index + 1; |
2204 | + this.seek(index); |
2205 | + }, |
2206 | + |
2207 | + on_canplaythrough: function(event) { |
2208 | + this.ready = true; |
2209 | + this.do_seek(); |
2210 | + }, |
2211 | + |
2212 | + on_seeked: function(event) { |
2213 | + if (this.pending != null) { |
2214 | + this.do_seek(); |
2215 | + } |
2216 | + }, |
2217 | + |
2218 | + set_clip: function(clip) { |
2219 | + this.ready = false; |
2220 | + this.framerate = clip.framerate; |
2221 | + this.frames = clip.duration.frames; |
2222 | + this.pending = null; |
2223 | + this.video.src = 'dmedia:' + clip._id; |
2224 | + }, |
2225 | + |
2226 | + play: function() { |
2227 | + this.video.play(); |
2228 | + }, |
2229 | + |
2230 | + pause: function() { |
2231 | + this.video.pause(); |
2232 | + }, |
2233 | + |
2234 | + seek: function(index) { |
2235 | + this.pending = frame_to_seconds(index, this.framerate); |
2236 | + if (this.ready && ! this.video.seeking) { |
2237 | + this.do_seek(); |
2238 | + } |
2239 | + }, |
2240 | + |
2241 | + do_seek: function() { |
2242 | + var t = this.pending; |
2243 | + this.pending = null; |
2244 | + this.video.currentTime = t; |
2245 | + }, |
2246 | + |
2247 | + show: function() { |
2248 | + this.element.classList.remove('hide'); |
2249 | + }, |
2250 | + |
2251 | + hide: function() { |
2252 | + this.video.pause(); |
2253 | + this.element.classList.add('hide'); |
2254 | + }, |
2255 | + |
2256 | + get_x: function(width) { |
2257 | + return Math.round(width * this.video.currentTime / this.video.duration); |
2258 | + }, |
2259 | + |
2260 | + get_frame: function() { |
2261 | + return Math.round(this.frames * this.video.currentTime / this.video.duration); |
2262 | + }, |
2263 | +} |
2264 | + |
2265 | + |
2266 | +var RoughCut = function(session) { |
2267 | + this.session = session; |
2268 | + this.active = false; |
2269 | + |
2270 | + this.element = $('roughcut'); |
2271 | + this.frames = $el('div', {'class': 'frames'}); |
2272 | + this.element.appendChild(this.frames); |
2273 | + |
2274 | + this.done = $('close_roughcut'); |
2275 | + this.done.onclick = function() { |
2276 | + this.blur(); |
2277 | + UI.hide_roughcut(); |
2278 | + } |
2279 | + |
2280 | + this.create_button = $('create_slice'); |
2281 | + this.create_button.onclick = $bind(this.create_slice, this); |
2282 | + |
2283 | + this.startvideo = new VideoFrame('start'); |
2284 | + this.frames.appendChild(this.startvideo.element); |
2285 | + |
2286 | + this.endvideo = new VideoFrame('end hide'); |
2287 | + this.frames.appendChild(this.endvideo.element); |
2288 | + |
2289 | + this.scrubber = $el('div', {'class': 'scrubber'}); |
2290 | + this.element.appendChild(this.scrubber); |
2291 | + |
2292 | + this.bar = $el('div', {'class': 'bar hide'}); |
2293 | + this.scrubber.appendChild(this.bar); |
2294 | + |
2295 | + this.playhead = $el('div', {'class': 'playhead hide'}); |
2296 | + this.scrubber.appendChild(this.playhead); |
2297 | + |
2298 | + this.scrubber.onmouseover = $bind(this.on_mouseover, this); |
2299 | + this.scrubber.onmousedown = $bind(this.on_mousedown, this); |
2300 | + |
2301 | + this.startvideo.video.addEventListener('timeupdate', |
2302 | + $bind(this.on_timeupdate, this) |
2303 | + ); |
2304 | + this.startvideo.video.addEventListener('ended', |
2305 | + $bind(this.on_ended, this) |
2306 | + ); |
2307 | + |
2308 | + this.startvideo.element.addEventListener('mousewheel', |
2309 | + $bind(this.on_mousewheel_start, this) |
2310 | + ); |
2311 | + this.endvideo.element.addEventListener('mousewheel', |
2312 | + $bind(this.on_mousewheel_end, this) |
2313 | + ); |
2314 | +} |
2315 | +RoughCut.prototype = { |
2316 | + on_ended: function() { |
2317 | + if (! this.playing) { |
2318 | + return; |
2319 | + } |
2320 | + var frame = (this.mode == 'edit' && this.inside) ? this.start : 0; |
2321 | + this.startvideo.seek(frame); |
2322 | + this.startvideo.video.play(); |
2323 | + this.pframe = frame; |
2324 | + }, |
2325 | + |
2326 | + on_timeupdate: function() { |
2327 | + if (! this.playing) { |
2328 | + return; |
2329 | + } |
2330 | + if (this.dnd) { |
2331 | + return; |
2332 | + } |
2333 | + var frame = this.startvideo.get_frame(); |
2334 | + if (this.mode == 'edit' && this.inside && frame >= this.stop - 1) { |
2335 | + this.startvideo.seek(this.start, true); |
2336 | + frame = this.start; |
2337 | + } |
2338 | + this.pframe = frame; |
2339 | + }, |
2340 | + |
2341 | + hide: function() { |
2342 | + this.active = false; |
2343 | + this.mode = null; |
2344 | + this.pause(); |
2345 | + $hide(this.element); |
2346 | + }, |
2347 | + |
2348 | + show: function(id) { |
2349 | + console.log('show ' + id); |
2350 | + if (! this.element.classList.contains('hide')) { |
2351 | + this.x = this.x + 130 + 10 + (this.xf * 3); |
2352 | + if (this.x > document.body.clientWidth - 130) { |
2353 | + this.x = 0; |
2354 | + } |
2355 | + } |
2356 | + else { |
2357 | + this.x = 0; |
2358 | + } |
2359 | + this.y = 0; |
2360 | + this.count = 0; |
2361 | + this.active = true; |
2362 | + this.clip = this.session.get_doc(id); |
2363 | + this.frames = this.clip.duration.frames; |
2364 | + this.startvideo.set_clip(this.clip); |
2365 | + this.endvideo.set_clip(this.clip); |
2366 | + $show(this.element); |
2367 | + }, |
2368 | + |
2369 | + reset: function() { |
2370 | + delete this.dnd; |
2371 | + this._start = 0; |
2372 | + this._stop = this.frames; |
2373 | + this.pframe = null; |
2374 | + this.startvideo.pause(); |
2375 | + this.playing = false; |
2376 | + this.scrubber.onmousemove = null; |
2377 | + }, |
2378 | + |
2379 | + get_x: function(frame) { |
2380 | + return Math.round(this.scrubber.clientWidth * frame / this.frames); |
2381 | + }, |
2382 | + |
2383 | + get_frame: function(x, key_unit) { |
2384 | + var frame = Math.round(this.frames * x / this.scrubber.clientWidth); |
2385 | + if (key_unit) { |
2386 | + return 1 + Math.round(frame / 15) * 15; |
2387 | + } |
2388 | + return frame; |
2389 | + }, |
2390 | + |
2391 | + set start(value) { |
2392 | + this._start = Math.max(0, Math.min(value, this._stop - 1)); |
2393 | + this.startvideo.set_index(this._start); |
2394 | + }, |
2395 | + |
2396 | + get start() { |
2397 | + return this._start; |
2398 | + }, |
2399 | + |
2400 | + set stop(value) { |
2401 | + this._stop = Math.max(this._start + 1, Math.min(value, this.frames)); |
2402 | + this.endvideo.set_index(this._stop - 1); |
2403 | + }, |
2404 | + |
2405 | + get stop() { |
2406 | + return this._stop; |
2407 | + }, |
2408 | + |
2409 | + get left() { |
2410 | + return this.get_x(this._start); |
2411 | + }, |
2412 | + |
2413 | + get right() { |
2414 | + return this.get_x(this._stop); |
2415 | + }, |
2416 | + |
2417 | + set pframe(value) { |
2418 | + if (value == null) { |
2419 | + this._pframe = null; |
2420 | + this.playhead.classList.add('hide'); |
2421 | + } |
2422 | + else { |
2423 | + this._pframe = Math.max(0, Math.min(value, this.frames - 1)); |
2424 | + this.playhead.classList.remove('hide'); |
2425 | + this.playhead.style.left = this.get_x(this._pframe) + 'px'; |
2426 | + } |
2427 | + }, |
2428 | + |
2429 | + get pframe() { |
2430 | + return this._pframe; |
2431 | + }, |
2432 | + |
2433 | + on_mousewheel_start: function(event) { |
2434 | + $halt(event); |
2435 | + var orig = this._start; |
2436 | + this.start = orig + wheel_delta(event); |
2437 | + if (this.start != orig) { |
2438 | + this.save_to_slice(); |
2439 | + this.session.delayed_commit(); |
2440 | + if (this.mode == 'create') { |
2441 | + this.bar.style.left = this.left + 'px'; |
2442 | + } |
2443 | + else { |
2444 | + this.update_bar(); |
2445 | + } |
2446 | + } |
2447 | + }, |
2448 | + |
2449 | + on_mousewheel_end: function(event) { |
2450 | + $halt(event); |
2451 | + var orig = this._stop; |
2452 | + this.stop = orig + wheel_delta(event); |
2453 | + if (this.stop != orig) { |
2454 | + this.save_to_slice(); |
2455 | + this.session.delayed_commit(); |
2456 | + this.update_bar(); |
2457 | + } |
2458 | + }, |
2459 | + |
2460 | + playpause: function() { |
2461 | + if (this.playing) { |
2462 | + this.pause(); |
2463 | + } |
2464 | + else { |
2465 | + this.play(); |
2466 | + } |
2467 | + }, |
2468 | + |
2469 | + play: function() { |
2470 | + this.playing = true; |
2471 | + this.scrubber.onmousemove = null; |
2472 | + if (this._pframe == null) { |
2473 | + this.pframe = this.start; |
2474 | + } |
2475 | + this.startvideo.seek(this.pframe); |
2476 | + this.startvideo.play(); |
2477 | + }, |
2478 | + |
2479 | + pause: function() { |
2480 | + this.startvideo.pause(); |
2481 | + this.startvideo.seek(this.start); |
2482 | + this.playing = false; |
2483 | + if (this.mode == 'create') { |
2484 | + this.bind_mousemove(); |
2485 | + } |
2486 | + }, |
2487 | + |
2488 | + update_bar: function() { |
2489 | + var left = this.left; |
2490 | + var width = Math.max(2, this.right - left); |
2491 | + this.bar.style.left = left + 'px'; |
2492 | + this.bar.style.width = width + 'px'; |
2493 | + }, |
2494 | + |
2495 | + sync_from_slice: function() { |
2496 | + this._start = 0; |
2497 | + this._stop = this.frames; |
2498 | + this.start = this.slice.node.start.frame; |
2499 | + this.stop = this.slice.node.stop.frame; |
2500 | + this.update_bar(); |
2501 | + }, |
2502 | + |
2503 | + save_to_slice: function() { |
2504 | + /* |
2505 | + Store start & stop in slice doc, mark doc as dirty. |
2506 | + |
2507 | + Note that this *only* marks the slice doc as dirty, does *not* call |
2508 | + session.commit(). This is for cases when you also need to update the |
2509 | + sequence doc, so you can send both in a single CouchDB request. |
2510 | + */ |
2511 | + this.slice.node.start.frame = this.start; |
2512 | + this.slice.node.stop.frame = this.stop; |
2513 | + this.session.save(this.slice); |
2514 | + }, |
2515 | + |
2516 | + create_slice: function() { |
2517 | + console.log('create_slice'); |
2518 | + this.create_button.blur(); |
2519 | + this.count += 1; |
2520 | + this.mode = 'create'; |
2521 | + this.endvideo.hide(); |
2522 | + this.reset(); |
2523 | + this.start = 0; |
2524 | + this.bar.style.left = this.left + 'px'; |
2525 | + this.bar.style.width = '1px'; |
2526 | + this.slice = create_slice(this.clip._id, this.frames); |
2527 | + this.bind_mousemove(); |
2528 | + }, |
2529 | + |
2530 | + edit_slice: function(slice) { |
2531 | + console.log('edit_slice ' + slice._id); |
2532 | + this.mode = 'edit'; |
2533 | + this.inside = true; |
2534 | + this.slice = slice; |
2535 | + this.endvideo.show(); |
2536 | + this.reset(); |
2537 | + $show(this.bar); |
2538 | + this.sync_from_slice(); |
2539 | + }, |
2540 | + |
2541 | + bind_mousemove: function() { |
2542 | + this.scrubber.onmousemove = $bind(this.on_mousemove, this); |
2543 | + }, |
2544 | + |
2545 | + on_mouseover: function(event) { |
2546 | + if (this.mode == 'create' && !this.playing && !this.dnd) { |
2547 | + $show(this.bar); |
2548 | + } |
2549 | + }, |
2550 | + |
2551 | + on_mousemove: function(event) { |
2552 | + this.start = this.get_frame(event.clientX); |
2553 | + this.bar.style.left = this.left + 'px'; |
2554 | + }, |
2555 | + |
2556 | + on_mousedown: function(event) { |
2557 | + this.scrubber.onmousemove = null; |
2558 | + this.dnd = new DragEvent(event); |
2559 | + this.dnd.ondragcancel = $bind(this.on_dragcancel, this); |
2560 | + this.dnd.ondragstart = $bind(this.on_dragstart, this); |
2561 | + |
2562 | + if (this.playing) { |
2563 | + this.startvideo.pause(); |
2564 | + return this.scrub_playhead(this.dnd); |
2565 | + } |
2566 | + if (this.mode == 'edit') { |
2567 | + var mid = (this.left + this.right) / 2; |
2568 | + this.point = (event.clientX <= mid) ? 'left' : 'right'; |
2569 | + var frame = this.get_frame(event.clientX); |
2570 | + if (this.point == 'left') { |
2571 | + this.start = frame; |
2572 | + } |
2573 | + else { |
2574 | + this.stop = frame + 1; |
2575 | + } |
2576 | + this.update_bar(); |
2577 | + } |
2578 | + }, |
2579 | + |
2580 | + scrub_playhead: function(dnd) { |
2581 | + var frame = this.get_frame(dnd.x); |
2582 | + if (this.start <= frame && frame < this.stop) { |
2583 | + this.inside = true; |
2584 | + } |
2585 | + else { |
2586 | + this.inside = false; |
2587 | + } |
2588 | + this.pframe = frame; |
2589 | + this.startvideo.seek(frame); |
2590 | + }, |
2591 | + |
2592 | + on_dragcancel: function(dnd) { |
2593 | + delete this.dnd; |
2594 | + if (this.playing) { |
2595 | + this.startvideo.play(); |
2596 | + return; |
2597 | + } |
2598 | + if (this.mode == 'create') { |
2599 | + this.bindmousemove(); |
2600 | + } |
2601 | + else { |
2602 | + this.save_to_slice(); |
2603 | + this.session.delayed_commit(); |
2604 | + } |
2605 | + }, |
2606 | + |
2607 | + on_dragstart: function(dnd) { |
2608 | + this.dnd.ondrag = $bind(this.on_drag, this); |
2609 | + this.dnd.ondrop = $bind(this.on_drop, this); |
2610 | + if (!this.playing && this.mode == 'create') { |
2611 | + this.endvideo.show(); |
2612 | + this.orig_start = this.start; |
2613 | + } |
2614 | + }, |
2615 | + |
2616 | + on_drag: function(dnd) { |
2617 | + var frame = this.get_frame(dnd.x); |
2618 | + if (this.playing) { |
2619 | + return this.scrub_playhead(dnd); |
2620 | + } |
2621 | + if (this.mode == 'create') { |
2622 | + if (frame < this.orig_start) { |
2623 | + this.start = frame; |
2624 | + this.stop = this.orig_start + 1; |
2625 | + } |
2626 | + else { |
2627 | + this.start = this.orig_start; |
2628 | + this.stop = frame + 1; |
2629 | + } |
2630 | + } |
2631 | + else { |
2632 | + if (this.point == 'left') { |
2633 | + this.start = frame; |
2634 | + } |
2635 | + else { |
2636 | + this.stop = frame + 1; |
2637 | + } |
2638 | + } |
2639 | + this.update_bar(); |
2640 | + }, |
2641 | + |
2642 | + xf: 25, |
2643 | + |
2644 | + yf: 50, |
2645 | + |
2646 | + on_drop: function(dnd) { |
2647 | + delete this.dnd; |
2648 | + if (this.playing) { |
2649 | + this.startvideo.play(); |
2650 | + return; |
2651 | + } |
2652 | + if (this.mode == 'create') { |
2653 | + this.save_to_slice(); |
2654 | + var x = this.x + (this.count * this.xf); |
2655 | + var y = this.y + (this.count * this.yf); |
2656 | + UI.sequence.doc.doodle.push({id: this.slice._id, x: x, y: y}); |
2657 | + this.session.save(UI.sequence.doc); |
2658 | + this.session.delayed_commit(); |
2659 | + this.edit_slice(this.slice); |
2660 | + } |
2661 | + else { |
2662 | + this.save_to_slice(); |
2663 | + this.session.delayed_commit(); |
2664 | + } |
2665 | + }, |
2666 | +} |
2667 | + |
2668 | + |
2669 | +function Clips() { |
2670 | + this.selected = null; |
2671 | + this.dropdown = $('dmedia_project'); |
2672 | + this.dropdown.onchange = $bind(this.on_dropdown_change, this); |
2673 | + this.div = $('clips'); |
2674 | + this.container = $('clips_outer'); |
2675 | + this.session = UI.session; |
2676 | + this.doc = this.session.get_doc(UI.project_id); |
2677 | + this.session.subscribe(this.doc._id, this.on_change, this); |
2678 | + this.id = null; |
2679 | + this.db = null; |
2680 | + this.load_projects(); |
2681 | + this.open = $('open_clips'); |
2682 | + this.open.onclick = $bind(this.on_open_click, this); |
2683 | + |
2684 | + this.div.onchildselect = $bind(this.on_childselect, this); |
2685 | +} |
2686 | +Clips.prototype = { |
2687 | + on_childselect: function(id) { |
2688 | + console.log('childselect ' + id); |
2689 | + $hscroll($(id)); |
2690 | + if (this.doc.selected_clips[this.id] != id) { |
2691 | + this.doc.selected_clips[this.id] = id; |
2692 | + this.session.save(this.doc, true); |
2693 | + this.session.delayed_commit(); |
2694 | + } |
2695 | + }, |
2696 | + |
2697 | + on_change: function(doc) { |
2698 | + console.log('Clips.on_change'); |
2699 | + this.doc = doc; |
2700 | + if (!this.doc.selected_clips) { |
2701 | + this.doc.selected_clips = {}; |
2702 | + } |
2703 | + var id = doc.dmedia_project_id; |
2704 | + this.dropdown.value = id; |
2705 | + if (this.load(id)) { |
2706 | + this.div.innerHTML = null; |
2707 | + this.load_clips(); |
2708 | + } |
2709 | + }, |
2710 | + |
2711 | + load: function(id) { |
2712 | + console.log('load ' + id); |
2713 | + if (!id) { |
2714 | + this.id = null; |
2715 | + this.db = null; |
2716 | + return false; |
2717 | + } |
2718 | + if (id == this.id) { |
2719 | + return false; |
2720 | + } |
2721 | + this.id = id; |
2722 | + this.db = dmedia_project_db(id); |
2723 | + return true; |
2724 | + }, |
2725 | + |
2726 | + load_projects: function() { |
2727 | + var callback = $bind(this.on_projects, this); |
2728 | + dmedia.view(callback, 'project', 'title'); |
2729 | + }, |
2730 | + |
2731 | + on_projects: function(req) { |
2732 | + var rows = req.read().rows; |
2733 | + this.dropdown.innerHTML = null; |
2734 | + this.placeholder = $el('option'); |
2735 | + this.dropdown.appendChild(this.placeholder); |
2736 | + rows.forEach(function(row) { |
2737 | + var option = $el('option', {textContent: row.key, value: row.id}); |
2738 | + this.dropdown.appendChild(option); |
2739 | + }, this); |
2740 | + }, |
2741 | + |
2742 | + on_dropdown_change: function(event) { |
2743 | + if (this.placeholder) { |
2744 | + $unparent(this.placeholder); |
2745 | + delete this.placeholder; |
2746 | + } |
2747 | + this.doc.dmedia_project_id = this.dropdown.value; |
2748 | + this.dropdown.blur(); |
2749 | + this.session.save(this.doc); |
2750 | + this.session.delayed_commit(); |
2751 | + }, |
2752 | + |
2753 | + load_clips: function() { |
2754 | + var callback = $bind(this.on_clips, this); |
2755 | + this.db.view(callback, 'user', 'video'); |
2756 | + }, |
2757 | + |
2758 | + on_clips: function(req) { |
2759 | + var rows = req.read().rows; |
2760 | + this.div.innerHTML = null; |
2761 | + var self = this; |
2762 | + rows.forEach(function(row) { |
2763 | + var id = row.id; |
2764 | + var img = new Image(); |
2765 | + img.id = id; |
2766 | + img.src = this.att_url(id); |
2767 | + img.onmousedown = function(event) { |
2768 | + self.on_mousedown(id, event); |
2769 | + } |
2770 | + img.ondblclick = function(event) { |
2771 | + self.on_dblclick(id, event); |
2772 | + } |
2773 | + this.div.appendChild(img); |
2774 | + }, this); |
2775 | + UI.select(this.doc.selected_clips[this.id]); |
2776 | + }, |
2777 | + |
2778 | + on_open_click: function(event) { |
2779 | + if (!this.container.classList.toggle('open')) { |
2780 | + var element = $(UI.selected); |
2781 | + if (element && element.parentNode.id == 'clips') { |
2782 | + UI.select(null); |
2783 | + } |
2784 | + } |
2785 | + }, |
2786 | + |
2787 | + on_mousedown: function(id, event) { |
2788 | + UI.select(id); |
2789 | + this.dnd = new DragEvent(event); |
2790 | + this.dnd.id = id; |
2791 | + this.dnd.ondragcancel = $bind(this.on_dragcancel, this); |
2792 | + this.dnd.ondragstart = $bind(this.on_dragstart, this); |
2793 | + }, |
2794 | + |
2795 | + on_dragcancel: function(dnd) { |
2796 | + delete this.dnd; |
2797 | + }, |
2798 | + |
2799 | + on_dragstart: function(dnd) { |
2800 | + this.dnd.ondrag = $bind(this.on_drag, this); |
2801 | + this.dnd.ondrop = $bind(this.on_drop, this); |
2802 | + }, |
2803 | + |
2804 | + on_drag: function(dnd) { |
2805 | + if (dnd.dy > 50) { |
2806 | + console.log('creating ' + dnd.dy); |
2807 | + dnd.ondrag = null; |
2808 | + UI.copy_clip(dnd.id); |
2809 | + var clip = this.session.get_doc(dnd.id); |
2810 | + var doc = create_slice(clip._id, clip.duration.frames); |
2811 | + this.session.save(doc, true); |
2812 | + var slice = new Slice(UI.session, doc); |
2813 | + slice.x = dnd.x - 64; |
2814 | + slice.y = dnd.y - 36; |
2815 | + UI.bucket.appendChild(slice.element); |
2816 | + slice.on_mousedown(dnd.event); |
2817 | + } |
2818 | + }, |
2819 | + |
2820 | + on_drop: function(dnd) { |
2821 | + delete this.dnd; |
2822 | + }, |
2823 | + |
2824 | + on_dblclick: function(id, event) { |
2825 | + UI.copy_clip(id); |
2826 | + UI.create_slice(id); |
2827 | + }, |
2828 | + |
2829 | + att_url: function(doc_or_id, name) { |
2830 | + if (!this.db) { |
2831 | + return null; |
2832 | + } |
2833 | + return this.db.att_url(doc_or_id, name); |
2834 | + }, |
2835 | + |
2836 | + att_css_url: function(doc_or_id, name) { |
2837 | + if (!this.db) { |
2838 | + return null; |
2839 | + } |
2840 | + return this.db.att_css_url(doc_or_id, name); |
2841 | + }, |
2842 | +} |
2843 | + |
2844 | + |
2845 | +var LoveOrb = function() { |
2846 | + this.logo = $el('img', {'id': 'logo', 'src': 'novacut.png'}); |
2847 | + document.body.appendChild(this.logo); |
2848 | + this.capture = $('flyout_capture'); |
2849 | + this.flyout = $('flyout'); |
2850 | + this.logo.onmousedown = $bind(this.on_mousedown, this); |
2851 | + this.logo.onclick = $bind(this.on_click, this); |
2852 | + this.capture.onclick = $bind(this.on_capture_click, this); |
2853 | + this.flyout.onclick = $bind(this.on_flyout_click, this); |
2854 | +} |
2855 | +LoveOrb.prototype = { |
2856 | + get active() { |
2857 | + return !this.capture.classList.contains('hide'); |
2858 | + }, |
2859 | + |
2860 | + toggle: function() { |
2861 | + if(this.capture.classList.toggle('hide')) { |
2862 | + this.logo.classList.remove('open'); |
2863 | + } |
2864 | + else { |
2865 | + this.logo.classList.add('open'); |
2866 | + } |
2867 | + }, |
2868 | + |
2869 | + on_mousedown: function(event) { |
2870 | + // Needed to prevent annoying drag behavior |
2871 | + $halt(event); |
2872 | + }, |
2873 | + |
2874 | + on_click: function(event) { |
2875 | + $halt(event); |
2876 | + this.toggle(); |
2877 | + }, |
2878 | + |
2879 | + on_capture_click: function(event) { |
2880 | + console.log('capture click'); |
2881 | + $halt(event); |
2882 | + this.toggle(); |
2883 | + }, |
2884 | + |
2885 | + on_flyout_click: function(event) { |
2886 | + console.log('flyout click'); |
2887 | + event.stopPropagation(); |
2888 | + }, |
2889 | +} |
2890 | + |
2891 | +function closeAll(){ |
2892 | + for(var a in UI.conts)UI.conts[a].close(); |
2893 | +} |
2894 | + |
2895 | + |
2896 | +function unselectAll(){ |
2897 | + for(var a in UI.selected){ |
2898 | + var b = UI.selected[a]; |
2899 | + $unselect(b); |
2900 | + } |
2901 | + UI.selected = Array(); |
2902 | +} |
2903 | + |
2904 | +var selector = { |
2905 | + init: function(){ |
2906 | + selector.down = false; |
2907 | + selector.el = ""; |
2908 | + selector.xs = 1; |
2909 | + selector.ys = 1; |
2910 | + }, |
2911 | + on_mouse_down: function(ev){ |
2912 | + closeAll(); |
2913 | + unselectAll(); |
2914 | + selector.down = true; |
2915 | + selector.el = $el('div', {'class': 'selector','id': 'sel'}); |
2916 | + selector.stx = ev.x; |
2917 | + selector.sty = ev.y; |
2918 | + selector.el.style.left = ev.x +'px'; |
2919 | + selector.el.style.top = ev.y +'px'; |
2920 | + UI.bucket.appendChild(selector.el); |
2921 | + }, |
2922 | + on_mouse_up: function(ev){ |
2923 | + console.log("mouse up"); |
2924 | + if(selector.down && selector.el && selector.el.parentNode){ |
2925 | + selector.el.parentNode.removeChild(selector.el); |
2926 | + if(document.getElementById('sel'))document.getElementById('sel').parentNode.removeChild(document.getElementById('sel')); |
2927 | + selector.down = false; |
2928 | + var stx = selector.stx; |
2929 | + var endx = selector.stx+selector.xs*parseInt(selector.el.style.width); |
2930 | + var sty = selector.sty; |
2931 | + var endy = selector.sty+selector.ys*parseInt(selector.el.style.height); |
2932 | + if(stx > endx){ |
2933 | + var tmp = stx; |
2934 | + stx = endx; |
2935 | + endx = tmp; |
2936 | + } |
2937 | + if(sty > endy){ |
2938 | + var tmp = sty; |
2939 | + sty = endy; |
2940 | + endy = tmp; |
2941 | + } |
2942 | + for(var a in UI.slices){ |
2943 | + var b = UI.slices[a]; |
2944 | + if(b.x > stx && b.x < endx && b.y > sty && b.y < endy){ |
2945 | + UI.selected.push(b.id); |
2946 | + $select(b.id); |
2947 | + } |
2948 | + } |
2949 | + for(var a in UI.conts){ |
2950 | + var b = UI.conts[a]; |
2951 | + if(b.x > stx && b.x < endx && b.y > sty && b.y < endy){ |
2952 | + UI.selected.push(b.id); |
2953 | + $select(b.id); |
2954 | + } |
2955 | + } |
2956 | + } |
2957 | + }, |
2958 | + on_mouse_move: function(ev){ |
2959 | + if(selector.down){ |
2960 | + var w = ev.x - selector.stx; |
2961 | + var h = ev.y - selector.sty; |
2962 | + selector.el.style.width = ev.x - selector.stx +'px'; |
2963 | + selector.el.style.height = ev.y - selector.sty +'px'; |
2964 | + selector.xs = 1; |
2965 | + selector.ys = 1; |
2966 | + if(w < 0){ |
2967 | + selector.el.style.width = -w + 'px'; |
2968 | + selector.el.style.left = ev.x + 'px'; |
2969 | + selector.xs = -1; |
2970 | + } |
2971 | + if(h < 0){ |
2972 | + selector.el.style.height = -h + 'px'; |
2973 | + selector.el.style.top = ev.y + 'px'; |
2974 | + selector.ys = -1; |
2975 | + } |
2976 | + } |
2977 | + } |
2978 | + |
2979 | +} |
2980 | + |
2981 | +function compare(a,b){ |
2982 | +return a.x-b.x; |
2983 | +} |
2984 | + |
2985 | +function generateAnimation(id,x,y,ex){//generate the animation |
2986 | + var keyframeprefix = "-webkit-"; |
2987 | + var keyframes = '@' + keyframeprefix + 'keyframes '+id+' { '+'0% {' + keyframeprefix + 'transform:scale(1)}'+'50% {' + keyframeprefix + 'transform:translatex('+x+'px) translatey('+y+'px)}'+'100% {' + keyframeprefix + 'transform:translatex('+ex+'px) translatey('+y+'px)}'+'}'; |
2988 | + keyframes += '#'+id+'{-webkit-animation-duration: 0.5s;-webkit-animation-iteration-count: 1;-webkit-animation-timing-function:linear;}'; |
2989 | + var s = document.createElement( 'style' ); |
2990 | + s.innerHTML = keyframes; |
2991 | + document.getElementsByTagName( 'head' )[ 0 ].appendChild( s ); |
2992 | +} |
2993 | + |
2994 | + |
2995 | +var UI = { |
2996 | + init: function() { |
2997 | + Hub.connect('edit_hashed', UI.on_edit_hashed); |
2998 | + Hub.connect('job_hashed', UI.on_job_hashed); |
2999 | + Hub.connect('job_rendered', UI.on_job_rendered); |
3000 | + |
3001 | + // Figure out what project we're in: |
3002 | + var parts = parse_hash(); |
3003 | + UI.project_id = parts[0]; |
3004 | + UI.db = novacut_project_db(UI.project_id); |
3005 | + |
3006 | + // Bit of UI setup |
3007 | + window.addEventListener('keyup', UI.on_keyup); |
3008 | + UI.bucket = $('bucket'); |
3009 | + UI.orb = new LoveOrb(); |
3010 | + document.getElementById('shortcuts').style.marginTop = window.innerHeight/2-200+"px"; |
3011 | + document.getElementById('shortcuts').style.marginLeft = window.innerWidth/2-255+"px"; |
3012 | + |
3013 | + //selector |
3014 | + UI.selected = Array(); |
3015 | + UI.bucket.addEventListener('mousedown', selector.on_mouse_down, false); |
3016 | + UI.bucket.addEventListener('mousemove', selector.on_mouse_move, false); |
3017 | + document.addEventListener('mouseup', selector.on_mouse_up, false); |
3018 | + |
3019 | + // Create and start the CouchDB session |
3020 | + UI.session = new couch.Session(UI.db, UI.on_new_doc); |
3021 | + UI.session.start(); |
3022 | + |
3023 | + UI.dragging = false; |
3024 | + UI.slices = Array(); |
3025 | + UI.conts = Array(); |
3026 | + document.body.onclick = $bind(closeAll); |
3027 | + }, |
3028 | + |
3029 | + animated: null, |
3030 | + |
3031 | + animate: function(element) { |
3032 | + if (UI.animated) { |
3033 | + UI.animated.classList.remove('animated'); |
3034 | + } |
3035 | + UI.animated = $(element); |
3036 | + if (UI.animated) { |
3037 | + UI.animated.classList.add('animated'); |
3038 | + } |
3039 | + }, |
3040 | + |
3041 | + copy_clip: function(id) { |
3042 | + try { |
3043 | + UI.session.get_doc(id); |
3044 | + } |
3045 | + catch (e) { |
3046 | + console.log('copying ' + id); |
3047 | + var doc = UI.clips.db.get_sync(id, {attachments: true}); |
3048 | + delete doc._rev; |
3049 | + UI.session.save(doc, true); |
3050 | + } |
3051 | + }, |
3052 | + |
3053 | + select: function(id) { |
3054 | + unselectAll(); |
3055 | + var element = $select(id); |
3056 | + if (element) { |
3057 | + UI.selected.push(id); |
3058 | + if (element.parentNode && element.parentNode.onchildselect) { |
3059 | + element.parentNode.onchildselect(id); |
3060 | + } |
3061 | + } |
3062 | + else { |
3063 | + UI.selected = Array(); |
3064 | + } |
3065 | + if (UI.sequence) { |
3066 | + var doc = UI.sequence.doc; |
3067 | + if (doc.selected != UI.selected) { |
3068 | + doc.selected = UI.selected; |
3069 | + UI.session.save(doc, true); // No local emit |
3070 | + UI.session.delayed_commit(); |
3071 | + } |
3072 | + } |
3073 | + }, |
3074 | + |
3075 | + delete_selected: function() { |
3076 | + for(var a in UI.selected){ |
3077 | + var id = UI.selected[a]; |
3078 | + var element = $(UI.selected[a]); |
3079 | + if (element) { |
3080 | + if (element.parentNode && element.parentNode.id == 'clips') { |
3081 | + console.log('no delete in clips browser'); |
3082 | + return; |
3083 | + } |
3084 | + try { |
3085 | + var doc = UI.session.get_doc(element.id); |
3086 | + UI.previous(); |
3087 | + doc._deleted = true; |
3088 | + UI.session.save(doc); |
3089 | + if(doc.node.type == 'cont')for(var a in UI.conts){ |
3090 | + if(UI.conts[a].id == id)UI.conts.splice(a,1); |
3091 | + } |
3092 | + if(doc.node.type == 'slice')for(var a in UI.slices){ |
3093 | + if(UI.slices[a].id == id)UI.slices.splice(a,1); |
3094 | + } |
3095 | + } |
3096 | + catch (e) { |
3097 | + return; |
3098 | + } |
3099 | + } |
3100 | + } |
3101 | + }, |
3102 | + |
3103 | + group_selected: function(){ |
3104 | + var ndoc = create_cont(); |
3105 | + var list = Array(); |
3106 | + if(UI.selected.length < 2)return; |
3107 | + for(var a in UI.selected){//get all the slices |
3108 | + var doc = UI.session.get_doc(UI.selected[a]); |
3109 | + if(doc.node.type == 'slice'){ |
3110 | + for(var b in UI.slices)if(UI.slices[b].id == UI.selected[a]){ |
3111 | + list.push(UI.slices[b]); |
3112 | + UI.slices.splice(b,1); |
3113 | + } |
3114 | + //UI.bucket.removeChild(document.getElementById(UI.selected[a])) |
3115 | + //ndoc.node.src.push(UI.selected[a]); |
3116 | + } |
3117 | + } |
3118 | + if(list.length < 2)return; |
3119 | + list.sort(compare);//sort for x position |
3120 | + var y = 0; |
3121 | + for(var a in list){//add the slices in the doc and compute the average y |
3122 | + ndoc.node.src.push(list[a].id); |
3123 | + y += list[a].y; |
3124 | + } |
3125 | + y /= list.length; |
3126 | + UI.session.save(ndoc); |
3127 | + var ncont = new Cont(UI.session,ndoc); |
3128 | + ncont.x = list[0].x; |
3129 | + ncont.y = y; |
3130 | + for(var a in list){//animate to form a line |
3131 | + generateAnimation(list[a].id,list[0].x+(a*130)-list[a].x,y-list[a].y,list[0].x-list[a].x); |
3132 | + list[a].element.style.webkitAnimationName = list[a].id; |
3133 | + console.log('animate'); |
3134 | + list[a].element.addEventListener('webkitAnimationEnd',function(ev){ |
3135 | + //console.log('end'); |
3136 | + /*this.style.webkitAnimationName = ""; |
3137 | + this.style.top = "0px"; |
3138 | + this.style.left = "0px"; |
3139 | + $unparent(this); |
3140 | + ncont.list.appendChild(this); |
3141 | + ncont.close();*/ |
3142 | + UI.bucket.removeChild(this); |
3143 | + UI.sequence.do_reorder(); |
3144 | + |
3145 | + }); |
3146 | + } |
3147 | + //setTimeout(UI.sequence.do_reorder(),530); |
3148 | + //setTimeout(function(){for(var a in list)UI.bucket.removeChild(document.getElementById(list[a].id));},530,list); |
3149 | + UI.bucket.appendChild(ncont.element); |
3150 | + }, |
3151 | + |
3152 | + duplicate_selected: function() { |
3153 | + for(var a in UI.selected){ |
3154 | + var element = $(UI.selected[a]); |
3155 | + var doc = UI.session.get_doc(element.id); |
3156 | + if(doc.node.type == 'slice'){ |
3157 | + var ndoc = create_slice(doc.node.src,doc.node.stop.frame); |
3158 | + ndoc.node.start.frame = doc.node.start.frame; |
3159 | + UI.session.save(ndoc); |
3160 | + var slice = new Slice(UI.session, ndoc); |
3161 | + } |
3162 | + if(doc.node.type == 'cont'){ |
3163 | + var ndoc = create_cont(); |
3164 | + ndoc.node.src = doc.node.src; |
3165 | + UI.session.save(ndoc); |
3166 | + var slice = new Cont(UI.session, ndoc); |
3167 | + } |
3168 | + slice.x = parseInt(element.style.left)-30; |
3169 | + slice.y = parseInt(element.style.top)-30; |
3170 | + UI.bucket.appendChild(slice.element); |
3171 | + } |
3172 | + UI.sequence.do_reorder(); |
3173 | + }, |
3174 | + |
3175 | + first: function() { |
3176 | + var element = $(UI.selected); |
3177 | + if (element && element.parentNode) { |
3178 | + UI.select(element.parentNode.children[0].id); |
3179 | + } |
3180 | + }, |
3181 | + |
3182 | + previous: function() { |
3183 | + var element = $(UI.selected); |
3184 | + if (element && element.previousSibling) { |
3185 | + UI.select(element.previousSibling.id); |
3186 | + } |
3187 | + }, |
3188 | + |
3189 | + next: function() { |
3190 | + var element = $(UI.selected); |
3191 | + if (element && element.nextSibling) { |
3192 | + UI.select(element.nextSibling.id); |
3193 | + } |
3194 | + }, |
3195 | + |
3196 | + last: function() { |
3197 | + var element = $(UI.selected); |
3198 | + if (element && element.parentNode) { |
3199 | + var i = element.parentNode.children.length - 1; |
3200 | + UI.select(element.parentNode.children[i].id); |
3201 | + } |
3202 | + }, |
3203 | + |
3204 | + |
3205 | + get_slice: function(_id) { |
3206 | + var element = $unparent(_id); |
3207 | + if (element) { |
3208 | + console.log(_id); |
3209 | + return element; |
3210 | + } |
3211 | + try { |
3212 | + var doc = UI.session.get_doc(_id); |
3213 | + } |
3214 | + catch (e) { |
3215 | + return null; |
3216 | + } |
3217 | + console.log(_id); |
3218 | + if(doc.node.type == 'slice'){ |
3219 | + var slice = new Slice(UI.session, doc); |
3220 | + return slice.element; |
3221 | + } |
3222 | + if(doc.node.type == 'cont'){ |
3223 | + var slice = new Cont(UI.session, doc); |
3224 | + return slice.element; |
3225 | + } |
3226 | + }, |
3227 | + |
3228 | + on_new_doc: function(doc) { |
3229 | + if (doc._id == UI.project_id) { |
3230 | + UI.doc = doc; |
3231 | + |
3232 | + // FIXME: create default sequence if needed |
3233 | + if (!UI.doc.root_id) { |
3234 | + console.log('creating default sequence'); |
3235 | + var seq = create_sequence(); |
3236 | + UI.doc.root_id = seq._id; |
3237 | + UI.session.save(UI.doc, true); |
3238 | + UI.session.save(seq, true); |
3239 | + UI.session.delayed_commit(); |
3240 | + } |
3241 | + |
3242 | + UI.sequence = new Sequence(UI.session, UI.session.get_doc(UI.doc.root_id)); |
3243 | + UI.clips = new Clips(dmedia); |
3244 | + UI.player= new SequencePlayer(UI.session, UI.sequence.doc); |
3245 | + //closeAll(); |
3246 | + |
3247 | + } |
3248 | + }, |
3249 | + |
3250 | + _roughcut: null, |
3251 | + |
3252 | + get roughcut() { |
3253 | + if (UI._roughcut == null) { |
3254 | + UI._roughcut = new RoughCut(UI.session); |
3255 | + } |
3256 | + return UI._roughcut; |
3257 | + }, |
3258 | + |
3259 | + create_slice: function(id) { |
3260 | + UI.roughcut.show(id); |
3261 | + UI.roughcut.create_slice(); |
3262 | + }, |
3263 | + |
3264 | + edit_slice: function(doc) { |
3265 | + UI.roughcut.show(doc.node.src); |
3266 | + UI.roughcut.edit_slice(doc); |
3267 | + }, |
3268 | + |
3269 | + hide_roughcut: function() { |
3270 | + UI.roughcut.hide(); |
3271 | + }, |
3272 | + |
3273 | + // Key bindings |
3274 | + actions: { |
3275 | + // Left arrow |
3276 | + 'Left': function(event) { |
3277 | + if (event.shiftKey) { |
3278 | + UI.first(); |
3279 | + } |
3280 | + else { |
3281 | + UI.previous(); |
3282 | + } |
3283 | + if (UI.player.active) { |
3284 | + UI.player.hold_and_resume(); |
3285 | + } |
3286 | + }, |
3287 | + |
3288 | + // Right arrow |
3289 | + 'Right': function(event) { |
3290 | + if (event.shiftKey) { |
3291 | + UI.last(); |
3292 | + } |
3293 | + else { |
3294 | + UI.next(); |
3295 | + } |
3296 | + if (UI.player.active) { |
3297 | + UI.player.hold_and_resume(); |
3298 | + } |
3299 | + }, |
3300 | + //G |
3301 | + 'U+0047': function(event){ |
3302 | + UI.group_selected(); |
3303 | + }, |
3304 | + //D |
3305 | + 'U+0044': function(event) { |
3306 | + UI.duplicate_selected(); |
3307 | + }, |
3308 | + |
3309 | + // The David Fulde key |
3310 | + // aka Backspace aka Big Delete on a mac keyboard |
3311 | + 'U+0008': function(event) { |
3312 | + UI.delete_selected(); |
3313 | + }, |
3314 | + |
3315 | + // Delete |
3316 | + 'U+007F': function(event) { |
3317 | + UI.delete_selected(); |
3318 | + }, |
3319 | + |
3320 | + // SpaceBar |
3321 | + 'U+0020': function(event) { |
3322 | + if (UI.roughcut.active) { |
3323 | + UI.roughcut.playpause(); |
3324 | + } |
3325 | + else { |
3326 | + if (UI.player.active) { |
3327 | + UI.player.playpause(); |
3328 | + } |
3329 | + else { |
3330 | + UI.player.show(); |
3331 | + } |
3332 | + } |
3333 | + }, |
3334 | + |
3335 | + // Escape |
3336 | + 'U+001B': function(event) { |
3337 | + if (UI.player.active) { |
3338 | + UI.player.hide(); |
3339 | + } |
3340 | + }, |
3341 | + }, |
3342 | + |
3343 | + on_keyup: function(event) { |
3344 | + console.log('keyup ' + event.keyIdentifier); |
3345 | + if (document.activeElement != document.body) { |
3346 | + console.log('document body not focused'); |
3347 | + return; |
3348 | + } |
3349 | + if (UI.orb.active) { |
3350 | + if (event.keyIdentifier == 'U+001B') { |
3351 | + UI.orb.toggle(); |
3352 | + } |
3353 | + return; |
3354 | + } |
3355 | + var action = UI.actions[event.keyIdentifier]; |
3356 | + if (action) { |
3357 | + $halt(event); |
3358 | + action(event); |
3359 | + } |
3360 | + }, |
3361 | + |
3362 | + render: function() { |
3363 | + $("render-btn").disabled = true; |
3364 | + $("render-btn").blur(); |
3365 | + UI.orb.toggle(); |
3366 | + console.log('render'); |
3367 | + }, |
3368 | + |
3369 | + on_edit_hashed: function(project_id, node_id, intrinsic_id) { |
3370 | + console.log(['edit_hashed', project_id, node_id, intrinsic_id].join(' ')); |
3371 | + // null for default settings_id: |
3372 | + Hub.send('hash_job', intrinsic_id, null); |
3373 | + }, |
3374 | + |
3375 | + on_job_hashed: function(intrinsic_id, settings_id, job_id) { |
3376 | + console.log(['job_hashed', intrinsic_id, settings_id, job_id].join(' ')); |
3377 | + Hub.send('render_job', job_id); |
3378 | + }, |
3379 | + |
3380 | + on_job_rendered: function(job_id, file_id, link) { |
3381 | + console.log(['job_rendered', job_id, file_id, link].join(' ')); |
3382 | + //UI.player.src = 'dmedia:' + file_id; |
3383 | + //UI.player.play(); |
3384 | + $("render-btn").disabled = false; |
3385 | + }, |
3386 | +} |
3387 | + |
3388 | +function showShort(event){ |
3389 | + console.log('show'); |
3390 | + UI.orb.toggle(); |
3391 | + document.getElementById("shortcuts").style.display = "block"; |
3392 | + event.stopPropagation(); |
3393 | + document.body.onclick = $bind(hideShort); |
3394 | +} |
3395 | + |
3396 | +function hideShort(event){ |
3397 | + console.log('hide'); |
3398 | + document.getElementById("shortcuts").style.display = "none"; |
3399 | + event.stopPropagation(); |
3400 | +} |
3401 | + |
3402 | +window.addEventListener('load', UI.init); |
3403 | + |
3404 | + |
3405 | |
3406 | === added file 'ui/novacut2.js' |
3407 | --- ui/novacut2.js 1970-01-01 00:00:00 +0000 |
3408 | +++ ui/novacut2.js 2012-08-14 17:10:21 +0000 |
3409 | @@ -0,0 +1,416 @@ |
3410 | +"use strict"; |
3411 | + |
3412 | +var novacut = new couch.Database('novacut-0'); |
3413 | +var dmedia = new couch.Database('dmedia-0'); |
3414 | + |
3415 | +function parse_hash() { |
3416 | + return window.location.hash.slice(1).split('/'); |
3417 | +} |
3418 | + |
3419 | +function set_title(id, value) { |
3420 | + var el = $(id); |
3421 | + if (value) { |
3422 | + el.textContent = value; |
3423 | + } |
3424 | + else { |
3425 | + el.textContent = ''; |
3426 | + el.appendChild($el('em', {textContent: 'Untitled'})); |
3427 | + } |
3428 | + return el; |
3429 | +} |
3430 | + |
3431 | + |
3432 | +function project_db(base, ver, project_id) { |
3433 | + var name = [base, ver, project_id.toLowerCase()].join('-'); |
3434 | + return new couch.Database(name); |
3435 | +} |
3436 | + |
3437 | + |
3438 | +function novacut_project_db(project_id) { |
3439 | + return project_db('novacut', 0, project_id); |
3440 | +} |
3441 | + |
3442 | + |
3443 | +function dmedia_project_db(project_id) { |
3444 | + return project_db('dmedia', 0, project_id); |
3445 | +} |
3446 | + |
3447 | + |
3448 | +function frame_to_seconds(frame, framerate) { |
3449 | + return frame * framerate.denom / framerate.num; |
3450 | +} |
3451 | + |
3452 | + |
3453 | +function seconds_to_frame(seconds, framerate) { |
3454 | + return Math.round(seconds * framerate.num / framerate.denom); |
3455 | +} |
3456 | + |
3457 | + |
3458 | + |
3459 | +function create_node(node) { |
3460 | + return { |
3461 | + '_id': couch.random_id(), |
3462 | + 'ver': 0, |
3463 | + 'type': 'novacut/node', |
3464 | + 'time': couch.time(), |
3465 | + 'node': node, |
3466 | + } |
3467 | +} |
3468 | + |
3469 | + |
3470 | +function create_slice(src, frame_count) { |
3471 | + var node = { |
3472 | + 'type': 'slice', |
3473 | + 'src': src, |
3474 | + 'start': {'frame': 0}, |
3475 | + 'stop': {'frame': frame_count}, |
3476 | + 'stream': 'both', |
3477 | + } |
3478 | + return create_node(node); |
3479 | +} |
3480 | + |
3481 | +function create_cont() { |
3482 | + var node = { |
3483 | + 'type': 'cont', |
3484 | + 'src': [], |
3485 | + } |
3486 | + return create_node(node); |
3487 | +} |
3488 | + |
3489 | +function create_sequence() { |
3490 | + var node = { |
3491 | + 'type': 'sequence', |
3492 | + 'src': [], |
3493 | + } |
3494 | + var doc = create_node(node); |
3495 | + doc.doodle = []; |
3496 | + return doc; |
3497 | +} |
3498 | + |
3499 | + |
3500 | +function SlicePlayer() { |
3501 | + this.video = document.createElement('video'); |
3502 | + //this.video.muted = true; |
3503 | + this.video.addEventListener('canplaythrough', |
3504 | + $bind(this.on_canplaythrough, this) |
3505 | + ); |
3506 | + this.video.addEventListener('seeked', |
3507 | + $bind(this.on_seeked, this) |
3508 | + ); |
3509 | + this.video.addEventListener('ended', |
3510 | + $bind(this.on_ended, this) |
3511 | + ); |
3512 | + |
3513 | + this.timeout_id = null; |
3514 | + |
3515 | + this.playing = false; |
3516 | + this.ready = false; |
3517 | + this.ended = false; |
3518 | + |
3519 | + this.onready = null; |
3520 | + this.onended = null; |
3521 | +} |
3522 | +SlicePlayer.prototype = { |
3523 | + log_event: function(name, point) { |
3524 | + var frame = seconds_to_frame(this.video.currentTime, this.clip.framerate); |
3525 | + var parts = [name, frame, point, frame == point]; |
3526 | + console.log(parts.join(' ')); |
3527 | + }, |
3528 | + |
3529 | + on_canplaythrough: function(event) { |
3530 | + this.seek(this.slice.node.start.frame); |
3531 | + }, |
3532 | + |
3533 | + on_seeked: function(event) { |
3534 | + //this.log_event('seeked', this.slice.node.start.frame); |
3535 | + if (!this.ready) { |
3536 | + this.ready = true; |
3537 | + if (this.onready) { |
3538 | + this.onready(this); |
3539 | + } |
3540 | + } |
3541 | + }, |
3542 | + |
3543 | + on_ended: function(event) { |
3544 | + this.video.pause(); |
3545 | + this.clear_timeout(); |
3546 | + //this.log_event('ended', this.slice.node.stop.frame); |
3547 | + this.ended = true; |
3548 | + if (this.onended) { |
3549 | + this.onended(this); |
3550 | + } |
3551 | + }, |
3552 | + |
3553 | + seek: function(frame) { |
3554 | + this.video.currentTime = this.frame_to_seconds(frame); |
3555 | + }, |
3556 | + |
3557 | + frame_to_seconds: function(frame) { |
3558 | + return frame_to_seconds(frame, this.clip.framerate); |
3559 | + }, |
3560 | + |
3561 | + clear_timeout: function() { |
3562 | + if (this.timeout_id != null) { |
3563 | + clearTimeout(this.timeout_id); |
3564 | + this.timeout_id = null; |
3565 | + } |
3566 | + }, |
3567 | + |
3568 | + set_timeout: function(duration) { |
3569 | + this.clear_timeout(); |
3570 | + var callback = $bind(this.on_ended, this); |
3571 | + this.timeout_id = setTimeout(callback, duration); |
3572 | + }, |
3573 | + |
3574 | + playpause: function() { |
3575 | + if (this.playing) { |
3576 | + this.pause(); |
3577 | + } |
3578 | + else { |
3579 | + this.play(); |
3580 | + } |
3581 | + }, |
3582 | + |
3583 | + play: function() { |
3584 | + if (this.playing || !this.ready) { |
3585 | + return; |
3586 | + } |
3587 | + this.playing = true; |
3588 | + this.video.style.visibility = 'visible'; |
3589 | + if (this.slice.node.stop.frame != this.clip.duration.frames) { |
3590 | + var stop = this.frame_to_seconds(this.slice.node.stop.frame); |
3591 | + var duration = 1000 * (stop - this.video.currentTime); |
3592 | + this.set_timeout(duration); |
3593 | + } |
3594 | + this.video.play(); |
3595 | + }, |
3596 | + |
3597 | + pause: function() { |
3598 | + if (!this.ready) { |
3599 | + return; |
3600 | + } |
3601 | + this.playing = false; |
3602 | + this.video.style.visibility = 'visible'; |
3603 | + this.clear_timeout(); |
3604 | + this.video.pause(); |
3605 | + }, |
3606 | + |
3607 | + stop: function() { |
3608 | + this.video.style.visibility = 'hidden'; |
3609 | + this.video.pause(); |
3610 | + this.clear_timeout(); |
3611 | + this.ended = false; |
3612 | + this.ready = false; |
3613 | + this.playing = false; |
3614 | + }, |
3615 | + |
3616 | + load_slice: function(clip, slice) { |
3617 | + this.stop(); |
3618 | + this.clip = clip; |
3619 | + this.slice = slice; |
3620 | + this.video.src = 'dmedia:' + this.clip._id; |
3621 | + //setTimeout($bind(this.do_load, this), 50); |
3622 | + }, |
3623 | + |
3624 | + do_load: function() { |
3625 | + this.video.src = 'dmedia:' + this.clip._id; |
3626 | + }, |
3627 | +} |
3628 | + |
3629 | + |
3630 | + |
3631 | +function SequencePlayer(session, doc) { |
3632 | + this.session = session; |
3633 | + this.doc = doc; |
3634 | + |
3635 | + this.element = $el('div', {'id': 'player', 'class': 'hide'}); |
3636 | + |
3637 | + this.player1 = new SlicePlayer(); |
3638 | + this.player1.i = 0; |
3639 | + this.player2 = new SlicePlayer(); |
3640 | + this.player2.i = 1; |
3641 | + |
3642 | + this.players = [this.player1, this.player2]; |
3643 | + var on_ready = $bind(this.on_ready, this); |
3644 | + var on_ended = $bind(this.on_ended, this); |
3645 | + this.players.forEach(function(player) { |
3646 | + player.onready = on_ready; |
3647 | + player.onended = on_ended; |
3648 | + this.element.appendChild(player.video); |
3649 | + }, this); |
3650 | + |
3651 | + this.ready = false; |
3652 | + this.playing = false; |
3653 | + this.active = false; |
3654 | + |
3655 | + this.timeout_id == null |
3656 | + |
3657 | + this.element.onclick = $bind(this.playpause, this); |
3658 | + |
3659 | + document.body.appendChild(this.element); |
3660 | + |
3661 | +} |
3662 | +SequencePlayer.prototype = { |
3663 | + show: function() { |
3664 | + console.log('show'); |
3665 | + if (this.doc.node.src.length == 0) { |
3666 | + return; |
3667 | + } |
3668 | + $show(this.element); |
3669 | + this.active = true; |
3670 | + this.playing = true; |
3671 | + this.play_from_slice(UI.selected); |
3672 | + }, |
3673 | + |
3674 | + soft_hide: function() { |
3675 | + $hide(this.element); |
3676 | + console.assert(!this.playing); |
3677 | + }, |
3678 | + |
3679 | + soft_show: function() { |
3680 | + $show(this.element); |
3681 | + console.assert(!this.playing); |
3682 | + }, |
3683 | + |
3684 | + hide: function() { |
3685 | + console.log('hide'); |
3686 | + $hide(this.element); |
3687 | + this.active = false; |
3688 | + this.stop(); |
3689 | + }, |
3690 | + |
3691 | + playpause: function() { |
3692 | + if (this.playing) { |
3693 | + this.pause(); |
3694 | + } |
3695 | + else { |
3696 | + this.play(); |
3697 | + } |
3698 | + }, |
3699 | + |
3700 | + hold: function() { |
3701 | + this.was_playing = this.playing; |
3702 | + this.playing = false; |
3703 | + this.activate_target(true); |
3704 | + }, |
3705 | + |
3706 | + hold_and_resume: function() { |
3707 | + if (this.timeout_id == null) { |
3708 | + console.log('first hold'); |
3709 | + this.hold(); |
3710 | + } |
3711 | + clearTimeout(this.timeout_id); |
3712 | + this.timeout_id = setTimeout($bind(this.on_timeout, this), 500); |
3713 | + }, |
3714 | + |
3715 | + on_timeout: function() { |
3716 | + console.log('timeout'); |
3717 | + this.timeout_id = null; |
3718 | + this.resume(); |
3719 | + }, |
3720 | + |
3721 | + resume: function() { |
3722 | + this.playing = this.was_playing; |
3723 | + if (UI.selected) { |
3724 | + this.play_from_slice(UI.selected); |
3725 | + } |
3726 | + else { |
3727 | + this.activate_target(true); |
3728 | + } |
3729 | + }, |
3730 | + |
3731 | + stop: function() { |
3732 | + this.players.forEach(function(player) { |
3733 | + player.stop(); |
3734 | + }); |
3735 | + this.ready = false; |
3736 | + this.target = null; |
3737 | + }, |
3738 | + |
3739 | + play: function() { |
3740 | + this.playing = true; |
3741 | + this.activate_target(); |
3742 | + }, |
3743 | + |
3744 | + pause: function() { |
3745 | + this.playing = false; |
3746 | + this.activate_target(); |
3747 | + }, |
3748 | + |
3749 | + play_from_slice: function(slice_id) { |
3750 | + if (this.doc.node.src.length == 0) { |
3751 | + return; |
3752 | + } |
3753 | + this.stop(); |
3754 | + if (!slice_id) { |
3755 | + slice_id = UI.selected; |
3756 | + } |
3757 | + console.log('play_from_slice ' + slice_id); |
3758 | + var index = Math.max(0, this.doc.node.src.indexOf(slice_id)); |
3759 | + this.load_slice(this.player1, index); |
3760 | + this.load_slice(this.player2, index + 1); |
3761 | + }, |
3762 | + |
3763 | + get_player: function(i) { |
3764 | + return this.players[i % this.players.length]; |
3765 | + }, |
3766 | + |
3767 | + next_slice_index: function(player) { |
3768 | + return this.doc.node.src.indexOf(player.slice._id) + 1; |
3769 | + }, |
3770 | + |
3771 | + load_slice: function(player, index) { |
3772 | + var src = this.doc.node.src; |
3773 | + var slice_id = src[index % src.length]; |
3774 | + var slice = this.session.get_doc(slice_id); |
3775 | + var clip = this.session.get_doc(slice.node.src); |
3776 | + player.load_slice(clip, slice); |
3777 | + }, |
3778 | + |
3779 | + on_ready: function(player) { |
3780 | + if (!this.ready) { |
3781 | + if (this.player1.ready && this.player2.ready) { |
3782 | + console.log('now ready'); |
3783 | + this.ready = true; |
3784 | + this.target = this.players[0]; |
3785 | + this.activate_target(); |
3786 | + } |
3787 | + } |
3788 | + else if (this.target.ended) { |
3789 | + this.swap(); |
3790 | + } |
3791 | + }, |
3792 | + |
3793 | + activate_target: function(no_select) { |
3794 | + if (!this.target) { |
3795 | + return; |
3796 | + } |
3797 | + if (this.playing) { |
3798 | + this.target.play(); |
3799 | + } |
3800 | + else { |
3801 | + this.target.pause(); |
3802 | + } |
3803 | + if (!no_select) { |
3804 | + UI.select(this.target.slice._id, true); |
3805 | + } |
3806 | + }, |
3807 | + |
3808 | + swap: function() { |
3809 | + var current = this.target; |
3810 | + var next = this.get_player(current.i + 1); |
3811 | + if (next.ready) { |
3812 | + this.target = next; |
3813 | + var index = this.next_slice_index(next); |
3814 | + this.activate_target(); |
3815 | + this.load_slice(current, index); |
3816 | + } |
3817 | + }, |
3818 | + |
3819 | + on_ended: function(player) { |
3820 | + this.swap(); |
3821 | + }, |
3822 | +} |
3823 | + |
3824 | + |
3825 | + |