# HG changeset patch
# User hertzhaft
# Date 1297027061 -3600
# Node ID ccf67eaf97ee44f0b65edd745f4837399aa1b6df
# Parent 4c0cc97a63993c69524c50e5d4b1fd1df63eed0a
added jQuery ui and svg javascripts
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/blank.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/blank.svg Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svg.compat-1.0.1.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svg.compat-1.0.1.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,69 @@
+/* http://keith-wood.name/svg.html
+ SVG for jQuery compatibility from v1.0.1 to v1.4.0.
+ Written by Keith Wood (kbwood{at}iinet.com.au) May 2008.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+var svgManager = null;
+var svgGraphing = null;
+
+(function($) { // Hide scope, no $ conflict
+
+svgManager = $.svg;
+svgGraphing = $.svg.graphing;
+$.svg._rootClass = $.svg._wrapperClass;
+
+$.extend($.svg, {
+ /* Retrieve the SVG wrapper for a given division.
+ @param input element - division to look for or
+ jQuery - jQuery collection containing the division or
+ string - jQuery selector for the division
+ @return SVGRoot - the associated SVG wrapper */
+ getSVGFor: function(input) {
+ input = (input.jquery ? input : $(input));
+ return $.svg._getSVG(input);
+ }
+});
+
+$.extend($.svg._rootClass.prototype, {
+ /* Draw a rounded rectangle.
+ @param parent element - the parent node for the new shape
+ @param x number - the x-coordinate for the left edge of the rectangle
+ @param y number - the y-coordinate for the top edge of the rectangle
+ @param width number - the width of the rectangle
+ @param height number - the height of the rectangle
+ @param rx number - the x-radius of the ellipse for the rounded corners
+ @param ry number - the y-radius of the ellipse for the rounded corners
+ @param settings object - additional settings for the shape (optional)
+ @return the new shape node */
+ roundrect: function(parent, x, y, width, height, rx, ry, settings) {
+ return this.rect(parent, x, y, width, height, rx, ry, settings);
+ },
+});
+
+/* Attach the SVG functionality to a jQuery selection.
+ @param loadURL string - the URL of the initial document to load (optional)
+ @param onLoad function - a callback functional invoked following loading (optional)
+ @param settings object - the new settings to use for this SVG instance (optional)
+ @return jQuery object - for chaining further calls */
+$.fn.svg = function(loadURL, onLoad, settings) {
+ if (typeof loadURL == 'function') {
+ settings = onLoad;
+ onLoad = loadURL;
+ loadURL = null;
+ }
+ if (loadURL && typeof loadURL == 'object') {
+ settings = loadURL;
+ loadURL = onLoad = null;
+ }
+ if (onLoad && typeof onLoad == 'object') {
+ settings = onLoad;
+ onLoad = null;
+ }
+ return this.each(function() {
+ $.svg._attachSVG(this, {loadURL: loadURL, onLoad: onLoad, settings: settings});
+ });
+};
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svg.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svg.css Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,15 @@
+/* http://keith-wood.name/svg.html
+ SVG for jQuery v1.4.2.
+ Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+svg\:svg {
+ display: none;
+}
+
+.svg_error {
+ color: red;
+ font-weight: bold;
+}
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svg.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svg.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,1339 @@
+/* http://keith-wood.name/svg.html
+ SVG for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+/* SVG manager.
+ Use the singleton instance of this class, $.svg,
+ to interact with the SVG functionality. */
+function SVGManager() {
+ this._settings = []; // Settings to be remembered per SVG object
+ this._extensions = []; // List of SVG extensions added to SVGWrapper
+ // for each entry [0] is extension name, [1] is extension class (function)
+ // the function takes one parameter - the SVGWrapper instance
+ this.regional = []; // Localisations, indexed by language, '' for default (English)
+ this.regional[''] = {errorLoadingText: 'Error loading',
+ notSupportedText: 'This browser does not support SVG'};
+ this.local = this.regional['']; // Current localisation
+ this._uuid = new Date().getTime();
+ this._renesis = detectActiveX('RenesisX.RenesisCtrl');
+}
+
+/* Determine whether a given ActiveX control is available.
+ @param classId (string) the ID for the ActiveX control
+ @return (boolean) true if found, false if not */
+function detectActiveX(classId) {
+ try {
+ return !!(window.ActiveXObject && new ActiveXObject(classId));
+ }
+ catch (e) {
+ return false;
+ }
+}
+
+var PROP_NAME = 'svgwrapper';
+
+$.extend(SVGManager.prototype, {
+ /* Class name added to elements to indicate already configured with SVG. */
+ markerClassName: 'hasSVG',
+
+ /* SVG namespace. */
+ svgNS: 'http://www.w3.org/2000/svg',
+ /* XLink namespace. */
+ xlinkNS: 'http://www.w3.org/1999/xlink',
+
+ /* SVG wrapper class. */
+ _wrapperClass: SVGWrapper,
+
+ /* Camel-case versions of attribute names containing dashes or are reserved words. */
+ _attrNames: {class_: 'class', in_: 'in',
+ alignmentBaseline: 'alignment-baseline', baselineShift: 'baseline-shift',
+ clipPath: 'clip-path', clipRule: 'clip-rule',
+ colorInterpolation: 'color-interpolation',
+ colorInterpolationFilters: 'color-interpolation-filters',
+ colorRendering: 'color-rendering', dominantBaseline: 'dominant-baseline',
+ enableBackground: 'enable-background', fillOpacity: 'fill-opacity',
+ fillRule: 'fill-rule', floodColor: 'flood-color',
+ floodOpacity: 'flood-opacity', fontFamily: 'font-family',
+ fontSize: 'font-size', fontSizeAdjust: 'font-size-adjust',
+ fontStretch: 'font-stretch', fontStyle: 'font-style',
+ fontVariant: 'font-variant', fontWeight: 'font-weight',
+ glyphOrientationHorizontal: 'glyph-orientation-horizontal',
+ glyphOrientationVertical: 'glyph-orientation-vertical',
+ horizAdvX: 'horiz-adv-x', horizOriginX: 'horiz-origin-x',
+ imageRendering: 'image-rendering', letterSpacing: 'letter-spacing',
+ lightingColor: 'lighting-color', markerEnd: 'marker-end',
+ markerMid: 'marker-mid', markerStart: 'marker-start',
+ stopColor: 'stop-color', stopOpacity: 'stop-opacity',
+ strikethroughPosition: 'strikethrough-position',
+ strikethroughThickness: 'strikethrough-thickness',
+ strokeDashArray: 'stroke-dasharray', strokeDashOffset: 'stroke-dashoffset',
+ strokeLineCap: 'stroke-linecap', strokeLineJoin: 'stroke-linejoin',
+ strokeMiterLimit: 'stroke-miterlimit', strokeOpacity: 'stroke-opacity',
+ strokeWidth: 'stroke-width', textAnchor: 'text-anchor',
+ textDecoration: 'text-decoration', textRendering: 'text-rendering',
+ underlinePosition: 'underline-position', underlineThickness: 'underline-thickness',
+ vertAdvY: 'vert-adv-y', vertOriginY: 'vert-origin-y',
+ wordSpacing: 'word-spacing', writingMode: 'writing-mode'},
+
+ /* Add the SVG object to its container. */
+ _attachSVG: function(container, settings) {
+ var svg = (container.namespaceURI == this.svgNS ? container : null);
+ var container = (svg ? null : container);
+ if ($(container || svg).hasClass(this.markerClassName)) {
+ return;
+ }
+ if (typeof settings == 'string') {
+ settings = {loadURL: settings};
+ }
+ else if (typeof settings == 'function') {
+ settings = {onLoad: settings};
+ }
+ $(container || svg).addClass(this.markerClassName);
+ try {
+ if (!svg) {
+ svg = document.createElementNS(this.svgNS, 'svg');
+ svg.setAttribute('version', '1.1');
+ svg.setAttribute('width', container.clientWidth);
+ svg.setAttribute('height', container.clientHeight);
+ container.appendChild(svg);
+ }
+ this._afterLoad(container, svg, settings || {});
+ }
+ catch (e) {
+ if ($.browser.msie) {
+ if (!container.id) {
+ container.id = 'svg' + (this._uuid++);
+ }
+ this._settings[container.id] = settings;
+ container.innerHTML = ' ';
+ }
+ else {
+ container.innerHTML = '
' +
+ this.local.notSupportedText + '
';
+ }
+ }
+ },
+
+ /* SVG callback after loading - register SVG root. */
+ _registerSVG: function() {
+ for (var i = 0; i < document.embeds.length; i++) { // Check all
+ var container = document.embeds[i].parentNode;
+ if (!$(container).hasClass($.svg.markerClassName) || // Not SVG
+ $.data(container, PROP_NAME)) { // Already done
+ continue;
+ }
+ var svg = null;
+ try {
+ svg = document.embeds[i].getSVGDocument();
+ }
+ catch(e) {
+ setTimeout($.svg._registerSVG, 250); // Renesis takes longer to load
+ return;
+ }
+ svg = (svg ? svg.documentElement : null);
+ if (svg) {
+ $.svg._afterLoad(container, svg);
+ }
+ }
+ },
+
+ /* Post-processing once loaded. */
+ _afterLoad: function(container, svg, settings) {
+ var settings = settings || this._settings[container.id];
+ this._settings[container ? container.id : ''] = null;
+ var wrapper = new this._wrapperClass(svg, container);
+ $.data(container || svg, PROP_NAME, wrapper);
+ try {
+ if (settings.loadURL) { // Load URL
+ wrapper.load(settings.loadURL, settings);
+ }
+ if (settings.settings) { // Additional settings
+ wrapper.configure(settings.settings);
+ }
+ if (settings.onLoad && !settings.loadURL) { // Onload callback
+ settings.onLoad.apply(container || svg, [wrapper]);
+ }
+ }
+ catch (e) {
+ alert(e);
+ }
+ },
+
+ /* Return the SVG wrapper created for a given container.
+ @param container (string) selector for the container or
+ (element) the container for the SVG object or
+ jQuery collection - first entry is the container
+ @return (SVGWrapper) the corresponding SVG wrapper element, or null if not attached */
+ _getSVG: function(container) {
+ container = (typeof container == 'string' ? $(container)[0] :
+ (container.jquery ? container[0] : container));
+ return $.data(container, PROP_NAME);
+ },
+
+ /* Remove the SVG functionality from a div.
+ @param container (element) the container for the SVG object */
+ _destroySVG: function(container) {
+ var $container = $(container);
+ if (!$container.hasClass(this.markerClassName)) {
+ return;
+ }
+ $container.removeClass(this.markerClassName);
+ if (container.namespaceURI != this.svgNS) {
+ $container.empty();
+ }
+ $.removeData(container, PROP_NAME);
+ },
+
+ /* Extend the SVGWrapper object with an embedded class.
+ The constructor function must take a single parameter that is
+ a reference to the owning SVG root object. This allows the
+ extension to access the basic SVG functionality.
+ @param name (string) the name of the SVGWrapper attribute to access the new class
+ @param extClass (function) the extension class constructor */
+ addExtension: function(name, extClass) {
+ this._extensions.push([name, extClass]);
+ }
+});
+
+/* The main SVG interface, which encapsulates the SVG element.
+ Obtain a reference from $().svg('get') */
+function SVGWrapper(svg, container) {
+ this._svg = svg; // The SVG root node
+ this._container = container; // The containing div
+ for (var i = 0; i < $.svg._extensions.length; i++) {
+ var extension = $.svg._extensions[i];
+ this[extension[0]] = new extension[1](this);
+ }
+}
+
+$.extend(SVGWrapper.prototype, {
+
+ /* Retrieve the width of the SVG object. */
+ _width: function() {
+ return (this._container ? this._container.clientWidth : this._svg.width);
+ },
+
+ /* Retrieve the height of the SVG object. */
+ _height: function() {
+ return (this._container ? this._container.clientHeight : this._svg.height);
+ },
+
+ /* Retrieve the root SVG element.
+ @return the top-level SVG element */
+ root: function() {
+ return this._svg;
+ },
+
+ /* Configure the SVG root.
+ @param settings (object) additional settings for the root
+ @param clear (boolean) true to remove existing attributes first,
+ false to add to what is already there (optional)
+ @return (SVGWrapper) this root */
+ configure: function(settings, clear) {
+ if (clear) {
+ for (var i = this._svg.attributes.length - 1; i >= 0; i--) {
+ var attr = this._svg.attributes.item(i);
+ if (!(attr.nodeName == 'onload' || attr.nodeName == 'version' ||
+ attr.nodeName.substring(0, 5) == 'xmlns')) {
+ this._svg.attributes.removeNamedItem(attr.nodeName);
+ }
+ }
+ }
+ for (var attrName in settings) {
+ this._svg.setAttribute(attrName, settings[attrName]);
+ }
+ return this;
+ },
+
+ /* Locate a specific element in the SVG document.
+ @param id (string) the element's identifier
+ @return (element) the element reference, or null if not found */
+ getElementById: function(id) {
+ return this._svg.ownerDocument.getElementById(id);
+ },
+
+ /* Change the attributes for a SVG node.
+ @param element (SVG element) the node to change
+ @param settings (object) the new settings
+ @return (SVGWrapper) this root */
+ change: function(element, settings) {
+ if (element) {
+ for (var name in settings) {
+ if (settings[name] == null) {
+ element.removeAttribute(name);
+ }
+ else {
+ element.setAttribute(name, settings[name]);
+ }
+ }
+ }
+ return this;
+ },
+
+ /* Check for parent being absent and adjust arguments accordingly. */
+ _args: function(values, names, optSettings) {
+ names.splice(0, 0, 'parent');
+ names.splice(names.length, 0, 'settings');
+ var args = {};
+ var offset = 0;
+ if (values[0] != null && values[0].jquery) {
+ values[0] = values[0][0];
+ }
+ if (values[0] != null && !(typeof values[0] == 'object' && values[0].nodeName)) {
+ args['parent'] = null;
+ offset = 1;
+ }
+ for (var i = 0; i < values.length; i++) {
+ args[names[i + offset]] = values[i];
+ }
+ if (optSettings) {
+ $.each(optSettings, function(i, value) {
+ if (typeof args[value] == 'object') {
+ args.settings = args[value];
+ args[value] = null;
+ }
+ });
+ }
+ return args;
+ },
+
+ /* Add a title.
+ @param parent (element or jQuery) the parent node for the new title (optional)
+ @param text (string) the text of the title
+ @param settings (object) additional settings for the title (optional)
+ @return (element) the new title node */
+ title: function(parent, text, settings) {
+ var args = this._args(arguments, ['text']);
+ var node = this._makeNode(args.parent, 'title', args.settings || {});
+ node.appendChild(this._svg.ownerDocument.createTextNode(args.text));
+ return node;
+ },
+
+ /* Add a description.
+ @param parent (element or jQuery) the parent node for the new description (optional)
+ @param text (string) the text of the description
+ @param settings (object) additional settings for the description (optional)
+ @return (element) the new description node */
+ describe: function(parent, text, settings) {
+ var args = this._args(arguments, ['text']);
+ var node = this._makeNode(args.parent, 'desc', args.settings || {});
+ node.appendChild(this._svg.ownerDocument.createTextNode(args.text));
+ return node;
+ },
+
+ /* Add a definitions node.
+ @param parent (element or jQuery) the parent node for the new definitions (optional)
+ @param id (string) the ID of this definitions (optional)
+ @param settings (object) additional settings for the definitions (optional)
+ @return (element) the new definitions node */
+ defs: function(parent, id, settings) {
+ var args = this._args(arguments, ['id'], ['id']);
+ return this._makeNode(args.parent, 'defs', $.extend(
+ (args.id ? {id: args.id} : {}), args.settings || {}));
+ },
+
+ /* Add a symbol definition.
+ @param parent (element or jQuery) the parent node for the new symbol (optional)
+ @param id (string) the ID of this symbol
+ @param x1 (number) the left coordinate for this symbol
+ @param y1 (number) the top coordinate for this symbol
+ @param width (number) the width of this symbol
+ @param height (number) the height of this symbol
+ @param settings (object) additional settings for the symbol (optional)
+ @return (element) the new symbol node */
+ symbol: function(parent, id, x1, y1, width, height, settings) {
+ var args = this._args(arguments, ['id', 'x1', 'y1', 'width', 'height']);
+ return this._makeNode(args.parent, 'symbol', $.extend({id: args.id,
+ viewBox: args.x1 + ' ' + args.y1 + ' ' + args.width + ' ' + args.height},
+ args.settings || {}));
+ },
+
+ /* Add a marker definition.
+ @param parent (element or jQuery) the parent node for the new marker (optional)
+ @param id (string) the ID of this marker
+ @param refX (number) the x-coordinate for the reference point
+ @param refY (number) the y-coordinate for the reference point
+ @param mWidth (number) the marker viewport width
+ @param mHeight (number) the marker viewport height
+ @param orient (string or int) 'auto' or angle (degrees) (optional)
+ @param settings (object) additional settings for the marker (optional)
+ @return (element) the new marker node */
+ marker: function(parent, id, refX, refY, mWidth, mHeight, orient, settings) {
+ var args = this._args(arguments, ['id', 'refX', 'refY',
+ 'mWidth', 'mHeight', 'orient'], ['orient']);
+ return this._makeNode(args.parent, 'marker', $.extend(
+ {id: args.id, refX: args.refX, refY: args.refY, markerWidth: args.mWidth,
+ markerHeight: args.mHeight, orient: args.orient || 'auto'}, args.settings || {}));
+ },
+
+ /* Add a style node.
+ @param parent (element or jQuery) the parent node for the new node (optional)
+ @param styles (string) the CSS styles
+ @param settings (object) additional settings for the node (optional)
+ @return (element) the new style node */
+ style: function(parent, styles, settings) {
+ var args = this._args(arguments, ['styles']);
+ var node = this._makeNode(args.parent, 'style', $.extend(
+ {type: 'text/css'}, args.settings || {}));
+ node.appendChild(this._svg.ownerDocument.createTextNode(args.styles));
+ if ($.browser.opera) {
+ $('head').append('');
+ }
+ return node;
+ },
+
+ /* Add a script node.
+ @param parent (element or jQuery) the parent node for the new node (optional)
+ @param script (string) the JavaScript code
+ @param type (string) the MIME type for the code (optional, default 'text/javascript')
+ @param settings (object) additional settings for the node (optional)
+ @return (element) the new script node */
+ script: function(parent, script, type, settings) {
+ var args = this._args(arguments, ['script', 'type'], ['type']);
+ var node = this._makeNode(args.parent, 'script', $.extend(
+ {type: args.type || 'text/javascript'}, args.settings || {}));
+ node.appendChild(this._svg.ownerDocument.createTextNode(this._escapeXML(args.script)));
+ if (!$.browser.mozilla) {
+ $.globalEval(args.script);
+ }
+ return node;
+ },
+
+ /* Add a linear gradient definition.
+ Specify all of x1, y1, x2, y2 or none of them.
+ @param parent (element or jQuery) the parent node for the new gradient (optional)
+ @param id (string) the ID for this gradient
+ @param stops (string[][]) the gradient stops, each entry is
+ [0] is offset (0.0-1.0 or 0%-100%), [1] is colour,
+ [2] is opacity (optional)
+ @param x1 (number) the x-coordinate of the gradient start (optional)
+ @param y1 (number) the y-coordinate of the gradient start (optional)
+ @param x2 (number) the x-coordinate of the gradient end (optional)
+ @param y2 (number) the y-coordinate of the gradient end (optional)
+ @param settings (object) additional settings for the gradient (optional)
+ @return (element) the new gradient node */
+ linearGradient: function(parent, id, stops, x1, y1, x2, y2, settings) {
+ var args = this._args(arguments,
+ ['id', 'stops', 'x1', 'y1', 'x2', 'y2'], ['x1']);
+ var sets = $.extend({id: args.id},
+ (args.x1 != null ? {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2} : {}));
+ return this._gradient(args.parent, 'linearGradient',
+ $.extend(sets, args.settings || {}), args.stops);
+ },
+
+ /* Add a radial gradient definition.
+ Specify all of cx, cy, r, fx, fy or none of them.
+ @param parent (element or jQuery) the parent node for the new gradient (optional)
+ @param id (string) the ID for this gradient
+ @param stops (string[][]) the gradient stops, each entry
+ [0] is offset, [1] is colour, [2] is opacity (optional)
+ @param cx (number) the x-coordinate of the largest circle centre (optional)
+ @param cy (number) the y-coordinate of the largest circle centre (optional)
+ @param r (number) the radius of the largest circle (optional)
+ @param fx (number) the x-coordinate of the gradient focus (optional)
+ @param fy (number) the y-coordinate of the gradient focus (optional)
+ @param settings (object) additional settings for the gradient (optional)
+ @return (element) the new gradient node */
+ radialGradient: function(parent, id, stops, cx, cy, r, fx, fy, settings) {
+ var args = this._args(arguments,
+ ['id', 'stops', 'cx', 'cy', 'r', 'fx', 'fy'], ['cx']);
+ var sets = $.extend({id: args.id}, (args.cx != null ?
+ {cx: args.cx, cy: args.cy, r: args.r, fx: args.fx, fy: args.fy} : {}));
+ return this._gradient(args.parent, 'radialGradient',
+ $.extend(sets, args.settings || {}), args.stops);
+ },
+
+ /* Add a gradient node. */
+ _gradient: function(parent, name, settings, stops) {
+ var node = this._makeNode(parent, name, settings);
+ for (var i = 0; i < stops.length; i++) {
+ var stop = stops[i];
+ this._makeNode(node, 'stop', $.extend(
+ {offset: stop[0], stopColor: stop[1]},
+ (stop[2] != null ? {stopOpacity: stop[2]} : {})));
+ }
+ return node;
+ },
+
+ /* Add a pattern definition.
+ Specify all of vx, vy, xwidth, vheight or none of them.
+ @param parent (element or jQuery) the parent node for the new pattern (optional)
+ @param id (string) the ID for this pattern
+ @param x (number) the x-coordinate for the left edge of the pattern
+ @param y (number) the y-coordinate for the top edge of the pattern
+ @param width (number) the width of the pattern
+ @param height (number) the height of the pattern
+ @param vx (number) the minimum x-coordinate for view box (optional)
+ @param vy (number) the minimum y-coordinate for the view box (optional)
+ @param vwidth (number) the width of the view box (optional)
+ @param vheight (number) the height of the view box (optional)
+ @param settings (object) additional settings for the pattern (optional)
+ @return (element) the new pattern node */
+ pattern: function(parent, id, x, y, width, height, vx, vy, vwidth, vheight, settings) {
+ var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height',
+ 'vx', 'vy', 'vwidth', 'vheight'], ['vx']);
+ var sets = $.extend({id: args.id, x: args.x, y: args.y,
+ width: args.width, height: args.height}, (args.vx != null ?
+ {viewBox: args.vx + ' ' + args.vy + ' ' + args.vwidth + ' ' + args.vheight} : {}));
+ return this._makeNode(args.parent, 'pattern', $.extend(sets, args.settings || {}));
+ },
+
+ /* Add a mask definition.
+ @param parent (element or jQuery) the parent node for the new mask (optional)
+ @param id (string) the ID for this mask
+ @param x (number) the x-coordinate for the left edge of the mask
+ @param y (number) the y-coordinate for the top edge of the mask
+ @param width (number) the width of the mask
+ @param height (number) the height of the mask
+ @param settings (object) additional settings for the mask (optional)
+ @return (element) the new mask node */
+ mask: function(parent, id, x, y, width, height, settings) {
+ var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height']);
+ return this._makeNode(args.parent, 'mask', $.extend(
+ {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height},
+ args.settings || {}));
+ },
+
+ /* Create a new path object.
+ @return (SVGPath) a new path object */
+ createPath: function() {
+ return new SVGPath();
+ },
+
+ /* Create a new text object.
+ @return (SVGText) a new text object */
+ createText: function() {
+ return new SVGText();
+ },
+
+ /* Add an embedded SVG element.
+ Specify all of vx, vy, vwidth, vheight or none of them.
+ @param parent (element or jQuery) the parent node for the new node (optional)
+ @param x (number) the x-coordinate for the left edge of the node
+ @param y (number) the y-coordinate for the top edge of the node
+ @param width (number) the width of the node
+ @param height (number) the height of the node
+ @param vx (number) the minimum x-coordinate for view box (optional)
+ @param vy (number) the minimum y-coordinate for the view box (optional)
+ @param vwidth (number) the width of the view box (optional)
+ @param vheight (number) the height of the view box (optional)
+ @param settings (object) additional settings for the node (optional)
+ @return (element) the new node */
+ svg: function(parent, x, y, width, height, vx, vy, vwidth, vheight, settings) {
+ var args = this._args(arguments, ['x', 'y', 'width', 'height',
+ 'vx', 'vy', 'vwidth', 'vheight'], ['vx']);
+ var sets = $.extend({x: args.x, y: args.y, width: args.width, height: args.height},
+ (args.vx != null ? {viewBox: args.vx + ' ' + args.vy + ' ' +
+ args.vwidth + ' ' + args.vheight} : {}));
+ return this._makeNode(args.parent, 'svg', $.extend(sets, args.settings || {}));
+ },
+
+ /* Create a group.
+ @param parent (element or jQuery) the parent node for the new group (optional)
+ @param id (string) the ID of this group (optional)
+ @param settings (object) additional settings for the group (optional)
+ @return (element) the new group node */
+ group: function(parent, id, settings) {
+ var args = this._args(arguments, ['id'], ['id']);
+ return this._makeNode(args.parent, 'g', $.extend({id: args.id}, args.settings || {}));
+ },
+
+ /* Add a usage reference.
+ Specify all of x, y, width, height or none of them.
+ @param parent (element or jQuery) the parent node for the new node (optional)
+ @param x (number) the x-coordinate for the left edge of the node (optional)
+ @param y (number) the y-coordinate for the top edge of the node (optional)
+ @param width (number) the width of the node (optional)
+ @param height (number) the height of the node (optional)
+ @param ref (string) the ID of the definition node
+ @param settings (object) additional settings for the node (optional)
+ @return (element) the new node */
+ use: function(parent, x, y, width, height, ref, settings) {
+ var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']);
+ if (typeof args.x == 'string') {
+ args.ref = args.x;
+ args.settings = args.y;
+ args.x = args.y = args.width = args.height = null;
+ }
+ var node = this._makeNode(args.parent, 'use', $.extend(
+ {x: args.x, y: args.y, width: args.width, height: args.height},
+ args.settings || {}));
+ node.setAttributeNS($.svg.xlinkNS, 'href', args.ref);
+ return node;
+ },
+
+ /* Add a link, which applies to all child elements.
+ @param parent (element or jQuery) the parent node for the new link (optional)
+ @param ref (string) the target URL
+ @param settings (object) additional settings for the link (optional)
+ @return (element) the new link node */
+ link: function(parent, ref, settings) {
+ var args = this._args(arguments, ['ref']);
+ var node = this._makeNode(args.parent, 'a', args.settings);
+ node.setAttributeNS($.svg.xlinkNS, 'href', args.ref);
+ return node;
+ },
+
+ /* Add an image.
+ @param parent (element or jQuery) the parent node for the new image (optional)
+ @param x (number) the x-coordinate for the left edge of the image
+ @param y (number) the y-coordinate for the top edge of the image
+ @param width (number) the width of the image
+ @param height (number) the height of the image
+ @param ref (string) the path to the image
+ @param settings (object) additional settings for the image (optional)
+ @return (element) the new image node */
+ image: function(parent, x, y, width, height, ref, settings) {
+ var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']);
+ var node = this._makeNode(args.parent, 'image', $.extend(
+ {x: args.x, y: args.y, width: args.width, height: args.height},
+ args.settings || {}));
+ node.setAttributeNS($.svg.xlinkNS, 'href', args.ref);
+ return node;
+ },
+
+ /* Draw a path.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param path (string or SVGPath) the path to draw
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ path: function(parent, path, settings) {
+ var args = this._args(arguments, ['path']);
+ return this._makeNode(args.parent, 'path', $.extend(
+ {d: (args.path.path ? args.path.path() : args.path)}, args.settings || {}));
+ },
+
+ /* Draw a rectangle.
+ Specify both of rx and ry or neither.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param x (number) the x-coordinate for the left edge of the rectangle
+ @param y (number) the y-coordinate for the top edge of the rectangle
+ @param width (number) the width of the rectangle
+ @param height (number) the height of the rectangle
+ @param rx (number) the x-radius of the ellipse for the rounded corners (optional)
+ @param ry (number) the y-radius of the ellipse for the rounded corners (optional)
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ rect: function(parent, x, y, width, height, rx, ry, settings) {
+ var args = this._args(arguments, ['x', 'y', 'width', 'height', 'rx', 'ry'], ['rx']);
+ return this._makeNode(args.parent, 'rect', $.extend(
+ {x: args.x, y: args.y, width: args.width, height: args.height},
+ (args.rx ? {rx: args.rx, ry: args.ry} : {}), args.settings || {}));
+ },
+
+ /* Draw a circle.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param cx (number) the x-coordinate for the centre of the circle
+ @param cy (number) the y-coordinate for the centre of the circle
+ @param r (number) the radius of the circle
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ circle: function(parent, cx, cy, r, settings) {
+ var args = this._args(arguments, ['cx', 'cy', 'r']);
+ return this._makeNode(args.parent, 'circle', $.extend(
+ {cx: args.cx, cy: args.cy, r: args.r}, args.settings || {}));
+ },
+
+ /* Draw an ellipse.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param cx (number) the x-coordinate for the centre of the ellipse
+ @param cy (number) the y-coordinate for the centre of the ellipse
+ @param rx (number) the x-radius of the ellipse
+ @param ry (number) the y-radius of the ellipse
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ ellipse: function(parent, cx, cy, rx, ry, settings) {
+ var args = this._args(arguments, ['cx', 'cy', 'rx', 'ry']);
+ return this._makeNode(args.parent, 'ellipse', $.extend(
+ {cx: args.cx, cy: args.cy, rx: args.rx, ry: args.ry}, args.settings || {}));
+ },
+
+ /* Draw a line.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param x1 (number) the x-coordinate for the start of the line
+ @param y1 (number) the y-coordinate for the start of the line
+ @param x2 (number) the x-coordinate for the end of the line
+ @param y2 (number) the y-coordinate for the end of the line
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ line: function(parent, x1, y1, x2, y2, settings) {
+ var args = this._args(arguments, ['x1', 'y1', 'x2', 'y2']);
+ return this._makeNode(args.parent, 'line', $.extend(
+ {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2}, args.settings || {}));
+ },
+
+ /* Draw a polygonal line.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param points (number[][]) the x-/y-coordinates for the points on the line
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ polyline: function(parent, points, settings) {
+ var args = this._args(arguments, ['points']);
+ return this._poly(args.parent, 'polyline', args.points, args.settings);
+ },
+
+ /* Draw a polygonal shape.
+ @param parent (element or jQuery) the parent node for the new shape (optional)
+ @param points (number[][]) the x-/y-coordinates for the points on the shape
+ @param settings (object) additional settings for the shape (optional)
+ @return (element) the new shape node */
+ polygon: function(parent, points, settings) {
+ var args = this._args(arguments, ['points']);
+ return this._poly(args.parent, 'polygon', args.points, args.settings);
+ },
+
+ /* Draw a polygonal line or shape. */
+ _poly: function(parent, name, points, settings) {
+ var ps = '';
+ for (var i = 0; i < points.length; i++) {
+ ps += points[i].join() + ' ';
+ }
+ return this._makeNode(parent, name, $.extend(
+ {points: $.trim(ps)}, settings || {}));
+ },
+
+ /* Draw text.
+ Specify both of x and y or neither of them.
+ @param parent (element or jQuery) the parent node for the text (optional)
+ @param x (number or number[]) the x-coordinate(s) for the text (optional)
+ @param y (number or number[]) the y-coordinate(s) for the text (optional)
+ @param value (string) the text content or
+ (SVGText) text with spans and references
+ @param settings (object) additional settings for the text (optional)
+ @return (element) the new text node */
+ text: function(parent, x, y, value, settings) {
+ var args = this._args(arguments, ['x', 'y', 'value']);
+ if (typeof args.x == 'string' && arguments.length < 4) {
+ args.value = args.x;
+ args.settings = args.y;
+ args.x = args.y = null;
+ }
+ return this._text(args.parent, 'text', args.value, $.extend(
+ {x: (args.x && isArray(args.x) ? args.x.join(' ') : args.x),
+ y: (args.y && isArray(args.y) ? args.y.join(' ') : args.y)},
+ args.settings || {}));
+ },
+
+ /* Draw text along a path.
+ @param parent (element or jQuery) the parent node for the text (optional)
+ @param path (string) the ID of the path
+ @param value (string) the text content or
+ (SVGText) text with spans and references
+ @param settings (object) additional settings for the text (optional)
+ @return (element) the new text node */
+ textpath: function(parent, path, value, settings) {
+ var args = this._args(arguments, ['path', 'value']);
+ var node = this._text(args.parent, 'textPath', args.value, args.settings || {});
+ node.setAttributeNS($.svg.xlinkNS, 'href', args.path);
+ return node;
+ },
+
+ /* Draw text. */
+ _text: function(parent, name, value, settings) {
+ var node = this._makeNode(parent, name, settings);
+ if (typeof value == 'string') {
+ node.appendChild(node.ownerDocument.createTextNode(value));
+ }
+ else {
+ for (var i = 0; i < value._parts.length; i++) {
+ var part = value._parts[i];
+ if (part[0] == 'tspan') {
+ var child = this._makeNode(node, part[0], part[2]);
+ child.appendChild(node.ownerDocument.createTextNode(part[1]));
+ node.appendChild(child);
+ }
+ else if (part[0] == 'tref') {
+ var child = this._makeNode(node, part[0], part[2]);
+ child.setAttributeNS($.svg.xlinkNS, 'href', part[1]);
+ node.appendChild(child);
+ }
+ else if (part[0] == 'textpath') {
+ var set = $.extend({}, part[2]);
+ set.href = null;
+ var child = this._makeNode(node, part[0], set);
+ child.setAttributeNS($.svg.xlinkNS, 'href', part[2].href);
+ child.appendChild(node.ownerDocument.createTextNode(part[1]));
+ node.appendChild(child);
+ }
+ else { // straight text
+ node.appendChild(node.ownerDocument.createTextNode(part[1]));
+ }
+ }
+ }
+ return node;
+ },
+
+ /* Add a custom SVG element.
+ @param parent (element or jQuery) the parent node for the new element (optional)
+ @param name (string) the name of the element
+ @param settings (object) additional settings for the element (optional)
+ @return (element) the new custom node */
+ other: function(parent, name, settings) {
+ var args = this._args(arguments, ['name']);
+ return this._makeNode(args.parent, args.name, args.settings || {});
+ },
+
+ /* Create a shape node with the given settings. */
+ _makeNode: function(parent, name, settings) {
+ parent = parent || this._svg;
+ var node = this._svg.ownerDocument.createElementNS($.svg.svgNS, name);
+ for (var name in settings) {
+ var value = settings[name];
+ if (value != null && value != null &&
+ (typeof value != 'string' || value != '')) {
+ node.setAttribute($.svg._attrNames[name] || name, value);
+ }
+ }
+ parent.appendChild(node);
+ return node;
+ },
+
+ /* Add an existing SVG node to the diagram.
+ @param parent (element or jQuery) the parent node for the new node (optional)
+ @param node (element) the new node to add or
+ (string) the jQuery selector for the node or
+ (jQuery collection) set of nodes to add
+ @return (SVGWrapper) this wrapper */
+ add: function(parent, node) {
+ var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']);
+ var svg = this;
+ args.parent = args.parent || this._svg;
+ try {
+ if ($.svg._renesis) {
+ throw 'Force traversal';
+ }
+ args.parent.appendChild(args.node.cloneNode(true));
+ }
+ catch (e) {
+ args.node = (args.node.jquery ? args.node : $(args.node));
+ args.node.each(function() {
+ var child = svg._cloneAsSVG(this);
+ if (child) {
+ args.parent.appendChild(child);
+ }
+ });
+ }
+ return this;
+ },
+
+ /* SVG nodes must belong to the SVG namespace, so clone and ensure this is so. */
+ _cloneAsSVG: function(node) {
+ var newNode = null;
+ if (node.nodeType == 1) { // element
+ newNode = this._svg.ownerDocument.createElementNS(
+ $.svg.svgNS, this._checkName(node.nodeName));
+ for (var i = 0; i < node.attributes.length; i++) {
+ var attr = node.attributes.item(i);
+ if (attr.nodeName != 'xmlns' && attr.nodeValue) {
+ if (attr.prefix == 'xlink') {
+ newNode.setAttributeNS($.svg.xlinkNS, attr.localName, attr.nodeValue);
+ }
+ else {
+ newNode.setAttribute(this._checkName(attr.nodeName), attr.nodeValue);
+ }
+ }
+ }
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = this._cloneAsSVG(node.childNodes[i]);
+ if (child) {
+ newNode.appendChild(child);
+ }
+ }
+ }
+ else if (node.nodeType == 3) { // text
+ if ($.trim(node.nodeValue)) {
+ newNode = this._svg.ownerDocument.createTextNode(node.nodeValue);
+ }
+ }
+ else if (node.nodeType == 4) { // CDATA
+ if ($.trim(node.nodeValue)) {
+ try {
+ newNode = this._svg.ownerDocument.createCDATASection(node.nodeValue);
+ }
+ catch (e) {
+ newNode = this._svg.ownerDocument.createTextNode(
+ node.nodeValue.replace(/&/g, '&').
+ replace(//g, '>'));
+ }
+ }
+ }
+ return newNode;
+ },
+
+ /* Node names must be lower case and without SVG namespace prefix. */
+ _checkName: function(name) {
+ name = (name.substring(0, 1) >= 'A' && name.substring(0, 1) <= 'Z' ?
+ name.toLowerCase() : name);
+ return (name.substring(0, 4) == 'svg:' ? name.substring(4) : name);
+ },
+
+ /* Load an external SVG document.
+ @param url (string) the location of the SVG document or
+ the actual SVG content
+ @param settings (boolean) see addTo below or
+ (function) see onLoad below or
+ (object) additional settings for the load with attributes below:
+ addTo (boolean) true to add to what's already there,
+ or false to clear the canvas first
+ changeSize (boolean) true to allow the canvas size to change,
+ or false to retain the original
+ onLoad (function) callback after the document has loaded,
+ 'this' is the container, receives SVG object and
+ optional error message as a parameter
+ @return (SVGWrapper) this root */
+ load: function(url, settings) {
+ settings = (typeof settings == 'boolean'? {addTo: settings} :
+ (typeof settings == 'function'? {onLoad: settings} : settings || {}));
+ if (!settings.addTo) {
+ this.clear(false);
+ }
+ var size = [this._svg.getAttribute('width'), this._svg.getAttribute('height')];
+ var wrapper = this;
+ // Report a problem with the load
+ var reportError = function(message) {
+ message = $.svg.local.errorLoadingText + ': ' + message;
+ if (settings.onLoad) {
+ settings.onLoad.apply(wrapper._container || wrapper._svg, [wrapper, message]);
+ }
+ else {
+ wrapper.text(null, 10, 20, message);
+ }
+ };
+ // Create a DOM from SVG content
+ var loadXML4IE = function(data) {
+ var xml = new ActiveXObject('Microsoft.XMLDOM');
+ xml.validateOnParse = false;
+ xml.resolveExternals = false;
+ xml.async = false;
+ xml.loadXML(data);
+ if (xml.parseError.errorCode != 0) {
+ reportError(xml.parseError.reason);
+ return null;
+ }
+ return xml;
+ };
+ // Load the SVG DOM
+ var loadSVG = function(data) {
+ if (!data) {
+ return;
+ }
+ if (data.documentElement.nodeName != 'svg') {
+ var errors = data.getElementsByTagName('parsererror');
+ var messages = (errors.length ? errors[0].getElementsByTagName('div') : []); // Safari
+ reportError(!errors.length ? '???' :
+ (messages.length ? messages[0] : errors[0]).firstChild.nodeValue);
+ return;
+ }
+ var attrs = {};
+ for (var i = 0; i < data.documentElement.attributes.length; i++) {
+ var attr = data.documentElement.attributes.item(i);
+ if (!(attr.nodeName == 'version' || attr.nodeName.substring(0, 5) == 'xmlns')) {
+ attrs[attr.nodeName] = attr.nodeValue;
+ }
+ }
+ wrapper.configure(attrs, true);
+ var nodes = data.documentElement.childNodes;
+ for (var i = 0; i < nodes.length; i++) {
+ try {
+ if ($.svg._renesis) {
+ throw 'Force traversal';
+ }
+ wrapper._svg.appendChild(nodes[i].cloneNode(true));
+ if (nodes[i].nodeName == 'script') {
+ $.globalEval(nodes[i].textContent);
+ }
+ }
+ catch (e) {
+ wrapper.add(null, nodes[i]);
+ }
+ }
+ if (!settings.changeSize) {
+ wrapper.configure({width: size[0], height: size[1]});
+ }
+ if (settings.onLoad) {
+ settings.onLoad.apply(wrapper._container || wrapper._svg, [wrapper]);
+ }
+ };
+ if (url.match('';
+ }
+ else { // Element
+ svgDoc = '<' + node.nodeName;
+ if (node.attributes) {
+ for (var i = 0; i < node.attributes.length; i++) {
+ var attr = node.attributes.item(i);
+ if (!($.trim(attr.nodeValue) == '' || attr.nodeValue.match(/^\[object/) ||
+ attr.nodeValue.match(/^function/))) {
+ svgDoc += ' ' + (attr.namespaceURI == $.svg.xlinkNS ? 'xlink:' : '') +
+ attr.nodeName + '="' + attr.nodeValue + '"';
+ }
+ }
+ }
+ if (node.firstChild) {
+ svgDoc += '>';
+ var child = node.firstChild;
+ while (child) {
+ svgDoc += this._toSVG(child);
+ child = child.nextSibling;
+ }
+ svgDoc += '' + node.nodeName + '>';
+ }
+ else {
+ svgDoc += '/>';
+ }
+ }
+ return svgDoc;
+ },
+
+ /* Escape reserved characters in XML. */
+ _escapeXML: function(text) {
+ text = text.replace(/&/g, '&');
+ text = text.replace(//g, '>');
+ return text;
+ }
+});
+
+/* Helper to generate an SVG path.
+ Obtain an instance from the SVGWrapper object.
+ String calls together to generate the path and use its value:
+ var path = root.createPath();
+ root.path(null, path.move(100, 100).line(300, 100).line(200, 300).close(), {fill: 'red'});
+ or
+ root.path(null, path.move(100, 100).line([[300, 100], [200, 300]]).close(), {fill: 'red'}); */
+function SVGPath() {
+ this._path = '';
+}
+
+$.extend(SVGPath.prototype, {
+ /* Prepare to create a new path.
+ @return (SVGPath) this path */
+ reset: function() {
+ this._path = '';
+ return this;
+ },
+
+ /* Move the pointer to a position.
+ @param x (number) x-coordinate to move to or
+ (number[][]) x-/y-coordinates to move to
+ @param y (number) y-coordinate to move to (omitted if x is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ move: function(x, y, relative) {
+ relative = (isArray(x) ? y : relative);
+ return this._coords((relative ? 'm' : 'M'), x, y);
+ },
+
+ /* Draw a line to a position.
+ @param x (number) x-coordinate to move to or
+ (number[][]) x-/y-coordinates to move to
+ @param y (number) y-coordinate to move to (omitted if x is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ line: function(x, y, relative) {
+ relative = (isArray(x) ? y : relative);
+ return this._coords((relative ? 'l' : 'L'), x, y);
+ },
+
+ /* Draw a horizontal line to a position.
+ @param x (number) x-coordinate to draw to or
+ (number[]) x-coordinates to draw to
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ horiz: function(x, relative) {
+ this._path += (relative ? 'h' : 'H') + (isArray(x) ? x.join(' ') : x);
+ return this;
+ },
+
+ /* Draw a vertical line to a position.
+ @param y (number) y-coordinate to draw to or
+ (number[]) y-coordinates to draw to
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ vert: function(y, relative) {
+ this._path += (relative ? 'v' : 'V') + (isArray(y) ? y.join(' ') : y);
+ return this;
+ },
+
+ /* Draw a cubic Bézier curve.
+ @param x1 (number) x-coordinate of beginning control point or
+ (number[][]) x-/y-coordinates of control and end points to draw to
+ @param y1 (number) y-coordinate of beginning control point (omitted if x1 is array)
+ @param x2 (number) x-coordinate of ending control point (omitted if x1 is array)
+ @param y2 (number) y-coordinate of ending control point (omitted if x1 is array)
+ @param x (number) x-coordinate of curve end (omitted if x1 is array)
+ @param y (number) y-coordinate of curve end (omitted if x1 is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ curveC: function(x1, y1, x2, y2, x, y, relative) {
+ relative = (isArray(x1) ? y1 : relative);
+ return this._coords((relative ? 'c' : 'C'), x1, y1, x2, y2, x, y);
+ },
+
+ /* Continue a cubic Bézier curve.
+ Starting control point is the reflection of the previous end control point.
+ @param x2 (number) x-coordinate of ending control point or
+ (number[][]) x-/y-coordinates of control and end points to draw to
+ @param y2 (number) y-coordinate of ending control point (omitted if x2 is array)
+ @param x (number) x-coordinate of curve end (omitted if x2 is array)
+ @param y (number) y-coordinate of curve end (omitted if x2 is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ smoothC: function(x2, y2, x, y, relative) {
+ relative = (isArray(x2) ? y2 : relative);
+ return this._coords((relative ? 's' : 'S'), x2, y2, x, y);
+ },
+
+ /* Draw a quadratic Bézier curve.
+ @param x1 (number) x-coordinate of control point or
+ (number[][]) x-/y-coordinates of control and end points to draw to
+ @param y1 (number) y-coordinate of control point (omitted if x1 is array)
+ @param x (number) x-coordinate of curve end (omitted if x1 is array)
+ @param y (number) y-coordinate of curve end (omitted if x1 is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ curveQ: function(x1, y1, x, y, relative) {
+ relative = (isArray(x1) ? y1 : relative);
+ return this._coords((relative ? 'q' : 'Q'), x1, y1, x, y);
+ },
+
+ /* Continue a quadratic Bézier curve.
+ Control point is the reflection of the previous control point.
+ @param x (number) x-coordinate of curve end or
+ (number[][]) x-/y-coordinates of points to draw to
+ @param y (number) y-coordinate of curve end (omitted if x is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ smoothQ: function(x, y, relative) {
+ relative = (isArray(x) ? y : relative);
+ return this._coords((relative ? 't' : 'T'), x, y);
+ },
+
+ /* Generate a path command with (a list of) coordinates. */
+ _coords: function(cmd, x1, y1, x2, y2, x3, y3) {
+ if (isArray(x1)) {
+ for (var i = 0; i < x1.length; i++) {
+ var cs = x1[i];
+ this._path += (i == 0 ? cmd : ' ') + cs[0] + ',' + cs[1] +
+ (cs.length < 4 ? '' : ' ' + cs[2] + ',' + cs[3] +
+ (cs.length < 6 ? '': ' ' + cs[4] + ',' + cs[5]));
+ }
+ }
+ else {
+ this._path += cmd + x1 + ',' + y1 +
+ (x2 == null ? '' : ' ' + x2 + ',' + y2 +
+ (x3 == null ? '' : ' ' + x3 + ',' + y3));
+ }
+ return this;
+ },
+
+ /* Draw an arc to a position.
+ @param rx (number) x-radius of arc or
+ (number/boolean[][]) x-/y-coordinates and flags for points to draw to
+ @param ry (number) y-radius of arc (omitted if rx is array)
+ @param xRotate (number) x-axis rotation (degrees, clockwise) (omitted if rx is array)
+ @param large (boolean) true to draw the large part of the arc,
+ false to draw the small part (omitted if rx is array)
+ @param clockwise (boolean) true to draw the clockwise arc,
+ false to draw the anti-clockwise arc (omitted if rx is array)
+ @param x (number) x-coordinate of arc end (omitted if rx is array)
+ @param y (number) y-coordinate of arc end (omitted if rx is array)
+ @param relative (boolean) true for coordinates relative to the current point,
+ false for coordinates being absolute
+ @return (SVGPath) this path */
+ arc: function(rx, ry, xRotate, large, clockwise, x, y, relative) {
+ relative = (isArray(rx) ? ry : relative);
+ this._path += (relative ? 'a' : 'A');
+ if (isArray(rx)) {
+ for (var i = 0; i < rx.length; i++) {
+ var cs = rx[i];
+ this._path += (i == 0 ? '' : ' ') + cs[0] + ',' + cs[1] + ' ' +
+ cs[2] + ' ' + (cs[3] ? '1' : '0') + ',' +
+ (cs[4] ? '1' : '0') + ' ' + cs[5] + ',' + cs[6];
+ }
+ }
+ else {
+ this._path += rx + ',' + ry + ' ' + xRotate + ' ' +
+ (large ? '1' : '0') + ',' + (clockwise ? '1' : '0') + ' ' + x + ',' + y;
+ }
+ return this;
+ },
+
+ /* Close the current path.
+ @return (SVGPath) this path */
+ close: function() {
+ this._path += 'z';
+ return this;
+ },
+
+ /* Return the string rendering of the specified path.
+ @return (string) stringified path */
+ path: function() {
+ return this._path;
+ }
+});
+
+SVGPath.prototype.moveTo = SVGPath.prototype.move;
+SVGPath.prototype.lineTo = SVGPath.prototype.line;
+SVGPath.prototype.horizTo = SVGPath.prototype.horiz;
+SVGPath.prototype.vertTo = SVGPath.prototype.vert;
+SVGPath.prototype.curveCTo = SVGPath.prototype.curveC;
+SVGPath.prototype.smoothCTo = SVGPath.prototype.smoothC;
+SVGPath.prototype.curveQTo = SVGPath.prototype.curveQ;
+SVGPath.prototype.smoothQTo = SVGPath.prototype.smoothQ;
+SVGPath.prototype.arcTo = SVGPath.prototype.arc;
+
+/* Helper to generate an SVG text object.
+ Obtain an instance from the SVGWrapper object.
+ String calls together to generate the text and use its value:
+ var text = root.createText();
+ root.text(null, x, y, text.string('This is ').
+ span('red', {fill: 'red'}).string('!'), {fill: 'blue'}); */
+function SVGText() {
+ this._parts = []; // The components of the text object
+}
+
+$.extend(SVGText.prototype, {
+ /* Prepare to create a new text object.
+ @return (SVGText) this text */
+ reset: function() {
+ this._parts = [];
+ return this;
+ },
+
+ /* Add a straight string value.
+ @param value (string) the actual text
+ @return (SVGText) this text object */
+ string: function(value) {
+ this._parts[this._parts.length] = ['text', value];
+ return this;
+ },
+
+ /* Add a separate text span that has its own settings.
+ @param value (string) the actual text
+ @param settings (object) the settings for this text
+ @return (SVGText) this text object */
+ span: function(value, settings) {
+ this._parts[this._parts.length] = ['tspan', value, settings];
+ return this;
+ },
+
+ /* Add a reference to a previously defined text string.
+ @param id (string) the ID of the actual text
+ @param settings (object) the settings for this text
+ @return (SVGText) this text object */
+ ref: function(id, settings) {
+ this._parts[this._parts.length] = ['tref', id, settings];
+ return this;
+ },
+
+ /* Add text drawn along a path.
+ @param id (string) the ID of the path
+ @param value (string) the actual text
+ @param settings (object) the settings for this text
+ @return (SVGText) this text object */
+ path: function(id, value, settings) {
+ this._parts[this._parts.length] = ['textpath', value,
+ $.extend({href: id}, settings || {})];
+ return this;
+ }
+});
+
+/* Attach the SVG functionality to a jQuery selection.
+ @param command (string) the command to run (optional, default 'attach')
+ @param options (object) the new settings to use for these SVG instances
+ @return jQuery (object) for chaining further calls */
+$.fn.svg = function(options) {
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
+ if (typeof options == 'string' && options == 'get') {
+ return $.svg['_' + options + 'SVG'].apply($.svg, [this[0]].concat(otherArgs));
+ }
+ return this.each(function() {
+ if (typeof options == 'string') {
+ $.svg['_' + options + 'SVG'].apply($.svg, [this].concat(otherArgs));
+ }
+ else {
+ $.svg._attachSVG(this, options || {});
+ }
+ });
+};
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+ return (a && a.constructor == Array);
+}
+
+// Singleton primary SVG interface
+$.svg = new SVGManager();
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svganim.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svganim.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,405 @@
+/* http://keith-wood.name/svg.html
+ SVG attribute animations for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) June 2008.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+// Enable animation for all of these SVG numeric attributes -
+// named as svg-* or svg* (with first character upper case)
+$.each(['x', 'y', 'width', 'height', 'rx', 'ry', 'cx', 'cy', 'r', 'x1', 'y1', 'x2', 'y2',
+ 'stroke-width', 'strokeWidth', 'opacity', 'fill-opacity', 'fillOpacity',
+ 'stroke-opacity', 'strokeOpacity', 'font-size', 'fontSize'],
+ function(i, attrName) {
+ var ccName = attrName.charAt(0).toUpperCase() + attrName.substr(1);
+ $.fx.step['svg' + ccName] = $.fx.step['svg-' + attrName] = function(fx) {
+ var realAttrName = $.svg._attrNames[attrName] || attrName;
+ var attr = fx.elem.attributes.getNamedItem(realAttrName);
+ if (!fx.set) {
+ fx.start = (attr ? parseFloat(attr.nodeValue) : 0);
+ var offset = fx.options.curAnim['svg-' + attrName] ||
+ fx.options.curAnim['svg' + ccName];
+ if (/^[+-]=/.exec(offset)) {
+ fx.end = fx.start + parseFloat(offset.replace(/=/, ''));
+ }
+ $(fx.elem).css(realAttrName, '');
+ fx.set = true;
+ }
+ var value = (fx.pos * (fx.end - fx.start) + fx.start) + (fx.unit == '%' ? '%' : '');
+ (attr ? attr.nodeValue = value : fx.elem.setAttribute(realAttrName, value));
+ };
+ }
+);
+
+// Enable animation for the SVG viewBox attribute
+$.fx.step['svgViewBox'] = $.fx.step['svg-viewBox'] = function(fx) {
+ var attr = fx.elem.attributes.getNamedItem('viewBox');
+ if (!fx.set) {
+ fx.start = parseViewBox(attr ? attr.nodeValue : '');
+ var offset = fx.options.curAnim['svg-viewBox'] || fx.options.curAnim['svgViewBox'];
+ fx.end = parseViewBox(offset);
+ if (/^[+-]=/.exec(offset)) {
+ offset = offset.split(' ');
+ while (offset.length < 4) {
+ offset.push('0');
+ }
+ for (var i = 0; i < 4; i++) {
+ if (/^[+-]=/.exec(offset[i])) {
+ fx.end[i] = fx.start[i] + parseFloat(offset[i].replace(/=/, ''));
+ }
+ }
+ }
+ fx.set = true;
+ }
+ var value = $.map(fx.start, function(n, i) {
+ return (fx.pos * (fx.end[i] - n) + n);
+ }).join(' ');
+ (attr ? attr.nodeValue = value : fx.elem.setAttribute('viewBox', value));
+};
+
+/* Parse a viewBox definition: x, y, width, height.
+ @param value (string) the definition
+ @return (number[4]) the extracted values */
+function parseViewBox(value) {
+ var viewBox = value.split(' ');
+ for (var i = 0; i < viewBox.length; i++) {
+ viewBox[i] = parseFloat(viewBox[i]);
+ if (isNaN(viewBox[i])) {
+ viewBox[i] = 0;
+ }
+ }
+ while (viewBox.length < 4) {
+ viewBox.push(0);
+ }
+ return viewBox;
+}
+
+// Enable animation for the SVG transform attribute
+$.fx.step['svgTransform'] = $.fx.step['svg-transform'] = function(fx) {
+ var attr = fx.elem.attributes.getNamedItem('transform');
+ if (!fx.set) {
+ fx.start = parseTransform(attr ? attr.nodeValue : '');
+ fx.end = parseTransform(fx.end, fx.start);
+ fx.set = true;
+ }
+ var transform = '';
+ for (var i = 0; i < fx.end.order.length; i++) {
+ switch (fx.end.order.charAt(i)) {
+ case 't':
+ transform += (fx.start.translateX != fx.end.translateX || fx.start.translateY != fx.end.translateY ?
+ ' translate(' + (fx.pos * (fx.end.translateX - fx.start.translateX) + fx.start.translateX) + ',' +
+ (fx.pos * (fx.end.translateY - fx.start.translateY) + fx.start.translateY) + ')' : '');
+ break;
+ case 's':
+ transform += (fx.start.scaleX != fx.end.scaleX || fx.start.scaleY != fx.end.scaleY ?
+ ' scale(' + (fx.pos * (fx.end.scaleX - fx.start.scaleX) + fx.start.scaleX) + ',' +
+ (fx.pos * (fx.end.scaleY - fx.start.scaleY) + fx.start.scaleY) + ')' : '');
+ break;
+ case 'r':
+ transform += (fx.start.rotateA != fx.end.rotateA ||
+ fx.start.rotateX != fx.end.rotateX || fx.start.rotateY != fx.end.rotateY ?
+ ' rotate(' + (fx.pos * (fx.end.rotateA - fx.start.rotateA) + fx.start.rotateA) + ',' +
+ (fx.pos * (fx.end.rotateX - fx.start.rotateX) + fx.start.rotateX) + ',' +
+ (fx.pos * (fx.end.rotateY - fx.start.rotateY) + fx.start.rotateY) + ')' : '');
+ break;
+ case 'x':
+ transform += (fx.start.skewX != fx.end.skewX ?
+ ' skewX(' + (fx.pos * (fx.end.skewX - fx.start.skewX) + fx.start.skewX) + ')' : '');
+ case 'y':
+ transform += (fx.start.skewY != fx.end.skewY ?
+ ' skewY(' + (fx.pos * (fx.end.skewY - fx.start.skewY) + fx.start.skewY) + ')' : '');
+ break;
+ case 'm':
+ var matrix = '';
+ for (var j = 0; j < 6; j++) {
+ matrix += ',' + (fx.pos * (fx.end.matrix[j] - fx.start.matrix[j]) + fx.start.matrix[j]);
+ }
+ transform += ' matrix(' + matrix.substr(1) + ')';
+ break;
+ }
+ }
+ (attr ? attr.nodeValue = transform : fx.elem.setAttribute('transform', transform));
+};
+
+/* Decode a transform string and extract component values.
+ @param value (string) the transform string to parse
+ @param original (object) the settings from the original node
+ @return (object) the combined transformation attributes */
+function parseTransform(value, original) {
+ value = value || '';
+ if (typeof value == 'object') {
+ value = value.nodeValue;
+ }
+ var transform = $.extend({translateX: 0, translateY: 0, scaleX: 0, scaleY: 0,
+ rotateA: 0, rotateX: 0, rotateY: 0, skewX: 0, skewY: 0,
+ matrix: [0, 0, 0, 0, 0, 0]}, original || {});
+ transform.order = '';
+ var pattern = /([a-zA-Z]+)\(\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*(?:[\s,]\s*([+-]?[\d\.]+)\s*[\s,]\s*([+-]?[\d\.]+)\s*[\s,]\s*([+-]?[\d\.]+)\s*)?)?)?\)/g;
+ var result = pattern.exec(value);
+ while (result) {
+ switch (result[1]) {
+ case 'translate':
+ transform.order += 't';
+ transform.translateX = parseFloat(result[2]);
+ transform.translateY = (result[3] ? parseFloat(result[3]) : 0);
+ break;
+ case 'scale':
+ transform.order += 's';
+ transform.scaleX = parseFloat(result[2]);
+ transform.scaleY = (result[3] ? parseFloat(result[3]) : transform.scaleX);
+ break;
+ case 'rotate':
+ transform.order += 'r';
+ transform.rotateA = parseFloat(result[2]);
+ transform.rotateX = (result[3] ? parseFloat(result[3]) : 0);
+ transform.rotateY = (result[4] ? parseFloat(result[4]) : 0);
+ break;
+ case 'skewX':
+ transform.order += 'x';
+ transform.skewX = parseFloat(result[2]);
+ break;
+ case 'skewY':
+ transform.order += 'y';
+ transform.skewY = parseFloat(result[2]);
+ break;
+ case 'matrix':
+ transform.order += 'm';
+ transform.matrix = [parseFloat(result[2]), parseFloat(result[3]),
+ parseFloat(result[4]), parseFloat(result[5]),
+ parseFloat(result[6]), parseFloat(result[7])];
+ break;
+ }
+ result = pattern.exec(value);
+ }
+ return transform;
+}
+
+// Enable animation for all of these SVG colour properties - based on jquery.color.js
+$.each(['fill', 'stroke'],
+ function(i, attrName) {
+ var ccName = attrName.charAt(0).toUpperCase() + attrName.substr(1);
+ $.fx.step['svg' + ccName] = $.fx.step['svg-' + attrName] = function(fx) {
+ if (!fx.set) {
+ fx.start = getColour(fx.elem, attrName);
+ var toNone = (fx.end == 'none');
+ fx.end = (toNone ? getColour(fx.elem.parentNode, attrName) : getRGB(fx.end));
+ fx.end[3] = toNone;
+ $(fx.elem).css(attrName, '');
+ fx.set = true;
+ }
+ var attr = fx.elem.attributes.getNamedItem(attrName);
+ var colour = 'rgb(' + [
+ Math.min(Math.max(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 0), 255),
+ Math.min(Math.max(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 0), 255),
+ Math.min(Math.max(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 0), 255)
+ ].join(',') + ')';
+ colour = (fx.end[3] && fx.state == 1 ? 'none' : colour);
+ (attr ? attr.nodeValue = colour : fx.elem.setAttribute(attrName, colour));
+ }
+ }
+);
+
+/* Find this attribute value somewhere up the node hierarchy.
+ @param elem (element) the starting element to find the attribute
+ @param attr (string) the attribute name
+ @return (number[3]) RGB components for the attribute colour */
+function getColour(elem, attr) {
+ var colour;
+ do {
+ colour = (elem.attributes && elem.attributes.getNamedItem(attr) ?
+ elem.attributes.getNamedItem(attr).nodeValue : '');
+ // Keep going until we find an element that has colour, or exit SVG
+ if ((colour != '' && colour != 'none') || $(elem).hasClass('hasSVG')) {
+ break;
+ }
+ } while (elem = elem.parentNode);
+ return getRGB(colour);
+}
+
+/* Parse strings looking for common colour formats.
+ @param colour (string) colour description to parse
+ @return (number[3]) RGB components of this colour */
+function getRGB(colour) {
+ var result;
+ // Check if we're already dealing with an array of colors
+ if (colour && colour.constructor == Array && (colour.length == 3 || colour.length == 4)) {
+ return colour;
+ }
+ // Look for rgb(num,num,num)
+ if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(colour)) {
+ return [parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)];
+ }
+ // Look for rgb(num%,num%,num%)
+ if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(colour)) {
+ return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55,
+ parseFloat(result[3]) * 2.55];
+ }
+ // Look for #a0b1c2
+ if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(colour)) {
+ return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)];
+ }
+ // Look for #abc
+ if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(colour)) {
+ return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16),
+ parseInt(result[3] + result[3], 16)];
+ }
+ // Otherwise, we're most likely dealing with a named color
+ return colours[$.trim(colour).toLowerCase()] || colours['none'];
+}
+
+// The SVG named colours
+var colours = {
+ '': [255, 255, 255, 1],
+ none: [255, 255, 255, 1],
+ aliceblue: [240, 248, 255],
+ antiquewhite: [250, 235, 215],
+ aqua: [ 0, 255, 255],
+ aquamarine: [127, 255, 212],
+ azure: [240, 255, 255],
+ beige: [245, 245, 220],
+ bisque: [255, 228, 196],
+ black: [ 0, 0, 0],
+ blanchedalmond: [255, 235, 205],
+ blue: [ 0, 0, 255],
+ blueviolet: [138, 43, 226],
+ brown: [165, 42, 42],
+ burlywood: [222, 184, 135],
+ cadetblue: [ 95, 158, 160],
+ chartreuse: [127, 255, 0],
+ chocolate: [210, 105, 30],
+ coral: [255, 127, 80],
+ cornflowerblue: [100, 149, 237],
+ cornsilk: [255, 248, 220],
+ crimson: [220, 20, 60],
+ cyan: [ 0, 255, 255],
+ darkblue: [ 0, 0, 139],
+ darkcyan: [ 0, 139, 139],
+ darkgoldenrod: [184, 134, 11],
+ darkgray: [169, 169, 169],
+ darkgreen: [ 0, 100, 0],
+ darkgrey: [169, 169, 169],
+ darkkhaki: [189, 183, 107],
+ darkmagenta: [139, 0, 139],
+ darkolivegreen: [ 85, 107, 47],
+ darkorange: [255, 140, 0],
+ darkorchid: [153, 50, 204],
+ darkred: [139, 0, 0],
+ darksalmon: [233, 150, 122],
+ darkseagreen: [143, 188, 143],
+ darkslateblue: [ 72, 61, 139],
+ darkslategray: [ 47, 79, 79],
+ darkslategrey: [ 47, 79, 79],
+ darkturquoise: [ 0, 206, 209],
+ darkviolet: [148, 0, 211],
+ deeppink: [255, 20, 147],
+ deepskyblue: [ 0, 191, 255],
+ dimgray: [105, 105, 105],
+ dimgrey: [105, 105, 105],
+ dodgerblue: [ 30, 144, 255],
+ firebrick: [178, 34, 34],
+ floralwhite: [255, 250, 240],
+ forestgreen: [ 34, 139, 34],
+ fuchsia: [255, 0, 255],
+ gainsboro: [220, 220, 220],
+ ghostwhite: [248, 248, 255],
+ gold: [255, 215, 0],
+ goldenrod: [218, 165, 32],
+ gray: [128, 128, 128],
+ grey: [128, 128, 128],
+ green: [ 0, 128, 0],
+ greenyellow: [173, 255, 47],
+ honeydew: [240, 255, 240],
+ hotpink: [255, 105, 180],
+ indianred: [205, 92, 92],
+ indigo: [ 75, 0, 130],
+ ivory: [255, 255, 240],
+ khaki: [240, 230, 140],
+ lavender: [230, 230, 250],
+ lavenderblush: [255, 240, 245],
+ lawngreen: [124, 252, 0],
+ lemonchiffon: [255, 250, 205],
+ lightblue: [173, 216, 230],
+ lightcoral: [240, 128, 128],
+ lightcyan: [224, 255, 255],
+ lightgoldenrodyellow: [250, 250, 210],
+ lightgray: [211, 211, 211],
+ lightgreen: [144, 238, 144],
+ lightgrey: [211, 211, 211],
+ lightpink: [255, 182, 193],
+ lightsalmon: [255, 160, 122],
+ lightseagreen: [ 32, 178, 170],
+ lightskyblue: [135, 206, 250],
+ lightslategray: [119, 136, 153],
+ lightslategrey: [119, 136, 153],
+ lightsteelblue: [176, 196, 222],
+ lightyellow: [255, 255, 224],
+ lime: [ 0, 255, 0],
+ limegreen: [ 50, 205, 50],
+ linen: [250, 240, 230],
+ magenta: [255, 0, 255],
+ maroon: [128, 0, 0],
+ mediumaquamarine: [102, 205, 170],
+ mediumblue: [ 0, 0, 205],
+ mediumorchid: [186, 85, 211],
+ mediumpurple: [147, 112, 219],
+ mediumseagreen: [ 60, 179, 113],
+ mediumslateblue: [123, 104, 238],
+ mediumspringgreen: [ 0, 250, 154],
+ mediumturquoise: [ 72, 209, 204],
+ mediumvioletred: [199, 21, 133],
+ midnightblue: [ 25, 25, 112],
+ mintcream: [245, 255, 250],
+ mistyrose: [255, 228, 225],
+ moccasin: [255, 228, 181],
+ navajowhite: [255, 222, 173],
+ navy: [ 0, 0, 128],
+ oldlace: [253, 245, 230],
+ olive: [128, 128, 0],
+ olivedrab: [107, 142, 35],
+ orange: [255, 165, 0],
+ orangered: [255, 69, 0],
+ orchid: [218, 112, 214],
+ palegoldenrod: [238, 232, 170],
+ palegreen: [152, 251, 152],
+ paleturquoise: [175, 238, 238],
+ palevioletred: [219, 112, 147],
+ papayawhip: [255, 239, 213],
+ peachpuff: [255, 218, 185],
+ peru: [205, 133, 63],
+ pink: [255, 192, 203],
+ plum: [221, 160, 221],
+ powderblue: [176, 224, 230],
+ purple: [128, 0, 128],
+ red: [255, 0, 0],
+ rosybrown: [188, 143, 143],
+ royalblue: [ 65, 105, 225],
+ saddlebrown: [139, 69, 19],
+ salmon: [250, 128, 114],
+ sandybrown: [244, 164, 96],
+ seagreen: [ 46, 139, 87],
+ seashell: [255, 245, 238],
+ sienna: [160, 82, 45],
+ silver: [192, 192, 192],
+ skyblue: [135, 206, 235],
+ slateblue: [106, 90, 205],
+ slategray: [112, 128, 144],
+ slategrey: [112, 128, 144],
+ snow: [255, 250, 250],
+ springgreen: [ 0, 255, 127],
+ steelblue: [ 70, 130, 180],
+ tan: [210, 180, 140],
+ teal: [ 0, 128, 128],
+ thistle: [216, 191, 216],
+ tomato: [255, 99, 71],
+ turquoise: [ 64, 224, 208],
+ violet: [238, 130, 238],
+ wheat: [245, 222, 179],
+ white: [255, 255, 255],
+ whitesmoke: [245, 245, 245],
+ yellow: [255, 255, 0],
+ yellowgreen: [154, 205, 50]
+};
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svgdom.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svgdom.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,332 @@
+/* http://keith-wood.name/svg.html
+ SVG/jQuery DOM compatibility for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) April 2009.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+/* Support adding class names to SVG nodes. */
+$.fn.addClass = function(origAddClass) {
+ return function(classNames) {
+ classNames = classNames || '';
+ return this.each(function() {
+ if (isSVGElem(this)) {
+ var node = this;
+ $.each(classNames.split(/\s+/), function(i, className) {
+ var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));
+ if ($.inArray(className, classes.split(/\s+/)) == -1) {
+ classes += (classes ? ' ' : '') + className;
+ (node.className ? node.className.baseVal = classes :
+ node.setAttribute('class', classes));
+ }
+ });
+ }
+ else {
+ origAddClass.apply($(this), [classNames]);
+ }
+ });
+ };
+}($.fn.addClass);
+
+/* Support removing class names from SVG nodes. */
+$.fn.removeClass = function(origRemoveClass) {
+ return function(classNames) {
+ classNames = classNames || '';
+ return this.each(function() {
+ if (isSVGElem(this)) {
+ var node = this;
+ $.each(classNames.split(/\s+/), function(i, className) {
+ var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));
+ classes = $.grep(classes.split(/\s+/), function(n, i) { return n != className; }).
+ join(' ');
+ (node.className ? node.className.baseVal = classes :
+ node.setAttribute('class', classes));
+ });
+ }
+ else {
+ origRemoveClass.apply($(this), [classNames]);
+ }
+ });
+ };
+}($.fn.removeClass);
+
+/* Support toggling class names on SVG nodes. */
+$.fn.toggleClass = function(origToggleClass) {
+ return function(className, state) {
+ return this.each(function() {
+ if (isSVGElem(this)) {
+ if (typeof state !== 'boolean') {
+ state = !$(this).hasClass(className);
+ }
+ $(this)[(state ? 'add' : 'remove') + 'Class'](className);
+ }
+ else {
+ origToggleClass.apply($(this), [className, state]);
+ }
+ });
+ };
+}($.fn.toggleClass);
+
+/* Support checking class names on SVG nodes. */
+$.fn.hasClass = function(origHasClass) {
+ return function(className) {
+ className = className || '';
+ var found = false;
+ this.each(function() {
+ if (isSVGElem(this)) {
+ var classes = (this.className ? this.className.baseVal :
+ this.getAttribute('class')).split(/\s+/);
+ found = ($.inArray(className, classes) > -1);
+ }
+ else {
+ found = (origHasClass.apply($(this), [className]));
+ }
+ return !found;
+ });
+ return found;
+ };
+}($.fn.hasClass);
+
+/* Support attributes on SVG nodes. */
+$.fn.attr = function(origAttr) {
+ return function(name, value, type) {
+ if (typeof name === 'string' && value === undefined) {
+ var val = origAttr.apply(this, [name, value, type]);
+ if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Transform
+ value = '';
+ val = val.baseVal;
+ for (var i = 0; i < val.numberOfItems; i++) {
+ var item = val.getItem(i);
+ switch (item.type) {
+ case 1: value += ' matrix(' + item.matrix.a + ',' + item.matrix.b + ',' +
+ item.matrix.c + ',' + item.matrix.d + ',' +
+ item.matrix.e + ',' + item.matrix.f + ')';
+ break;
+ case 2: value += ' translate(' + item.matrix.e + ',' + item.matrix.f + ')'; break;
+ case 3: value += ' scale(' + item.matrix.a + ',' + item.matrix.d + ')'; break;
+ case 4: value += ' rotate(' + item.angle + ')'; break; // Doesn't handle new origin
+ case 5: value += ' skewX(' + item.angle + ')'; break;
+ case 6: value += ' skewY(' + item.angle + ')'; break;
+ }
+ }
+ val = value.substring(1);
+ }
+ return (val && val.baseVal ? val.baseVal.valueAsString : val);
+ }
+ var options = name;
+ if (typeof name === 'string') {
+ options = {};
+ options[name] = value;
+ }
+ return this.each(function() {
+ if (isSVGElem(this)) {
+ for (var n in options) {
+ var val = ($.isFunction(options[n]) ? options[n]() : options[n]);
+ (type ? this.style[n] = val : this.setAttribute(n, val));
+ }
+ }
+ else {
+ origAttr.apply($(this), [name, value, type]);
+ }
+ });
+ };
+}($.fn.attr);
+
+/* Support removing attributes on SVG nodes. */
+$.fn.removeAttr = function(origRemoveAttr) {
+ return function(name) {
+ return this.each(function() {
+ if (isSVGElem(this)) {
+ (this[name] && this[name].baseVal ? this[name].baseVal.value = '' :
+ this.setAttribute(name, ''));
+ }
+ else {
+ origRemoveAttr.apply($(this), [name]);
+ }
+ });
+ };
+}($.fn.removeAttr);
+
+/* Determine if any nodes are SVG nodes. */
+function anySVG(checkSet) {
+ for (var i = 0; i < checkSet.length; i++) {
+ if (checkSet[i].nodeType == 1 && checkSet[i].namespaceURI == $.svg.svgNS) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Update Sizzle selectors. */
+
+$.expr.relative['+'] = function(origRelativeNext) {
+ return function(checkSet, part, isXML) {
+ origRelativeNext(checkSet, part, isXML || anySVG(checkSet));
+ };
+}($.expr.relative['+']);
+
+$.expr.relative['>'] = function(origRelativeChild) {
+ return function(checkSet, part, isXML) {
+ origRelativeChild(checkSet, part, isXML || anySVG(checkSet));
+ };
+}($.expr.relative['>']);
+
+$.expr.relative[''] = function(origRelativeDescendant) {
+ return function(checkSet, part, isXML) {
+ origRelativeDescendant(checkSet, part, isXML || anySVG(checkSet));
+ };
+}($.expr.relative['']);
+
+$.expr.relative['~'] = function(origRelativeSiblings) {
+ return function(checkSet, part, isXML) {
+ origRelativeSiblings(checkSet, part, isXML || anySVG(checkSet));
+ };
+}($.expr.relative['~']);
+
+$.expr.find.ID = function(origFindId) {
+ return function(match, context, isXML) {
+ return (isSVGElem(context) ?
+ [context.ownerDocument.getElementById(match[1])] :
+ origFindId(match, context, isXML));
+ };
+}($.expr.find.ID);
+
+var div = document.createElement('div');
+div.appendChild(document.createComment(''));
+if (div.getElementsByTagName('*').length > 0) { // Make sure no comments are found
+ $.expr.find.TAG = function(match, context) {
+ var results = context.getElementsByTagName(match[1]);
+ if (match[1] === '*') { // Filter out possible comments
+ var tmp = [];
+ for (var i = 0; results[i] || results.item(i); i++) {
+ if ((results[i] || results.item(i)).nodeType === 1) {
+ tmp.push(results[i] || results.item(i));
+ }
+ }
+ results = tmp;
+ }
+ return results;
+ };
+}
+
+$.expr.preFilter.CLASS = function(match, curLoop, inplace, result, not, isXML) {
+ match = ' ' + match[1].replace(/\\/g, '') + ' ';
+ if (isXML) {
+ return match;
+ }
+ for (var i = 0, elem = {}; elem != null; i++) {
+ elem = curLoop[i];
+ if (!elem) {
+ try {
+ elem = curLoop.item(i);
+ }
+ catch (e) {
+ // Ignore
+ }
+ }
+ if (elem) {
+ var className = (!isSVGElem(elem) ? elem.className :
+ (elem.className ? elem.className.baseVal : '') || elem.getAttribute('class'));
+ if (not ^ (className && (' ' + className + ' ').indexOf(match) > -1)) {
+ if (!inplace)
+ result.push(elem);
+ }
+ else if (inplace) {
+ curLoop[i] = false;
+ }
+ }
+ }
+ return false;
+};
+
+$.expr.filter.CLASS = function(elem, match) {
+ var className = (!isSVGElem(elem) ? elem.className :
+ (elem.className ? elem.className.baseVal : elem.getAttribute('class')));
+ return (' ' + className + ' ').indexOf(match) > -1;
+};
+
+$.expr.filter.ATTR = function(origFilterAttr) {
+ return function(elem, match) {
+ var handler = null;
+ if (isSVGElem(elem)) {
+ handler = match[1];
+ $.expr.attrHandle[handler] = function(elem){
+ var attr = elem.getAttribute(handler);
+ return attr && attr.baseVal || attr;
+ };
+ }
+ var filter = origFilterAttr(elem, match);
+ if (handler) {
+ $.expr.attrHandle[handler] = null;
+ }
+ return filter;
+ };
+}($.expr.filter.ATTR);
+
+/*
+ Change Sizzle initialisation (line 1425) in jQuery v1.3.2 base code...
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+ } else if ( context.nodeType === 1 ) {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+ results.push( set[i] || set.item(i) ); // Here
+ }
+ }
+ } else {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] || set.item(i) ); // Here
+ }
+ }
+ }
+ }
+
+ Change fallback makeArray (line 2076) implementation in jQuery Sizzle...
+
+ if ( typeof array.length === "number" ) {
+ for ( var i = 0, l = array.length; i < l; i++ ) {
+ ret.push( array[i] || array.item(i) ); // Here
+ }
+ }
+*/
+
+/*
+ Events management requires changes to jQuery v1.3.2 base code...
+
+ In $.event.add (line 2437)...
+
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+ // Bind the global event handler to the element
+ try { // Here
+ elem.addEventListener(type, handle, false);
+ }
+ catch(e) {
+ if (elem.attachEvent)
+ elem.attachEvent("on" + type, handle);
+ }
+ }
+
+ In $.event.remove (line 2521)...
+
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+ try { // Here
+ elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+ }
+ catch (e) {
+ if (elem.detachEvent)
+ elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+ }
+ }
+*/
+
+/* Does this node belong to SVG? */
+function isSVGElem(node) {
+ return (node.nodeType == 1 && node.namespaceURI == $.svg.svgNS);
+}
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svgfilter.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svgfilter.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,402 @@
+/* http://keith-wood.name/svg.html
+ SVG filters for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+$.svg.addExtension('filters', SVGFilter);
+
+$.extend($.svg._wrapperClass.prototype, {
+
+ /* Add a filter definition.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param id (string) the ID for this filter
+ @param x (number) the x-coordinate for the left edge of the filter
+ @param y (number) the y-coordinate for the top edge of the filter
+ @param width (number) the width of the filter
+ @param height (number) the height of the filter
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ filter: function(parent, id, x, y, width, height, settings) {
+ var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height']);
+ return this._makeNode(args.parent, 'filter', $.extend(
+ {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height},
+ args.settings || {}));
+ }
+});
+
+/* Extension point for SVG filters.
+ Access through svg.filters. */
+function SVGFilter(wrapper) {
+ this._wrapper = wrapper; // The attached SVG wrapper object
+}
+
+$.extend(SVGFilter.prototype, {
+
+ /* Add a distant light filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param azimuth (number) the angle (degrees) in the XY plane for the light source
+ @param elevation (number) the angle (degrees) in the YZ plane for the light source
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ distantLight: function(parent, result, azimuth, elevation, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'azimuth', 'elevation']);
+ return this._wrapper._makeNode(args.parent, 'feDistantLight', $.extend(
+ {result: args.result, azimuth: args.azimuth, elevation: args.elevation},
+ args.settings || {}));
+ },
+
+ /* Add a point light filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param x (number) the x-coordinate for the light source
+ @param y (number) the y-coordinate for the light source
+ @param z (number) the z-coordinate for the light source
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ pointLight: function(parent, result, x, y, z, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'x', 'y', 'z']);
+ return this._wrapper._makeNode(args.parent, 'fePointLight', $.extend(
+ {result: args.result, x: args.x, y: args.y, z: args.z}, args.settings || {}));
+ },
+
+ /* Add a spot light filter.
+ Specify all of toX, toY, toZ or none of them.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param x (number) the x-coordinate for the light source
+ @param y (number) the y-coordinate for the light source
+ @param z (number) the z-coordinate for the light source
+ @param toX (number) the x-coordinate for where the light is pointing (optional)
+ @param toY (number) the y-coordinate for where the light is pointing (optional)
+ @param toZ (number) the z-coordinate for where the light is pointing (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ spotLight: function(parent, result, x, y, z, toX, toY, toZ, settings) {
+ var args = this._wrapper._args(arguments,
+ ['result', 'x', 'y', 'z', 'toX', 'toY', 'toZ'], ['toX']);
+ var sets = $.extend({result: args.result, x: args.x, y: args.y, z: args.z},
+ (args.toX != null ? {pointsAtX: args.toX, pointsAtY: args.toY,
+ pointsAtZ: args.toZ} : {}));
+ return this._wrapper._makeNode(args.parent, 'feSpotLight',
+ $.extend(sets, args.settings || {}));
+ },
+
+ /* Add a blend filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param mode (string) normal | multiply | screen | darken | lighten
+ @param in1 (string) the first image to blend
+ @param in2 (string) the second image to blend
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ blend: function(parent, result, mode, in1, in2, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'mode', 'in1', 'in2']);
+ return this._wrapper._makeNode(args.parent, 'feBlend', $.extend(
+ {result: args.result, mode: args.mode, in_: args.in1, in2: args.in2},
+ args.settings || {}));
+ },
+
+ /* Add a colour matrix filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source to colour
+ @param type (string) matrix | saturate | hueRotate | luminanceToAlpha
+ @param values (number[][]) for 'matrix' the matrix (5x4) values to apply
+ (number) for 'saturate' 0.0 to 1.0
+ (number) for 'hueRotate' degrees
+ (void) for 'luminanceToAlpha'
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ colorMatrix: function(parent, result, in1, type, values, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'in1', 'type', 'values']);
+ if (isArray(args.values)) {
+ var vs = '';
+ for (var i = 0; i < args.values.length; i++) {
+ vs += (i == 0 ? '' : ' ') + args.values[i].join(' ');
+ }
+ args.values = vs;
+ }
+ else if (typeof args.values == 'object') {
+ args.settings = args.values;
+ args.values = null;
+ }
+ var sets = $.extend({result: args.result, in_: args.in1, type: args.type},
+ (args.values != null ? {values: args.values} : {}));
+ return this._wrapper._makeNode(args.parent, 'feColorMatrix',
+ $.extend(sets, args.settings || {}));
+ },
+
+ /* Add a component transfer filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param functions (object[]) one for each of RGB and A (alpha, optional)
+ for each entry:
+ [0] is (string) identity | table | discrete | linear | gamma
+ [1] is (number[]) for 'table' or 'discrete' the list of
+ interpolation or step values OR
+ (number) for 'linear' the slope, for 'gamma' the amplitude,
+ [2] is (number) for 'linear' the intercept, for 'gamma' the exponent,
+ [3] is (number) for 'gamma' the offset
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ componentTransfer: function(parent, result, functions, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'functions']);
+ var node = this._wrapper._makeNode(args.parent, 'feComponentTransfer',
+ $.extend({result: args.result}, args.settings || {}));
+ var rgba = ['R', 'G', 'B', 'A'];
+ for (var i = 0; i < Math.min(4, args.functions.length); i++) {
+ var props = args.functions[i];
+ var sets = $.extend({type: props[0]},
+ (props[0] == 'table' || props[0] == 'discrete' ? {tableValues: props[1].join(' ')} :
+ (props[0] == 'linear' ? {slope: props[1], intercept: props[2]} :
+ (props[0] == 'gamma' ? {amplitude: props[1],
+ exponent: props[2], offset: props[3]} : {}))));
+ this._wrapper._makeNode(node, 'feFunc' + rgba[i], sets);
+ }
+ return node;
+ },
+
+ /* Add a composite filter.
+ Specify all of k1, k2, k3, k4 or none of them.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param operator (string) over | in | out | atop | xor | arithmetic
+ @param in1 (string) the first filter to compose
+ @param in2 (string) the second filter to compose
+ @param k1 (number) for 'arithmetic' (optional)
+ @param k2 (number) for 'arithmetic' (optional)
+ @param k3 (number) for 'arithmetic' (optional)
+ @param k4 (number) for 'arithmetic' (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ composite: function(parent, result, operator, in1, in2, k1, k2, k3, k4, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'operator',
+ 'in1', 'in2', 'k1', 'k2', 'k3', 'k4'], ['k1']);
+ var sets = $.extend({result: args.result, operator: args.operator,
+ 'in': args.in1, in2: args.in2},
+ (args.k1 != null ? {k1: args.k1, k2: args.k2, k3: args.k3, k4: args.k4} : {}));
+ return this._wrapper._makeNode(args.parent, 'feComposite',
+ $.extend(sets, args.settings || {}));
+ },
+
+ /* Add a convolve matrix filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param order (int or 'int int') the size(s) of the matrix
+ @param matrix (number[][]) the kernel matrix for the convolution
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ convolveMatrix: function(parent, result, order, matrix, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'order', 'matrix']);
+ var mx = '';
+ for (var i = 0; i < args.matrix.length; i++) {
+ mx += (i == 0 ? '' : ' ') + args.matrix[i].join(' ');
+ }
+ args.matrix = mx;
+ return this._wrapper._makeNode(args.parent, 'feConvolveMatrix', $.extend(
+ {result: args.result, order: args.order, kernelMatrix: args.matrix},
+ args.settings || {}));
+ },
+
+ /* Add a diffuse lighting filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param colour (string) the lighting colour (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ diffuseLighting: function(parent, result, colour, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'colour'], ['colour']);
+ return this._wrapper._makeNode(args.parent, 'feDiffuseLighting',
+ $.extend($.extend({result: args.result},
+ (args.colour ? {lightingColor: args.colour} : {})), args.settings || {}));
+ },
+
+ /* Add a displacement map filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source image
+ @param in2 (string) the displacement image
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ displacementMap: function(parent, result, in1, in2, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'in1', 'in2']);
+ return this._wrapper._makeNode(args.parent, 'feDisplacementMap',
+ $.extend({result: args.result, in_: args.in1, in2: args.in2},
+ args.settings || {}));
+ },
+
+ /* Add a flood filter.
+ Specify all of x, y, width, height or none of them.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param x (number) the left coordinate of the rectangle (optional)
+ @param y (number) the top coordinate of the rectangle (optional)
+ @param width (number) the width of the rectangle (optional)
+ @param height (number) the height of the rectangle (optional)
+ @param colour (string) the colour to fill with
+ @param opacity (number) the opacity 0.0-1.0
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ flood: function(parent, result, x, y, width, height, colour, opacity, settings) {
+ var args = this._wrapper._args(arguments,
+ ['result', 'x', 'y', 'width', 'height', 'colour', 'opacity']);
+ if (arguments.length < 6) {
+ args.colour = args.x;
+ args.opacity = args.y;
+ args.settings = args.width;
+ args.x = null;
+ }
+ var sets = $.extend({result: args.result, floodColor: args.colour,
+ floodOpacity: args.opacity}, (args.x != null ?
+ {x: args.x, y: args.y, width: args.width, height: args.height} : {}));
+ return this._wrapper._makeNode(args.parent, 'feFlood',
+ $.extend(sets, args.settings || {}));
+ },
+
+ /* Add a Gaussian blur filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source filter
+ @param stdDevX (number) the standard deviation along the x-axis
+ @param stdDevY (number) the standard deviation along the y-axis (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ gaussianBlur: function(parent, result, in1, stdDevX, stdDevY, settings) {
+ var args = this._wrapper._args(arguments,
+ ['result', 'in1', 'stdDevX', 'stdDevY'], ['stdDevY']);
+ return this._wrapper._makeNode(args.parent, 'feGaussianBlur', $.extend(
+ {result: args.result, in_: args.in1, stdDeviation: args.stdDevX +
+ (args.stdDevY ? ' ' + args.stdDevY : '')}, args.settings || {}));
+ },
+
+ /* Add an image filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param href (string) the URL of the image
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ image: function(parent, result, href, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'href']);
+ var node = this._wrapper._makeNode(args.parent, 'feImage', $.extend(
+ {result: args.result}, args.settings || {}));
+ node.setAttributeNS($.svg.xlinkNS, 'href', args.href);
+ return node;
+ },
+
+ /* Add a merge filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param refs (string[]) the IDs of the filters to merge
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ merge: function(parent, result, refs, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'refs']);
+ var node = this._wrapper._makeNode(args.parent, 'feMerge', $.extend(
+ {result: args.result}, args.settings || {}));
+ for (var i = 0; i < args.refs.length; i++) {
+ this._wrapper._makeNode(node, 'feMergeNode', {in_: args.refs[i]});
+ }
+ return node;
+ },
+
+ /* Add a morphology filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source filter
+ @param operator (string) erode | dilate
+ @param radiusX (number) the size of the operation in the x-axis
+ @param radiusY (number) the size of the operation in the y-axis (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ morphology: function(parent, result, in1, operator, radiusX, radiusY, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'in1',
+ 'operator', 'radiusX', 'radiusY'], ['radiusY']);
+ return this._wrapper._makeNode(args.parent, 'feMorphology', $.extend(
+ {result: args.result, in_: args.in1, operator: args.operator,
+ radius: args.radiusX + (args.radiusY ? ' ' + args.radiusY : '')},
+ args.settings || {}));
+ },
+
+ /* Add an offset filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source filter
+ @param dX (number) the offset in the x-axis
+ @param dY (number) the offset in the y-axis
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ offset: function(parent, result, in1, dx, dy, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'in1', 'dx', 'dy']);
+ return this._wrapper._makeNode(args.parent, 'feOffset', $.extend(
+ {result: args.result, in_: args.in1, dx: args.dx, dy: args.dy},
+ args.settings || {}));
+ },
+
+ /* Add a specular lighting filter.
+ Numeric params are only optional if following numeric params are also omitted.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source filter
+ @param surfaceScale (number) the surface height when Ain = 1 (optional)
+ @param specularConstant (number) the ks in Phong lighting model (optional)
+ @param specularExponent (number) the shininess 1.0-128.0 (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ specularLighting: function(parent, result, in1, surfaceScale,
+ specularConstant, specularExponent, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'in1',
+ 'surfaceScale', 'specularConstant', 'specularExponent'],
+ ['surfaceScale', 'specularConstant', 'specularExponent']);
+ return this._wrapper._makeNode(args.parent, 'feSpecularLighting', $.extend(
+ {result: args.result, in_: args.in1, surfaceScale: args.surfaceScale,
+ specularConstant: args.specularConstant, specularExponent: args.specularExponent},
+ args.settings || {}));
+ },
+
+ /* Add a tile filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param in1 (string) the source filter
+ @param x (number) the left coordinate of the rectangle
+ @param y (number) the top coordinate of the rectangle
+ @param width (number) the width of the rectangle
+ @param height (number) the height of the rectangle
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ tile: function(parent, result, in1, x, y, width, height, settings) {
+ var args = this._wrapper._args(arguments,
+ ['result', 'in1', 'x', 'y', 'width', 'height']);
+ return this._wrapper._makeNode(args.parent, 'feTile', $.extend(
+ {result: args.result, in_: args.in1, x: args.x, y: args.y,
+ width: args.width, height: args.height}, args.settings || {}));
+ },
+
+ /* Add a turbulence filter.
+ @param parent (element or jQuery) the parent node for the new filter (optional)
+ @param result (string) the ID of this filter
+ @param type (string) fractalNoise | turbulence
+ @param baseFreq (number or 'number number') the base frequency,
+ optionally separated into x- and y-components
+ @param octaves (number) the amount of turbulence (optional)
+ @param settings (object) additional settings for the filter (optional)
+ @return (element) the new filter node */
+ turbulence: function(parent, result, type, baseFreq, octaves, settings) {
+ var args = this._wrapper._args(arguments, ['result', 'type',
+ 'baseFreq', 'octaves'], ['octaves']);
+ return this._wrapper._makeNode(args.parent, 'feTurbulence', $.extend(
+ {result: args.result, type: args.type, baseFrequency: args.baseFreq,
+ numOctaves: args.octaves}, args.settings || {}));
+ }
+});
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+ return (a && a.constructor == Array);
+}
+
+})(jQuery)
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svggraph.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svggraph.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,1482 @@
+/* http://keith-wood.name/svg.html
+ SVG graphing extension for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) August 2007.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+$.svg.addExtension('graph', SVGGraph);
+
+// Singleton primary SVG graphing interface
+$.svg.graphing = new SVGGraphing();
+
+function SVGGraphing() {
+ this.regional = [];
+ this.regional[''] = {percentageText: 'Percentage'};
+ this.region = this.regional[''];
+}
+
+$.extend(SVGGraphing.prototype, {
+ _chartTypes: [],
+
+ /* Add a new chart rendering type to the package.
+ The rendering object must implement the following functions:
+ getTitle(), getDescription(), getOptions(), drawChart(graph).
+ @param id (string) the ID of this graph renderer
+ @param chartType (object) the object implementing this chart type */
+ addChartType: function(id, chartType) {
+ this._chartTypes[id] = chartType;
+ },
+
+ /* Retrieve the list of chart types.
+ @return (object[string]) the array of chart types indexed by ID */
+ chartTypes: function() {
+ return this._chartTypes;
+ }
+});
+
+/* Extension point for SVG graphing.
+ Access through svg.graph. */
+function SVGGraph(wrapper) {
+ this._wrapper = wrapper; // The attached SVG wrapper object
+ this._drawNow = false; // True for immediate update, false to wait for redraw call
+ for (var id in $.svg.graphing._chartTypes) {
+ this._chartType = $.svg.graphing._chartTypes[id]; // Use first graph renderer
+ break;
+ }
+ this._chartOptions = {}; // Extra options for the graph type
+ // The graph title and settings
+ this._title = {value: '', offset: 25, settings: {textAnchor: 'middle'}};
+ this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom,
+ // > 1 in pixels, <= 1 as proportion
+ this._chartFormat = {fill: 'none', stroke: 'black'}; // The formatting for the chart area
+ this._gridlines = []; // The formatting of the x- and y-gridlines
+ this._series = []; // The series to be plotted, each is an object
+ this._onstatus = null; // The callback function for status updates
+ this._chartCont = this._wrapper.svg(0, 0, 0, 0, {class_: 'svg-graph'}); // The main container for the graph
+
+ this.xAxis = new SVGGraphAxis(this); // The main x-axis
+ this.xAxis.title('', 40);
+ this.yAxis = new SVGGraphAxis(this); // The main y-axis
+ this.yAxis.title('', 40);
+ this.x2Axis = null; // The secondary x-axis
+ this.y2Axis = null; // The secondary y-axis
+ this.legend = new SVGGraphLegend(this); // The chart legend
+ this._drawNow = true;
+}
+
+$.extend(SVGGraph.prototype, {
+
+ /* Useful indexes. */
+ X: 0,
+ Y: 1,
+ W: 2,
+ H: 3,
+ L: 0,
+ T: 1,
+ R: 2,
+ B: 3,
+
+ /* Standard percentage axis. */
+ _percentageAxis: new SVGGraphAxis(this, $.svg.graphing.region.percentageText, 0, 100, 10, 0),
+
+ /* Set or retrieve the container for the graph.
+ @param cont (SVG element) the container for the graph
+ @return (SVGGraph) this graph object or
+ (SVG element) the current container (if no parameters) */
+ container: function(cont) {
+ if (arguments.length == 0) {
+ return this._chartCont;
+ }
+ this._chartCont = cont;
+ return this;
+ },
+
+ /* Set or retrieve the type of chart to be rendered.
+ See $.svg.graphing.getChartTypes() for the list of available types.
+ @param id (string) the ID of the chart type
+ @param options (object) additional settings for this chart type (optional)
+ @return (SVGGraph) this graph object or
+ (string) the chart type (if no parameters)
+ @deprecated use type() */
+ chartType: function(id, options) {
+ return (arguments.length == 0 ? this.type() : this.type(id, options));
+ },
+
+ /* Set or retrieve the type of chart to be rendered.
+ See $.svg.graphing.getChartTypes() for the list of available types.
+ @param id (string) the ID of the chart type
+ @param options (object) additional settings for this chart type (optional)
+ @return (SVGGraph) this graph object or
+ (string) the chart type (if no parameters) */
+ type: function(id, options) {
+ if (arguments.length == 0) {
+ return this._chartType;
+ }
+ var chartType = $.svg.graphing._chartTypes[id];
+ if (chartType) {
+ this._chartType = chartType;
+ this._chartOptions = $.extend({}, options || {});
+ }
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve additional options for the particular chart type.
+ @param options (object) the extra options
+ @return (SVGGraph) this graph object or
+ (object) the chart options (if no parameters)
+ @deprecated use options() */
+ chartOptions: function(options) {
+ return(arguments.length == 0 ? this.options() : this.options(options));
+ },
+
+ /* Set or retrieve additional options for the particular chart type.
+ @param options (object) the extra options
+ @return (SVGGraph) this graph object or
+ (object) the chart options (if no parameters) */
+ options: function(options) {
+ if (arguments.length == 0) {
+ return this._chartOptions;
+ }
+ this._chartOptions = $.extend({}, options);
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the background of the graph chart.
+ @param fill (string) how to fill the chart background
+ @param stroke (string) the colour of the outline (optional)
+ @param settings (object) additional formatting for the chart background (optional)
+ @return (SVGGraph) this graph object or
+ (object) the chart format (if no parameters)
+ @deprecated use format() */
+ chartFormat: function(fill, stroke, settings) {
+ return (arguments.length == 0 ? this.format() : this.format(fill, stroke, settings));
+ },
+
+ /* Set or retrieve the background of the graph chart.
+ @param fill (string) how to fill the chart background
+ @param stroke (string) the colour of the outline (optional)
+ @param settings (object) additional formatting for the chart background (optional)
+ @return (SVGGraph) this graph object or
+ (object) the chart format (if no parameters) */
+ format: function(fill, stroke, settings) {
+ if (arguments.length == 0) {
+ return this._chartFormat;
+ }
+ if (typeof stroke == 'object') {
+ settings = stroke;
+ stroke = null;
+ }
+ this._chartFormat = $.extend({fill: fill},
+ (stroke ? {stroke: stroke} : {}), settings || {});
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the main chart area.
+ @param left (number) > 1 is pixels, <= 1 is proportion of width or
+ (number[4]) for left, top, right, bottom
+ @param top (number) > 1 is pixels, <= 1 is proportion of height
+ @param right (number) > 1 is pixels, <= 1 is proportion of width
+ @param bottom (number) > 1 is pixels, <= 1 is proportion of height
+ @return (SVGGraph) this graph object or
+ (number[4]) the chart area: left, top, right, bottom (if no parameters)
+ @deprecated use area() */
+ chartArea: function(left, top, right, bottom) {
+ return (arguments.length == 0 ? this.area() : this.area(left, top, right, bottom));
+ },
+
+ /* Set or retrieve the main chart area.
+ @param left (number) > 1 is pixels, <= 1 is proportion of width or
+ (number[4]) for left, top, right, bottom
+ @param top (number) > 1 is pixels, <= 1 is proportion of height
+ @param right (number) > 1 is pixels, <= 1 is proportion of width
+ @param bottom (number) > 1 is pixels, <= 1 is proportion of height
+ @return (SVGGraph) this graph object or
+ (number[4]) the chart area: left, top, right, bottom (if no parameters) */
+ area: function(left, top, right, bottom) {
+ if (arguments.length == 0) {
+ return this._area;
+ }
+ this._area = (isArray(left) ? left : [left, top, right, bottom]);
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the gridlines formatting for the graph chart.
+ @param xSettings (string) the colour of the gridlines along the x-axis, or
+ (object) formatting for the gridlines along the x-axis, or
+ null for none
+ @param ySettings (string) the colour of the gridlines along the y-axis, or
+ (object) formatting for the gridlines along the y-axis, or
+ null for none
+ @return (SVGGraph) this graph object or
+ (object[2]) the gridlines formatting (if no parameters) */
+ gridlines: function(xSettings, ySettings) {
+ if (arguments.length == 0) {
+ return this._gridlines;
+ }
+ this._gridlines = [(typeof xSettings == 'string' ? {stroke: xSettings} : xSettings),
+ (typeof ySettings == 'string' ? {stroke: ySettings} : ySettings)];
+ if (this._gridlines[0] == null && this._gridlines[1] == null) {
+ this._gridlines = [];
+ }
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the title of the graph and its formatting.
+ @param value (string) the title
+ @param offset (number) the vertical positioning of the title
+ > 1 is pixels, <= 1 is proportion of width (optional)
+ @param colour (string) the colour of the title (optional)
+ @param settings (object) formatting for the title (optional)
+ @return (SVGGraph) this graph object or
+ (object) value, offset, and settings for the title (if no parameters) */
+ title: function(value, offset, colour, settings) {
+ if (arguments.length == 0) {
+ return this._title;
+ }
+ if (typeof offset != 'number') {
+ settings = colour;
+ colour = offset;
+ offset = null;
+ }
+ if (typeof colour != 'string') {
+ settings = colour;
+ colour = null;
+ }
+ this._title = {value: value, offset: offset || this._title.offset,
+ settings: $.extend({textAnchor: 'middle'},
+ (colour ? {fill: colour} : {}), settings || {})};
+ this._drawGraph();
+ return this;
+ },
+
+ /* Add a series of values to be plotted on the graph.
+ @param name (string) the name of this series (optional)
+ @param values (number[]) the values to be plotted
+ @param fill (string) how the plotted values are filled
+ @param stroke (string) the colour of the plotted lines (optional)
+ @param strokeWidth (number) the width of the plotted lines (optional)
+ @param settings (object) additional settings for the plotted values (optional)
+ @return (SVGGraph) this graph object */
+ addSeries: function(name, values, fill, stroke, strokeWidth, settings) {
+ this._series.push(new SVGGraphSeries(
+ this, name, values, fill, stroke, strokeWidth, settings));
+ this._drawGraph();
+ return this;
+ },
+
+ /* Retrieve the series wrappers.
+ @param i (number) the series index (optional)
+ @return (SVGGraphSeries) the specified series or
+ (SVGGraphSeries[]) the list of series */
+ series: function(i) {
+ return (arguments.length > 0 ? this._series[i] : null) || this._series;
+ },
+
+ /* Suppress drawing of the graph until redraw() is called.
+ @return (SVGGraph) this graph object */
+ noDraw: function() {
+ this._drawNow = false;
+ return this;
+ },
+
+ /* Redraw the entire graph with the current settings and values.
+ @return (SVGGraph) this graph object */
+ redraw: function() {
+ this._drawNow = true;
+ this._drawGraph();
+ return this;
+ },
+
+ /* Set the callback function for status updates.
+ @param onstatus (function) the callback function
+ @return (SVGGraph) this graph object */
+ status: function(onstatus) {
+ this._onstatus = onstatus;
+ return this;
+ },
+
+ /* Actually draw the graph (if allowed) based on the graph type set. */
+ _drawGraph: function() {
+ if (!this._drawNow) {
+ return;
+ }
+ while (this._chartCont.firstChild) {
+ this._chartCont.removeChild(this._chartCont.firstChild);
+ }
+ if (!this._chartCont.parent) {
+ this._wrapper._svg.appendChild(this._chartCont);
+ }
+ // Set sizes if not already there
+ if (!this._chartCont.width) {
+ this._chartCont.setAttribute('width',
+ parseInt(this._chartCont.getAttribute('width'), 10) || this._wrapper._width());
+ }
+ else if (this._chartCont.width.baseVal) {
+ this._chartCont.width.baseVal.value =
+ this._chartCont.width.baseVal.value || this._wrapper._width();
+ }
+ else {
+ this._chartCont.width = this._chartCont.width || this._wrapper._width();
+ }
+ if (!this._chartCont.height) {
+ this._chartCont.setAttribute('height',
+ parseInt(this._chartCont.getAttribute('height'), 10) || this._wrapper._height());
+ }
+ else if (this._chartCont.height.baseVal) {
+ this._chartCont.height.baseVal.value =
+ this._chartCont.height.baseVal.value || this._wrapper._height();
+ }
+ else {
+ this._chartCont.height = this._chartCont.height || this._wrapper._height();
+ }
+ this._chartType.drawGraph(this);
+ },
+
+ /* Decode an attribute value.
+ @param node the node to examine
+ @param name the attribute name
+ @return the actual value */
+ _getValue: function(node, name) {
+ return (!node[name] ? parseInt(node.getAttribute(name), 10) :
+ (node[name].baseVal ? node[name].baseVal.value : node[name]));
+ },
+
+ /* Draw the graph title - centred. */
+ _drawTitle: function() {
+ this._wrapper.text(this._chartCont, this._getValue(this._chartCont, 'width') / 2,
+ this._title.offset, this._title.value, this._title.settings);
+ },
+
+ /* Calculate the actual dimensions of the chart area.
+ @param area (number[4]) the area values to evaluate (optional)
+ @return (number[4]) an array of dimension values: left, top, width, height */
+ _getDims: function(area) {
+ area = area || this._area;
+ var availWidth = this._getValue(this._chartCont, 'width');
+ var availHeight = this._getValue(this._chartCont, 'height');
+ var left = (area[this.L] > 1 ? area[this.L] : availWidth * area[this.L]);
+ var top = (area[this.T] > 1 ? area[this.T] : availHeight * area[this.T]);
+ var width = (area[this.R] > 1 ? area[this.R] : availWidth * area[this.R]) - left;
+ var height = (area[this.B] > 1 ? area[this.B] : availHeight * area[this.B]) - top;
+ return [left, top, width, height];
+ },
+
+ /* Draw the chart background, including gridlines.
+ @param noXGrid (boolean) true to suppress the x-gridlines, false to draw them (optional)
+ @param noYGrid (boolean) true to suppress the y-gridlines, false to draw them (optional)
+ @return (element) the background group element */
+ _drawChartBackground: function(noXGrid, noYGrid) {
+ var bg = this._wrapper.group(this._chartCont, {class_: 'background'});
+ var dims = this._getDims();
+ this._wrapper.rect(bg, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this._chartFormat);
+ if (this._gridlines[0] && this.yAxis._ticks.major && !noYGrid) {
+ this._drawGridlines(bg, this.yAxis, true, dims, this._gridlines[0]);
+ }
+ if (this._gridlines[1] && this.xAxis._ticks.major && !noXGrid) {
+ this._drawGridlines(bg, this.xAxis, false, dims, this._gridlines[1]);
+ }
+ return bg;
+ },
+
+ /* Draw one set of gridlines.
+ @param bg (element) the background group element
+ @param axis (SVGGraphAxis) the axis definition
+ @param horiz (boolean) true if horizontal, false if vertical
+ @param dims (number[]) the left, top, width, height of the chart area
+ @param format (object) additional settings for the gridlines */
+ _drawGridlines: function(bg, axis, horiz, dims, format) {
+ var g = this._wrapper.group(bg, format);
+ var scale = (horiz ? dims[this.H] : dims[this.W]) / (axis._scale.max - axis._scale.min);
+ var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
+ major = (major < axis._scale.min ? major + axis._ticks.major : major);
+ while (major <= axis._scale.max) {
+ var v = (horiz ? axis._scale.max - major : major - axis._scale.min) * scale +
+ (horiz ? dims[this.Y] : dims[this.X]);
+ this._wrapper.line(g, (horiz ? dims[this.X] : v), (horiz ? v : dims[this.Y]),
+ (horiz ? dims[this.X] + dims[this.W] : v), (horiz ? v : dims[this.Y] + dims[this.H]));
+ major += axis._ticks.major;
+ }
+ },
+
+ /* Draw the axes in their standard configuration.
+ @param noX (boolean) true to suppress the x-axes, false to draw it (optional) */
+ _drawAxes: function(noX) {
+ var dims = this._getDims();
+ if (this.xAxis && !noX) {
+ if (this.xAxis._title) {
+ this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2,
+ dims[this.Y] + dims[this.H] + this.xAxis._titleOffset,
+ this.xAxis._title, this.xAxis._titleFormat);
+ }
+ this._drawAxis(this.xAxis, 'xAxis', dims[this.X], dims[this.Y] + dims[this.H],
+ dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]);
+ }
+ if (this.yAxis) {
+ if (this.yAxis._title) {
+ this._wrapper.text(this._chartCont, 0, 0, this.yAxis._title, $.extend({textAnchor: 'middle',
+ transform: 'translate(' + (dims[this.X] - this.yAxis._titleOffset) + ',' +
+ (dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.yAxis._titleFormat || {}));
+ }
+ this._drawAxis(this.yAxis, 'yAxis', dims[this.X], dims[this.Y],
+ dims[this.X], dims[this.Y] + dims[this.H]);
+ }
+ if (this.x2Axis && !noX) {
+ if (this.x2Axis._title) {
+ this._wrapper.text(this._chartCont, dims[this.X] + dims[this.W] / 2,
+ dims[this.X] - this.x2Axis._titleOffset, this.x2Axis._title, this.x2Axis._titleFormat);
+ }
+ this._drawAxis(this.x2Axis, 'x2Axis', dims[this.X], dims[this.Y],
+ dims[this.X] + dims[this.W], dims[this.Y]);
+ }
+ if (this.y2Axis) {
+ if (this.y2Axis._title) {
+ this._wrapper.text(this._chartCont, 0, 0, this.y2Axis._title, $.extend({textAnchor: 'middle',
+ transform: 'translate(' + (dims[this.X] + dims[this.W] + this.y2Axis._titleOffset) +
+ ',' + (dims[this.Y] + dims[this.H] / 2) + ') rotate(-90)'}, this.y2Axis._titleFormat || {}));
+ }
+ this._drawAxis(this.y2Axis, 'y2Axis', dims[this.X] + dims[this.W], dims[this.Y],
+ dims[this.X] + dims[this.W], dims[this.Y] + dims[this.H]);
+ }
+ },
+
+ /* Draw an axis and its tick marks.
+ @param axis (SVGGraphAxis) the axis definition
+ @param id (string) the identifier for the axis group element
+ @param x1 (number) starting x-coodinate for the axis
+ @param y1 (number) starting y-coodinate for the axis
+ @param x2 (number) ending x-coodinate for the axis
+ @param y2 (number) ending y-coodinate for the axis */
+ _drawAxis: function(axis, id, x1, y1, x2, y2) {
+ var horiz = (y1 == y2);
+ var gl = this._wrapper.group(this._chartCont, $.extend({class_: id}, axis._lineFormat));
+ var gt = this._wrapper.group(this._chartCont, $.extend({class_: id + 'Labels',
+ textAnchor: (horiz ? 'middle' : 'end')}, axis._labelFormat));
+ this._wrapper.line(gl, x1, y1, x2, y2);
+ if (axis._ticks.major) {
+ var bottomRight = (x2 > (this._getValue(this._chartCont, 'width') / 2) &&
+ y2 > (this._getValue(this._chartCont, 'height') / 2));
+ var scale = (horiz ? x2 - x1 : y2 - y1) / (axis._scale.max - axis._scale.min);
+ var size = axis._ticks.size;
+ var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
+ major = (major < axis._scale.min ? major + axis._ticks.major : major);
+ var minor = (!axis._ticks.minor ? axis._scale.max + 1 :
+ Math.floor(axis._scale.min / axis._ticks.minor) * axis._ticks.minor);
+ minor = (minor < axis._scale.min ? minor + axis._ticks.minor : minor);
+ var offsets = this._getTickOffsets(axis, bottomRight);
+ var count = 0;
+ while (major <= axis._scale.max || minor <= axis._scale.max) {
+ var cur = Math.min(major, minor);
+ var len = (cur == major ? size : size / 2);
+ var v = (horiz ? x1 : y1) +
+ (horiz ? cur - axis._scale.min : axis._scale.max - cur) * scale;
+ this._wrapper.line(gl, (horiz ? v : x1 + len * offsets[0]),
+ (horiz ? y1 + len * offsets[0] : v),
+ (horiz ? v : x1 + len * offsets[1]),
+ (horiz ? y1 + len * offsets[1] : v));
+ if (cur == major) {
+ this._wrapper.text(gt, (horiz ? v : x1 - size), (horiz ? y1 + 2 * size : v),
+ (axis._labels ? axis._labels[count++] : '' + cur));
+ }
+ major += (cur == major ? axis._ticks.major : 0);
+ minor += (cur == minor ? axis._ticks.minor : 0);
+ }
+ }
+ },
+
+ /* Calculate offsets based on axis and tick positions.
+ @param axis (SVGGraphAxis) the axis definition
+ @param bottomRight (boolean) true if this axis is appearing on the bottom or
+ right of the chart area, false if to the top or left
+ @return (number[2]) the array of offset multipliers (-1..+1) */
+ _getTickOffsets: function(axis, bottomRight) {
+ return [(axis._ticks.position == (bottomRight ? 'in' : 'out') ||
+ axis._ticks.position == 'both' ? -1 : 0),
+ (axis._ticks.position == (bottomRight ? 'out' : 'in') ||
+ axis._ticks.position == 'both' ? +1 : 0), ];
+ },
+
+ /* Retrieve the standard percentage axis.
+ @return (SVGGraphAxis) percentage axis */
+ _getPercentageAxis: function() {
+ this._percentageAxis._title = $.svg.graphing.region.percentageText;
+ return this._percentageAxis;
+ },
+
+ /* Calculate the column totals across all the series. */
+ _getTotals: function() {
+ var totals = [];
+ var numVal = (this._series.length ? this._series[0]._values.length : 0);
+ for (var i = 0; i < numVal; i++) {
+ totals[i] = 0;
+ for (var j = 0; j < this._series.length; j++) {
+ totals[i] += this._series[j]._values[i];
+ }
+ }
+ return totals;
+ },
+
+ /* Draw the chart legend. */
+ _drawLegend: function() {
+ if (!this.legend._show) {
+ return;
+ }
+ var g = this._wrapper.group(this._chartCont, {class_: 'legend'});
+ var dims = this._getDims(this.legend._area);
+ this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H],
+ this.legend._bgSettings);
+ var horiz = dims[this.W] > dims[this.H];
+ var numSer = this._series.length;
+ var offset = (horiz ? dims[this.W] : dims[this.H]) / numSer;
+ var xBase = dims[this.X] + 5;
+ var yBase = dims[this.Y] + ((horiz ? dims[this.H] : offset) + this.legend._sampleSize) / 2;
+ for (var i = 0; i < numSer; i++) {
+ var series = this._series[i];
+ this._wrapper.rect(g, xBase + (horiz ? i * offset : 0),
+ yBase + (horiz ? 0 : i * offset) - this.legend._sampleSize,
+ this.legend._sampleSize, this.legend._sampleSize,
+ {fill: series._fill, stroke: series._stroke, strokeWidth: 1});
+ this._wrapper.text(g, xBase + (horiz ? i * offset : 0) + this.legend._sampleSize + 5,
+ yBase + (horiz ? 0 : i * offset), series._name, this.legend._textSettings);
+ }
+ },
+
+ /* Show the current value status on hover. */
+ _showStatus: function(elem, label, value) {
+ var status = this._onstatus;
+ if (this._onstatus) {
+ $(elem).hover(function() { status.apply(this, [label, value]); },
+ function() { status.apply(this, ['', 0]); });
+ }
+ }
+});
+
+/* Details about each graph series.
+ @param graph (SVGGraph) the owning graph
+ @param name (string) the name of this series (optional)
+ @param values (number[]) the list of values to be plotted
+ @param fill (string) how the series should be displayed
+ @param stroke (string) the colour of the (out)line for the series (optional)
+ @param strokeWidth (number) the width of the (out)line for the series (optional)
+ @param settings (object) additional formatting settings (optional)
+ @return (SVGGraphSeries) the new series object */
+function SVGGraphSeries(graph, name, values, fill, stroke, strokeWidth, settings) {
+ if (typeof name != 'string') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = fill;
+ fill = values;
+ values = name;
+ name = null;
+ }
+ if (typeof stroke != 'string') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = null;
+ }
+ if (typeof strokeWidth != 'number') {
+ settings = strokeWidth;
+ strokeWidth = null;
+ }
+ this._graph = graph; // The owning graph
+ this._name = name || ''; // The name of this series
+ this._values = values || []; // The list of values for this series
+ this._axis = 1; // Which axis this series applies to: 1 = primary, 2 = secondary
+ this._fill = fill || 'green'; // How the series is plotted
+ this._stroke = stroke || 'black'; // The colour for the (out)line
+ this._strokeWidth = strokeWidth || 1; // The (out)line width
+ this._settings = settings || {}; // Additional formatting settings for the series
+}
+
+$.extend(SVGGraphSeries.prototype, {
+
+ /* Set or retrieve the name for this series.
+ @param name (string) the series' name
+ @return (SVGGraphSeries) this series object or
+ (string) the series name (if no parameters) */
+ name: function(name) {
+ if (arguments.length == 0) {
+ return this._name;
+ }
+ this._name = name;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the values for this series.
+ @param name (string) the series' name (optional)
+ @param values (number[]) the values to be graphed
+ @return (SVGGraphSeries) this series object or
+ (number[]) the series values (if no parameters) */
+ values: function(name, values) {
+ if (arguments.length == 0) {
+ return this._values;
+ }
+ if (isArray(name)) {
+ values = name;
+ name = null;
+ }
+ this._name = name || this._name;
+ this._values = values;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the formatting for this series.
+ @param fill (string) how the values are filled when plotted
+ @param stroke (string) the (out)line colour (optional)
+ @param strokeWidth (number) the line's width (optional)
+ @param settings (object) additional formatting settings for the series (optional)
+ @return (SVGGraphSeries) this series object or
+ (object) formatting settings (if no parameters) */
+ format: function(fill, stroke, strokeWidth, settings) {
+ if (arguments.length == 0) {
+ return $.extend({fill: this._fill, stroke: this._stroke,
+ strokeWidth: this._strokeWidth}, this._settings);
+ }
+ if (typeof stroke != 'string') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = null;
+ }
+ if (typeof strokeWidth != 'number') {
+ settings = strokeWidth;
+ strokeWidth = null;
+ }
+ this._fill = fill || this._fill;
+ this._stroke = stroke || this._stroke;
+ this._strokeWidth = strokeWidth || this._strokeWidth;
+ $.extend(this._settings, settings || {});
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Return to the parent graph. */
+ end: function() {
+ return this._graph;
+ }
+});
+
+/* Details about each graph axis.
+ @param graph (SVGGraph) the owning graph
+ @param title (string) the title of the axis
+ @param min (number) the minimum value displayed on this axis
+ @param max (number) the maximum value displayed on this axis
+ @param major (number) the distance between major ticks
+ @param minor (number) the distance between minor ticks (optional)
+ @return (SVGGraphAxis) the new axis object */
+function SVGGraphAxis(graph, title, min, max, major, minor) {
+ this._graph = graph; // The owning graph
+ this._title = title || ''; // Title of this axis
+ this._titleFormat = {}; // Formatting settings for the title
+ this._titleOffset = 0; // The offset for positioning the title
+ this._labels = null; // List of labels for this axis - one per possible value across all series
+ this._labelFormat = {}; // Formatting settings for the labels
+ this._lineFormat = {stroke: 'black', strokeWidth: 1}; // Formatting settings for the axis lines
+ this._ticks = {major: major || 10, minor: minor || 0, size: 10, position: 'out'}; // Tick mark options
+ this._scale = {min: min || 0, max: max || 100}; // Axis scale settings
+ this._crossAt = 0; // Where this axis crosses the other one
+}
+
+$.extend(SVGGraphAxis.prototype, {
+
+ /* Set or retrieve the scale for this axis.
+ @param min (number) the minimum value shown
+ @param max (number) the maximum value shown
+ @return (SVGGraphAxis) this axis object or
+ (object) min and max values (if no parameters) */
+ scale: function(min, max) {
+ if (arguments.length == 0) {
+ return this._scale;
+ }
+ this._scale.min = min;
+ this._scale.max = max;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the ticks for this axis.
+ @param major (number) the distance between major ticks
+ @param minor (number) the distance between minor ticks
+ @param size (number) the length of the major ticks (minor are half) (optional)
+ @param position (string) the location of the ticks:
+ 'in', 'out', 'both' (optional)
+ @return (SVGGraphAxis) this axis object or
+ (object) major, minor, size, and position values (if no parameters) */
+ ticks: function(major, minor, size, position) {
+ if (arguments.length == 0) {
+ return this._ticks;
+ }
+ if (typeof size == 'string') {
+ position = size;
+ size = null;
+ }
+ this._ticks.major = major;
+ this._ticks.minor = minor;
+ this._ticks.size = size || this._ticks.size;
+ this._ticks.position = position || this._ticks.position;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the title for this axis.
+ @param title (string) the title text
+ @param offset (number) the distance to offset the title position (optional)
+ @param colour (string) how to colour the title (optional)
+ @param format (object) formatting settings for the title (optional)
+ @return (SVGGraphAxis) this axis object or
+ (object) title, offset, and format values (if no parameters) */
+ title: function(title, offset, colour, format) {
+ if (arguments.length == 0) {
+ return {title: this._title, offset: this._titleOffset, format: this._titleFormat};
+ }
+ if (typeof offset != 'number') {
+ format = colour;
+ colour = offset;
+ offset = null;
+ }
+ if (typeof colour != 'string') {
+ format = colour;
+ colour = null;
+ }
+ this._title = title;
+ this._titleOffset = (offset != null ? offset : this._titleOffset);
+ if (colour || format) {
+ this._titleFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
+ }
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the labels for this axis.
+ @param labels (string[]) the text for each entry
+ @param colour (string) how to colour the labels (optional)
+ @param format (object) formatting settings for the labels (optional)
+ @return (SVGGraphAxis) this axis object or
+ (object) labels and format values (if no parameters) */
+ labels: function(labels, colour, format) {
+ if (arguments.length == 0) {
+ return {labels: this._labels, format: this._labelFormat};
+ }
+ if (typeof colour != 'string') {
+ format = colour;
+ colour = null;
+ }
+ this._labels = labels;
+ if (colour || format) {
+ this._labelFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
+ }
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the line formatting for this axis.
+ @param colour (string) the line's colour
+ @param width (number) the line's width (optional)
+ @param settings (object) additional formatting settings for the line (optional)
+ @return (SVGGraphAxis) this axis object or
+ (object) line formatting values (if no parameters) */
+ line: function(colour, width, settings) {
+ if (arguments.length == 0) {
+ return this._lineFormat;
+ }
+ if (typeof width == 'object') {
+ settings = width;
+ width = null;
+ }
+ $.extend(this._lineFormat, {stroke: colour},
+ (width ? {strokeWidth: width} : {}), settings || {});
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Return to the parent graph. */
+ end: function() {
+ return this._graph;
+ }
+});
+
+/* Details about the graph legend.
+ @param graph (SVGGraph) the owning graph
+ @param bgSettings (object) additional formatting settings for the legend background (optional)
+ @param textSettings (object) additional formatting settings for the legend text (optional)
+ @return (SVGGraphLegend) the new legend object */
+function SVGGraphLegend(graph, bgSettings, textSettings) {
+ this._graph = graph; // The owning graph
+ this._show = true; // Show the legend?
+ this._area = [0.9, 0.1, 1.0, 0.9]; // The legend area: left, top, right, bottom,
+ // > 1 in pixels, <= 1 as proportion
+ this._sampleSize = 15; // Size of sample box
+ this._bgSettings = bgSettings || {stroke: 'gray'}; // Additional formatting settings for the legend background
+ this._textSettings = textSettings || {}; // Additional formatting settings for the text
+}
+
+$.extend(SVGGraphLegend.prototype, {
+
+ /* Set or retrieve whether the legend should be shown.
+ @param show (boolean) true to display it, false to hide it
+ @return (SVGGraphLegend) this legend object or
+ (boolean) show the legend? (if no parameters) */
+ show: function(show) {
+ if (arguments.length == 0) {
+ return this._show;
+ }
+ this._show = show;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve the legend area.
+ @param left (number) > 1 is pixels, <= 1 is proportion of width or
+ (number[4]) for left, top, right, bottom
+ @param top (number) > 1 is pixels, <= 1 is proportion of height
+ @param right (number) > 1 is pixels, <= 1 is proportion of width
+ @param bottom (number) > 1 is pixels, <= 1 is proportion of height
+ @return (SVGGraphLegend) this legend object or
+ (number[4]) the legend area: left, top, right, bottom (if no parameters) */
+ area: function(left, top, right, bottom) {
+ if (arguments.length == 0) {
+ return this._area;
+ }
+ this._area = (isArray(left) ? left : [left, top, right, bottom]);
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Set or retrieve additional settings for the legend area.
+ @param sampleSize (number) the size of the sample box to display (optional)
+ @param bgSettings (object) additional formatting settings for the legend background
+ @param textSettings (object) additional formatting settings for the legend text (optional)
+ @return (SVGGraphLegend) this legend object or
+ (object) bgSettings and textSettings for the legend (if no parameters) */
+ settings: function(sampleSize, bgSettings, textSettings) {
+ if (arguments.length == 0) {
+ return {sampleSize: this._sampleSize, bgSettings: this._bgSettings,
+ textSettings: this._textSettings};
+ }
+ if (typeof sampleSize != 'number') {
+ textSettings = bgSettings;
+ bgSettings = sampleSize;
+ sampleSize = null;
+ }
+ this._sampleSize = sampleSize || this._sampleSize;
+ this._bgSettings = bgSettings;
+ this._textSettings = textSettings || this._textSettings;
+ this._graph._drawGraph();
+ return this;
+ },
+
+ /* Return to the parent graph. */
+ end: function() {
+ return this._graph;
+ }
+});
+
+//==============================================================================
+
+/* Round a number to a given number of decimal points. */
+function roundNumber(num, dec) {
+ return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
+}
+
+var barOptions = ['barWidth (number) - the width of each bar',
+ 'barGap (number) - the gap between sets of bars'];
+
+//------------------------------------------------------------------------------
+
+/* Draw a standard grouped column bar chart. */
+function SVGColumnChart() {
+}
+
+$.extend(SVGColumnChart.prototype, {
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Basic column chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare sets of values as vertical bars with grouped categories.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return barOptions;
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ graph._drawChartBackground(true);
+ var barWidth = graph._chartOptions.barWidth || 10;
+ var barGap = graph._chartOptions.barGap || 10;
+ var numSer = graph._series.length;
+ var numVal = (numSer ? (graph._series[0])._values.length : 0);
+ var dims = graph._getDims();
+ var xScale = dims[graph.W] / ((numSer * barWidth + barGap) * numVal + barGap);
+ var yScale = dims[graph.H] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ for (var i = 0; i < numSer; i++) {
+ this._drawSeries(graph, i, numSer, barWidth, barGap, dims, xScale, yScale);
+ }
+ graph._drawTitle();
+ graph._drawAxes(true);
+ this._drawXAxis(graph, numSer, numVal, barWidth, barGap, dims, xScale);
+ graph._drawLegend();
+ },
+
+ /* Plot an individual series. */
+ _drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) {
+ var series = graph._series[cur];
+ var g = graph._wrapper.group(this._chart,
+ $.extend({class_: 'series' + cur, fill: series._fill, stroke: series._stroke,
+ strokeWidth: series._strokeWidth}, series._settings || {}));
+ for (var i = 0; i < series._values.length; i++) {
+ var r = graph._wrapper.rect(g,
+ dims[graph.X] + xScale * (barGap + i * (numSer * barWidth + barGap) + (cur * barWidth)),
+ dims[graph.Y] + yScale * (graph.yAxis._scale.max - series._values[i]),
+ xScale * barWidth, yScale * series._values[i]);
+ graph._showStatus(r, series._name, series._values[i]);
+ }
+ },
+
+ /* Draw the x-axis and its ticks. */
+ _drawXAxis: function(graph, numSer, numVal, barWidth, barGap, dims, xScale) {
+ var axis = graph.xAxis;
+ if (axis._title) {
+ graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
+ dims[graph.Y] + dims[graph.H] + axis._titleOffset,
+ axis._title, $.extend({textAnchor: 'middle'}, axis._titleFormat || {}));
+ }
+ var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxis'}, axis._lineFormat));
+ var gt = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxisLabels',
+ textAnchor: 'middle'}, axis._labelFormat));
+ graph._wrapper.line(gl, dims[graph.X], dims[graph.Y] + dims[graph.H],
+ dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
+ if (axis._ticks.major) {
+ var offsets = graph._getTickOffsets(axis, true);
+ for (var i = 1; i < numVal; i++) {
+ var x = dims[graph.X] + xScale * (barGap / 2 + i * (numSer * barWidth + barGap));
+ graph._wrapper.line(gl, x, dims[graph.Y] + dims[graph.H] + offsets[0] * axis._ticks.size,
+ x, dims[graph.Y] + dims[graph.H] + offsets[1] * axis._ticks.size);
+ }
+ for (var i = 0; i < numVal; i++) {
+ var x = dims[graph.X] + xScale * (barGap / 2 + (i + 0.5) * (numSer * barWidth + barGap));
+ graph._wrapper.text(gt, x, dims[graph.Y] + dims[graph.H] + 2 * axis._ticks.size,
+ (axis._labels ? axis._labels[i] : '' + i));
+ }
+ }
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Draw a stacked column bar chart. */
+function SVGStackedColumnChart() {
+}
+
+$.extend(SVGStackedColumnChart.prototype, {
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Stacked column chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare sets of values as vertical bars showing ' +
+ 'relative contributions to the whole for each category.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return barOptions;
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ var bg = graph._drawChartBackground(true, true);
+ var dims = graph._getDims();
+ if (graph._gridlines[0] && graph.xAxis._ticks.major) {
+ graph._drawGridlines(bg, graph._getPercentageAxis(), true, dims, graph._gridlines[0]);
+ }
+ var barWidth = graph._chartOptions.barWidth || 10;
+ var barGap = graph._chartOptions.barGap || 10;
+ var numSer = graph._series.length;
+ var numVal = (numSer ? (graph._series[0])._values.length : 0);
+ var xScale = dims[graph.W] / ((barWidth + barGap) * numVal + barGap);
+ var yScale = dims[graph.H];
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ this._drawColumns(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale);
+ graph._drawTitle();
+ graph._wrapper.text(graph._chartCont, 0, 0, $.svg.graphing.region.percentageText,
+ $.extend({textAnchor: 'middle', transform: 'translate(' +
+ (dims[graph.X] - graph.yAxis._titleOffset) + ',' +
+ (dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, graph.yAxis._titleFormat || {}));
+ var pAxis = $.extend({}, graph._getPercentageAxis());
+ $.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {});
+ graph._drawAxis(pAxis, 'yAxis', dims[graph.X], dims[graph.Y],
+ dims[graph.X], dims[graph.Y] + dims[graph.H]);
+ this._drawXAxis(graph, numVal, barWidth, barGap, dims, xScale);
+ graph._drawLegend();
+ },
+
+ /* Plot all of the columns. */
+ _drawColumns: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) {
+ var totals = graph._getTotals();
+ var accum = [];
+ for (var i = 0; i < numVal; i++) {
+ accum[i] = 0;
+ }
+ for (var s = 0; s < numSer; s++) {
+ var series = graph._series[s];
+ var g = graph._wrapper.group(this._chart,
+ $.extend({class_: 'series' + s, fill: series._fill,
+ stroke: series._stroke, strokeWidth: series._strokeWidth},
+ series._settings || {}));
+ for (var i = 0; i < series._values.length; i++) {
+ accum[i] += series._values[i];
+ var r = graph._wrapper.rect(g,
+ dims[graph.X] + xScale * (barGap + i * (barWidth + barGap)),
+ dims[graph.Y] + yScale * (totals[i] - accum[i]) / totals[i],
+ xScale * barWidth, yScale * series._values[i] / totals[i]);
+ graph._showStatus(r, series._name,
+ roundNumber(series._values[i] / totals[i] * 100, 2));
+ }
+ }
+ },
+
+ /* Draw the x-axis and its ticks. */
+ _drawXAxis: function(graph, numVal, barWidth, barGap, dims, xScale) {
+ var axis = graph.xAxis;
+ if (axis._title) {
+ graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
+ dims[graph.Y] + dims[graph.H] + axis._titleOffset,
+ axis._title, $.extend({textAnchor: 'middle'}, axis._titleFormat || {}));
+ }
+ var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxis'}, axis._lineFormat));
+ var gt = graph._wrapper.group(graph._chartCont, $.extend({class_: 'xAxisLabels',
+ textAnchor: 'middle'}, axis._labelFormat));
+ graph._wrapper.line(gl, dims[graph.X], dims[graph.Y] + dims[graph.H],
+ dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
+ if (axis._ticks.major) {
+ var offsets = graph._getTickOffsets(axis, true);
+ for (var i = 1; i < numVal; i++) {
+ var x = dims[graph.X] + xScale * (barGap / 2 + i * (barWidth + barGap));
+ graph._wrapper.line(gl, x, dims[graph.Y] + dims[graph.H] + offsets[0] * axis._ticks.size,
+ x, dims[graph.Y] + dims[graph.H] + offsets[1] * axis._ticks.size);
+ }
+ for (var i = 0; i < numVal; i++) {
+ var x = dims[graph.X] + xScale * (barGap / 2 + (i + 0.5) * (barWidth + barGap));
+ graph._wrapper.text(gt, x, dims[graph.Y] + dims[graph.H] + 2 * axis._ticks.size,
+ (axis._labels ? axis._labels[i] : '' + i));
+ }
+ }
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Draw a standard grouped row bar chart. */
+function SVGRowChart() {
+}
+
+$.extend(SVGRowChart.prototype, {
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Basic row chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare sets of values as horizontal rows with grouped categories.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return barOptions;
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ var bg = graph._drawChartBackground(true, true);
+ var dims = graph._getDims();
+ graph._drawGridlines(bg, graph.yAxis, false, dims, graph._gridlines[0]);
+ var barWidth = graph._chartOptions.barWidth || 10;
+ var barGap = graph._chartOptions.barGap || 10;
+ var numSer = graph._series.length;
+ var numVal = (numSer ? (graph._series[0])._values.length : 0);
+ var xScale = dims[graph.W] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
+ var yScale = dims[graph.H] / ((numSer * barWidth + barGap) * numVal + barGap);
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ for (var i = 0; i < numSer; i++) {
+ this._drawSeries(graph, i, numSer, barWidth, barGap, dims, xScale, yScale);
+ }
+ graph._drawTitle();
+ this._drawAxes(graph, numSer, numVal, barWidth, barGap, dims, yScale);
+ graph._drawLegend();
+ },
+
+ /* Plot an individual series. */
+ _drawSeries: function(graph, cur, numSer, barWidth, barGap, dims, xScale, yScale) {
+ var series = graph._series[cur];
+ var g = graph._wrapper.group(this._chart,
+ $.extend({class_: 'series' + cur, fill: series._fill,
+ stroke: series._stroke, strokeWidth: series._strokeWidth},
+ series._settings || {}));
+ for (var i = 0; i < series._values.length; i++) {
+ var r = graph._wrapper.rect(g,
+ dims[graph.X] + xScale * (0 - graph.yAxis._scale.min),
+ dims[graph.Y] + yScale * (barGap + i * (numSer * barWidth + barGap) + (cur * barWidth)),
+ xScale * series._values[i], yScale * barWidth);
+ graph._showStatus(r, series._name, series._values[i]);
+ }
+ },
+
+ /* Draw the axes for this graph. */
+ _drawAxes: function(graph, numSer, numVal, barWidth, barGap, dims, yScale) {
+ // X-axis
+ var axis = graph.yAxis;
+ if (axis) {
+ if (axis._title) {
+ graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
+ dims[graph.Y] + dims[graph.H] + axis._titleOffset, axis._title, axis._titleFormat);
+ }
+ graph._drawAxis(axis, 'xAxis', dims[graph.X], dims[graph.Y] + dims[graph.H],
+ dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
+ }
+ // Y-axis
+ var axis = graph.xAxis;
+ if (axis._title) {
+ graph._wrapper.text(graph._chartCont, 0, 0, axis._title, $.extend({textAnchor: 'middle',
+ transform: 'translate(' + (dims[graph.X] - axis._titleOffset) + ',' +
+ (dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, axis._titleFormat || {}));
+ }
+ var gl = graph._wrapper.group(graph._chartCont, $.extend({class_: 'yAxis'}, axis._lineFormat));
+ var gt = graph._wrapper.group(graph._chartCont, $.extend(
+ {class_: 'yAxisLabels', textAnchor: 'end'}, axis._labelFormat));
+ graph._wrapper.line(gl, dims[graph.X], dims[graph.Y], dims[graph.X], dims[graph.Y] + dims[graph.H]);
+ if (axis._ticks.major) {
+ var offsets = graph._getTickOffsets(axis, false);
+ for (var i = 1; i < numVal; i++) {
+ var y = dims[graph.Y] + yScale * (barGap / 2 + i * (numSer * barWidth + barGap));
+ graph._wrapper.line(gl, dims[graph.X] + offsets[0] * axis._ticks.size, y,
+ dims[graph.X] + offsets[1] * axis._ticks.size, y);
+ }
+ for (var i = 0; i < numVal; i++) {
+ var y = dims[graph.Y] + yScale * (barGap / 2 + (i + 0.5) * (numSer * barWidth + barGap));
+ graph._wrapper.text(gt, dims[graph.X] - axis._ticks.size, y,
+ (axis._labels ? axis._labels[i] : '' + i));
+ }
+ }
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Draw a stacked row bar chart. */
+function SVGStackedRowChart() {
+}
+
+$.extend(SVGStackedRowChart.prototype, {
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Stacked row chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare sets of values as horizontal bars showing ' +
+ 'relative contributions to the whole for each category.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return barOptions;
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ var bg = graph._drawChartBackground(true, true);
+ var dims = graph._getDims();
+ if (graph._gridlines[0] && graph.xAxis._ticks.major) {
+ graph._drawGridlines(bg, graph._getPercentageAxis(), false, dims, graph._gridlines[0]);
+ }
+ var barWidth = graph._chartOptions.barWidth || 10;
+ var barGap = graph._chartOptions.barGap || 10;
+ var numSer = graph._series.length;
+ var numVal = (numSer ? (graph._series[0])._values.length : 0);
+ var xScale = dims[graph.W];
+ var yScale = dims[graph.H] / ((barWidth + barGap) * numVal + barGap);
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ this._drawRows(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale);
+ graph._drawTitle();
+ graph._wrapper.text(graph._chartCont, dims[graph.X] + dims[graph.W] / 2,
+ dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset,
+ $.svg.graphing.region.percentageText,
+ $.extend({textAnchor: 'middle'}, graph.yAxis._titleFormat || {}));
+ var pAxis = $.extend({}, graph._getPercentageAxis());
+ $.extend(pAxis._labelFormat, graph.yAxis._labelFormat || {});
+ graph._drawAxis(pAxis, 'xAxis', dims[graph.X], dims[graph.Y] + dims[graph.H],
+ dims[graph.X] + dims[graph.W], dims[graph.Y] + dims[graph.H]);
+ this._drawYAxis(graph, numVal, barWidth, barGap, dims, yScale);
+ graph._drawLegend();
+ },
+
+ /* Plot all of the rows. */
+ _drawRows: function(graph, numSer, numVal, barWidth, barGap, dims, xScale, yScale) {
+ var totals = graph._getTotals();
+ var accum = [];
+ for (var i = 0; i < numVal; i++) {
+ accum[i] = 0;
+ }
+ for (var s = 0; s < numSer; s++) {
+ var series = graph._series[s];
+ var g = graph._wrapper.group(this._chart,
+ $.extend({class_: 'series' + s, fill: series._fill,
+ stroke: series._stroke, strokeWidth: series._strokeWidth},
+ series._settings || {}));
+ for (var i = 0; i < series._values.length; i++) {
+ var r = graph._wrapper.rect(g,
+ dims[graph.X] + xScale * accum[i] / totals[i],
+ dims[graph.Y] + yScale * (barGap + i * (barWidth + barGap)),
+ xScale * series._values[i] / totals[i], yScale * barWidth);
+ graph._showStatus(r, series._name,
+ roundNumber(series._values[i] / totals[i] * 100, 2));
+ accum[i] += series._values[i];
+ }
+ }
+ },
+
+ /* Draw the y-axis and its ticks. */
+ _drawYAxis: function(graph, numVal, barWidth, barGap, dims, yScale) {
+ var axis = graph.xAxis;
+ if (axis._title) {
+ graph._wrapper.text(graph._chartCont, 0, 0, axis._title, $.extend({textAnchor: 'middle',
+ transform: 'translate(' + (dims[graph.X] - axis._titleOffset) + ',' +
+ (dims[graph.Y] + dims[graph.H] / 2) + ') rotate(-90)'}, axis._titleFormat || {}));
+ }
+ var gl = graph._wrapper.group(graph._chartCont,
+ $.extend({class_: 'yAxis'}, axis._lineFormat));
+ var gt = graph._wrapper.group(graph._chartCont,
+ $.extend({class_: 'yAxisLabels', textAnchor: 'end'}, axis._labelFormat));
+ graph._wrapper.line(gl, dims[graph.X], dims[graph.Y],
+ dims[graph.X], dims[graph.Y] + dims[graph.H]);
+ if (axis._ticks.major) {
+ var offsets = graph._getTickOffsets(axis, false);
+ for (var i = 1; i < numVal; i++) {
+ var y = dims[graph.Y] + yScale * (barGap / 2 + i * (barWidth + barGap));
+ graph._wrapper.line(gl, dims[graph.X] + offsets[0] * axis._ticks.size, y,
+ dims[graph.X] + offsets[1] * axis._ticks.size, y);
+ }
+ for (var i = 0; i < numVal; i++) {
+ var y = dims[graph.Y] + yScale * (barGap / 2 + (i + 0.5) * (barWidth + barGap));
+ graph._wrapper.text(gt, dims[graph.X] - axis._ticks.size, y,
+ (axis._labels ? axis._labels[i] : '' + i));
+ }
+ }
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Draw a standard line chart. */
+function SVGLineChart() {
+}
+
+$.extend(SVGLineChart.prototype, {
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Basic line chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare sets of values as continuous lines.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return [];
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ graph._drawChartBackground();
+ var dims = graph._getDims();
+ var xScale = dims[graph.W] / (graph.xAxis._scale.max - graph.xAxis._scale.min);
+ var yScale = dims[graph.H] / (graph.yAxis._scale.max - graph.yAxis._scale.min);
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ for (var i = 0; i < graph._series.length; i++) {
+ this._drawSeries(graph, i, dims, xScale, yScale);
+ }
+ graph._drawTitle();
+ graph._drawAxes();
+ graph._drawLegend();
+ },
+
+ /* Plot an individual series. */
+ _drawSeries: function(graph, cur, dims, xScale, yScale) {
+ var series = graph._series[cur];
+ var path = graph._wrapper.createPath();
+ for (var i = 0; i < series._values.length; i++) {
+ var x = dims[graph.X] + i * xScale;
+ var y = dims[graph.Y] + (graph.yAxis._scale.max - series._values[i]) * yScale;
+ if (i == 0) {
+ path.move(x, y);
+ }
+ else {
+ path.line(x, y);
+ }
+ }
+ var p = graph._wrapper.path(this._chart, path,
+ $.extend({id: 'series' + cur, fill: 'none', stroke: series._stroke,
+ strokeWidth: series._strokeWidth}, series._settings || {}));
+ graph._showStatus(p, series._name, 0);
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Draw a standard pie chart. */
+function SVGPieChart() {
+}
+
+$.extend(SVGPieChart.prototype, {
+
+ _options: ['explode (number or number[]) - indexes of sections to explode out of the pie',
+ 'explodeDist (number) - the distance to move an exploded section',
+ 'pieGap (number) - the distance between pies for multiple values'],
+
+ /* Retrieve the display title for this chart type.
+ @return the title */
+ title: function() {
+ return 'Pie chart';
+ },
+
+ /* Retrieve a description of this chart type.
+ @return its description */
+ description: function() {
+ return 'Compare relative sizes of values as contributions to the whole.';
+ },
+
+ /* Retrieve a list of the options that may be set for this chart type.
+ @return options list */
+ options: function() {
+ return this._options;
+ },
+
+ /* Actually draw the graph in this type's style.
+ @param graph (object) the SVGGraph object */
+ drawGraph: function(graph) {
+ graph._drawChartBackground(true, true);
+ this._chart = graph._wrapper.group(graph._chartCont, {class_: 'chart'});
+ var dims = graph._getDims();
+ this._drawSeries(graph, dims);
+ graph._drawTitle();
+ graph._drawLegend();
+ },
+
+ /* Plot all the series. */
+ _drawSeries: function(graph, dims) {
+ var totals = graph._getTotals();
+ var numSer = graph._series.length;
+ var numVal = (numSer ? (graph._series[0])._values.length : 0);
+ var path = graph._wrapper.createPath();
+ var explode = graph._chartOptions.explode || [];
+ explode = (isArray(explode) ? explode : [explode]);
+ var explodeDist = graph._chartOptions.explodeDist || 10;
+ var pieGap = (numVal <= 1 ? 0 : graph._chartOptions.pieGap || 10);
+ var xBase = (dims[graph.W] - (numVal * pieGap) - pieGap) / numVal / 2;
+ var yBase = dims[graph.H] / 2;
+ var radius = Math.min(xBase, yBase) - (explode.length > 0 ? explodeDist : 0);
+ var gt = graph._wrapper.group(graph._chartCont, $.extend(
+ {class_: 'xAxisLabels', textAnchor: 'middle'}, graph.xAxis._labelFormat));
+ var gl = [];
+ for (var i = 0; i < numVal; i++) {
+ var cx = dims[graph.X] + xBase + (i * (2 * Math.min(xBase, yBase) + pieGap)) + pieGap;
+ var cy = dims[graph.Y] + yBase;
+ var curTotal = 0;
+ for (var j = 0; j < numSer; j++) {
+ var series = graph._series[j];
+ if (i == 0) {
+ gl[j] = graph._wrapper.group(this._chart, $.extend({class_: 'series' + j,
+ fill: series._fill, stroke: series._stroke,
+ strokeWidth: series._strokeWidth}, series._settings || {}));
+ }
+ if (series._values[i] == 0) {
+ continue;
+ }
+ var start = (curTotal / totals[i]) * 2 * Math.PI;
+ curTotal += series._values[i];
+ var end = (curTotal / totals[i]) * 2 * Math.PI;
+ var exploding = false;
+ for (var k = 0; k < explode.length; k++) {
+ if (explode[k] == j) {
+ exploding = true;
+ break;
+ }
+ }
+ var x = cx + (exploding ? explodeDist * Math.cos((start + end) / 2) : 0);
+ var y = cy + (exploding ? explodeDist * Math.sin((start + end) / 2) : 0);
+ var p = graph._wrapper.path(gl[j], path.reset().move(x, y).
+ line(x + radius * Math.cos(start), y + radius * Math.sin(start)).
+ arc(radius, radius, 0, (end - start < Math.PI ? 0 : 1), 1,
+ x + radius * Math.cos(end), y + radius * Math.sin(end)).close());
+ graph._showStatus(p, series._name,
+ roundNumber((end - start) / 2 / Math.PI * 100, 2));
+ }
+ if (graph.xAxis) {
+ graph._wrapper.text(gt, cx, dims[graph.Y] + dims[graph.H] + graph.xAxis._titleOffset,
+ graph.xAxis._labels[i])
+ }
+ }
+ }
+});
+
+//------------------------------------------------------------------------------
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+ return (a && a.constructor == Array);
+}
+
+// Basic chart types
+$.svg.graphing.addChartType('column', new SVGColumnChart());
+$.svg.graphing.addChartType('stackedColumn', new SVGStackedColumnChart());
+$.svg.graphing.addChartType('row', new SVGRowChart());
+$.svg.graphing.addChartType('stackedRow', new SVGStackedRowChart());
+$.svg.graphing.addChartType('line', new SVGLineChart());
+$.svg.graphing.addChartType('pie', new SVGPieChart());
+
+})(jQuery)
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/jquery.svgplot.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/jquery.svgplot.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,817 @@
+/* http://keith-wood.name/svg.html
+ SVG plotting extension for jQuery v1.4.3.
+ Written by Keith Wood (kbwood{at}iinet.com.au) December 2008.
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
+ Please attribute the author if you use it. */
+
+(function($) { // Hide scope, no $ conflict
+
+$.svg.addExtension('plot', SVGPlot);
+
+/* Extension point for SVG plotting.
+ Access through svg.plot. */
+function SVGPlot(wrapper) {
+ this._wrapper = wrapper; // The attached SVG wrapper object
+ this._drawNow = false; // True for immediate update, false to wait for redraw call
+ // The plot title and settings
+ this._title = {value: '', offset: 25, settings: {textAnchor: 'middle'}};
+ this._area = [0.1, 0.1, 0.8, 0.9]; // The chart area: left, top, right, bottom,
+ // > 1 in pixels, <= 1 as proportion
+ this._areaFormat = {fill: 'none', stroke: 'black'}; // The formatting for the plot area
+ this._gridlines = []; // The formatting of the x- and y-gridlines
+ this._equalXY = true; // True for equal-sized x- and y-units, false to fill available space
+ this._functions = []; // The functions to be plotted, each is an object
+ this._onstatus = null; // The callback function for status updates
+ this._uuid = new Date().getTime();
+ this._plotCont = this._wrapper.svg(0, 0, 0, 0, {class_: 'svg-plot'}); // The main container for the plot
+
+ this.xAxis = new SVGPlotAxis(this); // The main x-axis
+ this.xAxis.title('X', 20);
+ this.yAxis = new SVGPlotAxis(this); // The main y-axis
+ this.yAxis.title('Y', 20);
+ this.legend = new SVGPlotLegend(this); // The plot legend
+ this._drawNow = true;
+}
+
+$.extend(SVGPlot.prototype, {
+
+ /* Useful indexes. */
+ X: 0,
+ Y: 1,
+ W: 2,
+ H: 3,
+ L: 0,
+ T: 1,
+ R: 2,
+ B: 3,
+
+ /* Set or retrieve the container for the plot.
+ @param cont (SVG element) the container for the plot
+ @return (SVGPlot) this plot object or
+ (SVG element) the current container (if no parameters) */
+ container: function(cont) {
+ if (arguments.length == 0) {
+ return this._plotCont;
+ }
+ this._plotCont = cont;
+ return this;
+ },
+
+ /* Set or retrieve the main plotting area.
+ @param left (number) > 1 is pixels, <= 1 is proportion of width or
+ (number[4]) for left, top, right, bottom
+ @param top (number) > 1 is pixels, <= 1 is proportion of height
+ @param right (number) > 1 is pixels, <= 1 is proportion of width
+ @param bottom (number) > 1 is pixels, <= 1 is proportion of height
+ @return (SVGPlot) this plot object or
+ (number[4]) the plotting area: left, top, right, bottom (if no parameters) */
+ area: function(left, top, right, bottom) {
+ if (arguments.length == 0) {
+ return this._area;
+ }
+ this._area = (isArray(left) ? left : [left, top, right, bottom]);
+ this._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the background of the plot area.
+ @param fill (string) how to fill the area background
+ @param stroke (string) the colour of the outline (optional)
+ @param settings (object) additional formatting for the area background (optional)
+ @return (SVGPlot) this plot object or
+ (object) the area format (if no parameters) */
+ format: function(fill, stroke, settings) {
+ if (arguments.length == 0) {
+ return this._areaFormat;
+ }
+ if (typeof stroke == 'object') {
+ settings = stroke;
+ stroke = null;
+ }
+ this._areaFormat = $.extend({fill: fill},
+ (stroke ? {stroke: stroke} : {}), settings || {});
+ this._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the gridlines formatting for the plot area.
+ @param xSettings (string) the colour of the gridlines along the x-axis, or
+ (object) formatting for the gridlines along the x-axis, or
+ null for none
+ @param ySettings (string) the colour of the gridlines along the y-axis, or
+ (object) formatting for the gridlines along the y-axis, or
+ null for none
+ @return (SVGPlot) this plot object or
+ (object[2]) the gridlines formatting (if no parameters) */
+ gridlines: function(xSettings, ySettings) {
+ if (arguments.length == 0) {
+ return this._gridlines;
+ }
+ this._gridlines = [(typeof xSettings == 'string' ? {stroke: xSettings} : xSettings),
+ (typeof ySettings == 'string' ? {stroke: ySettings} : ySettings)];
+ if (this._gridlines[0] == null && this._gridlines[1] == null) {
+ this._gridlines = [];
+ }
+ this._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the equality of the x- and y-axes.
+ @param value (boolean) true for equal x- and y-units, false to fill the available space
+ @return (SVGPlot) this plot object or
+ (boolean) the current setting (if no parameters) */
+ equalXY: function(value) {
+ if (arguments.length == 0) {
+ return this._equalXY;
+ }
+ this._equalXY = value;
+ return this;
+ },
+
+ /* Set or retrieve the title of the plot and its formatting.
+ @param value (string) the title
+ @param offset (number) the vertical positioning of the title
+ > 1 is pixels, <= 1 is proportion of width (optional)
+ @param colour (string) the colour of the title (optional)
+ @param settings (object) formatting for the title (optional)
+ @return (SVGPlot) this plot object or
+ (object) value, offset, and settings for the title (if no parameters) */
+ title: function(value, offset, colour, settings) {
+ if (arguments.length == 0) {
+ return this._title;
+ }
+ if (typeof offset != 'number') {
+ settings = colour;
+ colour = offset;
+ offset = null;
+ }
+ if (typeof colour != 'string') {
+ settings = colour;
+ colour = null;
+ }
+ this._title = {value: value, offset: offset || this._title.offset,
+ settings: $.extend({textAnchor: 'middle'},
+ (colour ? {fill: colour} : {}), settings || {})};
+ this._drawPlot();
+ return this;
+ },
+
+ /* Add a function to be plotted on the plot.
+ @param name (string) the name of this series (optional)
+ @param fn (function) the function to be plotted
+ @param range (number[2]) the range of values to plot (optional)
+ @param points (number) the number of points to plot within this range (optional)
+ @param stroke (string) the colour of the plotted lines (optional)
+ @param strokeWidth (number) the width of the plotted lines (optional)
+ @param settings (object) additional settings for the plotted values (optional)
+ @return (SVGPlot) this plot object */
+ addFunction: function(name, fn, range, points, stroke, strokeWidth, settings) {
+ this._functions.push(new SVGPlotFunction(
+ this, name, fn, range, points, stroke, strokeWidth, settings));
+ this._drawPlot();
+ return this;
+ },
+
+ /* Retrieve the function wrappers.
+ @param i (number) the function index (optional)
+ @return (SVGPlotFunction) the specified function or
+ (SVGPlotFunction[]) the list of functions */
+ functions: function(i) {
+ return (arguments.length > 0 ? this._functions[i] : null) || this._functions;
+ },
+
+ /* Suppress drawing of the plot until redraw() is called.
+ @return (SVGPlot) this plot object */
+ noDraw: function() {
+ this._drawNow = false;
+ return this;
+ },
+
+ /* Redraw the entire plot with the current settings and values.
+ @return (SVGPlot) this plot object */
+ redraw: function() {
+ this._drawNow = true;
+ this._drawPlot();
+ return this;
+ },
+
+ /* Set the callback function for status updates.
+ @param onstatus (function) the callback function
+ @return (SVGPlot) this plot object */
+ status: function(onstatus) {
+ this._onstatus = onstatus;
+ return this;
+ },
+
+ /* Actually draw the plot (if allowed). */
+ _drawPlot: function() {
+ if (!this._drawNow) {
+ return;
+ }
+ while (this._plotCont.firstChild) {
+ this._plotCont.removeChild(this._plotCont.firstChild);
+ }
+ if (!this._plotCont.parent) {
+ this._wrapper._svg.appendChild(this._plotCont);
+ }
+ // Set sizes if not already there
+ if (!this._plotCont.width) {
+ this._plotCont.setAttribute('width',
+ parseInt(this._plotCont.getAttribute('width'), 10) || this._wrapper._width());
+ }
+ else if (this._plotCont.width.baseVal) {
+ this._plotCont.width.baseVal.value =
+ this._plotCont.width.baseVal.value || this._wrapper._width();
+ }
+ else {
+ this._plotCont.width = this._plotCont.width || this._wrapper._width();
+ }
+ if (!this._plotCont.height) {
+ this._plotCont.setAttribute('height',
+ parseInt(this._plotCont.getAttribute('height'), 10) || this._wrapper._height());
+ }
+ else if (this._plotCont.height.baseVal) {
+ this._plotCont.height.baseVal.value =
+ this._plotCont.height.baseVal.value || this._wrapper._height();
+ }
+ else {
+ this._plotCont.height = this._plotCont.height || this._wrapper._height();
+ }
+ this._drawChartBackground();
+ var dims = this._getDims();
+ var clip = this._wrapper.other(this._plotCont, 'clipPath', {id: 'clip' + this._uuid});
+ this._wrapper.rect(clip, dims[this.X], dims[this.Y], dims[this.W], dims[this.H]);
+ this._plot = this._wrapper.group(this._plotCont,
+ {class_: 'foreground', clipPath: 'url(#clip' + this._uuid + ')'});
+ this._drawAxis(true);
+ this._drawAxis(false);
+ for (var i = 0; i < this._functions.length; i++) {
+ this._plotFunction(this._functions[i], i);
+ }
+ this._drawTitle();
+ this._drawLegend();
+ },
+
+ /* Decode an attribute value.
+ @param node the node to examine
+ @param name the attribute name
+ @return the actual value */
+ _getValue: function(node, name) {
+ return (!node[name] ? parseInt(node.getAttribute(name), 10) :
+ (node[name].baseVal ? node[name].baseVal.value : node[name]));
+ },
+
+ /* Calculate the actual dimensions of the plot area.
+ @param area (number[4]) the area values to evaluate (optional)
+ @return (number[4]) an array of dimension values: left, top, width, height */
+ _getDims: function(area) {
+ var otherArea = (area != null);
+ area = area || this._area;
+ var availWidth = this._getValue(this._plotCont, 'width');
+ var availHeight = this._getValue(this._plotCont, 'height');
+ var left = (area[this.L] > 1 ? area[this.L] : availWidth * area[this.L]);
+ var top = (area[this.T] > 1 ? area[this.T] : availHeight * area[this.T]);
+ var width = (area[this.R] > 1 ? area[this.R] : availWidth * area[this.R]) - left;
+ var height = (area[this.B] > 1 ? area[this.B] : availHeight * area[this.B]) - top;
+ if (this._equalXY && !otherArea) {
+ var scale = Math.min(width / (this.xAxis._scale.max - this.xAxis._scale.min),
+ height / (this.yAxis._scale.max - this.yAxis._scale.min));
+ width = scale * (this.xAxis._scale.max - this.xAxis._scale.min);
+ height = scale * (this.yAxis._scale.max - this.yAxis._scale.min);
+ }
+ return [left, top, width, height];
+ },
+
+ /* Calculate the scaling factors for the plot area.
+ @return (number[2]) the x- and y-scaling factors */
+ _getScales: function() {
+ var dims = this._getDims();
+ return [dims[this.W] / (this.xAxis._scale.max - this.xAxis._scale.min),
+ dims[this.H] / (this.yAxis._scale.max - this.yAxis._scale.min)];
+ },
+
+ /* Draw the chart background, including gridlines.
+ @param noXGrid (boolean) true to suppress the x-gridlines, false to draw them (optional)
+ @param noYGrid (boolean) true to suppress the y-gridlines, false to draw them (optional)
+ @return (element) the background group element */
+ _drawChartBackground: function(noXGrid, noYGrid) {
+ var bg = this._wrapper.group(this._plotCont, {class_: 'background'});
+ var dims = this._getDims();
+ this._wrapper.rect(bg, dims[this.X], dims[this.Y], dims[this.W], dims[this.H], this._areaFormat);
+ if (this._gridlines[0] && this.yAxis._ticks.major && !noYGrid) {
+ this._drawGridlines(bg, true, this._gridlines[0], dims);
+ }
+ if (this._gridlines[1] && this.xAxis._ticks.major && !noXGrid) {
+ this._drawGridlines(bg, false, this._gridlines[1], dims);
+ }
+ return bg;
+ },
+
+ /* Draw one set of gridlines.
+ @param bg (element) the background group element
+ @param horiz (boolean) true if horizontal, false if vertical
+ @param format (object) additional settings for the gridlines */
+ _drawGridlines: function(bg, horiz, format, dims) {
+ var g = this._wrapper.group(bg, format);
+ var axis = (horiz ? this.yAxis : this.xAxis);
+ var scales = this._getScales();
+ var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
+ major += (major <= axis._scale.min ? axis._ticks.major : 0);
+ while (major < axis._scale.max) {
+ var v = (horiz ? axis._scale.max - major : major - axis._scale.min) *
+ scales[horiz ? 1 : 0] + (horiz ? dims[this.Y] : dims[this.X]);
+ this._wrapper.line(g, (horiz ? dims[this.X] : v), (horiz ? v : dims[this.Y]),
+ (horiz ? dims[this.X] + dims[this.W] : v), (horiz ? v : dims[this.Y] + dims[this.H]));
+ major += axis._ticks.major;
+ }
+ },
+
+ /* Draw an axis, its tick marks, and title.
+ @param horiz (boolean) true for x-axis, false for y-axis */
+ _drawAxis: function(horiz) {
+ var id = (horiz ? 'x' : 'y') + 'Axis';
+ var axis = (horiz ? this.xAxis : this.yAxis);
+ var axis2 = (horiz ? this.yAxis : this.xAxis);
+ var dims = this._getDims();
+ var scales = this._getScales();
+ var gl = this._wrapper.group(this._plot, $.extend({class_: id}, axis._lineFormat));
+ var gt = this._wrapper.group(this._plot, $.extend({class_: id + 'Labels',
+ textAnchor: (horiz ? 'middle' : 'end')}, axis._labelFormat));
+ var zero = (horiz ? axis2._scale.max : -axis2._scale.min) *
+ scales[horiz ? 1 : 0] + (horiz ? dims[this.Y] : dims[this.X]);
+ this._wrapper.line(gl, (horiz ? dims[this.X] : zero), (horiz ? zero : dims[this.Y]),
+ (horiz ? dims[this.X] + dims[this.W] : zero),
+ (horiz ? zero : dims[this.Y] + dims[this.H]));
+ if (axis._ticks.major) {
+ var size = axis._ticks.size;
+ var major = Math.floor(axis._scale.min / axis._ticks.major) * axis._ticks.major;
+ major = (major < axis._scale.min ? major + axis._ticks.major : major);
+ var minor = (!axis._ticks.minor ? axis._scale.max + 1 :
+ Math.floor(axis._scale.min / axis._ticks.minor) * axis._ticks.minor);
+ minor = (minor < axis._scale.min ? minor + axis._ticks.minor : minor);
+ var offsets = [(axis._ticks.position == 'nw' || axis._ticks.position == 'both' ? -1 : 0),
+ (axis._ticks.position == 'se' || axis._ticks.position == 'both' ? +1 : 0)];
+ while (major <= axis._scale.max || minor <= axis._scale.max) {
+ var cur = Math.min(major, minor);
+ var len = (cur == major ? size : size / 2);
+ var xy = (horiz ? cur - axis._scale.min : axis._scale.max - cur) *
+ scales[horiz ? 0 : 1] + (horiz ? dims[this.X] : dims[this.Y]);
+ this._wrapper.line(gl, (horiz ? xy : zero + len * offsets[0]),
+ (horiz ? zero + len * offsets[0] : xy),
+ (horiz ? xy : zero + len * offsets[1]),
+ (horiz ? zero + len * offsets[1] : xy));
+ if (cur == major && cur != 0) {
+ this._wrapper.text(gt, (horiz ? xy : zero - size),
+ (horiz ? zero - size : xy), '' + cur);
+ }
+ major += (cur == major ? axis._ticks.major : 0);
+ minor += (cur == minor ? axis._ticks.minor : 0);
+ }
+ }
+ if (axis._title) {
+ if (horiz) {
+ this._wrapper.text(this._plotCont, dims[this.X] - axis._titleOffset,
+ zero, axis._title, $.extend({textAnchor: 'end'}, axis._titleFormat || {}));
+ }
+ else {
+ this._wrapper.text(this._plotCont, zero,
+ dims[this.Y] + dims[this.H] + axis._titleOffset,
+ axis._title, $.extend({textAnchor : 'middle'}, axis._titleFormat || {}));
+ }
+ }
+ },
+
+ /* Plot an individual function. */
+ _plotFunction: function(fn, cur) {
+ var dims = this._getDims();
+ var scales = this._getScales();
+ var path = this._wrapper.createPath();
+ var range = fn._range || [this.xAxis._scale.min, this.xAxis._scale.max];
+ var xScale = (range[1] - range[0]) / fn._points;
+ var first = true;
+ for (var i = 0; i <= fn._points; i++) {
+ var x = range[0] + i * xScale;
+ if (x > this.xAxis._scale.max + xScale) {
+ break;
+ }
+ if (x < this.xAxis._scale.min - xScale) {
+ continue;
+ }
+ var px = (x - this.xAxis._scale.min) * scales[0] + dims[this.X];
+ var py = dims[this.H] - ((fn._fn(x) - this.yAxis._scale.min) * scales[1]) + dims[this.Y];
+ path[(first ? 'move' : 'line') + 'To'](px, py);
+ first = false;
+ }
+ var p = this._wrapper.path(this._plot, path,
+ $.extend({class_: 'fn' + cur, fill: 'none', stroke: fn._stroke,
+ strokeWidth: fn._strokeWidth}, fn._settings || {}));
+ this._showStatus(p, fn._name);
+ },
+
+ /* Draw the plot title - centred. */
+ _drawTitle: function() {
+ this._wrapper.text(this._plotCont, this._getValue(this._plotCont, 'width') / 2,
+ this._title.offset, this._title.value, this._title.settings);
+ },
+
+ /* Draw the chart legend. */
+ _drawLegend: function() {
+ if (!this.legend._show) {
+ return;
+ }
+ var g = this._wrapper.group(this._plotCont, {class_: 'legend'});
+ var dims = this._getDims(this.legend._area);
+ this._wrapper.rect(g, dims[this.X], dims[this.Y], dims[this.W], dims[this.H],
+ this.legend._bgSettings);
+ var horiz = dims[this.W] > dims[this.H];
+ var numFn = this._functions.length;
+ var offset = (horiz ? dims[this.W] : dims[this.H]) / numFn;
+ var xBase = dims[this.X] + 5;
+ var yBase = dims[this.Y] + ((horiz ? dims[this.H] : offset) + this.legend._sampleSize) / 2;
+ for (var i = 0; i < numFn; i++) {
+ var fn = this._functions[i];
+ this._wrapper.rect(g, xBase + (horiz ? i * offset : 0),
+ yBase + (horiz ? 0 : i * offset) - this.legend._sampleSize,
+ this.legend._sampleSize, this.legend._sampleSize, {fill: fn._stroke});
+ this._wrapper.text(g, xBase + (horiz ? i * offset : 0) + this.legend._sampleSize + 5,
+ yBase + (horiz ? 0 : i * offset), fn._name, this.legend._textSettings);
+ }
+ },
+
+ /* Show the current value status on hover. */
+ _showStatus: function(elem, label) {
+ var status = this._onstatus;
+ if (this._onstatus) {
+ $(elem).hover(function(evt) { status.apply(this, [label]); },
+ function() { status.apply(this, ['']); });
+ }
+ }
+});
+
+/* Details about each plot function.
+ @param plot (SVGPlot) the owning plot
+ @param name (string) the name of this function (optional)
+ @param fn (function) the function to be plotted
+ @param range (number[2]) the range of values to be plotted (optional)
+ @param points (number) the number of points to plot within this range (optional)
+ @param stroke (string) the colour of the (out)line for the plot (optional)
+ @param strokeWidth (number) the width of the (out)line for the plot (optional)
+ @param settings (object) additional formatting settings (optional)
+ @return (SVGPlotFunction) the new plot function object */
+function SVGPlotFunction(plot, name, fn, range, points, stroke, strokeWidth, settings) {
+ if (typeof name != 'string') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = points;
+ points = range;
+ range = fn;
+ fn = name;
+ name = null;
+ }
+ if (!isArray(range)) {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = points;
+ points = range;
+ range = null;
+ }
+ if (typeof points != 'number') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = points;
+ points = null;
+ }
+ if (typeof stroke != 'string') {
+ settings = strokeWidth;
+ strokeWidth = stroke;
+ stroke = null;
+ }
+ if (typeof strokeWidth != 'number') {
+ settings = strokeWidth;
+ strokeWidth = null;
+ }
+ this._plot = plot; // The owning plot
+ this._name = name || ''; // Display name
+ this._fn = fn || identity; // The actual function: y = fn(x)
+ this._range = range; // The range of values plotted
+ this._points = points || 100; // The number of points plotted
+ this._stroke = stroke || 'black'; // The line colour
+ this._strokeWidth = strokeWidth || 1; // The line width
+ this._settings = settings || {}; // Any other settings
+}
+
+$.extend(SVGPlotFunction.prototype, {
+
+ /* Set or retrieve the name for this function.
+ @param name (string) the function's name
+ @return (SVGPlotFunction) this plot function object or
+ (string) the function name (if no parameters) */
+ name: function(name) {
+ if (arguments.length == 0) {
+ return this._name;
+ }
+ this._name = name;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the function to be plotted.
+ @param name (string) the function's name (optional)
+ @param fn (function) the function to be ploted
+ @return (SVGPlotFunction) this plot function object or
+ (function) the actual function (if no parameters) */
+ fn: function(name, fn) {
+ if (arguments.length == 0) {
+ return this._fn;
+ }
+ if (typeof name == 'function') {
+ fn = name;
+ name = null;
+ }
+ this._name = name || this._name;
+ this._fn = fn;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the range of values to be plotted.
+ @param min (number) the minimum value to be plotted
+ @param max (number) the maximum value to be plotted
+ @return (SVGPlotFunction) this plot function object or
+ (number[2]) the value range (if no parameters) */
+ range: function(min, max) {
+ if (arguments.length == 0) {
+ return this._range;
+ }
+ this._range = (min == null ? null : [min, max]);
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the number of points to be plotted.
+ @param value (number) the number of points to plot
+ @return (SVGPlotFunction) this plot function object or
+ (number) the number of points (if no parameters) */
+ points: function(value) {
+ if (arguments.length == 0) {
+ return this._points;
+ }
+ this._points = value;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the formatting for this function.
+ @param stroke (string) the (out)line colour
+ @param strokeWidth (number) the line's width (optional)
+ @param settings (object) additional formatting settings for the function (optional)
+ @return (SVGPlotFunction) this plot function object or
+ (object) formatting settings (if no parameters) */
+ format: function(stroke, strokeWidth, settings) {
+ if (arguments.length == 0) {
+ return $.extend({stroke: this._stroke,
+ strokeWidth: this._strokeWidth}, this._settings);
+ }
+ if (typeof strokeWidth != 'number') {
+ settings = strokeWidth;
+ strokeWidth = null;
+ }
+ this._stroke = stroke || this._stroke;
+ this._strokeWidth = strokeWidth || this._strokeWidth;
+ $.extend(this._settings, settings || {});
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Return to the parent plot. */
+ end: function() {
+ return this._plot;
+ }
+});
+
+/* Default function to plot.
+ @param x (number) the input value
+ @return (number) the same value */
+function identity(x) {
+ return x;
+}
+
+/* Details about each plot axis.
+ @param plot (SVGPlot) the owning plot
+ @param title (string) the title of the axis
+ @param min (number) the minimum value displayed on this axis
+ @param max (number) the maximum value displayed on this axis
+ @param major (number) the distance between major ticks
+ @param minor (number) the distance between minor ticks (optional)
+ @return (SVGPlotAxis) the new axis object */
+function SVGPlotAxis(plot, title, min, max, major, minor) {
+ this._plot = plot; // The owning plot
+ this._title = title || ''; // The plot's title
+ this._titleFormat = {}; // Formatting settings for the title
+ this._titleOffset = 0; // The offset for positioning the title
+ this._labelFormat = {}; // Formatting settings for the labels
+ this._lineFormat = {stroke: 'black', strokeWidth: 1}; // Formatting settings for the axis lines
+ this._ticks = {major: major || 10, minor: minor || 0, size: 10, position: 'both'}; // Tick mark options
+ this._scale = {min: min || 0, max: max || 100}; // Axis scale settings
+ this._crossAt = 0; // Where this axis crosses the other one. */
+}
+
+$.extend(SVGPlotAxis.prototype, {
+
+ /* Set or retrieve the scale for this axis.
+ @param min (number) the minimum value shown
+ @param max (number) the maximum value shown
+ @return (SVGPlotAxis) this axis object or
+ (object) min and max values (if no parameters) */
+ scale: function(min, max) {
+ if (arguments.length == 0) {
+ return this._scale;
+ }
+ this._scale.min = min;
+ this._scale.max = max;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the ticks for this axis.
+ @param major (number) the distance between major ticks
+ @param minor (number) the distance between minor ticks
+ @param size (number) the length of the major ticks (minor are half) (optional)
+ @param position (string) the location of the ticks:
+ 'nw', 'se', 'both' (optional)
+ @return (SVGPlotAxis) this axis object or
+ (object) major, minor, size, and position values (if no parameters) */
+ ticks: function(major, minor, size, position) {
+ if (arguments.length == 0) {
+ return this._ticks;
+ }
+ if (typeof size == 'string') {
+ position = size;
+ size = null;
+ }
+ this._ticks.major = major;
+ this._ticks.minor = minor;
+ this._ticks.size = size || this._ticks.size;
+ this._ticks.position = position || this._ticks.position;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the title for this axis.
+ @param title (string) the title text
+ @param offset (number) the distance to offset the title position (optional)
+ @param colour (string) how to colour the title (optional)
+ @param format (object) formatting settings for the title (optional)
+ @return (SVGPlotAxis) this axis object or
+ (object) title, offset, and format values (if no parameters) */
+ title: function(title, offset, colour, format) {
+ if (arguments.length == 0) {
+ return {title: this._title, offset: this._titleOffset, format: this._titleFormat};
+ }
+ if (typeof offset != 'number') {
+ format = colour;
+ colour = offset;
+ offset = null;
+ }
+ if (typeof colour != 'string') {
+ format = colour;
+ colour = null;
+ }
+ this._title = title;
+ this._titleOffset = (offset != null ? offset : this._titleOffset);
+ if (colour || format) {
+ this._titleFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
+ }
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the label format for this axis.
+ @param colour (string) how to colour the labels (optional)
+ @param format (object) formatting settings for the labels (optional)
+ @return (SVGPlotAxis) this axis object or
+ (object) format values (if no parameters) */
+ format: function(colour, format) {
+ if (arguments.length == 0) {
+ return this._labelFormat;
+ }
+ if (typeof colour != 'string') {
+ format = colour;
+ colour = null;
+ }
+ this._labelFormat = $.extend(format || {}, (colour ? {fill: colour} : {}));
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the line formatting for this axis.
+ @param colour (string) the line's colour
+ @param width (number) the line's width (optional)
+ @param settings (object) additional formatting settings for the line (optional)
+ @return (SVGPlotAxis) this axis object or
+ (object) line formatting values (if no parameters) */
+ line: function(colour, width, settings) {
+ if (arguments.length == 0) {
+ return this._lineFormat;
+ }
+ if (typeof width != 'number') {
+ settings = width;
+ width = null;
+ }
+ $.extend(this._lineFormat, {stroke: colour, strokeWidth:
+ width || this._lineFormat.strokeWidth}, settings || {});
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Return to the parent plot. */
+ end: function() {
+ return this._plot;
+ }
+});
+
+/* Details about the plot legend.
+ @param plot (SVGPlot) the owning plot
+ @param bgSettings (object) additional formatting settings for the legend background (optional)
+ @param textSettings (object) additional formatting settings for the legend text (optional)
+ @return (SVGPlotLegend) the new legend object */
+function SVGPlotLegend(plot, bgSettings, textSettings) {
+ this._plot = plot; // The owning plot
+ this._show = true; // Show the legend?
+ this._area = [0.9, 0.1, 1.0, 0.9]; // The legend area: left, top, right, bottom,
+ // > 1 in pixels, <= 1 as proportion
+ this._sampleSize = 15; // Size of sample box
+ this._bgSettings = bgSettings || {stroke: 'gray'}; // Additional formatting settings for the legend background
+ this._textSettings = textSettings || {}; // Additional formatting settings for the text
+}
+
+$.extend(SVGPlotLegend.prototype, {
+
+ /* Set or retrieve whether the legend should be shown.
+ @param show (boolean) true to display it, false to hide it
+ @return (SVGPlotLegend) this legend object or
+ (boolean) show the legend? (if no parameters) */
+ show: function(show) {
+ if (arguments.length == 0) {
+ return this._show;
+ }
+ this._show = show;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve the legend area.
+ @param left (number) > 1 is pixels, <= 1 is proportion of width or
+ (number[4]) for left, top, right, bottom
+ @param top (number) > 1 is pixels, <= 1 is proportion of height
+ @param right (number) > 1 is pixels, <= 1 is proportion of width
+ @param bottom (number) > 1 is pixels, <= 1 is proportion of height
+ @return (SVGPlotLegend) this legend object or
+ (number[4]) the legend area: left, top, right, bottom (if no parameters) */
+ area: function(left, top, right, bottom) {
+ if (arguments.length == 0) {
+ return this._area;
+ }
+ this._area = (isArray(left) ? left : [left, top, right, bottom]);
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Set or retrieve additional settings for the legend area.
+ @param sampleSize (number) the size of the sample box to display (optional)
+ @param bgSettings (object) additional formatting settings for the legend background
+ @param textSettings (object) additional formatting settings for the legend text (optional)
+ @return (SVGPlotLegend) this legend object or
+ (object) bgSettings and textSettings for the legend (if no parameters) */
+ settings: function(sampleSize, bgSettings, textSettings) {
+ if (arguments.length == 0) {
+ return {sampleSize: this._sampleSize, bgSettings: this._bgSettings,
+ textSettings: this._textSettings};
+ }
+ if (typeof sampleSize == 'object') {
+ textSettings = bgSettings;
+ bgSettings = sampleSize;
+ sampleSize = null;
+ }
+ this._sampleSize = sampleSize || this._sampleSize;
+ this._bgSettings = bgSettings;
+ this._textSettings = textSettings || this._textSettings;
+ this._plot._drawPlot();
+ return this;
+ },
+
+ /* Return to the parent plot. */
+ end: function() {
+ return this._plot;
+ }
+});
+
+//==============================================================================
+
+/* Determine whether an object is an array. */
+function isArray(a) {
+ return (a && a.constructor == Array);
+}
+
+})(jQuery)
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/lion.svg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/lion.svg Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/svg/svgBasics.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/svg/svgBasics.html Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,74 @@
+
+
+
+
+jQuery SVG Basics
+
+
+
+
+
+
+jQuery SVG Basics
+This page demonstrates the very basics of the jQuery SVG plugin .
+ It contains the minimum requirements for using the plugin and
+ can be used as the basis for your own experimentation.
+The page creates an SVG document in the area below and draws an initial display.
+ The buttons then add randomly sized and coloured shapes on demand.
+For more detail see the documentation reference page.
+
+Add rectangle Add line
+ Add circle Add ellipse
+ Clear
+
+
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_flat_0_aaaaaa_40x100.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_flat_75_ffffff_40x100.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_flat_75_ffffff_40x100.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_glass_55_fbf9ee_1x400.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_glass_65_ffffff_1x400.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_glass_65_ffffff_1x400.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_glass_75_dadada_1x400.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_glass_75_dadada_1x400.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_glass_75_e6e6e6_1x400.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_glass_95_fef1ec_1x400.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_glass_95_fef1ec_1x400.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary file client/digitallibrary/jquery/ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-icons_222222_256x240.png
Binary file client/digitallibrary/jquery/ui/images/ui-icons_222222_256x240.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-icons_2e83ff_256x240.png
Binary file client/digitallibrary/jquery/ui/images/ui-icons_2e83ff_256x240.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-icons_454545_256x240.png
Binary file client/digitallibrary/jquery/ui/images/ui-icons_454545_256x240.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-icons_888888_256x240.png
Binary file client/digitallibrary/jquery/ui/images/ui-icons_888888_256x240.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/images/ui-icons_cd0a0a_256x240.png
Binary file client/digitallibrary/jquery/ui/images/ui-icons_cd0a0a_256x240.png has changed
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery-test-embedded.SLIDER.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery-test-embedded.SLIDER.html Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,117 @@
+
+
+
+ Digilib jQuery Test: embedded
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DEBUG
+
+
+
+
+
+
+
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery-test-full.SLIDER.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery-test-full.SLIDER.html Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,51 @@
+
+
+
+
+ Digilib jQuery Test: fullscreen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery-ui-1.8.9.custom.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery-ui-1.8.9.custom.css Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,573 @@
+/*
+ * jQuery UI CSS Framework 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*
+ * jQuery UI CSS Framework 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
+.ui-widget-header a { color: #222222; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
+ * jQuery UI Resizable 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
+ * jQuery UI Selectable 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*
+ * jQuery UI Accordion 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
+/*
+ * jQuery UI Autocomplete 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.9
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/*
+ * jQuery UI Button 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*
+ * jQuery UI Dialog 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*
+ * jQuery UI Slider 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
+ * jQuery UI Tabs 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*
+ * jQuery UI Datepicker 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ display: none; /*sorry for IE5*/
+ display/**/: block; /*sorry for IE5*/
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/*
+ * jQuery UI Progressbar 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.digilib.SLIDER.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.digilib.SLIDER.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,1613 @@
+/* Copyright (c) 2011 Martin Raspe, Robert Casties
+
+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 2 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
+
+Authors:
+ Martin Raspe, Robert Casties, 11.1.2011
+*/
+
+/**
+ * digilib jQuery plugin
+**/
+
+
+/* jslint browser: true, debug: true, forin: true
+*/
+
+// fallback for console.log calls
+if (typeof(console) === 'undefined') {
+ var console = {
+ log : function(){},
+ debug : function(){},
+ error : function(){}
+ };
+ var customConsole = true;
+}
+
+(function($) {
+ var buttons = {
+ reference : {
+ onclick : "reference",
+ tooltip : "get a reference URL",
+ img : "reference.png"
+ },
+ zoomin : {
+ onclick : ["zoomBy", 1.4],
+ tooltip : "zoom in",
+ img : "zoom-in.png"
+ },
+ zoomout : {
+ onclick : ["zoomBy", 0.7],
+ tooltip : "zoom out",
+ img : "zoom-out.png"
+ },
+ zoomarea : {
+ onclick : "zoomArea",
+ tooltip : "zoom area",
+ img : "zoom-area.png"
+ },
+ zoomfull : {
+ onclick : "zoomFull",
+ tooltip : "view the whole image",
+ img : "zoom-full.png"
+ },
+ pagewidth : {
+ onclick : ["zoomFull", "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 : "gotoPage",
+ tooltip : "goto image number",
+ 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 : "reset",
+ tooltip : "reset image",
+ img : "reset.png"
+ },
+ mark : {
+ onclick : "setMark",
+ tooltip : "set a mark",
+ img : "mark.png"
+ },
+ delmark : {
+ onclick : "removeMark",
+ tooltip : "delete the last mark",
+ img : "delmark.png"
+ },
+ hmir : {
+ onclick : ["mirror", "h"],
+ tooltip : "mirror horizontally",
+ img : "mirror-horizontal.png"
+ },
+ vmir : {
+ onclick : ["mirror", "v"],
+ tooltip : "mirror vertically",
+ img : "mirror-vertical.png"
+ },
+ rot : {
+ onclick : "rotate",
+ tooltip : "rotate image",
+ img : "rotate.png"
+ },
+ brgt : {
+ onclick : "brightness",
+ tooltip : "set brightness",
+ img : "brightness.png"
+ },
+ cont : {
+ onclick : "contrast",
+ tooltip : "set contrast",
+ img : "contrast.png"
+ },
+ rgb : {
+ onclick : "javascript:setParamWin('rgb', '...')",
+ tooltip : "set rgb values",
+ img : "rgb.png"
+ },
+ quality : {
+ onclick : "setQuality",
+ 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"
+ },
+ toggleoptions : {
+ onclick : "moreButtons",
+ tooltip : "more options",
+ img : "options.png"
+ },
+ moreoptions : {
+ onclick : ["moreButtons", "+1"],
+ tooltip : "more options",
+ img : "options.png"
+ },
+ lessoptions : {
+ onclick : ["moreButtons", "-1"],
+ tooltip : "less options",
+ img : "options.png"
+ },
+ SEP : {
+ img : "sep.png"
+ }
+ };
+
+ var defaults = {
+ // 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 digilib viewer (for reference URLs)
+ 'digilibBaseUrl' : null,
+ // base URL to Scaler servlet
+ 'scalerBaseUrl' : null,
+ // 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
+ 'pn' : 1,
+ 'ww' : 1.0,
+ 'wh' : 1.0,
+ 'wx' : 0.0,
+ 'wy' : 0.0,
+ 'ws' : 1.0,
+ 'mo' : '',
+ 'rot' : 0,
+ 'cont' : 0,
+ 'brgt' : 0,
+ 'rgbm' : '0/0/0',
+ 'rgba' : '0/0/0',
+ 'ddpi' : null,
+ 'ddpix' : null,
+ 'ddpiy' : null,
+ // list of digilib parameters
+ 'digilibParamNames' : ['fn','pn','ww','wh','wx','wy','ws','mo','rot','cont','brgt','rgbm','rgba','mk','clop'],
+ // digilib parameter defaults
+ 'mk' : '',
+ 'clop' : '',
+ // mode of operation:
+ // fullscreen = take parameters from page URL, keep state in page URL
+ // embedded = take parameters from Javascript options, keep state inside object
+ 'interactionMode' : 'fullscreen',
+ // buttons
+ 'buttons' : buttons,
+ // defaults for digilib buttons
+ 'buttonSettings' : {
+ 'fullscreen' : {
+ // path to button images (must end with a slash)
+ 'imagePath' : 'img/fullscreen/',
+ 'standardSet' : ["reference","zoomin","zoomout","zoomarea","zoomfull","pagewidth","back","fwd","page","bird","help","reset","toggleoptions"],
+ 'specialSet' : ["mark","delmark","hmir","vmir","rot","brgt","cont","rgb","quality","size","calibrationx","scale","toggleoptions"],
+ 'buttonSets' : ['standardSet', 'specialSet']
+ },
+ 'embedded' : {
+ 'imagePath' : 'img/embedded/16/',
+ 'standardSet' : ["reference","zoomin","zoomout","zoomarea","zoomfull","bird","help","reset","toggleoptions"],
+ 'specialSet' : ["mark","delmark","hmir","vmir","rot","brgt","cont","rgb","quality","toggleoptions"],
+ 'buttonSets' : ['standardSet', 'specialSet']
+ }
+ },
+ // number of visible button groups
+ 'visibleButtonSets' : 1,
+ // is birdView shown?
+ 'isBirdDivVisible' : false,
+ // dimensions of bird's eye div
+ 'birdDivWidth' : 200,
+ 'birdDivHeight' : 200,
+ // parameters used by bird's eye div
+ 'birdDivParams' : ['fn','pn','dw','dh'],
+ // style of the zoom area indicator in the bird's eye div
+ 'birdIndicatorStyle' : {'border' : '2px solid #ff0000' },
+ // style of zoom area "rubber band"
+ 'zoomrectStyle' : {'border' : '2px solid #ff0000' },
+ // is the "about" window shown?
+ 'isAboutDivVisible' : false,
+ // maximum width of background image for drag-scroll
+ 'maxBgSize' : 10000
+
+ };
+
+ // affine geometry classes
+ var geom = dlGeometry();
+
+ var FULL_AREA = geom.rectangle(0, 0, 1, 1);
+
+ var actions = {
+ // init: 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();
+ // check scalerBaseUrl
+ if (settings.scalerBaseUrl == null) {
+ // try the host this came from
+ var h = window.location.host;
+ if (window.location.host) {
+ var url = window.location.href;
+ // assume the page lives in [webapp]/jquery/
+ var pos = url.indexOf('jquery/');
+ if (pos > 0) {
+ settings.scalerBaseUrl = url.substring(0, pos) + 'servlet/Scaler';
+ }
+ }
+ }
+ }
+ return this.each(function() {
+ var $elem = $(this);
+ var data = $elem.data('digilib');
+ var params, elemSettings;
+ // if the plugin hasn't been initialized yet
+ if (!data) {
+ // merge query parameters
+ if (isFullscreen) {
+ params = queryParams;
+ } else {
+ params = parseImgParams($elem);
+ if (jQuery.cookie) {
+ // retrieve params from cookie
+ var ck = "digilib-embed:fn:" + escape(params.fn) + ":pn:" + (params.pn || '1');
+ var cs = jQuery.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);
+ }
+ }
+ }
+ // store $(this) element in the settings
+ elemSettings = jQuery.extend({}, settings, params);
+ data = {
+ $elem : $elem,
+ settings : elemSettings,
+ queryParams : params
+ };
+ // store in data element
+ $elem.data('digilib', data);
+ }
+ unpackParams(data);
+ // check if browser knows *background-size
+ for (var bs in {'':1, '-moz-':1, '-webkit-':1, '-o-':1}) {
+ if ($elem.css(bs+'background-size')) {
+ data.hasBgSize = true;
+ data.bgSizeName = bs+'background-size';
+ break;
+ }
+ }
+ // check digilib base URL
+ if (elemSettings.digilibBaseUrl == null) {
+ if (isFullscreen) {
+ // take current host
+ var url = window.location.toString();
+ var pos = url.indexOf('?');
+ elemSettings.digilibBaseUrl = url.substring(0, pos);
+ } else {
+ var url = elemSettings.scalerBaseUrl;
+ if (url) {
+ // build it from scaler URL
+ var bp = url.indexOf('/servlet/Scaler');
+ elemSettings.digilibBaseUrl = url.substring(0, bp) + '/digilib.jsp';
+ }
+ }
+ }
+ // create HTML structure for scaler
+ setupScalerDiv(data);
+ // add buttons
+ for (var i = 0; i < elemSettings.visibleButtonSets; ++i) {
+ showButtons(data, true, i);
+ }
+ // bird's eye view creation
+ if (elemSettings.isBirdDivVisible) {
+ setupBirdDiv(data);
+ data.$birdDiv.show();
+ }
+ // about window creation - TODO: could be deferred? restrict to only one item?
+ setupAboutDiv(data);
+ // drag zoom area around in scaler div
+ setupZoomDrag(data);
+ // dialog for brightness, rotate etc.
+ setupDialogDiv(data);
+ });
+ },
+
+ // destroy: clean up digilib
+ destroy : function(data) {
+ return this.each(function(){
+ var $elem = $(this);
+ $(window).unbind('.digilib'); // unbind all digilibs(?)
+ data.digilib.remove();
+ $elem.removeData('digilib');
+ });
+ },
+
+ // show or hide the 'about' window
+ showAboutDiv : function(data, show) {
+ data.settings.isAboutDivVisible = showDiv(data.settings.isAboutDivVisible, data.$aboutDiv, show);
+ },
+
+ // event handler: toggles the visibility of the bird's eye window
+ showBirdDiv : function (data, show) {
+ var settings = data.settings;
+ if (data.$birdDiv == null) {
+ // no bird div -> create
+ setupBirdDiv(data);
+ }
+ settings.isBirdDivVisible = showDiv(settings.isBirdDivVisible, data.$birdDiv, show);
+ updateBirdDiv(data);
+ storeOptions(data);
+ // data.$birdImg.triggerHandler('load'); // TODO: we shouldn't do that
+ },
+
+ // goto given page nr (+/-: relative)
+ gotoPage : function (data, pageNr) {
+ var settings = data.settings;
+ var oldpn = settings.pn;
+ if (pageNr == null) {
+ pageNr = window.prompt("Goto page number", oldpn);
+ }
+ 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;
+ }
+ }
+ // reset mk and others(?)
+ data.marks = [];
+ data.zoomArea = FULL_AREA;
+ // then reload
+ redisplay(data);
+ },
+
+ // zoom by a given factor
+ zoomBy : function (data, factor) {
+ zoomBy(data, factor);
+ },
+
+ // zoom interactively
+ zoomArea : function (data) {
+ zoomArea(data);
+ },
+
+ // zoom out to full page
+ zoomFull : function (data, mode) {
+ data.zoomArea = FULL_AREA;
+ if (mode === 'width') {
+ data.dlOpts.fitwidth = 1;
+ delete data.dlOpts.fitheight;
+ } else if (mode === 'height') {
+ data.dlOpts.fitheight = 1;
+ delete data.dlOpts.fitwidth;
+ } else {
+ delete data.dlOpts.fitwidth;
+ delete data.dlOpts.fitheight;
+ }
+ redisplay(data);
+ },
+
+ // set a mark by clicking (or giving a position)
+ setMark : function (data, mpos) {
+ if (mpos == null) {
+ // interactive
+ setMark(data);
+ } else {
+ // use position
+ data.marks.push(pos);
+ redisplay(data);
+ }
+ },
+
+ // remove the last mark
+ removeMark : function (data) {
+ data.marks.pop();
+ redisplay(data);
+ },
+
+ // mirror the image
+ mirror : function (data, mode) {
+ var flags = data.scalerFlags;
+ if (mode === 'h') {
+ if (flags.hmir) {
+ delete flags.hmir;
+ } else {
+ flags.hmir = 1;
+ }
+ } else {
+ if (flags.vmir) {
+ delete flags.vmir;
+ } else {
+ flags.vmir = 1;
+ }
+ }
+ redisplay(data);
+ },
+
+ // rotate the image
+ rotate : function (data, angle) {
+ var rot = data.settings.rot;
+ if (angle == null) {
+ // angle = window.prompt("Rotation angle:", rot);
+ var $slider = data.$slider;
+ $slider.slider('enable');
+ var $dialog = data.$dialog;
+ $dialog.text('Set the slider');
+ $dialog.dialog('option', {
+ 'title' : 'set rotation angle',
+ });
+ $dialog.dialog('open');
+ }
+ //data.settings.rot = angle;
+ //redisplay(data);
+ },
+
+ // change brightness
+ brightness : function (data, factor) {
+ var brgt = data.settings.brgt;
+ if (factor == null) {
+ factor = window.prompt("Brightness (-255..255)", brgt);
+ }
+ data.settings.brgt = factor;
+ redisplay(data);
+ },
+
+ // change contrast
+ contrast : function (data, factor) {
+ var cont = data.settings.cont;
+ if (factor == null) {
+ factor = window.prompt("Contrast (-8, 8)", cont);
+ }
+ data.settings.cont = factor;
+ redisplay(data);
+ },
+
+ // 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++;
+ }
+ }
+ // persist setting
+ storeOptions(data);
+ },
+
+ // reset image parameters to defaults
+ reset : function (data) {
+ var settings = data.settings;
+ var paramNames = settings.digilibParamNames;
+ var params = data.queryParams;
+ // delete all digilib parameters
+ for (var i = 0; i < paramNames.length; i++) {
+ var paramName = paramNames[i];
+ delete settings[paramName];
+ }
+ settings.fn = params.fn || ''; // no default defined
+ settings.pn = params.pn || defaults.pn;
+ settings.dw = params.dw;
+ settings.dh = params.dh;
+ settings.isBirdDivVisible = false;
+ settings.visibleButtonSets = 1;
+ // resets zoomArea, marks, scalerflags
+ data.zoomArea = FULL_AREA;
+ data.marks = [];
+ data.scalerFlags = {};
+ delete data.dlOpts.fitwidth;
+ delete data.dlOpts.fitheight;
+ redisplay(data);
+ },
+
+ // presents a reference url (returns value if noprompt)
+ reference : function (data, noprompt) {
+ var settings = data.settings;
+ var url = getDigilibUrl(data);
+ if (noprompt == null) {
+ window.prompt("URL reference to the current view", url);
+ }
+ return url;
+ },
+
+ // set image quality
+ setQuality : function (data, qual) {
+ var oldq = getQuality(data);
+ if (qual == null) {
+ qual = window.prompt("Image quality (0..2)", oldq);
+ }
+ qual = parseInt(qual, 10);
+ if (qual >= 0 && qual <= 2) {
+ setQuality(data, qual);
+ redisplay(data);
+ }
+ }
+ };
+
+ // 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 params = {};
+ if (query == null) return params;
+ var pairs = query.split("&");
+ //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 (ignoring if the same value is in defaults)
+ var getParamString = function (settings, keys, defaults) {
+ var paramString = '';
+ var nx = false;
+ for (i = 0; i < keys.length; ++i) {
+ var key = keys[i];
+ if ((settings[key] != null) && ((defaults == null) || (settings[key] != defaults[key]))) {
+ // first param gets no '&'
+ if (nx) {
+ paramString += '&';
+ } else {
+ nx = true;
+ }
+ // add parm=val
+ paramString += key + '=' + settings[key];
+ }
+ }
+ return paramString;
+ };
+
+ // returns URL and query string for Scaler
+ 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;
+ };
+
+ // returns URL for bird's eye view image
+ var getBirdImgUrl = function (data, moreParams) {
+ var settings = data.settings;
+ var birdDivOptions = {
+ dw : settings.birdDivWidth,
+ dh : settings.birdDivHeight
+ };
+ var birdSettings = jQuery.extend({}, settings, birdDivOptions);
+ // use only the relevant parameters
+ if (moreParams == null) {
+ var params = getParamString(birdSettings, settings.birdDivParams, defaults);
+ } else {
+ var params = getParamString(birdSettings,
+ settings.birdDivParams.concat(moreParams), defaults);
+ }
+ var url = settings.scalerBaseUrl + '?' + params;
+ return url;
+ };
+
+ // returns URL and query string for current digilib
+ var getDigilibUrl = function (data) {
+ packParams(data);
+ var settings = data.settings;
+ var queryString = getParamString(settings, settings.digilibParamNames, defaults);
+ return settings.digilibBaseUrl + '?' + queryString;
+ };
+
+ // 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);
+ data.zoomArea = zoomArea;
+ // marks
+ var marks = [];
+ if (settings.mk) {
+ 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]));
+ }
+ }
+ }
+ data.marks = marks;
+ // mo (Scaler flags)
+ var flags = {};
+ if (settings.mo) {
+ var pa = settings.mo.split(",");
+ for (var i = 0; i < pa.length ; i++) {
+ flags[pa[i]] = pa[i];
+ }
+ }
+ data.scalerFlags = flags;
+ retrieveOptions(data);
+ };
+
+ // put objects back into parameters
+ var packParams = function (data) {
+ var settings = data.settings;
+ // zoom area
+ if (data.zoomArea) {
+ settings.wx = cropFloat(data.zoomArea.x);
+ settings.wy = cropFloat(data.zoomArea.y);
+ settings.ww = cropFloat(data.zoomArea.width);
+ settings.wh = cropFloat(data.zoomArea.height);
+ }
+ // marks
+ if (data.marks) {
+ settings.mk = '';
+ for (var i = 0; i < data.marks.length; i++) {
+ if (i) {
+ settings.mk += ',';
+ }
+ settings.mk += cropFloat(data.marks[i].x).toString() +
+ '/' + cropFloat(data.marks[i].y).toString();
+ }
+ }
+ // Scaler flags
+ if (data.scalerFlags) {
+ var mo = '';
+ for (var f in data.scalerFlags) {
+ if (mo) {
+ mo += ',';
+ }
+ mo += f;
+ }
+ settings.mo = mo;
+ }
+ // user interface options
+ storeOptions(data);
+ };
+
+ var storeOptions = function (data) {
+ // save digilib options in cookie
+ var settings = data.settings;
+ if (data.dlOpts) {
+ // save digilib settings in options
+ data.dlOpts.birdview = settings.isBirdDivVisible ? 1 : 0;
+ data.dlOpts.buttons = settings.visibleButtonSets;
+ var clop = '';
+ for (var o in data.dlOpts) {
+ if (clop) {
+ clop += '&';
+ }
+ clop += o + '=' + data.dlOpts[o];
+ }
+ if (jQuery.cookie) {
+ var ck = "digilib:fn:" + escape(settings.fn) + ":pn:" + settings.pn;
+ console.debug("set cookie=", ck, " value=", clop);
+ jQuery.cookie(ck, clop);
+ }
+ }
+ if (settings.interactionMode !== 'fullscreen' && jQuery.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);
+ }
+ };
+
+ var retrieveOptions = function (data) {
+ // clop (digilib options)
+ var opts = {};
+ var settings = data.settings;
+ if (jQuery.cookie) {
+ // read from cookie
+ var ck = "digilib:fn:" + escape(settings.fn) + ":pn:" + settings.pn;
+ var cp = jQuery.cookie(ck);
+ console.debug("get cookie=", ck, " value=", cp);
+ // in query string format
+ opts = parseQueryString(cp);
+ }
+ data.dlOpts = opts;
+ // birdview option
+ if (opts.birdview != null) {
+ settings.isBirdDivVisible = opts.birdview === '1';
+ }
+ // visible button sets
+ if (opts.buttons != null) {
+ settings.visibleButtonSets = opts.buttons;
+ }
+ };
+
+ // (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);
+ // redisplay bird img
+ updateBirdDiv(data);
+ }
+ };
+
+ // returns maximum size for scaler img in fullscreen mode
+ var getFullscreenImgSize = function($elem) {
+ var $win = $(window);
+ var winH = $win.height();
+ var winW = $win.width();
+ // TODO: account for borders?
+ return geom.size(winW, winH);
+ };
+
+ // creates HTML structure for digilib in elem
+ var setupScalerDiv = function (data) {
+ var settings = data.settings;
+ var $elem = data.$elem;
+ $elem.addClass('digilib');
+ var $img;
+ var scalerUrl;
+ if (settings.interactionMode === 'fullscreen') {
+ // fullscreen
+ $elem.addClass('dl_fullscreen');
+ var imgSize = getFullscreenImgSize($elem);
+ // fitwidth/height omits destination height/width
+ if (data.dlOpts.fitheight == null) {
+ settings.dw = imgSize.width;
+ }
+ if (data.dlOpts.fitwidth == null) {
+ settings.dh = imgSize.height;
+ }
+ scalerUrl = getScalerUrl(data);
+ $img = $(' ');
+ } else {
+ // embedded mode -- try to keep img tag
+ $elem.addClass('dl_embedded');
+ scalerUrl = getScalerUrl(data);
+ $img = $elem.find('img');
+ if ($img.length > 0) {
+ oldUrl = $img.attr('src');
+ if (oldUrl === scalerUrl) {
+ console.debug("img detach:", $img);
+ $img.detach();
+ } else {
+ $img = $(' ');
+ }
+ } else {
+ $img = $(' ');
+ }
+ }
+ // create new html
+ $elem.empty(); // TODO: should we keep stuff for customization?
+ var $scaler = $('
');
+ $elem.append($scaler);
+ $scaler.append($img);
+ $img.addClass('pic');
+ data.$scaler = $scaler;
+ data.$img = $img;
+ // setup image load handler before setting the src attribute (IE bug)
+ $img.load(scalerImgLoadedHandler(data));
+ $img.attr('src', scalerUrl);
+ };
+
+ // 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 buttonSettings = settings.buttonSettings[mode];
+ var buttonGroup = buttonSettings.buttonSets[buttonSetIdx];
+ if (buttonGroup == null) {
+ // no buttons here
+ return;
+ }
+ var $buttonsDiv = $('
');
+ var buttonNames = buttonSettings[buttonGroup];
+ for (var i = 0; i < buttonNames.length; i++) {
+ var buttonName = buttonNames[i];
+ var buttonConfig = settings.buttons[buttonName];
+ // construct the button html
+ var $button = $('
');
+ var $a = $(' ');
+ var $img = $(' ');
+ $buttonsDiv.append($button);
+ $button.append($a);
+ $a.append($img);
+ // add attributes and bindings
+ $button.attr('title', buttonConfig.tooltip);
+ $button.addClass('button-' + buttonName);
+ // create handler for the buttons
+ $a.bind('click.digilib', (function () {
+ // we create a new closure to capture the value of action
+ var action = buttonConfig.onclick;
+ if ($.isArray(action)) {
+ // the handler function calls digilib with action and parameters
+ return function (evt) {
+ console.debug('click action=', action, ' evt=', evt);
+ $elem.digilib.apply($elem, action);
+ return false;
+ };
+ } else {
+ // the handler function calls digilib with action
+ return function (evt) {
+ console.debug('click action=', action, ' evt=', evt);
+ $elem.digilib(action);
+ return false;
+ };
+ }
+ })());
+ $img.attr('src', buttonSettings.imagePath + buttonConfig.img);
+ }
+ // 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;
+ };
+
+ // creates HTML structure for the bird's eye view in elem
+ var setupBirdDiv = function (data) {
+ var $elem = data.$elem;
+ // the bird's eye div
+ var $birdDiv = $('
');
+ // the detail indicator frame
+ var $birdZoom = $('
');
+ // the small image
+ var $birdImg = $(' ');
+ data.$birdDiv = $birdDiv;
+ data.$birdZoom = $birdZoom;
+ data.$birdImg = $birdImg;
+ $elem.append($birdDiv);
+ $birdDiv.append($birdZoom);
+ $birdDiv.append($birdImg);
+ $birdZoom.css(data.settings.birdIndicatorStyle);
+ var birdUrl = getBirdImgUrl(data);
+ $birdImg.load(birdImgLoadedHandler(data));
+ $birdImg.attr('src', birdUrl);
+ };
+
+ // update bird's eye view
+ var updateBirdDiv = function (data) {
+ if (!data.settings.isBirdDivVisible) return;
+ var $birdImg = data.$birdImg;
+ var oldsrc = $birdImg.attr('src');
+ var newsrc = getBirdImgUrl(data);
+ if (oldsrc !== newsrc) {
+ $birdImg.attr('src', newsrc);
+ // onload handler re-renders
+ } else {
+ // re-render
+ renderBirdArea(data);
+ // enable click and drag
+ setupBirdDrag(data);
+ }
+ };
+
+ // creates HTML structure for the dialog
+ var setupDialogDiv = function (data) {
+ var $elem = data.$elem;
+ var settings = data.settings;
+ var $dialogDiv = $('
');
+ var $sliderDiv = $('
');
+ $dialogDiv.append($sliderDiv);
+ $dialogDiv.dialog({
+ 'autoOpen' : false,
+ 'buttons': {
+ "Ok": function() {
+ $(this).dialog("close");
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $sliderDiv.slider({
+ 'range' : true,
+ 'min' : 0,
+ 'max' : 500,
+ 'values' : [ 75, 300 ]
+ });
+ data.$dialog = $dialogDiv;
+ data.$slider = $sliderDiv;
+ };
+
+ // creates HTML structure for the about view in elem
+ var setupAboutDiv = function (data) {
+ var $elem = data.$elem;
+ var settings = data.settings;
+ var $aboutDiv = $('
');
+ var $header = $('Digilib Graphic Viewer
');
+ var $link = $(' ');
+ var $logo = $(' ');
+ var $content = $('
');
+ $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.digilib', function () {
+ settings.isAboutDivVisible = showDiv(settings.isAboutDivVisible, $aboutDiv, 0);
+ return false;
+ });
+ data.$aboutDiv = $aboutDiv;
+ };
+
+ // shows some window e.g. 'about' (toggle visibility if show is null)
+ var showDiv = function (isVisible, $div, show) {
+ if (show == null) {
+ // toggle visibility
+ isVisible = !isVisible;
+ } else {
+ // set visibility
+ isVisible = show;
+ }
+ if (isVisible) {
+ $div.fadeIn();
+ } else {
+ $div.fadeOut();
+ }
+ return isVisible;
+ };
+
+ // display more (or less) button sets
+ var showButtons = function (data, more, setIdx, animated) {
+ var atime = animated ? 'fast': 0;
+ if (more) {
+ // add set
+ var $otherSets = data.$elem.find('div.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;
+ var btnWidth = $set.width();
+ // 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.width();
+ // hide last set
+ $set.hide();
+ // take remaining sets and move right
+ var $otherSets = data.$elem.find('div.buttons:visible');
+ $otherSets.animate({right : '-='+btnWidth+'px'}, atime);
+ }
+ return true;
+ };
+
+ // create Transform from area and $img
+ var getImgTrafo = function ($img, area, rot, hmir, vmir) {
+ var picrect = geom.rectangle($img);
+ var trafo = geom.transform();
+ // move zoom area offset to center
+ trafo.concat(trafo.getTranslation(geom.position(-area.x, -area.y)));
+ // scale zoom area size to [1,1]
+ trafo.concat(trafo.getScale(geom.size(1/area.width, 1/area.height)));
+ // rotate and mirror (around transformed image center i.e. [0.5,0.5])
+ if (rot || hmir || vmir) {
+ // move [0.5,0.5] to center
+ trafo.concat(trafo.getTranslation(geom.position(-0.5, -0.5)));
+ if (hmir) {
+ // mirror about center
+ trafo.concat(trafo.getMirror('y'));
+ }
+ if (vmir) {
+ // mirror about center
+ trafo.concat(trafo.getMirror('x'));
+ }
+ if (rot) {
+ // rotate around center
+ trafo.concat(trafo.getRotation(parseFloat(rot)));
+ }
+ // move back
+ trafo.concat(trafo.getTranslation(geom.position(0.5, 0.5)));
+ }
+ // scale to screen position and size
+ trafo.concat(trafo.getScale(picrect));
+ trafo.concat(trafo.getTranslation(picrect));
+ return trafo;
+ };
+
+ // returns function for load event of scaler img
+ var scalerImgLoadedHandler = function (data) {
+ return function () {
+ var $img = $(this);
+ var $scaler = data.$scaler;
+ // create Transform from current area and picsize
+ data.imgTrafo = getImgTrafo($img, data.zoomArea,
+ data.settings.rot, data.scalerFlags.hmir, data.scalerFlags.vmir);
+ console.debug("imgTrafo=", data.imgTrafo);
+ // adjust scaler div size
+ var imgRect = geom.rectangle($img);
+ console.debug("imgrect=", imgRect);
+ imgRect.adjustDiv($scaler);
+ // show image in case it was hidden (for example in zoomDrag)
+ $img.css('visibility', 'visible');
+ $scaler.css({'opacity' : '1', 'background-image' : 'none'});
+ // display marks
+ renderMarks(data);
+ // enable drag-to-scroll
+ setupZoomDrag(data);
+ // TODO: digilib.showArrows(); // show arrow overlays for zoom navigation
+ };
+ };
+
+ // returns function for load event of bird's eye view img
+ var birdImgLoadedHandler = function (data) {
+ return function () {
+ var $img = $(this);
+ console.debug("birdimg loaded! this=", this, " data=", data);
+ // create Transform from current area and picsize
+ data.birdTrafo = getImgTrafo($img, FULL_AREA);
+ // display red indicator around zoomarea
+ renderBirdArea(data);
+ // enable click and drag
+ setupBirdDrag(data);
+ };
+ };
+
+ // place marks on the image
+ var renderMarks = function (data) {
+ var $elem = data.$elem;
+ var marks = data.marks;
+ // clear marks
+ $elem.find('div.mark').remove();
+ for (var i = 0; i < marks.length; i++) {
+ var mark = marks[i];
+ if (data.zoomArea.containsPosition(mark)) {
+ var mpos = data.imgTrafo.transform(mark);
+ console.debug("renderMarks: mpos=",mpos);
+ // create mark
+ var html = ''+(i+1)+'
';
+ var $mark = $(html);
+ $elem.append($mark);
+ mpos.adjustDiv($mark);
+ }
+ }
+ };
+
+ // show zoom area indicator on bird's eye view
+ var renderBirdArea = function (data) {
+ var $birdZoom = data.$birdZoom;
+ var zoomArea = data.zoomArea;
+ var normalSize = isFullArea(zoomArea);
+ if (normalSize) {
+ $birdZoom.hide();
+ return;
+ } else {
+ $birdZoom.show();
+ }
+ // position may have changed
+ data.birdTrafo = getImgTrafo(data.$birdImg, FULL_AREA);
+ var zoomRect = data.birdTrafo.transform(zoomArea);
+ // acount for border width
+ zoomRect.addPosition({x : -2, y : -2});
+ if (data.settings.interactionMode === 'fullscreen') {
+ // no animation for fullscreen
+ zoomRect.adjustDiv($birdZoom);
+ } else {
+ // nice animation for embedded mode :-)
+ // correct offsetParent because animate doesn't use offset
+ var ppos = $birdZoom.offsetParent().offset();
+ var dest = {
+ left : (zoomRect.x - ppos.left) + 'px',
+ top : (zoomRect.y - ppos.top) + 'px',
+ width : zoomRect.width,
+ height : zoomRect.height};
+ $birdZoom.animate(dest);
+ }
+ };
+
+ // zooms by the given factor
+ var zoomBy = function(data, factor) {
+ var area = data.zoomArea;
+ var newarea = area.copy();
+ // scale
+ newarea.width /= factor;
+ newarea.height /= factor;
+ // and recenter
+ newarea.x -= 0.5 * (newarea.width - area.width);
+ newarea.y -= 0.5 * (newarea.height - area.height);
+ newarea = FULL_AREA.fit(newarea);
+ data.zoomArea = newarea;
+ redisplay(data);
+ };
+
+ // add a mark where clicked
+ var setMark = function (data) {
+ var $scaler = data.$scaler;
+ // unbind other handler
+ $scaler.unbind(".dlZoomDrag");
+ // start event capturing
+ $scaler.one('mousedown.dlSetMark', function (evt) {
+ // event handler adding a new mark
+ console.log("setmark at=", evt);
+ var mpos = geom.position(evt);
+ var pos = data.imgTrafo.invtransform(mpos);
+ data.marks.push(pos);
+ redisplay(data);
+ return false;
+ });
+ };
+
+ // zoom to the area around two clicked points
+ var zoomArea = function(data) {
+ $elem = data.$elem;
+ $scaler = data.$scaler;
+ var pt1, pt2;
+ var $zoomDiv = $('
');
+ $elem.append($zoomDiv);
+ $zoomDiv.css(data.settings.zoomrectStyle);
+ var picRect = geom.rectangle($scaler);
+ // FIX ME: is there a way to query the border width from CSS info?
+ // rect.x -= 2; // account for overlay borders
+ // rect.y -= 2;
+
+ var zoomStart = function (evt) {
+ pt1 = geom.position(evt);
+ // setup and show zoom div
+ pt1.adjustDiv($zoomDiv);
+ $zoomDiv.width(0).height(0);
+ $zoomDiv.show();
+ // register events
+ $elem.bind("mousemove.dlZoomArea", zoomMove);
+ $elem.bind("mouseup.dlZoomArea", zoomEnd);
+ return false;
+ };
+
+ // mouse move handler
+ var zoomMove = function (evt) {
+ pt2 = geom.position(evt);
+ var rect = geom.rectangle(pt1, pt2);
+ rect.clipTo(picRect);
+ // update zoom div
+ rect.adjustDiv($zoomDiv);
+ return false;
+ };
+
+ // mouseup handler: end moving
+ var zoomEnd = function (evt) {
+ pt2 = geom.position(evt);
+ // assume a click and continue if the area is too small
+ var clickRect = geom.rectangle(pt1, pt2);
+ if (clickRect.getArea() <= 5) return false;
+ // hide zoom div
+ $zoomDiv.remove();
+ // unregister events
+ $elem.unbind("mousemove.dlZoomArea", zoomMove);
+ $elem.unbind("mouseup.dlZoomArea", zoomEnd);
+ // clip and transform
+ clickRect.clipTo(picRect);
+ var area = data.imgTrafo.invtransform(clickRect);
+ data.zoomArea = area;
+ // zoomed is always fit
+ data.settings.ws = 1;
+ delete data.dlOpts.fitwidth;
+ delete data.dlOpts.fitheight;
+ redisplay(data);
+ return false;
+ };
+
+ // clear old handler (also ZoomDrag)
+ $scaler.unbind('.dlZoomArea');
+ $scaler.unbind(".dlZoomDrag");
+ $elem.unbind('.dlZoomArea');
+ // bind start zoom handler
+ $scaler.one('mousedown.dlZoomArea', zoomStart);
+ };
+
+ // bird's eye view zoom area click and drag handler
+ var setupBirdDrag = function(data) {
+ var $birdImg = data.$birdImg;
+ var $birdZoom = data.$birdZoom;
+ var $document = $(document);
+ var $scaler = data.$scaler;
+ var startPos, newRect, birdImgRect, birdZoomRect, fullRect, scalerPos;
+
+ // mousedown handler: start dragging bird zoom to a new position
+ var birdZoomStartDrag = function(evt) {
+ startPos = geom.position(evt);
+ // position may have changed
+ data.birdTrafo = getImgTrafo($birdImg, FULL_AREA);
+ birdImgRect = geom.rectangle($birdImg);
+ birdZoomRect = geom.rectangle($birdZoom);
+ scalerPos = geom.position($scaler);
+ newRect = null;
+ fullRect = setZoomBG(data); // setup zoom background image
+ $document.bind("mousemove.dlBirdMove", birdZoomMove);
+ $document.bind("mouseup.dlBirdMove", birdZoomEndDrag);
+ return false;
+ };
+
+ // mousemove handler: drag
+ var birdZoomMove = function(evt) {
+ var pos = geom.position(evt);
+ var delta = startPos.delta(pos);
+ // move birdZoom div, keeping size
+ newRect = birdZoomRect.copy();
+ newRect.addPosition(delta);
+ newRect.stayInside(birdImgRect);
+ // reflect birdview zoom position in scaler image
+ var area = data.birdTrafo.invtransform(newRect);
+ var imgArea = data.imgTrafo.transform(area);
+ var offset = imgArea.getPosition().neg();
+ offset.add(scalerPos);
+ console.log('offset', offset);
+ if (fullRect) {
+ var bgPos = fullRect.getPosition().add(offset);
+ } else {
+ var bgPos = offset;
+ }
+ // move the background image to the new position
+ data.$scaler.css({
+ 'background-position' : bgPos.x + "px " + bgPos.y + "px"
+ });
+ // acount for border width
+ newRect.addPosition({x : -2, y : -2});
+ newRect.adjustDiv($birdZoom);
+ return false;
+ };
+
+ // mouseup handler: reload page
+ var birdZoomEndDrag = function(evt) {
+ var settings = data.settings;
+ $document.unbind("mousemove.dlBirdMove", birdZoomMove);
+ $document.unbind("mouseup.dlBirdMove", birdZoomEndDrag);
+ if (newRect == null) {
+ // no movement happened - set center to click position
+ startPos = birdZoomRect.getCenter();
+ birdZoomMove(evt);
+ }
+ // ugly, but needed to prevent double border width compensation
+ newRect.addPosition({x : +2, y : +2});
+ var newArea = data.birdTrafo.invtransform(newRect);
+ data.zoomArea = newArea;
+ redisplay(data);
+ return false;
+ };
+
+ // clear old handler
+ $document.unbind(".dlBirdMove");
+ $birdImg.unbind(".dlBirdMove");
+ $birdZoom.unbind(".dlBirdMove");
+ if (! isFullArea(data.zoomArea)) {
+ // set new handler
+ $birdImg.bind("mousedown.dlBirdMove", birdZoomStartDrag);
+ $birdZoom.bind("mousedown.dlBirdMove", birdZoomStartDrag);
+ }
+ };
+
+ // move bird zoom indicator to reflect zoomed detail area
+ var setBirdZoom = function(data, rect) {
+ var part = data.imgTrafo.invtransform(rect);
+ // area = FULL_AREA.fit(part); // no, we want to see where we transcend the borders
+ birdTrafo = getImgTrafo(data.$birdImg, FULL_AREA);
+ var birdRect = birdTrafo.transform(part);
+ // acount for border width
+ birdRect.addPosition({x : -2, y : -2});
+ birdRect.adjustDiv(data.$birdZoom);
+ };
+
+ // set zoom background
+ var setZoomBG = function(data) {
+ var $scaler = data.$scaler;
+ var $img = data.$img;
+ var fullRect = null;
+ // hide the scaler img, show background of div instead
+ $img.css('visibility', 'hidden');
+ var scalerCss = {
+ 'background-image' : 'url(' + $img.attr('src') + ')',
+ 'background-repeat' : 'no-repeat',
+ 'background-position' : 'left top',
+ 'opacity' : '0.5',
+ 'cursor' : 'move'
+ };
+ if (data.hasBgSize) {
+ // full-size background using CSS3-background-size
+ fullRect = data.imgTrafo.transform(FULL_AREA);
+ if (fullRect.height < data.settings.maxBgSize && fullRect.width < data.settings.maxBgSize) {
+ // correct offset because background is relative
+ var scalerPos = geom.position($scaler);
+ fullRect.addPosition(scalerPos.neg());
+ var url = getBirdImgUrl(data, ['rot', 'mo']);
+ scalerCss['background-image'] = 'url(' + url + ')';
+ scalerCss[data.bgSizeName] = fullRect.width + 'px ' + fullRect.height + 'px';
+ scalerCss['background-position'] = fullRect.x + 'px '+ fullRect.y + 'px';
+ } else {
+ // too big
+ fullRect = null;
+ }
+ }
+ $scaler.css(scalerCss);
+ // isBgReady = true;
+ return fullRect;
+ };
+
+ // setup handlers for dragging the zoomed image
+ var setupZoomDrag = function(data) {
+ var startPos, delta, fullRect;
+ var $document = $(document);
+ var $elem = data.$elem;
+ var $scaler = data.$scaler;
+ var $img = data.$img;
+
+ // drag the image and load a new detail on mouse up
+ var dragStart = function (evt) {
+ console.debug("dragstart at=",evt);
+ // don't start dragging if not zoomed
+ if (isFullArea(data.zoomArea)) return false;
+ startPos = geom.position(evt);
+ delta = null;
+ // set low res background immediately on mousedown
+ fullRect = setZoomBG(data);
+ $document.bind("mousemove.dlZoomDrag", dragMove);
+ $document.bind("mouseup.dlZoomDrag", dragEnd);
+ return false;
+ };
+
+ // mousemove handler: drag zoomed image
+ var dragMove = function (evt) {
+ var pos = geom.position(evt);
+ delta = startPos.delta(pos);
+ if (fullRect) {
+ var bgPos = fullRect.getPosition().add(delta);
+ } else {
+ var bgPos = delta;
+ }
+ // move the background image to the new position
+ $scaler.css({
+ 'background-position' : bgPos.x + "px " + bgPos.y + "px"
+ });
+ // set birdview indicator to reflect new zoom position
+ var za = geom.rectangle($img);
+ za.addPosition(delta.neg());
+ setBirdZoom(data, za);
+ return false;
+ };
+
+ // mouseup handler: reload zoomed image in new position
+ var dragEnd = function (evt) {
+ $scaler.css('cursor', 'auto');
+ $document.unbind("mousemove.dlZoomDrag", dragMove);
+ $document.unbind("mouseup.dlZoomDrag", dragEnd);
+ if (delta == null || delta.distance() < 2) {
+ // no movement
+ $img.css('visibility', 'visible');
+ $scaler.css({'opacity' : '1', 'background-image' : 'none'});
+ return false;
+ }
+ // get old zoom area (screen coordinates)
+ var za = geom.rectangle($img);
+ // move
+ za.addPosition(delta.neg());
+ // transform back
+ var newArea = data.imgTrafo.invtransform(za);
+ data.zoomArea = FULL_AREA.fit(newArea);
+ redisplay(data);
+ return false;
+ };
+
+ // clear old handler
+ $document.unbind(".dlZoomDrag");
+ $scaler.unbind(".dlZoomDrag");
+ if (! isFullArea(data.zoomArea)) {
+ // set handler
+ $scaler.bind("mousedown.dlZoomDrag", dragStart);
+ }
+ };
+
+ // get image quality as a number (0..2)
+ var getQuality = function (data) {
+ var flags = data.scalerFlags;
+ var q = flags.q2 || flags.q1 || 'q0'; // assume q0 as default
+ return parseInt(q[1], 10);
+ };
+
+ // set image quality as a number (0..2)
+ var setQuality = function (data, qual) {
+ var flags = data.scalerFlags;
+ // clear flags
+ for (var i = 0; i < 3; ++i) {
+ delete flags['q'+i];
+ }
+ flags['q'+qual] = 'q'+qual;
+ };
+
+ // 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];
+ };
+
+ // auxiliary function (from old dllib.js)
+ var isFullArea = function(area) {
+ return (area.width === 1.0) && (area.height === 1.0);
+ };
+
+ // auxiliary function (from Douglas Crockford, A.10)
+ var isNumber = function isNumber(value) {
+ return typeof value === 'number' && isFinite(value);
+ };
+
+ // auxiliary function to crop senseless precision
+ var cropFloat = function (x) {
+ return parseInt(10000 * x, 10) / 10000;
+ };
+
+ // fallback for console.log calls
+ if (customConsole) {
+ var logFunction = function(type) {
+ return function(){
+ var $debug = $('#debug'); // debug div
+ if (!$debug) return;
+ var args = Array.prototype.slice.call(arguments);
+ var argtext = args.join(' ');
+ var $logDiv = $('
');
+ $logDiv.addClass(type);
+ $logDiv.text(argtext);
+ $debug.append($logDiv);
+ };
+ };
+ console.log = logFunction('_log');
+ console.debug = logFunction('_debug');
+ console.error = logFunction('_error');
+ }
+
+ // hook plugin into jquery
+ $.fn.digilib = function(action) {
+ if (actions[action]) {
+ // call action on this with the remaining arguments (inserting data as first argument)
+ var $elem = $(this);
+ var data = $elem.data('digilib');
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(data);
+ return actions[action].apply(this, args);
+ } else if (typeof(action) === 'object' || !action) {
+ // call init on this
+ return actions.init.apply(this, arguments);
+ } else {
+ $.error('action ' + action + ' does not exist on jQuery.digilib');
+ }
+ };
+
+})(jQuery);
\ No newline at end of file
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.button.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.button.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,373 @@
+/*
+ * jQuery UI Button 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var lastActive,
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+ stateClasses = "ui-state-hover ui-state-active ",
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+ formResetHandler = function( event ) {
+ $( ":ui-button", event.target.form ).each(function() {
+ var inst = $( this ).data( "button" );
+ setTimeout(function() {
+ inst.refresh();
+ }, 1 );
+ });
+ },
+ radioGroup = function( radio ) {
+ var name = radio.name,
+ form = radio.form,
+ radios = $( [] );
+ if ( name ) {
+ if ( form ) {
+ radios = $( form ).find( "[name='" + name + "']" );
+ } else {
+ radios = $( "[name='" + name + "']", radio.ownerDocument )
+ .filter(function() {
+ return !this.form;
+ });
+ }
+ }
+ return radios;
+ };
+
+$.widget( "ui.button", {
+ options: {
+ disabled: null,
+ text: true,
+ label: null,
+ icons: {
+ primary: null,
+ secondary: null
+ }
+ },
+ _create: function() {
+ this.element.closest( "form" )
+ .unbind( "reset.button" )
+ .bind( "reset.button", formResetHandler );
+
+ if ( typeof this.options.disabled !== "boolean" ) {
+ this.options.disabled = this.element.attr( "disabled" );
+ }
+
+ this._determineButtonType();
+ this.hasTitle = !!this.buttonElement.attr( "title" );
+
+ var self = this,
+ options = this.options,
+ toggleButton = this.type === "checkbox" || this.type === "radio",
+ hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
+ focusClass = "ui-state-focus";
+
+ if ( options.label === null ) {
+ options.label = this.buttonElement.html();
+ }
+
+ if ( this.element.is( ":disabled" ) ) {
+ options.disabled = true;
+ }
+
+ this.buttonElement
+ .addClass( baseClasses )
+ .attr( "role", "button" )
+ .bind( "mouseenter.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).addClass( "ui-state-hover" );
+ if ( this === lastActive ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "mouseleave.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( hoverClass );
+ })
+ .bind( "focus.button", function() {
+ // no need to check disabled, focus won't be triggered anyway
+ $( this ).addClass( focusClass );
+ })
+ .bind( "blur.button", function() {
+ $( this ).removeClass( focusClass );
+ });
+
+ if ( toggleButton ) {
+ this.element.bind( "change.button", function() {
+ self.refresh();
+ });
+ }
+
+ if ( this.type === "checkbox" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).toggleClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", self.element[0].checked );
+ });
+ } else if ( this.type === "radio" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", true );
+
+ var radio = self.element[ 0 ];
+ radioGroup( radio )
+ .not( radio )
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ });
+ } else {
+ this.buttonElement
+ .bind( "mousedown.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ lastActive = this;
+ $( document ).one( "mouseup", function() {
+ lastActive = null;
+ });
+ })
+ .bind( "mouseup.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).removeClass( "ui-state-active" );
+ })
+ .bind( "keydown.button", function(event) {
+ if ( options.disabled ) {
+ return false;
+ }
+ if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "keyup.button", function() {
+ $( this ).removeClass( "ui-state-active" );
+ });
+
+ if ( this.buttonElement.is("a") ) {
+ this.buttonElement.keyup(function(event) {
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
+ $( this ).click();
+ }
+ });
+ }
+ }
+
+ // TODO: pull out $.Widget's handling for the disabled option into
+ // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+ // be overridden by individual plugins
+ this._setOption( "disabled", options.disabled );
+ },
+
+ _determineButtonType: function() {
+
+ if ( this.element.is(":checkbox") ) {
+ this.type = "checkbox";
+ } else {
+ if ( this.element.is(":radio") ) {
+ this.type = "radio";
+ } else {
+ if ( this.element.is("input") ) {
+ this.type = "input";
+ } else {
+ this.type = "button";
+ }
+ }
+ }
+
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ // we don't search against the document in case the element
+ // is disconnected from the DOM
+ this.buttonElement = this.element.parents().last()
+ .find( "label[for=" + this.element.attr("id") + "]" );
+ this.element.addClass( "ui-helper-hidden-accessible" );
+
+ var checked = this.element.is( ":checked" );
+ if ( checked ) {
+ this.buttonElement.addClass( "ui-state-active" );
+ }
+ this.buttonElement.attr( "aria-pressed", checked );
+ } else {
+ this.buttonElement = this.element;
+ }
+ },
+
+ widget: function() {
+ return this.buttonElement;
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-helper-hidden-accessible" );
+ this.buttonElement
+ .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+ .removeAttr( "role" )
+ .removeAttr( "aria-pressed" )
+ .html( this.buttonElement.find(".ui-button-text").html() );
+
+ if ( !this.hasTitle ) {
+ this.buttonElement.removeAttr( "title" );
+ }
+
+ $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key, value ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.attr( "disabled", true );
+ } else {
+ this.element.removeAttr( "disabled" );
+ }
+ }
+ this._resetButton();
+ },
+
+ refresh: function() {
+ var isDisabled = this.element.is( ":disabled" );
+ if ( isDisabled !== this.options.disabled ) {
+ this._setOption( "disabled", isDisabled );
+ }
+ if ( this.type === "radio" ) {
+ radioGroup( this.element[0] ).each(function() {
+ if ( $( this ).is( ":checked" ) ) {
+ $( this ).button( "widget" )
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", true );
+ } else {
+ $( this ).button( "widget" )
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ }
+ });
+ } else if ( this.type === "checkbox" ) {
+ if ( this.element.is( ":checked" ) ) {
+ this.buttonElement
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", true );
+ } else {
+ this.buttonElement
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ }
+ }
+ },
+
+ _resetButton: function() {
+ if ( this.type === "input" ) {
+ if ( this.options.label ) {
+ this.element.val( this.options.label );
+ }
+ return;
+ }
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
+ buttonText = $( " " )
+ .addClass( "ui-button-text" )
+ .html( this.options.label )
+ .appendTo( buttonElement.empty() )
+ .text(),
+ icons = this.options.icons,
+ multipleIcons = icons.primary && icons.secondary;
+ if ( icons.primary || icons.secondary ) {
+ buttonElement.addClass( "ui-button-text-icon" +
+ ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+ if ( icons.primary ) {
+ buttonElement.prepend( " " );
+ }
+ if ( icons.secondary ) {
+ buttonElement.append( " " );
+ }
+ if ( !this.options.text ) {
+ buttonElement
+ .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
+ .removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
+ if ( !this.hasTitle ) {
+ buttonElement.attr( "title", buttonText );
+ }
+ }
+ } else {
+ buttonElement.addClass( "ui-button-text-only" );
+ }
+ }
+});
+
+$.widget( "ui.buttonset", {
+ options: {
+ items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
+ },
+
+ _create: function() {
+ this.element.addClass( "ui-buttonset" );
+ },
+
+ _init: function() {
+ this.refresh();
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "disabled" ) {
+ this.buttons.button( "option", key, value );
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+ },
+
+ refresh: function() {
+ this.buttons = this.element.find( this.options.items )
+ .filter( ":ui-button" )
+ .button( "refresh" )
+ .end()
+ .not( ":ui-button" )
+ .button()
+ .end()
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+ .filter( ":first" )
+ .addClass( "ui-corner-left" )
+ .end()
+ .filter( ":last" )
+ .addClass( "ui-corner-right" )
+ .end()
+ .end();
+ },
+
+ destroy: function() {
+ this.element.removeClass( "ui-buttonset" );
+ this.buttons
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-left ui-corner-right" )
+ .end()
+ .button( "destroy" );
+
+ $.Widget.prototype.destroy.call( this );
+ }
+});
+
+}( jQuery ) );
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.core.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.core.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,308 @@
+/*!
+ * jQuery UI 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */
+(function( $, undefined ) {
+
+// prevent duplicate loading
+// this is only a problem because we proxy existing functions
+// and we don't want to double proxy them
+$.ui = $.ui || {};
+if ( $.ui.version ) {
+ return;
+}
+
+$.extend( $.ui, {
+ version: "1.8.9",
+
+ keyCode: {
+ ALT: 18,
+ BACKSPACE: 8,
+ CAPS_LOCK: 20,
+ COMMA: 188,
+ COMMAND: 91,
+ COMMAND_LEFT: 91, // COMMAND
+ COMMAND_RIGHT: 93,
+ CONTROL: 17,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ INSERT: 45,
+ LEFT: 37,
+ MENU: 93, // COMMAND_RIGHT
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SHIFT: 16,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38,
+ WINDOWS: 91 // COMMAND
+ }
+});
+
+// plugins
+$.fn.extend({
+ _focus: $.fn.focus,
+ focus: function( delay, fn ) {
+ return typeof delay === "number" ?
+ this.each(function() {
+ var elem = this;
+ setTimeout(function() {
+ $( elem ).focus();
+ if ( fn ) {
+ fn.call( elem );
+ }
+ }, delay );
+ }) :
+ this._focus.apply( this, arguments );
+ },
+
+ scrollParent: function() {
+ var scrollParent;
+ if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ },
+
+ zIndex: function( zIndex ) {
+ if ( zIndex !== undefined ) {
+ return this.css( "zIndex", zIndex );
+ }
+
+ if ( this.length ) {
+ var elem = $( this[ 0 ] ), position, value;
+ while ( elem.length && elem[ 0 ] !== document ) {
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
+ // This makes behavior of this function consistent across browsers
+ // WebKit always returns auto if the element is positioned
+ position = elem.css( "position" );
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+ // IE returns 0 when zIndex is not specified
+ // other browsers return a string
+ // we ignore the case of nested elements with an explicit value of 0
+ //
+ value = parseInt( elem.css( "zIndex" ), 10 );
+ if ( !isNaN( value ) && value !== 0 ) {
+ return value;
+ }
+ }
+ elem = elem.parent();
+ }
+ }
+
+ return 0;
+ },
+
+ disableSelection: function() {
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
+ ".ui-disableSelection", function( event ) {
+ event.preventDefault();
+ });
+ },
+
+ enableSelection: function() {
+ return this.unbind( ".ui-disableSelection" );
+ }
+});
+
+$.each( [ "Width", "Height" ], function( i, name ) {
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+ type = name.toLowerCase(),
+ orig = {
+ innerWidth: $.fn.innerWidth,
+ innerHeight: $.fn.innerHeight,
+ outerWidth: $.fn.outerWidth,
+ outerHeight: $.fn.outerHeight
+ };
+
+ function reduce( elem, size, border, margin ) {
+ $.each( side, function() {
+ size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
+ if ( border ) {
+ size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
+ }
+ if ( margin ) {
+ size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
+ }
+ });
+ return size;
+ }
+
+ $.fn[ "inner" + name ] = function( size ) {
+ if ( size === undefined ) {
+ return orig[ "inner" + name ].call( this );
+ }
+
+ return this.each(function() {
+ $( this ).css( type, reduce( this, size ) + "px" );
+ });
+ };
+
+ $.fn[ "outer" + name] = function( size, margin ) {
+ if ( typeof size !== "number" ) {
+ return orig[ "outer" + name ].call( this, size );
+ }
+
+ return this.each(function() {
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
+ });
+ };
+});
+
+// selectors
+function visible( element ) {
+ return !$( element ).parents().andSelf().filter(function() {
+ return $.curCSS( this, "visibility" ) === "hidden" ||
+ $.expr.filters.hidden( this );
+ }).length;
+}
+
+$.extend( $.expr[ ":" ], {
+ data: function( elem, i, match ) {
+ return !!$.data( elem, match[ 3 ] );
+ },
+
+ focusable: function( element ) {
+ var nodeName = element.nodeName.toLowerCase(),
+ tabIndex = $.attr( element, "tabindex" );
+ if ( "area" === nodeName ) {
+ var map = element.parentNode,
+ mapName = map.name,
+ img;
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+ return false;
+ }
+ img = $( "img[usemap=#" + mapName + "]" )[0];
+ return !!img && visible( img );
+ }
+ return ( /input|select|textarea|button|object/.test( nodeName )
+ ? !element.disabled
+ : "a" == nodeName
+ ? element.href || !isNaN( tabIndex )
+ : !isNaN( tabIndex ))
+ // the element and all of its ancestors must be visible
+ && visible( element );
+ },
+
+ tabbable: function( element ) {
+ var tabIndex = $.attr( element, "tabindex" );
+ return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
+ }
+});
+
+// support
+$(function() {
+ var body = document.body,
+ div = body.appendChild( div = document.createElement( "div" ) );
+
+ $.extend( div.style, {
+ minHeight: "100px",
+ height: "auto",
+ padding: 0,
+ borderWidth: 0
+ });
+
+ $.support.minHeight = div.offsetHeight === 100;
+ $.support.selectstart = "onselectstart" in div;
+
+ // set display to none to avoid a layout bug in IE
+ // http://dev.jquery.com/ticket/4014
+ body.removeChild( div ).style.display = "none";
+});
+
+
+
+
+
+// deprecated
+$.extend( $.ui, {
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
+ plugin: {
+ add: function( module, option, set ) {
+ var proto = $.ui[ module ].prototype;
+ for ( var i in set ) {
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
+ }
+ },
+ call: function( instance, name, args ) {
+ var set = instance.plugins[ name ];
+ if ( !set || !instance.element[ 0 ].parentNode ) {
+ return;
+ }
+
+ for ( var i = 0; i < set.length; i++ ) {
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
+ set[ i ][ 1 ].apply( instance.element, args );
+ }
+ }
+ }
+ },
+
+ // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
+ contains: function( a, b ) {
+ return document.compareDocumentPosition ?
+ a.compareDocumentPosition( b ) & 16 :
+ a !== b && a.contains( b );
+ },
+
+ // only used by resizable
+ hasScroll: function( el, a ) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ( $( el ).css( "overflow" ) === "hidden") {
+ return false;
+ }
+
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+ has = false;
+
+ if ( el[ scroll ] > 0 ) {
+ return true;
+ }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[ scroll ] = 1;
+ has = ( el[ scroll ] > 0 );
+ el[ scroll ] = 0;
+ return has;
+ },
+
+ // these are odd functions, fix the API or move into individual plugins
+ isOverAxis: function( x, reference, size ) {
+ //Determines when x coordinate is over "b" element axis
+ return ( x > reference ) && ( x < ( reference + size ) );
+ },
+ isOver: function( y, x, top, left, height, width ) {
+ //Determines when x, y coordinates is over "b" element
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
+ }
+});
+
+})( jQuery );
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.dialog.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.dialog.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,857 @@
+/*
+ * jQuery UI Dialog 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
+ */
+(function( $, undefined ) {
+
+var uiDialogClasses =
+ 'ui-dialog ' +
+ 'ui-widget ' +
+ 'ui-widget-content ' +
+ 'ui-corner-all ',
+ sizeRelatedOptions = {
+ buttons: true,
+ height: true,
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true,
+ width: true
+ },
+ resizableRelatedOptions = {
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true
+ };
+
+$.widget("ui.dialog", {
+ options: {
+ autoOpen: true,
+ buttons: {},
+ closeOnEscape: true,
+ closeText: 'close',
+ dialogClass: '',
+ draggable: true,
+ hide: null,
+ height: 'auto',
+ maxHeight: false,
+ maxWidth: false,
+ minHeight: 150,
+ minWidth: 150,
+ modal: false,
+ position: {
+ my: 'center',
+ at: 'center',
+ collision: 'fit',
+ // ensure that the titlebar is never outside the document
+ using: function(pos) {
+ var topOffset = $(this).css(pos).offset().top;
+ if (topOffset < 0) {
+ $(this).css('top', pos.top - topOffset);
+ }
+ }
+ },
+ resizable: true,
+ show: null,
+ stack: true,
+ title: '',
+ width: 300,
+ zIndex: 1000
+ },
+
+ _create: function() {
+ this.originalTitle = this.element.attr('title');
+ // #5742 - .attr() might return a DOMElement
+ if ( typeof this.originalTitle !== "string" ) {
+ this.originalTitle = "";
+ }
+
+ this.options.title = this.options.title || this.originalTitle;
+ var self = this,
+ options = self.options,
+
+ title = options.title || ' ',
+ titleId = $.ui.dialog.getTitleId(self.element),
+
+ uiDialog = (self.uiDialog = $('
'))
+ .appendTo(document.body)
+ .hide()
+ .addClass(uiDialogClasses + options.dialogClass)
+ .css({
+ zIndex: options.zIndex
+ })
+ // setting tabIndex makes the div focusable
+ // setting outline to 0 prevents a border on focus in Mozilla
+ .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
+ if (options.closeOnEscape && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ self.close(event);
+ event.preventDefault();
+ }
+ })
+ .attr({
+ role: 'dialog',
+ 'aria-labelledby': titleId
+ })
+ .mousedown(function(event) {
+ self.moveToTop(false, event);
+ }),
+
+ uiDialogContent = self.element
+ .show()
+ .removeAttr('title')
+ .addClass(
+ 'ui-dialog-content ' +
+ 'ui-widget-content')
+ .appendTo(uiDialog),
+
+ uiDialogTitlebar = (self.uiDialogTitlebar = $('
'))
+ .addClass(
+ 'ui-dialog-titlebar ' +
+ 'ui-widget-header ' +
+ 'ui-corner-all ' +
+ 'ui-helper-clearfix'
+ )
+ .prependTo(uiDialog),
+
+ uiDialogTitlebarClose = $(' ')
+ .addClass(
+ 'ui-dialog-titlebar-close ' +
+ 'ui-corner-all'
+ )
+ .attr('role', 'button')
+ .hover(
+ function() {
+ uiDialogTitlebarClose.addClass('ui-state-hover');
+ },
+ function() {
+ uiDialogTitlebarClose.removeClass('ui-state-hover');
+ }
+ )
+ .focus(function() {
+ uiDialogTitlebarClose.addClass('ui-state-focus');
+ })
+ .blur(function() {
+ uiDialogTitlebarClose.removeClass('ui-state-focus');
+ })
+ .click(function(event) {
+ self.close(event);
+ return false;
+ })
+ .appendTo(uiDialogTitlebar),
+
+ uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $(' '))
+ .addClass(
+ 'ui-icon ' +
+ 'ui-icon-closethick'
+ )
+ .text(options.closeText)
+ .appendTo(uiDialogTitlebarClose),
+
+ uiDialogTitle = $(' ')
+ .addClass('ui-dialog-title')
+ .attr('id', titleId)
+ .html(title)
+ .prependTo(uiDialogTitlebar);
+
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
+ options.beforeClose = options.beforeclose;
+ }
+
+ uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+
+ if (options.draggable && $.fn.draggable) {
+ self._makeDraggable();
+ }
+ if (options.resizable && $.fn.resizable) {
+ self._makeResizable();
+ }
+
+ self._createButtons(options.buttons);
+ self._isOpen = false;
+
+ if ($.fn.bgiframe) {
+ uiDialog.bgiframe();
+ }
+ },
+
+ _init: function() {
+ if ( this.options.autoOpen ) {
+ this.open();
+ }
+ },
+
+ destroy: function() {
+ var self = this;
+
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
+ self.uiDialog.hide();
+ self.element
+ .unbind('.dialog')
+ .removeData('dialog')
+ .removeClass('ui-dialog-content ui-widget-content')
+ .hide().appendTo('body');
+ self.uiDialog.remove();
+
+ if (self.originalTitle) {
+ self.element.attr('title', self.originalTitle);
+ }
+
+ return self;
+ },
+
+ widget: function() {
+ return this.uiDialog;
+ },
+
+ close: function(event) {
+ var self = this,
+ maxZ, thisZ;
+
+ if (false === self._trigger('beforeClose', event)) {
+ return;
+ }
+
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
+ self.uiDialog.unbind('keypress.ui-dialog');
+
+ self._isOpen = false;
+
+ if (self.options.hide) {
+ self.uiDialog.hide(self.options.hide, function() {
+ self._trigger('close', event);
+ });
+ } else {
+ self.uiDialog.hide();
+ self._trigger('close', event);
+ }
+
+ $.ui.dialog.overlay.resize();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ if (self.options.modal) {
+ maxZ = 0;
+ $('.ui-dialog').each(function() {
+ if (this !== self.uiDialog[0]) {
+ thisZ = $(this).css('z-index');
+ if(!isNaN(thisZ)) {
+ maxZ = Math.max(maxZ, thisZ);
+ }
+ }
+ });
+ $.ui.dialog.maxZ = maxZ;
+ }
+
+ return self;
+ },
+
+ isOpen: function() {
+ return this._isOpen;
+ },
+
+ // the force parameter allows us to move modal dialogs to their correct
+ // position on open
+ moveToTop: function(force, event) {
+ var self = this,
+ options = self.options,
+ saveScroll;
+
+ if ((options.modal && !force) ||
+ (!options.stack && !options.modal)) {
+ return self._trigger('focus', event);
+ }
+
+ if (options.zIndex > $.ui.dialog.maxZ) {
+ $.ui.dialog.maxZ = options.zIndex;
+ }
+ if (self.overlay) {
+ $.ui.dialog.maxZ += 1;
+ self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
+ }
+
+ //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
+ // http://ui.jquery.com/bugs/ticket/3193
+ saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
+ $.ui.dialog.maxZ += 1;
+ self.uiDialog.css('z-index', $.ui.dialog.maxZ);
+ self.element.attr(saveScroll);
+ self._trigger('focus', event);
+
+ return self;
+ },
+
+ open: function() {
+ if (this._isOpen) { return; }
+
+ var self = this,
+ options = self.options,
+ uiDialog = self.uiDialog;
+
+ self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+ self._size();
+ self._position(options.position);
+ uiDialog.show(options.show);
+ self.moveToTop(true);
+
+ // prevent tabbing out of modal dialogs
+ if (options.modal) {
+ uiDialog.bind('keypress.ui-dialog', function(event) {
+ if (event.keyCode !== $.ui.keyCode.TAB) {
+ return;
+ }
+
+ var tabbables = $(':tabbable', this),
+ first = tabbables.filter(':first'),
+ last = tabbables.filter(':last');
+
+ if (event.target === last[0] && !event.shiftKey) {
+ first.focus(1);
+ return false;
+ } else if (event.target === first[0] && event.shiftKey) {
+ last.focus(1);
+ return false;
+ }
+ });
+ }
+
+ // set focus to the first tabbable element in the content area or the first button
+ // if there are no tabbable elements, set focus on the dialog itself
+ $(self.element.find(':tabbable').get().concat(
+ uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
+ uiDialog.get()))).eq(0).focus();
+
+ self._isOpen = true;
+ self._trigger('open');
+
+ return self;
+ },
+
+ _createButtons: function(buttons) {
+ var self = this,
+ hasButtons = false,
+ uiDialogButtonPane = $('
')
+ .addClass(
+ 'ui-dialog-buttonpane ' +
+ 'ui-widget-content ' +
+ 'ui-helper-clearfix'
+ ),
+ uiButtonSet = $( "
" )
+ .addClass( "ui-dialog-buttonset" )
+ .appendTo( uiDialogButtonPane );
+
+ // if we already have a button pane, remove it
+ self.uiDialog.find('.ui-dialog-buttonpane').remove();
+
+ if (typeof buttons === 'object' && buttons !== null) {
+ $.each(buttons, function() {
+ return !(hasButtons = true);
+ });
+ }
+ if (hasButtons) {
+ $.each(buttons, function(name, props) {
+ props = $.isFunction( props ) ?
+ { click: props, text: name } :
+ props;
+ var button = $(' ')
+ .attr( props, true )
+ .unbind('click')
+ .click(function() {
+ props.click.apply(self.element[0], arguments);
+ })
+ .appendTo(uiButtonSet);
+ if ($.fn.button) {
+ button.button();
+ }
+ });
+ uiDialogButtonPane.appendTo(self.uiDialog);
+ }
+ },
+
+ _makeDraggable: function() {
+ var self = this,
+ options = self.options,
+ doc = $(document),
+ heightBeforeDrag;
+
+ function filteredUi(ui) {
+ return {
+ position: ui.position,
+ offset: ui.offset
+ };
+ }
+
+ self.uiDialog.draggable({
+ cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
+ handle: '.ui-dialog-titlebar',
+ containment: 'document',
+ start: function(event, ui) {
+ heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
+ $(this).height($(this).height()).addClass("ui-dialog-dragging");
+ self._trigger('dragStart', event, filteredUi(ui));
+ },
+ drag: function(event, ui) {
+ self._trigger('drag', event, filteredUi(ui));
+ },
+ stop: function(event, ui) {
+ options.position = [ui.position.left - doc.scrollLeft(),
+ ui.position.top - doc.scrollTop()];
+ $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
+ self._trigger('dragStop', event, filteredUi(ui));
+ $.ui.dialog.overlay.resize();
+ }
+ });
+ },
+
+ _makeResizable: function(handles) {
+ handles = (handles === undefined ? this.options.resizable : handles);
+ var self = this,
+ options = self.options,
+ // .ui-resizable has position: relative defined in the stylesheet
+ // but dialogs have to use absolute or fixed positioning
+ position = self.uiDialog.css('position'),
+ resizeHandles = (typeof handles === 'string' ?
+ handles :
+ 'n,e,s,w,se,sw,ne,nw'
+ );
+
+ function filteredUi(ui) {
+ return {
+ originalPosition: ui.originalPosition,
+ originalSize: ui.originalSize,
+ position: ui.position,
+ size: ui.size
+ };
+ }
+
+ self.uiDialog.resizable({
+ cancel: '.ui-dialog-content',
+ containment: 'document',
+ alsoResize: self.element,
+ maxWidth: options.maxWidth,
+ maxHeight: options.maxHeight,
+ minWidth: options.minWidth,
+ minHeight: self._minHeight(),
+ handles: resizeHandles,
+ start: function(event, ui) {
+ $(this).addClass("ui-dialog-resizing");
+ self._trigger('resizeStart', event, filteredUi(ui));
+ },
+ resize: function(event, ui) {
+ self._trigger('resize', event, filteredUi(ui));
+ },
+ stop: function(event, ui) {
+ $(this).removeClass("ui-dialog-resizing");
+ options.height = $(this).height();
+ options.width = $(this).width();
+ self._trigger('resizeStop', event, filteredUi(ui));
+ $.ui.dialog.overlay.resize();
+ }
+ })
+ .css('position', position)
+ .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
+ },
+
+ _minHeight: function() {
+ var options = this.options;
+
+ if (options.height === 'auto') {
+ return options.minHeight;
+ } else {
+ return Math.min(options.minHeight, options.height);
+ }
+ },
+
+ _position: function(position) {
+ var myAt = [],
+ offset = [0, 0],
+ isVisible;
+
+ if (position) {
+ // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
+ // if (typeof position == 'string' || $.isArray(position)) {
+ // myAt = $.isArray(position) ? position : position.split(' ');
+
+ if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
+ myAt = position.split ? position.split(' ') : [position[0], position[1]];
+ if (myAt.length === 1) {
+ myAt[1] = myAt[0];
+ }
+
+ $.each(['left', 'top'], function(i, offsetPosition) {
+ if (+myAt[i] === myAt[i]) {
+ offset[i] = myAt[i];
+ myAt[i] = offsetPosition;
+ }
+ });
+
+ position = {
+ my: myAt.join(" "),
+ at: myAt.join(" "),
+ offset: offset.join(" ")
+ };
+ }
+
+ position = $.extend({}, $.ui.dialog.prototype.options.position, position);
+ } else {
+ position = $.ui.dialog.prototype.options.position;
+ }
+
+ // need to show the dialog to get the actual offset in the position plugin
+ isVisible = this.uiDialog.is(':visible');
+ if (!isVisible) {
+ this.uiDialog.show();
+ }
+ this.uiDialog
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+ .css({ top: 0, left: 0 })
+ .position($.extend({ of: window }, position));
+ if (!isVisible) {
+ this.uiDialog.hide();
+ }
+ },
+
+ _setOptions: function( options ) {
+ var self = this,
+ resizableOptions = {},
+ resize = false;
+
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
+
+ if ( key in sizeRelatedOptions ) {
+ resize = true;
+ }
+ if ( key in resizableRelatedOptions ) {
+ resizableOptions[ key ] = value;
+ }
+ });
+
+ if ( resize ) {
+ this._size();
+ }
+ if ( this.uiDialog.is( ":data(resizable)" ) ) {
+ this.uiDialog.resizable( "option", resizableOptions );
+ }
+ },
+
+ _setOption: function(key, value){
+ var self = this,
+ uiDialog = self.uiDialog;
+
+ switch (key) {
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ case "beforeclose":
+ key = "beforeClose";
+ break;
+ case "buttons":
+ self._createButtons(value);
+ break;
+ case "closeText":
+ // ensure that we always pass a string
+ self.uiDialogTitlebarCloseText.text("" + value);
+ break;
+ case "dialogClass":
+ uiDialog
+ .removeClass(self.options.dialogClass)
+ .addClass(uiDialogClasses + value);
+ break;
+ case "disabled":
+ if (value) {
+ uiDialog.addClass('ui-dialog-disabled');
+ } else {
+ uiDialog.removeClass('ui-dialog-disabled');
+ }
+ break;
+ case "draggable":
+ var isDraggable = uiDialog.is( ":data(draggable)" );
+ if ( isDraggable && !value ) {
+ uiDialog.draggable( "destroy" );
+ }
+
+ if ( !isDraggable && value ) {
+ self._makeDraggable();
+ }
+ break;
+ case "position":
+ self._position(value);
+ break;
+ case "resizable":
+ // currently resizable, becoming non-resizable
+ var isResizable = uiDialog.is( ":data(resizable)" );
+ if (isResizable && !value) {
+ uiDialog.resizable('destroy');
+ }
+
+ // currently resizable, changing handles
+ if (isResizable && typeof value === 'string') {
+ uiDialog.resizable('option', 'handles', value);
+ }
+
+ // currently non-resizable, becoming resizable
+ if (!isResizable && value !== false) {
+ self._makeResizable(value);
+ }
+ break;
+ case "title":
+ // convert whatever was passed in o a string, for html() to not throw up
+ $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' '));
+ break;
+ }
+
+ $.Widget.prototype._setOption.apply(self, arguments);
+ },
+
+ _size: function() {
+ /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
+ * divs will both have width and height set, so we need to reset them
+ */
+ var options = this.options,
+ nonContentHeight,
+ minContentHeight,
+ isVisible = this.uiDialog.is( ":visible" );
+
+ // reset content sizing
+ this.element.show().css({
+ width: 'auto',
+ minHeight: 0,
+ height: 0
+ });
+
+ if (options.minWidth > options.width) {
+ options.width = options.minWidth;
+ }
+
+ // reset wrapper sizing
+ // determine the height of all the non-content elements
+ nonContentHeight = this.uiDialog.css({
+ height: 'auto',
+ width: options.width
+ })
+ .height();
+ minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
+
+ if ( options.height === "auto" ) {
+ // only needed for IE6 support
+ if ( $.support.minHeight ) {
+ this.element.css({
+ minHeight: minContentHeight,
+ height: "auto"
+ });
+ } else {
+ this.uiDialog.show();
+ var autoHeight = this.element.css( "height", "auto" ).height();
+ if ( !isVisible ) {
+ this.uiDialog.hide();
+ }
+ this.element.height( Math.max( autoHeight, minContentHeight ) );
+ }
+ } else {
+ this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
+ }
+
+ if (this.uiDialog.is(':data(resizable)')) {
+ this.uiDialog.resizable('option', 'minHeight', this._minHeight());
+ }
+ }
+});
+
+$.extend($.ui.dialog, {
+ version: "1.8.9",
+
+ uuid: 0,
+ maxZ: 0,
+
+ getTitleId: function($el) {
+ var id = $el.attr('id');
+ if (!id) {
+ this.uuid += 1;
+ id = this.uuid;
+ }
+ return 'ui-dialog-title-' + id;
+ },
+
+ overlay: function(dialog) {
+ this.$el = $.ui.dialog.overlay.create(dialog);
+ }
+});
+
+$.extend($.ui.dialog.overlay, {
+ instances: [],
+ // reuse old instances due to IE memory leak with alpha transparency (see #5185)
+ oldInstances: [],
+ maxZ: 0,
+ events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
+ function(event) { return event + '.dialog-overlay'; }).join(' '),
+ create: function(dialog) {
+ if (this.instances.length === 0) {
+ // prevent use of anchors and inputs
+ // we use a setTimeout in case the overlay is created from an
+ // event that we're going to be cancelling (see #2804)
+ setTimeout(function() {
+ // handle $(el).dialog().dialog('close') (see #4065)
+ if ($.ui.dialog.overlay.instances.length) {
+ $(document).bind($.ui.dialog.overlay.events, function(event) {
+ // stop events if the z-index of the target is < the z-index of the overlay
+ // we cannot return true when we don't want to cancel the event (#3523)
+ if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
+ return false;
+ }
+ });
+ }
+ }, 1);
+
+ // allow closing by pressing the escape key
+ $(document).bind('keydown.dialog-overlay', function(event) {
+ if (dialog.options.closeOnEscape && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ dialog.close(event);
+ event.preventDefault();
+ }
+ });
+
+ // handle window resize
+ $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
+ }
+
+ var $el = (this.oldInstances.pop() || $('
').addClass('ui-widget-overlay'))
+ .appendTo(document.body)
+ .css({
+ width: this.width(),
+ height: this.height()
+ });
+
+ if ($.fn.bgiframe) {
+ $el.bgiframe();
+ }
+
+ this.instances.push($el);
+ return $el;
+ },
+
+ destroy: function($el) {
+ var indexOf = $.inArray($el, this.instances);
+ if (indexOf != -1){
+ this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
+ }
+
+ if (this.instances.length === 0) {
+ $([document, window]).unbind('.dialog-overlay');
+ }
+
+ $el.remove();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ var maxZ = 0;
+ $.each(this.instances, function() {
+ maxZ = Math.max(maxZ, this.css('z-index'));
+ });
+ this.maxZ = maxZ;
+ },
+
+ height: function() {
+ var scrollHeight,
+ offsetHeight;
+ // handle IE 6
+ if ($.browser.msie && $.browser.version < 7) {
+ scrollHeight = Math.max(
+ document.documentElement.scrollHeight,
+ document.body.scrollHeight
+ );
+ offsetHeight = Math.max(
+ document.documentElement.offsetHeight,
+ document.body.offsetHeight
+ );
+
+ if (scrollHeight < offsetHeight) {
+ return $(window).height() + 'px';
+ } else {
+ return scrollHeight + 'px';
+ }
+ // handle "good" browsers
+ } else {
+ return $(document).height() + 'px';
+ }
+ },
+
+ width: function() {
+ var scrollWidth,
+ offsetWidth;
+ // handle IE 6
+ if ($.browser.msie && $.browser.version < 7) {
+ scrollWidth = Math.max(
+ document.documentElement.scrollWidth,
+ document.body.scrollWidth
+ );
+ offsetWidth = Math.max(
+ document.documentElement.offsetWidth,
+ document.body.offsetWidth
+ );
+
+ if (scrollWidth < offsetWidth) {
+ return $(window).width() + 'px';
+ } else {
+ return scrollWidth + 'px';
+ }
+ // handle "good" browsers
+ } else {
+ return $(document).width() + 'px';
+ }
+ },
+
+ resize: function() {
+ /* If the dialog is draggable and the user drags it past the
+ * right edge of the window, the document becomes wider so we
+ * need to stretch the overlay. If the user then drags the
+ * dialog back to the left, the document will become narrower,
+ * so we need to shrink the overlay to the appropriate size.
+ * This is handled by shrinking the overlay before setting it
+ * to the full document size.
+ */
+ var $overlays = $([]);
+ $.each($.ui.dialog.overlay.instances, function() {
+ $overlays = $overlays.add(this);
+ });
+
+ $overlays.css({
+ width: 0,
+ height: 0
+ }).css({
+ width: $.ui.dialog.overlay.width(),
+ height: $.ui.dialog.overlay.height()
+ });
+ }
+});
+
+$.extend($.ui.dialog.overlay.prototype, {
+ destroy: function() {
+ $.ui.dialog.overlay.destroy(this.$el);
+ }
+});
+
+}(jQuery));
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.draggable.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.draggable.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,797 @@
+/*
+ * jQuery UI Draggable 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.draggable", $.ui.mouse, {
+ widgetEventPrefix: "drag",
+ options: {
+ addClasses: true,
+ appendTo: "parent",
+ axis: false,
+ connectToSortable: false,
+ containment: false,
+ cursor: "auto",
+ cursorAt: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ iframeFix: false,
+ opacity: false,
+ refreshPositions: false,
+ revert: false,
+ revertDuration: 500,
+ scope: "default",
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ snap: false,
+ snapMode: "both",
+ snapTolerance: 20,
+ stack: false,
+ zIndex: false
+ },
+ _create: function() {
+
+ if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
+ this.element[0].style.position = 'relative';
+
+ (this.options.addClasses && this.element.addClass("ui-draggable"));
+ (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
+
+ this._mouseInit();
+
+ },
+
+ destroy: function() {
+ if(!this.element.data('draggable')) return;
+ this.element
+ .removeData("draggable")
+ .unbind(".draggable")
+ .removeClass("ui-draggable"
+ + " ui-draggable-dragging"
+ + " ui-draggable-disabled");
+ this._mouseDestroy();
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+
+ var o = this.options;
+
+ // among others, prevent a drag on a resizable-handle
+ if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
+ return false;
+
+ //Quit if we're not on a valid handle
+ this.handle = this._getHandle(event);
+ if (!this.handle)
+ return false;
+
+ return true;
+
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options;
+
+ //Create and append the visible helper
+ this.helper = this._createHelper(event);
+
+ //Cache the helper size
+ this._cacheHelperProportions();
+
+ //If ddmanager is used for droppables, set the global draggable
+ if($.ui.ddmanager)
+ $.ui.ddmanager.current = this;
+
+ /*
+ * - Position generation -
+ * This block generates everything position related - it's the core of draggables.
+ */
+
+ //Cache the margins of the original element
+ this._cacheMargins();
+
+ //Store the helper's css position
+ this.cssPosition = this.helper.css("position");
+ this.scrollParent = this.helper.scrollParent();
+
+ //The element's absolute position on the page minus margins
+ this.offset = this.positionAbs = this.element.offset();
+ this.offset = {
+ top: this.offset.top - this.margins.top,
+ left: this.offset.left - this.margins.left
+ };
+
+ $.extend(this.offset, {
+ click: { //Where the click happened, relative to the element
+ left: event.pageX - this.offset.left,
+ top: event.pageY - this.offset.top
+ },
+ parent: this._getParentOffset(),
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+ });
+
+ //Generate the original position
+ this.originalPosition = this.position = this._generatePosition(event);
+ this.originalPageX = event.pageX;
+ this.originalPageY = event.pageY;
+
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+ //Set a containment if given in the options
+ if(o.containment)
+ this._setContainment();
+
+ //Trigger event + callbacks
+ if(this._trigger("start", event) === false) {
+ this._clear();
+ return false;
+ }
+
+ //Recache the helper size
+ this._cacheHelperProportions();
+
+ //Prepare the droppable offsets
+ if ($.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+
+ this.helper.addClass("ui-draggable-dragging");
+ this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+ return true;
+ },
+
+ _mouseDrag: function(event, noPropagation) {
+
+ //Compute the helpers position
+ this.position = this._generatePosition(event);
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ //Call plugins and callbacks and use the resulting position if something is returned
+ if (!noPropagation) {
+ var ui = this._uiHash();
+ if(this._trigger('drag', event, ui) === false) {
+ this._mouseUp({});
+ return false;
+ }
+ this.position = ui.position;
+ }
+
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ //If we are using droppables, inform the manager about the drop
+ var dropped = false;
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
+ dropped = $.ui.ddmanager.drop(this, event);
+
+ //if a drop comes from outside (a sortable)
+ if(this.dropped) {
+ dropped = this.dropped;
+ this.dropped = false;
+ }
+
+ //if the original element is removed, don't bother to continue if helper is set to "original"
+ if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
+ return false;
+
+ if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
+ var self = this;
+ $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
+ if(self._trigger("stop", event) !== false) {
+ self._clear();
+ }
+ });
+ } else {
+ if(this._trigger("stop", event) !== false) {
+ this._clear();
+ }
+ }
+
+ return false;
+ },
+
+ cancel: function() {
+
+ if(this.helper.is(".ui-draggable-dragging")) {
+ this._mouseUp({});
+ } else {
+ this._clear();
+ }
+
+ return this;
+
+ },
+
+ _getHandle: function(event) {
+
+ var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
+ $(this.options.handle, this.element)
+ .find("*")
+ .andSelf()
+ .each(function() {
+ if(this == event.target) handle = true;
+ });
+
+ return handle;
+
+ },
+
+ _createHelper: function(event) {
+
+ var o = this.options;
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
+
+ if(!helper.parents('body').length)
+ helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+
+ if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
+ helper.css("position", "absolute");
+
+ return helper;
+
+ },
+
+ _adjustOffsetFromHelper: function(obj) {
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
+ },
+
+ _getParentOffset: function() {
+
+ //Get the offsetParent and cache its position
+ this.offsetParent = this.helper.offsetParent();
+ var po = this.offsetParent.offset();
+
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
+ po.left += this.scrollParent.scrollLeft();
+ po.top += this.scrollParent.scrollTop();
+ }
+
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
+ po = { top: 0, left: 0 };
+
+ return {
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+ };
+
+ },
+
+ _getRelativeOffset: function() {
+
+ if(this.cssPosition == "relative") {
+ var p = this.element.position();
+ return {
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+ };
+ } else {
+ return { top: 0, left: 0 };
+ }
+
+ },
+
+ _cacheMargins: function() {
+ this.margins = {
+ left: (parseInt(this.element.css("marginLeft"),10) || 0),
+ top: (parseInt(this.element.css("marginTop"),10) || 0)
+ };
+ },
+
+ _cacheHelperProportions: function() {
+ this.helperProportions = {
+ width: this.helper.outerWidth(),
+ height: this.helper.outerHeight()
+ };
+ },
+
+ _setContainment: function() {
+
+ var o = this.options;
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
+ (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
+ (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
+ (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+ (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+ ];
+
+ if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
+ var ce = $(o.containment)[0]; if(!ce) return;
+ var co = $(o.containment).offset();
+ var over = ($(ce).css("overflow") != 'hidden');
+
+ this.containment = [
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
+ co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
+ co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
+ ];
+ } else if(o.containment.constructor == Array) {
+ this.containment = o.containment;
+ }
+
+ },
+
+ _convertPositionTo: function(d, pos) {
+
+ if(!pos) pos = this.position;
+ var mod = d == "absolute" ? 1 : -1;
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ return {
+ top: (
+ pos.top // The absolute mouse position
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ ),
+ left: (
+ pos.left // The absolute mouse position
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ )
+ };
+
+ },
+
+ _generatePosition: function(event) {
+
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+ var pageX = event.pageX;
+ var pageY = event.pageY;
+
+ /*
+ * - Position constraining -
+ * Constrain the position to a mix of grid, containment.
+ */
+
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+
+ if(this.containment) {
+ if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
+ if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
+ }
+
+ if(o.grid) {
+ var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
+ pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+ var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
+ pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+ }
+
+ }
+
+ return {
+ top: (
+ pageY // The absolute mouse position
+ - this.offset.click.top // Click offset (relative to the element)
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ ),
+ left: (
+ pageX // The absolute mouse position
+ - this.offset.click.left // Click offset (relative to the element)
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ )
+ };
+
+ },
+
+ _clear: function() {
+ this.helper.removeClass("ui-draggable-dragging");
+ if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
+ //if($.ui.ddmanager) $.ui.ddmanager.current = null;
+ this.helper = null;
+ this.cancelHelperRemoval = false;
+ },
+
+ // From now on bulk stuff - mainly helpers
+
+ _trigger: function(type, event, ui) {
+ ui = ui || this._uiHash();
+ $.ui.plugin.call(this, type, [event, ui]);
+ if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
+ return $.Widget.prototype._trigger.call(this, type, event, ui);
+ },
+
+ plugins: {},
+
+ _uiHash: function(event) {
+ return {
+ helper: this.helper,
+ position: this.position,
+ originalPosition: this.originalPosition,
+ offset: this.positionAbs
+ };
+ }
+
+});
+
+$.extend($.ui.draggable, {
+ version: "1.8.9"
+});
+
+$.ui.plugin.add("draggable", "connectToSortable", {
+ start: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options,
+ uiSortable = $.extend({}, ui, { item: inst.element });
+ inst.sortables = [];
+ $(o.connectToSortable).each(function() {
+ var sortable = $.data(this, 'sortable');
+ if (sortable && !sortable.options.disabled) {
+ inst.sortables.push({
+ instance: sortable,
+ shouldRevert: sortable.options.revert
+ });
+ sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
+ sortable._trigger("activate", event, uiSortable);
+ }
+ });
+
+ },
+ stop: function(event, ui) {
+
+ //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+ var inst = $(this).data("draggable"),
+ uiSortable = $.extend({}, ui, { item: inst.element });
+
+ $.each(inst.sortables, function() {
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+
+ inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+ this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+
+ //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
+ if(this.shouldRevert) this.instance.options.revert = true;
+
+ //Trigger the stop of the sortable
+ this.instance._mouseStop(event);
+
+ this.instance.options.helper = this.instance.options._helper;
+
+ //If the helper has been the original item, restore properties in the sortable
+ if(inst.options.helper == 'original')
+ this.instance.currentItem.css({ top: 'auto', left: 'auto' });
+
+ } else {
+ this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
+ this.instance._trigger("deactivate", event, uiSortable);
+ }
+
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), self = this;
+
+ var checkPos = function(o) {
+ var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
+ var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
+ var itemHeight = o.height, itemWidth = o.width;
+ var itemTop = o.top, itemLeft = o.left;
+
+ return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
+ };
+
+ $.each(inst.sortables, function(i) {
+
+ //Copy over some variables to allow calling the sortable's native _intersectsWith
+ this.instance.positionAbs = inst.positionAbs;
+ this.instance.helperProportions = inst.helperProportions;
+ this.instance.offset.click = inst.offset.click;
+
+ if(this.instance._intersectsWith(this.instance.containerCache)) {
+
+ //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+ if(!this.instance.isOver) {
+
+ this.instance.isOver = 1;
+ //Now we fake the start of dragging for the sortable instance,
+ //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+ //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+ this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
+ this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
+ this.instance.options.helper = function() { return ui.helper[0]; };
+
+ event.target = this.instance.currentItem[0];
+ this.instance._mouseCapture(event, true);
+ this.instance._mouseStart(event, true, true);
+
+ //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+ this.instance.offset.click.top = inst.offset.click.top;
+ this.instance.offset.click.left = inst.offset.click.left;
+ this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
+ this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
+
+ inst._trigger("toSortable", event);
+ inst.dropped = this.instance.element; //draggable revert needs that
+ //hack so receive/update callbacks work (mostly)
+ inst.currentItem = inst.element;
+ this.instance.fromOutside = inst;
+
+ }
+
+ //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+ if(this.instance.currentItem) this.instance._mouseDrag(event);
+
+ } else {
+
+ //If it doesn't intersect with the sortable, and it intersected before,
+ //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+ this.instance.cancelHelperRemoval = true;
+
+ //Prevent reverting on this forced stop
+ this.instance.options.revert = false;
+
+ // The out event needs to be triggered independently
+ this.instance._trigger('out', event, this.instance._uiHash(this.instance));
+
+ this.instance._mouseStop(event, true);
+ this.instance.options.helper = this.instance.options._helper;
+
+ //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+ this.instance.currentItem.remove();
+ if(this.instance.placeholder) this.instance.placeholder.remove();
+
+ inst._trigger("fromSortable", event);
+ inst.dropped = false; //draggable revert needs that
+ }
+
+ };
+
+ });
+
+ }
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+ start: function(event, ui) {
+ var t = $('body'), o = $(this).data('draggable').options;
+ if (t.css("cursor")) o._cursor = t.css("cursor");
+ t.css("cursor", o.cursor);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if (o._cursor) $('body').css("cursor", o._cursor);
+ }
+});
+
+$.ui.plugin.add("draggable", "iframeFix", {
+ start: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
+ $('
')
+ .css({
+ width: this.offsetWidth+"px", height: this.offsetHeight+"px",
+ position: "absolute", opacity: "0.001", zIndex: 1000
+ })
+ .css($(this).offset())
+ .appendTo("body");
+ });
+ },
+ stop: function(event, ui) {
+ $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
+ }
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data('draggable').options;
+ if(t.css("opacity")) o._opacity = t.css("opacity");
+ t.css('opacity', o.opacity);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if(o._opacity) $(ui.helper).css('opacity', o._opacity);
+ }
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+ start: function(event, ui) {
+ var i = $(this).data("draggable");
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
+ },
+ drag: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options, scrolled = false;
+
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
+
+ if(!o.axis || o.axis != 'x') {
+ if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
+ else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
+ else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
+ }
+
+ } else {
+
+ if(!o.axis || o.axis != 'x') {
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+ }
+
+ }
+
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(i, event);
+
+ }
+});
+
+$.ui.plugin.add("draggable", "snap", {
+ start: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options;
+ i.snapElements = [];
+
+ $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
+ var $t = $(this); var $o = $t.offset();
+ if(this != i.element[0]) i.snapElements.push({
+ item: this,
+ width: $t.outerWidth(), height: $t.outerHeight(),
+ top: $o.top, left: $o.left
+ });
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options;
+ var d = o.snapTolerance;
+
+ var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
+
+ for (var i = inst.snapElements.length - 1; i >= 0; i--){
+
+ var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
+ t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
+
+ //Yes, I know, this is insane ;)
+ if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
+ if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = false;
+ continue;
+ }
+
+ if(o.snapMode != 'inner') {
+ var ts = Math.abs(t - y2) <= d;
+ var bs = Math.abs(b - y1) <= d;
+ var ls = Math.abs(l - x2) <= d;
+ var rs = Math.abs(r - x1) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
+ }
+
+ var first = (ts || bs || ls || rs);
+
+ if(o.snapMode != 'outer') {
+ var ts = Math.abs(t - y1) <= d;
+ var bs = Math.abs(b - y2) <= d;
+ var ls = Math.abs(l - x1) <= d;
+ var rs = Math.abs(r - x2) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
+ }
+
+ if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
+ (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
+
+ };
+
+ }
+});
+
+$.ui.plugin.add("draggable", "stack", {
+ start: function(event, ui) {
+
+ var o = $(this).data("draggable").options;
+
+ var group = $.makeArray($(o.stack)).sort(function(a,b) {
+ return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
+ });
+ if (!group.length) { return; }
+
+ var min = parseInt(group[0].style.zIndex) || 0;
+ $(group).each(function(i) {
+ this.style.zIndex = min + i;
+ });
+
+ this[0].style.zIndex = min + group.length;
+
+ }
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data("draggable").options;
+ if(t.css("zIndex")) o._zIndex = t.css("zIndex");
+ t.css('zIndex', o.zIndex);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data("draggable").options;
+ if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
+ }
+});
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.mouse.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.mouse.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,151 @@
+/*!
+ * jQuery UI Mouse 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.mouse", {
+ options: {
+ cancel: ':input,option',
+ distance: 1,
+ delay: 0
+ },
+ _mouseInit: function() {
+ var self = this;
+
+ this.element
+ .bind('mousedown.'+this.widgetName, function(event) {
+ return self._mouseDown(event);
+ })
+ .bind('click.'+this.widgetName, function(event) {
+ if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
+ $.removeData(event.target, self.widgetName + '.preventClickEvent');
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind('.'+this.widgetName);
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ // TODO: figure out why we have to use originalEvent
+ event.originalEvent = event.originalEvent || {};
+ if (event.originalEvent.mouseHandled) { return; }
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var self = this,
+ btnIsLeft = (event.which == 1),
+ elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ self.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return self._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return self._mouseUp(event);
+ };
+ $(document)
+ .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ event.preventDefault();
+ event.originalEvent.mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+
+ if (event.target == this._mouseDownEvent.target) {
+ $.data(event.target, this.widgetName + '.preventClickEvent', true);
+ }
+
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(event) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(event) {},
+ _mouseDrag: function(event) {},
+ _mouseStop: function(event) {},
+ _mouseCapture: function(event) { return true; }
+});
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.position.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.position.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,252 @@
+/*
+ * jQuery UI Position 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var horizontalPositions = /left|center|right/,
+ verticalPositions = /top|center|bottom/,
+ center = "center",
+ _position = $.fn.position,
+ _offset = $.fn.offset;
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var target = $( options.of ),
+ targetElem = target[0],
+ collision = ( options.collision || "flip" ).split( " " ),
+ offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
+ targetWidth,
+ targetHeight,
+ basePosition;
+
+ if ( targetElem.nodeType === 9 ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: 0, left: 0 };
+ // TODO: use $.isWindow() in 1.9
+ } else if ( targetElem.setTimeout ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+ } else if ( targetElem.preventDefault ) {
+ // force left top to allow flipping
+ options.at = "left top";
+ targetWidth = targetHeight = 0;
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
+ } else {
+ targetWidth = target.outerWidth();
+ targetHeight = target.outerHeight();
+ basePosition = target.offset();
+ }
+
+ // force my and at to have valid horizontal and veritcal positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[this] || "" ).split( " " );
+ if ( pos.length === 1) {
+ pos = horizontalPositions.test( pos[0] ) ?
+ pos.concat( [center] ) :
+ verticalPositions.test( pos[0] ) ?
+ [ center ].concat( pos ) :
+ [ center, center ];
+ }
+ pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
+ pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
+ options[ this ] = pos;
+ });
+
+ // normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ // normalize offset option
+ offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
+ if ( offset.length === 1 ) {
+ offset[ 1 ] = offset[ 0 ];
+ }
+ offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
+
+ if ( options.at[0] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[0] === center ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[1] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[1] === center ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ basePosition.left += offset[ 0 ];
+ basePosition.top += offset[ 1 ];
+
+ return this.each(function() {
+ var elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
+ marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
+ collisionWidth = elemWidth + marginLeft +
+ ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
+ collisionHeight = elemHeight + marginTop +
+ ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
+ position = $.extend( {}, basePosition ),
+ collisionPosition;
+
+ if ( options.my[0] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[0] === center ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[1] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[1] === center ) {
+ position.top -= elemHeight / 2;
+ }
+
+ // prevent fractions (see #5280)
+ position.left = Math.round( position.left );
+ position.top = Math.round( position.top );
+
+ collisionPosition = {
+ left: position.left - marginLeft,
+ top: position.top - marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[i] ] ) {
+ $.ui.position[ collision[i] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: offset,
+ my: options.my,
+ at: options.at
+ });
+ }
+ });
+
+ if ( $.fn.bgiframe ) {
+ elem.bgiframe();
+ }
+ elem.offset( $.extend( position, { using: options.using } ) );
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var win = $( window ),
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
+ position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
+ },
+ top: function( position, data ) {
+ var win = $( window ),
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
+ position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
+ }
+ },
+
+ flip: {
+ left: function( position, data ) {
+ if ( data.at[0] === center ) {
+ return;
+ }
+ var win = $( window ),
+ over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ -data.targetWidth,
+ offset = -2 * data.offset[ 0 ];
+ position.left += data.collisionPosition.left < 0 ?
+ myOffset + atOffset + offset :
+ over > 0 ?
+ myOffset + atOffset + offset :
+ 0;
+ },
+ top: function( position, data ) {
+ if ( data.at[1] === center ) {
+ return;
+ }
+ var win = $( window ),
+ over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
+ myOffset = data.my[ 1 ] === "top" ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ -data.targetHeight,
+ offset = -2 * data.offset[ 1 ];
+ position.top += data.collisionPosition.top < 0 ?
+ myOffset + atOffset + offset :
+ over > 0 ?
+ myOffset + atOffset + offset :
+ 0;
+ }
+ }
+};
+
+// offset setter from jQuery 1.4
+if ( !$.offset.setOffset ) {
+ $.offset.setOffset = function( elem, options ) {
+ // set position first, in-case top/left are set even on static elem
+ if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
+ elem.style.position = "relative";
+ }
+ var curElem = $( elem ),
+ curOffset = curElem.offset(),
+ curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
+ curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
+ props = {
+ top: (options.top - curOffset.top) + curTop,
+ left: (options.left - curOffset.left) + curLeft
+ };
+
+ if ( 'using' in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ };
+
+ $.fn.offset = function( options ) {
+ var elem = this[ 0 ];
+ if ( !elem || !elem.ownerDocument ) { return null; }
+ if ( options ) {
+ return this.each(function() {
+ $.offset.setOffset( this, options );
+ });
+ }
+ return _offset.call( this );
+ };
+}
+
+}( jQuery ));
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.resizable.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.resizable.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,812 @@
+/*
+ * jQuery UI Resizable 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizables
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.resizable", $.ui.mouse, {
+ widgetEventPrefix: "resize",
+ options: {
+ alsoResize: false,
+ animate: false,
+ animateDuration: "slow",
+ animateEasing: "swing",
+ aspectRatio: false,
+ autoHide: false,
+ containment: false,
+ ghost: false,
+ grid: false,
+ handles: "e,s,se",
+ helper: false,
+ maxHeight: null,
+ maxWidth: null,
+ minHeight: 10,
+ minWidth: 10,
+ zIndex: 1000
+ },
+ _create: function() {
+
+ var self = this, o = this.options;
+ this.element.addClass("ui-resizable");
+
+ $.extend(this, {
+ _aspectRatio: !!(o.aspectRatio),
+ aspectRatio: o.aspectRatio,
+ originalElement: this.element,
+ _proportionallyResizeElements: [],
+ _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
+ });
+
+ //Wrap the element if it cannot hold child nodes
+ if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
+
+ //Opera fix for relative positioning
+ if (/relative/.test(this.element.css('position')) && $.browser.opera)
+ this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+ //Create a wrapper element and set the wrapper to the new current internal element
+ this.element.wrap(
+ $('
').css({
+ position: this.element.css('position'),
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight(),
+ top: this.element.css('top'),
+ left: this.element.css('left')
+ })
+ );
+
+ //Overwrite the original this.element
+ this.element = this.element.parent().data(
+ "resizable", this.element.data('resizable')
+ );
+
+ this.elementIsWrapper = true;
+
+ //Move margins to the wrapper
+ this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
+ this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+
+ //Prevent Safari textarea resize
+ this.originalResizeStyle = this.originalElement.css('resize');
+ this.originalElement.css('resize', 'none');
+
+ //Push the actual element to our proportionallyResize internal array
+ this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
+
+ // avoid IE jump (hard set the margin)
+ this.originalElement.css({ margin: this.originalElement.css('margin') });
+
+ // fix handlers offset
+ this._proportionallyResize();
+
+ }
+
+ this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
+ if(this.handles.constructor == String) {
+
+ if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
+ var n = this.handles.split(","); this.handles = {};
+
+ for(var i = 0; i < n.length; i++) {
+
+ var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
+ var axis = $('
');
+
+ // increase zIndex of sw, se, ne, nw axis
+ //TODO : this modifies original option
+ if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
+
+ //TODO : What's going on here?
+ if ('se' == handle) {
+ axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
+ };
+
+ //Insert into internal handles object and append to element
+ this.handles[handle] = '.ui-resizable-'+handle;
+ this.element.append(axis);
+ }
+
+ }
+
+ this._renderAxis = function(target) {
+
+ target = target || this.element;
+
+ for(var i in this.handles) {
+
+ if(this.handles[i].constructor == String)
+ this.handles[i] = $(this.handles[i], this.element).show();
+
+ //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+ if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
+
+ var axis = $(this.handles[i], this.element), padWrapper = 0;
+
+ //Checking the correct pad and border
+ padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+ //The padding type i have to apply...
+ var padPos = [ 'padding',
+ /ne|nw|n/.test(i) ? 'Top' :
+ /se|sw|s/.test(i) ? 'Bottom' :
+ /^e$/.test(i) ? 'Right' : 'Left' ].join("");
+
+ target.css(padPos, padWrapper);
+
+ this._proportionallyResize();
+
+ }
+
+ //TODO: What's that good for? There's not anything to be executed left
+ if(!$(this.handles[i]).length)
+ continue;
+
+ }
+ };
+
+ //TODO: make renderAxis a prototype function
+ this._renderAxis(this.element);
+
+ this._handles = $('.ui-resizable-handle', this.element)
+ .disableSelection();
+
+ //Matching axis name
+ this._handles.mouseover(function() {
+ if (!self.resizing) {
+ if (this.className)
+ var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+ //Axis, default = se
+ self.axis = axis && axis[1] ? axis[1] : 'se';
+ }
+ });
+
+ //If we want to auto hide the elements
+ if (o.autoHide) {
+ this._handles.hide();
+ $(this.element)
+ .addClass("ui-resizable-autohide")
+ .hover(function() {
+ $(this).removeClass("ui-resizable-autohide");
+ self._handles.show();
+ },
+ function(){
+ if (!self.resizing) {
+ $(this).addClass("ui-resizable-autohide");
+ self._handles.hide();
+ }
+ });
+ }
+
+ //Initialize the mouse interaction
+ this._mouseInit();
+
+ },
+
+ destroy: function() {
+
+ this._mouseDestroy();
+
+ var _destroy = function(exp) {
+ $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+ .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+ };
+
+ //TODO: Unwrap at same DOM position
+ if (this.elementIsWrapper) {
+ _destroy(this.element);
+ var wrapper = this.element;
+ wrapper.after(
+ this.originalElement.css({
+ position: wrapper.css('position'),
+ width: wrapper.outerWidth(),
+ height: wrapper.outerHeight(),
+ top: wrapper.css('top'),
+ left: wrapper.css('left')
+ })
+ ).remove();
+ }
+
+ this.originalElement.css('resize', this.originalResizeStyle);
+ _destroy(this.originalElement);
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+ var handle = false;
+ for (var i in this.handles) {
+ if ($(this.handles[i])[0] == event.target) {
+ handle = true;
+ }
+ }
+
+ return !this.options.disabled && handle;
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options, iniPos = this.element.position(), el = this.element;
+
+ this.resizing = true;
+ this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+
+ // bugfix for http://dev.jquery.com/ticket/1749
+ if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+ el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
+ }
+
+ //Opera fixing relative position
+ if ($.browser.opera && (/relative/).test(el.css('position')))
+ el.css({ position: 'relative', top: 'auto', left: 'auto' });
+
+ this._renderProxy();
+
+ var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+
+ if (o.containment) {
+ curleft += $(o.containment).scrollLeft() || 0;
+ curtop += $(o.containment).scrollTop() || 0;
+ }
+
+ //Store needed variables
+ this.offset = this.helper.offset();
+ this.position = { left: curleft, top: curtop };
+ this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalPosition = { left: curleft, top: curtop };
+ this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+ //Aspect Ratio
+ this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
+
+ var cursor = $('.ui-resizable-' + this.axis).css('cursor');
+ $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
+
+ el.addClass("ui-resizable-resizing");
+ this._propagate("start", event);
+ return true;
+ },
+
+ _mouseDrag: function(event) {
+
+ //Increase performance, avoid regex
+ var el = this.helper, o = this.options, props = {},
+ self = this, smp = this.originalMousePosition, a = this.axis;
+
+ var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
+ var trigger = this._change[a];
+ if (!trigger) return false;
+
+ // Calculate the attrs that will be change
+ var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
+
+ if (this._aspectRatio || event.shiftKey)
+ data = this._updateRatio(data, event);
+
+ data = this._respectSize(data, event);
+
+ // plugins callbacks need to be called first
+ this._propagate("resize", event);
+
+ el.css({
+ top: this.position.top + "px", left: this.position.left + "px",
+ width: this.size.width + "px", height: this.size.height + "px"
+ });
+
+ if (!this._helper && this._proportionallyResizeElements.length)
+ this._proportionallyResize();
+
+ this._updateCache(data);
+
+ // calling the user callback at the end
+ this._trigger('resize', event, this.ui());
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ this.resizing = false;
+ var o = this.options, self = this;
+
+ if(this._helper) {
+ var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+ soffsetw = ista ? 0 : self.sizeDiff.width;
+
+ var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+ left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+ top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+ if (!o.animate)
+ this.element.css($.extend(s, { top: top, left: left }));
+
+ self.helper.height(self.size.height);
+ self.helper.width(self.size.width);
+
+ if (this._helper && !o.animate) this._proportionallyResize();
+ }
+
+ $('body').css('cursor', 'auto');
+
+ this.element.removeClass("ui-resizable-resizing");
+
+ this._propagate("stop", event);
+
+ if (this._helper) this.helper.remove();
+ return false;
+
+ },
+
+ _updateCache: function(data) {
+ var o = this.options;
+ this.offset = this.helper.offset();
+ if (isNumber(data.left)) this.position.left = data.left;
+ if (isNumber(data.top)) this.position.top = data.top;
+ if (isNumber(data.height)) this.size.height = data.height;
+ if (isNumber(data.width)) this.size.width = data.width;
+ },
+
+ _updateRatio: function(data, event) {
+
+ var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+
+ if (data.height) data.width = (csize.height * this.aspectRatio);
+ else if (data.width) data.height = (csize.width / this.aspectRatio);
+
+ if (a == 'sw') {
+ data.left = cpos.left + (csize.width - data.width);
+ data.top = null;
+ }
+ if (a == 'nw') {
+ data.top = cpos.top + (csize.height - data.height);
+ data.left = cpos.left + (csize.width - data.width);
+ }
+
+ return data;
+ },
+
+ _respectSize: function(data, event) {
+
+ var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
+ ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+ isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
+
+ if (isminw) data.width = o.minWidth;
+ if (isminh) data.height = o.minHeight;
+ if (ismaxw) data.width = o.maxWidth;
+ if (ismaxh) data.height = o.maxHeight;
+
+ var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+ var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+
+ if (isminw && cw) data.left = dw - o.minWidth;
+ if (ismaxw && cw) data.left = dw - o.maxWidth;
+ if (isminh && ch) data.top = dh - o.minHeight;
+ if (ismaxh && ch) data.top = dh - o.maxHeight;
+
+ // fixing jump error on top/left - bug #2330
+ var isNotwh = !data.width && !data.height;
+ if (isNotwh && !data.left && data.top) data.top = null;
+ else if (isNotwh && !data.top && data.left) data.left = null;
+
+ return data;
+ },
+
+ _proportionallyResize: function() {
+
+ var o = this.options;
+ if (!this._proportionallyResizeElements.length) return;
+ var element = this.helper || this.element;
+
+ for (var i=0; i < this._proportionallyResizeElements.length; i++) {
+
+ var prel = this._proportionallyResizeElements[i];
+
+ if (!this.borderDif) {
+ var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+ p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+
+ this.borderDif = $.map(b, function(v, i) {
+ var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+ return border + padding;
+ });
+ }
+
+ if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
+ continue;
+
+ prel.css({
+ height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
+ width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
+ });
+
+ };
+
+ },
+
+ _renderProxy: function() {
+
+ var el = this.element, o = this.options;
+ this.elementOffset = el.offset();
+
+ if(this._helper) {
+
+ this.helper = this.helper || $('
');
+
+ // fix ie6 offset TODO: This seems broken
+ var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
+ pxyoffset = ( ie6 ? 2 : -1 );
+
+ this.helper.addClass(this._helper).css({
+ width: this.element.outerWidth() + pxyoffset,
+ height: this.element.outerHeight() + pxyoffset,
+ position: 'absolute',
+ left: this.elementOffset.left - ie6offset +'px',
+ top: this.elementOffset.top - ie6offset +'px',
+ zIndex: ++o.zIndex //TODO: Don't modify option
+ });
+
+ this.helper
+ .appendTo("body")
+ .disableSelection();
+
+ } else {
+ this.helper = this.element;
+ }
+
+ },
+
+ _change: {
+ e: function(event, dx, dy) {
+ return { width: this.originalSize.width + dx };
+ },
+ w: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { left: sp.left + dx, width: cs.width - dx };
+ },
+ n: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { top: sp.top + dy, height: cs.height - dy };
+ },
+ s: function(event, dx, dy) {
+ return { height: this.originalSize.height + dy };
+ },
+ se: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ sw: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ },
+ ne: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ nw: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ }
+ },
+
+ _propagate: function(n, event) {
+ $.ui.plugin.call(this, n, [event, this.ui()]);
+ (n != "resize" && this._trigger(n, event, this.ui()));
+ },
+
+ plugins: {},
+
+ ui: function() {
+ return {
+ originalElement: this.originalElement,
+ element: this.element,
+ helper: this.helper,
+ position: this.position,
+ size: this.size,
+ originalSize: this.originalSize,
+ originalPosition: this.originalPosition
+ };
+ }
+
+});
+
+$.extend($.ui.resizable, {
+ version: "1.8.9"
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+ start: function (event, ui) {
+ var self = $(this).data("resizable"), o = self.options;
+
+ var _store = function (exp) {
+ $(exp).each(function() {
+ var el = $(this);
+ el.data("resizable-alsoresize", {
+ width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+ left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
+ position: el.css('position') // to reset Opera on stop()
+ });
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
+ if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
+ else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
+ }else{
+ _store(o.alsoResize);
+ }
+ },
+
+ resize: function (event, ui) {
+ var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
+
+ var delta = {
+ height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
+ top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
+ },
+
+ _alsoResize = function (exp, c) {
+ $(exp).each(function() {
+ var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
+ css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
+
+ $.each(css, function (i, prop) {
+ var sum = (start[prop]||0) + (delta[prop]||0);
+ if (sum && sum >= 0)
+ style[prop] = sum || null;
+ });
+
+ // Opera fixing relative position
+ if ($.browser.opera && /relative/.test(el.css('position'))) {
+ self._revertToRelativePosition = true;
+ el.css({ position: 'absolute', top: 'auto', left: 'auto' });
+ }
+
+ el.css(style);
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
+ $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
+ }else{
+ _alsoResize(o.alsoResize);
+ }
+ },
+
+ stop: function (event, ui) {
+ var self = $(this).data("resizable"), o = self.options;
+
+ var _reset = function (exp) {
+ $(exp).each(function() {
+ var el = $(this);
+ // reset position for Opera - no need to verify it was changed
+ el.css({ position: el.data("resizable-alsoresize").position });
+ });
+ };
+
+ if (self._revertToRelativePosition) {
+ self._revertToRelativePosition = false;
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
+ $.each(o.alsoResize, function (exp) { _reset(exp); });
+ }else{
+ _reset(o.alsoResize);
+ }
+ }
+
+ $(this).removeData("resizable-alsoresize");
+ }
+});
+
+$.ui.plugin.add("resizable", "animate", {
+
+ stop: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options;
+
+ var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
+ soffsetw = ista ? 0 : self.sizeDiff.width;
+
+ var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
+ left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
+ top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
+
+ self.element.animate(
+ $.extend(style, top && left ? { top: top, left: left } : {}), {
+ duration: o.animateDuration,
+ easing: o.animateEasing,
+ step: function() {
+
+ var data = {
+ width: parseInt(self.element.css('width'), 10),
+ height: parseInt(self.element.css('height'), 10),
+ top: parseInt(self.element.css('top'), 10),
+ left: parseInt(self.element.css('left'), 10)
+ };
+
+ if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
+
+ // propagating resize, and updating values for each animation step
+ self._updateCache(data);
+ self._propagate("resize", event);
+
+ }
+ }
+ );
+ }
+
+});
+
+$.ui.plugin.add("resizable", "containment", {
+
+ start: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options, el = self.element;
+ var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+ if (!ce) return;
+
+ self.containerElement = $(ce);
+
+ if (/document/.test(oc) || oc == document) {
+ self.containerOffset = { left: 0, top: 0 };
+ self.containerPosition = { left: 0, top: 0 };
+
+ self.parentData = {
+ element: $(document), left: 0, top: 0,
+ width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
+ };
+ }
+
+ // i'm a node, so compute top, left, right, bottom
+ else {
+ var element = $(ce), p = [];
+ $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
+
+ self.containerOffset = element.offset();
+ self.containerPosition = element.position();
+ self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
+
+ var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
+ width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+
+ self.parentData = {
+ element: ce, left: co.left, top: co.top, width: width, height: height
+ };
+ }
+ },
+
+ resize: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options,
+ ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
+ pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
+
+ if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
+
+ if (cp.left < (self._helper ? co.left : 0)) {
+ self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
+ if (pRatio) self.size.height = self.size.width / o.aspectRatio;
+ self.position.left = o.helper ? co.left : 0;
+ }
+
+ if (cp.top < (self._helper ? co.top : 0)) {
+ self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
+ if (pRatio) self.size.width = self.size.height * o.aspectRatio;
+ self.position.top = self._helper ? co.top : 0;
+ }
+
+ self.offset.left = self.parentData.left+self.position.left;
+ self.offset.top = self.parentData.top+self.position.top;
+
+ var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
+ hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
+
+ var isParent = self.containerElement.get(0) == self.element.parent().get(0),
+ isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
+
+ if(isParent && isOffsetRelative) woset -= self.parentData.left;
+
+ if (woset + self.size.width >= self.parentData.width) {
+ self.size.width = self.parentData.width - woset;
+ if (pRatio) self.size.height = self.size.width / self.aspectRatio;
+ }
+
+ if (hoset + self.size.height >= self.parentData.height) {
+ self.size.height = self.parentData.height - hoset;
+ if (pRatio) self.size.width = self.size.height * self.aspectRatio;
+ }
+ },
+
+ stop: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options, cp = self.position,
+ co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
+
+ var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
+
+ if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ if (self._helper && !o.animate && (/static/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ }
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+ start: function(event, ui) {
+
+ var self = $(this).data("resizable"), o = self.options, cs = self.size;
+
+ self.ghost = self.originalElement.clone();
+ self.ghost
+ .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
+ .addClass('ui-resizable-ghost')
+ .addClass(typeof o.ghost == 'string' ? o.ghost : '');
+
+ self.ghost.appendTo(self.helper);
+
+ },
+
+ resize: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options;
+ if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
+ },
+
+ stop: function(event, ui){
+ var self = $(this).data("resizable"), o = self.options;
+ if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
+ }
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+ resize: function(event, ui) {
+ var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
+ o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+ var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
+
+ if (/^(se|s|e)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ }
+ else if (/^(ne)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.top = op.top - oy;
+ }
+ else if (/^(sw)$/.test(a)) {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.left = op.left - ox;
+ }
+ else {
+ self.size.width = os.width + ox;
+ self.size.height = os.height + oy;
+ self.position.top = op.top - oy;
+ self.position.left = op.left - ox;
+ }
+ }
+
+});
+
+var num = function(v) {
+ return parseInt(v, 10) || 0;
+};
+
+var isNumber = function(value) {
+ return !isNaN(parseInt(value, 10));
+};
+
+})(jQuery);
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.slider.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.slider.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,682 @@
+/*
+ * jQuery UI Slider 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
+
+$.widget( "ui.slider", $.ui.mouse, {
+
+ widgetEventPrefix: "slide",
+
+ options: {
+ animate: false,
+ distance: 0,
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ range: false,
+ step: 1,
+ value: 0,
+ values: null
+ },
+
+ _create: function() {
+ var self = this,
+ o = this.options;
+
+ this._keySliding = false;
+ this._mouseSliding = false;
+ this._animateOff = true;
+ this._handleIndex = null;
+ this._detectOrientation();
+ this._mouseInit();
+
+ this.element
+ .addClass( "ui-slider" +
+ " ui-slider-" + this.orientation +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" );
+
+ if ( o.disabled ) {
+ this.element.addClass( "ui-slider-disabled ui-disabled" );
+ }
+
+ this.range = $([]);
+
+ if ( o.range ) {
+ if ( o.range === true ) {
+ this.range = $( "
" );
+ if ( !o.values ) {
+ o.values = [ this._valueMin(), this._valueMin() ];
+ }
+ if ( o.values.length && o.values.length !== 2 ) {
+ o.values = [ o.values[0], o.values[0] ];
+ }
+ } else {
+ this.range = $( "
" );
+ }
+
+ this.range
+ .appendTo( this.element )
+ .addClass( "ui-slider-range" );
+
+ if ( o.range === "min" || o.range === "max" ) {
+ this.range.addClass( "ui-slider-range-" + o.range );
+ }
+
+ // note: this isn't the most fittingly semantic framework class for this element,
+ // but worked best visually with a variety of themes
+ this.range.addClass( "ui-widget-header" );
+ }
+
+ if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
+ $( " " )
+ .appendTo( this.element )
+ .addClass( "ui-slider-handle" );
+ }
+
+ if ( o.values && o.values.length ) {
+ while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
+ $( " " )
+ .appendTo( this.element )
+ .addClass( "ui-slider-handle" );
+ }
+ }
+
+ this.handles = $( ".ui-slider-handle", this.element )
+ .addClass( "ui-state-default" +
+ " ui-corner-all" );
+
+ this.handle = this.handles.eq( 0 );
+
+ this.handles.add( this.range ).filter( "a" )
+ .click(function( event ) {
+ event.preventDefault();
+ })
+ .hover(function() {
+ if ( !o.disabled ) {
+ $( this ).addClass( "ui-state-hover" );
+ }
+ }, function() {
+ $( this ).removeClass( "ui-state-hover" );
+ })
+ .focus(function() {
+ if ( !o.disabled ) {
+ $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
+ $( this ).addClass( "ui-state-focus" );
+ } else {
+ $( this ).blur();
+ }
+ })
+ .blur(function() {
+ $( this ).removeClass( "ui-state-focus" );
+ });
+
+ this.handles.each(function( i ) {
+ $( this ).data( "index.ui-slider-handle", i );
+ });
+
+ this.handles
+ .keydown(function( event ) {
+ var ret = true,
+ index = $( this ).data( "index.ui-slider-handle" ),
+ allowed,
+ curVal,
+ newVal,
+ step;
+
+ if ( self.options.disabled ) {
+ return;
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ ret = false;
+ if ( !self._keySliding ) {
+ self._keySliding = true;
+ $( this ).addClass( "ui-state-active" );
+ allowed = self._start( event, index );
+ if ( allowed === false ) {
+ return;
+ }
+ }
+ break;
+ }
+
+ step = self.options.step;
+ if ( self.options.values && self.options.values.length ) {
+ curVal = newVal = self.values( index );
+ } else {
+ curVal = newVal = self.value();
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ newVal = self._valueMin();
+ break;
+ case $.ui.keyCode.END:
+ newVal = self._valueMax();
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ if ( curVal === self._valueMax() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal + step );
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ if ( curVal === self._valueMin() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal - step );
+ break;
+ }
+
+ self._slide( event, index, newVal );
+
+ return ret;
+
+ })
+ .keyup(function( event ) {
+ var index = $( this ).data( "index.ui-slider-handle" );
+
+ if ( self._keySliding ) {
+ self._keySliding = false;
+ self._stop( event, index );
+ self._change( event, index );
+ $( this ).removeClass( "ui-state-active" );
+ }
+
+ });
+
+ this._refreshValue();
+
+ this._animateOff = false;
+ },
+
+ destroy: function() {
+ this.handles.remove();
+ this.range.remove();
+
+ this.element
+ .removeClass( "ui-slider" +
+ " ui-slider-horizontal" +
+ " ui-slider-vertical" +
+ " ui-slider-disabled" +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" )
+ .removeData( "slider" )
+ .unbind( ".slider" );
+
+ this._mouseDestroy();
+
+ return this;
+ },
+
+ _mouseCapture: function( event ) {
+ var o = this.options,
+ position,
+ normValue,
+ distance,
+ closestHandle,
+ self,
+ index,
+ allowed,
+ offset,
+ mouseOverHandle;
+
+ if ( o.disabled ) {
+ return false;
+ }
+
+ this.elementSize = {
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight()
+ };
+ this.elementOffset = this.element.offset();
+
+ position = { x: event.pageX, y: event.pageY };
+ normValue = this._normValueFromMouse( position );
+ distance = this._valueMax() - this._valueMin() + 1;
+ self = this;
+ this.handles.each(function( i ) {
+ var thisDistance = Math.abs( normValue - self.values(i) );
+ if ( distance > thisDistance ) {
+ distance = thisDistance;
+ closestHandle = $( this );
+ index = i;
+ }
+ });
+
+ // workaround for bug #3736 (if both handles of a range are at 0,
+ // the first is always used as the one with least distance,
+ // and moving it is obviously prevented by preventing negative ranges)
+ if( o.range === true && this.values(1) === o.min ) {
+ index += 1;
+ closestHandle = $( this.handles[index] );
+ }
+
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return false;
+ }
+ this._mouseSliding = true;
+
+ self._handleIndex = index;
+
+ closestHandle
+ .addClass( "ui-state-active" )
+ .focus();
+
+ offset = closestHandle.offset();
+ mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+ top: event.pageY - offset.top -
+ ( closestHandle.height() / 2 ) -
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+ };
+
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+ this._slide( event, index, normValue );
+ }
+ this._animateOff = true;
+ return true;
+ },
+
+ _mouseStart: function( event ) {
+ return true;
+ },
+
+ _mouseDrag: function( event ) {
+ var position = { x: event.pageX, y: event.pageY },
+ normValue = this._normValueFromMouse( position );
+
+ this._slide( event, this._handleIndex, normValue );
+
+ return false;
+ },
+
+ _mouseStop: function( event ) {
+ this.handles.removeClass( "ui-state-active" );
+ this._mouseSliding = false;
+
+ this._stop( event, this._handleIndex );
+ this._change( event, this._handleIndex );
+
+ this._handleIndex = null;
+ this._clickOffset = null;
+ this._animateOff = false;
+
+ return false;
+ },
+
+ _detectOrientation: function() {
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+ },
+
+ _normValueFromMouse: function( position ) {
+ var pixelTotal,
+ pixelMouse,
+ percentMouse,
+ valueTotal,
+ valueMouse;
+
+ if ( this.orientation === "horizontal" ) {
+ pixelTotal = this.elementSize.width;
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+ } else {
+ pixelTotal = this.elementSize.height;
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+ }
+
+ percentMouse = ( pixelMouse / pixelTotal );
+ if ( percentMouse > 1 ) {
+ percentMouse = 1;
+ }
+ if ( percentMouse < 0 ) {
+ percentMouse = 0;
+ }
+ if ( this.orientation === "vertical" ) {
+ percentMouse = 1 - percentMouse;
+ }
+
+ valueTotal = this._valueMax() - this._valueMin();
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+ return this._trimAlignValue( valueMouse );
+ },
+
+ _start: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+ return this._trigger( "start", event, uiHash );
+ },
+
+ _slide: function( event, index, newVal ) {
+ var otherVal,
+ newValues,
+ allowed;
+
+ if ( this.options.values && this.options.values.length ) {
+ otherVal = this.values( index ? 0 : 1 );
+
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+ ) {
+ newVal = otherVal;
+ }
+
+ if ( newVal !== this.values( index ) ) {
+ newValues = this.values();
+ newValues[ index ] = newVal;
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal,
+ values: newValues
+ } );
+ otherVal = this.values( index ? 0 : 1 );
+ if ( allowed !== false ) {
+ this.values( index, newVal, true );
+ }
+ }
+ } else {
+ if ( newVal !== this.value() ) {
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal
+ } );
+ if ( allowed !== false ) {
+ this.value( newVal );
+ }
+ }
+ }
+ },
+
+ _stop: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "stop", event, uiHash );
+ },
+
+ _change: function( event, index ) {
+ if ( !this._keySliding && !this._mouseSliding ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "change", event, uiHash );
+ }
+ },
+
+ value: function( newValue ) {
+ if ( arguments.length ) {
+ this.options.value = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, 0 );
+ }
+
+ return this._value();
+ },
+
+ values: function( index, newValue ) {
+ var vals,
+ newValues,
+ i;
+
+ if ( arguments.length > 1 ) {
+ this.options.values[ index ] = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, index );
+ }
+
+ if ( arguments.length ) {
+ if ( $.isArray( arguments[ 0 ] ) ) {
+ vals = this.options.values;
+ newValues = arguments[ 0 ];
+ for ( i = 0; i < vals.length; i += 1 ) {
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
+ this._change( null, i );
+ }
+ this._refreshValue();
+ } else {
+ if ( this.options.values && this.options.values.length ) {
+ return this._values( index );
+ } else {
+ return this.value();
+ }
+ }
+ } else {
+ return this._values();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var i,
+ valsLength = 0;
+
+ if ( $.isArray( this.options.values ) ) {
+ valsLength = this.options.values.length;
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ switch ( key ) {
+ case "disabled":
+ if ( value ) {
+ this.handles.filter( ".ui-state-focus" ).blur();
+ this.handles.removeClass( "ui-state-hover" );
+ this.handles.attr( "disabled", "disabled" );
+ this.element.addClass( "ui-disabled" );
+ } else {
+ this.handles.removeAttr( "disabled" );
+ this.element.removeClass( "ui-disabled" );
+ }
+ break;
+ case "orientation":
+ this._detectOrientation();
+ this.element
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+ .addClass( "ui-slider-" + this.orientation );
+ this._refreshValue();
+ break;
+ case "value":
+ this._animateOff = true;
+ this._refreshValue();
+ this._change( null, 0 );
+ this._animateOff = false;
+ break;
+ case "values":
+ this._animateOff = true;
+ this._refreshValue();
+ for ( i = 0; i < valsLength; i += 1 ) {
+ this._change( null, i );
+ }
+ this._animateOff = false;
+ break;
+ }
+ },
+
+ //internal value getter
+ // _value() returns value trimmed by min and max, aligned by step
+ _value: function() {
+ var val = this.options.value;
+ val = this._trimAlignValue( val );
+
+ return val;
+ },
+
+ //internal values getter
+ // _values() returns array of values trimmed by min and max, aligned by step
+ // _values( index ) returns single value trimmed by min and max, aligned by step
+ _values: function( index ) {
+ var val,
+ vals,
+ i;
+
+ if ( arguments.length ) {
+ val = this.options.values[ index ];
+ val = this._trimAlignValue( val );
+
+ return val;
+ } else {
+ // .slice() creates a copy of the array
+ // this copy gets trimmed by min and max and then returned
+ vals = this.options.values.slice();
+ for ( i = 0; i < vals.length; i+= 1) {
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
+ }
+
+ return vals;
+ }
+ },
+
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
+ _trimAlignValue: function( val ) {
+ if ( val <= this._valueMin() ) {
+ return this._valueMin();
+ }
+ if ( val >= this._valueMax() ) {
+ return this._valueMax();
+ }
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
+ valModStep = (val - this._valueMin()) % step;
+ alignValue = val - valModStep;
+
+ if ( Math.abs(valModStep) * 2 >= step ) {
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
+ }
+
+ // Since JavaScript has problems with large floats, round
+ // the final value to 5 digits after the decimal point (see #4124)
+ return parseFloat( alignValue.toFixed(5) );
+ },
+
+ _valueMin: function() {
+ return this.options.min;
+ },
+
+ _valueMax: function() {
+ return this.options.max;
+ },
+
+ _refreshValue: function() {
+ var oRange = this.options.range,
+ o = this.options,
+ self = this,
+ animate = ( !this._animateOff ) ? o.animate : false,
+ valPercent,
+ _set = {},
+ lastValPercent,
+ value,
+ valueMin,
+ valueMax;
+
+ if ( this.options.values && this.options.values.length ) {
+ this.handles.each(function( i, j ) {
+ valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+ if ( self.options.range === true ) {
+ if ( self.orientation === "horizontal" ) {
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ } else {
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+ lastValPercent = valPercent;
+ });
+ } else {
+ value = this.value();
+ valueMin = this._valueMin();
+ valueMax = this._valueMax();
+ valPercent = ( valueMax !== valueMin ) ?
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+ 0;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ if ( oRange === "min" && this.orientation === "vertical" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "vertical" ) {
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+
+});
+
+$.extend( $.ui.slider, {
+ version: "1.8.9"
+});
+
+}(jQuery));
diff -r 4c0cc97a6399 -r ccf67eaf97ee client/digitallibrary/jquery/ui/jquery.ui.widget.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/digitallibrary/jquery/ui/jquery.ui.widget.js Sun Feb 06 22:17:41 2011 +0100
@@ -0,0 +1,262 @@
+/*!
+ * jQuery UI Widget 1.8.9
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function( $, undefined ) {
+
+// jQuery 1.4+
+if ( $.cleanData ) {
+ var _cleanData = $.cleanData;
+ $.cleanData = function( elems ) {
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ $( elem ).triggerHandler( "remove" );
+ }
+ _cleanData( elems );
+ };
+} else {
+ var _remove = $.fn.remove;
+ $.fn.remove = function( selector, keepData ) {
+ return this.each(function() {
+ if ( !keepData ) {
+ if ( !selector || $.filter( selector, [ this ] ).length ) {
+ $( "*", this ).add( [ this ] ).each(function() {
+ $( this ).triggerHandler( "remove" );
+ });
+ }
+ }
+ return _remove.call( $(this), selector, keepData );
+ });
+ };
+}
+
+$.widget = function( name, base, prototype ) {
+ var namespace = name.split( "." )[ 0 ],
+ fullName;
+ name = name.split( "." )[ 1 ];
+ fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ // create selector for plugin
+ $.expr[ ":" ][ fullName ] = function( elem ) {
+ return !!$.data( elem, name );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ $[ namespace ][ name ] = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+
+ var basePrototype = new base();
+ // we need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+// $.each( basePrototype, function( key, val ) {
+// if ( $.isPlainObject(val) ) {
+// basePrototype[ key ] = $.extend( {}, val );
+// }
+// });
+ basePrototype.options = $.extend( true, {}, basePrototype.options );
+ $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+ namespace: namespace,
+ widgetName: name,
+ widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
+ widgetBaseClass: fullName
+ }, prototype );
+
+ $.widget.bridge( name, $[ namespace ][ name ] );
+};
+
+$.widget.bridge = function( name, object ) {
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string",
+ args = Array.prototype.slice.call( arguments, 1 ),
+ returnValue = this;
+
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.extend.apply( null, [ true, options ].concat(args) ) :
+ options;
+
+ // prevent calls to internal methods
+ if ( isMethodCall && options.charAt( 0 ) === "_" ) {
+ return returnValue;
+ }
+
+ if ( isMethodCall ) {
+ this.each(function() {
+ var instance = $.data( this, name ),
+ methodValue = instance && $.isFunction( instance[options] ) ?
+ instance[ options ].apply( instance, args ) :
+ instance;
+ // TODO: add this back in 1.9 and use $.error() (see #5972)
+// if ( !instance ) {
+// throw "cannot call methods on " + name + " prior to initialization; " +
+// "attempted to call method '" + options + "'";
+// }
+// if ( !$.isFunction( instance[options] ) ) {
+// throw "no such method '" + options + "' for " + name + " widget instance";
+// }
+// var methodValue = instance[ options ].apply( instance, args );
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue;
+ return false;
+ }
+ });
+ } else {
+ this.each(function() {
+ var instance = $.data( this, name );
+ if ( instance ) {
+ instance.option( options || {} )._init();
+ } else {
+ $.data( this, name, new object( options, this ) );
+ }
+ });
+ }
+
+ return returnValue;
+ };
+};
+
+$.Widget = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+};
+
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ options: {
+ disabled: false
+ },
+ _createWidget: function( options, element ) {
+ // $.widget.bridge stores the plugin instance, but we do it anyway
+ // so that it's stored even before the _create function runs
+ $.data( element, this.widgetName, this );
+ this.element = $( element );
+ this.options = $.extend( true, {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ var self = this;
+ this.element.bind( "remove." + this.widgetName, function() {
+ self.destroy();
+ });
+
+ this._create();
+ this._trigger( "create" );
+ this._init();
+ },
+ _getCreateOptions: function() {
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
+ },
+ _create: function() {},
+ _init: function() {},
+
+ destroy: function() {
+ this.element
+ .unbind( "." + this.widgetName )
+ .removeData( this.widgetName );
+ this.widget()
+ .unbind( "." + this.widgetName )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetBaseClass + "-disabled " +
+ "ui-state-disabled" );
+ },
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.extend( {}, this.options );
+ }
+
+ if (typeof key === "string" ) {
+ if ( value === undefined ) {
+ return this.options[ key ];
+ }
+ options = {};
+ options[ key ] = value;
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var self = this;
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
+ });
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ [ value ? "addClass" : "removeClass"](
+ this.widgetBaseClass + "-disabled" + " " +
+ "ui-state-disabled" )
+ .attr( "aria-disabled", value );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _trigger: function( type, event, data ) {
+ var callback = this.options[ type ];
+
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ data = data || {};
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if ( event.originalEvent ) {
+ for ( var i = $.event.props.length, prop; i; ) {
+ prop = $.event.props[ --i ];
+ event[ prop ] = event.originalEvent[ prop ];
+ }
+ }
+
+ this.element.trigger( event, data );
+
+ return !( $.isFunction(callback) &&
+ callback.call( this.element[0], event, data ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+})( jQuery );