Mercurial > hg > digilib-old
changeset 793:63c1b33e38b1 jquery
documentation for new plugin api in jquery-digilib-plugin.txt.
more steps towards plugification of birdseye view.
author | robcast |
---|---|
date | Fri, 18 Feb 2011 15:16:30 +0100 |
parents | 304488c72344 |
children | ad5cc0212b66 |
files | client/digitallibrary/jquery/jquery-digilib-plugins.txt client/digitallibrary/jquery/jquery.digilib.birdseye.js client/digitallibrary/jquery/jquery.digilib.geometry.js client/digitallibrary/jquery/jquery.digilib.js |
diffstat | 4 files changed, 313 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/digitallibrary/jquery/jquery-digilib-plugins.txt Fri Feb 18 15:16:30 2011 +0100 @@ -0,0 +1,38 @@ + +The plugin API of jquery.digilib +-------------------------------- + +* The plugin Javascript file has to be loaded after jquery.digilib.js. + +* The plugin should be written as a closure on jQuery (like a jquery plugin) exporting a plugin object as its interface: + + var plugin = { + name : 'mydigilibplugin', + install : install, + init : init, + buttons : {}, + actions : {}, + fn : {}, + plugins : {}, + defaults : {} + }; + + The "name" string, "install" function and "init" function are provided by the plugin and called by digilib. + "buttons", "actions", "fn" and "plugins" are shared objects provided by digilib. + "buttons" is the array of button objects. The plugin can add its own buttons to this array. + "actions" is the array of action objects. The plugin can add its own actions to this array. + "fn" is an object with functions from digilib. + "plugins" is an object with all digilib plugin objects. + "defaults" is an object with all digilib defaults. + +* the plugin object is passed to digilib in the "plugin" action on loading the plugin javascript file: + + $.fn.digilib('plugin', plugin); + + digilib then calls the "install" function on the populated plugin object (i.e. this = plugin) with the plugin object as parameter. + +* digilib calls the "init" function from the plugin object with the data object instance as a parameter in digilibs init phase. + +* further actions should be implemented as custom events on the data object. + +* events should be documented here...
--- a/client/digitallibrary/jquery/jquery.digilib.birdseye.js Fri Feb 18 10:39:40 2011 +0100 +++ b/client/digitallibrary/jquery/jquery.digilib.birdseye.js Fri Feb 18 15:16:30 2011 +0100 @@ -8,13 +8,34 @@ var FULL_AREA; + var buttons = { + bird : { + onclick : "showBirdDiv", + tooltip : "show bird's eye view", + icon : "birds-eye.png" + } + }; + var actions = { + // event handler: toggles the visibility of the bird's eye window + showBirdDiv : function (data, show) { + var settings = data.settings; + if (data.$birdDiv == null) { + // no bird div -> create + setupBirdDiv(data); + } + var on = showDiv(settings.isBirdDivVisible, data.$birdDiv, show); + settings.isBirdDivVisible = on; + highlightButtons(data, 'bird', on); + updateBirdDiv(data); + storeOptions(data); + } }; - // init: plugin initialization - var plugInit = function(data) { + // plugin initialization called by digilib on plugin object. + var install = function() { // import geometry classes - geom = digilib.fn.geometry; + geom = this.fn.geometry; FULL_AREA = digilib.fn.FULL_AREA; // TODO: add actions // TODO: add buttons @@ -22,11 +43,225 @@ }; + // returns URL for bird's eye view image + var getBirdImgUrl = function (data, moreParams) { + var settings = data.settings; + var birdDivOptions = { + dw : settings.birdDivWidth, + dh : settings.birdDivHeight + }; + var birdSettings = $.extend({}, settings, birdDivOptions); + // use only the relevant parameters + if (moreParams == null) { + var params = getParamString(birdSettings, settings.birdDivParams, defaults); + } else { + // filter scaler flags + if (birdSettings.mo != null) { + var mo = ''; + if (data.scalerFlags.hmir != null) { + mo += 'hmir,'; + } + if (data.scalerFlags.vmir != null) { + mo += 'vmir'; + } + birdSettings.mo = mo; + } + var params = getParamString(birdSettings, + settings.birdDivParams.concat(moreParams), defaults); + } + var url = settings.scalerBaseUrl + '?' + params; + return url; + }; + + // creates HTML structure for the bird's eye view in elem + var setupBirdDiv = function (data) { + var $elem = data.$elem; + // the bird's eye div + var $birdDiv = $('<div class="birdview" style="display:none"/>'); + // the detail indicator frame + var $birdZoom = $('<div class="birdzoom" style="display:none; background-color:transparent;"/>'); + // the small image + var $birdImg = $('<img class="birdimg"/>'); + data.$birdDiv = $birdDiv; + data.$birdZoom = $birdZoom; + data.$birdImg = $birdImg; + $elem.append($birdDiv); + $birdDiv.append($birdZoom); + $birdDiv.append($birdImg); + // $birdZoom.css(data.settings.birdIndicatorStyle); + var birdUrl = getBirdImgUrl(data); + $birdImg.load(birdImgLoadedHandler(data)); + $birdImg.error(function () {console.error("error loading birdview image");}); + $birdImg.attr('src', birdUrl); + }; + + // update bird's eye view + var updateBirdDiv = function (data) { + if (!data.settings.isBirdDivVisible) return; + var $birdImg = data.$birdImg; + var oldsrc = $birdImg.attr('src'); + var newsrc = getBirdImgUrl(data); + if (oldsrc !== newsrc) { + $birdImg.attr('src', newsrc); + // onload handler re-renders + } else { + // re-render + renderBirdArea(data); + // enable click and drag + setupBirdDrag(data); + } + }; + + // returns function for load event of bird's eye view img + var birdImgLoadedHandler = function (data) { + return function () { + var $birdImg = $(this); + var birdRect = geom.rectangle($birdImg); + console.debug("birdImg loaded!", $birdImg, "rect=", birdRect, "data=", data); + if (birdRect.width === 0) { + // malheureusement IE7 calls load handler when there is no size info yet + setTimeout(function () { $birdImg.triggerHandler('load'); }, 200); + } + // update display (zoom area indicator) + updateDisplay(data); + }; + }; + + // show zoom area indicator on bird's eye view + var renderBirdArea = function (data) { + if (data.$birdImg == null || ! data.$birdImg.get(0).complete) return; + var $birdZoom = data.$birdZoom; + var zoomArea = data.zoomArea; + var normalSize = isFullArea(zoomArea); + if (normalSize) { + $birdZoom.hide(); + return; + } else { + $birdZoom.show(); + } + // create Transform from current area and picsize + data.birdTrafo = getImgTrafo(data.$birdImg, FULL_AREA); + var zoomRect = data.birdTrafo.transform(zoomArea); + console.debug("renderBirdArea:", zoomRect, "zoomArea:", zoomArea, "$birdTrafo:", data.birdTrafo); + // acount for border width + var bw = getBorderWidth($birdZoom); + zoomRect.addPosition({x : -bw, y : -bw}); + if (data.settings.interactionMode === 'fullscreen') { + // no animation for fullscreen + zoomRect.adjustDiv($birdZoom); + } else { + // nice animation for embedded mode :-) + // correct offsetParent because animate doesn't use offset + var ppos = $birdZoom.offsetParent().offset(); + var dest = { + left : (zoomRect.x - ppos.left) + 'px', + top : (zoomRect.y - ppos.top) + 'px', + width : zoomRect.width, + height : zoomRect.height + }; + $birdZoom.animate(dest); + } + }; + + // bird's eye view zoom area click and drag handler + var setupBirdDrag = function(data) { + var $birdImg = data.$birdImg; + var $birdZoom = data.$birdZoom; + var $document = $(document); + var $scaler = data.$scaler; + var startPos, newRect, birdImgRect, birdZoomRect, fullRect, scalerPos; + var bw = getBorderWidth($birdZoom); + + // mousedown handler: start dragging bird zoom to a new position + var birdZoomStartDrag = function(evt) { + startPos = geom.position(evt); + // position may have changed + data.birdTrafo = getImgTrafo($birdImg, FULL_AREA); + birdImgRect = geom.rectangle($birdImg); + birdZoomRect = geom.rectangle($birdZoom); + scalerPos = geom.position($scaler); + newRect = null; + fullRect = setZoomBG(data); // setup zoom background image + $document.bind("mousemove.dlBirdMove", birdZoomMove); + $document.bind("mouseup.dlBirdMove", birdZoomEndDrag); + return false; + }; + + // mousemove handler: drag + var birdZoomMove = function(evt) { + var pos = geom.position(evt); + var delta = startPos.delta(pos); + // move birdZoom div, keeping size + newRect = birdZoomRect.copy(); + newRect.addPosition(delta); + newRect.stayInside(birdImgRect); + // reflect birdview zoom position in scaler image + var area = data.birdTrafo.invtransform(newRect); + var imgArea = data.imgTrafo.transform(area); + var offset = imgArea.getPosition().neg(); + offset.add(scalerPos); + if (fullRect) { + var bgPos = fullRect.getPosition().add(offset); + } else { + var bgPos = offset; + } + // move the background image to the new position + data.$scaler.css({ + 'background-position' : bgPos.x + "px " + bgPos.y + "px" + }); + // acount for border width + newRect.addPosition({x : -bw, y : -bw}); + newRect.adjustDiv($birdZoom); + return false; + }; + + // mouseup handler: reload page + var birdZoomEndDrag = function(evt) { + var settings = data.settings; + $document.unbind("mousemove.dlBirdMove", birdZoomMove); + $document.unbind("mouseup.dlBirdMove", birdZoomEndDrag); + if (newRect == null) { + // no movement happened - set center to click position + startPos = birdZoomRect.getCenter(); + birdZoomMove(evt); + } + // ugly, but needed to prevent double border width compensation + newRect.addPosition({x : bw, y : bw}); + var newArea = data.birdTrafo.invtransform(newRect); + data.zoomArea = newArea; + redisplay(data); + return false; + }; + + // clear old handler + $document.unbind(".dlBirdMove"); + $birdImg.unbind(".dlBirdMove"); + $birdZoom.unbind(".dlBirdMove"); + if (! isFullArea(data.zoomArea)) { + // set new handler + $birdImg.bind("mousedown.dlBirdMove", birdZoomStartDrag); + $birdZoom.bind("mousedown.dlBirdMove", birdZoomStartDrag); + } + }; + + // move bird zoom indicator to reflect zoomed detail area + var setBirdZoom = function(data, rect) { + var part = data.imgTrafo.invtransform(rect); + // area = FULL_AREA.fit(part); // no, we want to see where we transcend the borders + birdTrafo = getImgTrafo(data.$birdImg, FULL_AREA); + var birdRect = birdTrafo.transform(part); + var $birdZoom = data.$birdZoom; + // acount for border width + var bw = getBorderWidth($birdZoom); + birdRect.addPosition({x : -bw, y : -bw}); + birdRect.adjustDiv(data.$birdZoom); + }; + // plugin object with name and init // shared objects filled by digilib on registration var digilib = { name : 'birdseye', - init : plugInit, + install : install, buttons : {}, actions : {}, fn : {},
--- a/client/digitallibrary/jquery/jquery.digilib.geometry.js Fri Feb 18 10:39:40 2011 +0100 +++ b/client/digitallibrary/jquery/jquery.digilib.geometry.js Fri Feb 18 15:16:30 2011 +0100 @@ -475,17 +475,33 @@ }; // export constructor functions to digilib plugin - var init = function () { - return { + var geometry = { size : size, position : position, rectangle : rectangle, transform : transform - }; + }; + // install function called by digilib on plugin object + var install = function() { + // add constructor object to fn + this.fn.geometry = geometry; }; + // digilib plugin object + var plugin = { + name : 'geometry', + install : install, + fn : {}, + // TODO: remove old init + init : init + }; + // TODO: remove old version of init returning contructor + var init = function () { + return geometry; + }; + // plug into digilib if ($.fn.digilib == null) { $.error("jquery.digilib.geometry must be loaded after jquery.digilib!"); } else { - $.fn.digilib('plugin', {name : 'geometry', init : init}); + $.fn.digilib('plugin', plugin); } })(jQuery);
--- a/client/digitallibrary/jquery/jquery.digilib.js Fri Feb 18 10:39:40 2011 +0100 +++ b/client/digitallibrary/jquery/jquery.digilib.js Fri Feb 18 15:16:30 2011 +0100 @@ -269,7 +269,8 @@ // last straw: old version geom = dlGeometry(); } else { - geom = plugins.geometry.init(); + // geometry plugin puts classes in the shared fn + geom = fn.geometry; } FULL_AREA = geom.rectangle(0, 0, 1, 1); @@ -327,7 +328,7 @@ // TODO: move plugins reference out of data plugins : plugins }; - // store in data element + // store in jQuery data element $elem.data('digilib', data); } unpackParams(data); @@ -358,13 +359,9 @@ // initialise plugins for (n in plugins) { var p = plugins[n]; - // share common objects - p.buttons = buttons; - p.actions = actions; - p.fn = fn; - p.plugins = plugins; - // and init - p.init(data); + if (typeof p.init === 'function') { + p.init(data); + } } // get image info from server if needed if (data.scaleMode === 'pixel' || data.scaleMode === 'size') { @@ -1807,6 +1804,16 @@ // each plugin needs a name if (plugin.name != null) { plugins[plugin.name] = plugin; + // share common objects + plugin.defaults = defaults; + plugin.buttons = buttons; + plugin.actions = actions; + plugin.fn = fn; + plugin.plugins = plugins; + // and install + if (typeof plugin.install === 'function') { + plugin.install(plugin); + } } // initialisation of plugins done later } else if (actions[action]) {