Mercurial > hg > digilib-old
changeset 1102:8878c6e36fd5
refactoring; define regions in JS
author | hertzhaft |
---|---|
date | Fri, 26 Oct 2012 10:32:14 +0200 |
parents | 34f893492adb |
children | d8c380faa347 |
files | webapp/src/main/webapp/jquery/jquery.digilib.regions.js |
diffstat | 1 files changed, 129 insertions(+), 116 deletions(-) [+] |
line wrap: on
line diff
--- a/webapp/src/main/webapp/jquery/jquery.digilib.regions.js Thu Oct 25 19:35:33 2012 +0200 +++ b/webapp/src/main/webapp/jquery/jquery.digilib.regions.js Fri Oct 26 10:32:14 2012 +0200 @@ -2,8 +2,8 @@ Mark up a digilib image with rectangular regions. -If hasRegionInfo=true reads regions from page HTML. -Element with regions has to be in digilib element, e.g. +If the parameter "processHtmlRegions" is set, the plugin reads region data from HTML. +Region data should be declared inside in the digilib element, like so: <map class="dl-keep dl-regioncontent"> <area href="http://www.mpiwg-berlin.mpg.de" coords="0.1,0.1,0.4,0.1" alt="MPI fuer Wissenschaftsgeschichte"/> @@ -13,7 +13,7 @@ According to the HTML specs, "area" and "a" elements are allowed inside of a "map". Both can have a "coords" attribute, but "area" elements can't contain child nodes. -To have regions with content use "a" tags, e.g. +To have regions with content use "a" tags, like so:. <map class="dl-keep dl-regioncontent"> <a href="http://www.mpiwg-berlin.mpg.de" coords="0.4907,0.3521,0.1458,0.107"> @@ -25,6 +25,19 @@ <area coords="0.3,0.5,0.15,0.1" /> </map> +Regions can also be defined in Javascript: +Set the parameter "regions" to an array with items. +Each item should be an object containing the following fields: + +rect + a retangle with relative coordinates (0..1); +index (optional) + a number to display in the region +attributes (optional) + HTML attributes for the region (id, class, title) +inner (optional) + inner HTML (has to be a jQuery object) + */ (function($) { @@ -41,6 +54,8 @@ }; // affine geometry plugin var geom = null; + // convenience variable, set in init() + var CSS = ''; var buttons = { defineregion : { @@ -105,14 +120,17 @@ 'regionSet' : ['regions', 'defineregion', 'removeregion', 'removeallregions', 'regioninfo', 'findcoords', 'finddata', 'lessoptions'], // url param for regions 'rg' : null, + // array with region data + 'regions' : null, // region attributes to copy from HTML 'regionAttributes' : { 'id' :1, 'href' :1, - 'title' :1, + 'name' :1, + 'alt' :1, 'target':1, - 'style' :1, - 'class' :1 + 'title' :1, + 'style' :1 } }; @@ -124,7 +142,6 @@ alert("Please turn on regions visibility!"); return; } - var cssPrefix = data.settings.cssPrefix; var $elem = data.$elem; var $body = $('body'); var bodyRect = geom.rectangle($body); @@ -132,11 +149,11 @@ var scalerRect = geom.rectangle($scaler); var pt1, pt2; // overlay prevents other elements from reacting to mouse events - var $overlay = $('<div class="'+cssPrefix+'overlay" style="position:absolute"/>'); + var $overlay = $('<div class="'+CSS+'overlay" style="position:absolute"/>'); $body.append($overlay); bodyRect.adjustDiv($overlay); - var $regionDiv = newRegionDiv(data); - addRegionAttributes(data, $regionDiv, {'class' : cssPrefix+"regionURL"}); + var attr = {'class' : CSS+"regionURL"}; + var $regionDiv = newRegionDiv(data, attr); // mousedown handler: start sizing var regionStart = function (evt) { @@ -192,7 +209,7 @@ alert("Please turn on regions visibility!"); return; } - var selector = 'div.'+data.settings.cssPrefix+'regionURL'; + var selector = 'div.'+CSS+'regionURL'; var $regionDiv = data.$elem.find(selector).last(); $regionDiv.remove(); redisplay(data); @@ -204,7 +221,7 @@ alert("Please turn on regions visibility!"); return; } - var selector = 'div.'+data.settings.cssPrefix+'regionURL'; + var selector = 'div.'+CSS+'regionURL'; var $regionDivs = data.$elem.find(selector); $regionDivs.remove(); redisplay(data); @@ -221,18 +238,17 @@ // show region info in a window showRegionInfo : function (data) { var $elem = data.$elem; - var cssPrefix = data.settings.cssPrefix; - var infoSelector = '#'+cssPrefix+'regionInfo'; + var infoSelector = '#'+CSS+'regionInfo'; if (fn.isOnScreen(data, infoSelector)) return; // already onscreen var html = '\ - <div id="'+cssPrefix+'regionInfo" class="'+cssPrefix+'keep '+cssPrefix+'regionInfo">\ - <table class="'+cssPrefix+'infoheader">\ + <div id="'+CSS+'regionInfo" class="'+CSS+'keep '+CSS+'regionInfo">\ + <table class="'+CSS+'infoheader">\ <tr>\ - <td class="'+cssPrefix+'infobutton html">HTML</td>\ - <td class="'+cssPrefix+'infobutton svgattr">SVG</td>\ - <td class="'+cssPrefix+'infobutton csv">CSV</td>\ - <td class="'+cssPrefix+'infobutton digilib">Digilib</td>\ - <td class="'+cssPrefix+'infobutton x">X</td>\ + <td class="'+CSS+'infobutton html">HTML</td>\ + <td class="'+CSS+'infobutton svgattr">SVG</td>\ + <td class="'+CSS+'infobutton csv">CSV</td>\ + <td class="'+CSS+'infobutton digilib">Digilib</td>\ + <td class="'+CSS+'infobutton x">X</td>\ </tr>\ </table>\ </div>'; @@ -245,8 +261,8 @@ $info.append(regionInfoDigilib(data, $regions)); var bind = function(name) { $info.find('.'+name).on('click.regioninfo', function () { - $info.find('div.'+cssPrefix+'info').hide(); - $info.find('div.'+cssPrefix+name).show(); + $info.find('div.'+CSS+'info').hide(); + $info.find('div.'+CSS+name).show(); fn.centerOnScreen(data, $info); }); }; @@ -264,12 +280,11 @@ // display region coordinates in an edit line showRegionCoords : function (data, $regionDiv) { var $elem = data.$elem; - var cssPrefix = data.settings.cssPrefix; var rect = $regionDiv.data('rect'); var text = $regionDiv.data('text'); var coordString = packCoords(rect, ','); var html = '\ - <div id="'+cssPrefix+'regionInfo" class="'+cssPrefix+'keep '+cssPrefix+'regionInfo">\ + <div id="'+CSS+'regionInfo" class="'+CSS+'keep '+CSS+'regionInfo">\ <div>'+text+'</div>\ <input name="coords" type="text" size="30" maxlength="40" value="'+coordString+'"/>\ </div>'; @@ -302,9 +317,9 @@ alert('invalid coordinates: ' + coords); return; } - var cssPrefix = data.settings.cssPrefix; - var attr = { 'class' : cssPrefix+'regionURL '+cssPrefix+'findregion' }; - addRegionDiv(data, rect, attr); + var attr = { 'class' : CSS+'regionURL '+CSS+'findregion' }; + var item = { 'rect' : rect, 'attributes' : attr }; + var $regionDiv = addRegionDiv(data, item); var za = data.zoomArea; if (!fn.isFullArea(za)) { za.setCenter(rect.getCenter()).stayInside(FULL_AREA); @@ -320,35 +335,34 @@ // find coordinates and display as new region findCoords : function (data) { var $elem = data.$elem; - var cssPrefix = data.settings.cssPrefix; - var findSelector = '#'+cssPrefix+'regionFindCoords'; + var findSelector = '#'+CSS+'regionFindCoords'; if (fn.isOnScreen(data, findSelector)) return; // already onscreen var html = '\ - <div id="'+cssPrefix+'regionFindCoords" class="'+cssPrefix+'keep '+cssPrefix+'regionInfo">\ + <div id="'+CSS+'regionFindCoords" class="'+CSS+'keep '+CSS+'regionInfo">\ <div>coordinates to find:</div>\ - <form class="'+cssPrefix+'form">\ + <form class="'+CSS+'form">\ <div>\ - <input class="'+cssPrefix+'input" name="coords" type="text" size="30" maxlength="40"/> \ + <input class="'+CSS+'input" name="coords" type="text" size="30" maxlength="40"/> \ </div>\ - <input class="'+cssPrefix+'submit" type="submit" name="sub" value="Ok"/>\ - <input class="'+cssPrefix+'cancel" type="button" value="Cancel"/>\ + <input class="'+CSS+'submit" type="submit" name="sub" value="Ok"/>\ + <input class="'+CSS+'cancel" type="button" value="Cancel"/>\ </form>\ </div>'; var $info = $(html); $info.appendTo($elem); var $form = $info.find('form'); - var $input = $info.find('input.'+cssPrefix+'input'); + var $input = $info.find('input.'+CSS+'input'); // handle submit $form.on('submit', function () { var coords = $input.val(); actions.regionFromCoords(data, coords); fn.withdraw($info); return false; - }); + }); // handle cancel - $form.find('.'+cssPrefix+'cancel').on('click', function () { + $form.find('.'+CSS+'cancel').on('click', function () { fn.withdraw($info); - }); + }); $info.fadeIn(); fn.centerOnScreen(data, $info); $input.focus(); @@ -357,28 +371,27 @@ // find text data and display as new region findData : function (data) { var $elem = data.$elem; - var cssPrefix = data.settings.cssPrefix; - var findSelector = '#'+cssPrefix+'regionFindData'; + var findSelector = '#'+CSS+'regionFindData'; if (fn.isOnScreen(data, findSelector)) return; // already onscreen var textOptions = getTextOptions(data, 'regionHTML'); var html = '\ - <div id="'+cssPrefix+'regionFindData" class="'+cssPrefix+'keep '+cssPrefix+'regionInfo">\ + <div id="'+CSS+'regionFindData" class="'+CSS+'keep '+CSS+'regionInfo">\ <div>text to find:</div>\ - <form class="'+cssPrefix+'form">\ + <form class="'+CSS+'form">\ <div>\ - <select class="'+cssPrefix+'findData">\ + <select class="'+CSS+'findData">\ '+textOptions+'\ </select>\ </div>\ - <input class="'+cssPrefix+'input" name="data" type="text" size="30" maxlength="40"/> \ - <input class="'+cssPrefix+'submit" type="submit" name="sub" value="Ok"/>\ - <input class="'+cssPrefix+'cancel" type="button" value="Cancel"/>\ + <input class="'+CSS+'input" name="data" type="text" size="30" maxlength="40"/> \ + <input class="'+CSS+'submit" type="submit" name="sub" value="Ok"/>\ + <input class="'+CSS+'cancel" type="button" value="Cancel"/>\ </form>\ </div>'; var $info = $(html); $info.appendTo($elem); var $form = $info.find('form'); - var $input = $info.find('input.'+cssPrefix+'input'); + var $input = $info.find('input.'+CSS+'input'); var $select = $info.find('select'); var findRegion = function () { var coords = $select.val(); @@ -390,9 +403,9 @@ $form.on('submit', findRegion); $select.on('change', findRegion); // handle cancel - $form.find('.'+cssPrefix+'cancel').on('click', function () { + $form.find('.'+CSS+'cancel').on('click', function () { fn.withdraw($info); - }); + }); $info.fadeIn(); fn.centerOnScreen(data, $info); $input.focus(); @@ -430,11 +443,10 @@ }; // create a new regionDiv and add it to data.$elem - var newRegionDiv = function (data) { - var settings = data.settings; - var cssPrefix = settings.cssPrefix; - var cls = cssPrefix+'region '+cssPrefix+'overlay'; + var newRegionDiv = function (data, attr) { + var cls = CSS+'region'; var $regionDiv = $('<div class="'+cls+'" style="display:none"/>'); + addRegionAttributes(data, $regionDiv, attr); data.$elem.append($regionDiv); return $regionDiv; }; @@ -451,14 +463,12 @@ // copy attributes to a region div var addRegionAttributes = function (data, $regionDiv, attributes) { if (attributes == null) return; - var settings = data.settings; - var cssPrefix = settings.cssPrefix; if (attributes['class']) { $regionDiv.addClass(attributes['class']); delete attributes['class']; } if (attributes['href']) { - $regionDiv.data('href', attributes['href']); // TODO: href from HTML? + $regionDiv.data('href', attributes['href']); delete attributes['href']; } if (attributes['title']) { @@ -469,91 +479,91 @@ // set region number var addRegionNumber = function (data, $regionDiv, index) { - var settings = data.settings; - var cssPrefix = settings.cssPrefix; - var $number = $('<a class="'+cssPrefix+'regionnumber">'+index+'</a>'); + var $number = $('<a class="'+CSS+'regionnumber">'+index+'</a>'); $regionDiv.append($number); return $regionDiv; }; // construct a region from a rectangle - var addRegionDiv = function (data, rect, attributes, number) { // ### + var addRegionDiv = function (data, item) { + var $regionDiv = newRegionDiv(data, item.attributes); var settings = data.settings; - var cssPrefix = settings.cssPrefix; - var $regionDiv = newRegionDiv(data); - addRegionAttributes(data, $regionDiv, attributes); - if (settings.showRegionNumbers && number) { - addRegionNumber(data, $regionDiv, number); + // add region number + if (settings.showRegionNumbers && item.index) { + addRegionNumber(data, $regionDiv, item.index); + } + // add inner HTML + if (item.inner) { + $regionDiv.append(item.inner); } - $regionDiv.data('rect', rect); - // handle click events on div + // store the coordinates in data + $regionDiv.data('rect', item.rect); + // trigger a region event on click $regionDiv.on('click.dlRegion', function(evt) { - $(data).trigger('regionClick', [$regionDiv]); - }); + $(data).trigger('regionClick', [$regionDiv]); + }); return $regionDiv; }; + // create regions from a Javascript array of items + var createRegionsFromJS = function (data, items) { + $.each(items, function(index, item) { + addRegionDiv(data, item); + }); + }; + // create regions from URL parameters var createRegionsFromURL = function (data) { - var cssPrefix = data.settings.cssPrefix; - var attr = {'class' : cssPrefix+"regionURL"}; var userRegions = unpackRegions(data); - $.each(userRegions, function(index, rect) { - addRegionDiv(data, rect, attr, index+1); - }); + if (!userRegions) return; + createRegionsFromJS(data, userRegions); }; // create regions from HTML var createRegionsFromHTML = function (data) { // regions are defined in "area" tags - var $content = data.$elem.find(data.settings.areaSelector); - var cssPrefix = data.settings.cssPrefix; - console.debug("createRegionsFromHTML. elems found: ", $content.length); - $content.each(function(index, area) { + var $areas = data.$elem.find(data.settings.areaSelector); + console.debug("createRegionsFromHTML - elems found: ", $areas.length); + $areas.each(function(index, area) { var $area = $(area); + // the "title" attribute contains the text for the tooltip + var title = $area.attr('title'); // the "coords" attribute contains the region coords (0..1) var coords = $area.attr('coords'); - var title = $area.attr('title'); // create the rectangle var rect = parseCoords(data, coords); if (rect == null) { return console.error('bad coords in HTML:', title, coords); } + // mark div class as regionHTML + var cls = $area.attr('class') || ''; + cls += ' '+CSS+'regionHTML'; + var attr = {'class' : cls}; // copy attributes - var attributes = {}; for (var n in data.settings.regionAttributes) { - attributes[n] = $area.attr(n); + attr[n] = $area.attr(n); } - var $regionDiv = addRegionDiv(data, rect, attributes); - // mark div as regionHTML - $regionDiv.addClass(cssPrefix+'regionHTML'); - var $contents = $area.contents().clone(); - if (attributes.href != null) { // TODO: href set in region??? + // copy inner HTML + var $inner = $area.contents().clone(); + if (attr.href != null) { // wrap contents in a-tag - var $ca = $('<a href="'+attributes.href+'"/>'); - $ca.append($contents); - // alt attribute is also content (BTW: area-tag has no content()) - $ca.append($area.attr('alt')); - $regionDiv.append($ca); - } else { - $regionDiv.append($contents); - // alt attribute is also content (BTW: area-tag has no content()) - $regionDiv.append($area.attr('alt')); + var $a = $('<a href="'+attr.href+'"/>'); + $inner = $a.append($inner); } + var item = {'rect' : rect, 'attributes' : attr, 'inner' : $inner}; + var $regionDiv = addRegionDiv(data, item); }); }; // select region divs (HTML or URL) var getRegions = function (data, selector) { - var cssPrefix = data.settings.cssPrefix; - var $regions = data.$elem.find('div.'+cssPrefix+selector); + var $regions = data.$elem.find('div.'+CSS+selector); return $regions; }; // make text data options html var getTextOptions = function (data, selector) { - var cssPrefix = data.settings.cssPrefix; - var makeOptionHTML = function(item, index) { + var createOption = function(item, index) { var $item = $(item); var rect = $item.data('rect'); if (rect == null) @@ -563,7 +573,7 @@ return '<option value="'+coords+'">'+text+'</option>'; }; var $regions = getRegions(data, selector); - var options = $.map($regions, makeOptionHTML); + var options = $.map($regions, createOption); return options.join(''); }; @@ -578,9 +588,8 @@ // html for later insertion var regionInfoHTML = function (data, $regions) { - var cssPrefix = data.settings.cssPrefix; - var $infoDiv = $('<div class="'+cssPrefix+'info '+cssPrefix+'html"/>'); - $infoDiv.append($('<div/>').text('<map class="'+cssPrefix+'keep '+cssPrefix+'regioncontent">')); + var $infoDiv = $('<div class="'+CSS+'info '+CSS+'html"/>'); + $infoDiv.append($('<div/>').text('<map class="'+CSS+'keep '+CSS+'regioncontent">')); $regions.each(function(index, region) { var rect = $(region).data('rect'); var coords = packCoords(rect, ','); @@ -592,8 +601,7 @@ // SVG-style var regionInfoSVG = function (data, $regions) { - var cssPrefix = data.settings.cssPrefix; - var $infoDiv = $('<div class="'+cssPrefix+'info '+cssPrefix+'svgattr"/>'); + var $infoDiv = $('<div class="'+CSS+'info '+CSS+'svgattr"/>'); $regions.each(function(index, region) { var rect = $(region).data('rect'); var coords = packCoords(rect, ','); @@ -604,8 +612,7 @@ // CSV-style var regionInfoCSV = function (data, $regions) { - var cssPrefix = data.settings.cssPrefix; - var $infoDiv = $('<div class="'+cssPrefix+'info '+cssPrefix+'csv"/>'); + var $infoDiv = $('<div class="'+CSS+'info '+CSS+'csv"/>'); $regions.each(function(index, region) { var rect = $(region).data('rect'); var coords = packCoords(rect, ','); @@ -616,8 +623,7 @@ // digilib-style (h,w@x,y) var regionInfoDigilib = function (data, $regions) { - var cssPrefix = data.settings.cssPrefix; - var $infoDiv = $('<div class="'+cssPrefix+'info '+cssPrefix+'digilib"/>'); + var $infoDiv = $('<div class="'+CSS+'info '+CSS+'digilib"/>'); $regions.each(function(index, region) { var rect = $(region).data('rect'); var coords = packCoords(rect, ','); @@ -669,24 +675,27 @@ var regions = $.map(coords, function(coord, index) { var pos = coord.split("/", 4); var rect = geom.rectangle(pos[0], pos[1], pos[2], pos[3]); - return rect; + var attr = {'class' : CSS+"regionURL"}; + var item = {'rect' : rect, 'index' : index+1, 'attributes' : attr}; + return item; }); return regions; }; // pack user regions array into a URL parameter string var packRegions = function (data) { - var $regions = getRegions(data, 'regionsURL'); + var $regions = getRegions(data, 'regionURL'); if ($regions.length == 0) { data.settings.rg = null; return; } - var packRegion = function(region, index) { + var pack = function(region, index) { var $region = $(region); var rect = $region.data('rect'); - packCoords(rect, '/'); + var packed = packCoords(rect, '/'); + return packed; }; - var coords = $.map($regions, packRegion); + var coords = $.map($regions, pack); var rg = coords.join(','); data.settings.rg = rg; console.debug('pack regions:', rg); @@ -744,6 +753,10 @@ var data = this; var settings = data.settings; console.debug("regions: handleSetup", settings.rg); + // regions with content are given in a Javascript array + if (settings.regions) { + createRegionsFromJS(data, settings.regions); + } // regions with content are given in HTML divs if (settings.processHtmlRegions) { createRegionsFromHTML(data); @@ -796,7 +809,7 @@ console.debug('initialising regions plugin. data:', data); var $elem = data.$elem; var settings = data.settings; - var cssPrefix = data.settings.cssPrefix; + CSS = settings.cssPrefix; FULL_AREA = geom.rectangle(0, 0, 1, 1); // install event handlers var $data = $(data);