16 function rand16(n) { |
15 function rand16(n) { |
17 return pad(n, Math.floor(Math.random()*Math.pow(16,n)), 16); |
16 return pad(n, Math.floor(Math.random()*Math.pow(16,n)), 16); |
18 } |
17 } |
19 |
18 |
20 var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000); |
19 var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000); |
21 |
20 |
|
21 var charsub = [ |
|
22 [ 'a', 'á', 'à', 'â', 'ä' ], |
|
23 [ 'c', 'ç' ], |
|
24 [ 'e', 'é', 'è', 'ê', 'ë' ], |
|
25 [ 'i', 'í', 'ì', 'î', 'ï' ], |
|
26 [ 'o', 'ó', 'ò', 'ô', 'ö' ] |
|
27 ]; |
|
28 |
|
29 var removeChars = [ |
|
30 String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807), |
|
31 "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ", |
|
32 ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/" |
|
33 ] |
|
34 |
22 var Model = { |
35 var Model = { |
23 _SOURCE_STATUS_EMPTY : 0, |
36 _SOURCE_STATUS_EMPTY : 0, |
24 _SOURCE_STATUS_WAITING : 1, |
37 _SOURCE_STATUS_WAITING : 1, |
25 _SOURCE_STATUS_READY : 2, |
38 _SOURCE_STATUS_READY : 2, |
26 getUID : function() { |
39 getUID : function() { |
27 return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6); |
40 return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6); |
|
41 }, |
|
42 isLocalURL : function(url) { |
|
43 var matches = url.match(/^(\w+:)\/\/([^/]+)/); |
|
44 if (matches) { |
|
45 return(matches[1] === document.location.protocol && matches[2] === document.location.host) |
|
46 } |
|
47 return true; |
28 }, |
48 }, |
29 regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) { |
49 regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) { |
30 var _testOnly = _testOnly || false, |
50 var _testOnly = _testOnly || false, |
31 _iexact = _iexact || false; |
51 _iexact = _iexact || false; |
32 function escapeText(_text) { |
52 function escapeText(_text) { |
43 } |
63 } |
44 if (_iexact) { |
64 if (_iexact) { |
45 _source = '^' + _source + '$'; |
65 _source = '^' + _source + '$'; |
46 } |
66 } |
47 return new RegExp( _source, _flags); |
67 return new RegExp( _source, _flags); |
|
68 }, |
|
69 fullTextRegexps: function(_text) { |
|
70 var remsrc = "[\\" + removeChars.join("\\") + "]", |
|
71 remrx = new RegExp(remsrc,"gm"), |
|
72 txt = _text.toLowerCase().replace(remrx,"") |
|
73 res = [], |
|
74 charsrc = ns._(charsub).map(function(c) { |
|
75 return "(" + c.join("|") + ")"; |
|
76 }), |
|
77 charsrx = ns._(charsrc).map(function(c) { |
|
78 return new RegExp(c); |
|
79 }), |
|
80 src = ""; |
|
81 for (var j = 0; j < txt.length; j++) { |
|
82 if (j) { |
|
83 src += remsrc + "*"; |
|
84 } |
|
85 var l = txt[j]; |
|
86 ns._(charsrc).each(function(v, k) { |
|
87 l = l.replace(charsrx[k], v); |
|
88 }); |
|
89 src += l; |
|
90 } |
|
91 return "(" + src + ")"; |
48 }, |
92 }, |
49 isoToDate : function(_str) { |
93 isoToDate : function(_str) { |
50 // http://delete.me.uk/2005/03/iso8601.html |
94 // http://delete.me.uk/2005/03/iso8601.html |
51 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; |
95 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; |
52 var d = _str.match(new RegExp(regexp)); |
96 var d = _str.match(new RegExp(regexp)); |
472 this.on("pause", function() { |
554 this.on("pause", function() { |
473 _this.paused = true; |
555 _this.paused = true; |
474 }); |
556 }); |
475 this.on("timeupdate", function(_time) { |
557 this.on("timeupdate", function(_time) { |
476 _this.currentTime = _time; |
558 _this.currentTime = _time; |
477 }); |
|
478 } |
|
479 |
|
480 Model.Playable.prototype = new Model.Element(); |
|
481 |
|
482 Model.Playable.prototype.getCurrentTime = function() { |
|
483 return this.currentTime; |
|
484 } |
|
485 |
|
486 Model.Playable.prototype.getVolume = function() { |
|
487 return this.volume; |
|
488 } |
|
489 |
|
490 Model.Playable.prototype.getPaused = function() { |
|
491 return this.paused; |
|
492 } |
|
493 |
|
494 Model.Playable.prototype.getMuted = function() { |
|
495 return this.muted; |
|
496 } |
|
497 |
|
498 Model.Playable.prototype.setCurrentTime = function(_time) { |
|
499 this.trigger("setcurrenttime",_time); |
|
500 } |
|
501 |
|
502 Model.Playable.prototype.setVolume = function(_vol) { |
|
503 this.trigger("setvolume",_vol); |
|
504 } |
|
505 |
|
506 Model.Playable.prototype.setMuted = function(_muted) { |
|
507 this.trigger("setmuted",_muted); |
|
508 } |
|
509 |
|
510 Model.Playable.prototype.play = function() { |
|
511 this.trigger("setplay"); |
|
512 } |
|
513 |
|
514 Model.Playable.prototype.pause = function() { |
|
515 this.trigger("setpause"); |
|
516 } |
|
517 |
|
518 |
|
519 /* */ |
|
520 |
|
521 Model.Media = function(_id, _source) { |
|
522 Model.Playable.call(this, _id, _source); |
|
523 this.elementType = 'media'; |
|
524 this.duration = new Model.Time(); |
|
525 this.video = ''; |
|
526 |
|
527 var _this = this; |
|
528 this.on("timeupdate", function(_time) { |
|
529 _this.getAnnotations().filter(function(_a) { |
559 _this.getAnnotations().filter(function(_a) { |
530 return (_a.end <= _time || _a.begin > _time) && _a.playing |
560 return (_a.end <= _time || _a.begin > _time) && _a.playing |
531 }).forEach(function(_a) { |
561 }).forEach(function(_a) { |
532 _a.playing = false; |
562 _a.playing = false; |
533 _a.trigger("leave"); |
563 _a.trigger("leave"); |
|
564 _this.trigger("leave-annotation",_a); |
534 }); |
565 }); |
535 _this.getAnnotations().filter(function(_a) { |
566 _this.getAnnotations().filter(function(_a) { |
536 return _a.begin <= _time && _a.end > _time && !_a.playing |
567 return _a.begin <= _time && _a.end > _time && !_a.playing |
537 }).forEach(function(_a) { |
568 }).forEach(function(_a) { |
538 _a.playing = true; |
569 _a.playing = true; |
539 _a.trigger("enter"); |
570 _a.trigger("enter"); |
|
571 _this.trigger("enter-annotation",_a); |
540 }); |
572 }); |
541 }); |
573 }); |
|
574 } |
|
575 |
|
576 Model.Playable.prototype = new Model.Element(); |
|
577 |
|
578 Model.Playable.prototype.getCurrentTime = function() { |
|
579 return this.currentTime; |
|
580 } |
|
581 |
|
582 Model.Playable.prototype.getVolume = function() { |
|
583 return this.volume; |
|
584 } |
|
585 |
|
586 Model.Playable.prototype.getPaused = function() { |
|
587 return this.paused; |
|
588 } |
|
589 |
|
590 Model.Playable.prototype.getMuted = function() { |
|
591 return this.muted; |
|
592 } |
|
593 |
|
594 Model.Playable.prototype.setCurrentTime = function(_time) { |
|
595 this.trigger("setcurrenttime",_time); |
|
596 } |
|
597 |
|
598 Model.Playable.prototype.setVolume = function(_vol) { |
|
599 this.trigger("setvolume",_vol); |
|
600 } |
|
601 |
|
602 Model.Playable.prototype.setMuted = function(_muted) { |
|
603 this.trigger("setmuted",_muted); |
|
604 } |
|
605 |
|
606 Model.Playable.prototype.play = function() { |
|
607 this.trigger("setplay"); |
|
608 } |
|
609 |
|
610 Model.Playable.prototype.pause = function() { |
|
611 this.trigger("setpause"); |
|
612 } |
|
613 |
|
614 Model.Playable.prototype.show = function() {} |
|
615 |
|
616 Model.Playable.prototype.hide = function() {} |
|
617 |
|
618 /* */ |
|
619 |
|
620 Model.Media = function(_id, _source) { |
|
621 Model.Playable.call(this, _id, _source); |
|
622 this.elementType = 'media'; |
|
623 this.duration = new Model.Time(); |
|
624 this.video = ''; |
|
625 var _this = this; |
542 } |
626 } |
543 |
627 |
544 Model.Media.prototype = new Model.Playable(); |
628 Model.Media.prototype = new Model.Playable(); |
545 |
629 |
546 /* Default functions to be overriden by players */ |
630 /* Default functions to be overriden by players */ |
657 |
747 |
658 Model.MashedAnnotation = function(_mashup, _annotation) { |
748 Model.MashedAnnotation = function(_mashup, _annotation) { |
659 Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source); |
749 Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source); |
660 this.elementType = 'mashedAnnotation'; |
750 this.elementType = 'mashedAnnotation'; |
661 this.annotation = _annotation; |
751 this.annotation = _annotation; |
662 this.begin = new Model.Time(_mashup.duration); |
752 this.begin = new Model.Time(); |
663 this.end = new Model.Time(_mashup.duration + _annotation.getDuration()); |
753 this.end = new Model.Time(); |
|
754 this.duration = new Model.Time(); |
664 this.title = this.annotation.title; |
755 this.title = this.annotation.title; |
665 this.description = this.annotation.description; |
756 this.description = this.annotation.description; |
666 this.color = this.annotation.color; |
757 this.color = this.annotation.color; |
667 var _this = this; |
758 var _this = this; |
668 this.on("click", function() { |
759 this.on("click", function() { |
669 _mashup.setCurrentTime(_this.begin); |
760 _mashup.setCurrentTime(_this.begin); |
670 }); |
761 }); |
|
762 this.on("enter", function() { |
|
763 _this.annotation.trigger("enter"); |
|
764 }); |
|
765 this.on("leave", function() { |
|
766 _this.annotation.trigger("leave"); |
|
767 }); |
671 } |
768 } |
672 |
769 |
673 Model.MashedAnnotation.prototype = new Model.Element(null); |
770 Model.MashedAnnotation.prototype = new Model.Element(null); |
674 |
771 |
675 Model.MashedAnnotation.prototype.getMedia = function() { |
772 Model.MashedAnnotation.prototype.getMedia = function() { |
688 return this.annotation.getTags().getTitles(); |
785 return this.annotation.getTags().getTitles(); |
689 } |
786 } |
690 |
787 |
691 Model.MashedAnnotation.prototype.getDuration = function() { |
788 Model.MashedAnnotation.prototype.getDuration = function() { |
692 return this.annotation.getDuration(); |
789 return this.annotation.getDuration(); |
|
790 } |
|
791 |
|
792 Model.MashedAnnotation.prototype.setBegin = function(_begin) { |
|
793 this.begin.setMilliseconds(_begin); |
|
794 this.duration.setMilliseconds(this.annotation.getDuration()); |
|
795 this.end.setMilliseconds(_begin + this.duration); |
693 } |
796 } |
694 |
797 |
695 /* */ |
798 /* */ |
696 |
799 |
697 Model.Mashup = function(_id, _source) { |
800 Model.Mashup = function(_id, _source) { |
698 Model.Playable.call(this, _id, _source); |
801 Model.Playable.call(this, _id, _source); |
699 this.elementType = 'mashup'; |
802 this.elementType = 'mashup'; |
700 this.duration = new Model.Time(); |
803 this.duration = new Model.Time(); |
701 this.segments = new Model.List(_source.directory); |
804 this.segments = new Model.List(_source.directory); |
702 this.medias = new Model.List(_source.directory); |
805 this.loaded = false; |
703 var _currentMedia = null; |
|
704 var _this = this; |
806 var _this = this; |
705 this.on("timeupdate", function(_time) { |
807 this._updateTimes = function() { |
706 _this.getAnnotations().filter(function(_a) { |
808 _this.updateTimes(); |
707 return (_a.end <= _time || _a.begin > _time) && _a.playing |
809 _this.trigger("change"); |
708 }).forEach(function(_a) { |
810 } |
709 _a.playing = false; |
811 this.on("add", this._updateTimes); |
710 _a.trigger("leave"); |
812 this.on("remove", this._updateTimes); |
711 }); |
|
712 _this.getAnnotations().filter(function(_a) { |
|
713 return _a.begin <= _time && _a.end > _time && !_a.playing |
|
714 }).forEach(function(_a) { |
|
715 _a.playing = true; |
|
716 _a.trigger("enter"); |
|
717 var _m = _a.getMedia(); |
|
718 if (_m !== _currentMedia) { |
|
719 if (_currentMedia) { |
|
720 _currentMedia.trigger("leave"); |
|
721 } |
|
722 _m.trigger("enter"); |
|
723 _currentMedia = _m; |
|
724 } |
|
725 }); |
|
726 }); |
|
727 } |
813 } |
728 |
814 |
729 Model.Mashup.prototype = new Model.Playable(); |
815 Model.Mashup.prototype = new Model.Playable(); |
730 |
816 |
731 Model.Mashup.prototype.addSegment = function(_annotation) { |
817 Model.Mashup.prototype.checkLoaded = function() { |
732 var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation); |
818 var loaded = !!this.segments.length; |
733 this.duration.setMilliseconds(_mashedAnnotation.end); |
819 this.getMedias().forEach(function(_m) { |
|
820 loaded = loaded && _m.loaded; |
|
821 }); |
|
822 this.loaded = loaded; |
|
823 if (loaded) { |
|
824 this.trigger("loadedmetadata"); |
|
825 } |
|
826 } |
|
827 |
|
828 Model.Mashup.prototype.updateTimes = function() { |
|
829 var _time = 0; |
|
830 this.segments.forEach(function(_segment) { |
|
831 _segment.setBegin(_time); |
|
832 _time = _segment.end; |
|
833 }); |
|
834 this.duration.setMilliseconds(_time); |
|
835 } |
|
836 |
|
837 Model.Mashup.prototype.addAnnotation = function(_annotation, _defer) { |
|
838 var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation), |
|
839 _defer = _defer || false; |
734 this.segments.push(_mashedAnnotation); |
840 this.segments.push(_mashedAnnotation); |
735 this.medias.push(_annotation.getMedia()); |
841 _annotation.on("change-begin", this._updateTimes); |
736 } |
842 _annotation.on("change-end", this._updateTimes); |
737 |
843 if (!_defer) { |
738 Model.Mashup.prototype.addSegmentById = function(_elId) { |
844 this.trigger("add"); |
739 var _annotation = this.source.getElement(_elId); |
845 } |
|
846 } |
|
847 |
|
848 Model.Mashup.prototype.addAnnotationById = function(_elId, _defer) { |
|
849 var _annotation = this.source.getElement(_elId), |
|
850 _defer = _defer || false; |
740 if (typeof _annotation !== "undefined") { |
851 if (typeof _annotation !== "undefined") { |
741 this.addSegment(_annotation); |
852 this.addAnnotation(_annotation, _defer); |
742 } |
853 } |
|
854 } |
|
855 |
|
856 Model.Mashup.prototype.addAnnotations = function(_segments) { |
|
857 var _this = this; |
|
858 ns._(_segments).forEach(function(_segment) { |
|
859 _this.addAnnotation(_segment, true); |
|
860 }); |
|
861 this.trigger("add"); |
|
862 } |
|
863 |
|
864 Model.Mashup.prototype.addAnnotationsById = function(_segments) { |
|
865 var _this = this; |
|
866 ns._(_segments).forEach(function(_segment) { |
|
867 _this.addAnnotationById(_segment, true); |
|
868 }); |
|
869 this.trigger("add"); |
|
870 } |
|
871 |
|
872 Model.Mashup.prototype.removeAnnotation = function(_annotation, _defer) { |
|
873 var _defer = _defer || false; |
|
874 _annotation.off("change-begin", this._updateTimes); |
|
875 _annotation.off("change-end", this._updateTimes); |
|
876 this.segments.removeId(this.id + "_" + _annotation.id); |
|
877 if (!_defer) { |
|
878 this.trigger("remove"); |
|
879 } |
|
880 } |
|
881 |
|
882 Model.Mashup.prototype.removeAnnotationById = function(_annId, _defer) { |
|
883 var _defer = _defer || false; |
|
884 var _annotation = this.source.getElement(_annId); |
|
885 |
|
886 if (_annotation) { |
|
887 this.removeAnnotation(_annotation, _defer); |
|
888 } |
|
889 if (!_defer) { |
|
890 this.trigger("remove"); |
|
891 } |
|
892 } |
|
893 |
|
894 Model.Mashup.prototype.setAnnotations = function(_segments) { |
|
895 while (this.segments.length) { |
|
896 this.removeAnnotation(this.segments[0].annotation, true); |
|
897 } |
|
898 this.addAnnotations(_segments); |
|
899 } |
|
900 |
|
901 Model.Mashup.prototype.setAnnotationsById = function(_segments) { |
|
902 while (this.segments.length) { |
|
903 this.removeAnnotation(this.segments[0].annotation, true); |
|
904 } |
|
905 this.addAnnotationsById(_segments); |
|
906 } |
|
907 |
|
908 Model.Mashup.prototype.hasAnnotation = function(_annotation) { |
|
909 return !!ns._(this.segments).find(function(_s) { |
|
910 return _s.annotation === _annotation |
|
911 }); |
|
912 } |
|
913 |
|
914 Model.Mashup.prototype.getAnnotation = function(_annotation) { |
|
915 return ns._(this.segments).find(function(_s) { |
|
916 return _s.annotation === _annotation |
|
917 }); |
|
918 } |
|
919 |
|
920 Model.Mashup.prototype.getAnnotationById = function(_id) { |
|
921 return ns._(this.segments).find(function(_s) { |
|
922 return _s.annotation.id === _id |
|
923 }); |
743 } |
924 } |
744 |
925 |
745 Model.Mashup.prototype.getAnnotations = function() { |
926 Model.Mashup.prototype.getAnnotations = function() { |
746 return this.segments; |
927 return this.segments; |
747 } |
928 } |
748 |
929 |
|
930 Model.Mashup.prototype.getOriginalAnnotations = function() { |
|
931 var annotations = new Model.List(this.source.directory); |
|
932 this.segments.forEach(function(_s) { |
|
933 annotations.push(_s.annotation); |
|
934 }); |
|
935 return annotations; |
|
936 } |
|
937 |
749 Model.Mashup.prototype.getMedias = function() { |
938 Model.Mashup.prototype.getMedias = function() { |
750 return this.medias; |
939 var medias = new Model.List(this.source.directory); |
|
940 this.segments.forEach(function(_annotation) { |
|
941 medias.push(_annotation.getMedia()) |
|
942 }) |
|
943 return medias; |
751 } |
944 } |
752 |
945 |
753 Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) { |
946 Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) { |
754 var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id"); |
947 var _annTypes = this.source.getAnnotationTypes().searchByTitle(_title).pluck("id"); |
755 if (_annTypes.length) { |
948 if (_annTypes.length) { |