123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952 |
- /**
- * Image Map Editor (imgmap) - in-browser imagemap editor
- * Copyright (C) 2006 - 2008 Adam Maschek (adam.maschek @ gmail.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- /**
- * @fileoverview
- * Online Image Map Editor - main script file.
- * This is the main script file of the Online Image Map Editor.
- *
- * TODO:
- * -scriptload race condition fix
- * -destroy/cleanup function ?
- * -testing highlighter
- * -cursor area_mousemove in opera not refreshing quite well - bug reported
- * -get rid of memo array
- * -highlight which control point is edited in html or form mode
- * -more comments, especially on config vars
- * -make function names more logical
- * - dumpconfig
- * -prepare for bad input /poly not properly closed?
- * -prepare for % values in coords
- * -prepare for default shape http://www.w3.org/TR/html4/struct/objects.html#edef-AREA
- *
- * @date 26-02-2007 2:24:50
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @copyright
- * @version 2.2
- *
- */
- /*jslint browser: true, newcap: false, white: false, onevar: false, plusplus: false, eqeqeq: false, nomen: false */
- /*global imgmapStrings:true, window:false, G_vmlCanvasManager:false, air:false, imgmap_spawnObjects:true */
- /**
- * @author Adam Maschek
- * @constructor
- * @param config The config object.
- */
- function imgmap(config) {
- /** Version string of imgmap */
- this.version = "2.2";
- /** Build date of imgmap */
- this.buildDate = "2009/08/12 22:18";
- /** Sequential build number of imgmap */
- this.buildNumber = "113";
- /** Config object of the imgmap instance */
- this.config = {};
- /** Status flag to indicate current drawing mode */
- this.is_drawing = 0;
- /** Array to hold language strings */
- this.strings = [];
- /** Helper array for some drawing operations */
- this.memory = [];
- /** Array to hold reference to all areas (canvases) */
- this.areas = [];
- /** Array to hold last log entries */
- this.logStore = [];
- /** Associative array to hold bound event handlers */
- this.eventHandlers = {};
- this.currentid = 0;
- this.draggedId = null;
- this.selectedId = null;
- this.nextShape = 'rect';
- /** possible values: 0 - edit, 1 - preview */
- this.viewmode = 0;
- /** array of dynamically loaded javascripts */
- this.loadedScripts = [];
- this.isLoaded = false;
- this.cntReloads = 0;
- /** holds the name of the actively edited map, use getMapName to read it */
- this.mapname = '';
- /** holds the id of the actively edited map, use getMapIdto read it */
- this.mapid = '';
- /** watermark to attach to output */
- this.waterMark = '<!-- Created by Online Image Map Editor (http://www.maschek.hu/imagemap/index) -->';
- /** global scale of areas (1-normal, 2-doubled, 0.5-half, etc.) */
- this.globalscale = 1;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_DRAW = 1;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_MOVE = 11;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_RESIZE_TOP = 12;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_RESIZE_RIGHT = 13;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_RESIZE_BOTTOM = 14;
- /** is_drawing draw mode constant */
- this.DM_RECTANGLE_RESIZE_LEFT = 15;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_DRAW = 2;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_MOVE = 21;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_RESIZE_TOP = 22;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_RESIZE_RIGHT = 23;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_RESIZE_BOTTOM = 24;
- /** is_drawing draw mode constant */
- this.DM_SQUARE_RESIZE_LEFT = 25;
- /** is_drawing draw mode constant */
- this.DM_POLYGON_DRAW = 3;
- /** is_drawing draw mode constant */
- this.DM_POLYGON_LASTDRAW = 30;
- /** is_drawing draw mode constant */
- this.DM_POLYGON_MOVE = 31;
- /** is_drawing draw mode constant */
- this.DM_BEZIER_DRAW = 4;
- /** is_drawing draw mode constant */
- this.DM_BEZIER_LASTDRAW = 40;
- /** is_drawing draw mode constant */
- this.DM_BEZIER_MOVE = 41;
- //set some config defaults below
- /**
- * Mode of operation
- * possible values:
- * editor - classical editor,
- * editor2 - dreamweaver style editor,
- * highlighter - map highlighter, will spawn imgmap instances for each map found in the current page
- * highlighter_spawn - internal mode after spawning imgmap objects
- */
- this.config.mode = "editor";
- this.config.baseroot = '';
- this.config.lang = '';
- this.config.defaultLang = 'en';
- this.config.loglevel = 0;
- this.config.custom_callbacks = {};//possible values: see below!
- /** Callback events that you can handle in your GUI. */
- this.event_types = [
- 'onModeChanged',
- 'onHtmlChanged',
- 'onAddArea',
- 'onRemoveArea',
- 'onDrawArea',
- 'onResizeArea',
- 'onRelaxArea',
- 'onFocusArea',
- 'onBlurArea',
- 'onMoveArea',
- 'onSelectRow',
- 'onLoadImage',
- 'onSetMap',
- 'onGetMap',
- 'onSelectArea',
- 'onDblClickArea',
- 'onStatusMessage',
- 'onAreaChanged'];
- //default color values
- this.config.CL_DRAW_BOX = '#E32636';
- this.config.CL_DRAW_SHAPE = '#d00';
- this.config.CL_DRAW_BG = '#fff';
- this.config.CL_NORM_BOX = '#E32636';
- this.config.CL_NORM_SHAPE = '#d00';
- this.config.CL_NORM_BG = '#fff';
- this.config.CL_HIGHLIGHT_BOX = '#E32636';
- this.config.CL_HIGHLIGHT_SHAPE = '#d00';
- this.config.CL_HIGHLIGHT_BG = '#fff';
- this.config.CL_KNOB = '#555';
- this.config.bounding_box = true;
- this.config.label = '%n';
- //the format string of the area labels - possible values: %n - number, %c - coords, %h - href, %a - alt, %t - title
- this.config.label_class = 'imgmap_label';
- //the css class to apply on labels
- this.config.label_style = 'font: bold 10px Arial';
- //this.config.label_style = 'font-weight: bold; font-size: 10px; font-family: Arial; color: #964';
- //the css style(s) to apply on labels
- this.config.hint = '#%n %h';
- //the format string of the area mouseover hints - possible values: %n - number, %c - coords, %h - href, %a - alt, %t - title
- this.config.draw_opacity = '35';
- //the opacity value of the area while drawing, moving or resizing - possible values 0 - 100 or range "(x)-y"
- this.config.norm_opacity = '50';
- //the opacity value of the area while relaxed - possible values 0 - 100 or range "(x)-y"
- this.config.highlight_opacity = '70';
- //the opacity value of the area while highlighted - possible values 0 - 100 or range "(x)-y"
- this.config.cursor_default = 'crosshair'; //auto/pointer
- //the css cursor while hovering over the image
- //browser sniff
- var ua = navigator.userAgent;
- this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
- this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
- this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
- this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
- this.isGecko = ua.indexOf('Gecko') != -1;
- this.isSafari = ua.indexOf('Safari') != -1;
- this.isOpera = (typeof window.opera != 'undefined');
- this.setup(config);
- }
- /**
- * Return an object given by id or object itself.
- * @date 22-02-2007 0:14:50
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param objorid A DOM object, or id of a DOM object.
- * @return The identified DOM object or null on error.
- */
- imgmap.prototype.assignOID = function(objorid) {
- try {
- if (typeof objorid == 'undefined') {
- this.log("Undefined object passed to assignOID.");// Called from: " + arguments.callee.caller, 1);
- return null;
- }
- else if (typeof objorid == 'object') {
- return objorid;
- }
- else if (typeof objorid == 'string') {
- return document.getElementById(objorid);
- }
- }
- catch (err) {
- this.log("Error in assignOID", 1);
- }
- return null;
- };
- /**
- * Main setup function.
- * Can be called manually or constructor will call it.
- * @date 22-02-2007 0:15:42
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param config config object
- * @return True if all went ok.
- */
- imgmap.prototype.setup = function(config) {
- //this.log('setup');
- //copy non-default config parameters to this.config
- for (var i in config) {
- if (config.hasOwnProperty(i)) {
- this.config[i] = config[i];
- }
- }
- //set document event hooks
- this.addEvent(document, 'keydown', this.eventHandlers.doc_keydown = this.doc_keydown.bind(this));
- this.addEvent(document, 'keyup', this.eventHandlers.doc_keyup = this.doc_keyup.bind(this));
- this.addEvent(document, 'mousedown', this.eventHandlers.doc_mousedown = this.doc_mousedown.bind(this));
- //set pic_container element - supposedly it already exists in the DOM
- if (config && config.pic_container) {
- this.pic_container = this.assignOID(config.pic_container);
- this.disableSelection(this.pic_container);
- }
- if (!this.config.baseroot) {
- //search for a base - theoretically there can only be one, but lets search
- //for the first non-empty
- var bases = document.getElementsByTagName('base');
- var base = '';
- for (i=0; i<bases.length; i++) {//i declared earlier
- if (bases[i].href) {
- base = bases[i].href;
- //append slash if missing
- if (base.charAt(base.length-1) != '/') {
- base+= '/';
- }
- break;
- }
- }
- //search for scripts
- var scripts = document.getElementsByTagName('script');
- var found = false;
- for (i=0; i<scripts.length; i++) {//i declared earlier
- if (scripts[i].src && scripts[i].src.match(/imgmap\w*\.js(\?.*?)?$/)) {
- var src = scripts[i].src;
- //cut filename part, leave last slash
- src = src.substring(0, src.lastIndexOf('/') + 1);
- //set final baseroot path
- if (base && src.indexOf('://') == -1) {
- this.config.baseroot = base + src;
- }
- else {
- this.config.baseroot = src;
- }
- //exit loop
- found = true;
- break;
- }
- }
- if (!found && this.config.baseroot === '') {
- this.log("Unable to detect baseroot.", 1);
- }
- }
- //load excanvas js - as soon as possible
- if (this.isMSIE &&
- typeof window.CanvasRenderingContext2D == 'undefined' && typeof G_vmlCanvasManager == 'undefined') {
- this.loadScript(this.config.baseroot + 'excanvas.js');
- //alert('loadcanvas');
- }
- //alert(this.config.baseroot);
- //load language js - as soon as possible
- if (!this.config.lang) {
- this.config.lang = this.detectLanguage();
- }
- if (typeof imgmapStrings == 'undefined') {
- //language file might have already been loaded (ex highlighter mode)
- this.loadScript(this.config.baseroot + 'lang_' + this.config.lang + '.js');
- }
- //check event hooks
- var found, j, le;
- for (i in this.config.custom_callbacks) {
- if (this.config.custom_callbacks.hasOwnProperty(i)) {
- found = false;
- for (j = 0, le = this.event_types.length; j < le; j++) {
- if (i == this.event_types[j]) {
- found = true;
- break;
- }
- }
- if (!found) {
- this.log("Unknown custom callback: " + i, 1);
- }
- }
- }
- //hook onload event - as late as possible
- this.addEvent(window, 'load', this.onLoad.bind(this));
- return true;
- };
- /**
- * currently unused
- * @ignore
- */
- imgmap.prototype.retryDelayed = function(fn, delay, tries) {
- if (typeof fn.tries == 'undefined') {fn.tries = 0;}
- //alert(fn.tries+1);
- if (fn.tries++ < tries) {
- //alert('ss');
- window.setTimeout(function() {
- fn.apply(this);
- }, delay);
- }
- };
- /**
- * EVENT HANDLER: Handle event when the page with scripts is loaded.
- * @date 22-02-2007 0:16:22
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param e The event object.
- */
- imgmap.prototype.onLoad = function(e) {
- if (this.isLoaded) {return true;}
- var _this = this;
- //this.log('readystate: ' + document.readyState);
- if (typeof imgmapStrings == 'undefined') {
- if (this.cntReloads++ < 5) {
- //this.retryDelayed(_this.onLoad(), 1000, 3);
- window.setTimeout(function () {_this.onLoad(e);} ,1200);
- this.log('Delaying onload (language ' + this.config.lang + ' not loaded, try: ' + this.cntReloads + ')');
- return false;
- }
- else if (this.config.lang != this.config.defaultLang && this.config.defaultLang != 'en') {
- this.log('Falling back to default language: ' + this.config.defaultLang);
- this.cntReloads = 0;
- this.config.lang = this.config.defaultLang;
- this.loadScript(this.config.baseroot + 'lang_' + this.config.lang + '.js');
- window.setTimeout(function () {_this.onLoad(e);} ,1200);
- return false;
- }
- else if (this.config.lang != 'en') {
- this.log('Falling back to english language');
- this.cntReloads = 0;
- this.config.lang = 'en';
- this.loadScript(this.config.baseroot + 'lang_' + this.config.lang + '.js');
- window.setTimeout(function () {_this.onLoad(e);} ,1200);
- return false;
- }
- }
- //else
- try {
- this.loadStrings(imgmapStrings);
- }
- catch (err) {
- this.log("Unable to load language strings", 1);
- }
- //check if ExplorerCanvas correctly loaded - detect if browser supports canvas
- //alert(typeof G_vmlCanvasManager + this.isMSIE + typeof window.CanvasRenderingContext2D);
- if (this.isMSIE) {
- //alert('cccc');
- //alert(typeof G_vmlCanvasManager);
- if (typeof window.CanvasRenderingContext2D == 'undefined' && typeof G_vmlCanvasManager == 'undefined') {
- //alert('bbb');
- /*
- if (this.cntReloads++ < 5) {
- var _this = this;
- //this.retryDelayed(_this.onLoad(), 1000, 3);
- window.setTimeout(function () {
- _this.onLoad(e);
- }
- ,1000
- );
- //alert('aaa');
- this.log('Delaying onload (excanvas not loaded, try: ' + this.cntReloads + ')');
- return false;
- }
- */
- this.log(this.strings.ERR_EXCANVAS_LOAD, 2);//critical error
- }
- }
- if (this.config.mode == 'highlighter') {
- //call global scope function
- imgmap_spawnObjects(this.config);
- }
- this.isLoaded = true;
- return true;
- };
- /**
- * Attach new 'evt' event handler 'callback' to 'obj'
- * @date 24-02-2007 21:16:20
- * @param obj The object on which the handler is defined.
- * @param evt The name of the event, like mousedown.
- * @param callback The callback function (named if you want it to be removed).
- */
- imgmap.prototype.addEvent = function(obj, evt, callback) {
- if (obj.attachEvent) {
- //Microsoft style registration model
- return obj.attachEvent("on" + evt, callback);
- }
- else if (obj.addEventListener) {
- //W3C style model
- obj.addEventListener(evt, callback, false);
- return true;
- }
- else {
- obj['on' + evt] = callback;
- }
- };
- /**
- * Detach 'evt' event handled by 'callback' from 'obj' object.
- * Callback must be a non anonymous function, see eventHandlers.
- * @see #eventHandlers
- * Example: myimgmap.removeEvent(myimgmap.pic, 'mousedown', myimgmap.eventHandlers.img_mousedown);
- * @date 24-11-2007 15:22:17
- * @param obj The object on which the handler is defined.
- * @param evt The name of the event, like mousedown.
- * @param callback The named callback function.
- */
- imgmap.prototype.removeEvent = function(obj, evt, callback) {
- if (obj.detachEvent) {
- //Microsoft style detach model
- return obj.detachEvent("on" + evt, callback);
- }
- else if (obj.removeEventListener) {
- //W3C style model
- obj.removeEventListener(evt, callback, false);
- return true;
- }
- else {
- obj['on' + evt] = null;
- }
- };
- /**
- * We need this because load events for scripts function slightly differently.
- * @link http://dean.edwards.name/weblog/2006/06/again/
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 24-03-2007 11:02:21
- */
- imgmap.prototype.addLoadEvent = function(obj, callback) {
- if (obj.attachEvent) {
- //Microsoft style registration model
- return obj.attachEvent("onreadystatechange", callback);
- }
- else if (obj.addEventListener) {
- //W3C style registration model
- obj.addEventListener('load', callback, false);
- return true;
- }
- else {
- obj.onload = callback;
- }
- };
- /**
- * Include another js script into the current document.
- * @date 22-02-2007 0:17:04
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param url The url of the script we want to load.
- * @see #script_load
- * @see #addLoadEvent
- */
- imgmap.prototype.loadScript = function(url) {
- if (url === '') {return false;}
- if (this.loadedScripts[url] == 1) {return true;}//script already loaded
- this.log('Loading script: ' + url);
- //we might need this someday for safari?
- //var temp = '<script language="javascript" type="text/javascript" src="' + url + '"></script>';
- //document.write(temp);
- try {
- var head = document.getElementsByTagName('head')[0];
- var temp = document.createElement('SCRIPT');
- temp.setAttribute('language', 'javascript');
- temp.setAttribute('type', 'text/javascript');
- temp.setAttribute('src', url);
- //temp.setAttribute('defer', true);
- head.appendChild(temp);
- this.addLoadEvent(temp, this.script_load.bind(this));
- }
- catch (err) {
- this.log('Error loading script: ' + url);
- }
- return true;
- };
- /**
- * EVENT HANDLER: Event handler of external script loaded.
- * @param e The event object.
- */
- imgmap.prototype.script_load = function(e) {
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- var url = obj.src;
- var complete = false;
- if (typeof obj.readyState != 'undefined') {
- //explorer
- if (obj.readyState == 'complete' || obj.readyState == 'loaded') {
- complete = true;
- }
- }
- else {
- //other browsers?
- complete = true;
- }
- if (complete) {
- this.loadedScripts[url] = 1;
- this.log('Loaded script: ' + url);
- return true;
- }
- };
- /**
- * Load strings from a key:value object to the prototype strings array.
- * @author adam
- * @date 2007
- * @param obj Javascript object that holds key:value pairs.
- */
- imgmap.prototype.loadStrings = function(obj) {
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- this.strings[key] = obj[key];
- }
- }
- };
- /**
- * This function is to load a given img url to the pic_container.
- *
- * Loading an image will clear all current maps.
- * @see #useImage
- * @param img The imageurl or object to load (if object, function will get url, and do a recall)
- * @param imgw The width we want to force on the image (optional)
- * @param imgh The height we want to force on the image (optional)
- * @returns True on success
- */
- imgmap.prototype.loadImage = function(img, imgw, imgh) {
- //test for container
- if (typeof this.pic_container == 'undefined') {
- this.log('You must have pic_container defined to use loadImage!', 2);
- return false;
- }
- //wipe all
- this.removeAllAreas();
- //reset scale
- this.globalscale = 1;
- this.fireEvent('onHtmlChanged', '');//empty
- if (!this._getLastArea()) {
- //init with one new area if there was none editable
- if (this.config.mode != "editor2") {this.addNewArea();}
- }
- if (typeof img == 'string') {
- //there is an image given with url to load
- if (typeof this.pic == 'undefined') {
- this.pic = document.createElement('IMG');
- this.pic_container.appendChild(this.pic);
- //event handler hooking - only at the first load
- this.addEvent(this.pic, 'mousedown', this.eventHandlers.img_mousedown = this.img_mousedown.bind(this));
- this.addEvent(this.pic, 'mouseup', this.eventHandlers.img_mouseup = this.img_mouseup.bind(this));
- this.addEvent(this.pic, 'mousemove', this.eventHandlers.img_mousemove = this.img_mousemove.bind(this));
- this.pic.style.cursor = this.config.cursor_default;
- }
- //img ='../../'+img;
- //this.log('Loading image: ' + img, 0);
- //calculate timestamp to bypass browser cache mechanism
- var q = '?';
- if (img.indexOf('?') > -1) {
- q = '&';
- }
- this.pic.src = img + q + (new Date().getTime());
- if (imgw && imgw > 0) {this.pic.setAttribute('width', imgw);}
- if (imgh && imgh > 0) {this.pic.setAttribute('height', imgh);}
- this.fireEvent('onLoadImage', this.pic);
- return true;
- }
- else if (typeof img == 'object') {
- //we have to use the src of the image object
- var src = img.src; //img.getAttribute('src');
- if (src === '' && img.getAttribute('mce_src') !== '') {
- //if it is a tinymce object, it has no src but mce_src attribute!
- src = img.getAttribute('mce_src');
- }
- else if (src === '' && img.getAttribute('_fcksavedurl') !== '') {
- //if it is an fck object, it might have only _fcksavedurl attribute!
- src = img.getAttribute('_fcksavedurl');
- }
- // Get the displayed dimensions of the image
- if (!imgw) {
- imgw = img.clientWidth;
- }
- if (!imgh) {
- imgh = img.clientHeight;
- }
- //recurse, this time with the url string
- return this.loadImage(src, imgw, imgh);
- }
- };
- /**
- * We use this when there is an existing image object we want to handle with imgmap.
- * Mainly used in highlighter mode.
- * @author adam
- * @see #loadImage
- * @see #imgmap_spawnObjects
- * @date 2007
- * @param img DOM object or id of image we want to use.
- */
- imgmap.prototype.useImage = function(img) {
- //wipe all
- this.removeAllAreas();
- if (!this._getLastArea()) {
- //init with one new area if there was none editable
- if (this.config.mode != "editor2") {this.addNewArea();}
- }
- img = this.assignOID(img);
- if (typeof img == 'object') {
- if (typeof this.pic != 'undefined') {
- //remove previous handlers
- this.removeEvent(this.pic, 'mousedown', this.eventHandlers.img_mousedown);
- this.removeEvent(this.pic, 'mouseup', this.eventHandlers.img_mouseup);
- this.removeEvent(this.pic, 'mousemove', this.eventHandlers.img_mousemove);
- this.pic.style.cursor = '';
- }
- this.pic = img;
- //hook event handlers
- this.addEvent(this.pic, 'mousedown', this.eventHandlers.img_mousedown = this.img_mousedown.bind(this));
- this.addEvent(this.pic, 'mouseup', this.eventHandlers.img_mouseup = this.img_mouseup.bind(this));
- this.addEvent(this.pic, 'mousemove', this.eventHandlers.img_mousemove = this.img_mousemove.bind(this));
- this.pic.style.cursor = this.config.cursor_default;
- if (this.pic.parentNode.className == 'pic_container') {
- //use existing container
- this.pic_container = this.pic.parentNode;
- }
- else {
- //dynamically create container
- this.pic_container = document.createElement("div");
- this.pic_container.className = 'pic_container';
- this.pic.parentNode.insertBefore(this.pic_container, this.pic);
- //ref: If the node already exists it is removed from current parent node, then added to new parent node.
- this.pic_container.appendChild(this.pic);
- }
- this.fireEvent('onLoadImage', this.pic);
- return true;
- }
- };
- /**
- * Fires custom hook onStatusMessage, passing the status string.
- * Use this to update your GUI.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 26-07-2008 13:22:54
- * @param str The status string
- */
- imgmap.prototype.statusMessage = function(str) {
- this.fireEvent('onStatusMessage', str);
- };
- /**
- * Adds basic logging functionality using firebug console object if available.
- * Also tries to use AIR introspector if available.
- * @date 20-02-2007 17:55:18
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param obj The object or string you want to debug/echo.
- * @level level The log level, 0 being the smallest issue.
- */
- imgmap.prototype.log = function(obj, level) {
- /*
- if (level === '' || typeof level == 'undefined') {level = 0;}
- if (this.config.loglevel != -1 && level >= this.config.loglevel) {
- this.logStore.push({level: level, obj: obj});
- }
- if (typeof console == 'object') {
- console.log(obj);
- }
- else if (this.isOpera) {
- opera.postError(level + ': ' + obj);
- }
- else if (typeof air == 'object') {
- //we are inside AIR
- if (typeof air.Introspector == 'object') {
- air.Introspector.Console.log(obj);
- }
- else {
- air.trace(obj);
- }
- }
- else {
- if (level > 1) {
- //alert(level + ': ' + obj);
- //dump with all pevious errors:
- var msg = '';
- for (var i=0, le = this.logStore.length; i<le; i++) {
- msg+= this.logStore[i].level + ': ' + this.logStore[i].obj + "\n";
- }
- alert(msg);
- }
- else {
- window.defaultStatus = (level + ': ' + obj);
- }
- }
- */
- };
- /**
- * Produces the image map HTML output with the defined areas.
- * Invokes getMapInnerHTML.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-06 15:10:27
- * @param flags Currently ony 'noscale' used to prevent scaling of coordinates in preview mode.
- * @return The generated html code.
- */
- imgmap.prototype.getMapHTML = function(flags) {
- var html = '<map id="'+this.getMapId()+'" name="'+this.getMapName()+'">' + this.getMapInnerHTML(flags) + this.waterMark + '</map>';
- this.fireEvent('onGetMap', html);
- //alert(html);
- return html;
- };
- /**
- * Get the map areas part only of the current imagemap.
- * @see #getMapHTML
- * @author adam
- * @param flags Currently ony 'noscale' used to prevent scaling of coordinates in preview mode.
- * @return The generated map code without the map wrapper.
- */
- imgmap.prototype.getMapInnerHTML = function(flags) {
- var html, coords;
- html = '';
- //foreach area properties
- for (var i=0, le = this.areas.length; i<le; i++) {
- if (this.areas[i]) {
- if (this.areas[i].shape && this.areas[i].shape != 'undefined') {
- coords = this.areas[i].lastInput;
- if (flags && flags.match(/noscale/)) {
- //for preview use real coordinates, not scaled
- var cs = coords.split(',');
- for (var j=0, le2 = cs.length; j<le2; j++) {
- cs[j] = Math.round(cs[j] * this.globalscale);
- }
- coords = cs.join(',');
- }
- html+= '<area shape="' + this.areas[i].shape + '"' +
- ' alt="' + this.areas[i].aalt + '"' +
- ' title="' + this.areas[i].atitle + '"' +
- ' coords="' + coords + '"' +
- ' href="' + this.areas[i].ahref + '"' +
- ' target="' + this.areas[i].atarget + '" />';
- }
- }
- }
- //alert(html);
- return html;
- };
- /**
- * Get the map name of the current imagemap.
- * If doesnt exist, nor map id, generate a new name based on timestamp.
- * The most portable solution is to use the same value for id and name.
- * This also conforms the HTML 5 specification, that says:
- * "If the id attribute is also specified, both attributes must have the same value."
- * @link http://www.w3.org/html/wg/html5/#the-map-element
- * @author adam
- * @see #getMapId
- * @return The name of the map.
- */
- imgmap.prototype.getMapName = function() {
- if (this.mapname === '') {
- if (this.mapid !== '') {return this.mapid;}
- var now = new Date();
- this.mapname = 'imgmap' + now.getFullYear() + (now.getMonth()+1) + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds();
- }
- return this.mapname;
- };
- /**
- * Get the map id of the current imagemap.
- * If doesnt exist, use map name.
- * @author adam
- * @see #getMapName
- * @return The id of the map.
- */
- imgmap.prototype.getMapId = function() {
- if (this.mapid === '') {
- this.mapid = this.getMapName();
- }
- return this.mapid;
- };
- /**
- * Convert wild shape names to normal ones.
- * @date 25-12-2008 19:27:06
- * @param shape The name of the shape to convert.
- * @return The normalized shape name, rect as default.
- */
- imgmap.prototype._normShape = function(shape) {
- if (!shape) {return 'rect';}
- shape = this.trim(shape).toLowerCase();
- if (shape.substring(0, 4) == 'rect') {return 'rect';}
- if (shape.substring(0, 4) == 'circ') {return 'circle';}
- if (shape.substring(0, 4) == 'poly') {return 'poly';}
- return 'rect';
- };
- /**
- * Try to normalize coordinates that came from:
- * 1. html textarea
- * 2. user input in the active area's input field
- * 3. from the html source in case of plugins or highlighter
- * Example of inputs that need to be handled:
- * 035,035 075,062
- * 150,217, 190,257, 150,297,110,257
- * @author adam
- * @param coords The coordinates in a string.
- * @param shape The shape of the object (rect, circle, poly, bezier1).
- * @param flag Flags that modify the operation. (fromcircle, frompoly, fromrect, preserve)
- * @returns The normalized coordinates.
- */
- imgmap.prototype._normCoords = function(coords, shape, flag) {
- //function level var declarations
- var i;//generic cycle counter
- var sx;//smallest x
- var sy;//smallest y
- var gx;//greatest x
- var gy;//greatest y
- var temp, le;
- //console.log('normcoords: ' + coords + ' - ' + shape + ' - ' + flag);
- coords = this.trim(coords);
- if (coords === '') {return '';}
- var oldcoords = coords;
- //replace some general junk
- coords = coords.replace(/(\d)(\D)+(\d)/g, "$1,$3");
- coords = coords.replace(/,\D+(\d)/g, ",$1");//cut leading junk
- coords = coords.replace(/,0+(\d)/g, ",$1");//cut leading zeros
- coords = coords.replace(/(\d)(\D)+,/g, "$1,");
- coords = coords.replace(/^\D+(\d)/g, "$1");//cut leading junk
- coords = coords.replace(/^0+(\d)/g, "$1");//cut leading zeros
- coords = coords.replace(/(\d)(\D)+$/g, "$1");//cut trailing junk
- //console.log('>'+coords + ' - ' + shape + ' - ' + flag);
- //now fix other issues
- var parts = coords.split(',');
- if (shape == 'rect') {
- if (flag == 'fromcircle') {
- var r = parts[2];
- parts[0] = parts[0] - r;
- parts[1] = parts[1] - r;
- parts[2] = parseInt(parts[0], 10) + 2 * r;
- parts[3] = parseInt(parts[1], 10) + 2 * r;
- }
- else if (flag == 'frompoly') {
- sx = parseInt(parts[0], 10); gx = parseInt(parts[0], 10);
- sy = parseInt(parts[1], 10); gy = parseInt(parts[1], 10);
- for (i=0, le = parts.length; i<le; i++) {
- if (i % 2 === 0 && parseInt(parts[i], 10) < sx) {
- sx = parseInt(parts[i], 10);}
- if (i % 2 === 1 && parseInt(parts[i], 10) < sy) {
- sy = parseInt(parts[i], 10);}
- if (i % 2 === 0 && parseInt(parts[i], 10) > gx) {
- gx = parseInt(parts[i], 10);}
- if (i % 2 === 1 && parseInt(parts[i], 10) > gy) {
- gy = parseInt(parts[i], 10);}
- //console.log(sx+","+sy+","+gx+","+gy);
- }
- parts[0] = sx; parts[1] = sy;
- parts[2] = gx; parts[3] = gy;
- }
- if (!(parseInt(parts[1], 10) >= 0)) {parts[1] = parts[0];}
- if (!(parseInt(parts[2], 10) >= 0)) {parts[2] = parseInt(parts[0], 10) + 10;}
- if (!(parseInt(parts[3], 10) >= 0)) {parts[3] = parseInt(parts[1], 10) + 10;}
- if (parseInt(parts[0], 10) > parseInt(parts[2], 10)) {
- temp = parts[0];
- parts[0] = parts[2];
- parts[2] = temp;
- }
- if (parseInt(parts[1], 10) > parseInt(parts[3], 10)) {
- temp = parts[1];
- parts[1] = parts[3];
- parts[3] = temp;
- }
- coords = parts[0]+","+parts[1]+","+parts[2]+","+parts[3];
- //console.log(coords);
- }
- else if (shape == 'circle') {
- if (flag == 'fromrect') {
- sx = parseInt(parts[0], 10); gx = parseInt(parts[2], 10);
- sy = parseInt(parts[1], 10); gy = parseInt(parts[3], 10);
- //use smaller side
- parts[2] = (gx - sx < gy - sy) ? gx - sx : gy - sy;
- parts[2] = Math.floor(parts[2] / 2);//radius
- parts[0] = sx + parts[2];
- parts[1] = sy + parts[2];
- }
- else if (flag == 'frompoly') {
- sx = parseInt(parts[0], 10); gx = parseInt(parts[0], 10);
- sy = parseInt(parts[1], 10); gy = parseInt(parts[1], 10);
- for (i=0, le = parts.length; i<le; i++) {
- if (i % 2 === 0 && parseInt(parts[i], 10) < sx) {
- sx = parseInt(parts[i], 10);}
- if (i % 2 === 1 && parseInt(parts[i], 10) < sy) {
- sy = parseInt(parts[i], 10);}
- if (i % 2 === 0 && parseInt(parts[i], 10) > gx) {
- gx = parseInt(parts[i], 10);}
- if (i % 2 === 1 && parseInt(parts[i], 10) > gy) {
- gy = parseInt(parts[i], 10);}
- //console.log(sx+","+sy+","+gx+","+gy);
- }
- //use smaller side
- parts[2] = (gx - sx < gy - sy) ? gx - sx : gy - sy;
- parts[2] = Math.floor(parts[2] / 2);//radius
- parts[0] = sx + parts[2];
- parts[1] = sy + parts[2];
- }
- if (!(parseInt(parts[1], 10) > 0)) {parts[1] = parts[0];}
- if (!(parseInt(parts[2], 10) > 0)) {parts[2] = 10;}
- coords = parts[0]+","+parts[1]+","+parts[2];
- }
- else if (shape == 'poly') {
- if (flag == 'fromrect') {
- parts[4] = parts[2];
- parts[5] = parts[3];
- parts[2] = parts[0];
- parts[6] = parts[4];
- parts[7] = parts[1];
- }
- else if (flag == 'fromcircle') {
- // @ url http://www.pixelwit.com/blog/2007/06/29/basic-circle-drawing-actionscript/
- var centerX = parseInt(parts[0], 10);
- var centerY = parseInt(parts[1], 10);
- var radius = parseInt(parts[2], 10);
- var j = 0;
- parts[j++] = centerX + radius;
- parts[j++] = centerY;
- var sides = 60;//constant = sides the fake circle will have
- for (i=0; i<=sides; i++) {
- var pointRatio = i/sides;
- var xSteps = Math.cos(pointRatio*2*Math.PI);
- var ySteps = Math.sin(pointRatio*2*Math.PI);
- var pointX = centerX + xSteps * radius;
- var pointY = centerY + ySteps * radius;
- parts[j++] = Math.round(pointX);
- parts[j++] = Math.round(pointY);
- }
- //console.log(parts);
- }
- coords = parts.join(',');
- }
- else if (shape == 'bezier1') {
- coords = parts.join(',');
- }
- if (flag == 'preserve' && oldcoords != coords) {
- //return original and throw error
- //throw "invalid coords";
- return oldcoords;
- }
- return coords;
- };
- /**
- * Sets the coordinates according to the given HTML map code or DOM object.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-07 11:47:16
- * @param map DOM object or string of a map you want to apply.
- * @return True on success
- */
- imgmap.prototype.setMapHTML = function(map) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- this.fireEvent('onSetMap', map);
- //this.log(map);
- //remove all areas
- this.removeAllAreas();
- //console.log(this.areas);
- var oMap;
- if (typeof map == 'string') {
- var oHolder = document.createElement('DIV');
- oHolder.innerHTML = map;
- oMap = oHolder.firstChild;
- }
- else if (typeof map == 'object') {
- oMap = map;
- }
- if (!oMap || oMap.nodeName.toLowerCase() !== 'map') {return false;}
- this.mapname = oMap.name;
- this.mapid = oMap.id;
- var newareas = oMap.getElementsByTagName('area');
- var shape, coords, href, alt, title, target, id;
- for (var i=0, le = newareas.length; i<le; i++) {
- shape = coords = href = alt = title = target = '';
- id = this.addNewArea();//btw id == this.currentid, just this form is a bit clearer
- shape = this._normShape(newareas[i].getAttribute('shape', 2));
- this.initArea(id, shape);
- if (newareas[i].getAttribute('coords', 2)) {
- //normalize coords
- coords = this._normCoords(newareas[i].getAttribute('coords', 2), shape);
- this.areas[id].lastInput = coords;
- //for area this one will be set in recalculate
- }
- href = newareas[i].getAttribute('href', 2);
- // FCKeditor stored url to prevent mangling from the browser.
- var sSavedUrl = newareas[i].getAttribute( '_fcksavedurl' );
- if (sSavedUrl) {
- href = sSavedUrl;
- }
- if (href) {
- this.areas[id].ahref = href;
- }
- alt = newareas[i].getAttribute('alt');
- if (alt) {
- this.areas[id].aalt = alt;
- }
- title = newareas[i].getAttribute('title');
- if (!title) {title = alt;}
- if (title) {
- this.areas[id].atitle = title;
- }
- target = newareas[i].getAttribute('target');
- if (target) {target = target.toLowerCase();}
- // if (target == '') target = '_self';
- this.areas[id].atarget = target;
- this._recalculate(id, coords);//contains repaint
- this.relaxArea(id);
- this.fireEvent('onAreaChanged', this.areas[id]);
- }//end for areas
- this.fireEvent('onHtmlChanged', this.getMapHTML());
- return true;
- };
- /**
- * Preview image with imagemap applied.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-06 14:51:01
- * @url http://www.quirksmode.org/bugreports/archives/2005/03/Usemap_attribute_wrongly_case_sensitive.html
- * @return False on error, 0 when switched to edit mode, 1 when switched to preview mode
- */
- imgmap.prototype.togglePreview = function() {
- var i, le;//generic cycle counter
- if (!this.pic) {return false;}//exit if pic is undefined
- //dynamically create preview container
- if (!this.preview) {
- this.preview = document.createElement('DIV');
- this.preview.style.display = 'none';
- this.pic_container.appendChild(this.preview);
- }
- if (this.viewmode === 0) {
- //hide canvas elements and labels
- for (i = 0, le = this.areas.length; i < le; i++) {
- if (this.areas[i]) {
- this.areas[i].style.display = 'none';
- if (this.areas[i].label) {this.areas[i].label.style.display = 'none';}
- }
- }
- //activate image map
- this.preview.innerHTML = this.getMapHTML('noscale');
- this.pic.setAttribute('border', '0', 0);
- this.pic.setAttribute('usemap', '#' + this.mapname, 0);
- this.pic.style.cursor = 'auto';
- this.viewmode = 1;
- this.statusMessage(this.strings.PREVIEW_MODE);
- }
- else {
- //show canvas elements
- for (i = 0, le = this.areas.length; i < le; i++) {
- if (this.areas[i]) {
- this.areas[i].style.display = '';
- if (this.areas[i].label && this.config.label) {this.areas[i].label.style.display = '';}
- }
- }
- //clear image map
- this.preview.innerHTML = '';
- this.pic.style.cursor = this.config.cursor_default;
- this.pic.removeAttribute('usemap', 0);
- this.viewmode = 0;
- this.statusMessage(this.strings.DESIGN_MODE);
- this.is_drawing = 0;
- }
- this.fireEvent('onModeChanged', this.viewmode);
- return this.viewmode;
- };
- /**
- * Adds a new area. It will later become a canvas.
- * GUI should use the onAddArea callback to act accordingly.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-06 16:49:25
- * @see #initArea
- */
- imgmap.prototype.addNewArea = function() {
- if (this.viewmode === 1) {return;}//exit if preview mode
- var lastarea = this._getLastArea();
- var id = (lastarea) ? lastarea.aid + 1 : 0;
- //alert(id);
- //insert new possibly? unknown area (will be initialized at mousedown)
- this.areas[id] = document.createElement('DIV');
- this.areas[id].id = this.mapname + 'area' + id;
- this.areas[id].aid = id;
- this.areas[id].shape = "undefined";
- this.currentid = id;
- this.fireEvent('onAddArea', id);
- return id;
- };
- /**
- * Initialize a new area.
- * Create the canvas, initialize it.
- * Reset area parameters.
- * @param id The id of the area (already existing with undefined shape)
- * @param shape The shape the area will have (rect, circle, poly, bezier1)
- */
- imgmap.prototype.initArea = function(id, shape) {
- if (!this.areas[id]) {return false;}//if all was erased, return
- //remove preinited dummy div or already placed canvas
- if (this.areas[id].parentNode) {this.areas[id].parentNode.removeChild(this.areas[id]);}
- if (this.areas[id].label) {this.areas[id].label.parentNode.removeChild(this.areas[id].label);}
- this.areas[id] = null;
- //create CANVAS node
- this.areas[id] = document.createElement('CANVAS');
- this.pic_container.appendChild(this.areas[id]);
- this.pic_container.style.position = 'relative';
- //alert('init' + typeof G_vmlCanvasManager);
- if (typeof G_vmlCanvasManager != "undefined") {
- //override CANVAS with VML object
- this.areas[id] = G_vmlCanvasManager.initElement(this.areas[id]);
- //this.areas[id] = this.pic.parentNode.lastChild;
- }
- this.areas[id].id = this.mapname + 'area' + id;
- this.areas[id].aid = id;
- this.areas[id].shape = shape;
- this.areas[id].ahref = '';
- this.areas[id].atitle = '';
- this.areas[id].aalt = '';
- this.areas[id].atarget = ''; // '_self';
- this.areas[id].style.position = 'absolute';
- this.areas[id].style.top = this.pic.offsetTop + 'px';
- this.areas[id].style.left = this.pic.offsetLeft + 'px';
- this._setopacity(this.areas[id], this.config.CL_DRAW_BG, this.config.draw_opacity);
- //hook event handlers
- this.areas[id].ondblclick = this.area_dblclick.bind(this);
- this.areas[id].onmousedown = this.area_mousedown.bind(this);
- this.areas[id].onmouseup = this.area_mouseup.bind(this);
- this.areas[id].onmousemove = this.area_mousemove.bind(this);
- this.areas[id].onmouseover = this.area_mouseover.bind(this);
- this.areas[id].onmouseout = this.area_mouseout.bind(this);
- //initialize memory object
- this.memory[id] = {};
- this.memory[id].downx = 0;
- this.memory[id].downy = 0;
- this.memory[id].left = 0;
- this.memory[id].top = 0;
- this.memory[id].width = 0;
- this.memory[id].height = 0;
- this.memory[id].xpoints = [];
- this.memory[id].ypoints = [];
- //create label node
- this.areas[id].label = document.createElement('DIV');
- this.pic_container.appendChild(this.areas[id].label);
- this.areas[id].label.className = this.config.label_class;
- this.assignCSS(this.areas[id].label, this.config.label_style);
- this.areas[id].label.style.position = 'absolute';
- };
- /**
- * Resets area border and opacity to a normal state after drawing.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 15-02-2007 22:07:28
- * @param id The id of the area.
- * @see #relaxAllAreas
- */
- imgmap.prototype.relaxArea = function(id) {
- if (!this.areas[id]) {return;}
- this.fireEvent('onRelaxArea', id);
- this._setBorder(id, 'NORM');
- this._setopacity(this.areas[id], this.config.CL_NORM_BG, this.config.norm_opacity);
- };
- /**
- * Resets area border and opacity of all areas.
- * Calls relaxArea on each of them.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 23-04-2007 23:31:09
- * @see #relaxArea
- */
- imgmap.prototype.relaxAllAreas = function() {
- for (var i=0, le = this.areas.length; i<le; i++) {
- if (this.areas[i]) {
- this.relaxArea(i);
- }
- }
- };
- /**
- * Set border of a given area according to style flag.
- * Possible values of style: NORM, HIGHLIGHT, DRAW.
- * Non-rectangle shapes wont get a border if config.bounding_box is false.
- * @date 26-12-2008 22:34:41
- * @param id The id of the area to set the border on.
- * @param style Coloring style (NORM, HIGHLIGHT, DRAW), see relevant colors in config.
- * @since 2.1
- */
- imgmap.prototype._setBorder = function(id, style) {
- if (this.areas[id].shape == 'rect' || this.config.bounding_box) {
- this.areas[id].style.borderWidth = '1px';
- this.areas[id].style.borderStyle = (style == 'DRAW' ? 'dotted' : 'solid');
- this.areas[id].style.borderColor = this.config['CL_' + style + '_' + (this.areas[id].shape == 'rect' ? 'SHAPE' : 'BOX')];
- }
- else {
- //clear border
- this.areas[id].style.border = '';
- }
- };
- /**
- * Set opacity of area to the given percentage, as well as set the background color.
- * If percentage contains a dash(-), the setting of the opacity will be gradual.
- * @param area The area object.
- * @param bgcolor New background color
- * @param pct Percentage of the opacity.
- */
- imgmap.prototype._setopacity = function(area, bgcolor, pct) {
- if (bgcolor) {area.style.backgroundColor = bgcolor;}
- if (pct && typeof pct == 'string' && pct.match(/^\d*\-\d+$/)) {
- //gradual fade
- var parts = pct.split('-');
- if (typeof parts[0] != 'undefined') {
- //set initial opacity
- parts[0] = parseInt(parts[0], 10);
- this._setopacity(area, bgcolor, parts[0]);
- }
- if (typeof parts[1] != 'undefined') {
- parts[1] = parseInt(parts[1], 10);
- var curr = this._getopacity(area);
- //this.log('curr: '+curr);
- var _this = this;
- var diff = Math.round(parts[1] - curr);
- if (diff > 5) {
- window.setTimeout(function () {_this._setopacity(area, null, '-'+parts[1]);}, 20);
- pct = 1*curr + 5;
- }
- else if (diff < -3) {
- window.setTimeout(function () {_this._setopacity(area, null, '-'+parts[1]);}, 20);
- pct = 1*curr - 3;
- }
- else {
- //final set
- pct = parts[1];
- }
- }
- }
- if (!isNaN(pct)) {
- pct = Math.round(parseInt(pct, 10));
- //this.log('set ('+area.aid+'): ' + pct, 1);
- area.style.opacity = pct / 100;
- area.style.filter = 'alpha(opacity='+pct+')';
- }
- };
- /**
- * Get the currently set opacity of a given area.
- * @author adam
- * @param area The area (canvas) you want to get opacity info from.
- * @return Opacity value in a range of 0-100.
- */
- imgmap.prototype._getopacity = function(area) {
- if (area.style.opacity <= 1) {
- return area.style.opacity * 100;
- }
- if (area.style.filter) {
- //alpha(opacity=NaN)
- return parseInt(area.style.filter.replace(/alpha\(opacity\=([^\)]*)\)/ig, "$1"), 10);
- }
- return 100;//default opacity
- };
- /**
- * Removes the area marked by id.
- * removeAllAreas will indicate a mass flag so that the output HTML will only be updated at
- * the end of the operation.
- * Callback will call the GUI code to remove GUI elements.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 11-02-2007 20:40:58
- * @param id The id of the area to remove.
- * @param mass Flag to indicate skipping the call of onHtmlChanged callback
- * @see #removeAllAreas
- */
- imgmap.prototype.removeArea = function(id, mass) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- if (id === null || typeof id == "undefined") {return;}//exit if no id given
- try {
- //remove area and label
- //explicitly set some values to null to avoid IE circular reference memleak
- this.areas[id].label.parentNode.removeChild(this.areas[id].label);
- this.areas[id].parentNode.removeChild(this.areas[id]);
- this.areas[id].label.className = null;
- //this.areas[id].label.style = null;
- //console.log(this.areas[id].label);
- this.areas[id].label = null;
- this.areas[id].onmouseover = null;
- this.areas[id].onmouseout = null;
- this.areas[id].onmouseup = null;
- this.areas[id].onmousedown = null;
- this.areas[id].onmousemove = null;
- // console.log(this.areas[id].label);
- }
- catch (err) {
- //alert('noparent');
- }
- this.areas[id] = null;
- this.fireEvent('onRemoveArea', id);
- //update grand html
- if (!mass) {this.fireEvent('onHtmlChanged', this.getMapHTML());}
- };
- /**
- * Removes all areas.
- * Will call removeArea on all areas.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-07 11:55:34
- * @see #removeArea
- */
- imgmap.prototype.removeAllAreas = function() {
- for (var i = 0, le = this.areas.length; i < le; i++) {
- if (this.areas[i]) {
- this.removeArea(i, true);
- }
- }
- //only call this at the end, use mass param above to avoid calling it in process
- this.fireEvent('onHtmlChanged', this.getMapHTML());
- };
- /**
- * Scales all areas.
- * Will store scale parameter in globalscale property.
- * This is needed to know how to draw new areas on an already scaled canvas.
- * @author adam
- * @date 02-11-2008 14:13:14
- * @param scale Scale factor (1-original, 0.5-half, 2-double, etc.)
- */
- imgmap.prototype.scaleAllAreas = function(scale) {
- var rscale = 1;//relative scale
- try {
- rscale = scale / this.globalscale;
- }
- catch (err) {
- this.log("Invalid (global)scale", 1);
- }
- //console.log('gscale: '+this.globalscale);
- //console.log('scale: '+scale);
- //console.log('rscale: '+rscale);
- this.globalscale = scale;
- for (var i = 0, le = this.areas.length; i < le; i++) {
- if (this.areas[i] && this.areas[i].shape != 'undefined') {
- this.scaleArea(i, rscale);
- }
- }
- };
- /**
- * Scales one area.
- * @author adam
- * @date 02-11-2008 14:13:14
- * @param rscale Relative scale factor (1-keep, 0.5-half, 2-double, etc.)
- */
- imgmap.prototype.scaleArea = function(id, rscale) {
- //set position and new dimensions
- this.areas[id].style.top = parseInt(this.areas[id].style.top, 10) * rscale + 'px';
- this.areas[id].style.left = parseInt(this.areas[id].style.left, 10) * rscale + 'px';
- this.setAreaSize(id, this.areas[id].width * rscale, this.areas[id].height * rscale);
- //handle polygon/bezier coordinates scaling
- if (this.areas[id].shape == 'poly' || this.areas[id].shape == 'bezier1') {
- for (var i=0, le = this.areas[id].xpoints.length; i<le; i++) {
- this.areas[id].xpoints[i]*= rscale;
- this.areas[id].ypoints[i]*= rscale;
- }
- }
- this._repaint(this.areas[id], this.config.CL_NORM_SHAPE);
- this._updatecoords(id);
- };
- /**
- * Put label in the top left corner according to label config.
- * By default it will contain the number of the area (area.aid)
- * @param id The id of the area to add label to.
- */
- imgmap.prototype._putlabel = function(id) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- if (!this.areas[id].label) {return;}//not yet inited
- try {
- if (!this.config.label) {
- this.areas[id].label.innerHTML = '';
- this.areas[id].label.style.display = 'none';
- }
- else {
- this.areas[id].label.style.display = '';
- var label = this.config.label;
- label = label.replace(/%n/g, String(id));
- label = label.replace(/%c/g, String(this.areas[id].lastInput));
- label = label.replace(/%h/g, String(this.areas[id].ahref));
- label = label.replace(/%a/g, String(this.areas[id].aalt));
- label = label.replace(/%t/g, String(this.areas[id].atitle));
- this.areas[id].label.innerHTML = label;
- }
- //align to the top left corner
- this.areas[id].label.style.top = this.areas[id].style.top;
- this.areas[id].label.style.left = this.areas[id].style.left;
- }
- catch (err) {
- this.log("Error putting label", 1);
- }
- };
- /**
- * Set area title and alt (for IE) according to the hint configuration.
- * This will show up in the usual yellow box when you hover over with the mouse.
- * @param id The id of the area to set hint at.
- */
- imgmap.prototype._puthint = function(id) {
- try {
- if (!this.config.hint) {
- this.areas[id].title = '';
- this.areas[id].alt = '';
- }
- else {
- var hint = this.config.hint;
- hint = hint.replace(/%n/g, String(id));
- hint = hint.replace(/%c/g, String(this.areas[id].lastInput));
- hint = hint.replace(/%h/g, String(this.areas[id].ahref));
- hint = hint.replace(/%a/g, String(this.areas[id].aalt));
- hint = hint.replace(/%t/g, String(this.areas[id].atitle));
- this.areas[id].title = hint;
- this.areas[id].alt = hint;
- }
- }
- catch (err) {
- this.log("Error putting hint", 1);
- }
- };
- /**
- * Will call repaint on all areas.
- * Useful when you change labeling or hint config on the GUI.
- * @see #_repaint
- */
- imgmap.prototype._repaintAll = function() {
- for (var i=0, le = this.areas.length; i<le; i++) {
- if (this.areas[i]) {
- this._repaint(this.areas[i], this.config.CL_NORM_SHAPE);
- }
- }
- };
- /**
- * Repaints the actual canvas content.
- * This is the only canvas drawing magic that is happening.
- * In fact rectangles will not have any canvas content, just a normal css border.
- * After repainting the canvas, it will call putlabel and puthint methods.
- * @param area The area object.
- * @param color Color of the line to draw on the canvas.
- * @param x Only used for polygons/beziers as the newest control point x.
- * @param y Only used for polygons/beziers as the newest control point y.
- */
- imgmap.prototype._repaint = function(area, color, x, y) {
- var ctx;//canvas context
- var width, height, left, top;//canvas properties
- var i, le;//loop counter
- if (area.shape == 'circle') {
- width = parseInt(area.style.width, 10);
- var radius = Math.floor(width/2) - 1;
- if (radius<0)
- radius=0;
- //get canvas context
- //alert(area.tagName);
- ctx = area.getContext("2d");
- //clear canvas
- ctx.clearRect(0, 0, width, width);
- //draw circle
- ctx.beginPath();
- ctx.strokeStyle = color;
- ctx.arc(radius, radius, radius, 0, Math.PI*2, 0);
- ctx.stroke();
- ctx.closePath();
- //draw center
- ctx.strokeStyle = this.config.CL_KNOB;
- ctx.strokeRect(radius, radius, 1, 1);
- //put label
- this._putlabel(area.aid);
- this._puthint(area.aid);
- }
- else if (area.shape == 'rect') {
- //put label
- this._putlabel(area.aid);
- this._puthint(area.aid);
- }
- else if (area.shape == 'poly') {
- width = parseInt(area.style.width, 10);
- height = parseInt(area.style.height, 10);
- left = parseInt(area.style.left, 10);
- top = parseInt(area.style.top, 10);
- if (area.xpoints) {
- //get canvas context
- ctx = area.getContext("2d");
- //clear canvas
- ctx.clearRect(0, 0, width, height);
- //draw polygon
- ctx.beginPath();
- ctx.strokeStyle = color;
- ctx.moveTo(area.xpoints[0] - left, area.ypoints[0] - top);
- for (i = 1, le = area.xpoints.length; i < le; i++) {
- ctx.lineTo(area.xpoints[i] - left , area.ypoints[i] - top);
- }
- if (this.is_drawing == this.DM_POLYGON_DRAW || this.is_drawing == this.DM_POLYGON_LASTDRAW) {
- //only draw to the current position if not moving
- ctx.lineTo(x - left - 5 , y - top - 5);
- }
- ctx.lineTo(area.xpoints[0] - left , area.ypoints[0] - top);
- ctx.stroke();
- ctx.closePath();
- }
- //put label
- this._putlabel(area.aid);
- this._puthint(area.aid);
- }
- else if (area.shape == 'bezier1') {
- width = parseInt(area.style.width, 10);
- height = parseInt(area.style.height, 10);
- left = parseInt(area.style.left, 10);
- top = parseInt(area.style.top, 10);
- if (area.xpoints) {
- //get canvas context
- ctx = area.getContext("2d");
- //clear canvas
- ctx.clearRect(0, 0, width, height);
- //draw bezier1 (every second point is control point)
- ctx.beginPath();
- ctx.strokeStyle = color;
- //move to the beginning position
- ctx.moveTo(area.xpoints[0] - left, area.ypoints[0] - top);
- //draw previous points - use every second point only
- for (i = 2, le = area.xpoints.length; i < le; i+= 2) {
- ctx.quadraticCurveTo(area.xpoints[i-1] - left, area.ypoints[i-1] - top, area.xpoints[i] - left, area.ypoints[i] - top);
- }
- if (this.is_drawing == this.DM_BEZIER_DRAW || this.is_drawing == this.DM_BEZIER_LASTDRAW) {
- //only draw to the current position if not moving
- if (area.xpoints.length % 2 === 0 && area.xpoints.length > 1) {
- //drawing point - draw a curve to it using the previous control point
- ctx.quadraticCurveTo(area.xpoints[area.xpoints.length - 1] - left - 5 , area.ypoints[area.ypoints.length - 1] - top - 5, x - left - 5 , y - top - 5);
- }
- else {
- //control point - simply draw a line to it
- ctx.lineTo(x - left - 5 , y - top - 5);
- }
- }
- //close area by drawing a line to the first point
- ctx.lineTo(area.xpoints[0] - left , area.ypoints[0] - top);
- ctx.stroke();
- ctx.closePath();
- }
- //put label
- this._putlabel(area.aid);
- this._puthint(area.aid);
- }
- };
- /**
- * Updates Area coordinates.
- * Called when needed, eg. on mousemove, mousedown.
- * Also updates html container value (thru hook).
- * Calls callback onAreaChanged and onHtmlChanged so that GUI can follow.
- * This is an important hook to your GUI.
- * Uses globalscale to scale real coordinates to area coordinates.
- * @date 2006.10.24. 22:39:27
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param id The id of the area.
- */
- imgmap.prototype._updatecoords = function(id) {
- var left = Math.round(parseInt(this.areas[id].style.left, 10) / this.globalscale);
- var top = Math.round(parseInt(this.areas[id].style.top, 10) / this.globalscale);
- var height = Math.round(parseInt(this.areas[id].style.height, 10) / this.globalscale);
- var width = Math.round(parseInt(this.areas[id].style.width, 10) / this.globalscale);
- var value = '';
- if (this.areas[id].shape == 'rect') {
- value = left + ',' + top + ',' + (left + width) + ',' + (top + height);
- this.areas[id].lastInput = value;
- }
- else if (this.areas[id].shape == 'circle') {
- var radius = Math.floor(width/2) - 1;
- value = (left + radius) + ',' + (top + radius) + ',' + radius;
- this.areas[id].lastInput = value;
- }
- else if (this.areas[id].shape == 'poly' || this.areas[id].shape == 'bezier1') {
- if (this.areas[id].xpoints) {
- for (var i=0, le = this.areas[id].xpoints.length; i<le; i++) {
- value+= Math.round(this.areas[id].xpoints[i] / this.globalscale) + ',' +
- Math.round(this.areas[id].ypoints[i] / this.globalscale) + ',';
- }
- value = value.substring(0, value.length - 1);
- }
- this.areas[id].lastInput = value;
- }
- this.fireEvent('onAreaChanged', this.areas[id]);
- this.fireEvent('onHtmlChanged', this.getMapHTML());
- };
- /**
- * Updates the visual representation of the area with the given id according
- * to the new coordinates that typically come from an input on the GUI.
- * Uses globalscale to scale area coordinates to real coordinates.
- * @date 2006.10.24. 22:46:55
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @param id The id of the area.
- * @param coords The new coords, they will be normalized.
- */
- imgmap.prototype._recalculate = function(id, coords) {
- try {
- if (coords) {
- coords = this._normCoords(coords, this.areas[id].shape, 'preserve');
- }
- else {
- coords = this.areas[id].lastInput || '' ;
- }
- var parts = coords.split(',');
- if (this.areas[id].shape == 'rect') {
- if (parts.length != 4 ||
- parseInt(parts[0], 10) > parseInt(parts[2], 10) ||
- parseInt(parts[1], 10) > parseInt(parts[3], 10)) {throw "invalid coords";}
- this.areas[id].style.left = this.globalscale * (this.pic.offsetLeft + parseInt(parts[0], 10)) + 'px';
- this.areas[id].style.top = this.globalscale * (this.pic.offsetTop + parseInt(parts[1], 10)) + 'px';
- this.setAreaSize(id, this.globalscale * (parts[2] - parts[0]), this.globalscale * (parts[3] - parts[1]));
- this._repaint(this.areas[id], this.config.CL_NORM_SHAPE);
- }
- else if (this.areas[id].shape == 'circle') {
- if (parts.length != 3 ||
- parseInt(parts[2], 10) < 0) {throw "invalid coords";}
- var width = 2 * (parts[2]);
- //alert(parts[2]);
- //alert(width);
- this.setAreaSize(id, this.globalscale * width, this.globalscale * width);
- this.areas[id].style.left = this.globalscale * (this.pic.offsetLeft + parseInt(parts[0], 10) - width/2) + 'px';
- this.areas[id].style.top = this.globalscale * (this.pic.offsetTop + parseInt(parts[1], 10) - width/2) + 'px';
- this._repaint(this.areas[id], this.config.CL_NORM_SHAPE);
- }
- else if (this.areas[id].shape == 'poly' || this.areas[id].shape == 'bezier1') {
- if (parts.length < 2) {throw "invalid coords";}
- this.areas[id].xpoints = [];
- this.areas[id].ypoints = [];
- for (var i=0, le = parts.length; i<le; i+=2) {
- this.areas[id].xpoints[this.areas[id].xpoints.length] = this.globalscale * (this.pic.offsetLeft + parseInt(parts[i], 10));
- this.areas[id].ypoints[this.areas[id].ypoints.length] = this.globalscale * (this.pic.offsetTop + parseInt(parts[i+1], 10));
- this._polygongrow(this.areas[id], this.globalscale * parts[i], this.globalscale * parts[i+1]);
- }
- this._polygonshrink(this.areas[id]);//includes repaint
- }
- }
- catch (err) {
- var msg = (err.message) ? err.message : 'error calculating coordinates';
- this.log(msg, 1);
- this.statusMessage(this.strings.ERR_INVALID_COORDS);
- if (this.areas[id].lastInput) {
- this.fireEvent('onAreaChanged', this.areas[id]);
- }
- this._repaint(this.areas[id], this.config.CL_NORM_SHAPE);
- return;
- }
- //on success update lastInput
- this.areas[id].lastInput = coords;
- };
- /**
- * Grow polygon area to be able to contain the given new coordinates.
- * @author adam
- * @param area The area to grow.
- * @param newx The new coordinate x.
- * @param newy The new coordinate y.
- * @see #_polygonshrink
- */
- imgmap.prototype._polygongrow = function(area, newx, newy) {
- //this.log('pgrow');
- var xdiff = newx - parseInt(area.style.left, 10);
- var ydiff = newy - parseInt(area.style.top , 10);
- var pad = 0;//padding on the edges
- var pad2 = 0;//twice the padding
- if (newx < parseInt(area.style.left, 10)) {
- area.style.left = (newx - pad) + 'px';
- this.setAreaSize(area.aid, parseInt(area.style.width, 10) + Math.abs(xdiff) + pad2, null);
- }
- else if (newx > parseInt(area.style.left, 10) + parseInt(area.style.width, 10)) {
- this.setAreaSize(area.aid, newx - parseInt(area.style.left, 10) + pad2, null);
- }
- if (newy < parseInt(area.style.top, 10)) {
- area.style.top = (newy - pad) + 'px';
- this.setAreaSize(area.aid, null, parseInt(area.style.height, 10) + Math.abs(ydiff) + pad2);
- }
- else if (newy > parseInt(area.style.top, 10) + parseInt(area.style.height, 10)) {
- this.setAreaSize(area.aid, null, newy - parseInt(area.style.top, 10) + pad2);
- }
- };
- /**
- * Shrink the polygon bounding area to the necessary size, by first reducing it
- * to the minimum, and then gradually growing it.
- * We need this because while we were drawing the polygon, it might have expanded
- * the canvas more than needed.
- * Will repaint the area.
- * @author adam
- * @param area The area to shrink.
- * @see #_polygongrow
- */
- imgmap.prototype._polygonshrink = function(area) {
- //this.log('pshrink');
- area.style.left = (area.xpoints[0]) + 'px';
- area.style.top = (area.ypoints[0]) + 'px';
- this.setAreaSize(area.aid, 0, 0);
- for (var i=0, le = area.xpoints.length; i<le; i++) {
- this._polygongrow(area, area.xpoints[i], area.ypoints[i]);
- }
- this._repaint(area, this.config.CL_NORM_SHAPE);
- };
- /**
- * EVENT HANDLER: Handles mousemove on the image.
- * This is the main drawing routine.
- * Depending on the current shape, will draw the rect/circle/poly to the new position.
- * @param e The event object.
- */
- imgmap.prototype.img_mousemove = function(e) {
- //function level var declarations
- var x;
- var y;
- var xdiff;
- var ydiff;
- var diff;
- if (this.viewmode === 1) {return;}//exit if preview mode
- //event.x is relative to parent element, but page.x is NOT
- //pos coordinates are the same absolute coords, offset coords are relative to parent
- var pos = this._getPos(this.pic);
- // 3.3.3 fix
- x = (this.isMSIE) ? (window.event.x - this.pic.offsetLeft) : (e.clientX - pos.x);
- y = (this.isMSIE) ? (window.event.y - this.pic.offsetTop) : (e.clientY - pos.y);
- x = x + this.pic_container.scrollLeft;
- y = y + this.pic_container.scrollTop;
- //exit if outside image
- if (x<0 || y<0 || x>this.pic.width || y>this.pic.height) {return;}
- //old dimensions that need to be updated in this function
- if (this.memory[this.currentid]) {
- var top = this.memory[this.currentid].top;
- var left = this.memory[this.currentid].left;
- var height = this.memory[this.currentid].height;
- var width = this.memory[this.currentid].width;
- }
- // Handle shift state for Safari
- // Safari doesn't generate keyboard events for modifiers: http://bugs.webkit.org/show_bug.cgi?id=11696
- if (this.isSafari) {
- if (e.shiftKey) {
- if (this.is_drawing == this.DM_RECTANGLE_DRAW) {
- this.is_drawing = this.DM_SQUARE_DRAW;
- this.statusMessage(this.strings.SQUARE2_DRAW);
- }
- }
- else {
- if (this.is_drawing == this.DM_SQUARE_DRAW && this.areas[this.currentid].shape == 'rect') {
- //not for circle!
- this.is_drawing = this.DM_RECTANGLE_DRAW;
- this.statusMessage(this.strings.RECTANGLE_DRAW);
- }
- }
- }
- if (this.is_drawing == this.DM_RECTANGLE_DRAW) {
- //rectangle mode
- this.fireEvent('onDrawArea', this.currentid);
- xdiff = x - this.memory[this.currentid].downx;
- ydiff = y - this.memory[this.currentid].downy;
- //alert(xdiff);
- this.setAreaSize(this.currentid, Math.abs(xdiff), Math.abs(ydiff));
- if (xdiff < 0) {
- this.areas[this.currentid].style.left = (x + 1) + 'px';
- }
- if (ydiff < 0) {
- this.areas[this.currentid].style.top = (y + 1) + 'px';
- }
- }
- else if (this.is_drawing == this.DM_SQUARE_DRAW) {
- //square mode - align to shorter side
- this.fireEvent('onDrawArea', this.currentid);
- xdiff = x - this.memory[this.currentid].downx;
- ydiff = y - this.memory[this.currentid].downy;
- if (Math.abs(xdiff) < Math.abs(ydiff)) {
- diff = Math.abs(parseInt(xdiff, 10));
- }
- else {
- diff = Math.abs(parseInt(ydiff, 10));
- }
- //alert(xdiff);
- this.setAreaSize(this.currentid, diff, diff);
- if (xdiff < 0) {
- this.areas[this.currentid].style.left = (this.memory[this.currentid].downx + diff*-1) + 'px';
- }
- if (ydiff < 0) {
- this.areas[this.currentid].style.top = (this.memory[this.currentid].downy + diff*-1 + 1) + 'px';
- }
- }
- else if (this.is_drawing == this.DM_POLYGON_DRAW || this.is_drawing == this.DM_BEZIER_DRAW) {
- //polygon or bezier mode
- this.fireEvent('onDrawArea', this.currentid);
- this._polygongrow(this.areas[this.currentid], x, y);
- }
- else if (this.is_drawing == this.DM_RECTANGLE_MOVE || this.is_drawing == this.DM_SQUARE_MOVE) {
- this.fireEvent('onMoveArea', this.currentid);
- x = x - this.memory[this.currentid].rdownx;
- y = y - this.memory[this.currentid].rdowny;
- if (x + width > this.pic.width || y + height > this.pic.height) {return;}
- if (x < 0 || y < 0) {return;}
- //this.log(x + ' - '+width+ '+'+this.memory[this.currentid].rdownx +'='+xdiff );
- this.areas[this.currentid].style.left = x + 1 + 'px';
- this.areas[this.currentid].style.top = y + 1 + 'px';
- }
- else if (this.is_drawing == this.DM_POLYGON_MOVE || this.is_drawing == this.DM_BEZIER_MOVE) {
- this.fireEvent('onMoveArea', this.currentid);
- x = x - this.memory[this.currentid].rdownx;
- y = y - this.memory[this.currentid].rdowny;
- if (x + width > this.pic.width || y + height > this.pic.height) {return;}
- if (x < 0 || y < 0) {return;}
- xdiff = x - left;
- ydiff = y - top;
- if (this.areas[this.currentid].xpoints) {
- for (var i=0, le = this.areas[this.currentid].xpoints.length; i<le; i++) {
- this.areas[this.currentid].xpoints[i] = this.memory[this.currentid].xpoints[i] + xdiff;
- this.areas[this.currentid].ypoints[i] = this.memory[this.currentid].ypoints[i] + ydiff;
- }
- }
- this.areas[this.currentid].style.left = x + 'px';
- this.areas[this.currentid].style.top = y + 'px';
- }
- else if (this.is_drawing == this.DM_SQUARE_RESIZE_LEFT) {
- this.fireEvent('onResizeArea', this.currentid);
- diff = x - left;
- //alert(diff);
- if ((width + (-1 * diff)) > 0) {
- //real resize left
- this.areas[this.currentid].style.left = x + 1 + 'px';
- this.areas[this.currentid].style.top = (top + (diff/2)) + 'px';
- this.setAreaSize(this.currentid, parseInt(width + (-1 * diff), 10), parseInt(height + (-1 * diff), 10));
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].left = x;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_SQUARE_RESIZE_RIGHT;
- }
- }
- else if (this.is_drawing == this.DM_SQUARE_RESIZE_RIGHT) {
- this.fireEvent('onResizeArea', this.currentid);
- diff = x - left - width;
- if ((width + (diff)) - 1 > 0) {
- //real resize right
- this.areas[this.currentid].style.top = (top + (-1* diff/2)) + 'px';
- this.setAreaSize(this.currentid, (width + (diff)) - 1, (height + (diff)));
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].left = x;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_SQUARE_RESIZE_LEFT;
- }
- }
- else if (this.is_drawing == this.DM_SQUARE_RESIZE_TOP) {
- this.fireEvent('onResizeArea', this.currentid);
- diff = y - top;
- if ((width + (-1 * diff)) > 0) {
- //real resize top
- this.areas[this.currentid].style.top = y + 1 + 'px';
- this.areas[this.currentid].style.left = (left + (diff/2)) + 'px';
- this.setAreaSize(this.currentid, (width + (-1 * diff)), (height + (-1 * diff)));
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].left = x;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_SQUARE_RESIZE_BOTTOM;
- }
- }
- else if (this.is_drawing == this.DM_SQUARE_RESIZE_BOTTOM) {
- this.fireEvent('onResizeArea', this.currentid);
- diff = y - top - height;
- if ((width + (diff)) - 1 > 0) {
- //real resize bottom
- this.areas[this.currentid].style.left = (left + (-1* diff/2)) + 'px';
- this.setAreaSize(this.currentid, (width + (diff)) - 1 , (height + (diff)) - 1);
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].left = x;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_SQUARE_RESIZE_TOP;
- }
- }
- else if (this.is_drawing == this.DM_RECTANGLE_RESIZE_LEFT) {
- this.fireEvent('onResizeArea', this.currentid);
- xdiff = x - left;
- if (width + (-1 * xdiff) > 0) {
- //real resize left
- this.areas[this.currentid].style.left = x + 1 + 'px';
- this.setAreaSize(this.currentid, width + (-1 * xdiff), null);
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].left = x;
- this.is_drawing = this.DM_RECTANGLE_RESIZE_RIGHT;
- }
- }
- else if (this.is_drawing == this.DM_RECTANGLE_RESIZE_RIGHT) {
- this.fireEvent('onResizeArea', this.currentid);
- xdiff = x - left - width;
- if ((width + (xdiff)) - 1 > 0) {
- //real resize right
- this.setAreaSize(this.currentid, (width + (xdiff)) - 1, null);
- }
- else {
- //jump to another state
- this.memory[this.currentid].width = 0;
- this.memory[this.currentid].left = x;
- this.is_drawing = this.DM_RECTANGLE_RESIZE_LEFT;
- }
- }
- else if (this.is_drawing == this.DM_RECTANGLE_RESIZE_TOP) {
- this.fireEvent('onResizeArea', this.currentid);
- ydiff = y - top;
- if ((height + (-1 * ydiff)) > 0) {
- //real resize top
- this.areas[this.currentid].style.top = y + 1 + 'px';
- this.setAreaSize(this.currentid, null, (height + (-1 * ydiff)));
- }
- else {
- //jump to another state
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_RECTANGLE_RESIZE_BOTTOM;
- }
- }
- else if (this.is_drawing == this.DM_RECTANGLE_RESIZE_BOTTOM) {
- this.fireEvent('onResizeArea', this.currentid);
- ydiff = y - top - height;
- if ((height + (ydiff)) - 1 > 0) {
- //real resize bottom
- this.setAreaSize(this.currentid, null, (height + (ydiff)) - 1);
- }
- else {
- //jump to another state
- this.memory[this.currentid].height = 0;
- this.memory[this.currentid].top = y;
- this.is_drawing = this.DM_RECTANGLE_RESIZE_TOP;
- }
- }
- //repaint canvas elements
- if (this.is_drawing) {
- this._repaint(this.areas[this.currentid], this.config.CL_DRAW_SHAPE, x, y);
- this._updatecoords(this.currentid);
- }
- };
- /**
- * EVENT HANDLER: Handles mouseup on the image.
- * Handles dragging and resizing.
- * @param e The event object.
- */
- imgmap.prototype.img_mouseup = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- //console.log('img_mouseup');
- //if (!this.props[this.currentid]) return;
- var pos = this._getPos(this.pic);
- // 3.3.3 fix
- var x = (this.isMSIE) ? (window.event.x - this.pic.offsetLeft) : (e.clientX - pos.x);
- var y = (this.isMSIE) ? (window.event.y - this.pic.offsetTop) : (e.clientY - pos.y);
- x = x + this.pic_container.scrollLeft;
- y = y + this.pic_container.scrollTop;
- //for everything that is move or resize
- if (this.is_drawing != this.DM_RECTANGLE_DRAW &&
- this.is_drawing != this.DM_SQUARE_DRAW &&
- this.is_drawing != this.DM_POLYGON_DRAW &&
- this.is_drawing != this.DM_POLYGON_LASTDRAW &&
- this.is_drawing != this.DM_BEZIER_DRAW &&
- this.is_drawing != this.DM_BEZIER_LASTDRAW) {
- //end dragging
- this.draggedId = null;
- //finish state
- this.is_drawing = 0;
- this.statusMessage(this.strings.READY);
- this.relaxArea(this.currentid);
- if (this.areas[this.currentid] == this._getLastArea()) {
- //if (this.config.mode != "editor2") this.addNewArea();
- return;
- }
- this.memory[this.currentid].downx = x;
- this.memory[this.currentid].downy = y;
- }
- };
- /**
- * EVENT HANDLER: Handles mousedown on the image.
- * Handles beggining or end of draw, or polygon/bezier point set.
- * @param e The event object.
- */
- imgmap.prototype.img_mousedown = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- if (!this.areas[this.currentid] && this.config.mode != "editor2") {return;}
- //console.log('img_mousedown');
- var pos = this._getPos(this.pic);
- // 3.3.3 fix
- var x = (this.isMSIE) ? (window.event.x - this.pic.offsetLeft) : (e.clientX - pos.x);
- var y = (this.isMSIE) ? (window.event.y - this.pic.offsetTop) : (e.clientY - pos.y);
- x = x + this.pic_container.scrollLeft;
- y = y + this.pic_container.scrollTop;
- // Handle the Shift state
- if (!e) {
- e = window.event;
- }
- if (e.shiftKey) {
- if (this.is_drawing == this.DM_POLYGON_DRAW) {
- this.is_drawing = this.DM_POLYGON_LASTDRAW;
- }
- else if (this.is_drawing == this.DM_BEZIER_DRAW) {
- this.is_drawing = this.DM_BEZIER_LASTDRAW;
- }
- }
- //console.log(this.is_drawing);
- //this.statusMessage(x + ' - ' + y + ': ' + this.props[this.currentid].getElementsByTagName('select')[0].value);
- if (this.is_drawing == this.DM_POLYGON_DRAW || this.is_drawing == this.DM_BEZIER_DRAW) {
- //its not finish state yet
- this.areas[this.currentid].xpoints[this.areas[this.currentid].xpoints.length] = x - 5;
- this.areas[this.currentid].ypoints[this.areas[this.currentid].ypoints.length] = y - 5;
- this.memory[this.currentid].downx = x;
- this.memory[this.currentid].downy = y;
- return;
- }
- else if (this.is_drawing && this.is_drawing != this.DM_POLYGON_DRAW && this.is_drawing != this.DM_BEZIER_DRAW) {
- //finish any other state
- if (this.is_drawing == this.DM_POLYGON_LASTDRAW || this.is_drawing == this.DM_BEZIER_LASTDRAW) {
- //add last controlpoint and update coords
- this.areas[this.currentid].xpoints[this.areas[this.currentid].xpoints.length] = x - 5;
- this.areas[this.currentid].ypoints[this.areas[this.currentid].ypoints.length] = y - 5;
- this._updatecoords(this.currentid);
- this.is_drawing = 0;
- this._polygonshrink(this.areas[this.currentid]);
- }
- this.is_drawing = 0;
- this.statusMessage(this.strings.READY);
- this.relaxArea(this.currentid);
- if (this.areas[this.currentid] == this._getLastArea()) {
- //editor mode adds next area automatically
- if (this.config.mode != "editor2") {this.addNewArea();}
- return;
- }
- return;
- }
- if (this.config.mode == "editor2") {
- if (!this.nextShape) {return;}
- this.addNewArea();
- //console.log("init: " + this.nextShape);
- this.initArea(this.currentid, this.nextShape);
- }
- else if (this.areas[this.currentid].shape == 'undefined' || this.areas[this.currentid].shape == 'poly') {
- //var shape = (this.props[this.currentid]) ? this.props[this.currentid].getElementsByTagName('select')[0].value : this.nextShape;
- var shape = this.nextShape;
- if (!shape) {shape = 'rect';}
- //console.log("init: " + shape);
- this.initArea(this.currentid, shape);
- }
- if (this.areas[this.currentid].shape == 'poly') {
- this.is_drawing = this.DM_POLYGON_DRAW;
- this.statusMessage(this.strings.POLYGON_DRAW);
- this.areas[this.currentid].style.left = x + 'px';
- this.areas[this.currentid].style.top = y + 'px';
- this.areas[this.currentid].style.width = 0;
- this.areas[this.currentid].style.height = 0;
- this.areas[this.currentid].xpoints = [];
- this.areas[this.currentid].ypoints = [];
- this.areas[this.currentid].xpoints[0] = x;
- this.areas[this.currentid].ypoints[0] = y;
- }
- else if (this.areas[this.currentid].shape == 'bezier1') {
- this.is_drawing = this.DM_BEZIER_DRAW;
- this.statusMessage(this.strings.BEZIER_DRAW);
- this.areas[this.currentid].style.left = x + 'px';
- this.areas[this.currentid].style.top = y + 'px';
- this.areas[this.currentid].style.width = 0;
- this.areas[this.currentid].style.height = 0;
- this.areas[this.currentid].xpoints = [];
- this.areas[this.currentid].ypoints = [];
- this.areas[this.currentid].xpoints[0] = x;
- this.areas[this.currentid].ypoints[0] = y;
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_DRAW;
- this.statusMessage(this.strings.RECTANGLE_DRAW);
- this.areas[this.currentid].style.left = x + 'px';
- this.areas[this.currentid].style.top = y + 'px';
- this.areas[this.currentid].style.width = 0;
- this.areas[this.currentid].style.height = 0;
- }
- else if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_DRAW;
- this.statusMessage(this.strings.SQUARE_DRAW);
- this.areas[this.currentid].style.left = x + 'px';
- this.areas[this.currentid].style.top = y + 'px';
- this.areas[this.currentid].style.width = 0;
- this.areas[this.currentid].style.height = 0;
- }
- this._setBorder(this.currentid, 'DRAW');
- this.memory[this.currentid].downx = x;
- this.memory[this.currentid].downy = y;
- };
- /**
- * Highlights a given area.
- * Sets opacity and repaints.
- * @date 2007.12.28. 18:23:00
- * @param id The id of the area to blur.
- * @param flag Modifier, possible values: grad - for gradual fade in
- */
- imgmap.prototype.highlightArea = function(id, flag) {
- if (this.is_drawing) {return;}//exit if in drawing state
- if (this.areas[id] && this.areas[id].shape != 'undefined') {
- //area exists - highlight it
- this.fireEvent('onFocusArea', this.areas[id]);
- this._setBorder(id, 'HIGHLIGHT');
- var opacity = this.config.highlight_opacity;
- if (flag == 'grad') {
- //apply gradient opacity
- opacity = '-' + opacity;
- }
- this._setopacity(this.areas[id], this.config.CL_HIGHLIGHT_BG, opacity);
- this._repaint(this.areas[id], this.config.CL_HIGHLIGHT_SHAPE);
- }
- };
- /**
- * Blurs a given area.
- * Sets opacity and repaints.
- * @date 2007.12.28. 18:23:26
- * @param id The id of the area to blur.
- * @param flag Modifier, possible values: grad - for gradual fade out
- */
- imgmap.prototype.blurArea = function(id, flag) {
- if (this.is_drawing) {return;}//exit if in drawing state
- if (this.areas[id] && this.areas[id].shape != 'undefined') {
- //area exists - fade it back
- this.fireEvent('onBlurArea', this.areas[id]);
- this._setBorder(id, 'NORM');
- var opacity = this.config.norm_opacity;
- if (flag == 'grad') {
- //apply gradient opacity
- opacity = '-' + opacity;
- }
- this._setopacity(this.areas[id], this.config.CL_NORM_BG, opacity);
- this._repaint(this.areas[id], this.config.CL_NORM_SHAPE);
- }
- };
- /**
- * EVENT HANDLER: Handles event of mousemove on imgmap areas.
- * - changes cursor depending where we are inside the area (buggy in opera)
- * - handles area resize
- * - handles area move
- * @url http://evolt.org/article/Mission_Impossible_mouse_position/17/23335/index.html
- * @url http://my.opera.com/community/forums/topic.dml?id=239498&t=1217158015&page=1
- * @author adam
- * @param e The event object.
- */
- imgmap.prototype.area_mousemove = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- if (!this.is_drawing) {
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- //opera fix - adam - 04-12-2007 23:14:05
- if (this.isOpera) {
- e.layerX = e.offsetX;
- e.layerY = e.offsetY;
- }
- var xdiff = (this.isMSIE) ? (window.event.offsetX) : (e.layerX);
- var ydiff = (this.isMSIE) ? (window.event.offsetY) : (e.layerY);
- //this.log(obj.aid + ' : ' + xdiff + ',' + ydiff);
- var resizable = (obj.shape == 'rect' || obj.shape == 'circle');
- if (resizable && xdiff < 6 && ydiff > 6) {
- //move left
- obj.style.cursor = 'w-resize';
- }
- else if (resizable && xdiff > parseInt(obj.style.width, 10) - 6 && ydiff > 6) {
- //move right
- obj.style.cursor = 'e-resize';
- }
- else if (resizable && xdiff > 6 && ydiff < 6) {
- //move top
- obj.style.cursor = 'n-resize';
- }
- else if (resizable && ydiff > parseInt(obj.style.height, 10) - 6 && xdiff > 6) {
- //move bottom
- obj.style.cursor = 's-resize';
- }
- else {
- //move all
- obj.style.cursor = 'move';
- }
- if (obj.aid != this.draggedId) {
- //not dragged or different
- if (obj.style.cursor == 'move') {obj.style.cursor = 'default';}
- return;
- }
- //moved here from mousedown
- if (xdiff < 6 && ydiff > 6) {
- //move left
- if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_RESIZE_LEFT;
- this.statusMessage(this.strings.SQUARE_RESIZE_LEFT);
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_RESIZE_LEFT;
- this.statusMessage(this.strings.RECTANGLE_RESIZE_LEFT);
- }
- }
- else if (xdiff > parseInt(this.areas[this.currentid].style.width, 10) - 6 && ydiff > 6) {
- //move right
- if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_RESIZE_RIGHT;
- this.statusMessage(this.strings.SQUARE_RESIZE_RIGHT);
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_RESIZE_RIGHT;
- this.statusMessage(this.strings.RECTANGLE_RESIZE_RIGHT);
- }
- }
- else if (xdiff > 6 && ydiff < 6) {
- //move top
- if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_RESIZE_TOP;
- this.statusMessage(this.strings.SQUARE_RESIZE_TOP);
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_RESIZE_TOP;
- this.statusMessage(this.strings.RECTANGLE_RESIZE_TOP);
- }
- }
- else if (ydiff > parseInt(this.areas[this.currentid].style.height, 10) - 6 && xdiff > 6) {
- //move bottom
- if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_RESIZE_BOTTOM;
- this.statusMessage(this.strings.SQUARE_RESIZE_BOTTOM);
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_RESIZE_BOTTOM;
- this.statusMessage(this.strings.RECTANGLE_RESIZE_BOTTOM);
- }
- }
- else/*if (xdiff < 10 && ydiff < 10 ) */{
- //move all
- if (this.areas[this.currentid].shape == 'circle') {
- this.is_drawing = this.DM_SQUARE_MOVE;
- this.statusMessage(this.strings.SQUARE_MOVE);
- this.memory[this.currentid].rdownx = xdiff;
- this.memory[this.currentid].rdowny = ydiff;
- }
- else if (this.areas[this.currentid].shape == 'rect') {
- this.is_drawing = this.DM_RECTANGLE_MOVE;
- this.statusMessage(this.strings.RECTANGLE_MOVE);
- this.memory[this.currentid].rdownx = xdiff;
- this.memory[this.currentid].rdowny = ydiff;
- }
- else if (this.areas[this.currentid].shape == 'poly' || this.areas[this.currentid].shape == 'bezier1') {
- if (this.areas[this.currentid].xpoints) {
- for (var i=0, le = this.areas[this.currentid].xpoints.length; i<le; i++) {
- this.memory[this.currentid].xpoints[i] = this.areas[this.currentid].xpoints[i];
- this.memory[this.currentid].ypoints[i] = this.areas[this.currentid].ypoints[i];
- }
- }
- if (this.areas[this.currentid].shape == 'poly') {
- this.is_drawing = this.DM_POLYGON_MOVE;
- this.statusMessage(this.strings.POLYGON_MOVE);
- }
- else if (this.areas[this.currentid].shape == 'bezier1') {
- this.is_drawing = this.DM_BEZIER_MOVE;
- this.statusMessage(this.strings.BEZIER_MOVE);
- }
- this.memory[this.currentid].rdownx = xdiff;
- this.memory[this.currentid].rdowny = ydiff;
- }
- }
- //common memory settings (preparing to move or resize)
- this.memory[this.currentid].width = parseInt(this.areas[this.currentid].style.width, 10);
- this.memory[this.currentid].height = parseInt(this.areas[this.currentid].style.height, 10);
- this.memory[this.currentid].top = parseInt(this.areas[this.currentid].style.top, 10);
- this.memory[this.currentid].left = parseInt(this.areas[this.currentid].style.left, 10);
- this._setBorder(this.currentid, 'DRAW');
- this._setopacity(this.areas[this.currentid], this.config.CL_DRAW_BG, this.config.draw_opacity);
- }
- else {
- //if drawing and not ie, have to propagate to image event
- this.img_mousemove(e);
- }
- };
- /**
- * EVENT HANDLER: Handles event of mouseup on imgmap areas.
- * Basically clears draggedId.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.area_mouseup = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- //console.log('area_mouseup');
- if (!this.is_drawing) {
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- if (this.areas[this.currentid] != obj) {
- //trying to draw on a different canvas,switch to this one
- if (typeof obj.aid == 'undefined') {
- this.log('Cannot identify target area', 1);
- return;
- }
- //this.form_selectRow(obj.aid, true);
- //this.currentid = obj.aid;
- }
- this.draggedId = null;
- }
- else {
- //if drawing and not ie, have to propagate to image event
- //console.log('propup');
- this.img_mouseup(e);
- }
- };
- /**
- * EVENT HANDLER: Handles event of mouseover on imgmap areas.
- * Calls gradual highlight on the given area.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.area_mouseover = function(e) {
- if (this.viewmode === 1 && this.config.mode !== 'highlighter_spawn') {return;}//exit if preview mode
- if (!this.is_drawing) {
- //this.log('area_mouseover');
- //identify source object
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- /*
- //switch to hovered area
- if (this.areas[this.currentid] != obj) {
- //trying to draw on a different canvas, switch to this one
- if (typeof obj.aid == 'undefined') {
- this.log('Cannot identify target area', 1);
- return;
- }
- this.form_selectRow(obj.aid, true);
- this.currentid = obj.aid;
- }
- */
- this.highlightArea(obj.aid, 'grad');
- }
- };
- /**
- * EVENT HANDLER: Handles event of mouseout on imgmap areas.
- * Calls gradient blur on the given area.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.area_mouseout = function(e) {
- if (this.viewmode === 1 && this.config.mode !== 'highlighter_spawn') {return;}//exit if preview mode
- if (!this.is_drawing) {
- //this.log('area_mouseout');
- //identify source object
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- this.blurArea(obj.aid, 'grad');
- }
- };
- /**
- * EVENT HANDLER: Handles event of double click on imgmap areas.
- * Basically only fires the custom callback.
- * @author Colin Bell
- * @param e The event object
- */
- imgmap.prototype.area_dblclick = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- //console.log('area_dblclick');
- if (!this.is_drawing) {
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- if (this.areas[this.currentid] != obj) {
- //trying to draw on a different canvas, switch to this one
- if (typeof obj.aid == 'undefined') {
- this.log('Cannot identify target area', 1);
- return;
- }
- this.currentid = obj.aid;
- }
- this.fireEvent('onDblClickArea', this.areas[this.currentid]);
- //stop event propagation to document level
- if (this.isMSIE) {
- window.event.cancelBubble = true;
- }
- else {
- e.stopPropagation();
- }
- }
- };
- /**
- * EVENT HANDLER: Handles event of mousedown on imgmap areas.
- * Sets the variables draggedid, selectedid and currentid to the given area.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.area_mousedown = function(e) {
- if (this.viewmode === 1 && this.config.mode !== 'highlighter_spawn') {return;}//exit if preview mode
- //console.log('area_mousedown');
- if (!this.is_drawing) {
- var obj = (this.isMSIE) ? window.event.srcElement : e.currentTarget;
- if (obj.tagName == 'DIV') {
- //do this because of label
- obj = obj.parentNode;
- }
- if (obj.tagName == 'image' || obj.tagName == 'group' ||
- obj.tagName == 'shape' || obj.tagName == 'stroke') {
- //do this because of excanvas
- obj = obj.parentNode.parentNode;
- }
- if (this.areas[this.currentid] != obj) {
- //trying to draw on a different canvas, switch to this one
- if (typeof obj.aid == 'undefined') {
- this.log('Cannot identify target area', 1);
- return;
- }
- this.currentid = obj.aid;
- }
- //this.log('selected = '+this.currentid);
- this.draggedId = this.currentid;
- this.selectedId = this.currentid;
- this.fireEvent('onSelectArea', this.areas[this.currentid]);
- //stop event propagation to document level
- if (this.isMSIE) {
- window.event.cancelBubble = true;
- }
- else {
- e.stopPropagation();
- }
- }
- else {
- //if drawing and not ie, have to propagate to image event
- //console.log('propdown');
- this.img_mousedown(e);
- }
- };
- /**
- * EVENT HANDLER: Handles event 'keydown' on document.
- * Handles SHIFT hold while drawing.
- * Note: Safari doesn't generate keyboard events for modifiers:
- * @url http://bugs.webkit.org/show_bug.cgi?id=11696
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.doc_keydown = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- var key = (this.isMSIE) ? event.keyCode : e.keyCode;
- //console.log(key);
- if (key == 46) {
- //delete key pressed
- if (this.selectedId !== null && !this.is_drawing) {this.removeArea(this.selectedId);}
- }
- else if (key == 16) {
- //shift key pressed
- if (this.is_drawing == this.DM_RECTANGLE_DRAW) {
- this.is_drawing = this.DM_SQUARE_DRAW;
- this.statusMessage(this.strings.SQUARE2_DRAW);
- }
- }
- };
- /**
- * EVENT HANDLER: Handles event 'keyup' on document.
- * Handles SHIFT release while drawing.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.doc_keyup = function(e) {
- var key = (this.isMSIE) ? event.keyCode : e.keyCode;
- //alert(key);
- if (key == 16) {
- //shift key released
- if (this.is_drawing == this.DM_SQUARE_DRAW && this.areas[this.currentid].shape == 'rect') {
- //not for circle!
- this.is_drawing = this.DM_RECTANGLE_DRAW;
- this.statusMessage(this.strings.RECTANGLE_DRAW);
- }
- }
- };
- /**
- * EVENT HANDLER: Handles event 'mousedown' on document.
- * @author adam
- * @param e The event object
- */
- imgmap.prototype.doc_mousedown = function(e) {
- if (this.viewmode === 1) {return;}//exit if preview mode
- if (!this.is_drawing) {
- this.selectedId = null;
- }
- };
- /**
- * Get the real position of the element.
- * Deal with browser differences when trying to get the position of an area.
- * @param element The element you want the position of.
- * @return An object with x and y members.
- */
- imgmap.prototype._getPos = function(element) {
- var xpos = 0;
- var ypos = 0;
- if (element) {
- var elementOffsetParent = element.offsetParent;
- // If the element has an offset parent
- if (elementOffsetParent) {
- // While there is an offset parent
- while ((elementOffsetParent = element.offsetParent)) {
- //offset might give negative in opera when the image is scrolled
- if (element.offsetLeft > 0) {xpos += element.offsetLeft;}
- if (element.offsetTop > 0) {ypos += element.offsetTop;}
- element = elementOffsetParent;
- }
- // handle positioned element in Chrome
- if (element.offsetLeft > 0) {xpos += element.offsetLeft;}
- if (element.offsetTop > 0) {ypos += element.offsetTop;}
- }
- else {
- xpos = element.offsetLeft;
- ypos = element.offsetTop;
- }
- }
- return {x: xpos, y: ypos};
- };
- /**
- * Gets the last (visible and editable) area.
- * @author Adam Maschek (adam.maschek(at)gmail.com)
- * @date 2006-06-15 16:34:51
- * @returns The last area object or null.
- */
- imgmap.prototype._getLastArea = function() {
- for (var i = this.areas.length-1; i>=0; i--) {
- if (this.areas[i]) {
- return this.areas[i];
- }
- }
- return null;
- };
- /**
- * Parses cssText to single style declarations.
- * @author adam
- * @date 25-09-2007 18:19:51
- * @param obj The DOM object to apply styles on.
- * @param cssText The css declarations to apply.
- */
- imgmap.prototype.assignCSS = function(obj, cssText) {
- var parts = cssText.split(';');
- for (var i = 0; i < parts.length; i++) {
- var p = parts[i].split(':');
- //we need to camelcase by - signs
- var pp = this.trim(p[0]).split('-');
- var prop = pp[0];
- for (var j = 1; j < pp.length; j++) {
- //replace first letters to uppercase
- prop+= pp[j].replace(/^\w/, pp[j].substring(0,1).toUpperCase());
- }
- obj.style[this.trim(prop)] = this.trim(p[1]);
- }
- };
- /**
- * To fire callback hooks on custom events, passing them the object of the event.
- * @author adam
- * @date 13-10-2007 15:24:49
- * @param evt The type of event
- * @param obj The object of the event. (can be an id, a string, an object, whatever is most relevant)
- */
- imgmap.prototype.fireEvent = function(evt, obj) {
- //this.log("Firing event: " + evt);
- if (typeof this.config.custom_callbacks[evt] == 'function') {
- return this.config.custom_callbacks[evt](obj);
- }
- };
- /**
- * To set area dimensions.
- * This is needed to achieve the same result in all browsers.
- * @author adam
- * @date 10-12-2007 22:29:41
- * @param id The id of the area (canvas) to resize.
- * @param w The desired width in pixels.
- * @param h The desired height in pixels.
- */
- imgmap.prototype.setAreaSize = function(id, w, h) {
- if (id === null) {id = this.currentid;}
- if (w !== null) {
- this.areas[id].width = w;
- this.areas[id].style.width = (w) + 'px';
- this.areas[id].setAttribute('width', w);
- }
- if (h !== null) {
- this.areas[id].height = h;
- this.areas[id].style.height = (h) + 'px';
- this.areas[id].setAttribute('height', h);
- }
- };
- /**
- * Tries to detect preferred language of user.
- * @date 2007.12.28. 15:43:46
- * @return The two byte language code. (We dont care now for pt-br, etc.)
- */
- imgmap.prototype.detectLanguage = function() {
- var lang;
- if (navigator.userLanguage) {
- lang = navigator.userLanguage.toLowerCase();
- }
- else if (navigator.language) {
- lang = navigator.language.toLowerCase();
- }
- else {
- return this.config.defaultLang;
- }
- //this.log(lang, 2);
- if (lang.length >= 2) {
- lang = lang.substring(0,2);
- return lang;
- }
- return this.config.defaultLang;
- };
- /**
- * Disable selection on a given object.
- * This is especially useful in Safari, where dragging around areas
- * keeps selecting all sorts of things.
- * @author Bret Taylor
- * @url http://ajaxcookbook.org/disable-text-selection/
- * @date 27-07-2008 1:57:45
- * @param element The DOM element on which you want to disable selection.
- */
- imgmap.prototype.disableSelection = function(element) {
- if (typeof element == 'undefined' || !element) {return false;}
- if (typeof element.onselectstart != "undefined") {
- element.onselectstart = function() {
- return false;
- };
- }
- if (typeof element.unselectable != "undefined") {
- element.unselectable = "on";
- }
- if (typeof element.style.MozUserSelect != "undefined") {
- element.style.MozUserSelect = "none";
- }
- };
- /**
- * @date 11-02-2007 19:57:05
- * @url http://www.deepwood.net/writing/method-references.html.utf8
- * @author Daniel Brockman
- * @addon
- */
- Function.prototype.bind = function(object) {
- var method = this;
- return function () {
- return method.apply(object, arguments);
- };
- };
- /**
- * Trims a string.
- * Changed not to extend String but use own function for better compatibility.
- * @param str The string to trim.
- */
- imgmap.prototype.trim = function(str) {
- return str.replace(/^\s+|\s+$/g, '');
- };
- /**
- * Spawn an imgmap object for each imagemap found in the document.
- * This is used for highlighter mode only.
- * @param config An imgmap config object
- */
- function imgmap_spawnObjects(config) {
- //console.log('spawnobjects');
- var maps = document.getElementsByTagName('map');
- var imgs = document.getElementsByTagName('img');
- var imaps = [];
- var imapn;
- //console.log(maps.length);
- for (var i=0, le=maps.length; i<le; i++) {
- for (var j=0, le2=imgs.length; j<le2; j++) {
- //console.log(i);
- // console.log(maps[i].name);
- // console.log(imgs[j].getAttribute('usemap'));
- if ('#' + maps[i].name == imgs[j].getAttribute('usemap')) {
- //we found one matching pair
- // console.log(maps[i]);
- config.mode = 'highlighter_spawn';
- imapn = new imgmap(config);
- //imapn.setup(config);
- imapn.useImage(imgs[j]);
- imapn.setMapHTML(maps[i]);
- imapn.viewmode = 1;
- imaps.push(imapn);
- }
- }
- }
- }
- //global instance?
- //imgmap_spawnObjects();?
|