PageSourceSearch

https://elifnurhali.com/map/js/mapsvg.js?v=5.5.8

js elifnurhali.com collected 2026-10-01 03:54:19 UTC 80,742 bytes, 1,944 lines download raw bytes

1/**
2 * mapSvg 5.5.18 - Interactive Map Plugin
3 *
4 * Author - Roman S. Stepanov
5 * http://codecanyon.net/user/Yatek/portfolio?ref=Yatek
6 *
7 * Version : 5.5.18
8 * Released: Deember 7, 2013
9 *
10 * You must purchase Regular or Extended license to use mapSvg plugin.
11 * Visit plugin's page @ CodeCanyon: http://codecanyon.net/item/jquery-interactive-svg-map-plugin/1694201
12 * Licenses: http://codecanyon.net/licenses/regular_extended
13 */
14
15 (function( $ ) {
16
17        var instances = {},
18        globalID  = 0,
19        userAgent = navigator.userAgent.toLowerCase();
20
21    // Get plugin's path
22    var scripts       = document.getElementsByTagName('script');
23    var myScript      = scripts[scripts.length - 1].src.split('/');
24        myScript.pop();
25    var pluginJSURL   =  myScript.join('/')+'/';
26        myScript.pop();
27    var pluginRootURL =  myScript.join('/')+'/';
28
29    // Check for iPad/Iphone/Andriod
30    var touchDevice =
31        (userAgent.indexOf("ipad") > -1) ||
32        (userAgent.indexOf("iphone") > -1) ||
33        (userAgent.indexOf("ipod") > -1) ||
34        (userAgent.indexOf("android") > -1);
35
36    var _browser = {};
37
38    _browser.ie = userAgent.indexOf("msie") > -1 ? {} : false;
39    if(_browser.ie)
40        _browser.ie.old = (navigator.userAgent.match(/MSIE [6-8]/) !== null);
41
42    _browser.firefox = userAgent.indexOf("firefox") > -1;
43
44    if (!String.prototype.trim) {
45        String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');};
46    }
47
48
49    // Create function for retrieving mouse coordinates
50    if (touchDevice){
51        var mouseCoords = function(e){
52            return e.touches[0] ?
53            {'x':e.touches[0].pageX, 'y':e.touches[0].pageY} :
54            {'x':e.changedTouches[0].pageX, 'y':e.changedTouches[0].pageY};
55        };
56    }else{
57        var mouseCoords = function(e){
58            
59            //return e.pageX ?
60            //{'x':e.pageX, 'y':e.pageY} :
61            //{'x':e.clientX + $('html').scrollLeft(), 'y':e.clientY + $('html').scrollTop()};
62            return {'x':e.clientX + $(window).scrollLeft(), 'y':e.clientY + $(window).scrollTop()};
63            
64        };
65    }
66
67    // This data is needed for lat-lon to x-y conversions
68    var CBK = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472]
69    var CEK = [0.7111111111111111, 1.4222222222222223, 2.8444444444444446, 5.688888888888889, 11.377777777777778, 22.755555555555556, 45.51111111111111, 91.02222222222223, 182.04444444444445, 364.0888888888889, 728.1777777777778, 1456.3555555555556, 2912.711111111111, 5825.422222222222, 11650.844444444445, 23301.68888888889, 46603.37777777778, 93206.75555555556, 186413.51111111112, 372827.02222222224, 745654.0444444445, 1491308.088888889, 2982616.177777778, 5965232.355555556, 11930464.711111112, 23860929.422222223, 47721858.844444446, 95443717.68888889, 190887435.37777779, 381774870.75555557, 763549741.5111111]
70    var CFK = [40.74366543152521, 81.48733086305042, 162.97466172610083, 325.94932345220167, 651.8986469044033, 1303.7972938088067, 2607.5945876176133, 5215.189175235227, 10430.378350470453, 20860.756700940907, 41721.51340188181, 83443.02680376363, 166886.05360752725, 333772.1072150545, 667544.214430109, 1335088.428860218, 2670176.857720436, 5340353.715440872, 10680707.430881744, 21361414.86176349, 42722829.72352698, 85445659.44705395, 170891318.8941079, 341782637.7882158, 683565275.5764316, 1367130551.1528633, 2734261102.3057265, 5468522204.611453, 10937044409.222906, 21874088818.445812, 43748177636.891624]
71
72    // Default options
73    var defaults = {
74        keepSourceStyles    : false,
75        loadingText         : 'Harita Yükleniyor...',
76        //colors              : {base: "#E1F1F1", background: "#eeeeee", hover: "#548eac", selected: "#065A85", stroke: "#7eadc0"},
77        colors: { background: "#4b566c", selected: 5, hover: 2, base: "#FFFFFF", hover: "#FFFFFF", stroke: "#000000" },
78        regions             : {},
79        viewBox             : [],
80        cursor              : 'pointer',
81        scale               : 1,
82        tooltipsMode        : 'hover',
83        tooltips            : {show: 'hover', mode: 'names'},
84        onClick             : null,
85        mouseOver           : null,
86        mouseOut            : null,
87        disableAll          : false,
88        hideAll             : false,
89        marks               : null,
90        hover_mode          : 'brightness',
91        selected_mode       : 'brightness',
92        hover_brightness    : 1,
93        selected_brightness : 5,
94        pan                 : false,
95        panLimit            : true,
96        panBackground       : false,
97        zoom                : false,
98        popover             : {width: 'auto', height:  'auto'},
99        buttons             : true,
100        zoomLimit           : [0,5],
101        zoomDelta           : 1.2,
102        zoomButtons         : {'show': true, 'location': 'right'},
103        multiSelect         : false
104
105    };
106
107    // Default mark style
108    var markOptions = {attrs: {'cursor': 'pointer', 'src': pluginRootURL+'markers/_pin_default.png'}};
109
110
111/** Main Class **/
112var mapSVG = function(elem, options){
113
114    var _data;
115
116    this.methods = {
117
118
119        // destroy
120        destroy : function(){
121            delete instances[_data.$map.attr('id')];
122            _data.$map.empty();
123            return _this;
124        },
125        getData : function(){
126          return _data;
127        },
128        // GET SCALE VALUE
129        getScale: function(){
130
131            var ratio_def = _data.svgDefault.width / _data.svgDefault.height;
132            var ratio_new = _data.options.width / _data.options.height;
133            var scale1, scale2;
134
135            var size = _data.options.responsive ? [_data.$map.width(), _data.$map.height()] : [_data.options.width, _data.options.height];
136
137            if(ratio_new < ratio_def ){
138            // Calculate scale by height
139                scale1 = _data.svgDefault.width / _data.svgDefault.viewBox[2];
140                scale2 = size[0] / _data.viewBox[2];
141            }else{
142            // Calculate scale by width
143                scale1 = _data.svgDefault.height / _data.svgDefault.viewBox[3];
144                scale2 = size[1] / _data.viewBox[3];
145            }
146
147            return (1 - (scale1-scale2));
148        },
149        fluidResize : function(w,h){
150
151            if(!w || !h){
152                w = _data.$map.width();
153                h = _data.$map.height();
154            }
155
156           _data.R.setSize(w,h);
157
158           _data.scale = _this.getScale();
159           _this.marksAdjustPosition();
160
161           //_data.R.setViewBox(_data.viewBox[0], _data.viewBox[1], _data.viewBox[2], _data.viewBox[3], true);
162        },
163        // GET VIEBOX [x,y,width,height]
164        getViewBox : function(){
165            return _data.viewBox;
166        },
167        // SET VIEWBOX
168        setViewBox : function(v){
169
170            if(typeof v == 'string'){
171                var coords = _data.R.getById(v).getBBox();
172                _data.viewBox = [coords.x-5, coords.y-5, coords.width+10, coords.height+10];
173                var isZooming = true;
174            }else{
175                var d = (v && v.length==4) ? v : _data.svgDefault.viewBox;
176                var isZooming = parseInt(d[2]) != _data.viewBox[2] || parseInt(d[3]) != _data.viewBox[3];
177                _data.viewBox = [parseFloat(d[0]), parseFloat(d[1]), parseFloat(d[2]), parseFloat(d[3])];
178            }
179            /*
180            var vbRatio = _data.viewBox[2]/_data.viewBox[3];
181            var whRatio = _data.options.width / _data.options.height;
182            
183            if( vbRatio != whRatio ){
184                if(vbRatio>whRatio){ // add height to VB
185                    var newvb3 = _data.viewBox[2] / whRatio;
186                    _data.viewBox[1] -= (newvb3-_data.viewBox[3])/2; 
187                    _data.viewBox[3] = newvb3;
188                }else{               // add width to VB
189                    var newvb2 = _data.viewBox[3] * whRatio;
190                    _data.viewBox[0] -= (newvb2 - _data.viewBox[2])/2;
191                    _data.viewBox[2] = newvb2;
192                }
193            }
194            */
195            
196
197            _data.R.setViewBox(_data.viewBox[0], _data.viewBox[1], _data.viewBox[2], _data.viewBox[3], true);
198
199            if(isZooming){
200                _data.scale = _this.getScale();
201                _this.marksAdjustPosition();
202                if((_browser.ie && !_browser.ie.old) || _browser.firefox){
203                        _this.mapAdjustStrokes();
204                }
205
206            }
207
208            return true;
209        },
210        // SET VIEWBOX BY SIZE
211        viewBoxSetBySize : function(width,height){
212
213            _data._viewBox = _this.viewBoxGetBySize(width,height);
214            _data.viewBox  = $.extend([],_data._viewBox);
215            _data.scale    = _this.getScale();
216
217            _data.R.setViewBox(_data.viewBox[0], _data.viewBox[1], _data.viewBox[2], _data.viewBox[3], true);
218
219            _this.marksAdjustPosition();
220
221            return _data.viewBox;
222        },
223        viewBoxGetBySize : function(width, height){
224
225
226            var new_ratio = width / height;
227            var old_ratio = _data.svgDefault.viewBox[2] / _data.svgDefault.viewBox[3];
228
229            var vb = $.extend([],_data.svgDefault.viewBox);
230
231            if (new_ratio != old_ratio){
232                    vb[2] = width*_data.svgDefault.viewBox[2] / _data.svgDefault.width;
233                    vb[3] = height*_data.svgDefault.viewBox[3] / _data.svgDefault.height;
234
235            }
236
237            return vb;
238        },
239        viewBoxReset : function(){
240            _this.setViewBox();
241        },
242        mapAdjustStrokes : function(){        
243                _data.R.forEach(function(region){
244                    if(region.default_attr && region.default_attr['stroke-width'])
245                        region.attr( {'stroke-width': region.default_attr['stroke-width'] / _data.scale } );
246                });
247        },
248        // ZOOM
249        zoomIn: function(){
250            _this.zoom(1);
251        },
252        zoomOut: function(){
253            _this.zoom(-1);
254        },
255        touchZoomStart : function (touchScale){
256
257            touchZoomStart = _data._scale;
258            _data.scale  = _data.scale * zoom_k;
259            zoom   = _data._scale;
260            _data._scale = _data._scale * zoom_k;
261
262
263            var vWidth     = _data.viewBox[2];
264            var vHeight    = _data.viewBox[3];
265            var newViewBox = [];
266
267            newViewBox[2]  = _data._viewBox[2] / _data._scale;
268            newViewBox[3]  = _data._viewBox[3] / _data._scale;
269
270            newViewBox[0]  = _data.viewBox[0] + (vWidth - newViewBox[2]) / 2;
271            newViewBox[1]  = viewBox[1] + (vHeight - newViewBox[3]) / 2;
272
273            _this.setViewBox(newViewBox, true);
274
275        },
276        touchZoomMove : function(){
277
278        },
279        touchZoomEnd : function(){
280
281        },
282        zoom : function (delta, exact){
283
284            var vWidth     = _data.viewBox[2];
285            var vHeight    = _data.viewBox[3];
286            var newViewBox = [];
287
288            if(!exact){
289            // check for zoom limit
290                var d = delta > 0 ? 1 : -1;
291                _data._zoomLevel = _data.zoomLevel;
292                _data._zoomLevel += d;
293                if(_data._zoomLevel > _data.options.zoomLimit[1] || _data._zoomLevel < _data.options.zoomLimit[0]) return false;
294
295                _data.zoomLevel = _data._zoomLevel;
296
297                var zoom_k = d * _data.options.zoomDelta;
298                if (zoom_k < 1) zoom_k = -1/zoom_k;
299
300                _data._scale         = _data._scale * zoom_k;
301                newViewBox[2]  = _data._viewBox[2] / _data._scale;
302                newViewBox[3]  = _data._viewBox[3] / _data._scale;
303            }else{
304                _data._scale         = exact;
305                newViewBox[2]  = _data.touchZoomStartViewBox[2] / _data._scale;
306                newViewBox[3]  = _data.touchZoomStartViewBox[3] / _data._scale;
307            }
308
309            newViewBox[0]  = _data.viewBox[0] + (vWidth - newViewBox[2]) / 2;
310            newViewBox[1]  = _data.viewBox[1] + (vHeight - newViewBox[3]) / 2;
311
312            _this.setViewBox(newViewBox, true);
313        },
314        //  MARK : UPDATE
315        markUpdate : function(mark, data){
316
317            if(data.attrs['src']=="")
318                delete data.attrs['src'];
319            if(data.attrs['href']=="")
320                delete data.attrs['href'];
321
322                var img  = new Image();
323
324                img.onload = function(){
325
326                    data.data.width = this.width;
327                    data.data.height = this.height;
328                    data.attrs.width = parseFloat(data.data.width/_data.scale).toFixed(2);
329                    data.attrs.height = parseFloat(data.data.height/_data.scale).toFixed(2);
330
331                    // we don't want href to be active in edit mode
332                    if(_data.options.editMode && data.attrs.href){
333                            mark.data('href',data.attrs.href);
334                            delete data.attrs.href;
335                    }else if(_data.options.editMode && !data.attrs.href){
336                            mark.removeData('href');
337                    }
338
339                    mark.data(data.data);
340                    mark.attr(data.attrs);
341                };
342
343                img.src  = data.attrs.src;
344
345        },
346        // MARK : DELETE
347        markDelete: function(mark){
348            mark.remove();
349        },
350        // MARK : ADD
351        markAdd : function(opts, create) {
352
353                // Join default mark options with user-defined options
354                var mark = $.extend(true, {}, markOptions, opts);
355
356
357                if (mark.width && mark.height){
358
359                    return _this.markAddFinalStep(mark, create);
360
361                }else{
362
363                    var img = new Image();
364
365
366                    img.onload = function(){
367
368                        mark.width = this.width;
369                        mark.height = this.height;
370
371                        return _this.markAddFinalStep(mark, create);
372                    };
373
374                    img.src = mark.attrs.src;
375                }
376        },
377        markAddFinalStep : function(mark, create){
378                // We don't need to open a link in edit mode
379                var markAttrs = $.extend(true, {}, mark.attrs);
380
381                var width  = parseFloat(mark.width/_data.scale).toFixed(2);
382                var height = parseFloat(mark.height/_data.scale).toFixed(2);
383
384
385                // Get mark's xy OR convert lat/lon to x/y
386                var xy = mark.xy ? mark.xy :
387                            (mark.attrs.x ? [mark.attrs.x, mark.attrs.y] :
388                                (mark.c ? _this.ll2px(mark) : false)
389                             );
390
391                if(!xy) return false;
392
393                if(create){
394                    xy[0] = xy[0]/_data.scale - mark.width/(2*_data.scale) + (_data.viewBox[0] - _data._viewBox[0]);
395                    xy[1] = (xy[1]-mark.height)/_data.scale + (_data.viewBox[1] - _data._viewBox[1]);
396                    xy = _this.markGetDefaultCoords(xy[0],xy[1],mark.width,mark.height,this.getScale());
397                }
398
399                xy[0] = parseFloat(xy[0]).toFixed(4);
400                xy[1] = parseFloat(xy[1]).toFixed(4);
401
402                //if(_data.options.editMode)
403                //    delete markAttrs.href;
404                // we don't want href to be active in edit mode
405                if(_data.options.editMode && markAttrs.href){
406                        mark.href = markAttrs.href;
407                        delete markAttrs.href;
408                }
409
410
411                delete markAttrs.width;
412                delete markAttrs.height;
413
414
415                // Add mark (image)
416                var RMark = _data.R.image(mark.attrs.src, xy[0], xy[1], width, height)
417                             .attr(markAttrs)
418                             .data(mark);
419                RMark.mapsvg_type = 'mark';
420
421
422                if(mark.id)
423                    RMark.node.id = mark.id;
424
425                if(!_data.options.editMode){
426                    if(!touchDevice){
427                        RMark.mousedown(function(e){
428                            console.log('mark clicked');
429                            console.log(this.data('popover'));
430                                if(this.data('popover')){
431
432                                    _this.showPopover(e, this.data('popover'));
433                                }
434                                if(_data.options.onClick)
435                                    return _data.options.onClick.call(this, e, _this);
436
437                        });
438
439                        if(_data.options.mouseOver){
440                            RMark.mouseover(function(e){
441                                return _data.options.mouseOver.call(this, e, _this);
442                            });
443                        }
444                        if(_data.options.mouseOut){
445                            RMark.mouseout(function(e){
446                                return _data.options.mouseOver.call(this, e, _this);
447                            });
448                        }
449
450                    }else{
451                        RMark.touchstart(function(e){
452                                if(this.attrs.href){
453                                    window.location.href = this.attrs.href;
454                                }else if(this.data('popover')){
455                                    _this.showPopover(e, this.data('popover'));
456                                }
457                                if(_data.options.onClick)
458                                    return _data.options.onClick.call(this, e, _this);
459
460                        });
461                    }
462                }
463
464                _this.markEventHandlersSet(_data.options.editMode, RMark);
465                _data.RMarks.push(RMark);
466
467
468                // Call edit window
469                if(create)
470                    _data.options.marksEditHandler.call(RMark);
471
472                    _this.markAdjustPosition(RMark);
473
474
475                return RMark;
476
477        },
478        marksAdjustPosition : function(mark){
479
480            if(!mark && (!_data.RMarks || _data.RMarks.length < 1)) return false;
481
482            // We want a marker "tip" to be on bottom side (like a pin)
483            // But Raphael starts to draw an image from left top corner.
484            // At the same time we don't want a mark to be scaled in size when map scales;
485            // Mark always should stay the same size.
486            // In this case coordinates of bottom point of image will vary with map scaling.
487            // So we have to calculate the offset.
488
489            var dx, dy;
490
491            for (var m in _data.RMarks.items){
492                var w = _data.RMarks.items[m].data('width');
493                var h = _data.RMarks.items[m].data('height');
494                dx = w/2 - w/(2*_data.scale);
495                dy = h - h/_data.scale;
496                if(_browser.ie){
497                    w  = parseInt(w);
498                    h  = parseInt(h);
499                }
500
501                _data.RMarks.items[m].attr({width: w/_data.scale, height: h/_data.scale}).transform('t'+dx+','+dy);
502            }
503
504        },
505        markAdjustPosition : function(mark){
506                var w = mark.data('width');
507                var h = mark.data('height');
508                var dx = w/2 - w/(2*_data.scale);
509                var dy = h - h/_data.scale;
510                mark.attr({width: w/(_data.scale), height: h/(_data.scale)}).transform('t'+dx+','+dy);
511        },
512        // GET MARK COORDINATES TRANSLATED TO 1:1 SCALE (used when saving new added marks)
513        markGetDefaultCoords : function(markX, markY, markWidth, markHeight, mapScale){
514            markX       = parseFloat(markX);
515            markY       = parseFloat(markY);
516            markWidth   = parseFloat(markWidth);
517            markHeight  = parseFloat(markHeight);
518            markX       = parseFloat(markX + markWidth/(2*mapScale) - markWidth/2).toFixed(2);
519            markY       = parseFloat(markY + markHeight/mapScale - markHeight).toFixed(2);
520            return [markX, markY];
521        },
522        // MARK MOVE & EDIT HANDLERS
523        markMoveStart : function(){
524            // storing original coordinates
525            this.data('ox', parseFloat(this.attr('x')));
526            this.data('oy', parseFloat(this.attr('y')));
527        },
528        markMove : function (dx, dy) {
529            dx = dx/_data.scale;
530            dy = dy/_data.scale;
531            this.attr({x: this.data('ox') + dx, y: this.data('oy') + dy});
532        },
533        markMoveEnd : function () {
534            // if coordinates are same then it was a "click" and we should start editing
535            if(this.data('ox') == this.attr('x') && this.data('oy') == this.attr('y')){
536               options.marksEditHandler.call(this);
537            }
538        },
539        panStart : function (e){
540
541
542                if(e.target.id == 'btnZoomIn' || e.target.id == 'btnZoomOut')
543                    return false;
544
545                if(_data.options.editMode && e.target.nodeName == "image")
546                    return false;
547
548                e.preventDefault();
549                var ce = e.touches && e.touches[0] ? e.touches[0] : e;
550
551                _data.pan = {};
552
553                // initial viewbox when panning started
554                _data.pan.vxi = _data.viewBox[0];
555                _data.pan.vyi = _data.viewBox[1];
556                // mouse coordinates when panning started
557                _data.pan.x  = ce.clientX;
558                _data.pan.y  = ce.clientY;
559                // mouse delta
560                _data.pan.dx = 0;
561                _data.pan.dy = 0;
562                // new viewbox x/y
563                _data.pan.vx = 0;
564                _data.pan.vy = 0;
565
566                if(!touchDevice)
567                    $('body').on('mousemove', _this.panMove).on('mouseup', _this.panEnd);
568        },
569        panMove :  function (e){
570
571                e.preventDefault();
572
573                _data.isPanning = true;
574
575                _data.RMap.attr({'cursor': 'move'});
576                $('body').css({'cursor': 'move'});
577
578                var ce = e.touches && e.touches[0] ? e.touches[0] : e;
579
580                // delta x/y
581                _data.pan.dx = (_data.pan.x - ce.clientX);
582                _data.pan.dy = (_data.pan.y - ce.clientY);
583
584                // new viewBox x/y
585                var vx = parseInt(_data.pan.vxi + _data.pan.dx /_data.scale);
586                var vy = parseInt(_data.pan.vyi + _data.pan.dy /_data.scale);
587
588                // Limit pan to map's boundaries
589                if(_data.options.panLimit){
590                    if(vx < _data.svgDefault.viewBox[0])
591                        vx = _data.svgDefault.viewBox[0];
592                    else if(_data.viewBox[2] + vx > _data.svgDefault.viewBox[2])
593                        vx = _data.svgDefault.viewBox[2]-_data.viewBox[2];
594
595                    if(vy < _data.svgDefault.viewBox[1])
596                        vy = _data.svgDefault.viewBox[1];
597                    else if(_data.viewBox[3] + vy > _data.svgDefault.viewBox[3])
598                        vy = _data.svgDefault.viewBox[3]-_data.viewBox[3];
599                }
600
601                _data.pan.vx = vx;
602                _data.pan.vy = vy;
603
604
605                // set new viewBox
606                _this.setViewBox([_data.pan.vx,  _data.pan.vy, _data.viewBox[2], _data.viewBox[3]]);
607                //_data.$map.css({'-webkit-transform' : 'translate('+vx+'px,'+vy+'px'});
608
609        },
610        panEnd : function (e){
611
612                _data.isPanning = false;
613
614                // call regionClickHandler if mouse did not move more than 5 pixels
615                if (Math.abs(_data.pan.dx)<5 && Math.abs(_data.pan.dy)<5){
616                    if(_data.options.editMode)
617                        _this.markAddClickHandler(e);
618                    if(_data.region_clicked)
619                    _this.regionClickHandler(e, _data.region_clicked);
620                }
621
622
623                $('body').css({'cursor': 'default'});
624                _data.RMap.attr({'cursor': _data.options.cursor});
625
626                _data.viewBox[0] = _data.pan.vx || _data.viewBox[0];
627                _data.viewBox[1] = _data.pan.vy || _data.viewBox[1] ;
628
629                if(!touchDevice)
630                    $('body').off('mousemove', _this.panMove).off('mouseup', _this.panEnd);
631        },
632        // REMEMBER WHICH REGION WAS CLICKED BEFORE START PANNING
633        panRegionClickHandler : function (e, region) {
634                _data.region_clicked = region;
635        },
636        touchStart : function (e){
637            e.preventDefault();
638            if(_data.options.zoom && e.touches && e.touches.length == 2){
639                _data.touchZoomStartViewBox = _data.viewBox;
640                _data.touchZoomStart =  _data.scale;
641                _data.touchZoomEnd   =  1;
642            }else{
643                _this.panStart(e);
644                _data.isPanning = true;
645            }
646        },
647        touchMove : function (e){
648            e.preventDefault();
649            if(_data.options.zoom && e.touches && e.touches.length >= 2){
650                _this.zoom(null, e.scale);
651                _data.isPanning = false;
652            }else if(_data.isPanning){
653                _this.panMove(e);
654            }
655        },
656        touchEnd : function (e){
657            e.preventDefault();
658                if(_data.touchZoomStart){
659                   _data.touchZoomStart  = false;
660                   _data.touchZoomEnd    = false;
661                }else if(_data.isPanning){
662                    _this.panEnd(e);
663                }
664        },
665        marksHide : function(){
666            _data.RMarks.hide();
667        },
668        marksShow : function(){
669            _data.RMarks.show();
670        },
671        // GET ALL MARKS
672        marksGet : function(){
673            var _marks = [];
674            $.each(_data.RMarks, function(i, m){
675                    if(m.attrs){
676                    // If mark exist
677                        var attrs = $.extend({},m.attrs);
678                        /*
679                        if(!m.data('placed')){
680                            var xy = _this.markGetDefaultCoords(m.attrs.x, m.attrs.y, m.data('width'), m.data('height'), _data.scale);
681                            attrs.x = xy[0];
682                            attrs.y = xy[1];
683                        }
684                        */
685
686                        if(m.data('href'))
687                            attrs.href = m.data('href');
688
689                        _marks.push({
690                            attrs:    attrs,
691                            tooltip:  m.data('tooltip'),
692                            popover:  m.data('popover'),
693                            width:    m.data('width'),
694                            height:   m.data('height'),
695                            href:     m.data('href')
696                            //placed:   true
697                        });
698                    }
699            });
700            return _marks;
701        },
702        // GET SELECTED REGION OR ARRAY OF SELECTED REGIONS
703        getSelected : function(){
704            return _data.selected_id;
705        },
706        // SELECT REGION
707        selectRegion :    function(id){
708                var region = _data.R.getById(id);
709                if(!region || region.disabled) return false;
710                
711                if(_data.options.multiSelect){
712                // if multi select is ON
713                    var i = $.inArray(id, _data.selected_id);
714
715                    if(i >= 0){
716                    // if selected, deselect
717                        region.attr({'fill' : region.default_attr.fill});
718                        _data.selected_id.splice(i,1);
719                        return;
720                    }else{
721                    // select
722                        _data.selected_id.push(id);
723                    }
724                }else{
725                // single select
726                    if(_data.selected_id){
727                        var selectedRegion = _data.R.getById(_data.selected_id);
728                        selectedRegion.attr(selectedRegion.default_attr);
729                                                if(_browser.ie && !_browser.ie.old)
730                            _this.mapAdjustStrokes();
731                    }
732                    _data.selected_id = id;
733                }
734                
735                region.attr(region.selected_attr);
736        },
737        // UNHIGHLIGHT REGION
738        unhighlightRegion :   function(id){
739                var region = _data.R.getById(id);
740                if(region.disabled
741                   || (_data.options.multiSelect && $.inArray(id,_data.selected_id)>=0)
742                   || _data.selected_id == id
743                   ) return false;
744
745                region.attr({'fill' : region.default_attr.fill});
746        },
747        // HIGHLIGHT REGION
748        highlightRegion : function(id){
749                var region = _data.R.getById(id);
750                if(_data.isPanning
751                    || region.disabled
752                    || (_data.options.multiSelect && $.inArray(id,_data.selected_id)>=0)
753                    || _data.selected_id == id
754                   )
755                    return false;
756
757                region.attr(region.hover_attr);
758        },
759        // CONVERT LAT/LON TO X/Y (works only with world_high.svg map!)
760        ll2px : function(mark){
761
762                var latlng = mark.c;
763
764                var lat = parseFloat(latlng[0]);
765                var lng = parseFloat(latlng[1]);
766
767                var czoom = 2;
768
769                var cbk = CBK[czoom];
770                //var scale = options.width/1024;
771                var scale_ = 1;
772
773                var x = Math.round(cbk + (lng * CEK[czoom]));
774
775                var foo = Math.sin(lat * 3.14159 / 180)
776                if (foo < -0.9999)
777                    foo = -0.9999;
778                else if (foo > 0.9999)
779                    foo = 0.9999;
780
781                var y = Math.round(cbk + (0.5 * Math.log((1+foo)/(1-foo)) * (-CFK[czoom])));
782
783                var coordsXY  = [x-(33.8+(mark.width/2)), y-(141.7+mark.height)];
784
785                return coordsXY;
786       },
787       // CHECK IF REGION IS DISABLED
788       isRegionDisabled : function (name, svgfill){
789           
790            if(_data.options.regions[name] && (_data.options.regions[name].disabled || svgfill == 'none') ){
791                return true;
792            }else if(
793               (_data.options.regions[name] == undefined || _this.parseBoolean(_data.options.regions[name].disabled)) &&
794               (_data.options.disableAll || svgfill == 'none' || name == 'labels' || name == 'Labels')
795
796            ){
797                return true;
798            }else{
799                return false;
800            }
801       },
802       regionClickHandler : function(e, region){
803
804            if(!region) return false;
805
806            _data.region_clicked = null;
807            _this.selectRegion(region.name);
808
809            _this.showPopover(e, region.popover);
810
811            if(_data.options.onClick)
812                return _data.options.onClick.call(region, e, _this);
813
814            if(touchDevice && region.attrs.href)
815                window.location.href = region.attrs.href;
816
817       },
818       renderSVGPath : function (item, parentTransform, parentStyle){
819        
820          var path = _data.R.path($(item).attr('d'));          
821          var rObj = _this.initRaphaelObject( path, item, parentTransform, parentStyle);
822
823          _this.regionAdd(rObj);
824       },
825       renderSVGImage: function (item, parentTransform, parentStyle){
826
827          var src = $(item).attr('xlink:href'),
828              x   = $(item).attr('x') || 0,
829              y   = $(item).attr('y') || 0,
830              w   = $(item).attr('width') || 0,
831              h   = $(item).attr('height') || 0;
832          
833          if (!_this.fileExists(src))
834            return false;
835             
836          var rObj = _data.R.image(src, x, y, w, h)
837         _this.initRaphaelObject( rObj, item, parentTransform, parentStyle );
838          return rObj;
839       },
840       renderSVGPolygon : function (item, parentTransform, parentStyle){
841          //var points = item.getAttribute('points').trim().replace(/ +(?= )/g,'').split(/\s+|,/);
842          var points = item.attr('points').trim().replace(/ +(?= )/g,'').split(/\s+|,/);
843          var x0 = points.shift(),
844              y0 = points.shift();
845          var pathdata = 'M'+x0+','+y0+' L'+points.join(' ')+'z';
846          var rObj = _this.initRaphaelObject( _data.R.path(pathdata), item, parentTransform, parentStyle);
847          _this.regionAdd(rObj);
848          return rObj;          
849       },
850       renderSVGPolyline : function (item, parentTransform, parentStyle){
851          //var points = item.getAttribute('points').trim().replace(/ +(?= )/g,'').split(/\s+|,/);
852          var points = item.attr('points').trim().replace(/ +(?= )/g,'').split(/\s+|,/);
853          var x0 = points.shift(),
854              y0 = points.shift();
855          var pathdata = 'M'+x0+','+y0+' L'+points.join(' ');
856          var rObj = _this.initRaphaelObject( _data.R.path(pathdata), item, parentTransform, parentStyle);
857          return rObj;          
858       },
859       renderSVGCircle: function (item, parentTransform, parentStyle){
860          var x   = $(item).attr('cx') || 0,
861              y   = $(item).attr('cy') || 0;
862              r   = $(item).attr('r')  || 0;
863          var rObj = _this.initRaphaelObject( _data.R.circle(x,y,r), item, parentTransform, parentStyle);
864
865          _this.regionAdd(rObj);
866          return rObj;          
867       },
868       renderSVGEllipse: function (item, parentTransform, parentStyle){
869          var x   = $(item).attr('cx') || 0,
870              y   = $(item).attr('cy') || 0;
871              rx  = $(item).attr('rx')  || 0;
872              ry  = $(item).attr('ry')  || 0;
873          var rObj = _this.initRaphaelObject( _data.R.ellipse(x,y,rx,ry), item, parentTransform, parentStyle);
874          _this.regionAdd(rObj);
875          return rObj;          
876       },
877       renderSVGRect: function (item, parentTransform, parentStyle){
878          var x   = $(item).attr('x') || 0,
879              y   = $(item).attr('y') || 0,
880              w   = $(item).attr('width') || 0,
881              h   = $(item).attr('height') || 0;
882              r   = $(item).attr('rx') || $(item).attr('ry') || 0;
883          var rObj = _this.initRaphaelObject( _data.R.rect(x,y,w,h,r), item, parentTransform, parentStyle);
884          _this.regionAdd(rObj);
885          return rObj;          
886       },
887       renderSVGText : function (textObj){
888
889            var tspans = $(textObj).find('tspan');
890
891            var x = parseFloat($(textObj).attr('x')) || 0;
892            var y = parseFloat($(textObj).attr('y')) || 0;
893
894            tspans.each(function(i,tspan){
895                var t = _this.renderSVGTspan($(tspan), {x: x, y: y});
896                
897                t.attr(_this.styleSVG2Raphael(textObj));
898                t.attr(_this.styleSVG2Raphael($(tspan)));
899                
900                t.transform( _this.transformSVG2Raphael(textObj) );
901                t.transform( _this.transformSVG2Raphael($(tspan)));
902                                
903            });
904
905            if(tspans.length == 0){
906                var t = _this.renderSVGTspan(textObj);
907                t.attr(_this.styleSVG2Raphael(textObj));
908                t.transform( _this.transformSVG2Raphael(textObj) );
909            }
910            
911          return t;
912       },
913       renderSVGTspan : function (textObj, parent){
914        
915            parent = parent || {x: 0, y: 0};
916
917            var x = parseFloat($(textObj).attr('x')) || parent.x;
918            var y = parseFloat($(textObj).attr('y')) || parent.y;
919
920            if($(textObj).attr('dx'))
921                x += parent.x + $(textObj).attr('dx');
922            if($(textObj).attr('dy'))
923                y += parent.y + $(textObj).attr('dy');
924
925            text = $(textObj).text();
926            
927
928            var rObj = _data.R.text(x, y, text).attr({'text-anchor': 'start'}).toFront();
929
930            rObj.mapsvg_type = 'text';
931
932            $(rObj.node).css({
933            	"-webkit-touch-callout": "none",
934            	"-webkit-user-select": "none",
935                'pointer-events': 'none'
936            });
937          return rObj;            
938       },
939       initRaphaelObject : function (rObj, svgItem, parentTransform, parentStyle){
940  
941          var _parentStyle        = parentStyle || {};
942          var _parentTransform    = parentTransform || '';
943           
944          rObj.id            = $(svgItem).attr('id') || rObj.type+(globalID++);
945          rObj.node.id       = rObj.id;
946          rObj.name          = rObj.id;
947          
948          var style = _this.styleSVG2Raphael(svgItem, parentStyle);          
949          rObj.attr(style);
950          
951          var transform = _this.transformSVG2Raphael(svgItem) + _parentTransform;
952          rObj.transform(transform);
953          
954          return rObj;
955       },
956       styleSVG2Raphael : function(svgItem, parentStyle){
957            var parentStyle = parentStyle || {};
958            var style       = {};
959            var attrs       = $(svgItem).get(0).attributes;
960            var style_attrs = ["fill","fill-opacity","opacity", "font","font-name","font-family","font-size","font-weight","stroke","stroke-lincap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width"];
961
962            if($(svgItem).attr('style')){
963                var _style = $(svgItem).attr('style').split(';');
964                    $.each(_style, function(i, val){
965                        
966                        var p = val.split(':');
967                        p[0] = p[0].trim();
968                        if(p[1])
969                            p[1] = p[1].trim();
970                        if(p[0]=='font-size')
971                            p[1] = parseInt(p[1].replace('px',''));
972                        if(_this.isNumber(p[0]))
973                            p[1] = parseFloat(p[1]);                        
974                        style[p[0]] = p[1];
975                    });
976            }
977
978            if(attrs)    
979            $.each(attrs, function(i,attr){
980               if ($.inArray(attr.name, style_attrs) > -1){
981                    if(attr.name=='font-size'){
982                        attr.value = parseInt(attr.value.replace('px',''));
983                    }
984                    style[attr.name] = attr.value;
985               }
986            });
987
988            if(style['font-size'])
989                style['font-size'] = parseInt(style['font-size']);
990            
991            
992            if(style['font-family'])
993                style['font-family'] = style['font-family']+', Arial';
994            
995            
996            // Combine with parent styles
997            var final_style = $.extend({}, parentStyle, style); 
998
999            if(final_style['stroke']==undefined && final_style['fill']==undefined){                
1000                final_style['stroke'] = 'none';
1001                //final_style['fill'] = "#000000";
1002                final_style['fill'] = "none"                
1003            }else if (final_style['stroke']==undefined){
1004                final_style['stroke'] = 'none';
1005            }else if(final_style['fill']==undefined){
1006                final_style['fill'] = 'none';
1007            }
1008            
1009            return final_style;
1010       },
1011       transformSVG2Raphael : function(svgItem){
1012        
1013            var _transform = $(svgItem).attr('transform');
1014            var m;
1015
1016            if(_transform){
1017
1018                var tparts = _transform.split(')');
1019                var rtransform = [];
1020
1021                for (t in tparts){
1022                    if(tparts[t] != ""){
1023                        var kv = tparts[t].split('(');
1024
1025                        if (kv[0]!='matrix'){
1026                            kv[0] = kv[0].slice(0,1).toLowerCase();
1027                            rtransform.push(kv[0]+kv[1]);
1028                        }else{
1029                            
1030                            if( kv[1].indexOf(",") != -1 )
1031                                m = kv[1].split(',');
1032                            else
1033                                m = kv[1].split(' ');
1034                                                                   
1035                            var transform_string = Raphael.matrix(parseFloat(m[0]),parseFloat(m[1]),parseFloat(m[2]),parseFloat(m[3]),parseFloat(m[4]),parseFloat(m[5])).toTransformString();                            
1036                            rtransform.push(transform_string);
1037                        }
1038                    }
1039                }
1040
1041                return rtransform.join();
1042            }
1043            return '';        
1044       },
1045       // GET ELEMENT'S STYLES (fill, strokes etc..)
1046       getElementStyles : function (elem){
1047            if(!_browser.ie){
1048                return elem.style;
1049            }else{
1050                var styles = {};
1051                styles.getPropertyValue = function(v){
1052                    return styles[v] || undefined;
1053                };
1054                if($(elem).attr('style')){
1055                    var def_styles = $(elem).attr('style').split(';');
1056                    $.each(def_styles, function(i, val){
1057                        var p = val.split(':');
1058                        styles[p[0]] = p[1];
1059                    });
1060                }
1061                return styles;
1062            }
1063       },
1064       fileExists : function(url){
1065            if(url.substr(0,4)=="data") 
1066                return true;
1067            var http = new XMLHttpRequest();
1068            http.open('HEAD', url, false);
1069            http.send();
1070            return http.status!=404;
1071       },
1072       // ADD REGION (PARSE SVG DATA)
1073       regionAdd : function (_item){
1074
1075            var name                      = _item.name;
1076
1077            _item.disabled      = _this.isRegionDisabled(name, _item.attr('fill'));
1078            _item.default_attr  = {};
1079
1080            _item.disabled && console.log(_data.options.colors.disabled);
1081            _item.default_attr['fill']     = _item.disabled && _data.options.colors.disabled ? _data.options.colors.disabled : (_item.attr('fill') || 'none');
1082
1083            if(_item.default_attr['fill'] && _item.default_attr['fill'] != 'none' && _data.options.colors.base && !_item.disabled)
1084                _item.default_attr['fill'] = _data.options.colors.base;
1085
1086            if(_item.attr('stroke'))
1087                _item.default_attr['stroke'] = _item.attr('stroke');
1088
1089                
1090            if(_item.attr('stroke-width'))
1091                _item.default_attr['stroke-width'] = parseFloat(_item.attr('stroke-width'));
1092
1093            if(_item.default_attr['stroke'] && _item.default_attr['stroke'] != 'none' && _data.options.colors.stroke)
1094                    _item.default_attr['stroke'] = _data.options.colors.stroke;
1095                    
1096            if(_item.default_attr['stroke-width'] && _data.options.strokeWidth)
1097                    _item.default_attr['stroke-width'] = parseFloat(_data.options.strokeWidth);
1098
1099            _item.selected_attr = {};
1100            _item.hover_attr = {};
1101
1102            // Set cursor
1103            if(_item.disabled){
1104                _item.default_attr.cursor = 'default';
1105                $(_item.node).css({'pointer-events' :'none'});
1106            }else{
1107                _item.default_attr.cursor = _data.options.cursor;
1108            }
1109
1110            if(_data.options.regions[name]){
1111                // Set attributes (colors, href, etc..)
1112                if(_data.options.regions[name].attr)
1113                    _item.default_attr = $.extend(true, {}, _item.default_attr, _data.options.regions[name].attr);
1114                // Set tooltip
1115                if(_data.options.regions[name].tooltip)
1116                    _item.tooltip = _data.options.regions[name].tooltip;
1117                // Set popover
1118                if(_data.options.regions[name].popover)
1119                    _item.popover = _data.options.regions[name].popover;
1120                // Add custom data
1121                if(_data.options.regions[name].data){
1122                    if(typeof _data.options.regions[name].data == 'string'){
1123                            if(_data.options.regions[name].data.substr(0,1)=='[' || _data.options.regions[name].data.substr(0,1)=='{'){
1124                                try{           
1125                                    var tmp;
1126                                    eval('tmp = '+_data.options.regions[name].data);
1127                                    _item._data = tmp;        
1128                                }catch(err){
1129                                    _item._data = _data.options.regions[name].data;
1130                                }                                                            
1131                            }else{
1132                                _item._data = _data.options.regions[name].data;
1133                            }
1134                    }else{
1135                        _item._data = _data.options.regions[name].data;                        
1136                    }                   
1137                }
1138            }
1139
1140            if(_this.isNumber(_data.options.colors.selected))                
1141                _item.selected_attr['fill'] = _this.lighten(_item.default_attr.fill, parseFloat(_data.options.colors.selected));
1142            else
1143                _item.selected_attr['fill'] = _data.options.colors.selected;
1144
1145            if(_this.isNumber(_data.options.colors.hover))
1146                _item.hover_attr['fill'] = _this.lighten(_item.default_attr.fill, parseFloat(_data.options.colors.hover));                
1147            else
1148                _item.hover_attr['fill'] = _data.options.colors.hover;
1149
1150            // If stroke is dashed, convert it to simple: - - - - -
1151            var dash = _item.attr('stroke-dasharray');
1152            if( dash && dash!='none')
1153                _item.default_attr['stroke-dasharray'] = '--';
1154
1155            _item.attr(_item.default_attr);
1156
1157            // Make stroke-width always the same:
1158            if(!_browser.ie && !_browser.firefox)
1159                $(_item.node).css({'vector-effect' : 'non-scaling-stroke'});
1160
1161            // Add region to Raphael.set()
1162            _data.RMap.push(_item);
1163
1164            // Should we select the region now?
1165            if(_data.options.regions[name] && _data.options.regions[name].selected)
1166                _this.selectRegion(name);
1167        },
1168
1169        /** Lighten / Darken color
1170         *  Taken from http://stackoverflow.com/questions/801406/c-create-a-lighter-darker-color-based-on-a-system-color/801463#801463
1171         */
1172
1173        lighten2: function(hexColor, factor){
1174                var h = (hexColor.charAt(0)=="#") ? hexColor.substring(1,7) : hexColor;
1175                var hsb = Raphael.rgb2hsb(parseInt(h.substring(0,2),16), parseInt(h.substring(2,4),16),parseInt(h.substring(4,6),16));
1176                hsb.b += .1;
1177                return Raphael.hsb(hsb);
1178        },
1179        lighten: function ( hexColor, delta ){
1180
1181            if(!hexColor) return false;
1182
1183            delta = parseInt(delta)*0.008;
1184
1185            var rgb = Raphael.getRGB(hexColor);
1186            var hsb = Raphael.rgb2hsb(rgb.r, rgb.g, rgb.b);
1187
1188            var b   = hsb.b + delta;
1189
1190            if(b >= 1){
1191                b = 1;
1192                hsb.s = hsb.s - delta*1.5;
1193            }else if (b <= 0){
1194                b = 0;
1195            }
1196
1197            var new_rgb = Raphael.hsb2rgb(hsb.h, hsb.s, b);
1198
1199            return new_rgb.hex;
1200
1201        },
1202        setPan : function(on){
1203            if(on){
1204                _data.options.pan = true;
1205                _data.$map.on('mousedown', _this.panStart);
1206            }else{
1207                if(_data.options.pan)
1208                  _data.$map.off('mousedown', _this.panStart);
1209                _data.options.pan = false;
1210            }
1211        },
1212        markAddClickHandler : function(e){
1213            // Don't add marker if marker was clicked
1214            if($(e.target).is('image')) return false;
1215            var x = e.offsetX == undefined ? e.layerX : e.offsetX;
1216            var y = e.offsetY == undefined ? e.layerY : e.offsetY;
1217            _this.markAdd({xy: [x, y]}, true);
1218        },
1219        markEventHandlersSet : function(on, mark){
1220
1221            on = _this.parseBoolean(on);
1222
1223            if(on){
1224                if(_data.options.editMode === false)
1225                    mark.unhover();
1226                mark.drag(_this.markMove, _this.markMoveStart, _this.markMoveEnd);
1227
1228            }else{
1229                if(_data.options.editMode)
1230                    mark.undrag();
1231
1232                mark.hover(
1233                     function(){
1234                        if(this.data('tooltip')){
1235                            _data.mapTip.html( this.data('tooltip') );
1236                            _data.mapTip.show();
1237                        }
1238                     },
1239                     function(){
1240                        if(this.data('tooltip'))
1241                            _data.mapTip.hide();
1242                });
1243
1244            }
1245        },
1246        setMarksEditMode : function(on, mark){
1247
1248            on = _this.parseBoolean(on);
1249
1250            /*
1251            if(on){
1252                _data.$map.on('click',_this.markAddClickHandler);
1253            }else{
1254                _data.$map.off('click',_this.markAddClickHandler);
1255            }
1256            */
1257
1258            _data.options.editMode = on;
1259        },
1260        setZoom : function (on){
1261            if(on){
1262                _data.options.zoom = true;
1263                _data.$map.bind('mousewheel.mapsvg',function(event, delta, deltaX, deltaY) {
1264                    var d = delta > 0 ? 1 : -1;
1265                    _this.zoom(d);
1266                    return false;
1267                });
1268
1269                // Add zoom buttons
1270                if(_data.options.zoomButtons.show){
1271
1272                    var buttons = $('<div></div>');
1273
1274                    var cssBtn = {'border-radius': '3px', 'display': 'block', 'margin-bottom': '7px'};
1275
1276                    var btnZoomIn = $('<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABhElEQVR4nJWTT4rqQBDGf92pSEJWmYfgQpABb+EB1NU8DyBe5M1q5iKStTCDd/AWggElC3EQJAQxbb/NJDH+mccraEh31fdVfR8pBRBF0Uuapn+AX8CZn0MDuyAI3sfj8aeaTqcvWZZ9XFdZazmdTgC4rotS6oYpCILfkmXZ6yNwt9tFKcVyucRxnBuSNE1fNfB0TWCModlsMhwOGQwGdDod8jy/J+dJP9JsjKl9W2vvlZ3lcuyiS57ntY7FvZDgum6Zk0vN7XYbay3GGMIwLItarRbGGEQErTVxHON5XkVQAEaj0b0x6fV6tXsURRwOBxzHQd9F/CPO58o2ARARdrsds9ms9CIMQ/r9PgCLxYL1eo3rulhr2e/3dQkAnueRJElp2vF4LLskScJmsynNK8A1AqjcVUohUqVEBBGpuV+E/j63CV093/sLizIBvoDny1fHcdhut8znc5RSrFar2kQX8aV933+7ZldK0Wg0iOO4BD9YpjcF8L2R/7XOvu+/TyaTz79+UqnWsVHWHAAAAABJRU5ErkJggg==" id="btnZoomIn"/>').on('click', function(e){
1277                        e.stopPropagation();
1278                        _this.zoomIn();
1279                    }).css(cssBtn);
1280
1281                    var btnZoomOut = $('<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA6klEQVR4nKWTPW6DQBBG3w4RaLXSFs4puAe9fQHEReLKPgYN4gLxQei5RNytFraANNEKKwk29uum+N78SKMA2rbdO+c+gHdgYh0Bvowx57IsL6ppmr33/vNO6E+MMQfx3h+fCQM4544C7J4VADvh/s5rTG/LKoTANK37RIQ0TWMdBSEE8jwnyzLmef437L2n7/soiQLnHEVRPDR313VRIA8lVogTWGup6/pmhSRJAFBKxcAwDFhrfwuSJCGEwDiOqx2VUlF8I1h23ILw2h1EgOsLgqtorU/LI23BGHNSAD8fuemdtdbnqqou39SbTK6RdYDsAAAAAElFTkSuQmCC" id="btnZoomOut"/>').on('click', function(e){
1282                        e.stopPropagation();
1283                        _this.zoomOut();
1284                    }).css(cssBtn);
1285
1286                    buttons.append(btnZoomOut).append(btnZoomIn).css({position: 'absolute', top: '15px', width: '16px', cursor: 'pointer'});
1287
1288                    if(_data.options.zoomButtons.location == 'right')
1289                        buttons.css({'right': '15px'});
1290                    else if(_data.options.zoomButtons.location == 'left')
1291                        buttons.css({'left': '15px'});
1292
1293                    _data.zoomButtons = buttons;
1294
1295                    _data.$map.append(_data.zoomButtons);
1296                }
1297
1298            }else{
1299                if(_data.options.zoom)
1300                    _data.$map.unbind('mousewheel.mapsvg');
1301                if(_data.zoomButtons)
1302                    _data.zoomButtons.hide();
1303                _data.options.zoom = false;
1304            }
1305        },
1306        setSize : function( width, height, responsive ){
1307
1308            // Convert strings to numbers
1309            _data.options.width      = parseInt(width);
1310            _data.options.height     = parseInt(height);
1311            _data.options.responsive = _this.parseBoolean(responsive);
1312
1313            // Calculate width and height
1314            if ((!_data.options.width && !_data.options.height)){
1315                _data.options.width	 = _data.svgDefault.width;
1316                _data.options.height = _data.svgDefault.height;
1317            }else if (!_data.options.width && _data.options.height){
1318            	_data.options.width	 = parseInt(_data.options.height * _data.svgDefault.width / _data.svgDefault.height);
1319            }else if (_data.options.width && !_data.options.height){
1320            	_data.options.height = parseInt(_data.options.width * _data.svgDefault.height/_data.svgDefault.width);
1321            }
1322
1323            if(_data.options.responsive){
1324                var maxWidth  = _data.options.width;
1325                var maxHeight = _data.options.height;
1326                _data.options.width	 = _data.svgDefault.width;
1327                _data.options.height = _data.svgDefault.height;
1328            }
1329
1330            _data.whRatio      = _data.options.width / _data.options.height;
1331            _data.scale        = _this.getScale();
1332
1333            if(_data.options.responsive){
1334
1335                _data.$map.css({
1336                    'max-width': maxWidth+'px',
1337                    'max-height': maxHeight+'px',
1338                    'width': 'auto',
1339                    'height': 'auto',
1340                    'position': 'relative'
1341                }).height(_data.$map.width()  / _data.whRatio);
1342
1343                $(window).bind('resize.mapsvg', function(){
1344                    _data.$map.height(_data.$map.width() / _data.whRatio);
1345                });
1346            }else{
1347                _data.$map.css({
1348                    'width': _data.options.width+'px',
1349                    'height': _data.options.height+'px',
1350                    'max-width': 'none',
1351                    'max-height': 'none',
1352                    'position': 'relative'
1353                });
1354                $(window).unbind('resize.mapsvg');
1355            }
1356
1357            if(!_data.options.responsive && _data.R)
1358                _data.R.setSize(_data.options.width, _data.options.height);
1359
1360            return [_data.options.width, _data.options.height];
1361
1362
1363        },
1364        // Adding marks
1365        setMarks : function (marksArr){
1366            if(marksArr){
1367                $.each(marksArr, function(i, mark){
1368                        _this.markAdd(mark);
1369                });
1370            }
1371        },
1372
1373        // Show tooltip (this function will be defined later in setTooltip method)
1374        showTip : function(){},
1375        showPopover : function(){},
1376        // Hide tooltip
1377        hideTip : function (){
1378            _data.mapTip.hide();
1379            _data.mapTip.html('');
1380        },
1381        // Set tooltip behaviour
1382        setTooltip : function (mode){
1383
1384            // Add tooltip container
1385            _data.mapTip = $('<div class="map_tooltip"></div>');
1386            $("body").append(_data.mapTip);
1387
1388            _data.mapTip.css({
1389               'font-weight': 'normal',
1390               'font-size' : '12px',
1391               'color': '#000000',
1392               'position': 'absolute',
1393               'border-radius' : '4px',
1394               '-moz-border-radius' : '4px',
1395               '-webkit-border-radius' : '4px',
1396               'top': '0',
1397               'left': '0',
1398               'z-index': '1000',
1399               'display': 'none',
1400               'background-color': 'white',
1401               'border': '1px solid #eee',
1402               'padding': '4px 7px',
1403               'max-width': '600px'
1404            });
1405
1406            if(_data.options.tooltips.show == 'hover'){
1407                _data.$map.mousemove(function(e) {
1408                    _data.mapTip.css('left', e.clientX + $(window).scrollLeft()).css('top', e.clientY + $(window).scrollTop() + 30);
1409                });
1410            }
1411
1412            _this.showTip = (_data.options.tooltipsMode == 'custom' ?
1413                function (name){
1414                    var obj = _data.R.getById(name);
1415                    if(obj.tooltip){
1416                        _data.mapTip.html(obj.tooltip);
1417                        _data.mapTip.show();
1418                    }
1419                }: _data.options.tooltipsMode == 'names' ?
1420                function (name){
1421                    var obj = _data.R.getById(name);
1422                    if(obj.disabled) return false;
1423                    _data.mapTip.html(name.replace(/_/g, ' '));
1424                    _data.mapTip.show();
1425                }: _data.options.tooltipsMode == 'combined' ?
1426                function (name){
1427                    var obj = _data.R.getById(name);                    
1428                    if(obj.tooltip){
1429                        _data.mapTip.html(obj.tooltip);
1430                        _data.mapTip.show();
1431                    }else{
1432                        if(obj.disabled) return false;
1433                        _data.mapTip.html(name.replace(/_/g, ' '));
1434                        _data.mapTip.show();
1435                    }
1436                }: function(name){null;}
1437            );
1438
1439        },
1440        // Set popover behaviour
1441        setPopover : function (on){
1442
1443            if(!on) return false;
1444
1445            // Add tooltip container
1446            $("body").prepend('<div class="map_popover"><div class="map_popover_content"></div><div class="map_popover_close">x</div></div>');
1447
1448            _data.mapPopover = $('.map_popover');
1449
1450            var popoverClose = _data.mapPopover.find('.map_popover_close');
1451
1452
1453            _data.mapPopover.css({
1454               'font-weight': 'normal',
1455               'font-size' : '12px',
1456               'color': '#000000',
1457               'position': 'absolute',
1458               'border-radius' : '4px',
1459               '-moz-border-radius' : '4px',
1460               '-webkit-border-radius' : '4px',
1461               'top': '0',
1462               'left': '0',
1463               'z-index': '1000',
1464               'width': _data.options.popover.width+(_data.options.popover.width=='auto'? '': 'px'),
1465               'height': _data.options.popover.height+(_data.options.popover.height=='auto'? '': 'px'),
1466               'display': 'none',
1467               'background-color': 'white',
1468               'border': '1px solid #ccc',
1469               'padding': '12px',
1470               '-webkit-box-shadow': '5px 5px 5px 0px rgba(0, 0, 0, 0.2)',
1471               'box-shadow': '5px 5px 5px 0px rgba(0, 0, 0, 0.2)'
1472
1473            });
1474
1475            popoverClose.css({
1476                'position': 'absolute',
1477                'top': '0',
1478                'right' : '5px',
1479                'cursor': 'pointer',
1480                'color': '#aaa',
1481                'z-index' : '1200'
1482
1483            });
1484
1485            _this.showPopover = function (e, content, pos){
1486
1487
1488                                    if (!pos || pos.length != 2){
1489                                        var m   = mouseCoords(e);
1490                                        var pos = [m.x, m.y];
1491                                    }else{
1492                                        var scale = _this.getScale();
1493                                        pos[0] = _data.$map.offset().left  + pos[0]*scale;
1494                                        pos[1] = _data.$map.offset().top + pos[1]*scale;
1495                                    }
1496
1497                                    if(content){
1498                                        _data.mapPopover.find('.map_popover_content').html(content);
1499                                        var nx = pos[0] - _data.mapPopover.outerWidth(false)/2;
1500                                        var ny = pos[1] - _data.mapPopover.outerHeight(false) - 7;
1501                                        if(nx<0) nx = 0;
1502                                        if(ny<0) ny = 0;
1503
1504                                        if(nx+_data.mapPopover.outerWidth(false) > $(window).scrollLeft() + $(window).width()) nx = ($(window).scrollLeft() + $(window).width()) - _data.mapPopover.outerWidth(false);
1505                                        if(ny+_data.mapPopover.outerHeight(false) > $(window).scrollTop() + $(window).height()) ny = ($(window).scrollTop() + $(window).height()) - _data.mapPopover.outerHeight(false);
1506                                        if(nx < $(window).scrollLeft()) nx = $(window).scrollLeft();
1507                                        if(ny < $(window).scrollTop()) ny = $(window).scrollTop();
1508
1509                                        _data.mapPopover.css('left', nx).css('top', ny);
1510                                        _data.mapPopover.show()
1511                                    }else{
1512                                        _this.hidePopover();
1513                                    }                                    
1514            };
1515            
1516            _this.hidePopover = function(){
1517                _data.mapPopover.find('.map_popover_content').html('');
1518                _data.mapPopover.hide(0,function(){
1519                    $('body').off('mousedown', _this.popoverOffHandler);
1520                    if(_data.options.onPopoverClose){
1521                        _data.options.onPopoverClose.call(_this);
1522                    }
1523                                                
1524                });                
1525            };
1526
1527            popoverClose.on('click', _this.hidePopover);
1528
1529        },
1530        popoverOffHandler : function(e){
1531            
1532            var id = $(e.target).attr('id');
1533        
1534            
1535            // If clicked object was popover by itself, stop.
1536            // If region was clicked - stop, because pop-up will just move to another position, we don't have to hide it.
1537            if($(e.target).closest('.map_popover').length || (_data.options.regions[id] && !_data.options.regions[id].disabled ))
1538                return false;
1539            
1540            _this.hidePopover();
1541        },
1542        isNumber : function (n) {
1543          return !isNaN(parseFloat(n)) && isFinite(n);
1544        },
1545        parseBoolean : function (string) {
1546          switch (String(string).toLowerCase()) {
1547            case "true":
1548            case "1":
1549            case "yes":
1550            case "y":
1551              return true;
1552            case "false":
1553            case "0":
1554            case "no":
1555            case "n":
1556              return false;
1557            default:
1558              return undefined;
1559          }
1560        },
1561        mouseOverHandler : function(){},
1562        mouseOutHandler : function(){},
1563        mouseDownHandler : function(){},
1564        // INIT
1565        init : function(opts, elem) {
1566
1567            if(!opts.source) {
1568                alert('mapSVG Error: Please provide a map URL');
1569                return false;
1570            }
1571
1572            // Cut protocol (http: || https:) - to avoid "cross-domain" error
1573            if(opts.source.indexOf('http://') == 0 || opts.source.indexOf('https://') == 0)
1574                opts.source = "//"+opts.source.split("://").pop();
1575
1576            opts.pan  = _this.parseBoolean(opts.pan);
1577            opts.zoom = _this.parseBoolean(opts.zoom);
1578            opts.responsive  = _this.parseBoolean(opts.responsive);
1579            opts.disableAll  = _this.parseBoolean(opts.disableAll);
1580            opts.multiSelect = _this.parseBoolean(opts.multiSelect);
1581
1582            // If veiwBox is set as string region's name (or country name)
1583            // then we'll calculate veiwBox parameters later
1584            if(opts.viewBox && typeof opts.viewBox == 'string'){
1585                opts.viewBoxFind = opts.viewBox;
1586                delete opts.viewBox;
1587            }
1588
1589            /** Setting _data **/
1590            _data  = {};
1591
1592            _data.options = $.extend(true, {}, defaults, opts);
1593
1594            _data.map  = elem;
1595            _data.$map = $(elem);
1596            _data.whRatio = 0;
1597            _data.isPanning = false;
1598
1599            _data.markOptions = {};
1600            _data.svgDefault = {};
1601            _data.mouseDownHandler;
1602
1603            _data.refLength = 0;
1604
1605            _data.scale  = 1;         // absolute scale
1606            _data._scale = 1;         // relative scale starting from current zoom level
1607
1608            _data.selected_id   =  _data.options.multiSelect ? [] : 0;
1609            _data.mapData       = {};
1610
1611            _data.marks         = [];
1612            _data._viewBox      = []; // initial viewBox
1613            _data.viewBox       = []; // current viewBox
1614            _data.viewBoxZoom   = [];
1615            _data.viewBoxFind   = undefined;
1616            _data.zoomLevel     = 0;
1617            _data.pan           = {};
1618            _data.zoom;
1619            _data.touchZoomStart;
1620            _data.touchZoomStartViewBox;
1621            _data.touchZoomEnd;
1622            /****/
1623
1624
1625            // Set background
1626            _data.$map.css({
1627                             'background': _data.options.colors.background,
1628                             'height': '100px',
1629                             'position' : 'relative'
1630                           });
1631
1632            var loading = $('<div>'+_data.options.loadingText+'</div>').css({
1633                position: 'absolute',
1634                top:  '50%',
1635                left: '50%',
1636                'z-index': 1,
1637                padding: '7px 10px',
1638                'border-radius': '5px',
1639                '-webkit-border-radius': '5px',
1640                '-moz-border-radius': '5px',
1641                '-ms-border-radius': '5px',
1642                '-o-border-radius': '5px',
1643                'border': '1px solid #ccc',
1644                background: '#f5f5f2',
1645                color: '#999'
1646            });
1647
1648            _data.$map.append(loading);
1649
1650            loading.css({
1651                'margin-left': function () {
1652                    return -($(this).outerWidth(false) / 2)+'px';
1653                },
1654                'margin-top': function () {
1655                    return -($(this).outerHeight(false) / 2)+'px';
1656                }
1657            });
1658
1659
1660            // GET the map by ajax request
1661            $.ajax({
1662                url: _data.options.source,
1663                contentType: "image/svg+xml; charset=utf-8",
1664                //dataType: (_browser.ie) ? 'text' : 'xml', // check if IE
1665                beforeSend: function(x) {
1666                        if(x && x.overrideMimeType) {
1667                            x.overrideMimeType("image/svg+xml; charset=utf-8");
1668                        }
1669                    },
1670                success:  function(xmlData){
1671
1672                    $data = $(xmlData);
1673
1674                    // Default width/height/viewBox from SVG
1675                    var svgTag               = $data.find('svg');
1676                    _data.svgDefault.width   = parseFloat(svgTag.attr('width').replace(/px/g,''));
1677                    _data.svgDefault.height  = parseFloat(svgTag.attr('height').replace(/px/g,''));
1678                    _data.svgDefault.viewBox = svgTag.attr('viewBox') ? svgTag.attr('viewBox').split(' ') : [0,0, _data.svgDefault.width, _data.svgDefault.height];
1679
1680                    $.each(_data.svgDefault.viewBox, function(i,v){
1681                        _data.svgDefault.viewBox[i] = parseInt(v);
1682                    });
1683
1684                    _data._viewBox  = (_data.options.viewBox.length==4) ? _data.options.viewBox : _data.svgDefault.viewBox;
1685
1686                    $.each(_data._viewBox, function(i,v){
1687                        _data._viewBox[i] = parseInt(v);
1688                    });
1689
1690
1691                    // Set size
1692                    _this.setSize(_data.options.width, _data.options.height, _data.options.responsive);
1693
1694                    // Attach Raphael to given jQuery element
1695
1696                    // IE 7&8 doesn't support responsive size so we just set
1697                    // width and height in pixels, and then resize it on window.resize event.
1698                    // For all other cool browsers we just set width and height
1699                    // to 100% to simply fit DIV container.
1700                    
1701                    
1702                    if(_browser.ie && _browser.ie.old){
1703
1704                        _data.R = Raphael(_data.$map.attr('id'), _data.options.width, _data.options.height);
1705                        _data.scale = _this.getScale();
1706
1707                        if(_data.options.responsive)
1708                            $(window).on('resize', _this.fluidResize);
1709
1710                    }else{
1711                        _data.R = Raphael(_data.$map.attr('id'), '100%', '100%');
1712
1713                        if(_data.options.responsive){
1714                            $(window).on('resize', function(e){
1715                                _data.scale = _this.getScale();
1716                                _this.marksAdjustPosition();
1717                            });
1718                        }
1719                    }
1720
1721                    // Adding moving sticky draggable image on background
1722                    if(_data.options.panBackground)
1723                        _data.background = _data.R.rect(_data.svgDefault.viewBox[0],_data.svgDefault.viewBox[1],_data.svgDefault.viewBox[2],_data.svgDefault.viewBox[3]).attr({fill: _data.options.colors.background});
1724
1725                	_data.RMap     = _data.R.set();
1726                    _data.RMarks   = _data.R.set();
1727
1728                    // Render each SVG element
1729                    
1730                    var parse = function(_item, parentTransform, parentStyle){
1731                        var type = $(_item).get(0).tagName;
1732                        
1733                        switch (type){
1734                            case 'path':
1735                                _this.renderSVGPath(_item, parentTransform, parentStyle);
1736                                break;
1737                            case 'polygon':
1738                                _this.renderSVGPolygon(_item, parentTransform, parentStyle);
1739                                break;
1740                            case 'polyline':
1741                                _this.renderSVGPolyline(_item, parentTransform, parentStyle);
1742                                break;
1743                            case 'circle':
1744                                _this.renderSVGCircle(_item, parentTransform, parentStyle);
1745                                break;
1746                            case 'ellipse':
1747                                _this.renderSVGEllipse(_item, parentTransform, parentStyle);
1748                                break;
1749                            case 'rect':                            
1750                                _this.renderSVGRect(_item, parentTransform, parentStyle);
1751                                break;
1752                            case 'image':
1753                                _this.renderSVGImage(_item, parentTransform, parentStyle);
1754                                break;
1755                            case 'text':                                
1756                                _this.renderSVGText(_item, parentTransform, parentStyle);
1757                                break;
1758                            default:
1759                                null;
1760                                break;
1761                        }                        
1762                    };                 
1763                    
1764                    var traverse = function (node, parentTransformString, parentStyle){
1765                        
1766                        var children = $(node).children();
1767                        
1768                        if (children.length){// && !$(node).is('text')) {
1769                            
1770                            var nodes = [];
1771                            
1772                            parentTransformString = parentTransformString || "";
1773                            parentTransformString = _this.transformSVG2Raphael(node) + parentTransformString;
1774                            parentStyle = parentStyle || {};
1775                            
1776                            $(node).children().each(function(i,n){
1777                              var _parentStyle = _this.styleSVG2Raphael(n, parentStyle);
1778                              traverse($(n), parentTransformString, _parentStyle);
1779                            });
1780                            
1781                        }// else{                
1782                            parse($(node), parentTransformString, parentStyle);
1783                        //} 
1784                            
1785                    };
1786                    
1787                    traverse($data.find('svg'));
1788                    
1789                    // Set viewBox
1790                    var v = _data.options.viewBoxFind || _data._viewBox;
1791                    _this.setViewBox(v);
1792
1793                    // If there are markers, put them to the map
1794                    _this.setMarks(_data.options.marks);
1795                    _this.setMarksEditMode(_data.options.editMode);
1796
1797                    // Set panning
1798                    _this.setPan(_data.options.pan);
1799
1800                    // Set zooming by mouswheel
1801                    _this.setZoom(_data.options.zoom);
1802
1803                    // Set tooltips
1804                    _this.setTooltip(_data.options.tooltips.mode);
1805
1806                    // Set popovers
1807                    _this.setPopover(_data.options.popover);
1808
1809
1810                    if(_data.options.responsive && _browser.ie && _browser.ie.old)
1811                        _this.fluidResize();
1812
1813
1814                    if((_browser.ie && !_browser.ie.old) || _browser.firefox)
1815                            _this.mapAdjustStrokes();
1816
1817
1818                    //Create event handlers
1819                    var funcStr = '';
1820
1821                    /*
1822                     * Now let's add event handlers.
1823                     * Please note that we don't need mouseOver / mouseOut on mobile devices (iPad etc..)
1824                     */
1825                    if(!touchDevice){
1826                        // 1. MouseOver
1827                        funcStr = 'methods.highlightRegion(this.name);';
1828                        if(_data.options.tooltips.show == 'hover')
1829                            funcStr += 'methods.showTip(this.name);';
1830                        if(_data.options.mouseOver)
1831                            funcStr += 'return options.mouseOver.call(this, e, methods);';
1832
1833                        _this.mouseOverHandler = new Function('e, methods, options', funcStr);
1834
1835                        // 2. MouseOut
1836                        funcStr = '';
1837                        funcStr += 'methods.unhighlightRegion(this.name);';
1838                        if(_data.options.tooltips.show == 'hover')
1839                            funcStr += 'methods.hideTip();';
1840                        if(_data.options.mouseOut)
1841                            funcStr += 'return options.mouseOut.call(this, e, methods);';
1842                        _this.mouseOutHandler = new Function('e, methods, options', funcStr);
1843                    }
1844
1845                    // 3. MouseDown
1846                    funcStr = '';
1847                    funcStr = 'methods.regionClickHandler.call(mapObj, e, this);';
1848                    _this.mouseDownHandler = new Function('e, methods', funcStr);
1849                    
1850
1851                    /* EVENTS */
1852                    if(!touchDevice){
1853                    	_data.RMap
1854                            .mouseover( function(e){_this.mouseOverHandler.call(this, e, _this, options);} )
1855                            .mouseout(  function(e){_this.mouseOutHandler.call(this, e, _this, options);} );
1856                    }
1857
1858                    if(!_data.options.pan){
1859                        
1860                        if(!touchDevice){
1861                            _data.RMap.mousedown( function(e){
1862                                
1863                                //_this.mouseDownHandler.call(this, e, methods);}
1864                                _this.regionClickHandler.call(_this, e, this);
1865                             });
1866                        }else{
1867                            _data.RMap.touchstart(
1868                                function(e){
1869                                
1870                                    e.preventDefault();
1871                                    _this.regionClickHandler.call(_this, e, this);
1872                                }
1873                            );
1874                        }
1875                    }else{
1876                        if(!touchDevice){
1877                            _data.RMap.mousedown( function(e){
1878                                // While panning we just remember which region was clicked
1879                                // by panRegionClickHandler method, and then trigger
1880                                // regionClickHandler on that region when panning finishes
1881                                e.preventDefault();
1882                                
1883                                _this.panRegionClickHandler.call(_this, e, this);
1884                            });
1885                        }else{
1886                            _data.RMap.touchstart(
1887                                function(e){
1888                                    _this.panRegionClickHandler.call(_this, e, this);
1889                                }
1890                            );
1891                            _data.R.canvas.addEventListener('touchstart', function(e) {
1892                                _this.touchStart(e);
1893                            }, false);
1894                            _data.R.canvas.addEventListener('touchmove', function(e) {
1895                                _this.touchMove(e);
1896                            }, false);
1897                            _data.R.canvas.addEventListener('touchend', function(e) {
1898                                _this.touchEnd(e);
1899                            }, false);
1900                        }
1901                    }
1902                    loading.hide();
1903                    
1904                    if(_data.options.onLoad)
1905                        _data.options.onLoad.call(_this);
1906                        
1907                        
1908                    
1909                    } // end of AJAX callback
1910                    
1911                     
1912
1913                });// end of AJAX
1914
1915        
1916            
1917        return _this;
1918
1919        } // end of init
1920
1921   }; // end of methods
1922
1923   var _this = this.methods;
1924
1925  }; // end of mapSVG class
1926
1927
1928  /** $.FN **/
1929  $.fn.mapSvg = function( opts ) {
1930
1931    var id = $(this).attr('id');
1932
1933    if(typeof opts == 'object' && instances[id] === undefined){
1934        instances[id] = new mapSVG(this, opts);
1935        return instances[id].methods.init(opts, this);
1936    }else if(instances[id]){
1937        return instances[id].methods;
1938    }else{
1939        return $(this);
1940    }
1941
1942  }; // end of $.fn.mapSvg
1943
1944})( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.