Mercurial > hg > digilib
changeset 1488:49a5b1e73098
new digicat works now.
has rows and cols as parameters. no ui for setting geometry yet.
does not use sequence plugin yet.
author | robcast |
---|---|
date | Fri, 26 Feb 2016 18:57:43 +0100 |
parents | 684632a23c80 |
children | 02e055d9b84e |
files | webapp/src/main/webapp/jquery/digicat.html webapp/src/main/webapp/jquery/jquery.digicat.buttons.js webapp/src/main/webapp/jquery/jquery.digicat.css webapp/src/main/webapp/jquery/jquery.digicat.geometry.js webapp/src/main/webapp/jquery/jquery.digicat.js webapp/src/main/webapp/jquery/jquery.digilib.geometry.js |
diffstat | 6 files changed, 1651 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webapp/src/main/webapp/jquery/digicat.html Fri Feb 26 18:57:43 2016 +0100 @@ -0,0 +1,40 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="initial-scale=1.0"/> + <title>digicat TEST</title> + + <style type="text/css"> + body { + background: silver; + } + </style> + + <script type="text/javascript" src="jquery.js"></script> + <script type="text/javascript" src="jquery.cookie.js"></script> + <script type="text/javascript" src="jquery.digicat.js"></script> + <script type="text/javascript" src="jquery.digicat.geometry.js"></script> + <script type="text/javascript" src="jquery.digicat.buttons.js"></script> + <link rel="stylesheet" type="text/css" href="jquery.digicat.css" /> + <link rel="stylesheet" type="text/css" href="jquery.digilib.buttons-full-32-sprite.css" /> + + <script type="text/javascript"> + $(document).ready(function(){ + var opts = { + }; + var $div = $('div#digicat'); + $div.digicat(opts); + }); + + </script> + </head> + + <body> + <div id="digicat"> + <p>digicat doesn't work! Please switch on Javascript or notify the server administrator!</p> + <img src="http://digilib.sourceforge.net/images/digilib-logo-big.png" /> + </div> + </body> +</html> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webapp/src/main/webapp/jquery/jquery.digicat.buttons.js Fri Feb 26 18:57:43 2016 +0100 @@ -0,0 +1,510 @@ +/* + * #%L + * digilib buttons plugin + * %% + * Copyright (C) 2011 - 2013 Bibliotheca Hertziana, MPIWG Berlin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + * Authors: Martin Raspe, Robert Casties + */ +/** +digilib buttons plugin + */ + +(function($) { + + // plugin object with digilib data + var digilib = null; + // the functions made available by digilib + var fn = null; + // affine geometry plugin + var geom = null; + + var buttons = { + reference : { + onclick : "reference", + tooltip : "get a reference URL", + icon : "reference.png" + }, + zoomin : { + onclick : ["zoomBy", 1.4], + tooltip : "zoom in", + icon : "zoom-in.png" + }, + zoomout : { + onclick : ["zoomBy", 0.7], + tooltip : "zoom out", + icon : "zoom-out.png" + }, + zoomarea : { + onclick : "zoomArea", + tooltip : "zoom area", + icon : "zoom-area.png" + }, + zoomfull : { + onclick : "zoomFull", + tooltip : "view the whole image", + icon : "zoom-full.png" + }, + pagewidth : { + onclick : ["zoomFull", "width"], + tooltip : "page width", + icon : "pagewidth.png" + }, + back : { + onclick : ["gotoPage", "-1"], + tooltip : "goto previous page", + icon : "back.png" + }, + fwd : { + onclick : ["gotoPage", "+1"], + tooltip : "goto next page", + icon : "fwd.png" + }, + page : { + onclick : "gotoPage", + tooltip : "goto page number", + icon : "page.png" + }, + about : { + onclick : "about", + tooltip : "about Digilib", + icon : "info.png" + }, + reset : { + onclick : "reset", + tooltip : "reset image", + icon : "reset.png" + }, + hmir : { + onclick : ["mirror", "h"], + tooltip : "mirror horizontally", + icon : "mirror-horizontal.png" + }, + vmir : { + onclick : ["mirror", "v"], + tooltip : "mirror vertically", + icon : "mirror-vertical.png" + }, + rot : { + onclick : "rotate", + tooltip : "rotate image", + icon : "rotate.png" + }, + brgt : { + onclick : "brightness", + tooltip : "set brightness", + icon : "brightness.png" + }, + cont : { + onclick : "contrast", + tooltip : "set contrast", + icon : "contrast.png" + }, + rgb : { + onclick : "setRGB", + tooltip : "set rgb values", + icon : "rgb.png" + }, + quality : { + onclick : "setQuality", + tooltip : "set image quality", + icon : "quality.png" + }, + size : { + onclick : "setSize", + tooltip : "set page size", + icon : "size-bigger.png" + }, + calibrationx : { + // onclick : "showCalibrationDiv", + onclick : "calibrate", + tooltip : "calibrate screen resolution", + icon : "calibration.png" + }, + scale : { + // onclick : "showScaleModeSelector", + onclick : "setScaleMode", + tooltip : "change image scale", + icon : "original-size.png" + }, + toggleoptions : { + onclick : "moreButtons", + tooltip : "more options", + icon : "options.png" + }, + moreoptions : { + onclick : ["moreButtons", "+1"], + tooltip : "more options", + icon : "buttons-more.png" + }, + lessoptions : { + onclick : ["moreButtons", "-1"], + tooltip : "less options", + icon : "buttons-less.png" + }, + SEP : { + icon : "sep.png" + } + }; + + var modes = [ + { name : "screen", + label : "fit to screen", + tooltip : "scales the graphic file so that it fills the screen" + }, + { name : "pixel", + label : "pixel by pixel", + tooltip : "all pixels of the current part of the graphic file are shown" + }, + { name : "size", + label : "original size", + tooltip : "tries to display the current part of the graphic file in the size of the orginal resource (after screen calibration)" + } + ]; + + var defaults = { + // buttons (reference added later) + 'buttons' : null, + // disabled buttons (should be an array of button names) + 'buttonsDisabled' : [], + // show buttons needed for consecutive (book-like) consultation of image files + 'showPageButtons' : true, + // defaults for digilib buttons + 'buttonSettings' : { + 'fullscreen' : { + // path to button images (must end with a slash) + 'imagePath' : 'img/fullscreen/32/', + 'buttonSetWidth' : 36, + 'standardSet' : ["back","fwd","page","about"], + 'specialSet' : ["mark","delmark","hmir","vmir","rot","brgt","cont","rgb","quality","size","calibrationx","scale","lessoptions","moreoptions"], + 'pageSet' : ["back","fwd","page"], + 'buttonSets' : ['standardSet', 'specialSet'] + }, + 'embedded' : { + 'imagePath' : 'img/embedded/16/', + 'buttonSetWidth' : 18, + 'standardSet' : ["reference","zoomin","zoomout","zoomarea","zoomfull","about","reset","moreoptions"], + 'specialSet' : ["mark","delmark","hmir","vmir","rot","brgt","cont","rgb","quality","scale","lessoptions"], + 'pageSet' : ["back","fwd","page"], + 'buttonSets' : ['standardSet', 'specialSet'] + } + }, + // number of visible button groups + 'visibleButtonSets' : 1 + }; + + var actions = { + // display more (or less) button sets + moreButtons : function (data, more) { + var settings = data.settings; + if (more == null) { + // toggle more or less (only works for 2 sets) + var maxbtns = settings.buttonSettings[settings.interactionMode].buttonSets.length; + if (settings.visibleButtonSets >= maxbtns) { + more = '-1'; + } else { + more = '+1'; + } + } + if (more === '-1') { + // remove set + var setIdx = settings.visibleButtonSets - 1; + if (showButtons(data, false, setIdx, true)) { + settings.visibleButtonSets--; + } + } else { + // add set + var setIdx = settings.visibleButtonSets; + if (showButtons(data, true, setIdx, true)) { + settings.visibleButtonSets++; + } + } + // adjust insets + data.currentInsets['buttons'] = getInsets(data); + // persist setting + fn.storeOptions(data); + } + }; + + // plugin installation called by digilib on plugin object. + var install = function(plugin) { + digilib = plugin; + console.debug('installing buttons plugin. digilib:', digilib); + fn = digilib.fn; + // import geometry classes + geom = fn.geometry; + // add defaults, actions, buttons + $.extend(digilib.buttons, buttons); + $.extend(true, digilib.defaults, defaults); // make deep copy + $.extend(digilib.actions, actions); + // update buttons reference in defaults + digilib.defaults.buttons = digilib.buttons; + // export functions + fn.createButton = createButton; + fn.highlightButtons = highlightButtons; + fn.setButtonAction = setButtonAction; + fn.findButtonByName = findButtonByName; + }; + + // plugin initialization + var init = function (data) { + console.debug('initialising buttons plugin. data:', data); + var settings = data.settings; + // add insets + data.currentInsets['buttons'] = getInsets(data); + if (!settings.showPageButtons) { + var pageSet = settings.buttonSettings[settings.interactionMode].pageSet; + $.merge(settings.buttonsDisabled, pageSet); + } + // install event handler + var $data = $(data); + $data.bind('setup', handleSetup); + }; + + var handleSetup = function (evt) { + console.debug("buttons: handleSetup"); + var data = this; + var settings = data.settings; + // create buttons before scaler + for (var i = 0; i < settings.visibleButtonSets; ++i) { + showButtons(data, true, i); + } + disableButtons(data); + }; + + /** + * returns insets for buttons (based on visibleButtonSets and buttonSetWidth + */ + var getInsets = function (data) { + var settings = data.settings; + var bw = settings.visibleButtonSets * settings.buttonSettings[settings.interactionMode].buttonSetWidth; + var insets = {'x' : bw, 'y' : 0}; + return insets; + }; + + /** + * creates HTML structure for a single button + */ + var createButton = function (data, $div, buttonName) { + var $elem = data.$elem; + var settings = data.settings; + var cssPrefix = settings.cssPrefix; + var mode = settings.interactionMode; + var imagePath = settings.buttonSettings[mode].imagePath; + // make relative imagePath absolute + if (imagePath.charAt(0) !== '/' && imagePath.substring(0,7) !== 'http://') { + imagePath = settings.digilibBaseUrl + '/jquery/' + imagePath; + } + var buttonConfig = settings.buttons[buttonName]; + if (buttonConfig == null) { + console.error('Could not create button: ' + buttonName); + return; + } + // button properties + var action = buttonConfig.onclick; + var tooltip = buttonConfig.tooltip; + var iconId = buttonConfig.icon.slice(0, -4); + // construct the button html + var html = '\ + <div id="'+cssPrefix+'button-'+buttonName+'" class="'+cssPrefix+'button" title="'+tooltip+'">\ + <a href="">\ + <div id="'+cssPrefix+'button-'+iconId+'-img"></div>\ + </a>\ + </div>'; + var $button = $(html); + $button.appendTo($div); + // create handler for the buttons + $button.on('click.digilib', (function () { + // we create a new closure to capture the value of action + if ($.isArray(action)) { + // the handler function calls digilib with action and parameters + return function (evt) { + console.debug('click action=', action, ' evt=', evt); + $elem.digicat.apply($elem, action); + return false; + }; + } else { + // the handler function calls digilib with action + return function (evt) { + console.debug('click action=', action, ' evt=', evt); + $elem.digicat(action); + return false; + }; + } + })()); + return $button; + }; + + // creates HTML structure for buttons in elem + var createButtons = function (data, buttonSetIdx) { + var $elem = data.$elem; + var settings = data.settings; + var mode = settings.interactionMode; + var cssPrefix = settings.cssPrefix; + var buttonSettings = settings.buttonSettings[mode]; + var buttonGroup = buttonSettings.buttonSets[buttonSetIdx]; + if (buttonGroup == null) { + // no buttons here + return; + } + // button divs are marked with class "keep" + var $buttonsDiv = $('<div class="'+cssPrefix+'keep '+cssPrefix+'buttons"/>'); + var buttonNames = buttonSettings[buttonGroup]; + for (var i = 0; i < buttonNames.length; i++) { + var buttonName = buttonNames[i]; + var $button = createButton(data, $buttonsDiv, buttonName); + settings.buttons[buttonName].button = $button; + } + // make buttons div scroll if too large for window + if ($buttonsDiv.height() > $(window).height() - 10) { + $buttonsDiv.css('position', 'absolute'); + } + // buttons hidden at first + $buttonsDiv.hide(); + $elem.append($buttonsDiv); + if (data.$buttonSets == null) { + // first button set + data.$buttonSets = [$buttonsDiv]; + } else { + $elem.append($buttonsDiv); + data.$buttonSets[buttonSetIdx] = $buttonsDiv; + } + return $buttonsDiv; + }; + + // display more (or less) button sets + var showButtons = function (data, more, setIdx, animated) { + var atime = animated ? 'fast': 0; + var cssPrefix = data.settings.cssPrefix; + // get button width from settings + var mode = data.settings.interactionMode; + var btnWidth = data.settings.buttonSettings[mode].buttonSetWidth; + if (more) { + // add set + var $otherSets = data.$elem.find('div.'+cssPrefix+'buttons:visible'); + var $set; + if (data.$buttonSets && data.$buttonSets[setIdx]) { + // set exists + $set = data.$buttonSets[setIdx]; + } else { + $set = createButtons(data, setIdx); + } + if ($set == null) return false; + // include border in calculation + //var btnWidth = $set.outerWidth(); + // console.debug("btnWidth", btnWidth); + // move remaining sets left and show new set + if ($otherSets.length > 0) { + $otherSets.animate({right : '+='+btnWidth+'px'}, atime, + function () {$set.show();}); + } else { + $set.show(); + } + } else { + // remove set + var $set = data.$buttonSets[setIdx]; + if ($set == null) return false; + //var btnWidth = $set.outerWidth(); + // hide last set + $set.hide(); + // take remaining sets and move right + var $otherSets = data.$elem.find('div.'+cssPrefix+'buttons:visible'); + $otherSets.animate({right : '-='+btnWidth+'px'}, atime); + } + return true; + }; + + // check for buttons to highlight TODO: improve this! + var highlightButtons = function (data, name, on) { + var cssPrefix = data.settings.cssPrefix; + var $buttons = data.$elem.find('div.'+cssPrefix+'buttons:visible'); // include hidden? + // add a class for highlighted button + var highlight = function (name, on) { + var $button = findButtonByName(data, name); + if (on) { + $button.addClass(cssPrefix+'button-on'); + } else { + $button.removeClass(cssPrefix+'button-on'); + } + }; + if (name != null) { + return highlight(name, on); + } + var flags = data.scalerFlags; + var settings = data.settings; + highlight('rot', settings.rot); + highlight('brgt', settings.brgt); + highlight('cont', settings.cont); + highlight('bird', settings.isBirdDivVisible); + highlight('hmir', flags.hmir); + highlight('vmir', flags.vmir); + highlight('quality', flags.q1 || flags.q2); + highlight('zoomin', ! isFullArea(data.zoomArea)); + }; + + // find a button + var findButtonByName = function (data, name) { + var $elem = data.$elem; + var cssPrefix = data.settings.cssPrefix; + var $button = $elem.find('#'+cssPrefix+'button-'+name); + console.debug("find button", name, $button); + return $button; + }; + + // hide disabled buttons + var disableButtons = function (data, buttonnames) { + // if present, buttonnames should be an array of button names + var $elem = data.$elem; + var settings = data.settings; + var cssPrefix = settings.cssPrefix; + var disabled = buttonnames || settings.buttonsDisabled; + $.each(disabled, function(index, name) { + var $button = findButtonByName(data, name); + $button.addClass(cssPrefix+'disabled'); + }); + console.debug('disabled buttons:', disabled); + }; + + // set standard button "onclick" field to a new action + var setButtonAction = function(buttonName, action) { + var button = buttons[buttonName]; + if (button == null) { + console.log('could not set button action ' + action + + ', button ' + buttonName + ' not available' ); + return; + } + button.onclick = action; + }; + + // plugin object with name and init + // shared objects filled by digilib on registration + var plugin = { + name : 'buttons', + install : install, + init : init, + buttons : {}, + actions : {}, + fn : {}, + plugins : {} + }; + + if ($.fn.digicat == null) { + $.error("jquery.digicat.buttons must be loaded after jquery.digicat!"); + } else { + $.fn.digicat('plugin', plugin); + } +})(jQuery);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webapp/src/main/webapp/jquery/jquery.digicat.css Fri Feb 26 18:57:43 2016 +0100 @@ -0,0 +1,73 @@ +/* + * CSS style file for jQuery digilib + * + * Martin Raspe, Robert Casties, 11.1.2011 + */ +* { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +div.dl-digicat .dl-disabled { + display: none; +} + +div.dl-digicat, +div.dl-digicat button, +div.dl-digicat input { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 12px; +} + + +div.dl-digicat div.dl-about { + position: absolute; + padding: 10px; + font-family: Verdana, Arial, Helvetica, sans-serif; + border: 2px solid aqua; + background-color: silver; + text-align: center; + display: none; + z-index: 100; +} + +div.dl-digicat .dl-error { + color: red; + background-color: maroon; + } + +div.dl-digicat div.dl-buttons { + position: fixed; + right: 0px; + top: 0px; + padding: 2px; + background-color: transparent; + z-index: 200; +} + +div.dl-digicat div.dl-buttons div.dl-button { + margin-bottom: 3px; +} + +div.dl-digicat div.dl-buttons div.dl-button:hover { + background-image: url('img/fullscreen/corona.png'); + background-repeat: no-repeat; +} + +div.dl-digicat div.dl-button-on { + background-image: url('img/fullscreen/whitedisc.png'); + background-repeat: no-repeat; +} + +/* no borders for button images */ +div.dl-digicat a img.dl-button { + border:none; +} + +/* table contents */ +div.dl-digicat td { + text-align: center; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webapp/src/main/webapp/jquery/jquery.digicat.geometry.js Fri Feb 26 18:57:43 2016 +0100 @@ -0,0 +1,811 @@ +/* + * #%L + * required digilib geometry plugin + * %% + * Copyright (C) 2011 - 2013 MPIWG Berlin, Bibliotheca Hertziana + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + * Authors: Robert Casties, Martin Raspe + */ +/** required digilib geometry plugin + */ + +(function($) { +//var dlGeometry = function() { + /* + * Size class + */ + var size = function(w, h) { + var that; + if (typeof w === "object") { + // assume an object having width and height + that = { + width : w.width, + height : w.height + }; + } else { + that = { + width : parseFloat(w), + height : parseFloat(h) + }; + } + // returns true if both sizes are equal + that.equals = function(other) { + return (this.width === other.width && this.height === other.height); + }; + // returns the aspect ratio of this size + that.getAspect = function() { + return (this.width / this.height); + }; + // returns a size of a given aspect ratio that fits into this one + that.fitAspect = function(aspect) { + var s = size(this); + if (aspect > this.getAspect()) { + // size is more horizontally stretched than this + s.height = s.width / aspect; + } else { + s.width = s.height * aspect; + } + return s; + }; + // adjusts size of jQuery element "$elem" to this size + that.adjustDiv = function($elem) { + $elem.width(this.width).height(this.height); + }; + that.toString = function() { + return (this.width + "x" + this.height); + }; + return that; + }; + + /* + * Position class + */ + var position = function(x, y) { + var that; + if (typeof x === "object") { + if (x instanceof jQuery) { + // jQuery object + var pos = x.offset(); + that = { + x : pos.left, + y : pos.top + }; + } else if ($.isArray(x)) { + that = { + x : x[0], + y : x[1] + }; + } else { + if (x.x != null) { + // position object + that = { + x : parseFloat(x.x), + y : parseFloat(x.y) + }; + } + if (x.pageX != null) { + // event object + that = { + x : x.pageX, + y : x.pageY + }; + } + } + } else { + that = { + x : parseFloat(x), + y : parseFloat(y) + }; + }; + // return a copy of this position + that.copy = function() { + return position(this); + }; + // compare function + that.equals = function(other) { + return (this.x === other.x && this.y === other.y); + }; + // add vector or position to this + that.add = function(other) { + if ($.isArray(other)) { + this.x += other[0]; + this.y += other[1]; + } else { + this.x += other.x; + this.y += other.y; + } + return this; + }; + // returns negative position + that.neg = function() { + return position({ + x : -this.x, + y : -this.y + }); + }; + // returns new position that is the difference between this and other + that.delta = function(other) { + return position({ + x : other.x - this.x, + y : other.y - this.y + }); + }; + // returns other position scaled by ratio with regard to this point + that.scale = function(other, ratio) { + var d = this.delta(other); + return position({ + x : this.x + d.x * ratio, + y : this.y + d.y * ratio + }); + }; + // adjusts CSS position of $elem to this position + that.adjustDiv = function($elem) { + $elem.offset({ + left : this.x, + top : this.y + }); + }; + // move this position to another + that.moveTo = function(other) { + this.x = other.x; + this.y = other.y; + return this; + }; + // adjust this position so that is is inside rect + that.clipTo = function (rect) { + var p1 = rect.getPt1(); + var p2 = rect.getPt2(); + this.x = Math.max(this.x, p1.x); + this.y = Math.max(this.y, p1.y); + this.x = Math.min(this.x, p2.x); + this.y = Math.min(this.y, p2.y); + return this; + }; + // returns distance of this position to pos (length if pos == null) + that.distance = function(pos) { + if (pos == null) { + pos = { + x : 0, + y : 0 + }; + } + var dx = pos.x - this.x; + var dy = pos.y - this.y; + return Math.sqrt(dx * dx + dy * dy); + }; + // nearest of several points + that.nearest = function (points) { + var nearest = points[0]; + var dist = this.distance(nearest); + $.each(points, function(index, item) { + var len = this.distance(item); + if (len < dist) { + dist = len; + nearest = item; + } + }); + return nearest; + }; + // midpoint of this and other pos + that.mid = function (pos) { + return position({ + x : (this.x + pos.x)/2, + y : (this.y + pos.y)/2 + }); + }; + // radians of angle between line and the positive X axis + that.rad = function (pos) { + return Math.atan2(pos.y - this.y, pos.x - this.x); + }; + + // degree of angle between line and the positive X axis + that.deg = function (pos) { + return this.rad(pos) / Math.PI * 180; + }; + + // returns position in css-compatible format + that.getAsCss = function() { + return { + left : this.x, + top : this.y + }; + }; + // return as string + that.toString = function() { + return (this.x + "," + this.y); + }; + // return as array + that.toArray = function() { + return [this.x, this.y]; + }; + return that; + }; + + /* + * Line class (for on-screen geometry) + */ + var line = function(p, q) { + var that = { // definition point + x : p.x, + y : p.y + }; + if (q.x != null) { // second point + that.dx = q.x - that.x; + that.dy = q.y - that.y; + } else if ($.isArray(q)) { // vector + that.dx = q[0]; + that.dy = q[1]; + } else if (q === 0) { // slope + that.dx = 0; + that.dy = 1; + } else if (q === Infinity) { + that.dx = 1; + that.dy = 0; + } else if (q === -Infinity) { + that.dx = -1; + that.dy = 0; + } else if (typeof q === 'number' && isFinite(q)) { + that.dx = 1; + that.dy = 1/q; + } else { + that.dx = 1; + that.dy = 1; + } + // get/set origin of line + that.origin = function(p) { + if (p == null) { + return position(this.x, this.y); + } + this.x = p.x; + this.y = p.y; + return this; + }; + // get/set vector + that.vector = function(vector) { + if (vector == null) { + return [this.dx, this.dy]; + } + this.dx = vector[0]; + this.dy = vector[1]; + return this; + }; + // return a vector with the contrary direction + that.invertedVector = function() { + return [-this.dx, -this.dy]; + }; + // return a vector that is perpendicular to this line + that.perpendicularVector = function(clockwise) { + return clockwise ? [-this.dy, this.dx] : [this.dy, -this.dx]; + }; + // return vector distance + that.dist = function() { + return Math.sqrt(this.dx * this.dx + this.dy * this.dy); + }; + // multiply vector with a ratio + that.scale = function(ratio) { + this.dx *= ratio; + this.dy *= ratio + return this; + }; + // get/set vector length + that.length = function(length) { + var dist = this.dist(); + if (length == null) { + return dist; + } + return this.scale(length/dist); + }; + // return the slope + that.slope = function() { + return this.dx/this.dy; + }; + // return a copy of this line + that.copy = function() { + return line(position(this.x, this.y), this.vector()); + }; + // invert direction + that.invert = function() { + this.vector(this.invertedVector); + return this; + }; + // return a parallel line through a point (with the same vector) + that.parallel = function(p) { + return line(position(p.x, p.y), this.vector()); + }; + // return a perpendicular line from the origin (optionally from another point) with direction + that.perpendicular = function(p, clockwise) { + var point = (p == null || p.x == null) + ? position(this.x, this.y) : p; + return line(point, this.perpendicularVector(clockwise)); + }; + // return the intersection with a perpendicular line through a point + that.perpendicularPoint = function(p) { + return this.intersection(this.perpendicular(p)); + }; + // return perpendicular line from point + that.perpendicularLine = function(p) { + return line(p, this.perpendicularPoint(p)); + }; + // return point in mirrored position (with regard to this line) + that.mirror = function(p) { + var line = this.perpendicularLine(p); + return line.addEnd(line.vector()); + }; + // return a position by adding a vector/position/distance to origin + that.add = function(item) { + if (item == null) { + return this.origin(); + } else if ($.isArray(item)) { // add a vector + return position(this.x + item[0], this.y + item[1]) + } else if (item.x != null) { // add a position + return position(this.x + item.x, this.y + item.y); + } else if (typeof item === 'number' && isFinite(item)) { // add a distance + ratio = item/this.dist(); + return position(this.x + this.dx*ratio, this.y + this.dy*ratio); + } else { + return this.origin(); + } + }; + // return a position by adding a vector/position/distance to end point + that.addEnd = function(item) { + return this.add(item).add(this.vector()); + }; + // end point on the line (pointed to by vector) + that.point = function(factor) { + if (factor == null) { factor = 1; } + var vector = [factor*this.dx, factor*this.dy]; + return this.add(vector); + }; + // midpoint on the line (half of vector distance, multiplied by factor) + that.mid = function(factor) { + return this.origin().mid(this.point(factor)); + }; + // factor of point (assuming it is on the line) + that.factor = function(p) { + return (dx === 0) + ? (p.y - this.y)/this.dy + : (p.x - this.x)/this.dx; + }; + // intersection point with other line + that.intersection = function(line) { + var denominator = this.dy*line.dx - this.dx*line.dy + if (denominator === 0) { // parallel + return null; } + var num = this.dx*(line.y - this.y) + this.dy*(this.x - line.x); + return line.point(num/denominator); + }; + return that; + }; + + /* + * Rectangle class + */ + var rectangle = function(x, y, w, h) { + var that = {}; + if (typeof x === "object") { + if (x instanceof jQuery) { + // jQuery object + var pos = x.offset(); + that = { + x : pos.left, + y : pos.top, + width : x.width(), + height : x.height() + }; + } else if (y == null) { + // assume x is rectangle + that = { + x : parseFloat(x.x) || 0, + y : parseFloat(x.y) || 0, + width : parseFloat(x.width) || 0, + height : parseFloat(x.height) || 0 + }; + } else { + // assume x and y are Position + that = { + x : Math.min(x.x, y.x), + y : Math.min(x.y, y.y), + width : Math.abs(y.x - x.x), + height : Math.abs(y.y - x.y) + }; + } + } else { + that = { + x : parseFloat(x), + y : parseFloat(y), + width : parseFloat(w), + height : parseFloat(h) + }; + } + // returns a copy of this Rectangle + that.copy = function() { + return rectangle(this); + }; + // returns the position of this Rectangle + that.getPosition = function() { + return position(this); + }; + // returns the size of this Rectangle + that.getSize = function() { + return size(this); + }; + // returns the upper left corner position + that.getPt1 = that.getPosition; + // returns the lower right corner position of this Rectangle + that.getPt2 = function() { + return position({ + x : this.x + this.width, + y : this.y + this.height + }); + }; + // sets the upper left corner position to pos + that.setPosition = function(pos) { + this.x = pos.x; + this.y = pos.y; + return this; + }; + // adds pos to the position + that.setPt1 = that.setPosition; // TODO: not really the same + that.addPosition = function(pos) { + this.x += pos.x; + this.y += pos.y; + return this; + }; + // adds pos to the dimensions + that.enlarge = function(pos) { + this.width += pos.x; + this.height += pos.y; + return this; + }; + // sets the lower right corner to position pos + that.setPt2 = function(pos) { + this.width = pos.x - this.x; + this.height = pos.y - this.y; + return this; + }; + // returns the center position of this Rectangle + that.getCenter = function() { + return position({ + x : this.x + this.width / 2, + y : this.y + this.height / 2 + }); + }; + // moves this rectangle's center to position pos + that.setCenter = function(pos) { + this.x = pos.x - this.width / 2; + this.y = pos.y - this.height / 2; + return this; + }; + // returns true if both rectangles have equal position and size + that.equals = function(other) { + var eq = (this.x === other.x && this.y === other.y && this.width === other.width); + return eq; + }; + // returns a rectangle with the difference width, height and position + that.delta = function(other) { + return rectangle(other.x - this.x, other.y - this.y, + other.width - this.width, other.height - this.height); + }; + // returns the area of this Rectangle + that.getArea = function() { + return (this.width * this.height); + }; + // returns the aspect ratio of this Rectangle + that.getAspect = function() { + return (this.width / this.height); + }; + // eliminates negative width and height + that.normalize = function() { + var p = this.getPt2(); + this.x = Math.min(this.x, p.x); + this.y = Math.min(this.y, p.y); + this.width = Math.abs(this.width); + this.height = Math.abs(this.height); + return this; + }; + // returns if Position "pos" lies inside of this rectangle + that.containsPosition = function(pos) { + var ct = ((pos.x >= this.x) && (pos.y >= this.y) + && (pos.x <= this.x + this.width) && (pos.y <= this.y + + this.height)); + return ct; + }; + // returns true if rectangle "rect" is contained in this rectangle + that.containsRect = function(rect) { + return (this.containsPosition(rect.getPt1()) && this + .containsPosition(rect.getPt2())); + }; + // returns true if rectangle "rect" and this rectangle overlap + that.overlapsRect = function(rect) { + return this.intersect(rect) != null; + }; + // returns the ratio of height to width + that.getProportion = function() { + return this.height/this.width; + }; + // shrink/grow rectangle until it has the given proportion + that.setProportion = function(ratio, canGrow) { + var prop = this.getProportion(); + if (ratio < prop == canGrow) { + this.width = this.height / ratio; + } else { + this.height = this.width * ratio; + } + return this; + }; + // changes this rectangle's x/y values so it stays inside of rectangle + // "rect", keeping the proportions + that.stayInside = function(rect) { + this.x = Math.max(this.x, rect.x); + this.y = Math.max(this.y, rect.y); + if (this.x + this.width > rect.x + rect.width) { + this.x = rect.x + rect.width - this.width; + } + if (this.y + this.height > rect.y + rect.height) { + this.y = rect.y + rect.height - this.height; + } + return this; + }; + // clips this rectangle so it stays inside of rectangle "rect" + that.clipTo = function(rect) { + var p1 = rect.getPt1(); + var p2 = rect.getPt2(); + var this2 = this.getPt2(); + this.setPosition(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y))); + this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y))); + return this; + }; + // returns the intersection of rectangle "rect" and this one + that.intersect = function(rect) { + var r = rect.copy(); + var result = r.clipTo(this); + if (result.width < 0 || result.height < 0) result = null; + return result; + }; + + // returns a copy of rectangle "rect" that fits into this one + // (moving it first) + that.fit = function(rect) { + var r = rect.copy(); + r.x = Math.max(r.x, this.x); + r.y = Math.max(r.y, this.x); + if (r.x + r.width > this.x + this.width) { + r.x = this.x + this.width - r.width; + } + if (r.y + r.height > this.y + this.height) { + r.y = this.y + this.height - r.height; + } + return r.intersect(this); + }; + + // adjusts position and size of jQuery element "$elem" to this rectangle + that.adjustDiv = function($elem) { + $elem.offset({ + left : this.x, + top : this.y + }); + $elem.width(this.width).height(this.height); + }; + // returns position and size of this rectangle in css-compatible format + that.getAsCss = function() { + return { + left : this.x, + top : this.y, + width : this.width, + height : this.height + }; + }; + // returns position and size of this rectangle formatted for SVG attributes + that.getAsSvg = function() { + return [this.x, this.y, this.width, this.height].join(" "); + }; + // returns if this rectangle is a rectangle + that.isRectangle = function () { + return this.width > 0 && this.height > 0; + }; + // returns size and position of this rectangle formatted for ??? (w x h@x,y) + that.toString = function() { + return this.width + "x" + this.height + "@" + this.x + "," + this.y; + }; + return that; + }; + + /* + * Transform class + * + * defines a class of affine transformations + */ + var transform = function(spec) { + var that = { + m00 : 1.0, + m01 : 0.0, + m02 : 0.0, + m10 : 0.0, + m11 : 1.0, + m12 : 0.0, + m20 : 0.0, + m21 : 0.0, + m22 : 1.0 + }; + if (spec) { + jQuery.extend(that, spec); + } + ; + that.concat = function(trafA) { + // add Transform trafA to this Transform (i.e. this = trafC = trafA * this) + var trafC = {}; + for ( var i = 0; i < 3; i++) { + for ( var j = 0; j < 3; j++) { + var c = 0.0; + for ( var k = 0; k < 3; k++) { + c += trafA["m" + i + k] * this["m" + k + j]; + } + trafC["m" + i + j] = c; + } + } + jQuery.extend(this, trafC); + return this; + }; + that.transform = function(rect) { + // returns transformed Rectangle or Position with this Transform + // applied + var x = this.m00 * rect.x + this.m01 * rect.y + this.m02; + var y = this.m10 * rect.x + this.m11 * rect.y + this.m12; + var pt = position(x, y); + if (rect.width != null) { + // transform the other corner point + var pt2 = this.transform(rect.getPt2()); + return rectangle(pt, pt2); + } + return pt; + }; + that.invtransform = function(rect) { + // returns transformed Rectangle or Position with the inverse of + // this Transform applied + var det = this.m00 * this.m11 - this.m01 * this.m10; + var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11 + * this.m02 + this.m01 * this.m12) + / det; + var y = (-this.m10 * rect.x + this.m00 * rect.y + this.m10 + * this.m02 - this.m00 * this.m12) + / det; + var pt = position(x, y); + if (rect.width != null) { + // transform the other corner point + var pt2 = this.invtransform(rect.getPt2()); + return rectangle(pt, pt2); + } + return pt; + }; + that.toString = function(pretty) { + var s = '['; + if (pretty) + s += '\n'; + for ( var i = 0; i < 3; ++i) { + s += '['; + for ( var j = 0; j < 3; ++j) { + if (j) + s += ','; + s += this['m' + i + j]; + } + s += ']'; + if (pretty) + s += '\n'; + } + s += ']'; + if (pretty) + s += '\n'; + return s; + }; + // add class methods to instance + that.getRotation = transform.getRotation; + that.getRotationAround = transform.getRotationAround; + that.getTranslation = transform.getTranslation; + that.getMirror = transform.getMirror; + that.getScale = transform.getScale; + + return that; + }; + + transform.getRotation = function(angle) { + // returns a Transform that is a rotation by angle degrees around [0,0] + if (angle !== 0) { + var t = Math.PI * parseFloat(angle) / 180.0; + var cost = Math.cos(t); + var sint = Math.sin(t); + var traf = { + m00 : cost, + m01 : -sint, + m10 : sint, + m11 : cost + }; + return transform(traf); + } + return transform(); + }; + + transform.getRotationAround = function(angle, pos) { + // returns a Transform that is a rotation by angle degrees around pos + var traf = transform.getTranslation(pos.neg()); + traf.concat(transform.getRotation(angle)); + traf.concat(transform.getTranslation(pos)); + return traf; + }; + + transform.getTranslation = function(pos) { + // returns a Transform that is a translation by [pos.x, pos,y] + var traf = { + m02 : pos.x, + m12 : pos.y + }; + return transform(traf); + }; + + transform.getMirror = function(type) { + // returns a Transform that is a mirror about the axis type + if (type === 'x') { + var traf = { + m00 : 1, + m11 : -1 + }; + } else { + var traf = { + m00 : -1, + m11 : 1 + }; + } + return transform(traf); + }; + + transform.getScale = function(size) { + // returns a Transform that is a scale by [size.width, size.height] + var traf = { + m00 : size.width, + m11 : size.height + }; + return transform(traf); + }; + + // export constructor functions to digilib plugin + var geometry = { + size : size, + position : position, + line : line, + 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 : {}, + }; + + // plug into digilib + if ($.fn.digicat == null) { + $.error("jquery.digicat.geometry must be loaded after jquery.digicat!"); + } else { + $.fn.digicat('plugin', plugin); + } +})(jQuery);
--- a/webapp/src/main/webapp/jquery/jquery.digicat.js Fri Feb 26 17:44:52 2016 +0100 +++ b/webapp/src/main/webapp/jquery/jquery.digicat.js Fri Feb 26 18:57:43 2016 +0100 @@ -50,17 +50,33 @@ 'scalerBaseUrl' : null, // prefix of digilib classes in CSS styles 'cssPrefix' : 'dl-', - // Scaler parameter defaults - 'pn' : 1, + // parameter defaults + 'pg' : 1, + 'rows' : 5, + 'cols' : 4, + // list of digicat parameters + 'digicatParamNames' : [ 'fn', 'pg', 'rows', 'cols' ], // list of additional parameters (for page outside of digilib) 'additionalParamNames' : [], // list of parameters to suppress when generating page URL 'suppressParamNames' : null, // list of Scaler parameters - 'scalerParamNames' : ['fn','pn','dw','dh','ww','wh','wx','wy','ws','mo', - 'rot','cont','brgt','rgbm','rgba','ddpi','ddpix','ddpiy','colop'], + 'scalerParamNames' : ['fn', 'pn', 'dw', 'dh', 'ww', 'wh', 'wx', 'wy', 'ws', 'mo', 'rot', 'cont', 'brgt', 'rgbm', 'rgba', + 'ddpi', 'ddpix', 'ddpiy', 'colop'], + // list of digilib parameters + 'digilibParamNames' : ['fn','pn','ww','wh','wx','wy','ws','mo','rot','cont','brgt','rgbm','rgba','ddpi','colop','mk','clop'], // reserved space in full page display (default value accounts for body margins) - 'pageInsets' : { 'x' : 26, 'y': 20 } + 'pageInsets' : { + 'x' : 26, + 'y' : 20 + }, + // reserved space for each image + 'imageInsets' : { + 'x' : 4, + 'y' : 20 + }, + // TODO: do we need this? + 'interactionMode' : 'fullscreen' }; // affine geometry plugin stub @@ -82,7 +98,7 @@ init : function(options) { // import geometry classes if (plugins.geometry == null) { - $.error("jquery.digilib.geometry plugin not found!"); + $.error("jquery.digicat.geometry plugin not found!"); } else { // geometry plugin puts classes in the shared fn geom = fn.geometry; @@ -95,7 +111,7 @@ queryParams = parseQueryParams(); // filter additional parameters for ( var p in queryParams) { - if ($.inArray(p, settings.digilibParamNames) < 0) { + if ($.inArray(p, settings.digicatParamNames) < 0) { settings.additionalParamNames.push(p); } } @@ -126,6 +142,10 @@ elemSettings = data.settings; } unpackParams(data); + // list of current insets (dynamic for buttons etc.) + data.currentInsets = { + 'static' : elemSettings.pageInsets + }; // check digilib base URL if (elemSettings.digilibBaseUrl == null) { // take current host @@ -168,7 +188,41 @@ // send setup event $(data).trigger('setup'); }); - } + }, + + /** + * goto given page nr (+/-: relative) + * + * @param data + * @param pageNr + * @returns {Boolean} + */ + gotoPage : function(data, pageNr) { + var settings = data.settings; + var oldpg = settings.pg; + if (pageNr == null) { + pageNr = window.prompt("Goto page number", oldpg); + } + var pg = setNumValue(settings, "pg", pageNr); + if (pg == null) + return false; // nothing happened + if (pg < 1) { + alert("no such page (page number too low)"); + settings.pg = oldpg; + return false; + } + // TODO: how do we get pt? + if (settings.pt != null) { + if (pg > settings.pt) { + alert("no such page (page number too high)"); + settings.pg = oldpg; + return false; + } + } + // then reload + redisplay(data); + }, + }; /** @@ -218,13 +272,14 @@ // retrieveOptions(data); }; - /** put objects back into parameters + /** + * put objects back into parameters * */ - var packParams = function (data) { + var packParams = function(data) { var settings = data.settings; // store user interface options in cookie - //storeOptions(data); + // storeOptions(data); // trigger pack handlers $(data).trigger('pack'); }; @@ -254,12 +309,12 @@ return geom.size(imgW, imgH); }; - /** - * return a query string from key names from a parameter hash - * (ignores keys if the same value is in defaults) + /** + * return a query string from key names from a parameter hash (ignores keys + * if the same value is in defaults) * */ - var getParamString = function (settings, keys, defaults) { + var getParamString = function(settings, keys, defaults) { var paramString = ''; var nx = false; for (var i = 0; i < keys.length; ++i) { @@ -279,21 +334,103 @@ }; /** + * returns URL and query string for current digicat. + * if digilibPage != null returns URL to page in digilib installation with digilib parameters, + * otherwise using current URL and parameters. + * + */ + var getDigicatUrl = function (data, digilibPage) { + packParams(data); + var settings = data.settings; + var paramList = settings.digicatParamNames; + if (digilibPage != null) { + var baseUrl = data.settings.digilibBaseUrl + digilibPage; + } else { + paramList = settings.additionalParamNames.concat(settings.digicatParamNames); + if (settings.suppressParamNames != null) { + // eliminate suppressed parameters from list + paramList = $.map(paramList, function(e, idx) { + if ($.inArray(e, settings.suppressParamNames) >= 0) { + return null; + } else { + return e; + } + }); + } + // take url from current location + var baseUrl = window.location.href; + var pos = baseUrl.indexOf('?'); + if (pos > -1) { + baseUrl = baseUrl.substring(0, pos); + } + } + var queryString = getParamString(settings, paramList, defaults); + return baseUrl + '?' + queryString; + }; + + /** + * returns URL and query string for current digilib. + * if digilibPage != null returns URL to page in digilib installation with digilib parameters, + * otherwise using current URL and parameters. + * + */ + var getDigilibUrl = function (data, digilibPage) { + packParams(data); + var settings = data.settings; + var paramList = settings.digilibParamNames; + if (digilibPage != null) { + var baseUrl = data.settings.digilibBaseUrl + digilibPage; + } else { + paramList = settings.additionalParamNames.concat(settings.digilibParamNames); + if (settings.suppressParamNames != null) { + // eliminate suppressed parameters from list + paramList = $.map(paramList, function(e, idx) { + if ($.inArray(e, settings.suppressParamNames) >= 0) { + return null; + } else { + return e; + } + }); + } + // take url from current location + var baseUrl = window.location.href; + var pos = baseUrl.indexOf('?'); + if (pos > -1) { + baseUrl = baseUrl.substring(0, pos); + } + } + var queryString = getParamString(settings, paramList, defaults); + return baseUrl + '?' + queryString; + }; + + /** * returns URL and query string for Scaler */ - var getScalerUrl = function (data) { + var getScalerUrl = function(data) { packParams(data); var settings = data.settings; if (settings.scalerBaseUrl == null) { alert("ERROR: URL of digilib Scaler servlet missing!"); - } + } var keys = settings.scalerParamNames; var queryString = getParamString(settings, keys, defaults); var url = settings.scalerBaseUrl + '?' + queryString; return url; }; - var handleScalerImgError = function (data, evt, a, b) { + /** + * (re)load the page with the current settings. + * + */ + var redisplay = function(data) { + var settings = data.settings; + // update location.href (browser URL) in fullscreen mode + var url = getDigicatUrl(data); + // reload window + window.location = url; + }; + + var handleScalerImgError = function(data, evt, a, b) { console.error("error loading scaler image:", evt); $(data).trigger('imgerror'); }; @@ -307,29 +444,39 @@ var cssPrefix = settings.cssPrefix; $elem.addClass(cssPrefix + 'digicat'); var scalerUrl; - var rows = 4; - var cols = 5; - var pn = 1; + var dlUrl; + var pg = settings.pg; + var rows = settings.rows; + var cols = settings.cols; + var pn = (pg - 1) * rows * cols + 1; var tblSize = getFullscreenImgSize(data); - tblSize.width -= settings.pageInsets.x; - tblSize.height -= settings.pageInsets.y; - settings.dw = Math.floor(tblSize.width / cols); - settings.dh = Math.floor(tblSize.height / rows); + var tdw = Math.floor(tblSize.width / cols); + var tdh = Math.floor(tblSize.height / rows); + settings.dw = tdw - settings.imageInsets.x; + settings.dh = tdh - settings.imageInsets.y; var $tbl = $('<table/>'); var $tr; var $td; + var $link; var $img; - for (var ridx=0; ridx < rows; ++ridx) { + for (var ridx = 0; ridx < rows; ++ridx) { $tr = $('<tr/>'); - for (var cidx=0; cidx < cols; ++cidx) { + for (var cidx = 0; cidx < cols; ++cidx) { $td = $('<td>'); + settings.pn = pn; + /* + * link + */ + dlUrl = getDigilibUrl(data, '/digilib.html'); + $link = $('<a href="'+dlUrl+'" target="_blank"/>'); /* * scaler image */ $img = $('<img/>'); - $img.addClass(cssPrefix+'pic'); - $img.on('error', function (evt, a, b) { handleScalerImgError(data, evt, a, b); }); - settings.pn = pn; + $img.addClass(cssPrefix + 'pic'); + $img.on('error', function(evt, a, b) { + handleScalerImgError(data, evt, a, b); + }); scalerUrl = getScalerUrl(data); $img.attr('src', scalerUrl); /* @@ -340,21 +487,56 @@ /* * assemble element */ - $td.append($img); - $td.append($cap); + $td.css('width', tdw + 'px'); + $td.css('height', tdh + 'px'); + $link.append($img); + $link.append($cap); + $td.append($link); $tr.append($td); pn += 1; } $tbl.append($tr); } - // create new inner html, keeping buttons and content marked with "keep" class - $elem.contents(':not(.'+cssPrefix+'keep)').remove(); + // create new inner html, keeping buttons and content marked with class "keep" + $elem.contents(':not(.' + cssPrefix + 'keep)').remove(); // scaler should be the first child element? $elem.prepend($tbl); data.$tbl = $tbl; }; /** + * sets a key to a value (relative values with +/- if relative=true). + * + */ + var setNumValue = function(settings, key, value) { + if (value == null) + return null; + if (isNumber(value)) { + settings[key] = value; + return value; + } + var sign = value[0]; + if (sign === '+' || sign === '-') { + if (settings[key] == null) { + // this isn't perfect but still... + settings[key] = 0; + } + settings[key] = parseFloat(settings[key]) + parseFloat(value); + } else { + settings[key] = value; + } + return settings[key]; + }; + + /** + * return if the argument is a number. from Douglas Crockford, A.10. this is + * different from $.isNumeric(). + */ + var isNumber = function(value) { + return typeof value === 'number' && isFinite(value); + }; + + /** * functions to export to plugins. */ fn = {
--- a/webapp/src/main/webapp/jquery/jquery.digilib.geometry.js Fri Feb 26 17:44:52 2016 +0100 +++ b/webapp/src/main/webapp/jquery/jquery.digilib.geometry.js Fri Feb 26 18:57:43 2016 +0100 @@ -804,12 +804,7 @@ // plug into digilib if ($.fn.digilib == null) { - if ($.fn.digicat == null) { - $.error("jquery.digilib.geometry must be loaded after jquery.digilib!"); - } else { - // plug into digicat (somewhat ugly) - $.fn.digicat('plugin', plugin); - } + $.error("jquery.digilib.geometry must be loaded after jquery.digilib!"); } else { $.fn.digilib('plugin', plugin); }