# HG changeset patch # User robcast # Date 1297863110 -3600 # Node ID b9a75079aece2bf48061b8b88b79b72b5e62f143 # Parent dde58c15bbd255fba3a8956582665d7f1178ea07 geometry as first digilib plugin. special case that only exports classes. diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery-test-embedded-rc.html --- a/client/digitallibrary/jquery/jquery-test-embedded-rc.html Tue Feb 15 11:02:31 2011 +0100 +++ b/client/digitallibrary/jquery/jquery-test-embedded-rc.html Wed Feb 16 14:31:50 2011 +0100 @@ -47,9 +47,9 @@ - + diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery-test-embedded.html --- a/client/digitallibrary/jquery/jquery-test-embedded.html Tue Feb 15 11:02:31 2011 +0100 +++ b/client/digitallibrary/jquery/jquery-test-embedded.html Wed Feb 16 14:31:50 2011 +0100 @@ -52,9 +52,9 @@ - + diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery-test-full-rc.html --- a/client/digitallibrary/jquery/jquery-test-full-rc.html Tue Feb 15 11:02:31 2011 +0100 +++ b/client/digitallibrary/jquery/jquery-test-full-rc.html Wed Feb 16 14:31:50 2011 +0100 @@ -12,9 +12,9 @@ - + diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery-test-full.html --- a/client/digitallibrary/jquery/jquery-test-full.html Tue Feb 15 11:02:31 2011 +0100 +++ b/client/digitallibrary/jquery/jquery-test-full.html Wed Feb 16 14:31:50 2011 +0100 @@ -56,9 +56,9 @@ - + diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery.digilib.geometry.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/digitallibrary/jquery/jquery.digilib.geometry.js Wed Feb 16 14:31:50 2011 +0100 @@ -0,0 +1,485 @@ +/** required digilib geometry plugin + */ + +(function($) { +//var dlGeometry = function() { + /* + * Size class + */ + var size = function(w, h) { + var that; + if (typeof w === "object") { + // assume its size + that = { + width : w.width, + height : w.height + }; + } else { + that = { + width : parseFloat(w), + height : parseFloat(h) + }; + } + that.equals = function(other) { + return (this.width === other.width && this.height === other.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 (x.x != null) { + // position object + that = { + x : x.x, + y : x.y + }; + } + if (x.pageX != null) { + // event object + that = { + x : x.pageX, + y : x.pageY + }; + } + } + } else { + that = { + x : parseFloat(x), + y : parseFloat(y) + }; + } + that.equals = function(other) { + return (this.x === other.x && this.y === other.y); + }; + // add position other to this + that.add = function(other) { + 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 + }); + }; + // adjusts position $elem to this position + that.adjustDiv = function($elem) { + $elem.offset({ + left : this.x, + top : this.y + }); + }; + // 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); + }; + that.toString = function() { + return (this.x + "," + this.y); + }; + 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 : x.x, + y : x.y, + width : x.width, + height : x.height + }; + } 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; + }; + that.setPt1 = that.setPosition; // TODO: not really the same + // adds pos to the position + that.addPosition = function(pos) { + this.x += pos.x; + this.y += 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; + }; + that.equals = function(other) { + // equal props + var eq = (this.x === other.x && this.y === other.y && this.width === other.width); + return eq; + }; + // returns the area of this Rectangle + that.getArea = 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 if rectangle "rect" is contained in this rectangle + that.containsRect = function(rect) { + return (this.containsPosition(rect.getPt1()) && this + .containsPosition(rect.getPt2())); + }; + // changes this rectangle's x/y values so it stays inside of rectangle + // rect + // keeping the proportions + that.stayInside = function(rect) { + if (this.x < rect.x) { + this.x = rect.x; + } + if (this.y < rect.y) { + 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 the given Rectangle and this one + that.intersect = function(rect) { + // FIX ME: not really, it should return null if there is no overlap + var sec = rect.copy(); + if (sec.x < this.x) { + sec.width = sec.width - (this.x - sec.x); + sec.x = this.x; + } + if (sec.y < this.y) { + sec.height = sec.height - (this.y - sec.y); + sec.y = this.y; + } + if (sec.x + sec.width > this.x + this.width) { + sec.width = (this.x + this.width) - sec.x; + } + if (sec.y + sec.height > this.y + this.height) { + sec.height = (this.y + this.height) - sec.y; + } + return sec; + }; + // returns a Rectangle that fits into this one (by moving first) + that.fit = function(rect) { + var sec = rect.copy(); + sec.x = Math.max(sec.x, this.x); + sec.y = Math.max(sec.y, this.x); + if (sec.x + sec.width > this.x + this.width) { + sec.x = this.x + this.width - sec.width; + } + if (sec.y + sec.height > this.y + this.height) { + sec.y = this.y + this.height - sec.height; + } + return sec.intersect(this); + }; + // adjusts position and size of $elem to this rectangle + that.adjustDiv = function($elem) { + $elem.offset({ + left : this.x, + top : this.y + }); + $elem.width(this.width).height(this.height); + }; + // returns size and position in css-compatible format + that.getAsCss = function() { + return { + left : this.x, + top : this.y, + width : this.width, + height : this.height + }; + }; + 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) { + // 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) { + // 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 functions to digilib plugin + $.fn.digilib.geometry = { + size : size, + position : position, + rectangle : rectangle, + transform : transform + }; + +})(jQuery); diff -r dde58c15bbd2 -r b9a75079aece client/digitallibrary/jquery/jquery.digilib.js --- a/client/digitallibrary/jquery/jquery.digilib.js Tue Feb 15 11:02:31 2011 +0100 +++ b/client/digitallibrary/jquery/jquery.digilib.js Wed Feb 16 14:31:50 2011 +0100 @@ -21,8 +21,6 @@ * digilib jQuery plugin **/ -/*requires dlGeometry.js */ - /*jslint browser: true, debug: true, forin: true */ @@ -250,17 +248,26 @@ // maximum width of background image for drag-scroll 'maxBgSize' : 10000, // space to be left free in full page display, default value is for scrollbar - 'scalerInset' : 10, + 'scalerInset' : 10 }; // affine geometry classes - var geom = dlGeometry(); + var geom; - var FULL_AREA = geom.rectangle(0, 0, 1, 1); + var FULL_AREA; var actions = { // init: digilib initialization init : function(options) { + // import geometry classes TODO: move to general plugin mechanism? + if ($.fn.digilib.geometry == null) { + console.error("You should use jquery.digilib.geometry"); + geom = dlGeometry(); + } else { + geom = $.fn.digilib.geometry; + } + FULL_AREA = geom.rectangle(0, 0, 1, 1); + // settings for this digilib instance are merged from defaults and options var settings = $.extend({}, defaults, options); var isFullscreen = settings.interactionMode === 'fullscreen'; @@ -292,22 +299,22 @@ params = queryParams; } else { params = parseImgParams($elem); - if (jQuery.cookie) { + if ($.cookie) { // retrieve params from cookie var ck = "digilib-embed:fn:" + escape(params.fn) + ":pn:" + (params.pn || '1'); - var cs = jQuery.cookie(ck); + var cs = $.cookie(ck); console.debug("get cookie=", ck, " value=", cs); if (cs) { var cp = parseQueryString(cs); // ignore fn and pn from cookie TODO: should we keep pn? delete cp.fn; delete cp.pn; - jQuery.extend(params, cp); + $.extend(params, cp); } } } // store $(this) element in the settings - elemSettings = jQuery.extend({}, settings, params); + elemSettings = $.extend({}, settings, params); data = { $elem : $elem, settings : elemSettings, @@ -702,7 +709,7 @@ dw : settings.birdDivWidth, dh : settings.birdDivHeight }; - var birdSettings = jQuery.extend({}, settings, birdDivOptions); + var birdSettings = $.extend({}, settings, birdDivOptions); // use only the relevant parameters if (moreParams == null) { var params = getParamString(birdSettings, settings.birdDivParams, defaults); @@ -740,7 +747,7 @@ var url = settings.scalerBaseUrl.substring(0, p) + '/ImgInfo-json.jsp'; url += '?' + getParamString(settings, ['fn', 'pn'], defaults); // TODO: better error handling - jQuery.getJSON(url, function (json) { + $.getJSON(url, function (json) { console.debug("got json data=", json); data.imgInfo = json; if (complete != null) { @@ -835,18 +842,18 @@ } clop += o + '=' + data.dlOpts[o]; } - if (jQuery.cookie) { + if ($.cookie) { var ck = "digilib:fn:" + escape(settings.fn) + ":pn:" + settings.pn; console.debug("set cookie=", ck, " value=", clop); - jQuery.cookie(ck, clop); + $.cookie(ck, clop); } } - if (settings.interactionMode !== 'fullscreen' && jQuery.cookie) { + if (settings.interactionMode !== 'fullscreen' && $.cookie) { // store normal parameters in cookie for embedded mode var qs = getParamString(settings, settings.digilibParamNames, defaults); var ck = "digilib-embed:fn:" + escape(settings.fn) + ":pn:" + settings.pn; console.debug("set cookie=", ck, " value=", qs); - jQuery.cookie(ck, qs); + $.cookie(ck, qs); } }; @@ -854,10 +861,10 @@ // clop (digilib options) var opts = {}; var settings = data.settings; - if (jQuery.cookie) { + if ($.cookie) { // read from cookie var ck = "digilib:fn:" + escape(settings.fn) + ":pn:" + settings.pn; - var cp = jQuery.cookie(ck); + var cp = $.cookie(ck); console.debug("get cookie=", ck, " value=", cp); // in query string format opts = parseQueryString(cp); @@ -1754,7 +1761,7 @@ } // hook plugin into jquery - $.fn.digilib = function(action) { + $.fn.digilib = function (action) { // plugin extension mechanism if (action === 'extendPlugin') { // for each digilib $elem extend data.settings with obj.options