changeset 785:b9a75079aece jquery

geometry as first digilib plugin. special case that only exports classes.
author robcast
date Wed, 16 Feb 2011 14:31:50 +0100
parents dde58c15bbd2
children 868c2e795aca
files client/digitallibrary/jquery/jquery-test-embedded-rc.html client/digitallibrary/jquery/jquery-test-embedded.html client/digitallibrary/jquery/jquery-test-full-rc.html client/digitallibrary/jquery/jquery-test-full.html client/digitallibrary/jquery/jquery.digilib.geometry.js client/digitallibrary/jquery/jquery.digilib.js
diffstat 6 files changed, 514 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
         </style>
 
         <script type="text/javascript" src="jquery-1.4.4.js"></script>
-        <script type="text/javascript" src="dlGeometry.js"></script>
         <script type="text/javascript" src="jquery.cookie.js"></script>
         <script type="text/javascript" src="jquery.digilib.js"></script>
+        <script type="text/javascript" src="jquery.digilib.geometry.js"></script>
         <link rel="stylesheet" type="text/css" href="jquery.digilib.css" />
 
 
--- 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 @@
         </style>
 
         <script type="text/javascript" src="jquery-1.4.4.js"></script>
-        <script type="text/javascript" src="dlGeometry.js"></script>
         <script type="text/javascript" src="jquery.cookie.js"></script>
         <script type="text/javascript" src="jquery.digilib.js"></script>
+        <script type="text/javascript" src="jquery.digilib.geometry.js"></script>
         <link rel="stylesheet" type="text/css" href="jquery.digilib.css" />
 
 
--- 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 @@
         </style>
 
         <script type="text/javascript" src="jquery-1.4.4.js"></script>
-        <script type="text/javascript" src="dlGeometry.js"></script>
         <script type="text/javascript" src="jquery.cookie.js"></script>
         <script type="text/javascript" src="jquery.digilib.js"></script>
+        <script type="text/javascript" src="jquery.digilib.geometry.js"></script>
         <link rel="stylesheet" type="text/css" href="jquery.digilib.css" />
 
 
--- 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 @@
         </style>
 
         <script type="text/javascript" src="jquery-1.4.4.js"></script>
-        <script type="text/javascript" src="dlGeometry.js"></script>
         <script type="text/javascript" src="jquery.cookie.js"></script>
         <script type="text/javascript" src="jquery.digilib.js"></script>
+        <script type="text/javascript" src="jquery.digilib.geometry.js"></script>
         <link rel="stylesheet" type="text/css" href="jquery.digilib.css" />
 
 
--- /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);
--- 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