# HG changeset patch # User veltr # Date 1353512031 -3600 # Node ID 97fef7a4b1891ae54350e3de89dd4306a7fee304 # Parent cfcbac34d02088a49a4484bcebe3e6765a0657a2 updated search diff -r cfcbac34d020 -r 97fef7a4b189 src/js/model.js --- a/src/js/model.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/js/model.js Wed Nov 21 16:33:51 2012 +0100 @@ -1,7 +1,6 @@ /* TODO: Separate Project-specific data from Source */ /* model.js is where data is stored in a standard form, whatever the serializer */ - IriSP.Model = (function (ns) { function pad(n, x, b) { @@ -18,7 +17,21 @@ } var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000); - + + var charsub = [ + [ 'a', 'á', 'à', 'â', 'ä' ], + [ 'c', 'ç' ], + [ 'e', 'é', 'è', 'ê', 'ë' ], + [ 'i', 'í', 'ì', 'î', 'ï' ], + [ 'o', 'ó', 'ò', 'ô', 'ö' ] + ]; + + var removeChars = [ + String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807), + "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ", + ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/" + ] + var Model = { _SOURCE_STATUS_EMPTY : 0, _SOURCE_STATUS_WAITING : 1, @@ -26,6 +39,13 @@ getUID : function() { return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6); }, + isLocalURL : function(url) { + var matches = url.match(/^(\w+:)\/\/([^/]+)/); + if (matches) { + return(matches[1] === document.location.protocol && matches[2] === document.location.host) + } + return true; + }, regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) { var _testOnly = _testOnly || false, _iexact = _iexact || false; @@ -46,6 +66,30 @@ } return new RegExp( _source, _flags); }, + fullTextRegexps: function(_text) { + var remsrc = "[\\" + removeChars.join("\\") + "]", + remrx = new RegExp(remsrc,"gm"), + txt = _text.toLowerCase().replace(remrx,"") + res = [], + charsrc = ns._(charsub).map(function(c) { + return "(" + c.join("|") + ")"; + }), + charsrx = ns._(charsrc).map(function(c) { + return new RegExp(c); + }), + src = ""; + for (var j = 0; j < txt.length; j++) { + if (j) { + src += remsrc + "*"; + } + var l = txt[j]; + ns._(charsrc).each(function(v, k) { + l = l.replace(charsrx[k], v); + }); + src += l; + } + return "(" + src + ")"; + }, isoToDate : function(_str) { // http://delete.me.uk/2005/03/iso8601.html 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})))?)?)?)?"; @@ -71,7 +115,8 @@ _res.setTime(Number(time)); return _res; }, - dateToIso : function(d) { + dateToIso : function(_d) { + var d = _d ? new Date(_d) : new Date(); return d.getUTCFullYear()+'-' + pad(2, d.getUTCMonth()+1)+'-' + pad(2, d.getUTCDate())+'T' @@ -93,6 +138,15 @@ console.trace(); throw "Error : new Model.List(directory): directory is undefined"; } + var _this = this; + this.on("clear-search", function() { + _this.searching = false; + _this.regexp = undefined; + _this.forEach(function(_element) { + _element.found = undefined; + }); + _this.trigger("search-cleared"); + }) } Model.List.prototype = new Array(); @@ -191,6 +245,28 @@ }); } +Model.List.prototype.search = function(_text) { + if (!_text) { + this.trigger("clear-search"); + return this; + } + this.searching = true; + this.trigger("search", _text); + var rxsource = Model.fullTextRegexps(_text) + rgxp = new RegExp(rxsource,"im"), + this.regexp = new RegExp(rxsource,"gim"); + var res = this.filter(function(_element, _k) { + var titlematch = rgxp.test(_element.title), + descmatch = rgxp.test(_element.description), + _isfound = !!(titlematch || descmatch); + _element.found = _isfound; + _element.trigger(_isfound ? "found" : "not-found"); + return _isfound; + }); + this.trigger(res.length ? "found" : "not-found",res); + return res; +} + Model.List.prototype.getTitles = function() { return this.map(function(_el) { return _el.title; @@ -297,16 +373,16 @@ } Model.Time.prototype.setMilliseconds = function(_milliseconds) { - var _ante = _milliseconds; + var _ante = this.milliseconds; switch(typeof _milliseconds) { case "string": - this.milliseconds = parseFloat(_milliseconds); + this.milliseconds = parseInt(_milliseconds); break; case "number": - this.milliseconds = _milliseconds; + this.milliseconds = Math.floor(_milliseconds); break; case "object": - this.milliseconds = parseFloat(_milliseconds.valueOf()); + this.milliseconds = parseInt(_milliseconds.valueOf()); break; default: this.milliseconds = 0; @@ -329,7 +405,8 @@ return { hours : Math.floor(_totalSeconds / 3600), minutes : (Math.floor(_totalSeconds / 60) % 60), - seconds : _totalSeconds % 60 + seconds : _totalSeconds % 60, + milliseconds: this.milliseconds % 1000 } } @@ -341,13 +418,16 @@ return this.milliseconds; } -Model.Time.prototype.toString = function() { +Model.Time.prototype.toString = function(showCs) { var _hms = this.getHMS(), _res = ''; if (_hms.hours) { _res += _hms.hours + ':' } _res += pad(2, _hms.minutes) + ':' + pad(2, _hms.seconds); + if (showCs) { + _res += "." + Math.round(_hms.milliseconds / 100) + } return _res; } @@ -394,18 +474,20 @@ Model.Element = function(_id, _source) { this.elementType = 'element'; + this.title = ""; + this.description = ""; + this.__events = {} if (typeof _source === "undefined") { return; } if (typeof _id === "undefined" || !_id) { _id = Model.getUID(); } + this.id = _id; this.source = _source; - this.id = _id; - this.title = ""; - this.description = ""; - this.__events = {} - this.source.directory.addElement(this); + if (_source !== this) { + this.source.directory.addElement(this); + } } Model.Element.prototype.toString = function() { @@ -474,6 +556,20 @@ }); this.on("timeupdate", function(_time) { _this.currentTime = _time; + _this.getAnnotations().filter(function(_a) { + return (_a.end <= _time || _a.begin > _time) && _a.playing + }).forEach(function(_a) { + _a.playing = false; + _a.trigger("leave"); + _this.trigger("leave-annotation",_a); + }); + _this.getAnnotations().filter(function(_a) { + return _a.begin <= _time && _a.end > _time && !_a.playing + }).forEach(function(_a) { + _a.playing = true; + _a.trigger("enter"); + _this.trigger("enter-annotation",_a); + }); }); } @@ -515,6 +611,9 @@ this.trigger("setpause"); } +Model.Playable.prototype.show = function() {} + +Model.Playable.prototype.hide = function() {} /* */ @@ -523,22 +622,7 @@ this.elementType = 'media'; this.duration = new Model.Time(); this.video = ''; - var _this = this; - this.on("timeupdate", function(_time) { - _this.getAnnotations().filter(function(_a) { - return (_a.end <= _time || _a.begin > _time) && _a.playing - }).forEach(function(_a) { - _a.playing = false; - _a.trigger("leave"); - }); - _this.getAnnotations().filter(function(_a) { - return _a.begin <= _time && _a.end > _time && !_a.playing - }).forEach(function(_a) { - _a.playing = true; - _a.trigger("enter"); - }); - }); } Model.Media.prototype = new Model.Playable(); @@ -610,11 +694,17 @@ Model.Annotation.prototype.setBegin = function(_beginMs) { this.begin.setMilliseconds(Math.max(0,_beginMs)); this.trigger("change-begin"); + if (this.end < this.begin) { + this.setEnd(this.begin); + } } Model.Annotation.prototype.setEnd = function(_endMs) { - this.end.setMilliseconds(Math.min(_endMs)); + this.end.setMilliseconds(Math.min(_endMs, this.getMedia().duration.milliseconds)); this.trigger("change-end"); + if (this.end < this.begin) { + this.setBegin(this.end); + } } Model.Annotation.prototype.setDuration = function(_durMs) { @@ -659,8 +749,9 @@ Model.Element.call(this, _mashup.id + "_" + _annotation.id, _annotation.source); this.elementType = 'mashedAnnotation'; this.annotation = _annotation; - this.begin = new Model.Time(_mashup.duration); - this.end = new Model.Time(_mashup.duration + _annotation.getDuration()); + this.begin = new Model.Time(); + this.end = new Model.Time(); + this.duration = new Model.Time(); this.title = this.annotation.title; this.description = this.annotation.description; this.color = this.annotation.color; @@ -668,6 +759,12 @@ this.on("click", function() { _mashup.setCurrentTime(_this.begin); }); + this.on("enter", function() { + _this.annotation.trigger("enter"); + }); + this.on("leave", function() { + _this.annotation.trigger("leave"); + }); } Model.MashedAnnotation.prototype = new Model.Element(null); @@ -692,6 +789,12 @@ return this.annotation.getDuration(); } +Model.MashedAnnotation.prototype.setBegin = function(_begin) { + this.begin.setMilliseconds(_begin); + this.duration.setMilliseconds(this.annotation.getDuration()); + this.end.setMilliseconds(_begin + this.duration); +} + /* */ Model.Mashup = function(_id, _source) { @@ -699,55 +802,145 @@ this.elementType = 'mashup'; this.duration = new Model.Time(); this.segments = new Model.List(_source.directory); - this.medias = new Model.List(_source.directory); - var _currentMedia = null; + this.loaded = false; var _this = this; - this.on("timeupdate", function(_time) { - _this.getAnnotations().filter(function(_a) { - return (_a.end <= _time || _a.begin > _time) && _a.playing - }).forEach(function(_a) { - _a.playing = false; - _a.trigger("leave"); - }); - _this.getAnnotations().filter(function(_a) { - return _a.begin <= _time && _a.end > _time && !_a.playing - }).forEach(function(_a) { - _a.playing = true; - _a.trigger("enter"); - var _m = _a.getMedia(); - if (_m !== _currentMedia) { - if (_currentMedia) { - _currentMedia.trigger("leave"); - } - _m.trigger("enter"); - _currentMedia = _m; - } - }); - }); + this._updateTimes = function() { + _this.updateTimes(); + _this.trigger("change"); + } + this.on("add", this._updateTimes); + this.on("remove", this._updateTimes); } Model.Mashup.prototype = new Model.Playable(); -Model.Mashup.prototype.addSegment = function(_annotation) { - var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation); - this.duration.setMilliseconds(_mashedAnnotation.end); +Model.Mashup.prototype.checkLoaded = function() { + var loaded = !!this.segments.length; + this.getMedias().forEach(function(_m) { + loaded = loaded && _m.loaded; + }); + this.loaded = loaded; + if (loaded) { + this.trigger("loadedmetadata"); + } +} + +Model.Mashup.prototype.updateTimes = function() { + var _time = 0; + this.segments.forEach(function(_segment) { + _segment.setBegin(_time); + _time = _segment.end; + }); + this.duration.setMilliseconds(_time); +} + +Model.Mashup.prototype.addAnnotation = function(_annotation, _defer) { + var _mashedAnnotation = new Model.MashedAnnotation(this, _annotation), + _defer = _defer || false; this.segments.push(_mashedAnnotation); - this.medias.push(_annotation.getMedia()); + _annotation.on("change-begin", this._updateTimes); + _annotation.on("change-end", this._updateTimes); + if (!_defer) { + this.trigger("add"); + } +} + +Model.Mashup.prototype.addAnnotationById = function(_elId, _defer) { + var _annotation = this.source.getElement(_elId), + _defer = _defer || false; + if (typeof _annotation !== "undefined") { + this.addAnnotation(_annotation, _defer); + } +} + +Model.Mashup.prototype.addAnnotations = function(_segments) { + var _this = this; + ns._(_segments).forEach(function(_segment) { + _this.addAnnotation(_segment, true); + }); + this.trigger("add"); } -Model.Mashup.prototype.addSegmentById = function(_elId) { - var _annotation = this.source.getElement(_elId); - if (typeof _annotation !== "undefined") { - this.addSegment(_annotation); +Model.Mashup.prototype.addAnnotationsById = function(_segments) { + var _this = this; + ns._(_segments).forEach(function(_segment) { + _this.addAnnotationById(_segment, true); + }); + this.trigger("add"); +} + +Model.Mashup.prototype.removeAnnotation = function(_annotation, _defer) { + var _defer = _defer || false; + _annotation.off("change-begin", this._updateTimes); + _annotation.off("change-end", this._updateTimes); + this.segments.removeId(this.id + "_" + _annotation.id); + if (!_defer) { + this.trigger("remove"); + } +} + +Model.Mashup.prototype.removeAnnotationById = function(_annId, _defer) { + var _defer = _defer || false; + var _annotation = this.source.getElement(_annId); + + if (_annotation) { + this.removeAnnotation(_annotation, _defer); + } + if (!_defer) { + this.trigger("remove"); } } +Model.Mashup.prototype.setAnnotations = function(_segments) { + while (this.segments.length) { + this.removeAnnotation(this.segments[0].annotation, true); + } + this.addAnnotations(_segments); +} + +Model.Mashup.prototype.setAnnotationsById = function(_segments) { + while (this.segments.length) { + this.removeAnnotation(this.segments[0].annotation, true); + } + this.addAnnotationsById(_segments); +} + +Model.Mashup.prototype.hasAnnotation = function(_annotation) { + return !!ns._(this.segments).find(function(_s) { + return _s.annotation === _annotation + }); +} + +Model.Mashup.prototype.getAnnotation = function(_annotation) { + return ns._(this.segments).find(function(_s) { + return _s.annotation === _annotation + }); +} + +Model.Mashup.prototype.getAnnotationById = function(_id) { + return ns._(this.segments).find(function(_s) { + return _s.annotation.id === _id + }); +} + Model.Mashup.prototype.getAnnotations = function() { return this.segments; } +Model.Mashup.prototype.getOriginalAnnotations = function() { + var annotations = new Model.List(this.source.directory); + this.segments.forEach(function(_s) { + annotations.push(_s.annotation); + }); + return annotations; +} + Model.Mashup.prototype.getMedias = function() { - return this.medias; + var medias = new Model.List(this.source.directory); + this.segments.forEach(function(_annotation) { + medias.push(_annotation.getMedia()) + }) + return medias; } Model.Mashup.prototype.getAnnotationsByTypeTitle = function(_title) { @@ -784,6 +977,7 @@ /* */ Model.Source = function(_config) { + Model.Element.call(this, false, this); this.status = Model._SOURCE_STATUS_EMPTY; this.elementType = "source"; if (typeof _config !== "undefined") { @@ -939,10 +1133,18 @@ Model.RemoteSource.prototype.get = function() { this.status = Model._SOURCE_STATUS_WAITING; - var _this = this; - this.serializer.loadData(this.url, function(_result) { - _this.deSerialize(_result); - _this.handleCallbacks(); + var _this = this, + urlparams = this.url_params || {}, + dataType = (Model.isLocalURL(this.url) ? "json" : "jsonp"); + urlparams.format = dataType; + ns.jQuery.ajax({ + url: this.url, + dataType: dataType, + data: urlparams, + success: function(_result) { + _this.deSerialize(_result); + _this.handleCallbacks(); + } }); } @@ -958,10 +1160,12 @@ throw "Error : Model.Directory.remoteSource(configuration): configuration.url is undefined"; } var _config = ns._({ directory: this }).extend(_properties); - if (typeof this.remoteSources[_properties.url] === "undefined") { - this.remoteSources[_properties.url] = new Model.RemoteSource(_config); + _config.url_params = _config.url_params || {}; + var _hash = _config.url + "?" + ns.jQuery.param(_config.url_params); + if (typeof this.remoteSources[_hash] === "undefined") { + this.remoteSources[_hash] = new Model.RemoteSource(_config); } - return this.remoteSources[_properties.url]; + return this.remoteSources[_hash]; } Model.Directory.prototype.newLocalSource = function(_properties) { diff -r cfcbac34d020 -r 97fef7a4b189 src/js/serializers/ldt.js --- a/src/js/serializers/ldt.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/js/serializers/ldt.js Wed Nov 21 16:33:51 2012 +0100 @@ -31,16 +31,42 @@ } return _res; }, - serializer : function(_data, _source) { - return { + serializer : function(_data, _source, _dest) { + var _res = { id : _data.id, url : _data.video, meta : { - "dc:title" : _data.title, - "dc:description" : _data.description, + "dc:title": _data.title || "", + "dc:description": _data.description || "", + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, "dc:duration" : _data.duration.milliseconds } } + _dest.medias.push(_res); + var _list = { + id: IriSP.Model.getUID(), + meta : { + "dc:title": _data.title || "", + "dc:description": _data.description || "", + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, + "id-ref": _data.id + }, + items: _source.getAnnotationTypes().filter(function(_at) { + return _at.media === _data; + }).map(function(_at) { + return { + "id-ref": _at.id + } + }) + } + _dest.lists.push(_list); + _dest.views[0].contents.push(_data.id); } }, tag : { @@ -51,13 +77,19 @@ _res.title = _data.meta["dc:title"]; return _res; }, - serializer : function(_data, _source) { - return { + serializer : function(_data, _source, _dest) { + var _res = { id : _data.id, meta : { - "dc:title" : _data.title + "dc:title": _data.title || "", + "dc:description": _data.description || "", + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, } } + _dest.tags.push(_res); } }, annotationType : { @@ -68,12 +100,18 @@ _res.description = _data["dc:description"]; return _res; }, - serializer : function(_data, _source) { - return { + serializer : function(_data, _source, _dest) { + var _res = { id : _data.id, - "dc:title" : _data.title, - "dc:description" : _data.description + "dc:title": _data.title || "", + "dc:description": _data.description || "", + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, } + _dest["annotation-types"].push(_res); + _dest.views[0].annotation_types.push(_data.id); } }, annotation : { @@ -96,6 +134,7 @@ _res.setMedia(_data.media); _res.setAnnotationType(_data.meta["id-ref"]); _res.setTags(IriSP._(_data.tags).pluck("id-ref")); + _res.keywords = _res.getTagTexts(); _res.setBegin(_data.begin); _res.setEnd(_data.end); _res.creator = _data.meta["dc:creator"] || ""; @@ -108,22 +147,29 @@ } return _res; }, - serializer : function(_data, _source) { - return { + serializer : function(_data, _source, _dest) { + var _color = parseInt(_data.color.replace(/^#/,''),16).toString(); + var _res = { id : _data.id, begin : _data.begin.milliseconds, end : _data.end.milliseconds, content : { - title : _data.title, - description : _data.description, - audio : _data.audio + title : _data.title || "", + description : _data.description || "", + audio : _data.audio, + img: { + src: _data.thumbnail + } }, + color: _color, media : _data.media.id, meta : { - "id-ref" : _data.annotationType.id, - "dc:created" : IriSP.Model.dateToIso(_data.created), - "dc:creator" : _data.creator, - project : _source.projectId + "id-ref" : _data.getAnnotationType().id, + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, +// project : _source.projectId }, tags : IriSP._(_data.tag.id).map(function(_id) { return { @@ -131,6 +177,7 @@ } }) } + _dest.annotations.push(_res); } }, mashup : { @@ -142,41 +189,64 @@ var _res = new IriSP.Model.Mashup(_data.id, _source); _res.title = _data.meta["dc:title"]; _res.description = _data.meta["dc:description"]; - for (var _i = 0; _i < _data.items.length; _i++) { - _res.addSegmentById(_data.items[_i]); - } + _res.creator = _data.meta["dc:creator"]; + _res.setAnnotationsById(_data.items); return _res; }, - serializer : function(_data, _source) { - return { + serializer : function(_data, _source, _dest) { + var _res = { meta : { - "dc:title": _data.title, - "dc:description": _data.description, + "dc:title": _data.title || "", + "dc:description": _data.description || "", + "dc:created" : IriSP.Model.dateToIso(_data.created || _source.created), + "dc:modified" : IriSP.Model.dateToIso(_data.modified || _source.modified), + "dc:creator" : _data.creator || _source.creator, + "dc:contributor" : _data.contributor || _source.contributor || _data.creator || _source.creator, listtype: "mashup" }, items: _data.segments.map(function(_annotation) { - return _id; + return _annotation.annotation.id; }), id: _data.id } + _dest.lists.push(_res); } } }, serialize : function(_source) { - var _res = {}, + var _res = { + meta: { + "dc:creator": _source.creator, + "dc:contributor" : _source.contributor || _source.creator, + "dc:created": IriSP.Model.dateToIso(_source.created), + "dc:modified" : IriSP.Model.dateToIso(_source.modified), + "dc:title": _source.title || "", + "dc:description": _source.description || "", + id: _source.projectId || _source.id + }, + views: [ + { + id: IriSP.Model.getUID(), + contents: [], + annotation_types: [] + } + ], + lists: [], + "annotation-types": [], + medias: [], + tags: [], + annotations: [] + }, _this = this; _source.forEach(function(_list, _typename) { if (typeof _this.types[_typename] !== "undefined") { - _res[_this.types[_typename].serialized_name] = _list.map(function(_el) { - return _this.types[_typename].serializer(_el, _source); + _list.forEach(function(_el) { + _this.types[_typename].serializer(_el, _source, _res); }); } }); return JSON.stringify(_res); }, - loadData : function(_url, _callback) { - IriSP.jQuery.getJSON(_url, _callback) - }, deSerialize : function(_data, _source) { if (typeof _data !== "object" || _data === null) { return; diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/Annotation.css --- a/src/widgets/Annotation.css Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/Annotation.css Wed Nov 21 16:33:51 2012 +0100 @@ -6,6 +6,10 @@ margin: 0; } +.Ldt-Annotation-Highlight { + background: #ffa0fc; +} + .Ldt-Annotation-Widget.Ldt-Annotation-ShowTop { border-top-style: solid; padding-top: 1px; @@ -15,6 +19,8 @@ background: url(img/pinstripe.png); padding: 5px; margin: 0; + max-height: 300px; + overflow: auto; } .Ldt-Annotation-Inner h3 { @@ -66,6 +72,7 @@ .Ldt-Annotation-Inner p { font-size: 12px; + line-height: 16px; } .Ldt-Annotation-Label { diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/Annotation.js --- a/src/widgets/Annotation.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/Annotation.js Wed Nov 21 16:33:51 2012 +0100 @@ -56,7 +56,8 @@ IriSP.Widgets.Annotation.prototype.draw = function() { - var _this = this; + var _this = this, + currentAnnotation; function timeupdate(_time) { var _list = _this.getWidgetAnnotationsAtTime(); @@ -70,7 +71,29 @@ } } + function highlightTitleAndDescription() { + if (!currentAnnotation) { + return; + } + var title = currentAnnotation.title, + description = currentAnnotation.description.replace(/(^\s+|\s+$)/g,''); + if (currentAnnotation.found) { + var rgxp = _this.source.getAnnotations().regexp || /^$/, + repl = '$1'; + title = title.replace(rgxp,repl); + description = description.replace(rgxp,repl); + } + _this.$.find(".Ldt-Annotation-Title").html(title || "(" + _this.l10n.untitled + ")"); + if (description) { + _this.$.find(".Ldt-Annotation-Description-Block").removeClass("Ldt-Annotation-EmptyBlock"); + _this.$.find(".Ldt-Annotation-Description").html(description); + } else { + _this.$.find(".Ldt-Annotation-Description-Block").addClass("Ldt-Annotation-EmptyBlock"); + } + } + function drawAnnotation(_annotation) { + currentAnnotation = _annotation; var _url = (typeof _annotation.url !== "undefined" ? _annotation.url : (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id)), @@ -85,7 +108,7 @@ var _el = IriSP.jQuery('
  • ').append(IriSP.jQuery('').text(_trimmedTitle)); _el.click(function() { if (_this.search_on_tag_click) { - _this.player.trigger("search.triggeredSearch",_trimmedTitle); + _this.source.getAnnotations().search(_trimmedTitle); } _tag.trigger("click"); }); @@ -95,14 +118,7 @@ } else { _this.$.find(".Ldt-Annotation-Tags-Block").addClass("Ldt-Annotation-EmptyBlock"); } - _this.$.find(".Ldt-Annotation-Title").text(_annotation.title || "(" + _this.l10n.untitled + ")"); - var _desc = _annotation.description.replace(/(^\s+|\s+$)/g,''); - if (_desc) { - _this.$.find(".Ldt-Annotation-Description-Block").removeClass("Ldt-Annotation-EmptyBlock"); - _this.$.find(".Ldt-Annotation-Description").html(_desc); - } else { - _this.$.find(".Ldt-Annotation-Description-Block").addClass("Ldt-Annotation-EmptyBlock"); - } + highlightTitleAndDescription(); if (_this.show_annotation_type) { _this.$.find(".Ldt-Annotation-Type").text(_annotation.getAnnotationType().title) } @@ -135,7 +151,7 @@ this.renderTemplate(); - if (_this.show_social) { + if (this.show_social) { this.insertSubwidget(this.$.find(".Ldt-Annotation-Social"), { type: "Social" }, "socialWidget"); } @@ -152,6 +168,9 @@ drawAnnotation(_a) }); }); + this.source.getAnnotations().on("found", highlightTitleAndDescription); + this.source.getAnnotations().on("not-found", highlightTitleAndDescription); + this.source.getAnnotations().on("search-cleared", highlightTitleAndDescription); } IriSP.Widgets.Annotation.prototype.sendBounds = function() { diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/AnnotationsList.css --- a/src/widgets/AnnotationsList.css Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/AnnotationsList.css Wed Nov 21 16:33:51 2012 +0100 @@ -29,8 +29,7 @@ background-image: url(img/pinstripe-grey.png); } .Ldt-AnnotationsList-highlight { - background: #F7268E; - color: #ffffff; + background: #FFA0FC; } .Ldt-AnnotationsList-ThumbContainer { float: left; diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/AnnotationsList.js --- a/src/widgets/AnnotationsList.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/AnnotationsList.js Wed Nov 21 16:33:51 2012 +0100 @@ -1,11 +1,12 @@ IriSP.Widgets.AnnotationsList = function(player, config) { IriSP.Widgets.Widget.call(this, player, config); - this.searchString = false; this.lastIds = []; var _this = this; this.throttledRefresh = IriSP._.throttle(function() { _this.refresh(false); - }, 1500); + }, 800); + this.searchString = false; + this.lastSearch = false; }; IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget(); @@ -87,18 +88,6 @@ + '{{#audio}}
    {{l10n.voice_annotation}}
    {{/audio}}' + ''; -IriSP.Widgets.AnnotationsList.prototype.onSearch = function(searchString) { - this.searchString = typeof searchString !== "undefined" ? searchString : ''; - var _n = this.refresh(true); - if (this.searchString) { - if (_n) { - this.player.trigger("search.matchFound"); - } else { - this.player.trigger("search.noMatchFound"); - } - } -} - //obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id; IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() { @@ -150,9 +139,9 @@ }); } } - if (this.searchString) { - _list = _list.searchByTextFields(this.searchString); - } + _list = _list.filter(function(_annotation) { + return _annotation.found !== false; + }); if (this.limit_count) { /* Get the n annotations closest to current timecode */ _list = _list.sortBy(function(_annotation) { @@ -171,8 +160,9 @@ var _ids = _list.idIndex; - if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds)) { + if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds) || this.searchString !== this.lastSearch) { /* This part only gets executed if the list needs updating */ + this.lastSearch = this.searchString; this.lastIds = _ids; this.list_$.html(""); _list.forEach(function(_annotation) { @@ -258,7 +248,7 @@ }); this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() { - _this.player.trigger("search.triggeredSearch", IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,'')); + _this.source.getAnnotations().search(IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,'')); }); this.$.find(".Ldt-AnnotationsList-Play").click(function() { @@ -274,11 +264,10 @@ _this.jw_paused_media = true; }); - if(this.searchString) { - var _searchRe = IriSP.Model.regexpFromTextOrArray(this.searchString); + if (this.source.getAnnotations().searching) { this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() { var _$ = IriSP.jQuery(this); - _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_searchRe, '$1')) + _$.html(_$.text().replace(/(^\s+|\s+$)/g,'').replace(_this.source.getAnnotations().regexp, '$1')) }) } } @@ -328,9 +317,29 @@ this.list_$ = this.$.find(".Ldt-AnnotationsList-ul"); - this.onMdpEvent("search", "onSearch"); - this.onMdpEvent("search.closed", "onSearch"); - this.onMdpEvent("search.cleared", "onSearch"); + this.source.getAnnotations().on("search", function(_text) { + _this.searchString = _text; + if (_this.source !== _this.currentSource) { + _this.currentSource.getAnnotations().search(_text); + _this.throttledRefresh(); + } + }); + this.source.getAnnotations().on("found", function() { + _this.throttledRefresh(); + }); + this.source.getAnnotations().on("not-found", function() { + _this.throttledRefresh(); + }); + this.source.getAnnotations().on("clear-search", function() { + _this.searchString = false; + if (_this.source !== _this.currentSource) { + _this.currentSource.getAnnotations().trigger("clear-search"); + } + }); + this.source.getAnnotations().on("search-cleared", function() { + _this.throttledRefresh(); + }); + this.onMdpEvent("AnnotationsList.refresh", function() { if (_this.ajax_url) { if (_this.mashupMode) { diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/Controller.js --- a/src/widgets/Controller.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/Controller.js Wed Nov 21 16:33:51 2012 +0100 @@ -92,10 +92,6 @@ this.onMediaEvent("volumechange","volumeUpdater"); this.onMediaEvent("timeupdate","timeDisplayUpdater"); this.onMediaEvent("loadedmetadata","volumeUpdater"); - this.onMdpEvent("search.matchFound","searchMatch"); - this.onMdpEvent("search.noMatchFound","searchNoMatch"); - this.onMdpEvent("search.triggeredSearch","triggeredSearch"); - this.onMdpEvent("search.cleared","hideSearchBlock"); // handle clicks this.$playButton.click(this.functionWrapper("playHandler")); @@ -157,6 +153,21 @@ }); this.timeDisplayUpdater(new IriSP.Model.Time(0)); + + var annotations = this.source.getAnnotations(); + annotations.on("search", function(_text) { + _this.$searchInput.val(_text); + _this.showSearchBlock(); + }); + annotations.on("found", function(_text) { + _this.$searchInput.css('background-color','#e1ffe1'); + }); + annotations.on("not-found", function(_text) { + _this.$searchInput.css('background-color', "#d62e3a"); + }); + annotations.on("search-cleared", function() { + _this.hideSearchBlock(); + }); }; @@ -222,23 +233,11 @@ IriSP.Widgets.Controller.prototype.showSearchBlock = function() { this.$searchBlock.animate({ width:"160px" }, 200); this.$searchInput.css('background-color','#fff'); - this.$searchInput.focus(); - - // we need this variable because some widgets can find a match in - // their data while at the same time others don't. As we want the - // search field to become green when there's a match, we need a - // variable to remember that we had one. - this._positiveMatch = false; - - // tell the world the field is open - this.player.trigger("search.open"); }; IriSP.Widgets.Controller.prototype.hideSearchBlock = function() { this.$searchBlock.animate( { width: 0 }, 200); - this._positiveMatch = false; - this.player.trigger("search.closed"); }; /** react to clicks on the search button */ @@ -247,7 +246,7 @@ this.showSearchBlock(); var _val = this.$searchInput.val(); if (_val) { - this.player.trigger("search", _val); // trigger the search to make it more natural. + this.source.getAnnotations().search(_val); } } else { this.hideSearchBlock(); @@ -267,37 +266,12 @@ // do nothing if the search field is empty, instead of highlighting everything. if (_val !== this.lastSearchValue) { if (_val) { - this.player.trigger("search", _val); + this.source.getAnnotations().search(_val); } else { - this.player.trigger("search.cleared"); + this.source.getAnnotations().trigger("clear-search"); this.$searchInput.css('background-color',''); } } this.lastSearchValue = _val; }; -/** - handler for the IriSP.search.found message, which is sent by some views when they - highlight a match. -*/ -IriSP.Widgets.Controller.prototype.searchMatch = function() { - this._positiveMatch = true; - this.$searchInput.css('background-color','#e1ffe1'); -}; - -/** the same, except that no value could be found */ -IriSP.Widgets.Controller.prototype.searchNoMatch = function() { - if (this._positiveMatch !== true) { - this.$searchInput.css('background-color', "#d62e3a"); - } -}; - -/** react to an IriSP.Player.triggeredSearch - that is, when - a widget ask the.Player to do a search on his behalf */ -IriSP.Widgets.Controller.prototype.triggeredSearch = function(searchString) { - this.showSearchBlock(); - this.$searchInput.attr('value', searchString); - this.player.trigger("search", searchString); // trigger the search to make it more natural. -}; - - diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/KnowledgeConcierge.css --- a/src/widgets/KnowledgeConcierge.css Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/KnowledgeConcierge.css Wed Nov 21 16:33:51 2012 +0100 @@ -10,6 +10,27 @@ display: none; } +.Ldt-Kc-Related h2 { + border: none; + color: #330099; + font-size: 18px; + margin: 8px 0 2px; + padding: 0 5px; +} + +h3.Ldt-Kc-For-Keywords { + border-bottom: 1px solid #666666; + color: #000000; + font-size: 12px; + margin: 2px 0 5px; + padding: 0 5px 5px; + text-align: right; +} + +.Ldt-Kc-Keywords { + color: #d000c0; font-weight: bold; +} + .Ldt-Kc-Related-Item { width: 235px; float: left; margin: 4px 0; padding: 4px 0; } diff -r cfcbac34d020 -r 97fef7a4b189 src/widgets/KnowledgeConcierge.js --- a/src/widgets/KnowledgeConcierge.js Fri Nov 16 17:36:56 2012 +0100 +++ b/src/widgets/KnowledgeConcierge.js Wed Nov 21 16:33:51 2012 +0100 @@ -13,17 +13,19 @@ related_api_endpoint: "", use_word_boundaries: false, related_data_type: 'json', // SET TO "jsonp" FOR CROSS-DOMAIN OPERATION - related_count: 8 + related_count: 8, } IriSP.Widgets.KnowledgeConcierge.prototype.messages = { "fr": { related_videos: "Vidéos liées", - duration_: "Durée :" + duration_: "Durée :", + for_keywords_: "pour le(s) mots-clé(s) :" }, "en": { related_videos: "Related Videos", - duration_: "Duration:" + duration_: "Duration:", + for_keywords_: "for keyword(s):" } } @@ -31,6 +33,7 @@ '
    ' + '
    ' + ''; IriSP.Widgets.KnowledgeConcierge.prototype.draw = function() { @@ -54,6 +57,7 @@ _selectedText = "", currentNodesList = "", relatedCache = {}, + relatedRequests = {}, relatedTemplate = '