1var SEAOLasso = new Class({ 2 3 Implements : [Options, Events], 4 5 active : false, 6 7 options : { 8 autoHide: true, 9 cropMode : false, 10 globalTrigger : false, 11 min : false, 12 max : false, 13 ratio : false, 14 contain : false, 15 trigger : null, 16 border : '#999', 17 color : '#7389AE', 18 opacity : .3, 19 zindex : 10000, 20 bgimage : './blank.gif' 21 }, 22 23 binds : {}, 24 25 initialize : function(options){ 26 this.setOptions(options); 27 28 this.box = new Element('div', { 29 'styles' : { 30 'display' : 'none', 31 'position' : 'absolute', 32 'z-index' : this.options.zindex 33 } 34 }).inject((this.container) ? this.container : document.body); 35 36 this.overlay = new Element('div',{ 37 'class' : 'lasso-overlay', 38 'styles' : { 39 'position' : 'relative', /* 40 'background' : 'url('+this.options.bgimage+')',*/ 'height' : '100%', 41 'width' : '100%', 42 'z-index' : this.options.zindex+1 43 } 44 }).inject(this.box); 45 46 this.mask = new Element('div',{ 47 'styles' : { 48 'position' : 'absolute', 49 'background-color' : this.options.color, 50 'opacity' : this.options.opacity, 51 'height' : '100%', 52 'width' : '100%', 53 'z-index' : this.options.zindex-1 54 } 55 }); 56 57 if(this.options.cropMode){ 58 this.mask.setStyle('z-index',this.options.zindex-2).inject(this.container); 59 this.options.trigger = this.mask; // override trigger since we are a crop 60 } else { 61 this.mask.inject(this.overlay); 62 } 63 64 this.trigger = $(this.options.trigger); 65 66 // Marching Ants 67 var antStyles = { 68 'position' : 'absolute', 69 'width' : 1, 70 'height' : 1, 71 'overflow' : 'hidden', 72 'z-index' : this.options.zindex+1 73 }; 74 75 if( this.options.border.test(/\.(jpe?g|gif|png)/) ) antStyles.backgroundImage = 'url('+this.options.border+')'; 76 else var antBorder = '1px dashed '+this.options.border; 77 78 this.marchingAnts = {}; 79 ['left','right','top','bottom'].each(function(side,idx){ 80 switch(side){ 81 case 'left' : 82 style = $merge(antStyles,{ 83 top : 0, 84 left : -1, 85 height : '100%' 86 }); 87 break; 88 case 'right' : 89 style = $merge(antStyles,{ 90 top : 0, 91 right : -1, 92 height : '100%' 93 }); 94 break; 95 case 'top' : 96 style = $merge(antStyles,{ 97 top : -1, 98 left : 0, 99 width : '100%' 100 }); 101 break; 102 case 'bottom' : 103 style = $merge(antStyles,{ 104 bottom : -1, 105 left : 0, 106 width : '100%' 107 }); 108 break; 109 } 110 if(antBorder) style['border-'+side] = antBorder; 111 this.marchingAnts[side] = new Element('div',{ 112 'styles' : style 113 }).inject(this.overlay); 114 },this); 115 116 this.binds.start = this.start.bindWithEvent(this); 117 this.binds.move = this.move.bindWithEvent(this); 118 this.binds.end = this.end.bindWithEvent(this); 119 120 this.attach(); 121 122 document.body.onselectstart = function(e){ 123 e = new Event(e).stop(); 124 return false; 125 }; 126 127 // better alternative? 128 this.removeDOMSelection = (document.selection && document.selection.empty) ? function(){ 129 document.selection.empty(); 130 } : 131 (window.getSelection) ? function(){ 132 var s=window.getSelection(); 133 if(s && s.removeAllRanges) s.removeAllRanges(); 134 } : $lambda(false); 135 136 this.resetCoords(); 137 }, 138 139 attach : function(){ 140 this.trigger.addEvent('mousedown', this.binds.start); 141 }, 142 143 detach : function(){ 144 if(this.active) this.end(); 145 this.trigger.removeEvent('mousedown', this.binds.start); 146 }, 147 148 start : function(event){ 149 if((!this.options.autoHide && event.target == this.box) || (!this.options.globalTrigger && (this.trigger != event.target))) return false; 150 this.active = true; 151 document.addEvents({ 152 'mousemove' : this.binds.move, 153 'mouseup' : this.binds.end 154 }); 155 this.resetCoords(); 156 if(this.options.contain) this.getContainCoords(); 157 if(this.container) this.getRelativeOffset(); 158 this.setStartCoords(event.page); 159 this.fireEvent('start'); 160 return true; 161 }, 162 163 move : function(event){ 164 if(!this.active) return false;
165 166 this.removeDOMSelection(); // clear as fast as possible! 167 168 // saving bytes s = start, m = move, c = container 169 var s = this.coords.start, m = event.page, box = this.coords.box = {}, c = this.coords.container; 170 171 if(this.container){ 172 m.y -= this.offset.top; 173 m.x -= this.offset.left; 174 } 175 176 var f = this.flip = { 177 y : (s.y > m.y), 178 x : (s.x > m.x) 179 }; // flipping orgin? compare start to move 180 box.y = (f.y) ? [m.y,s.y] : [s.y, m.y]; // order y 181 box.x = (f.x) ? [m.x,s.x] : [s.x, m.x]; // order x 182 183 if(this.options.contain){ 184 if(box.y[0] < c.y[0] ) box.y[0] = c.y[0]; // constrain top 185 if(box.y[1] > c.y[1] ) box.y[1] = c.y[1]; // constrain bottom 186 if(box.x[0] < c.x[0] ) box.x[0] = c.x[0]; // constrain left 187 if(box.x[1] > c.x[1] ) box.x[1] = c.x[1]; // constrain right 188 } 189 190 if(this.options.max){ // max width & height 191 if( box.x[1] - box.x[0] > this.options.max[0]){ // width is larger then max, fix 192 if(f.x) box.x[0] = box.x[1] - this.options.max[0]; // if flipped 193 else box.x[1] = box.x[0] + this.options.max[0]; // if normal 194 } 195 if( box.y[1] - box.y[0] > this.options.max[1]){ // height is larger then max, fix 196 if(f.y) box.y[0] = box.y[1] - this.options.max[1]; // if flipped 197 else box.y[1] = box.y[0] + this.options.max[1]; // if normal 198 } 199 } 200 201 // ratio constraints 202 if(this.options.ratio){ 203 var ratio = this.options.ratio; 204 // get width/height divide by ratio 205 var r = { 206 x : (box.x[1] - box.x[0]) / ratio[0], 207 y : (box.y[1] - box.y[0]) / ratio[1] 208 }; 209 if(r.x > r.y){ // if width ratio is bigger fix width 210 if(f.x) box.x[0] = box.x[1] - (r.y * ratio[0]); // if flipped width fix 211 else box.x[1] = box.x[0] + (r.y * ratio[0]); // normal width fix 212 } else if( r.x < r.y){ // if height ratio is bigger fix height 213 if(f.y) box.y[0] = box.y[1] - (r.x * ratio[1]); // if flipped height fix 214 else box.y[1] = box.y[0] + (r.x * ratio[1]); // normal height fix 215 } 216 } 217 218 this.refresh(); 219 return true; 220 }, 221 222 refresh : function(){ 223 var c = this.coords, box = this.coords.box, cc = this.coords.container; 224 c.w = box.x[1] - box.x[0]; 225 c.h = box.y[1] - box.y[0]; 226 c.top = box.y[0]; 227 c.left = box.x[0]; 228 this.box.setStyles({ 229 'display' : 'block', 230 'top' : c.top, 231 'left' : c.left, 232 'width' : c.w, 233 'height' : c.h 234 }); 235 this.fireEvent('resize',this.getRelativeCoords()); 236 }, 237 238 end : function(event){ 239 if(!this.active) return false; 240 this.active = false; 241 document.removeEvents({ 242 'mousemove' : this.binds.move, 243 'mouseup' : this.binds.end 244 }); 245 if(this.options.autoHide) this.resetCoords(); 246 else if(this.options.min){ 247 if(this.coords.w < this.options.min[0] || this.coords.h < this.options.min[1]) this.resetCoords(); 248 } 249 var ret = (this.options.autoHide) ? null : this.getRelativeCoords(); 250 this.fireEvent('complete',ret); 251 return true; 252 }, 253 254 setStartCoords : function(coords){ 255 if(this.container){ 256 coords.y -= this.offset.top; 257 coords.x -= this.offset.left; 258 } 259 this.coords.start = coords; 260 this.coords.w = 0; 261 this.coords.h = 0; 262 this.box.setStyles({ 263 'display' : 'block', 264 'top' : this.coords.start.y, 265 'left' : this.coords.start.x 266 }); 267 }, 268 269 resetCoords : function(){ 270 this.coords = { 271 start : { 272 x : 0, 273 y : 0 274 }, 275 move : { 276 x : 0, 277 y : 0 278 }, 279 end : { 280 x: 0, 281 y: 0 282 }, 283 w: 0, 284 h: 0 285 }; 286 this.box.setStyles({ 287 'display' : 'none', 288 'top' : 0, 289 'left' : 0, 290 'width' : 0, 291 'height' : 0 292 }); 293 this.getContainCoords(); 294 }, 295 296 getRelativeCoords : function(){ 297 var box = this.coords.box, cc = $merge(this.coords.container), c = this.coords; 298 if(!this.options.contain) cc = { 299 x : [0,0], 300 y : [0,0] 301 }; 302 return { 303 x : (box.x[0] - cc.x[0]).toInt(), 304 y : (box.y[0] - cc.y[0]).toInt(), 305 w : (c.w).toInt(), 306 h : (c.h).toInt() 307 }; 308 }, 309 310 getContainCoords : function(){ 311 var tc = this.trigger.getCoordinates(this.container); 312 this.coords.container = { 313 y : [tc.top,tc.top+tc.height], 314 x : [tc.left,tc.left+tc.width] 315 }; // FIXME 316 }, 317 318 getRelativeOffset : function(){ 319 this.offset = this.container.getCoordinates(); 320 }, 321 322 reset : function(){ 323 this.detach(); 324 }, 325 326 destroy : function(){ 327 this.detach(); 328 this.mask.destroy(); 329 this.overlay.destroy(); 330 this.box.destroy();/* 331 $H(this.marchingAnts).each(function(el){ 332 el.destroy(); 333 });*/ 334 } 335 336}); 337
338SEAOLasso.Crop = new Class({ 339 340 Extends : SEAOLasso, 341 342 options : { 343 autoHide : false, 344 cropMode : true, 345 contain : true, 346 handleSize : 8, 347 preset : false, 348 handleStyle : { 349 'border' : '1px solid #000', 350 'background-color' : '#ccc' , 351 opacity : .75 352 }, 353 handlePreventsDefault : true 354 }, 355 356 initialize : function(img,options){ 357 358 this.img = $(img); 359 if( this.img.get('tag') != 'img' ) return false; 360 361 var coords = this.img.getCoordinates(); 362 363 // the getCoordinates adds 2 extra pixels 364 var widthFix = coords.width - 2; 365 var heightFix = coords.height - 2; 366 367 this.container = new Element('div', { 368 'id' :'lassoMask', 369 'styles' : { 370 'position' : 'relative', 371 'width' : widthFix, 372 'height' : heightFix 373 } 374 }).inject(this.img, 'after'); 375 376 this.img.setStyle('display', 'none'); 377 378 options.p = this.container; 379 380 381 this.crop = new Element('img', { 382 'src' : this.img.get('src'), 383 styles : { 384 'position' : 'absolute', 385 'top' : 0, 386 'left' : 0, 387 'width' : widthFix +1, 388 'height' : heightFix +1, 389 'padding' : 0, 390 'margin' : 0, 391 'z-index' : this.options.zindex-1 392 } 393 }).inject(this.container); 394 395 396 this.parent(options); 397 398 this.binds.handleMove = this.handleMove.bind(this); 399 this.binds.handleEnd = this.handleEnd.bind(this); 400 this.binds.handles = {}; 401 402 this.handles = {}; // stores resize handler elements 403 // important! this setup a matrix for each handler, patterns emerge when broken into 3x3 grid. Faster/easier processing. 404 this.handlesGrid = { 405 'NW':[0,0], 406 'N':[0,1], 407 'NE':[0,2], 408 'W':[1,0], 409 'E':[1,2], 410 'SW':[2,0], 411 'S':[2,1], 412 'SE':[2,2] 413 }; 414 // this could be more elegant! 415 ['NW','N','NE','W','E','SW','S','SE'].each(function(handle){ 416 var grid = this.handlesGrid[handle]; // grab location in matrix 417 this.binds.handles[handle] = this.handleStart.bindWithEvent(this,[handle,grid[0],grid[1]]); // bind 418 this.handles[handle] = new Element("div", { 419 'styles' : $merge({ 420 'position' : 'absolute', 421 'display' : 'block', 422 'visibility' : 'hidden', 423 'width' : this.options.handleSize, 424 'height' : this.options.handleSize, 425 'overflow' : 'hidden', 426 'cursor' : (handle.toLowerCase()+'-resize'), 427 'z-index' : this.options.zindex+2 428 },this.options.handleStyle), 429 'events' : { 430 'mousedown' : this.binds.handles[handle] 431 } 432 }).inject(this.box,'bottom'); 433 // start - Webligo Developments 434 // Seems to not let them be hidden for some reason 435 this.handles[handle].style.visibility = 'hidden'; 436 // end - Webligo Developments 437 },this); 438 439 this.binds.drag = this.handleStart.bindWithEvent(this,['DRAG',1,1]); 440 this.overlay.addEvent('mousedown', this.binds.drag); 441 442 this.setDefault(); 443 }, 444 445 setDefault : function(){ 446 if(!this.options.preset) return this.resetCoords(); 447 this.getContainCoords(); 448 this.getRelativeOffset(); 449 var c = this.coords.container, d = this.options.preset; 450 this.coords.start = { 451 x : d[0], 452 y : d[1] 453 }; 454 this.active = true; 455 this.move({ 456 page : { 457 x: d[2]+this.offset.left, 458 y: d[3]+this.offset.top 459 } 460 }); 461 this.active = false; 462 }, 463 464 handleStart : function(event,handle,row,col){ 465 this.currentHandle = { 466 'handle' : handle, 467 'row' : row, 468 'col' : col 469 }; // important! used for easy matrix transforms. 470 document.addEvents({ 471 'mousemove' : this.binds.handleMove, 472 'mouseup' : this.binds.handleEnd 473 }); 474 // had to merge because we don't want to effect the class instance of box. we want to record it 475 event.page.y -= this.offset.top; 476 event.page.x -= this.offset.left; 477 this.coords.hs = { 478 's' : event.page, 479 'b' : $merge(this.coords.box) 480 }; // handler start (used for 'DRAG') 481 this.active = true; 482 483 if( this.options.handlePreventsDefault ) { 484 event.stop(); 485 } 486 }, 487 488 handleMove : function(event){ 489 var box = this.coords.box, c = this.coords.container, m = event.page, cur = this.currentHandle, s = this.coords.start; 490 m.y -= this.offset.top; 491 m.x -= this.offset.left; 492 if(cur.handle == 'DRAG'){ // messy? could probably be optimized. 493 var hs = this.coords.hs, xm = m.x - hs.s.x, ym = m.y - hs.s.y, diff;
494 box.y[0] = hs.b.y[0] + ym; 495 box.y[1] = hs.b.y[1] + ym; 496 box.x[0] = hs.b.x[0] + xm; 497 box.x[1] = hs.b.x[1] + xm; 498 if((diff = box.y[0] - c.y[0]) < 0) { 499 box.y[0] -= diff; 500 box.y[1] -= diff; 501 } // constrains drag North 502 if((diff = box.y[1] - c.y[1]) > 0) { 503 box.y[0] -= diff; 504 box.y[1] -= diff; 505 } // constrains drag South 506 if((diff = box.x[0] - c.x[0]) < 0) { 507 box.x[0] -= diff; 508 box.x[1] -= diff; 509 } // constrains drag West 510 if((diff = box.x[1] - c.x[1]) > 0) { 511 box.x[0] -= diff; 512 box.x[1] -= diff; 513 } // constrains drag East 514 return this.refresh(); 515 } 516 517 // handles flipping ( nw handle behaves like a se when past the orgin ) 518 if(cur.row == 0 && box.y[1] < m.y){ 519 cur.row = 2; 520 } // fixes North passing South 521 if(cur.row == 2 && box.y[0] > m.y){ 522 cur.row = 0; 523 } // fixes South passing North 524 if(cur.col == 0 && box.x[1] < m.x){ 525 cur.col = 2; 526 } // fixes West passing East 527 if(cur.col == 2 && box.x[0] > m.x){ 528 cur.col = 0; 529 } // fixes East passing West 530 531 if(cur.row == 0 || cur.row == 2){ // if top or bottom row ( center e,w are special case) 532 s.y = (cur.row) ? box.y[0] : box.y[1]; // set start.y opposite of current direction ( anchor ) 533 if(cur.col == 0){ 534 s.x = box.x[1]; 535 } // if West side anchor East 536 if(cur.col == 1){ 537 s.x = box.x[0]; 538 m.x = box.x[1]; 539 } // if center lock width 540 if(cur.col == 2){ 541 s.x = box.x[0]; 542 } // if East side anchor West 543 } 544 545 if(!this.options.ratio){ // these handles only apply when ratios are not in effect. center handles don't makes sense on ratio 546 if(cur.row == 1){ // sanity check make sure we are dealing with the right handler 547 if(cur.col == 0){ 548 s.y = box.y[0]; 549 m.y = box.y[1]; 550 s.x = box.x[1]; 551 } // if West lock height anchor East 552 else if(cur.col == 2){ 553 s.y = box.y[0]; 554 m.y = box.y[1]; 555 s.x = box.x[0]; 556 }// if East lock height anchor West 557 } 558 } 559 m.y += this.offset.top; 560 m.x += this.offset.left; 561 this.move(event); // now that we manipulated event pass it to move to manage. 562 563 if( this.options.handlePreventsDefault ) { 564 event.stop(); 565 } 566 }, 567 568 handleEnd : function(event){ 569 document.removeEvents({ 570 'mousemove' : this.binds.handleMove, 571 'mouseup' : this.binds.handleEnd 572 }); 573 this.active = false; 574 this.currentHandle = false; 575 if(this.options.min && (this.coords.w < this.options.min[0] || this.coords.h < this.options.min[1])){ 576 if(this.options.preset) this.setDefault(); 577 else this.resetCoords(); 578 } 579 580 if( this.options.handlePreventsDefault ) { 581 event.stop(); 582 } 583 }, 584 585 end : function(event){ 586 if(!this.parent(event)) return false; 587 if(this.options.min && (this.coords.w < this.options.min[0] || this.coords.h < this.options.min[1])){ 588 this.setDefault(); 589 } 590 }, 591 592 resetCoords : function(){ 593 this.parent(); 594 this.coords.box = { 595 x : [0,0], 596 y : [0,0] 597 }; 598 this.hideHandlers(); 599 //this.crop.setStyle('clip', 'rect(0px 0px 0px 0px)'); 600 }, 601 602 showHandlers : function(){ 603 var box = this.coords.box; 604 605 if(this.options.min && (this.coords.w < this.options.min[0] || this.coords.h < this.options.min[1])) this.hideHandlers(); 606 607 else { 608 var tops = [], lefts = [], pxdiff = (this.options.handleSize / 2)+1; // used to store location of handlers 609 for(var cell = 0, cells = 2; cell <= cells; cell++ ){ // using matrix again 610 tops[cell] = ( (cell == 0) ? 0 : ((cell == 2) ? box.y[1] - box.y[0] : (box.y[1] - box.y[0])/2 ) ) - pxdiff; 611 lefts[cell] = ( (cell == 0) ? 0 : ((cell == 2) ? box.x[1] - box.x[0] : (box.x[1] - box.x[0])/2 ) ) - pxdiff; 612 } 613 614 for(var handleID in this.handlesGrid){ // get each handler's matrix location 615 var grid = this.handlesGrid[handleID], handle = this.handles[handleID]; 616 if(!this.options.ratio || (grid[0] != 1 && grid[1] != 1)
616){ // if no ratio or not N,E,S,W show 617 if(this.options.min && this.options.max){ 618 if((this.options.min[0] == this.options.max[0]) && (grid[1] % 2) == 0) continue; // turns off W&E since width is set 619 if(this.options.min[1] == this.options.max[1] && (grid[0] % 2) == 0) continue; // turns off N&S since height is set 620 } 621 handle.setStyles({ 622 'visibility' : 'visible', 623 'top' : tops[grid[0]], 624 'left' : lefts[grid[1]] 625 }); // just grab from grid 626 } 627 } 628 } 629 }, 630 631 hideHandlers : function(){ 632 for(handle in this.handles){ 633 this.handles[handle].setStyle('visibility','hidden'); 634 } 635 }, 636 637 refresh : function(){ 638 this.parent(); 639 var box = this.coords.box, cc = this.coords.container; 640 641 if(Browser.Engine.trident && Browser.Engine.version < 5 && this.currentHandle && this.currentHandle.col === 1) 642 this.overlay.setStyle('width' , '100.1%').setStyle('width','100%'); 643 644 // this.crop.setStyle('clip' , 'rect('+(box.y[0])+'px '+(box.x[1])+'px '+(box.y[1])+'px '+(box.x[0])+'px )' ); 645 this.showHandlers(); 646 }, 647 648 destroy : function(){ 649 this.parent(); 650 651 this.img.inject(this.container, 'after'); 652 this.img.setStyle('display', ''); 653 this.container.destroy();/* 654 $H(this.handles).each(function(el){ 655 el.destroy(); 656 });*/ 657 } 658 659}); 660 661 662 663var SEAOTagger = new Class({ 664 665 Implements : [Events, Options], 666 667 options : { 668 // Local options 669 'title' : false, 670 'description' : false, 671 'transImage' : 'application/modules/Seaocore/externals/images/trans.gif', 672 'existingTags' : [], 673 'tagListElement' : false, 674 'linkElement' : false, 675 'noTextTagHref' : true, 676 'guid' : false, 677 'enableCreate' : false, 678 'enableDelete' : false, 679 680 // Create 681 'createRequestOptions' : { 682 'url' : '', 683 'data' : { 684 'format' : 'json' 685 } 686 }, 687 'deleteRequestOptions' : { 688 'url' : '', 689 'data' : { 690 'format' : 'json' 691 } 692 }, 693 694 // Cropper options 695 'cropOptions' : { 696 'preset' : [10,10,58,58], 697 'min' : [48,48], 698 'max' : [128,128], 699 'handleSize' : 8, 700 'opacity' : .6, 701 'color' : '#7389AE', 702 'border' : 'externals/moolasso/crop.gif' 703 }, 704 705 // Autosuggest options 706 'suggestProto' : 'local', 707 'suggestParam' : [ 708 709 ], 710 'suggestOptions' : { 711 'minLength': 0, 712 'maxChoices' : 100, 713 'delay' : 250, 714 'selectMode': 'pick', 715 //'autocompleteType': 'message', 716 'multiple': false, 717 'className': 'message-autosuggest', 718 'filterSubset' : true, 719 'tokenFormat' : 'object', 720 'tokenValueKey' : 'label', 721 'injectChoice': $empty, 722 'onPush' : $empty, 723 724 'prefetchOnInit' : true, 725 'alwaysOpen' : true, 726 'ignoreKeys' : true 727 }, 728 729 'enableShowToolTip':false, 730 // Show ToolTip 731 'showToolTipRequestOptions' : { 732 'url' : '', 733 'data' : { 734 'format' : 'json' 735 } 736 } 737 }, 738 739 initialize : function(el, options) { 740 el = $(el); 741 if(!el) 742 return; 743 if( el.get('tag') != 'img' ) { 744 this.image = el.getElement('img'); 745 } else { 746 this.image = el; 747 } 748 749 this.element = el; 750 this.count = 0; 751 752 this.actualImage = new Image(); 753 this.actualImage.src = this.image.get('src'); 754 this.setOptions(options); 755 756 //this.element.addEvent('') 757 this.options.existingTags.each(this.addTag.bind(this)); 758 this.addToolTip(); 759 }, 760 761 begin : function() { 762 if( !this.options.enableCreate ) return; 763 this.getCrop(); 764 this.getForm(); 765 this.getSuggest(); 766 this.fireEvent('onBegin'); 767 }, 768 769 end : function() { 770 if( this.crop ) { 771 this.crop.destroy(); 772 delete this.crop; 773 } 774 if( this.form ) { 775 this.form.destroy(); 776 delete this.form; 777 } 778 if( this.suggest ) { 779 delete this.suggest; 780 } 781 this.fireEvent('onEnd'); 782 }, 783 784 getCrop : function() { 785 if( !this.crop ) { 786 var options = $merge(this.options.cropOptions, { 787 788 }); 789 this.crop = new SEAOLasso.Crop(this.image, options); 790 this.crop.addEvent('resize', this.onMove.bind(this)); 791 this.crop.refresh(); 792 } 793 794 return this.crop; 795 }, 796 797 getForm : function() { 798 if( !this.form ) { 799 this.form = new Element('div', { 800 'id' : 'tagger_form', 801 'class' : 'tagger_form', 802 'styles' : { 803 'position' : 'absolute', 804 'z-index' : '100000', 805 'width' : '150px' 806 //'height' : '300px' 807 } 808 }).inject(this.element, 'after'); 809 810 // Title 811 if( this.options.title ) { 812 new Element('div', { 813 'class' : 'media_photo_tagform_titlebar', 814 'html' : this.options.title 815 }).inject(this.form); 816 } 817 818 // Container 819 this.formContainer = new Element('div', { 820 'class' : 'media_photo_tagform_container' 821 }).inject(this.form); 822 823 // Description 824 if( this.options.description ) { 825 new Element('div', { 826 'class' : 'media_photo_tagform_text', 827 'html' : this.options.description 828 }).inject(this.formContainer); 829 } 830
831 // Input 832 this.input = new Element('input', { 833 'id' : 'tagger_input', 834 'class' : 'tagger_input', 835 'type' : 'text', 836 'styles' : { 837 838 } 839 }).inject(this.formContainer); 840 841 // Choices 842 this.choices = new Element('div', { 843 'class' : 'tagger_list' 844 }).inject(this.formContainer); 845 846 // Submit container 847 var submitContainer = new Element('div', { 848 'class' : 'media_photo_tagform_submits' 849 }).inject(this.formContainer); 850 851 var self = this; 852 new Element('a', { 853 'id' : 'tag_save', 854 'href' : 'javascript:void(0);', 855 'html' : en4.core.language.translate('Save'), 856 'events' : { 857 'click' : function() { 858 var data = {}; //JSON.decode(choice.getElement('input').value); 859 data.label = self.input.value; 860 if( $type(data.label) && data.label != '' ) { 861 data.extra = self.coords; 862 self.createTag(data); 863 } 864 } 865 } 866 }).inject(submitContainer); 867 868 new Element('a', { 869 'id' : 'tag_cancel', 870 'href' : 'javascript:void(0);', 871 'html' : en4.core.language.translate('Cancel'), 872 'events' : { 873 'click' : function() { 874 this.end(); 875 }.bind(this) 876 } 877 }).inject(submitContainer); 878 879 this.input.focus(); 880 } 881 882 return this.form; 883 }, 884 885 getSuggest : function() { 886 if( !this.suggest ) { 887 var self = this; 888 var options = $merge(this.options.suggestOptions, { 889 'overflow' : true, 890 'maxChoices' : 4, 891 'customChoices' : this.choices, 892 'injectChoice' : function(token) { 893 var choice = new Element('li', { 894 'class': 'autocompleter-choices', 895 //'value': token.id, 896 'html': token.photo || '', 897 'id': token.guid 898 }); 899 new Element('div', { 900 'html' : this.markQueryValue(token.label), 901 'class' : 'autocompleter-choice' 902 }).inject(choice); 903 new Element('input', { 904 'type' : 'hidden', 905 'value' : JSON.encode(token) 906 }).inject(choice); 907 this.addChoiceEvents(choice).inject(this.choices); 908 choice.store('autocompleteChoice', token); 909 }, 910 'onChoiceSelect' : function(choice) { 911 var data = JSON.decode(choice.getElement('input').value); 912 data.extra = self.coords; 913 self.createTag(data); 914 //alert(choice.getElement('input').value); 915 }, 916 'emptyChoices' : function() { 917 this.fireEvent('onHide', [this.element, this.choices]); 918 }, 919 'onCommand' : function(e) { 920 switch (e.key) { 921 case 'enter': 922 self.createTag({ 923 label : self.input.value, 924 extra : self.coords 925 }); 926 break; 927 } 928 } 929 }); 930 931 if( this.options.suggestProto == 'local' ) { 932 this.suggest = new Autocompleter.Local(this.input, this.options.suggestParam, options); 933 } else if( this.options.suggestProto == 'request.json' ) { 934 this.suggest = new Autocompleter.Request.JSON(this.input, this.options.suggestParam, options); 935 } 936 } 937 938 return this.suggest; 939 }, 940 941 getTagList : function() { 942 if( !this.tagList ) { 943 if( !this.options.tagListElement ) { 944 this.tagList = new Element('div', { 945 'class' : 'tag_list' 946 }).inject(this.element, 'after'); 947 } else { 948 this.tagList = $(this.options.tagListElement); 949 } 950 } 951 952 return this.tagList; 953 }, 954 955 onMove : function(coords) { 956 this.coords = coords; 957 var coords_y=coords.y; 958 var pos = { 959 x:0, 960 y:0 961 }; //this.element.getPosition(); 962 var form = this.getForm(); 963 var formParentHeight=this.getForm().getParent().getCoordinates().height - 2; 964 if(formParentHeight < (coords_y + 20 +form.getCoordinates().height - 2 )){ 965 coords_y = coords_y - (form.getCoordinates().height - 2); 966 } 967 form.setStyles({ 968 'top' : pos.y + coords_y + 20, 969 'left' : pos.x + coords.x + coords.w + 20 970 }); 971 }, 972 973 974 975 976 // Tagging stuff 977 978 addTag : function(params) { 979 // Required: id, text, x, y, w, h 980 981 if ( 'object' != $type(params) || !params.extra) { 982 //alert('This entry has already been tagged.'); 983 return; 984 } 985 986 var baseX = 0, baseY = 0, baseW = 0, baseH = 0; 987 988 ["x", "y", "w", "h"].each(function(key) { 989 params.extra[key] = parseInt(params.extra[key]); 990 }); 991 992 var actualImageCoords =this.getActualImageCoords(); 993 var imageCoords =this.getImageCoords(); 994 // Set Relative X Coords 995 ["x", "w"].each(function(key) { 996 params.extra[key]= (params.extra[key]/ actualImageCoords.width * imageCoords.width).toInt(); 997 }); 998 999 // Set Relative Y Coords 1000 ["y", "h"].each(function(key) { 1001 params.extra[key]= (params.extra[key] / actualImageCoords.height * imageCoords.height).toInt(); 1002 }); 1003 1004 if( this.options.noTextTagHref && params.tag_type == 'core_tag' ) { 1005 delete params.href; 1006 } 1007 1008 // Make tag 1009 if($('tag_' + params.id)) 1010 $('tag_' + params.id).destroy(); 1011 var tag = new Element('div', { 1012 'id' : 'tag_' + params.id, 1013 'class' : 'tag_div', 1014 'html' : '<img src="'+this.options.transImage+'" width="100%" height="100%" />', 1015 'styles' : { 1016 'position' : 'absolute', 1017 'width' : params.extra.w, 1018 'height' : params.extra.h, 1019 'top' : baseY + params.extra.y, 1020 'left' : baseX + params.extra.x 1021 }, 1022 'events' : { 1023 'mouseover' : function() { 1024 this.showTag(params.id); 1025 }.bind(this), 1026 'mouseout' : function() { 1027 this.hideTag(params.id); 1028 }.bind(this) 1029 } 1030 }).inject(this.element, 'after'); 1031 1032 // Make label 1033 // Note: we need to use visibility hidden to position correctly in IE 1034 if($('tag_label_' + params.id)) 1035 $('tag_label_' + params.id).destroy(); 1036 var label = new Element("span", { 1037 'id' : 'tag_label_' + params.id, 1038 'class' : 'tag_label', 1039 'html' : params.text, 1040 'styles' : { 1041 'position' : 'absolute' 1042 } 1043 }).inject(this.element, 'after'); 1044 1045 var labelPos = {}; 1046 labelPos.top = ( baseY + params.extra.y + tag.getSize().y ); 1047 labelPos.left = Math.round( ( baseX + params.extra.x ) + ( tag.getSize().x / 2 ) - (label.getSize().x / 2) ); 1048 1049 if( this.element.getSize().y < labelPos.top.toInt() + 20 ){ 1050 labelPos.top = baseY + params.extra.y - label.getSize().y; 1051 } 1052 1053 label.setStyles(labelPos); 1054 1055 this.hideTag(params.id); 1056 1057 var isFirst = ( !$type(this.count) || this.count == 0 ); 1058 this.getTagList().setStyle('display', ''); 1059 1060 // Make list 1061 if($('tag_comma_' + params.id)) 1062 $('tag_comma_' + params.id).destroy(); 1063 if( !isFirst ) new Element('span', { 1064 'id' : 'tag_comma_' + params.id, 1065 'class' : 'tag_comma', 1066 'html' : ',' 1067 }).inject(this.getTagList()); 1068 1069 // Make other thingy 1070 if($('tag_info_' + params.id)) 1071 $('tag_info_' + params.id).destroy(); 1072 var info = new Element('span', { 1073 'id' : 'tag_info_' + params.id, 1074 'class' : 'tag_info media_tag_listcontainer' 1075 }).inject(this.getTagList()); 1076 1077 if($('tag_activator_' + params.id)) 1078 $('tag_activator_' + params.id).destroy(); 1079 var activator = new Element('a', { 1080 'id' : 'tag_activator_' + params.id, 1081 'class' : 'tag_activator', 1082 'href' : params.href || null, 1083 'html' : params.text, 1084 'rel': params.id, 1085 'events' : { 1086 'mouseover' : function() { 1087 this.showTag(params.id); 1088 }.bind(this), 1089 'mouseout' : function() { 1090 this.hideTag(params.id); 1091 }.bind(this) 1092 } 1093 }).inject(info); 1094 1095 // Delete
1096 if(!this.options.enableShowToolTip && this.checkCanRemove(params.id) ) 1097 { 1098 info.appendText(' ('); 1099 if($('tag_destroyer_' + params.id)) 1100 $('tag_destroyer_' + params.id).destroy(); 1101 var destroyer = new Element('a', { 1102 'id' : 'tag_destroyer_' + params.id, 1103 'class' : 'tag_destroyer albums_tag_delete', 1104 'href' : 'javascript:void(0);', 1105 'html' : en4.core.language.translate('delete'), 1106 'events' : { 1107 'click' : function() { 1108 this.removeTag(params.id); 1109 }.bind(this) 1110 } 1111 }).inject(info); 1112 info.appendText(')'); 1113 } 1114 1115 this.count++; 1116 }, 1117 1118 createTag : function(params) { 1119 if( !this.options.enableCreate ) return; 1120 1121 params.extra = this.getSaveCoords(params.extra); 1122 // Send request 1123 var requestOptions = $merge(this.options.createRequestOptions, { 1124 'data' : $merge(params, { 1125 1126 }), 1127 'onComplete' : function(responseJSON) { 1128 this.addTag(responseJSON); 1129 this.addToolTip(); 1130 this.fireEvent('onCreateTag',responseJSON); 1131 }.bind(this) 1132 }); 1133 var request = new Request.JSON(requestOptions); 1134 request.send(); 1135 1136 // End tagging 1137 this.end(); 1138 }, 1139 1140 removeTag : function(id) { 1141 1142 if( !this.checkCanRemove(id) ) return; 1143 1144 // Remove from frontend 1145 var next = $('tag_info_' + id).getNext(); 1146 if($('tag_comma_' + id)) 1147 $('tag_comma_' + id).destroy(); 1148 else if( next && next.get('html').trim() == ',' ) next.destroy(); 1149 $('tag_' + id).destroy(); 1150 $('tag_label_' + id).destroy(); 1151 $('tag_info_' + id).destroy(); 1152 this.count--; 1153 this.fireEvent('onRemoveTag',[id]); 1154 1155 // Send request 1156 var requestOptions = $merge(this.options.deleteRequestOptions, { 1157 'data' : { 1158 'tagmap_id' : id 1159 }, 1160 'onComplete' : function(responseJSON) { 1161 1162 }.bind(this) 1163 }); 1164 var request = new Request.JSON(requestOptions); 1165 request.send(); 1166 }, 1167 1168 checkCanRemove : function(id) { 1169 1170 // Check if can remove 1171 var tagData; 1172 this.options.existingTags.each(function(datum) { 1173 if( datum.tagmap_id == id ) { 1174 tagData = datum; 1175 } 1176 }); 1177 1178 if( this.options.enableDelete ) return true; 1179 1180 if( tagData ) { 1181 if( tagData.tag_type + '_' + tagData.tag_id == this.options.guid ) return true; 1182 if( tagData.tagger_type + '_' + tagData.tagger_id == this.options.guid ) return true; 1183 } 1184 1185 return false; 1186 }, 1187 1188 showTag : function(id) { 1189 $('tag_' + id)/*.addClass('tag_div')*/.removeClass('tag_div_hidden'); 1190 $('tag_label_' + id)/*.addClass('tag_label')*/.removeClass('tag_label_hidden'); 1191 }, 1192 1193 hideTag : function(id) { 1194 $('tag_' + id).addClass('tag_div_hidden')/*.removeClass('tag_div')*/; 1195 $('tag_label_' + id).addClass('tag_label_hidden')/*.removeClass('tag_label')*/; 1196 }, 1197 1198 getActualImageCoords: function(){ 1199 return { 1200 'width' : this.actualImage.width, 1201 'height' : this.actualImage.height 1202 }; 1203 }, 1204 1205 1206 getImageCoords: function(){ 1207 var coords = this.image.getCoordinates(); 1208 // the getCoordinates adds 2 extra pixels 1209 return { 1210 'width' : (coords.width - 2), 1211 'height' : (coords.height - 2) 1212 }; 1213 }, 1214 getCropCoords: function(){ 1215 var coords =this.getCrop().crop.getCoordinates(); 1216 // the getCoordinates adds 2 extra pixels 1217 return { 1218 'width' : (coords.width - 2), 1219 'height' : (coords.height - 2) 1220 }; 1221 }, 1222 getSaveCoords: function(coods){ 1223 var actualImageCoords =this.getActualImageCoords(); 1224 var imageCoords =this.getCropCoords(); 1225 // Set Relative X Coords 1226 ["x", "w"].each(function(key) { 1227 coods[key]= ((coods[key]/ imageCoords.width) * actualImageCoords.width).toInt(); 1228 }); 1229 1230 // Set Relative Y Coords 1231 ["y", "h"].each(function(key) { 1232 coods[key]= ((coods[key] / imageCoords.height) * actualImageCoords.height).toInt(); 1233 }); 1234 1235 return coods; 1236 }, 1237 1238 setToolTip:function(){ 1239 if(this.options.enableShowToolTip == false) 1240 return; 1241 // Add tooltips 1242 var window_size = window.getSize() 1243 return new SEATips($$('.tag_activator'), { 1244 fixed : true, 1245 title:'', 1246 className : 'sea_add_tooltip_link_tips', 1247 hideDelay :200,
1248 showDelay :200, 1249 offset : { 1250 'x' : 0, 1251 'y' : 0 1252 }, 1253 windowPadding: { 1254 'x':200, 1255 'y':(window_size.y/2) 1256 }, 1257 req_pendding:0 1258 } 1259 ); 1260 }, 1261 getToolTipDefaultContent: function(){ 1262 var toolTipDefault = new Element('div', {}); 1263 1264 var info_tip = new Element('div', { 1265 1266 'class' : 'uiOverlay info_tip', 1267 'styles' : { 1268 'width' : 200, 1269 'top' : 0 1270 } 1271 }).inject(toolTipDefault); 1272 1273 var info_tip_content_wrapper = new Element('div', { 1274 'class' : 'info_tip_content_wrapper' 1275 }).inject(info_tip); 1276 1277 var info_tip_content = new Element('div', { 1278 'class' : 'info_tip_content' 1279 }).inject(info_tip_content_wrapper); 1280 1281 new Element('div', { 1282 'class' : 'info_tip_content_loader', 1283 'html' : '<img src="application/modules/Seaocore/externals/images/core/loading.gif" alt="Loading" />' 1284 }).inject(info_tip_content); 1285 1286 1287 return toolTipDefault; 1288 }, 1289 addToolTip:function(){ 1290 var self=this; 1291 if(this.options.enableShowToolTip){ 1292 $$('.tag_activator').addEvent('mouseover', function(event) { 1293 var el = $(event.target); 1294 ItemTooltips.options.offset.y = el.offsetHeight; 1295 ItemTooltips.options.showDelay = 0; 1296 ItemTooltips.options.showToolTip=true; 1297 if( !el.retrieve('tip-loaded', false) ) { 1298 ItemTooltips.options.req_pendding++; 1299 var id=''; 1300 if(el.hasAttribute("rel")) 1301 id=el.rel; 1302 if(id =='') 1303 return; 1304 1305 el.store('tip-loaded', true); 1306 el.store('tip:title',self.getToolTipDefaultContent()); 1307 el.store('tip:text', ''); 1308 1309 el.addEvent('mouseleave',function(){ 1310 ItemTooltips.options.showToolTip=false; 1311 }); 1312 1313 var requestOptions = $merge(self.options.showToolTipRequestOptions, { 1314 'data' : { 1315 format : 'html', 1316 'tagmap_id' : id 1317 }, 1318 evalScripts : true, 1319 onSuccess : function(responseTree, responseElements, responseHTML, responseJavaScript) { 1320 el.store('tip:title', ''); 1321 var responseHTMLContent = new Element('div', 1322 { 1323 html :responseHTML 1324 }); 1325 1326 if( self.checkCanRemove(id) ) 1327 { 1328 var responseHTMLContentDelete = responseHTMLContent.getElement('.tagged_info_tip_content_delete'); 1329 responseHTMLContentDelete.appendText(' ('); 1330 if($('tag_destroyer_' + id)) 1331 $('tag_destroyer_' + id).destroy(); 1332 new Element('a', { 1333 'id' : 'tag_destroyer_' + id, 1334 'class' : 'tag_destroyer albums_tag_delete', 1335 'href' : 'javascript:void(0);', 1336 'html' : en4.core.language.translate('remove tag'), 1337 'events' : { 1338 'click' : function() { 1339 ItemTooltips.options.canHide = true; 1340 ItemTooltips.hide(el); 1341 self.removeTag(id); 1342 }.bind(this) 1343 } 1344 }).inject(responseHTMLContentDelete); 1345 responseHTMLContentDelete.appendText(')'); 1346 } 1347 1348 el.store('tip:text', responseHTMLContent); 1349 ItemTooltips.options.showDelay=0; 1350 ItemTooltips.elementEnter(event, el); // Force it to update the text 1351 ItemTooltips.options.showDelay=200; 1352 ItemTooltips.options.req_pendding--; 1353 if(!ItemTooltips.options.showToolTip || ItemTooltips.options.req_pendding > 0){ 1354 ItemTooltips.elementLeave(event,el); 1355 } 1356 var tipEl=ItemTooltips.toElement(); 1357 tipEl.addEvents({ 1358 'mouseenter': function() { 1359 ItemTooltips.options.canHide = false;
1360 ItemTooltips.show(el); 1361 }, 1362 'mouseleave': function() { 1363 ItemTooltips.options.canHide = true; 1364 ItemTooltips.hide(el); 1365 } 1366 }); 1367 Smoothbox.bind($$(".tag_activator")); 1368 }.bind(this) 1369 }); 1370 1371 new Request.HTML(requestOptions).send(); 1372 } 1373 1374 }); 1375 var ItemTooltips = self.setToolTip(); 1376 } 1377 } 1378 1379});
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.