# HG changeset patch
# User robcast
# Date 1298038590 -3600
# Node ID 63c1b33e38b1d342eb6f897876f690d4247ada8a
# Parent 304488c72344af422cc836e8d10e45f69c68eb90
documentation for new plugin api in jquery-digilib-plugin.txt.
more steps towards plugification of birdseye view.
diff -r 304488c72344 -r 63c1b33e38b1 client/digitallibrary/jquery/jquery-digilib-plugins.txt
--- /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...
diff -r 304488c72344 -r 63c1b33e38b1 client/digitallibrary/jquery/jquery.digilib.birdseye.js
--- 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 = $('
');
+ // the detail indicator frame
+ var $birdZoom = $('');
+ // the small image
+ var $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 : {},
diff -r 304488c72344 -r 63c1b33e38b1 client/digitallibrary/jquery/jquery.digilib.geometry.js
--- 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);
diff -r 304488c72344 -r 63c1b33e38b1 client/digitallibrary/jquery/jquery.digilib.js
--- 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]) {