Mercurial > hg > digilib
view client/digitallibrary/jquery/jquery.digilib.js @ 629:6b24ad042d7b jquery
last and next page works now
implemented redisplay function (only tested with fullscreen)
parameters that are changed need to be in data.queryParams to get in the url on redisplay
author | robcast |
---|---|
date | Tue, 18 Jan 2011 21:30:03 +0100 |
parents | a78491a53c2a |
children | 89d9ac6199a3 |
line wrap: on
line source
/* * digilib jQuery plugin * */ // fallback for console.log calls if (typeof(console) === 'undefined') { var console = { log : function(){}, debug : function(){}, error : function(){} }; } (function($) { var actions = { reference : { onclick : "javascript:getRefWin()", tooltip : "get a reference URL", img : "reference.png" }, zoomin : { onclick : "javascript:dl.zoomBy(1.4)", tooltip : "zoom in", img : "zoom-in.png" }, zoomout : { onclick : "javascript:zoomBy(0.7)", tooltip : "zoom out", img : "zoom-out.png" }, zoomarea : { onclick : "javascript:zoomArea()", tooltip : "zoom area", img : "zoom-area.png" }, zoomfull : { onclick : "javascript:zoomFullpage()", tooltip : "view the whole image", img : "zoom-full.png" }, pagewidth : { onclick : "javascript:zoomFullpage('width')", tooltip : "page width", img : "pagewidth.png" }, back : { onclick : ["gotoPage", "-1"], tooltip : "goto previous image", img : "back.png" }, fwd : { onclick : ["gotoPage", "+1"], tooltip : "goto next image", img : "fwd.png" }, page : { onclick : "javascript:gotoPageWin()", tooltip : "specify image", img : "page.png" }, bird : { onclick : "showBirdDiv", tooltip : "show bird's eye view", img : "birds-eye.png" }, help : { onclick : "showAboutDiv", tooltip : "about Digilib", img : "help.png" }, reset : { onclick : "javascript:resetImage()", tooltip : "reset image", img : "reset.png" }, mark : { onclick : "javascript:setMark()", tooltip : "set a mark", img : "mark.png" }, delmark : { onclick : "javascript:removeMark()", tooltip : "delete the last mark", img : "delmark.png" }, hmir : { onclick : "javascript:mirror('h')", tooltip : "mirror horizontally", img : "mirror-horizontal.png" }, vmir : { onclick : "javascript:mirror('v')", tooltip : "mirror vertically", img : "mirror-vertical.png" }, rot : { onclick : "javascript:setParamWin('rot', 'Rotate (0..360) clockwise')", tooltip : "rotate image", img : "rotate.png" }, brgt : { onclick : "javascript:setParamWin('brgt', 'Brightness (-255..255)')", tooltip : "set brightness", img : "brightness.png" }, cont : { onclick : "javascript:setParamWin('cont', 'Contrast (0..8)')", tooltip : "set contrast", img : "contrast.png" }, rgb : { onclick : "javascript:setParamWin('rgb', '...')", tooltip : "set rgb values", img : "rgb.png" }, quality : { onclick : "javascript:setQualityWin('Quality (0..2)')", tooltip : "set image quality", img : "quality.png" }, size : { onclick : "javascript:toggleSizeMenu()", tooltip : "set page size", img : "size.png" }, calibrationx : { onclick : "javascript:calibrate('x')", tooltip : "calibrate screen x-ratio", img : "calibration-x.png" }, scale : { onclick : "javascript:toggleScaleMenu()", tooltip : "change image scale", img : "original-size.png" }, options : { onclick : "javascript:toggleOptionDiv()", tooltip : "hide options", img : "options.png" }, SEP : { img : "sep.png" } }; var defaults = { // the root digilib element, for easy retrieval 'digilibRoot' : null, // version of this script 'version' : 'jquery.digilib.js 0.9', // logo url 'logoUrl' : '../img/digilib-logo-text1.png', // homepage url (behind logo) 'homeUrl' : 'http://digilib.berlios.de', // base URL to Scaler servlet 'scalerBaseUrl' : 'http://digilib.mpiwg-berlin.mpg.de/digitallibrary/servlet/Scaler', // list of Scaler parameters 'scalerParamNames' : ['fn','pn','dw','dh','ww','wh','wx','wy','ws','mo', 'rot','cont','brgt','rgbm','rgba','ddpi','ddpix','ddpiy'], // Scaler parameter defaults 'ww' : 1.0, 'wh' : 1.0, 'wx' : 0.0, 'wy' : 0.0, 'ws' : 1.0, // mode of operation. // fullscreen: takes parameters from page URL, keeps state in page URL // embedded: takes parameters from Javascript options, keeps state inside object 'interactionMode' : 'fullscreen', // actions 'actions' : actions, // path to button images (must end with a slash) 'buttonsImagePath' : '../greyskin/', // actions groups 'actionsStandard' : ["reference","zoomin","zoomout","zoomarea","zoomfull","pagewidth","back","fwd","page","bird","SEP","help","reset","options"], 'actionsSpecial' : ["mark","delmark","hmir","vmir","rot","brgt","cont","rgb","quality","size","calibrationx","scale","SEP","options"], 'actionsCustom' : [], // is birdView shown? 'isBirdDivVisible' : false, // dimensions of bird's eye window 'birdMaxX' : 200, 'birdMaxY' : 200, // is the "about" window shown? 'isAboutDivVisible' : false }; // affine geometry classes var geom = dlGeometry(); var methods = { // digilib initialization init : function(options) { // settings for this digilib instance are merged from defaults and options var settings = $.extend({}, defaults, options); var isFullscreen = settings.interactionMode === 'fullscreen'; var queryParams = {}; if (isFullscreen) { queryParams = parseQueryParams(); } return this.each(function() { var $elem = $(this); var data = $elem.data('digilib'); var elemSettings; // if the plugin hasn't been initialized yet if (!data) { // merge query parameters if (isFullscreen) { elemSettings = $.extend({}, settings, queryParams); } else { elemSettings = $.extend({}, settings, parseImgParams($elem)); } // store $(this) element in the settings elemSettings.digilibRoot = $elem; data = { target : $elem, settings : elemSettings, queryParams : queryParams }; // store in data element $elem.data('digilib', data); } unpackParams(data); // create HTML structure setupScalerDiv(data); setupButtons(data, 'actionsStandard'); // bird's eye view creation - TODO: could be deferred? setupBirdviewDiv(data); // about window creation - TODO: could be deferred? restrict to only one item? setupAboutDiv(data); }); }, // clean up digilib destroy : function() { return this.each(function(){ var $elem = $(this); var data = $elem.data('digilib'); // Namespacing FTW $(window).unbind('.digilib'); // unbinds all digilibs(?) data.digilib.remove(); $elem.removeData('digilib'); }); }, // show or hide the 'about' window showAboutDiv : function(show) { var $elem = $(this); var data = $elem.data('digilib'); data.settings.isAboutDivVisible = showDiv(data.settings.isAboutDivVisible, data.$aboutDiv, show); }, // event handler: toggles the visibility of the bird's eye window showBirdDiv : function (show) { var $elem = $(this); var data = $elem.data('digilib'); data.settings.isBirdDivVisible = showDiv(data.settings.isBirdDivVisible, data.$birdDiv, show); }, // goto given page nr (+/-: relative) gotoPage : function (pageNr) { var $elem = $(this); // the clicked button var data = $elem.data('digilib'); var settings = data.settings; var oldpn = settings.pn; var pn = setNumValue(settings, "pn", pageNr); if (pn == null) return false; // nothing happened if (pn < 1) { alert("no such page (page number too low)"); settings.pn = oldpn; return false; } if (settings.pt) { if (pn > settings.pt) { alert("no such page (page number too high)"); settings.pn = oldpn; return false; } } // add pn to param list and remove mk and others(?) data.queryParams.pn = pn; delete data.queryParams.mk; // then reload redisplay(data); } }; // sets a key to a value (relative values with +/- if relative=true) var setNumValue = function(settings, key, value) { // TODO: type and error checking if (settings[key] == null) return null; var sign = value.substring(0,1); if (sign === '+' || sign === '-') { settings[key] = parseFloat(settings[key]) + parseFloat(value); } else { settings[key] = value; } return settings[key]; }; // returns parameters from page url var parseQueryParams = function() { return parseQueryString(window.location.search.slice(1)); }; // returns parameters from embedded img-element var parseImgParams = function($elem) { var src = $elem.find('img').first().attr('src'); if (!src) { return null; } var pos = src.indexOf('?'); var query = (pos < 0) ? '' : src.substring(pos + 1); var scalerUrl = src.substring(0, pos); var params = parseQueryString(query); params.scalerBaseUrl = scalerUrl; return params; }; // parses query parameter string into parameter object var parseQueryString = function(query) { var pairs = query.split("&"); var params = {}; //var keys = []; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split("="); if (pair.length === 2) { params[pair[0]] = pair[1]; //keys.push(pair[0]); } } return params; }; // returns a query string from key names from a parameter hash var getParamString = function (settings, keys) { var paramString = ''; var latter = false; for (i = 0; i < keys.length; ++i) { var key = keys[i]; if (settings[key]) { // first param gets no '&' paramString += latter ? '&' : ''; latter = true; // add parm=val paramString += key + '=' + settings[key]; } } return paramString; }; // returns URL and query string for Scaler var getScalerUrl = function (data) { var settings = data.settings; var keys = settings.scalerParamNames; var queryString = getParamString(settings, keys); var url = settings.scalerBaseUrl + '?' + queryString; return url; }; // returns URL and query string for current digilib var getDigilibUrl = function (data) { var settings = data.settings; // make list from queryParams keys var keys = []; for (var k in data.queryParams) { keys.push(k); } var queryString = getParamString(settings, keys); var url = window.location.toString(); var pos = url.indexOf('?'); var baseUrl = url.substring(0, pos); var newurl = baseUrl + '?' + queryString; return newurl; }; // processes some parameters into objects and stuff var unpackParams = function (data) { var settings = data.settings; // zoom area var zoomArea = geom.rectangle(settings.wx, settings.wy, settings.ww, settings.wh); settings.zoomArea = zoomArea; // marks var marks = []; var mk = settings.mk || ''; if (mk.indexOf(";") >= 0) { var pa = mk.split(";"); // old format with ";" } else { var pa = mk.split(","); // new format } for (var i = 0; i < pa.length ; i++) { var pos = pa[i].split("/"); if (pos.length > 1) { marks.push(geom.position(pos[0], pos[1])); } } settings.marks = marks; }; // put objects back into parameters var packParams = function (data) { var settings = data.settings; // zoom area if (settings.zoomArea) { settings.wx = settings.zoomArea.x; settings.wy = settings.zoomArea.y; settings.ww = settings.zoomArea.width; settings.wh = settings.zoomArea.height; } // marks if (settings.marks) { var ma = []; for (var i = 0; i < settings.marks.length; i++) { ma.push(cropFloat(settings.marks[i].x) + "/" + cropFloat(settings.marks[i].y)); } settings.mk = ma.join(","); } }; // returns maximum size for scaler img in fullscreen mode var getFullscreenImgSize = function($elem) { var winH = $(window).height(); var winW = $(window).width(); // TODO: account for borders? return geom.size(winW, winH); }; // (re)load the img from a new scaler URL var redisplay = function (data) { var settings = data.settings; if (settings.interactionMode === 'fullscreen') { // update location.href (browser URL) in fullscreen mode var url = getDigilibUrl(data); var history = window.history; if (typeof(history.pushState) === 'function') { console.debug("we could modify history, but we don't..."); } window.location = url; } else { // embedded mode -- just change img src var url = getScalerUrl(data); data.$img.attr('src', url); } }; // creates HTML structure for digilib in elem var setupScalerDiv = function (data) { var settings = data.settings; var $elem = data.target; var $img; if (settings.interactionMode === 'fullscreen') { // fullscreen var imgSize = getFullscreenImgSize($elem); settings.dw = imgSize.width; settings.dh = imgSize.height; $img = $('<img/>'); var scalerUrl = getScalerUrl(data); $img.attr('src', scalerUrl); } else { // embedded mode -- try to keep img tag $img = $elem.find('img'); if ($img.length > 0) { console.debug("img detach:",$img); $img.detach(); } else { $img = $('<img/>'); var scalerUrl = getScalerUrl(data); $img.attr('src', scalerUrl); } } // create new html $elem.empty(); // TODO: should we keep stuff for customization? var $scaler = $('<div class="scaler"/>'); $elem.append($scaler); $scaler.append($img); $img.addClass('pic'); data.$img = $img; $img.load(scalerImgLoadedHandler(data)); }; // creates HTML structure for buttons in elem var setupButtons = function (data, actionGroup) { var $elem = data.target; var settings = data.settings; if (settings.interactionMode === 'fullscreen') { // fullscreen -- create new var $buttonsDiv = $('<div class="buttons"></div>'); $elem.append($buttonsDiv); var actionNames = settings[actionGroup]; for (var i = 0; i < actionNames.length; i++) { var actionName = actionNames[i]; var actionSettings = settings.actions[actionName]; // construct the button html var $button = $('<div class="button"></div>'); var $a = $('<a/>'); var $img = $('<img class="button"/>'); $buttonsDiv.append($button); $button.append($a); $a.append($img); // add attributes and bindings $button.attr('title', actionSettings.tooltip); $button.addClass('button-' + actionName); // create handler for the buttons $a.bind('click', (function () { // we create a new closure to capture the value of method var method = actionSettings.onclick; if ($.isArray(method)) { // the handler function calls digilib with method and parameters return function () { console.debug('click method=', method); $elem.digilib.apply($elem, method); }; } else { // the handler function calls digilib with method return function () { console.debug('click method=', method); $elem.digilib(method); }; } })()); $img.attr('src', settings.buttonsImagePath + actionSettings.img); }; } return $buttonsDiv; }; // creates HTML structure for the bird's eye view in elem var setupBirdviewDiv = function (data) { var $elem = data.target; var settings = data.settings; // use only the relevant parameters var keys = ['fn','pn','dw','dh']; var birdDimensions = { 'dw' : settings.birdMaxX, 'dh' : settings.birdMaxY }; var birdSettings = $.extend({}, settings, birdDimensions); var birdUrl = settings.scalerBaseUrl + '?' + getParamString(birdSettings, keys); // the bird's eye div var $birdviewDiv = $('<div class="birdview" style="display:none"/>'); // the detail indicator frame var $birdzoomDiv = $('<div class="birdzoom"/>'); // the small image var $birdImg = $('<img class="birdimg"/>'); $elem.append($birdviewDiv); $birdviewDiv.append($birdzoomDiv); $birdviewDiv.append($birdImg); $birdImg.attr('src', birdUrl); data.$birdDiv = $birdviewDiv; }; // creates HTML structure for the about view in elem var setupAboutDiv = function (data) { var $elem = data.target; var settings = data.settings; var $aboutDiv = $('<div class="about" style="display:none"/>'); var $header = $('<p>Digilib Graphic Viewer</p>'); var $link = $('<a/>'); var $logo = $('<img class="logo" title="digilib"/>'); var $content = $('<p/>'); $elem.append($aboutDiv); $aboutDiv.append($header); $aboutDiv.append($link); $aboutDiv.append($content); $link.append($logo); $logo.attr('src', settings.logoUrl); $link.attr('href', settings.homeUrl); $content.text('Version: ' + settings.version); // click hides $aboutDiv.bind('click', function () { showDiv(settings.isAboutDivVisible, $aboutDiv, 0); }); data.$aboutDiv = $aboutDiv; }; // shows some window e.g. 'about' (toggle visibility if show is null) var showDiv = function (isVisible, $div, show) { if (typeof(show) !== 'number') { // toggle visibility isVisible = !isVisible; } else { // set visibility isVisible = show; } if (isVisible) { $div.fadeIn(); } else { $div.fadeOut(); } return isVisible; }; // returns function for load event of scaler img var scalerImgLoadedHandler = function (data) { var settings = data.settings; var $elem = data.target; var $img = data.$img; return function () { console.debug("img loaded! this=", this, " data=", data); var area = settings.zoomArea; // create Transform from current area and picsize var picpos = $img.offset(); var picrect = geom.rectangle(picpos.left, picpos.top, $img.width(), $img.height()); var trafo = geom.transform(); // subtract area offset and size trafo.concat(trafo.getTranslation(geom.position(area.x, area.y))); trafo.concat(trafo.getScale(geom.size(1/area.width, 1/area.height))); // scale to screen size trafo.concat(trafo.getScale(picrect)); trafo.concat(trafo.getTranslation(picrect)); data.imgTrafo = trafo; // display marks renderMarks(data); // show birds eye view //showDiv(settings.isBirdDivVisible); //digilib.showArrows(); // show arrow overlays for zoom navigation // done -- hide about div settings.isAboutDivVisible = showDiv(null, data.$aboutDiv, 0); }; }; // place marks on the image var renderMarks = function (data) { var $elem = data.target; var marks = data.settings.marks; for (var i = 0; i < marks.length; i++) { var mark = marks[i]; if (data.settings.zoomArea.containsPosition(mark)) { var mpos = data.imgTrafo.transform(mark); // create mark var html = '<div class="mark">'+(i+1)+'</div>'; var $mark = $(html); $elem.append($mark); $mark.offset({ left : mpos.x, top : mpos.y}); } } }; // auxiliary function to crop senseless precision var cropFloat = function (x) { return parseInt(10000 * x) / 10000; }; // hook plugin into jquery $.fn.digilib = function(method) { if (methods[method]) { // call method on this with the remaining arguments return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof(method) === 'object' || !method) { // call init on this return methods.init.apply(this, arguments); } else { $.error( 'Method ' + method + ' does not exist on jQuery.digilib' ); } }; })(jQuery);