1(function($){ 2 3 $.fn.easypin = function(options) { 4 5 options = options || {}; 6 7 if(localStorage) { 8 localStorage.removeItem('easypin'); 9 } 10 11 var parentClass = $.fn.easypin.defaults.parentClass; 12 var pinMapClass = $.fn.easypin.defaults.pinMapClass; 13 var hoverClass = $.fn.easypin.defaults.hoverClass; 14 var dashWidth = $.fn.easypin.defaults.dashWidth; 15 var imageZindex = $.fn.easypin.defaults.imageZindex; 16 var pinMapZindex = $.fn.easypin.defaults.pinMapZindex; 17 var hoverLayerZindex = $.fn.easypin.defaults.hoverLayerZindex; 18 19 // set default options values and became user side 20 $.extend($.fn.easypin.defaults, options ); 21 22 var willPinningElements = this; 23 var loadedImgNum = 0; 24 var total = $(this).length; 25 26 // hide all images 27 willPinningElements.each(function(i) { 28 $(this).css('opacity', 0); 29 }); 30 31 $(this).on('load', function() { 32 33 loadedImgNum += 1; 34 // show loaded image 35 $(this).animate( 36 { 37 'opacity': '1' 38 }, 39 { 40 duration: 'fast', 41 easing: 'easeInQuad' 42 } 43 ); 44 45 if (loadedImgNum == total) { 46 47 willPinningElements.each(function(i) { 48 49 // get targetimage sizes 50 var imageWidth = $(this).width(); 51 var imageHeight = $(this).height(); 52 53 if(imageHeight > 0) { 54 55 // create parent element and add than target image after 56 var containerElement = $(this) 57 .after( 58 $('<div/>', {'class': parentClass}) 59 .attr('data-index', setIndex(setClass(parentClass), document.body)) 60 ) 61 .appendTo(setClass(parentClass)+':last') 62 .css('position', 'absolute') 63 .css('z-index', imageZindex); 64 65 // add class to target image 66 $(this).addClass('easypin-target') 67 68 // creating random key for easypin-id 69 if(! $(this).attr('easypin-id')) { 70 var easypinId = createRandomId(); 71 $(this).attr('easypin-id', easypinId); 72 }else{ 73 var easypinId = $(this).attr('easypin-id'); 74 } 75 76 // set target image sizes to parent container 77 containerElement 78 .parent() 79 .attr($.fn.easypin.config('widthAttribute'), imageWidth) 80 .attr($.fn.easypin.config('heightAttribute'), imageHeight) 81 // and set style width, height and position 82 .css({ 83 width: setPx(imageWidth), 84 height: setPx(imageHeight), 85 position: $.fn.easypin.config('parentPosition'), 86 border: setPx(dashWidth)+' dashed #383838', 87 'box-sizing': 'content-box', 88 'webkit-box-sizing': 'content-box', 89 '-moz-box-sizing': 'content-box' 90 }); 91 92 initPin(easypinId, $(this)); 93 } 94 }); 95 96 // hover event 97 var parentElement = $(setClass(parentClass)); 98 99 // on hover parent element then create opacity 100 $(parentElement).hover(function() { 101 // if popup is open stop hover animate 102 if(! is_open('popup', $(this))) { 103 $(this) 104 .prepend( 105 $('<div/>', {'class': hoverClass}) 106 .css({ 107 width: '100%', 108 height: '100%', 109 position: 'absolute', 110 opacity: 0, 111 'z-index': hoverLayerZindex, 112 'background-color': 'black', 113 cursor: 'copy' 114 }) 115 ) 116 // cross to children object 117 .children(setClass(hoverClass)) 118 .animate({ 119 opacity: 0.2, 120 }, 800); 121 } 122 123 // on mouseleave then remove opacity 124 },function() { 125 $(this) 126 // cross to children object 127 .children(setClass(hoverClass)) 128 .animate({ 129 opacity: 0, 130 }, 131 'fast', // how fast we are animating 132 'swing', // the type of easing 133 function() { 134 $(this).remove(); 135 } 136 ); 137 138 }) 139 .append($('<div/>', {'class': pinMapClass}) 140 // child element 141 .css({ 142 position: 'absolute', 143 'z-index': pinMapZindex 144 }) 145 ) 146 // set mousedown event on parent element 147 .bind('mousedown', function(e) { 148 // if clicked event is not parent and hover class stop propagation 149 if(! $(e.target).is(setClass(parentClass)) && !$(e.target).is(setClass(hoverClass))) { 150 e.stopPropagation(); 151 return; 152 } 153 154 // only allow key code one 155 if(e.which != 1) return; 156 157 // get parent element instance 158 var parentElement = e.currentTarget; 159 160 // get total marker 161 var totalMarker = $('.easy-marker', parentElement).size(); 162 163 // general limit 164 var limit = parseInt($.fn.easypin.defaults.limit); 165 166 // only element limit 167 var elLimit = $('img'+setClass('easypin-target'), parentElement).attr('easypin-limit'); 168 169 // check the limit 170 if(elLimit && !isNaN(elLimit) && parseInt(elLimit) != 0) { 171 if(totalMarker >= parseInt(elLimit)) { 172 $.fn.easypin.defaults.exceeded('limit exceeded'); 173 return; 174 } 175 } 176 else if(limit != 0 && totalMarker >= limit) { 177 $.fn.easypin.defaults.exceeded('limit exceeded'); 178 return; 179 } 180 181 // get target image sizes 182 var imageWidth = $('img'+setClass('easypin-target'), parentElement).width(); 183 var imageHeight = $('img'+setClass('easypin-target'), parentElement).height(); 184 185 // pin map class sized 186 $(setClass(pinMapClass), parentElement) 187 .css({ 188 width: setPx(imageWidth), 189 height: setPx(imageHeight) 190 }); 191 192 // get config variable 193 var src = $.fn.easypin.defaults.markerSrc; 194 var markerWidth = $.fn.easypin.defaults.markerWidth; 195 var markerHeight = $.fn.easypin.defaults.markerHeight == 'auto' ? markerWidth : $.fn.easypin.defaults.markerHeight; 196 var markerClass = $.fn.easypin.defaults.markerClass; 197 var markerContainerZindex = $.fn.easypin.defaults.markerContainerZindex; 198 199 // canvas border width 200 var dashWidth = $.fn.easypin.defaults.dashWidth; 201 202 // get x, y balance value 203 var posYBalance = $.fn.easypin.defaults.posYBalance; 204 var posXBalance = $.fn.easypin.defaults.posXBalance; 205 206 // get current target image instance 207 var targetImage = $('img'+setClass('easypin-target'), parentElement); 208 209 // set cursor position coordinate 210 var imagePositionY = targetImage.offset().top - (dashWidth-posYBalance); 211 var imagePositionX = targetImage.offset().left - (dashWidth-posXBalance); 212 var clickPosX = (e.pageX-imagePositionX); 213 var clickPosY = (e.pageY-imagePositionY); 214 215 // get marker half size (width/height) 216 var markerWidthHalf = (markerWidth/2); 217 var markerHeightHalf = (markerHeight/2); 218 219 // set canvas border position 220 var markerBorderX = clickPosX-(markerWidth/2); 221 var markerBorderY = clickPosY-(markerHeight/2); 222 223 if(markerBorderX < 0) { 224 markerBorderX = 0; 225 } 226 else if(clickPosX+markerWidthHalf > imageWidth) { 227 markerBorderX = imageWidth-markerWidth; 228 } 229 230 if(markerBorderY < 0) { 231 markerBorderY = 0; 232 } 233 else if(clickPosY+markerHeightHalf > imageHeight) { 234 markerBorderY = imageHeight-markerHeight; 235 } 236 237 var absX = markerBorderX.toFixed(3)-markerWidthHalf; 238 var absY = markerBorderY.toFixed(3)-markerHeightHalf; 239 240 // create tool 241 var tools = createTools({ 242 markerWidth: markerWidth, 243 markerHeight: markerHeight 244 }); 245 246 // create marker container 247 var markerContainer = createMarker({ 248 tools: tools, 249 parentElement: parentElement, 250 markerClass: markerClass, 251 markerBorderX: markerBorderX, 252 markerBorderY: markerBorderY, 253 markerWidth: markerWidth, 254 markerHeight: markerHeight, 255 markerContainerZindex: markerContainerZindex, 256 markerWidth: markerWidth, 257 absX: absX, 258 absY: absY, 259 imageWidth: imageWidth, 260 imageHeight: imageHeight, 261 parentElement: parentElement, 262 src: src 263 }); 264 }); 265 266 // object instance add to container 267 $.fn.easypin.di('instance', $.fn.easypin); 268 269 } 270 271 }); 272 273 return this; 274 }; 275 276 var createMarker = function(depends) { 277 278 var parentElement = depends.parentElement; 279 280 // create marker container
281 var markerContainer = $('<div/>', {'class': depends.markerClass}) 282 .css('left', setPx(depends.markerBorderX)) 283 .css('top', setPx(depends.markerBorderY-15)) 284 .css('width', depends.markerWidth) 285 .css('height', depends.markerHeight) 286 .css('margin-left', setPx(depends.marginLeft)) 287 .css('margin-top', setPx(depends.marginTop)) 288 .css('position', 'absolute') 289 .css('opacity', 0) 290 .css('z-index', depends.markerContainerZindex+10) 291 .css('background-image', 'url('+depends.src+')') 292 .css('background-size', setPx(depends.markerWidth)) 293 .css('cursor', 'move') 294 .attr($.fn.easypin.config('xAttribute'), depends.absX) 295 .attr($.fn.easypin.config('yAttribute'), depends.absY) 296 .attr($.fn.easypin.config('widthAttribute'), depends.imageWidth) 297 .attr($.fn.easypin.config('heightAttribute'), depends.imageHeight) 298 .attr('data-index', setIndex('.easy-marker', depends.parentElement)); 299 300 var markerIndex = $(markerContainer).attr('data-index'); 301 var parentIndex = $(depends.parentElement).attr('data-index'); 302 var parentId = $('.easypin-target', depends.parentElement).attr('easypin-id'); 303 304 // remove marker 305 $(markerContainer).on('click', '.easy-delete', function(e) { 306 307 dataRemove(parentId, markerIndex); 308 309 $(e.currentTarget).closest('.easy-marker').remove(); 310 }); 311 312 // set the marker content 313 $(markerContainer).on('click', '.easy-edit', function(e) { 314 // creates popup and return instance 315 var modalInstance = createPopup(e, markerContainer); 316 317 // data set to input fields 318 setDataToFields(parentId, markerIndex, modalInstance); 319 }); 320 321 // marker tools append to marker container 322 $(markerContainer).append(depends.tools); 323 324 // set cursor x,y position 325 var xPosition = depends.markerBorderX.toFixed(3); 326 var yPosition = depends.markerBorderY.toFixed(3); 327 328 // marker container append to pin parent container and run callback function 329 if(is_open('popup', depends.parentElement)) { 330 $(depends.parentElement).prepend(markerContainer, $.fn.easypin.defaults.drop(depends.absX, depends.absY, markerContainer)); 331 }else{ 332 $(depends.parentElement).append(markerContainer, $.fn.easypin.defaults.drop(depends.absX, depends.absY, markerContainer)); 333 } 334 335 // calculate tools position for animate 336 if((depends.markerBorderY+depends.markerHeight+10) > depends.imageHeight) { 337 var toolsPosition = -13; 338 }else { 339 var toolsPosition = depends.markerHeight+2; 340 } 341 342 // marker animate 343 $(markerContainer).animate( 344 { 345 opacity: 1, 346 top: setPx(depends.markerBorderY) 347 }, 348 { 349 duration: 'slow', 350 easing: 'easeOutElastic', 351 complete: function() { 352 353 // tools animate 354 $(depends.tools).animate( 355 { 356 'opacity': '.4', 357 'top': setPx(toolsPosition) 358 }, 359 { 360 duration: 'slow', 361 easing: 'easeOutElastic' 362 } 363 ).hover(function() { 364 $(this).animate( 365 { 366 'opacity': '1' 367 }, 368 { 369 duration: 'slow', 370 easing: 'easeInOutQuint' 371 } 372 ).css('cursor', 'pointer'); 373 },function() { 374 $(this).animate( 375 { 376 'opacity': '.4' 377 }, 378 { 379 duration: 'slow', 380 easing: 'easeInOutQuint' 381 } 382 ); 383 }); 384 } 385 } 386 ); 387 388 var cc = false;
389 // binding methods mousedown and mousemove 390 $(markerContainer).bind('mousedown', function (e) { 391 e.stopPropagation(); 392 393 if(e.which != 1) return; 394 395 var markerInstance = e.currentTarget; 396 397 if($(e.target).parent().is(setClass('popoverContent'))) { 398 cc = true; 399 }else{ 400 cc = $(e.target).is(setClass('popoverContent')); 401 } 402 403 $(parentElement).bind('mousemove', function (e) { 404 405 if((! $(e.target).is('div.easy-marker') && 406 !$(e.target).is(setClass($.fn.easypin.defaults.hoverClass))) && 407 cc === true 408 ) return; 409 410 var parentElement = $(markerInstance).parent(); 411 var markerContainer = $(markerInstance); 412 413 var targetImage = $('img.easypin-target', parentElement) 414 var markerWidthHalf = (depends.markerWidth/2); 415 var markerHeightHalf = (depends.markerHeight/2); 416 liveY = e.pageY-targetImage.offset().top; 417 liveX = e.pageX-targetImage.offset().left; 418 419 var relY = liveY; 420 var relX = liveX; 421 422 if(liveY - markerHeightHalf < 0) { 423 var relY = markerHeightHalf; 424 } 425 else if(liveY + markerHeightHalf > depends.imageHeight) { 426 var relY = depends.imageHeight-markerHeightHalf; 427 } 428 429 if(liveX - markerWidthHalf < 0) { 430 var relX = markerWidthHalf; 431 } 432 else if(liveX + markerWidthHalf > depends.imageWidth) { 433 var relX = depends.imageWidth-markerWidthHalf; 434 } 435 436 var absX = relX.toFixed(3)-markerWidthHalf; 437 var absY = parseInt(relY.toFixed(3))+markerHeightHalf; 438 439 // on move marker then check tool container position 440 checkToolsPosition(absY, depends.imageHeight, markerContainer) 441 442 // drag event 443 $.fn.easypin.defaults.drag(absX, absY, markerContainer); 444 console.log(relX); 445 $(markerContainer).css({ 446 position: 'absolute', 447 top: setPx(relY), 448 left: setPx(relX), 449 marginTop: -(depends.markerHeight/2), 450 marginLeft: -(depends.markerWidth/2), 451 }) 452 .attr($.fn.easypin.config('xAttribute'), absX) 453 .attr($.fn.easypin.config('yAttribute'), absY); 454 }); 455 }); 456 457 // unbinding the events and removing 458 $(markerContainer).bind('mouseup', function (e) { 459 cc = false; 460 var markerInstance = e.currentTarget; 461 var lat = $(markerInstance).attr($.fn.easypin.config('xAttribute')); 462 var long = $(markerInstance).attr($.fn.easypin.config('yAttribute')); 463 464 dataUpdate(parentId, markerIndex, {coords: {lat: lat, long: long}}); 465 466 $(parentElement).unbind('mousemove'); 467 }); 468 469 return markerContainer; 470 }; 471 472 var createTools = function(depends) { 473 474 var tools = $('<div/>', {'class': 'easy-tools'}) 475 .css({ 476 'width': setPx(depends.markerWidth), 477 'height': '10px', 478 'position': 'absolute', 479 'background-color': '#868585', 480 'left': '-1px', 481 'top': setPx((depends.markerHeight+2)-5), 482 'opacity': '0' 483 484 }) 485 .append(function() { // edit button create 486 return $('<a/>', {'class': 'easy-edit'}) 487 .css({ 488 'display': 'inline-block', 489 'width': setPx(depends.markerWidth/2), 490 'height': '10px', 491 'position': 'absolute', 492 'left': '0px', 493 'background-image': 'url('+$.fn.easypin.defaults.editSrc+')', 494 'background-repeat': 'no-repeat', 495 'background-size': '8px', 496 'background-position-y': '1px', 497 'background-position-x': '3px' 498 }).hover(function() { 499 $(this) 500 .css('background-color', 'black') 501 .css('opacity', '.6'); 502 },function() { 503 $(this).css('background-color', 'inherit'); 504 }); 505 }) 506 .append(function() { // delete button 507 return $('<a/>', {'class': 'easy-delete'}) 508 .css({ 509 'display': 'inline-block', 510 'width': setPx(depends.markerWidth/2), 511 'height': '10px', 512 'position': 'absolute', 513 'right': '0px', 514 'background-image': 'url('+$.fn.easypin.defaults.deleteSrc+')', 515 'background-repeat': 'no-repeat', 516 'background-size': '8px', 517 'background-position-y': '1px', 518 'background-position-x': '3px' 519 }).hover(function() { 520 $(this) 521 .css('background-color', 'black') 522 .css('opacity', '.6'); 523 },function() { 524 $(this).css('background-color', 'inherit'); 525 }); 526 }); 527 528 return tools; 529 }; 530 531 var checkToolsPosition = function(absY, imageHeight, markerContainer) { 532 533 var markerHeight = $(markerContainer).height(); 534 var yBottom = absY+10; 535 536 if(yBottom > imageHeight && yBottom == imageHeight+1) { 537 $('.easy-tools', markerContainer).animate( 538 { 539 'top': setPx(-13) 540 }, 541 { 542 duration: 'slow', 543 easing: 'easeOutElastic' 544 } 545 ); 546 } 547 548 else if((absY-markerHeight)-10 == -1) { 549 $('.easy-tools', markerContainer).animate( 550 { 551 'top': setPx(markerHeight+2) 552 }, 553 { 554 duration: 'slow', 555 easing: 'easeOutElastic' 556 } 557 ); 558 } 559 }; 560 561 var getEventData = function(namespace) { 562 563 switch (namespace) { 564 case "get.coordinates": 565 if(localStorage) { 566 return JSON.parse(localStorage.getItem('easypin')); 567 }else { 568 try { 569 return JSON.parse(decodeURIComponent($('input[name="easypin-store"]').val())); 570 } catch (e) { 571 return null; 572 } 573 } 574 break; 575 default: 576 return null; 577 } 578 579 }; 580 581 getByIndex = function(index, data) { 582 583 data = data || {}; 584 index = parseInt(index); 585 586 if(typeof(data) == 'object') { 587 588 var j = 0; 589 for(var i in data) { 590 591 j++; 592 if(j == index) { 593 return data[i]; 594 } 595 596 } 597 598 } 599 600 return {}; 601 602 }; 603 $.fn.easypinShow = function(options) { 604 605 options = options || {}; 606 607 // set default options values and became user side 608 $.extend($.fn.easypinShow.defaults, options ); 609 610 try { 611 612 var depends = { 613 responsive: options.responsive || false, 614 pin: options.pin || 'marker.png', 615 data: options.data || {}, 616 popover: options.popover || {}, 617 error: typeof(options.error) != 'function' ? function(e) {} : options.error, 618 each: typeof(options.each) != 'function' ? function(i, data) { return data;} : options.each, 619 success: typeof(options.success) != 'function' ? function() {} : options.success, 620 allCanvas: this 621 }; 622 623 var loadedImgNum = 0; 624 var total = $(this).length; 625 626 // hide all images 627 depends.allCanvas.each(function(i) { 628 $(this).css('opacity', 0); 629 }); 630 631 $(depends.allCanvas).one('load', function() { 632 loadedImgNum += 1; 633 634 // show loaded image 635 $(this).animate( 636 { 637 'opacity': '1' 638 }, 639 { 640 duration: 'fast', 641 easing: 'easeInQuad' 642 } 643 ); 644 645 if (loadedImgNum == total) { 646 647 var markerWidth = $(this)[0].width; 648 var markerHeight = $(this)[0].height; 649 var markerImgInstance = $(this); 650 pinLocate(depends); 651 depends.success.apply(); 652 } 653 }).each(function() { 654 if(this.complete) $(this).load(); 655 }); 656 657 } catch (e) { 658 var args = new Array(); 659 args.push(e.message); 660 args.push(e);
661 depends.error.apply(null, args); 662 } 663 664 }; 665 666 pinLocate = function(depends) { 667 668 // for each all canvas 669 $(depends.allCanvas).each(function(i) { 670 671 var offsetTop = $(this).offset().top; 672 var offsetLeft = $(this).offset().left; 673 var canvas = $(this).parent(); 674 var height = $(this).height(); 675 var width = $(this).width(); 676 var parentWidth = $(canvas).width(); 677 678 if(depends.responsive === true) { 679 var absWidth = '100%'; 680 var absHeight = '100%'; 681 }else{ 682 var absWidth = setPx(width); 683 var absHeight = setPx(height); 684 } 685 686 var pinContainer = $('<div/>') 687 .css({ 688 'width': absWidth, 689 'height': absHeight, 690 'position': 'relative' 691 }) 692 .addClass('easypin'); 693 694 $(this) 695 .css('position', 'relative') 696 .replaceWith(pinContainer); 697 698 $(pinContainer).html( 699 $('<div/>') 700 .css('position', 'relative') 701 .css('height', '100%') 702 .append($(this)) 703 ); 704 705 var parentId = $(this).attr('easypin-id'); 706 707 if(typeof(depends.data) == 'string') { 708 depends.data = JSON.parse(depends.data); 709 } 710 711 if(typeof(depends.data[parentId]) != 'undefined') { 712 713 for (var j in depends.data[parentId]) { 714 if(j == 'canvas') return; 715 716 var tpl = $('[easypin-tpl]').clone(); 717 718 // set current canvas_id and pin_id to di container 719 $.fn.easypin.di('canvas_id', parentId); 720 $.fn.easypin.di('pin_id', j); 721 722 // run callback function 723 var args = new Array(); 724 args.push(i); 725 args.push(depends.data[parentId][j]); 726 var returnData = depends.each.apply(null, args); 727 var viewContainer = viewLocater(depends.data[parentId], j, parentWidth, createView(returnData, tpl)); 728 729 var opacity = getCssPropertyValue('opacity', $(viewContainer).clone()); 730 731 $(viewContainer).css('opacity', 0); 732 $(pinContainer).append(viewContainer); 733 734 if(depends.popover.show == true) { 735 $('.easypin-popover', pinContainer).show(); 736 } 737 738 // marker 739 $(viewContainer).animate( 740 { 741 'opacity': opacity 742 }, 743 { 744 duration: 'slow', 745 easing: 'easeOutBack' 746 } 747 ); 748 749 // popover 750 751 $('.closepin',pinContainer).click(function(e){ 752 $('.easypin-popover', pinContainer).each(function() { 753 if($(this).css('display') == 'block' ) { 754 $(this).fadeOut('fast'); 755 } 756 }); 757 }); 758 759 $('.easypin-marker:last', pinContainer).click(function(e) { 760 761 if(! $(e.target).is('div.easypin-marker') && 762 !$(e.target).parent().is('div.easypin-marker')) return; 763 764 // set 0 to z-index all marker 765 $('.easypin-marker', pinContainer).css('z-index', 0); 766 767 // set 1 to z-index current marker 768 $(this).css('z-index', 1); 769 770 var ins = this; 771 var clickedMarkerIndex = $(ins).index(); 772 773 if(depends.popover.animate === true) { 774 775 // hide all content 776 $('.easypin-popover', pinContainer).each(function() { 777 if($(this).css('display') == 'block' && clickedMarkerIndex != $(this).closest('.easypin-marker').index()) { 778 $(this).toggle('fast'); 779 } 780 }); 781 782 $('.easypin-popover', ins).toggle('fast'); 783 784 }else{ 785 // hide all content 786 $('.easypin-popover', pinContainer).each(function() { 787 if($(this).css('display') == 'block' && clickedMarkerIndex != $(this).closest('.easypin-marker').index()) { 788 $(this).hide(); 789 } 790 }); 791 792 if ( $('.easypin-popover', this).css('display') == 'none' ){ 793 $('.easypin-popover', this).show(); 794 }else{ 795 $('.easypin-popover', this).hide(); 796 } 797 } 798 }); 799 } 800 } 801 }); 802 }; 803 804 var createView = function(data, tplInstance) { 805 806 var popover = $('popover', tplInstance); 807 var marker = $('marker', tplInstance); 808 809 $(popover) 810 .children(':first') 811 .addClass('easypin-popover') 812 .css('position', 'absolute') 813 .css('display', 'none'); 814 815 $(marker) 816 .children(':first') 817 .addClass('easypin-marker') 818 .css({ 819 'position': 'absolute' 820 }); 821 822 var markerBorderWidth = $(marker).children(':first').css('border-width').replace('px', ''); 823 markerBorderWidth = markerBorderWidth != '' ? parseInt(markerBorderWidth) : 0; 824 var markerWidth = $(marker).children(':first').width(); 825 var markerHeight = $(marker).children(':first').height(); 826 var popoverHeight = $(popover).children(':first').height(); 827 828 var popIns = $(popover).children(':first').clone(); 829 var bottom = getCssPropertyValue('bottom', popover); 830 var newBottom = bottom == 'auto' ? setPx(markerHeight+markerBorderWidth) : bottom; 831 832 $(popover) 833 .children(':first') 834 .css('bottom', newBottom) 835 .css('cursor', 'default'); 836 837 $(marker) 838 .children(':first') 839 .append(tplHandler(data, $(popover).html())) 840 .css('cursor', 'pointer'); 841 842 return $(marker).html(); 843 844 }; 845 846 var viewLocater = function(data, markerIndex, parentWidth, markerContainer) { 847 848 var pinWidth = parseInt(data.canvas.width); 849 var pinHeight = parseInt(data.canvas.height); 850 var markerWidth = $(markerContainer).width(); 851 var markerHeight = $(markerContainer).height(); 852 853 var pos = calculatePinRate(data[markerIndex],pinWidth, markerWidth, pinHeight, markerHeight); 854 var pinLeft = pos.left; 855 var pinTop = pos.top; 856 var clas='';
857 if(parseInt(pinLeft)>=80){ 858 clas='pinLeft'; 859 }else if(parseInt(pinLeft)>50 && parseInt(pinLeft)<80){ 860 861 clas='pinCenterLeft'; 862 863 }else if(parseInt(pinLeft)>20 && parseInt(pinLeft)<=50){ 864 clas='pinCenterRight'; 865 }else{ 866 clas='pinRight'; 867 } 868 869 markerContainer = $(markerContainer).addClass(clas).css('left', pinLeft+'%').css('top', pinTop+'%') 870 871 return markerContainer; 872 873 874 }; 875 876 var tplHandler = function(data, tpl) { 877 878 if(typeof(data) == 'object') { 879 880 var callbackVars = $.fn.easypinShow.defaults.variables; 881 882 for(var i in data) { 883 884 var content = data[i]; 885 886 if(typeof(callbackVars) != 'undefined' && typeof(callbackVars[i]) == 'function') { 887 888 var args = new Array(); 889 890 // current canvas id 891 args.push($.fn.easypin.container['canvas_id']); 892 893 // current pin id 894 args.push($.fn.easypin.container['pin_id']); 895 args.push(data[i]); 896 content = callbackVars[i].apply(null, args) 897 898 } 899 900 var pattern = RegExp("\\{\\["+i+"\\]\\}", "g"); 901 tpl = tpl.replace(pattern,content); 902 } 903 } 904 905 return tpl; 906 }; 907 908 var calculatePinRate = function(data, pinWidth, markerWidth, pinHeight, markerHeight) { 909 return { 910 left: (parseInt(data.coords.lat)/pinWidth)*100, 911 top: ((parseInt(data.coords.long)-(markerHeight))/pinHeight)*100, 912 }; 913 }; 914 915 var getCssPropertyValue = function(prop, el) { 916 var el = $(el).hide().appendTo('body'); 917 var val = el.css(prop); 918 el.remove(); 919 920 return val; 921 }; 922 923 $.fn.easypin.clear = function() { 924 if(localStorage) { 925 localStorage.removeItem('easypin'); 926 }else { 927 $('input[name="easypin-store"]').val(''); 928 } 929 }; 930 931 $.fn.easypin.event = function(namespace, closure) { 932 $.fn.easypin.di(namespace, closure); 933 }; 934 935 $.fn.easypin.fire = function(namespace, params, callback) { 936 937 if(typeof($.fn.easypin.container[namespace]) != 'undefined') { 938 939 if(typeof(params) == 'function') { 940 callback = params; 941 params = null; 942 }else{ 943 params = params || null; 944 callback = callback || null; 945 } 946 947 if(typeof(callback) == 'function') { 948 var callbackArgs = new Array(); 949 callbackArgs.push(getEventData(namespace)); 950 var eventReturn = callback.apply(null, callbackArgs); 951 }else { 952 var eventReturn = getEventData(namespace); 953 } 954 955 var dependsArgs = new Array(); 956 dependsArgs.push($.fn.easypin.container['instance']); 957 dependsArgs.push(eventReturn); 958 dependsArgs.push(params); 959 $.fn.easypin.container[namespace].apply(null, dependsArgs); 960 961 } 962 }; 963 964 $.fn.easypin.config = function(attr) { 965 return $.fn.easypin.defaults[attr]; 966 }; 967 968 $.fn.easypin.di = function(key, depends) { 969
970 $.fn.easypin.container[key] = depends; 971 }; 972 973 $.fn.easypin.call = function(func, params) { 974 975 params = params || ''; 976 977 var depends = func.toString().match(/function\s*\(\s*(.*?)\s*\)/i); 978 979 if(depends.length > 1) { 980 981 depends = depends[1]; 982 983 var clientParm = depends.replace(/(\$[a-zA-Z]+)/g, ''); 984 clientParm = clientParm.replace(/\s+/g, ''); 985 clientParm = clientParm.replace(/,+/g,','); 986 clientParm = clientParm.replace(/(^,)/, ''); 987 clientParm = clientParm.split(/,/g); 988 989 expectParm = depends.match(/(\$[a-zA-Z]+)/g); 990 991 var dependsArgs = new Array(); 992 993 for(var i in expectParm) { 994 if($.fn.easypin.container[expectParm[i]]) { 995 dependsArgs.push($.fn.easypin.container[expectParm[i]]); 996 } 997 } 998 999 dependsArgs.push(params); 1000 func.apply(null, dependsArgs); 1001 } 1002 }; 1003 1004 $.fn.easypin.defaults = { 1005 1006 init: {}, 1007 limit: 0, 1008 popover: {}, 1009 exceeded: function() {}, 1010 drop: function() {}, 1011 drag: function() {}, 1012 modalWidth: '200px', 1013 widthAttribute: 'data-width', 1014 heightAttribute: 'data-height', 1015 xAttribute: 'data-x', 1016 yAttribute: 'data-y', 1017 markerSrc: 'img/marker.png', 1018 editSrc: 'img/edit.png', 1019 deleteSrc: 'img/remove.png', 1020 parentClass: 'pinParent', 1021 markerClass: 'easy-marker', 1022 hoverClass: 'hoverClass', 1023 pinMapClass: 'pinCanvas', 1024 parentPosition: 'relative', 1025 popupOpacityLayer: 'popupOpacityLayer', 1026 markerWidth: 32, 1027 markerHeight: 'auto', 1028 animate: false, 1029 posYBalance: 2, 1030 posXBalance: 2, 1031 dashWidth: 2, 1032 imageZindex: 1, 1033 pinMapZindex: 2, 1034 hoverLayerZindex: 3, 1035 markerContainerZindex: 4, 1036 markerBorderColor: '#FFFF00', 1037 downPoint: 10 1038 1039 }; 1040 1041 $.fn.easypinShow.defaults = {}; 1042 1043 $.fn.easypin.container = {}; 1044 $.fn.easypin.markerContainer = {}; 1045 1046 var setClass = function(name) { 1047 return '.'+name; 1048 }; 1049 1050 var setPx = function(num) { 1051 return num+'px'; 1052 }; 1053 1054 var getMarkerUrl = function() { 1055 return $.fn.easypin.defaults.markerSrc; 1056 }; 1057 1058 var is_open = function(type, parentElement) { 1059 1060 if(type == 'popup') { 1061 1062 var className = setClass($.fn.easypin.defaults.popupOpacityLayer); 1063 return $(className, parentElement).size() > 0; 1064 1065 } 1066 1067 }; 1068 1069 var createPopup = function(elem, markerContainer) { 1070 1071 var parentElement = $(elem.target).closest('.pinParent'); 1072 var parentIndex = $(parentElement).attr('data-index'); 1073 var targetImage = $('.easypin-target', parentElement); 1074 var widthAttr = $.fn.easypin.defaults.widthAttribute; 1075 var heightAttr = $.fn.easypin.defaults.heightAttribute; 1076 1077 // create modal base layer 1078 var opacityLayer = $('<div/>') 1079 .addClass('popupOpacityLayer') 1080 .css({ 1081 'width': '100%', 1082 'height': '100%', 1083 'background-color': 'black', 1084 'position': 'absolute', 1085 'opacity': '.0', 1086 'z-index': 14 1087 }); 1088 1089 // append to parent container 1090 $(parentElement) 1091 .append(opacityLayer) 1092 1093 // cross to child element 1094 .children(setClass($.fn.easypin.defaults.hoverClass)) 1095 .hide() // hover class hide 1096 1097 // back to parent element 1098 .parent() 1099 1100 // base layer animate 1101 .children(setClass($.fn.easypin.defaults.popupOpacityLayer)) 1102 .animate({ 1103 opacity: 0.4, 1104 }, 800); 1105 1106 var width = parseInt($(parentElement).attr(widthAttr)); 1107 var height = parseInt($(parentElement).attr(heightAttr)); 1108 1109 // create modal parent element 1110 var modalParent = $('<div/>') 1111 .addClass('modalParent') 1112 .css({ 1113 'width': '100%', 1114 'height': '100%', 1115 'position': 'absolute', 1116 'z-index': 15 1117 }) 1118 .click(function(e) { 1119 1120 if($(e.target). is('div.modalParent')) { 1121 closePopup(parentElement); 1122 } 1123 1124 e.stopPropagation(); 1125 }); 1126 1127 // clonning modal content 1128 var modalContent = $('.easy-modal:last').clone(); 1129 1130 // create modal body element 1131 var modalContext = $('<div/>') 1132 .addClass('modalContext') 1133 .css({ 1134 'background-color': '#fff', 1135 'width': $.fn.easypin.defaults.modalWidth, 1136 'opacity': '0', 1137 'position': 'absolute', 1138 'padding': '10px', 1139 '-webkit-box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)', 1140 '-moz-box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)', 1141 'box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)', 1142 '-webkit-border-radius': '5px', 1143 '-moz-border-radius': '5px', 1144 'border-radius': '5px', 1145 'cursor': 'move' 1146 })
1147 .append($(modalContent).show()) 1148 .appendTo(modalParent); // modal body append to modal parent element 1149 1150 // modal parent element append to parent element 1151 $('.popupOpacityLayer', parentElement).after(modalParent); 1152 1153 var modalHeight = $('.modalContext').height() 1154 var modalWidth = $(modalContext).width(); 1155 1156 var parentLeft = $(elem.target).closest(setClass($.fn.easypin.defaults.parentClass)).offset().left; 1157 var markerLeft = $(elem.target).offset().left; 1158 var clickPosLeft = (markerLeft - parentLeft); 1159 1160 var parentTop = $(elem.target).closest(setClass($.fn.easypin.defaults.parentClass)).offset().top; 1161 var markerTop = $(elem.target).offset().top; 1162 var clickPosTop = (markerTop - parentTop); 1163 1164 // modal position process 1165 if($(modalContent).attr('modal-position') == 'free') { 1166 1167 1168 // calculate free left position 1169 if((clickPosLeft-100) < modalWidth) { 1170 var modalLeftPosition = clickPosLeft+$(markerContainer).width()+50; 1171 }else{ 1172 var modalLeftPosition = clickPosLeft-modalWidth-100; 1173 } 1174 1175 // calculate free top position 1176 if(modalHeight > height) { 1177 var modalTopPosition = parentTop; 1178 } 1179 else if((height-clickPosTop) < modalHeight) { 1180 var modalTopPosition = height - (modalHeight+100); 1181 }else{ 1182 var modalTopPosition = clickPosTop-(modalHeight/2); 1183 } 1184 }else{ 1185 var modalLeftPosition = (width/2)-(modalWidth/2)-10; 1186 var modalTopPosition = (height/2)-($(modalContext).height()/2)-10; 1187 } 1188 1189 // modal body hide by position 1190 $(modalContext) 1191 .css('top', -(modalHeight+5)+'px') 1192 .css('left', modalLeftPosition+'px'); 1193 1194 // without onhover action (close modal) 1195 keyBinder(27, function() { 1196 if(is_open('popup', parentElement)) { 1197 closePopup(parentElement); 1198 $(document.body).unbind('keydown'); 1199 } 1200 }); 1201 1202 // on hover action (close modal) 1203 $(parentElement).hover(function() { 1204 if($(this).is(':hover') && is_open('popup', parentElement)) { 1205 keyBinder(27, function() { 1206 closePopup(parentElement); 1207 }); 1208 } 1209 },function() { 1210 $(document).unbind('keydown'); 1211 }); 1212 1213 // animate modal body 1214 $(modalContext).animate( 1215 { 1216 'top': modalTopPosition+'px', 1217 'opacity': '1' 1218 }, 1219 { 1220 duration: 'slow', 1221 easing: 'easeOutElastic' 1222 } 1223 ) 1224 .bind('mousedown', function(e) { 1225 1226 // if mouse down event is not either easy-modal, or modalContext 1227 // or modal form stop modal move 1228 if(! $(e.target).is('div.easy-modal') && !$(e.target).is('div.modalContext') && !$(e.target).is('form')) { 1229 e.stopPropagation(); 1230 return; 1231 } 1232 1233 var pinParent = $(e.currentTarget).closest('.pinParent'); 1234 var downPageY = e.pageY-$(e.currentTarget).offset().top; 1235 var downPageX = e.pageX-$(e.currentTarget).offset().left; 1236 1237 $(pinParent).bind('mousemove', function(e) { 1238 1239 $(modalContext).css({ 1240 position: 'absolute', 1241 top: setPx((e.pageY-parentElement.offset().top)-downPageY), 1242 left: setPx((e.pageX-parentElement.offset().left)-downPageX) 1243 }); 1244 1245 }); 1246 }) 1247 .bind('mouseup', function(e) { 1248 var pinParent = $(e.currentTarget).closest('.pinParent'); 1249 $(pinParent).unbind('mousemove'); 1250 }); 1251 1252 $('.easy-submit', modalContext) 1253 .click(function() { 1254 1255 var lat = $(markerContainer).attr($.fn.easypin.defaults.xAttribute); 1256 var long = $(markerContainer).attr($.fn.easypin.defaults.yAttribute); 1257 var ImgWidth = $(markerContainer).attr($.fn.easypin.defaults.widthAttribute);
1258 var ImgHeight = $(markerContainer).attr($.fn.easypin.defaults.heightAttribute); 1259 var markerIndex = $(markerContainer).attr('data-index'); 1260 var parentId = $('.easypin-target', parentElement).attr('easypin-id'); 1261 1262 // check the form exists 1263 var formExists = $('form', modalContext).size() > 0; 1264 1265 if(formExists) { 1266 var modalBody = $('form', modalContext); // form instance 1267 }else{ 1268 var modalBody = $('.easy-modal', modalContext); // current modal instance 1269 } 1270 1271 // run callback function 1272 if(typeof($.fn.easypin.defaults.done) == 'function') { 1273 1274 var result = $.fn.easypin.defaults.done(modalBody); 1275 1276 if(typeof(result) == 'boolean') { 1277 1278 if(result == true) { 1279 1280 closePopup(parentElement); 1281 }else{ 1282 return; 1283 } 1284 1285 }else{ 1286 closePopup(parentElement); 1287 } 1288 } 1289 1290 var formData = getFormData(modalBody, function(data) { 1291 1292 data['coords'] = new Object(); 1293 1294 data.coords['lat'] = lat; 1295 data.coords['long'] = long; 1296 data.coords['canvas'] = new Object(); 1297 data.coords.canvas['src'] = $(targetImage).attr('src'); 1298 data.coords.canvas['width'] = ImgWidth; 1299 data.coords.canvas['height'] = ImgHeight; 1300 1301 return data; 1302 }); 1303 1304 dataInsert(parentId, markerIndex, formData); 1305 1306 createPopover(markerContainer, formData); 1307 1308 }); 1309 1310 return modalContext; 1311 }; 1312 1313 var dataInsert = function(parentId, markerIndex, data) { 1314 1315 if(localStorage) { 1316 storageInsert(parentId, markerIndex, data); 1317 }else{ 1318 inputInsert(parentId, markerIndex, data); 1319 } 1320 }; 1321 1322 // local storage 1323 var storageInsert = function(parentId, markerIndex, data) { 1324 1325 var items = localStorage.getItem('easypin'); 1326 1327 if(! items) { 1328 var items = new Object(); 1329 }else{ 1330 try { 1331 var items = JSON.parse(items); 1332 }catch(e) { 1333 var items = new Object(); 1334 } 1335 } 1336 1337 var items = setNestedObject(parentId, markerIndex, items); 1338 1339 if(typeof(items[parentId]['canvas']) == 'undefined') { 1340 items[parentId]['canvas'] = data.coords.canvas; 1341 } 1342 1343 delete data.coords.canvas; 1344 1345 if(typeof(data['canvas']) != 'undefined') { 1346 items[parentId]['canvas'] = data.canvas; 1347 delete data.canvas; 1348 } 1349 1350 items[parentId][markerIndex] = data; 1351 1352 localStorage.setItem('easypin', toJsonString(items)); 1353 }; 1354 1355 // stores in hidden field 1356 var inputInsert = function(parentId, markerIndex, data) { 1357 1358 var items = $('input[name="easypin-store"]').val(); 1359 1360 if(! items) { 1361 var items = new Object(); 1362 }else{ 1363 try { 1364 var items = JSON.parse(decodeURIComponent(items)); 1365 }catch(e) { 1366 var items = new Object(); 1367 } 1368 } 1369 1370 var items = setNestedObject(parentId, markerIndex, items); 1371 1372 if(typeof(items[parentId]['canvas']) == 'undefined') { 1373 items[parentId]['canvas'] = data.coords.canvas; 1374 } 1375 1376 delete data.coords.canvas; 1377 1378 if(typeof(data['canvas']) != 'undefined') { 1379 items[parentId]['canvas'] = data.canvas; 1380 delete data.canvas; 1381 } 1382 1383 items[parentId][markerIndex] = data; 1384 1385 if($('input[name="easypin-store"]').size() < 1) { 1386 $(setClass($.fn.easypin.defaults.parentClass)+':first').before('<input type="hidden" name="easypin-store" value="'+encodeURIComponent(toJsonString(items))+'" />'); 1387 }else{ 1388 $('input[name="easypin-store"]').val(encodeURIComponent(toJsonString(items))); 1389 } 1390 }; 1391 1392 var dataUpdate = function(parentId, markerIndex, data) { 1393 if(localStorage) { 1394 storageUpdate(parentId, markerIndex, data); 1395 }else{ 1396 inputUpdate(parentId, markerIndex, data); 1397 } 1398 }; 1399 1400 var storageUpdate = function(parentId, markerIndex, data) { 1401 1402 var items = localStorage.getItem('easypin'); 1403 1404 if(items) { 1405 1406 try { 1407 var items = JSON.parse(items); 1408 items = setNestedObject(parentId, markerIndex, items); 1409 items[parentId][markerIndex] = merge(items[parentId][markerIndex], data); 1410 localStorage.setItem('easypin', toJsonString(items)); 1411 }catch(e) { 1412 return false;
1413 } 1414 } 1415 }; 1416 1417 var inputUpdate = function(parentId, markerIndex, data) { 1418 1419 var items = $('input[name="easypin-store"]').val(); 1420 1421 if(items) { 1422 1423 try { 1424 var items = JSON.parse(decodeURIComponent(items)); 1425 items = setNestedObject(parentId, markerIndex, items); 1426 items[parentId][markerIndex] = merge(items[parentId][markerIndex], data); 1427 $('input[name="easypin-store"]').val(encodeURIComponent(toJsonString(items))); 1428 }catch(e) { 1429 return false; 1430 } 1431 } 1432 }; 1433 1434 /** 1435 * Remove data container function 1436 * 1437 * @param parentIndex int 1438 * @param markerIndex int 1439 */ 1440 var dataRemove = function(parentId, markerIndex) { 1441 1442 if(localStorage) { 1443 removeFromStorage(parentId, markerIndex); 1444 }else{ 1445 removeFromInput(parentId, markerIndex); 1446 } 1447 1448 }; 1449 1450 /** 1451 * Remove data on input hidden field 1452 * @param {[int]} parentIndex [parent container index] 1453 * @param {[int]} markerIndex [marker container index] 1454 * @return {[void]} 1455 */ 1456 var removeFromInput = function(parentId, markerIndex) { 1457 1458 var items = $('input[name="easypin-store"]').val(); 1459 if(items) { 1460 try { 1461 var items = JSON.parse(decodeURIComponent(items)); 1462 1463 items = removeHelper(parentId, markerIndex, items) 1464 1465 var totalPin = $('input[name="easypin-store"]').size(); 1466 if(totalPin < 1) { 1467 $(setClass($.fn.easypin.defaults.parentClass)+':first').before('<input type="hidden" name="easypin-store" value="'+encodeURIComponent(toJsonString(items))+'" />'); 1468 }else{ 1469 $('input[name="easypin-store"]').val(encodeURIComponent(toJsonString(items))); 1470 } 1471 1472 } catch (e) {} 1473 1474 } 1475 1476 }; 1477 1478 /** 1479 * Remove from local storage 1480 * 1481 * @param parentIndex int 1482 * @param markerIndex int 1483 * @return void 1484 */ 1485 var removeFromStorage = function(parentId, markerIndex) { 1486 1487 var items = localStorage.getItem('easypin'); 1488 1489 if(items) { 1490 1491 try { 1492 var items = JSON.parse(items); 1493 1494 localStorage.setItem('easypin', toJsonString(removeHelper(parentId, markerIndex, items))); 1495 1496 }catch(e) {} 1497 1498 } 1499 1500 }; 1501 1502 /** 1503 * Remove process from data object 1504 * 1505 * @param {[int]} parentIndex [parent container index] 1506 * @param {[int]} markerIndex [marker container index] 1507 * @param {[object]} items [data object] 1508 * @return {[object]} 1509 */ 1510 var removeHelper = function(parentId, markerIndex, items) { 1511 1512 if(parentId && !markerIndex) { 1513 1514 if(typeof(items[parentId]) != 'undefined') { 1515 delete items[parentId]; 1516 } 1517 1518 } 1519 1520 if(parentId && markerIndex) { 1521 1522 if(typeof(items[parentId][markerIndex]) != 'undefined') { 1523 delete items[parentId][markerIndex]; 1524 1525 if(sizeof(items[parentId]) < 1 || (sizeof(items[parentId]) == 1 && typeof(items[parentId]['canvas']) != 'undefined')) { 1526 delete items[parentId]; 1527 } 1528 } 1529 1530 } 1531 1532 return items; 1533 }; 1534 1535 // set nested object 1536 /** 1537 * Set nested object 1538 * @param int parentIndex parent container index 1539 * @param int markerIndex marker ocntainer index 1540 * @param int items data object 1541 * @return object 1542 */ 1543 var setNestedObject = function(parentId, markerIndex, items) { 1544 1545 if(typeof(items[parentId]) == 'undefined') { 1546 items[parentId] = new Object(); 1547 } 1548 1549 if(typeof(items[parentId][markerIndex]) == 'undefined') { 1550 items[parentId][markerIndex] = new Object(); 1551 } 1552 1553 return items; 1554 }; 1555 1556 var getItem = function(parentIndex, markerIndex) { 1557 1558 if(localStorage) { 1559 var items = localStorage.getItem('easypin'); 1560 1561 try { 1562 items = JSON.parse(items); 1563 } catch (e) { 1564 items = {}; 1565 } 1566 }else{ 1567 var items = $('input[name="easypin-store"]').val(); 1568 1569 try { 1570 items = JSON.parse(decodeURIComponent(items)); 1571 } catch (e) { 1572 items = {}; 1573 } 1574 } 1575 1576 try { 1577 return items[parentIndex][markerIndex]; 1578 } catch (e) { 1579 return null; 1580 } 1581 }; 1582 1583 // get values of current modal 1584 var getFormData = function(element, callback) { 1585 1586 var elements = new Object(); 1587 1588 $('input, select, textarea', element).each(function() { 1589 1590 var elementType = $(this).attr('type'); 1591 var elementName = $(this).attr('name'); 1592 1593 if(elementType == 'radio') { 1594 1595 var checked = $(this).filter(":checked").val(); 1596 1597 if(typeof(checked) != 'undefined' && typeof(elements[elementName]) == 'undefined') { 1598 elements[elementName] = checked; 1599 } 1600 } 1601 1602 else if(elementType == 'checkbox') { 1603 1604 if($(this).is(':checked')) { 1605 elements[elementName] = $(this).val(); 1606 } 1607 } 1608 else{ 1609 if(typeof($(this).val()) != 'undefined') { 1610 elements[elementName] = $(this).val(); 1611 } 1612 } 1613 1614 }); 1615 1616 if(typeof(callback) == 'function') { 1617 1618 var args = new Array(); 1619 args.push(elements);
1620 return callback.apply(null, args); 1621 1622 } 1623 1624 return elements; 1625 }; 1626 1627 var toJsonString = function(data) { 1628 return JSON.stringify(data); 1629 }; 1630 1631 // modal close 1632 var closePopup = function(parentElement) { 1633 1634 // close opacity layer 1635 $(setClass($.fn.easypin.defaults.popupOpacityLayer), parentElement) 1636 .animate( 1637 { 1638 opacity:0 1639 }, 1640 'fast', // how fast we are animating 1641 'swing', // the type of easing 1642 function() { 1643 $(this).remove(); 1644 } 1645 ); 1646 1647 var modalHeight = $('.modalContext', parentElement).height(); 1648 var modalWidth = $('.modalContext', parentElement).width(); 1649 1650 // animate modal body 1651 $('.modalContext', parentElement).animate( 1652 { 1653 'top': -(modalHeight+50)+'px', 1654 'opacity': '0', 1655 'z-index': 0 1656 }, 1657 { 1658 duration: 'slow', 1659 easing: 'easeOutElastic', 1660 complete: function() { 1661 $('.modalParent', parentElement).remove(); 1662 } 1663 } 1664 ); 1665 }; 1666 1667 var keyBinder = function(expectCode, callback) { 1668 1669 $(document).bind('keydown', function(e) { 1670
1671 if(e.which == expectCode) { 1672 1673 callback.apply(null); 1674 1675 $(this).unbind('keydown'); 1676 } 1677 }); 1678 }; 1679 1680 var setIndex = function(selector, parent) { 1681 1682 var index = $(selector+':last', parent).attr('data-index'); 1683 1684 if(typeof(index) == 'undefined') { 1685 return '0'; 1686 } 1687 1688 return parseInt(index)+1; 1689 }; 1690 1691 var sizeof = function(data) { 1692 if(typeof(data) == 'object') { 1693 var j = 0; 1694 1695 for(var i in data) { 1696 j++; 1697 } 1698 1699 return j; 1700 } 1701 }; 1702 1703 /** 1704 * Set to input fields all data 1705 * @param int parentIndex parent container index 1706 * @param int markerIndex marker container index 1707 * @param object modalInstance current modal instance 1708 * @return void 1709 */ 1710 var setDataToFields = function(parentId, markerIndex, modalInstance) { 1711 1712 var item = getItem(parentId, markerIndex); 1713 1714 if(typeof(item) == 'object') { 1715 1716 for(var i in item) { 1717 1718 var element = $('[name="'+i+'"]', modalInstance); 1719 var type = $(element).prop('type'); 1720 1721 if(type == 'text' || type == 'hidden') { 1722 $(element).attr('value', item[i]); 1723 } 1724 1725 else if(type == 'checkbox') { 1726 $(element).attr('checked', true); 1727 } 1728 1729 else if(type == 'radio') { 1730 $('[value="'+item[i]+'"]', modalInstance).attr('checked', true); 1731 } 1732 1733 else if(type == 'textarea') { 1734 $(element).val(item[i]); 1735 } 1736 1737 else if(type == 'select-one') { 1738 $(element).val(item[i]).prop('selected', true); 1739 } 1740 1741 } 1742 1743 } 1744 }; 1745 1746 var createPopover = function(markerContainer, formData) { 1747 1748 // check and set popover callbacks 1749 var popoverCallBacks = sizeof($.fn.easypin.defaults.popover) > 0 ? $.fn.easypin.defaults.popover : false; 1750 1751 var arrow = $('<div/>') 1752 .addClass('popover-arrow-down') 1753 .css({ 1754 width: 0, 1755 height: 0, 1756 'border-left': '10px solid transparent', 1757 'border-right': '10px solid transparent', 1758 'border-top': '10px solid #000', 1759 'opacity': '.8', 1760 position: 'absolute', 1761 bottom: '-50px', 1762 left: '58px' 1763 }); 1764
1765 var tooltipContainer = $('<div/>') 1766 .addClass('popover') 1767 .css('position', 'absolute') 1768 .css('display','inline') 1769 .css('top', '-51px') 1770 .css('left', '-51px') 1771 .css('opacity', '0'); 1772 1773 var popoverHtml = $('[popover]:last').clone(); 1774 popoverHtml.removeAttr('popover'); 1775 var toHtml = popoverHtml.html(); 1776 var popoverUserWidth = popoverHtml.attr('width') ? popoverHtml.attr('width') : 150; 1777 1778 var defaultStyle = { 1779 color: '#FFFFFF', 1780 background: '#000000', 1781 opacity: '.8', 1782 height: 'auto', 1783 'line-height': '40px', 1784 'border-radius': '5px', 1785 cursor: 'context-menu' 1786 }; 1787 1788 if(typeof($.fn.easypin.defaults.popoverStyle) == 'object') { 1789 delete $.fn.easypin.defaults.popoverStyle.width; 1790 delete $.fn.easypin.defaults.popoverStyle.position; 1791 popoverStyle = merge(defaultStyle, $.fn.easypin.defaults.popoverStyle); 1792 }else{ 1793 popoverStyle = defaultStyle; 1794 } 1795 1796 var span = $('<span/>') 1797 .addClass('popoverContent') 1798 .css({ 1799 position: 'absolute', 1800 width:setPx(popoverUserWidth) 1801 }) 1802 .css(popoverStyle); 1803 1804 var bgColor = $(span).css('background-color'); 1805 1806 $(arrow).css('border-top-color', bgColor); 1807 1808 if(popoverHtml.attr('shadow') == 'true') { 1809 $(span) 1810 .css({ 1811 '-webkit-box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)', 1812 '-moz-box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)', 1813 'box-shadow': '10px 13px 5px 0px rgba(0,0,0,0.75)' 1814 }); 1815 } 1816 1817 // delete canvas parameters 1818 delete formData['canvas']; 1819 1820 for(var i in formData) { 1821 1822 // callback check and run 1823 if(popoverCallBacks && typeof(popoverCallBacks[i]) == 'function') { 1824 var args = new Array(); 1825 args.push(formData[i]); 1826 formData[i] = popoverCallBacks[i].apply(null, args); 1827 } 1828 1829 var pattern = RegExp("\\{\\["+i+"\\]\\}", "g"); 1830 toHtml = toHtml.replace(pattern,formData[i]); 1831 1832 } 1833 1834 $(span).append(toHtml); 1835 $(tooltipContainer).append(span).append(arrow); 1836 1837 // remove previous popover 1838 if($('div.popover', markerContainer).size() > 0) { 1839 // animate modal body 1840 $('div.popover', markerContainer).animate( 1841 { 1842 'top': '-'+setPx((popoverHeight-15)), 1843 'opacity': '0' 1844 }, 1845 { 1846 duration: 'slow', 1847 easing: 'easeOutElastic', 1848 complete: function() { 1849 $(this).remove(); 1850 } 1851 } 1852 ); 1853 } 1854 1855 // popover element apend yo marker container 1856 $(markerContainer).prepend(tooltipContainer); 1857 1858 var popoverEl = $('div.popover > span:first', markerContainer); 1859 var popoverHeight = popoverEl.height(); 1860 var popoverWidth = popoverEl.width(); 1861 1862 // set popover container position 1863 $(tooltipContainer) 1864 .css('top', '-'+setPx((popoverHeight+12)-10)) 1865 .css('left', '-'+setPx((popoverWidth/2)-16)); 1866 1867 // set arrow position 1868 $(arrow, tooltipContainer) 1869 .css('left', setPx((popoverWidth/2)-10)) 1870 .css('top', setPx(popoverHeight)); 1871 1872 // animate modal body 1873 $(tooltipContainer).animate( 1874 { 1875 'top': '-'+setPx((popoverHeight+12)), 1876 'opacity': '1' 1877 }, 1878 { 1879 duration: 'slow', 1880 easing: 'easeOutElastic' 1881 } 1882 ); 1883 }; 1884 1885 var initPin = function(imgIndex, element) { 1886 1887 var initData = $.fn.easypin.defaults.init; 1888 var config = getConfigs(); 1889 1890 if(typeof(initData) == 'string') { 1891 initData = JSON.parse(initData) 1892 } 1893 1894 var parentElement = $(element).parents(setClass(config.parentClass)); 1895 1896 if(sizeof(initData) > 0 && $(element).attr('easypin-init') != 'false') { 1897 1898 // canvas border width 1899 var dashWidth = $.fn.easypin.defaults.dashWidth; 1900 1901 // get x, y balance value 1902 var posYBalance = config.posYBalance; 1903 var posXBalance = config.posXBalance; 1904 1905 // get current target image instance 1906 var targetImage = $('img'+setClass('easypin-target'), parentElement); 1907 1908 if(typeof(initData[imgIndex]) == 'undefined') { 1909 return; 1910 } 1911 1912 for(var i in initData[imgIndex]) { 1913 1914 if(isNaN(i) === true) return; 1915
1916 var imageWidth = parseInt(initData[imgIndex].canvas.width); 1917 var imageHeight = parseInt(initData[imgIndex].canvas.height); 1918 var lat = parseInt(initData[imgIndex][i].coords.lat); 1919 var long = parseInt(initData[imgIndex][i].coords.long); 1920 // set cursor position coordinate 1921 var imagePositionY = targetImage.offset().top - (config.dashWidth-posYBalance); 1922 var imagePositionX = targetImage.offset().left - (config.dashWidth-posXBalance); 1923 1924 var clickPosX = lat;//(lat-imagePositionX); 1925 var clickPosY = long;//(long-imagePositionY); 1926 // get marker half size (width/height) 1927 var markerWidthHalf = (config.markerWidth/2); 1928 var markerHeightHalf = (config.markerHeight/2); 1929 1930 // set canvas border position 1931 var markerBorderX = clickPosX-(config.markerWidth/2); 1932 var markerBorderY = clickPosY-(config.markerHeight/2); 1933 1934 if(markerBorderX < 0) { 1935 markerBorderX = 0; 1936 } 1937 else if(clickPosX+markerWidthHalf > imageWidth) { 1938 markerBorderX = imageWidth-config.markerWidth; 1939 } 1940 1941 if(markerBorderY < 0) { 1942 markerBorderY = 0; 1943 } 1944 else if(clickPosY+markerHeightHalf > imageHeight) { 1945 markerBorderY = imageHeight-config.markerHeight; 1946 } 1947 1948 var absX = markerBorderX.toFixed(3)-markerWidthHalf; 1949 var absY = markerBorderY.toFixed(3)-markerHeightHalf; 1950 1951 // create tool 1952 var tools = createTools({ 1953 markerWidth: config.markerWidth, 1954 markerHeight: config.markerHeight 1955 }); 1956 1957 // create marker container 1958 var markerContainer = createMarker({ 1959 tools: tools, 1960 parentElement: parentElement, 1961 markerClass: config.markerClass, 1962 markerBorderX: markerBorderX, 1963 markerBorderY: markerBorderY, 1964 marginLeft: (config.markerWidth/2), 1965 marginTop: -(config.markerHeight/2), 1966 markerWidth: config.markerWidth, 1967 markerHeight: config.markerHeight, 1968 markerContainerZindex: config.markerContainerZindex, 1969 absX: absX, 1970 absY: absY, 1971 imageWidth: imageWidth, 1972 imageHeight: imageHeight, 1973 parentElement: parentElement, 1974 src: config.src 1975 }); 1976 1977 var markerIndex = $(markerContainer).attr('data-index'); 1978 var markerData = merge(initData[imgIndex][i], {'canvas': initData[imgIndex]['canvas']}); 1979 1980 dataInsert(imgIndex, markerIndex, markerData); 1981 createPopover(markerContainer, initData[imgIndex][i]); 1982 } 1983 } 1984 }; 1985 1986 var createRandomId = function() { 1987 var length = 10; 1988 var strings = 'abcdefghijklmnoprstuvyzABCDEFGHIJKLMNOPRSTUVYZ1234567890_'; 1989 1990 var key = ''; 1991 1992 for(var i = 1; i<=length; i++) { 1993 1994 var randNum = Math.floor(Math.random() * (strings.length - 1 + 1) + 1); 1995 1996 if(typeof(strings[randNum]) != 'undefined') { 1997 key += strings[randNum]; 1998 } 1999 2000 } 2001 2002 return key; 2003 }; 2004 2005 var getConfigs = function() { 2006 2007 return { 2008 src: $.fn.easypin.defaults.markerSrc, 2009 markerWidth: $.fn.easypin.defaults.markerWidth, 2010 markerHeight: $.fn.easypin.defaults.markerHeight == 'auto' ? $.fn.easypin.defaults.markerWidth : $.fn.easypin.defaults.markerHeight, 2011 markerClass: $.fn.easypin.defaults.markerClass, 2012 parentClass: $.fn.easypin.defaults.parentClass, 2013 markerContainerZindex: $.fn.easypin.defaults.markerContainerZindex, 2014 // canvas border width 2015 dashWidth: $.fn.easypin.defaults.dashWidth, 2016 // get x, y balance value 2017 posYBalance: $.fn.easypin.defaults.posYBalance, 2018 posXBalance: $.fn.easypin.defaults.posXBalance, 2019 // canvas border width 2020 dashWidth: $.fn.easypin.defaults.dashWidth 2021 }; 2022 }; 2023 2024 /* 2025 * Recursively merge properties of two objects 2026 */ 2027 function merge(obj1, obj2) { 2028 2029 for (var p in obj2) { 2030 try { 2031 obj1[p] = obj2[p]; 2032 2033 } catch(e) { 2034 // Property in destination object not set; create it and set its value. 2035 obj1[p] = obj2[p]; 2036 2037 } 2038 } 2039 2040 return obj1; 2041 } 2042}(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.