From 934c7e34dedf10bccd112e7aa6e4aead1144449a Mon Sep 17 00:00:00 2001 From: Trevor Parscal Date: Fri, 20 Nov 2009 02:24:28 +0000 Subject: [PATCH] Initial check in for the SVGZoom tool. --- extensions/SVGZoom/SVGZoom.hooks.php | 37 ++ extensions/SVGZoom/SVGZoom.i18n.php | 17 + extensions/SVGZoom/SVGZoom.js | 461 ++++++++++++++++++ extensions/SVGZoom/SVGZoom.php | 44 ++ extensions/SVGZoom/images/east-mini.png | Bin 0 -> 451 bytes extensions/SVGZoom/images/north-mini.png | Bin 0 -> 484 bytes extensions/SVGZoom/images/searchtool.png | Bin 0 -> 49687 bytes extensions/SVGZoom/images/south-mini.png | Bin 0 -> 481 bytes extensions/SVGZoom/images/west-mini.png | Bin 0 -> 453 bytes extensions/SVGZoom/images/zoom-minus-mini.png | Bin 0 -> 359 bytes extensions/SVGZoom/images/zoom-plus-mini.png | Bin 0 -> 489 bytes extensions/SVGZoom/images/zoom-world-mini.png | Bin 0 -> 1072 bytes extensions/SVGZoom/src/svg.htc | 1 + extensions/SVGZoom/src/svg.js | 1 + extensions/SVGZoom/src/svg.swf | Bin 0 -> 44793 bytes 15 files changed, 561 insertions(+) create mode 100644 extensions/SVGZoom/SVGZoom.hooks.php create mode 100644 extensions/SVGZoom/SVGZoom.i18n.php create mode 100644 extensions/SVGZoom/SVGZoom.js create mode 100644 extensions/SVGZoom/SVGZoom.php create mode 100644 extensions/SVGZoom/images/east-mini.png create mode 100644 extensions/SVGZoom/images/north-mini.png create mode 100644 extensions/SVGZoom/images/searchtool.png create mode 100644 extensions/SVGZoom/images/south-mini.png create mode 100644 extensions/SVGZoom/images/west-mini.png create mode 100644 extensions/SVGZoom/images/zoom-minus-mini.png create mode 100644 extensions/SVGZoom/images/zoom-plus-mini.png create mode 100644 extensions/SVGZoom/images/zoom-world-mini.png create mode 100644 extensions/SVGZoom/src/svg.htc create mode 100644 extensions/SVGZoom/src/svg.js create mode 100644 extensions/SVGZoom/src/svg.swf diff --git a/extensions/SVGZoom/SVGZoom.hooks.php b/extensions/SVGZoom/SVGZoom.hooks.php new file mode 100644 index 0000000000..50c772c8eb --- /dev/null +++ b/extensions/SVGZoom/SVGZoom.hooks.php @@ -0,0 +1,37 @@ +getText() ends in .svg + */ + + $out->addScript( + Xml::element( + 'script', + array( + 'type' => $wgJsMimeType, + 'src' => "{$wgScriptPath}/extensions/SVGZoom/SVGZoom.js?{$wgSVGZoomScriptVersion}", + ), + '', + false + ) + ); + return true; + } +} \ No newline at end of file diff --git a/extensions/SVGZoom/SVGZoom.i18n.php b/extensions/SVGZoom/SVGZoom.i18n.php new file mode 100644 index 0000000000..514a83fe67 --- /dev/null +++ b/extensions/SVGZoom/SVGZoom.i18n.php @@ -0,0 +1,17 @@ + 'SVGZoom', + 'svgzoom-desc' => 'Adds pan and zoom capabilies to MediaWiki when viewing SVG files.', +); diff --git a/extensions/SVGZoom/SVGZoom.js b/extensions/SVGZoom/SVGZoom.js new file mode 100644 index 0000000000..9b79dc5067 --- /dev/null +++ b/extensions/SVGZoom/SVGZoom.js @@ -0,0 +1,461 @@ +(function(){ // hide everything externally to avoid name collisions + +// whether to display debugging output +var svgDebug = true; + +// whether we are locally debugging (i.e. the page is downloaded to our +// hard drive and served from a local server to ease development) +var localDebug = true; + +// the full URL to where svg.js is located +// Note: Update this before putting on production +var svgSrcURL; +if (localDebug) { + svgSrcURL = wgScriptPath + '/extensions/SVGZoom/src/svg.js'; +} else { + svgSrcURL = wgScriptPath + '/extensions/SVGZoom/src/svg.js'; +} + +// whether the pan and zoom UI is initialized +var svgUIReady = false; + +// a reference to the SVG OBJECT on the page +var svgObject; + +// a reference to our zoom and pan controls +var svgControls; + +// a reference to our SVG root tag +var svgRoot; + +var isWebkit = (Math.max(navigator.appVersion.indexOf('WebKit'), + navigator.appVersion.indexOf('Safari'), 0)); + +var isFF = false; +if (navigator.userAgent.indexOf('Gecko') >= 0) { + isFF = parseFloat(navigator.userAgent.split('Firefox/')[1]) || undefined; +} + +// the URL to the proxy from which we can fetch SVG images within the same +// domain as this page is served from +// TODO: define once a proxy or API call is setup + +// the location of our images +var imageBundle; +if (localDebug) { + // for local debugging + var imageRoot = '/images/'; + imageBundle = { + 'searchtool': imageRoot + 'searchtool.png', + 'controls-north-mini': imageRoot + 'north-mini.png', + 'controls-west-mini': imageRoot + 'west-mini.png', + 'controls-east-mini': imageRoot + 'east-mini.png', + 'controls-south-mini': imageRoot + 'south-mini.png', + 'controls-zoom-plus-mini': imageRoot + 'zoom-plus-mini.png', + 'controls-zoom-world-mini': imageRoot + 'zoom-world-mini.png', + 'controls-zoom-minus-mini': imageRoot + 'zoom-minus-mini.png' + }; +} else { + // Note: update this before putting on production + var imageRoot = wgScriptPath + '/extensions/SVGZoom/images/'; + imageBundle = { + 'searchtool': imageRoot + 'searchtool.png', + 'controls-north-mini': imageRoot + 'north-mini.png', + 'controls-west-mini': imageRoot + 'west-mini.png', + 'controls-east-mini': imageRoot + 'east-mini.png', + 'controls-south-mini': imageRoot + 'south-mini.png', + 'controls-zoom-plus-mini': imageRoot + 'zoom-plus-mini.png', + 'controls-zoom-world-mini': imageRoot + 'zoom-world-mini.png', + 'controls-zoom-minus-mini': imageRoot + 'zoom-minus-mini.png' + }; +} + +// determines if we are at a Wikimedia Commons detail page for an SVG file +function isSVGPage() { + if (wgNamespaceNumber == 6 && wgTitle && wgTitle.indexOf('.svg') != -1 + && wgAction == 'view') { + return true; + } else { + return false; + } +} + +// Determines whether this page has image annotation enabled (i.e. the +// Add Note button). If this is enabled the DOM changes slightly and we have +// to account for it. Some SVG images have this (Tux.svg); others don't +// (Commons-logo.svg, for example). +function hasAnnotation() { + if (document.getElementById('ImageAnnotationAddButton')) { + return true; + } else { + return false; + } +} + +// inserts the SVG Web library into the page +function insertSVGWeb() { + document.write(''); +} + +// adds a button that when pressed turns on the zoom and pan UI +function addStartButton() { + // are we already present? user could have hit back button on an old + // loaded page + if (document.getElementById('SVGZoom.startButton')) { + return; + } + + // insert ourselves beside the SVG thumbnail area + var info = getSVGInfo(); + var thumbnail = info.fileNode; + if (hasAnnotation()) { + thumbnail = thumbnail.childNodes[0].childNodes[0]; + } + // make the container element we will go into a bit larger to accommodate + // the icon + var infoWidth = Number(String(info.width).replace('px', '')); + thumbnail.style.width = (infoWidth + 30) + 'px'; + var img = document.createElement('img'); + img.id = 'SVGZoom.startButton'; + img.src = imageBundle['searchtool']; + img.setAttribute('width', '30px'); + img.setAttribute('height', '30px'); + img.style.position = 'absolute'; + img.style.cursor = 'pointer'; + img.onclick = initUI; + // some SVG pages have a spurious
element; add before that + if (thumbnail.lastChild.nodeType == 1 + && thumbnail.lastChild.nodeName.toLowerCase() == 'br') { + thumbnail.insertBefore(img, thumbnail.lastChild); + } else { + thumbnail.appendChild(img); + } +} + +// adds the pan and zoom UI and turns the PNG into an SVG object +function initUI() { + if (svgUIReady) { // already initialized + return; + } + + svgUIReady = true; + + // remove magnifying glass icon + var startButton = document.getElementById('SVGZoom.startButton'); + startButton.parentNode.removeChild(startButton); + + // get the thumbnail container and make it invisible + var info = getSVGInfo(); + var thumbnail = info.fileNode; + if (hasAnnotation()) { + thumbnail = thumbnail.childNodes[0].childNodes[0]; + } + var oldPNG = thumbnail.childNodes[0]; + oldPNG.style.visibility = 'hidden'; + oldPNG.style.zIndex = -1000; + + // store a reference to the SVG root to make subsequent accesses faster + svgRoot = svgObject.contentDocument.rootElement; + + // Safari/Native has a bug where it doesn't respect the height/width of + // the OBJECT when scaling the size of some objects (commons-logo.svg, + // for example). A workaround is to manually set the size inside the SVG. + if (isWebkit) { + svgRoot.setAttribute('width', info.width); + svgRoot.setAttribute('height', info.height); + } + + // reveal the SVG object and controls + svgObject.parentNode.style.zIndex = 1000; + svgControls.style.display = 'block'; + + // make the cursor a hand when over the SVG; not all browsers support + // this property yet + svgRoot.setAttribute('cursor', 'pointer'); + // TODO: Get hand cursor showing up in SVG Web's Flash renderer + + // add drag listeners on the SVG root + svgRoot.addEventListener('mousedown', mouseDown, false); + svgRoot.addEventListener('mousemove', mouseMove, false); + svgRoot.addEventListener('mouseup', mouseUp, false); +} + +// Creates the SVG OBJECT during page load so that when we swap the PNG +// thumbnail and the SVG OBJECT it happens much faster +function createSVGObject() { + var info = getSVGInfo(); + var thumbnail = info.fileNode; + if (hasAnnotation()) { + thumbnail = thumbnail.childNodes[0].childNodes[0]; + } + + // create the SVG OBJECT that will replace our thumbnail container + var obj = document.createElement('object', true); + obj.setAttribute('type', 'image/svg+xml'); + obj.setAttribute('data', info.url); + obj.setAttribute('width', info.width); + obj.setAttribute('height', info.height); + obj.addEventListener('load', function() { + // store a reference to the SVG OBJECT + svgObject = this; + + // create the controls + svgControls = createControls(); + svgControls.style.display = 'none'; + + // now place the controls on top of the SVG object + if (thumbnail.lastChild.nodeType == 1 + && thumbnail.lastChild.nodeName.toLowerCase() == 'br') { + thumbnail.insertBefore(svgControls, thumbnail.lastChild); + } else { + thumbnail.appendChild(svgControls); + } + + // add our magnification icon + addStartButton(); + + // set up the mouse scroll wheel; FF 3.5/Native has an annoying bug + // where DOMMouseScroll events do not propagate to OBJECTs under + // some situations! + if (isFF && svgweb.getHandlerType() == 'native') { + hookEvent(svgObject.contentDocument.rootElement, 'mousewheel', + MouseWheel); + } else { + hookEvent('file', 'mousewheel', MouseWheel); + } + + // prevent IE memory leaks + thumbnail = obj = null; + }, false); + // ensure that the thumbnail container has relative positioning; this will + // reset our absolutely positioned elements to be relative to our parent + // so we have correct coordinates + thumbnail.style.position = 'relative'; + // position object behind the PNG image; do it in a DIV to avoid any + // strange style + OBJECT interactions + var container = document.createElement('div'); + container.id = 'SVGZoom.container'; + container.style.zIndex = -1000; + container.style.position = 'absolute'; + // FIXME: This is a hack; figure out why the Flash version of Commons-logo.svg + // is off by one 1 pixel on x and y + if (!hasAnnotation() && svgweb.getHandlerType() == 'flash') { + container.style.top = '-1px'; + container.style.left = '-1px'; + } else { + container.style.top = '0px'; + container.style.left = '0px'; + } + if (thumbnail.lastChild.nodeType == 1 + && thumbnail.lastChild.nodeName.toLowerCase() == 'br') { + thumbnail.insertBefore(container, thumbnail.lastChild); + } else { + thumbnail.appendChild(container); + } + svgweb.appendChild(obj, container); +} + +// Returns a DIV ready to append to the page with our zoom and pan controls +function createControls() { + var controls = document.createElement('div'); + controls.id = 'SVGZoom.controls'; + controls.innerHTML = + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
'; + + // attach event handlers + controls.childNodes[0].childNodes[0].onclick = panUp; + controls.childNodes[0].childNodes[1].onclick = panLeft; + controls.childNodes[0].childNodes[2].onclick = panRight; + controls.childNodes[0].childNodes[3].onclick = panDown; + controls.childNodes[0].childNodes[4].onclick = zoomIn; + controls.childNodes[0].childNodes[5].onclick = zoomWorld; + controls.childNodes[0].childNodes[6].onclick = zoomOut; + + return controls; +} + +function panUp() { + svgRoot.currentTranslate.setY(svgRoot.currentTranslate.getY() - 25); +} + +function panLeft() { + svgRoot.currentTranslate.setX(svgRoot.currentTranslate.getX() - 25); +} + +function panRight() { + svgRoot.currentTranslate.setX(svgRoot.currentTranslate.getX() + 25); +} + +function panDown() { + svgRoot.currentTranslate.setY(svgRoot.currentTranslate.getY() + 25); +} + +function zoomIn() { + svgRoot.currentScale = svgRoot.currentScale * 1.1; +} + +function zoomWorld() { + svgRoot.currentScale = 1; + svgRoot.currentTranslate.setXY(0, 0); +} + +function zoomOut() { + svgRoot.currentScale = svgRoot.currentScale / 1.1; +} + +// variables used for dragging +var x, y, rootX, rootY; +var dragX = 0, dragY = 0; +var dragging = false; + +function mouseDown(evt) { + dragging = true; + + x = evt.clientX; + y = evt.clientY; + + rootX = svgRoot.currentTranslate.getX(); + rootY = svgRoot.currentTranslate.getY(); + + evt.preventDefault(true); +} + +function mouseMove(evt) { + if (!dragging) { + return; + } + + dragX = evt.clientX - x; + dragY = evt.clientY - y; + + // Firefox and Webkit differ on the coordinates they return; Firefox + // returns the mouse coordinates with no scaling, while Webkit and SVG Web + // scale the mouse coordinates using the currentScale + if (isWebkit || svgweb.getHandlerType() == 'flash') { + dragX /= svgRoot.currentScale; + dragY /= svgRoot.currentScale; + } + + var newX = rootX + dragX; + var newY = rootY + dragY; + + svgRoot.currentTranslate.setXY(newX, newY); + + evt.preventDefault(true); +} + +function mouseUp(evt) { + dragging = false; + + evt.preventDefault(true); +} + +// Returns a data structure that has info about the SVG file on this page, including: +// url - filename and URL necessary to fetch the SVG file +// width and height - the width and height to make the SVG file +// fileNode - the DOM node that has the top level PNG thumbnail in it to replace +// imgNode - the actual IMG tag that has the PNG thumbnail inside of it +// Note that this method returns null if there is no file node on the page. +function getSVGInfo() { + var fileNode = document.getElementById('file'); + if (!fileNode) { + return null; + } + + var url; + if (hasAnnotation()) { + url = fileNode.childNodes[0].childNodes[0].childNodes[0].href; + } else { + url = fileNode.childNodes[0].href; + } + var imgNode = fileNode.getElementsByTagName('img')[0]; + var width = imgNode.getAttribute('width'); + var height = imgNode.getAttribute('height'); + + return { url: url, fileNode: fileNode, imgNode: imgNode, + width: width, height: height }; +} + +// Mousewheel Scrolling thanks to +// http://blog.paranoidferret.com/index.php/2007/10/31/javascript-tutorial-the-scroll-wheel/ +function hookEvent(element, eventName, callback) { + if (typeof(element) == 'string') { + element = document.getElementById(element); + } + + if (element == null) { + return; + } + + if (element.addEventListener) { + if (eventName == 'mousewheel') { + element.addEventListener('DOMMouseScroll', callback, false); + } + element.addEventListener(eventName, callback, false); + } else if (element.attachEvent) { + element.attachEvent("on" + eventName, callback); + } +} + +function MouseWheel(e) { + e = e ? e : window.event; + + var wheelData = e.detail ? e.detail * -1 : e.wheelDelta; + + if (wheelData > 0) { + zoomIn(); + } else { + zoomOut(); + } + + if (e.preventDefault) { + e.preventDefault(); + } + + return false; +} + +// called when the page is loaded and ready to be manipulated +function pageLoaded() { + svgweb.addOnLoad(createSVGObject); +} + +if (isSVGPage()) { + insertSVGWeb(); + addOnloadHook(pageLoaded); +} + +// hide internal implementation details inside of a closure +})(); diff --git a/extensions/SVGZoom/SVGZoom.php b/extensions/SVGZoom/SVGZoom.php new file mode 100644 index 0000000000..f826e71c27 --- /dev/null +++ b/extensions/SVGZoom/SVGZoom.php @@ -0,0 +1,44 @@ +, Brad Neuberg + * @license ? + * @version 0.1.0 + */ + +/* Configuration */ + +// This needs to be updated before deployments +$wgSVGZoomScriptVersion = 1; + +/* Setup */ + +// Sets Credits +$wgExtensionCredits['other'][] = array( + 'path' => __FILE__, + 'name' => 'SVGZoom', + 'author' => array( 'Trevor Parscal', 'Brad Neuberg' ), + 'version' => '0.1.0', + 'url' => 'http://www.mediawiki.org/wiki/Extension:SVGZoom', + 'descriptionmsg' => 'svgzoom-desc', +); + +// Adds Autoload Classes +$wgAutoloadClasses['SVGZoomHooks'] = + dirname( __FILE__ ) . "/SVGZoom.hooks.php"; + +// Adds Internationalized Messages +$wgExtensionMessagesFiles['SVGZoom'] = + dirname( __FILE__ ) . "/SVGZoom.i18n.php"; + +// Registers Hooks +$wgHooks['BeforePageDisplay'][] = 'SVGZoomHooks::addResources'; \ No newline at end of file diff --git a/extensions/SVGZoom/images/east-mini.png b/extensions/SVGZoom/images/east-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..0707567a7d50203cedc0bd73637db130aeb4b789 GIT binary patch literal 451 zcmV;!0X+VRP)D z)UiuKQ547V@0BoUP#nS`XpnRXbg>~@grLPG3u+4_aTVc#|AOFy{s0FzArL3Q$+RGp z6hScpCk?Ej9E2nZ>^40pd+O6O-t*(bLXn7@U~tC>wgp@Zp;~nzhr>!PcTA~thR3sM1iR9OwDSA6X*4cK zrH-)MH|Aj>A=Lf3GcuV3;jo)d=MqKnVm8l=9~v6A#j;K^>8ITe5ePW+B6~}1&FQp} z&!12zoZ@oXez&|!uYWT6rrRAd7<~RYUt0z#m!FA7Z)mmNr(1PHP_H*cQEtg*JF_CS zxzK3zMI!Nls@52fC-b63T}VnvCi6r*en-FmvFO5SDV54UsM&nO=gUy7zAgd)`ald; tfBhPAE~Ro0tH1s@ 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 XLCTLS$T zl)paibF^>Dft7U1W{0Gu@=E42itQHT%26p-YAIwfI%Qqh(mLsLs3wZ zP(+h9=ineoV7I|6dC&KJhTrY{xSxB@xtuErAy7+_ic#PY2m>KtLzASEMFp?}CE#S< zL0ym}759L1U~^FjfIL-+DM&K8MJBU58^pLBLr5U7MzeWLqj7}WZP&ytKZDhsiPO1? zqU@7S?;y*P?nM^HucMLGDwE3vDHNjEY%4~^{({14XCmRIREpv8IOYPTL7|D^^*Sh* z4~WNIrU4Vl(?+lNL8sGaH2V4%=#5a zI(-w*NuC&V>Gm(yx`qw)3->;~_Os(HkJvl&8*k0>5?Mr9zb`E~lJO{^#5=$8ppF>tyzo!t1#uE5{2^Q@d+w8{^rUH@BD9j>SO`@5+8V3~Et zERDk?myN;y$@l%wDi51Kkj-FRf343l$70joc`v0O%=1ZUWRF<^3T zk~>cVK@>*M;IIp1RV*w-?1+t)nD}T+`~liYV?k$Yvi|}SS}QHAtTeHs~8=CeJ45 fP4rX#?H_#tm&$|IMWgd%00000NkvXXu0mjfXz|d8 literal 0 HcmV?d00001 diff --git a/extensions/SVGZoom/images/zoom-world-mini.png b/extensions/SVGZoom/images/zoom-world-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..2159dde7ba0c32010d5d76910fd4d49bae925912 GIT binary patch literal 1072 zcmV-01kd}4P)K;tg z_(&AUz=Rk^zzAfh$QTk7qoAn37>t|1C}ms<{M$W{;TW8^lbn3#@;m2<;72!Gm{<%6 z2|6+}L(ypD)YkU#`0+4;uw^)+|ARCdIn~vB(P+FG8gigecv4aE7OORkxVQiu4kw2W z)zQ;4y)p5Boztfic>VeZ?Dl11V(wzKKA^C$g@uI`va)K}v7?mE&IzikzsF|Vy)~$) zD3R>!?PO$BGc~oq{rh_{8dbb{HA!%=F9w5x)m0Zyo(wZEFw4Gu;oQ0N-A0gJui*Ic zII61N@#f7GM~^l#JnSGfHHdU^J>Qn{|lABF>%LMO4(?wTk3& zDLFayw6~8@UT!5bGlY*H?SzN>t(X4n*`K7Q1_2 zF>vo*4=-Mf6B43iY;2zV{Aer|14^YQCX<%HKm|vRM6+$15{X2_+}tv^Z+Brf>j01* zI1q{34av!RT3bi(@{-WdFi1ngAVo!qR8+hJKoDH``g(Hd(r*AyLsZ@kqE+s!dnk!e52@dw<#ED-p8r3v54kGR9 z`b12OKU%Ffp`l93%6h1;A0Re10JB*~QPEcjf(w6tZ#+E2G&TJ}X=yh$+iu)$Fqw3m zJlTxY<$@0%{^I7%Z;(htOv1Hm7W8@_ ztkzI+a_ZJv2bi2(q_VP?jEoSHl73?U{s;~pjKt5+3#U^cHa38Xi3KiROhToS@$%&- z;^Vc{*7niSG5#3@aQ=KNV`G2w{(U}mb^RPW) diff --git a/extensions/SVGZoom/src/svg.js b/extensions/SVGZoom/src/svg.js new file mode 100644 index 0000000000..f3ce9b886d --- /dev/null +++ b/extensions/SVGZoom/src/svg.js @@ -0,0 +1 @@ +window.timer={};function start(subject,subjectStarted){if(subjectStarted&&!ifStarted(subjectStarted)){return;}window.timer[subject]={start:new Date().getTime()};}function end(subject,subjectStarted){if(subjectStarted&&!ifStarted(subjectStarted)){return;}if(!window.timer[subject]){console.log("Unknown subject: "+subject);return;}window.timer[subject].end=new Date().getTime();}function increment(subject,amount){if(!window.timer[subject]){window.timer[subject]={incremented:true,total:0};}window.timer[subject].total+=amount;}function total(subject){if(!window.timer[subject]){console.log("Unknown subject: "+subject);return;}var t=window.timer[subject];if(t.incremented){return t.total;}else{if(t){return t.end-t.start;}else{return null;}}}function ifStarted(subject){for(var i in window.timer){var t=window.timer[i];if(i==subject&&t.start!==undefined&&t.end===undefined){return true;}}return false;}function report(){for(var i in window.timer){var t=total(i);if(t!==null){console.log(i+": "+t+"ms");}}}(function(){window.svgns="http://www.w3.org/2000/svg";window.xlinkns="http://www.w3.org/1999/xlink";svgnsFake="urn:__fake__internal__namespace";var isOpera=false,isSafari=false,isMoz=false,isIE=false,isAIR=false,isKhtml=false,isFF=false,isXHTML=false;function _detectBrowsers(){var n=navigator,dua=n.userAgent,dav=n.appVersion,tv=parseFloat(dav);if(dua.indexOf("Opera")>=0){isOpera=tv;}var index=Math.max(dav.indexOf("WebKit"),dav.indexOf("Safari"),0);if(index){isSafari=parseFloat(dav.split("Version/")[1])||(parseFloat(dav.substr(index+7))>419.3)?3:2;}if(dua.indexOf("AdobeAIR")>=0){isAIR=1;}if(dav.indexOf("Konqueror")>=0||isSafari){isKhtml=tv;}if(dua.indexOf("Gecko")>=0&&!isKhtml){isMoz=tv;}if(isMoz){isFF=parseFloat(dua.split("Firefox/")[1])||undefined;}if(document.all&&!isOpera){isIE=parseFloat(dav.split("MSIE ")[1])||undefined;}if(document.documentMode){isStandardsMode=(document.documentMode>5);}else{isStandardsMode=(document.compatMode=="CSS1Compat");}if(document.contentType=="application/xhtml+xml"){isXHTML=true;}else{if(typeof XMLDocument!="undefined"&&document.constructor==XMLDocument){isXHTML=true;}}}_detectBrowsers();function doDebugging(){var debug=false;var scripts=document.getElementsByTagName("script");for(var i=0;i<\/script>');var script=document.getElementById("__ie__svg__onload");script.onreadystatechange=function(){if(this.readyState!="complete"&&window.onload){self._saveWindowOnload();}else{if(this.readyState=="complete"){self._onDOMContentLoaded();}}};var documentReady=function(){if(window.onload){self._saveWindowOnload();document.detachEvent("onreadystatechange",documentReady);}};document.attachEvent("onreadystatechange",documentReady);}},_setXDomain:function(){var scripts=document.getElementsByTagName("script");for(var i=0;i\s*/,"");}if(addMissing){if(/\<\?xml/m.test(svg)==false){svg='\n'+svg;}if(svg.indexOf(":svg ")==-1){if(/xmlns\=['"]http:\/\/www\.w3\.org\/2000\/svg['"]/.test(svg)==false){svg=svg.replace("\s+\<");}if(this.renderer==FlashHandler){var commentRE=/")+3;var comment="