1/** 2 * Bitrix HTML Editor 3.0 3 * Date: 24.04.13 4 * Time: 4:23 5 * 6 * Taskbarmanager 7 * Taskbar 8 * Context Menu 9 * Search/Replace 10 */ 11;(function() { 12 function TaskbarManager(editor, init) 13 { 14 this.editor = editor; 15 this.bShown = false; 16 this.closedWidth = 20; 17 this.MIN_CLOSED_WIDTH = 120; 18 this.width = this.editor.config.taskbarWidth || 250; 19 this.taskbars = {}; 20 this.freezeOnclickHandler = false; 21 22 if (init) 23 { 24 this.Init(); 25 } 26 } 27 28 TaskbarManager.prototype = { 29 Init: function() 30 { 31 this.pCont = this.editor.dom.taskbarCont; 32 this.pCont.setAttribute('data-bx-type', 'taskbarmanager'); 33 34 this.pResizer = BX('bx-html-editor-tskbr-res-' + this.editor.id); 35 this.pResizer.setAttribute('data-bx-type', 'taskbarflip'); 36 this.pTopCont = BX('bx-html-editor-tskbr-top-' + this.editor.id); 37 38 BX.bind(this.pResizer, 'mousedown', BX.proxy(this.StartResize, this)); 39 BX.bind(this.pCont, 'click', BX.proxy(this.OnClick, this)); 40 41 // Search 42 this.pSearchCont = BX('bxhed-tskbr-search-cnt-' + this.editor.id); 43 this.pSearchAli = BX('bxhed-tskbr-search-ali-' + this.editor.id); 44 this.pSearchInput = BX('bxhed-tskbr-search-inp-' + this.editor.id); 45 this.pSearchNothingNotice = BX('bxhed-tskbr-search-nothing-' + this.editor.id); 46 BX.bind(this.pSearchInput, 'keyup', BX.proxy(this.TaskbarSearch, this)); 47 }, 48 49 OnClick: function(e) 50 { 51 if (!e) 52 e = window.event; 53 54 if (this.freezeOnclickHandler) 55 return; 56 57 var 58 _this = this, 59 target = e.target || e.srcElement, 60 type = (target && target.getAttribute) ? target.getAttribute('data-bx-type') : null; 61 62 if (!type) 63 { 64 target = BX.findParent(target, function(node) 65 { 66 return node == _this.pCont || (node.getAttribute && node.getAttribute('data-bx-type')); 67 }, this.pCont); 68 type = (target && target.getAttribute) ? target.getAttribute('data-bx-type') : null; 69 } 70 71 if (type == 'taskbarflip' || (!this.bShown && (type == 'taskbarmanager' || !type))) 72 { 73 if (this.bShown) 74 { 75 this.Hide(); 76 } 77 else 78 { 79 this.Show(); 80 } 81 } 82 else if(type == 'taskbargroup_title') 83 { 84 BX.onCustomEvent(this, 'taskbargroupTitleClick', [target]); 85 } 86 else if(type == 'taskbarelement') 87 { 88 BX.onCustomEvent(this, 'taskbarelementClick', [target]); 89 } 90 else if(type == 'taskbar_title_but') 91 { 92 BX.onCustomEvent(this, 'taskbarTitleClick', [target]); 93 } 94 else if(type == 'taskbar_top_menu') 95 { 96 BX.onCustomEvent(this, 'taskbarMenuClick', [target]); 97 } 98 else if(type == 'taskbar_search_cancel') 99 { 100 this.pSearchInput.value = ''; 101 this.TaskbarSearch(); 102 } 103 }, 104 105 Show: function(saveValue) 106 { 107 if (!this.bShown) 108 { 109 this.bShown = true; 110 this.pCont.className = 'bxhtmled-taskbar-cnt bxhtmled-taskbar-shown'; 111 } 112 this.pCont.style.width = this.GetWidth(true) + 'px'; 113 this.editor.ResizeSceleton(); 114 115 if (saveValue !== false) 116 {
117 this.editor.SaveOption('taskbar_shown', 1); 118 } 119 }, 120 121 Hide: function(saveValue) 122 { 123 if (this.bShown) 124 { 125 this.bShown = false; 126 this.pCont.className = 'bxhtmled-taskbar-cnt bxhtmled-taskbar-hidden'; 127 } 128 this.pCont.style.width = this.GetWidth() + 'px'; 129 this.editor.ResizeSceleton(); 130 131 if (saveValue !== false) 132 { 133 this.editor.SaveOption('taskbar_shown', 0); 134 } 135 }, 136 137 GetWidth: function(bCheck, maxWidth) 138 { 139 var width; 140 if (this.bShown) 141 { 142 width = bCheck ? Math.max(this.width, this.closedWidth + this.MIN_CLOSED_WIDTH) : this.width; 143 if(maxWidth && width > maxWidth) 144 { 145 width = this.width = Math.round(maxWidth); 146 } 147 } 148 else 149 { 150 width = this.closedWidth; 151 } 152 153 return width; 154 }, 155 156 AddTaskbar: function(oTaskbar) 157 { 158 this.taskbars[oTaskbar.id] = oTaskbar; 159 this.pCont.appendChild(oTaskbar.GetCont()); 160 this.pTopCont.appendChild(oTaskbar.GetTitleCont()); 161 }, 162 163 ShowTaskbar: function(taskbarId) 164 { 165 this.pSearchInput.value = ''; 166 for(var id in this.taskbars) 167 { 168 if (this.taskbars.hasOwnProperty(id)) 169 { 170 if (id == taskbarId) 171 { 172 this.taskbars[id].Activate(); 173 this.pSearchInput.placeholder = this.taskbars[id].searchPlaceholder; 174 } 175 else 176 { 177 this.taskbars[id].Deactivate(); 178 } 179 180 this.activeTaskbarId = taskbarId; 181 this.taskbars[id].ClearSearchResult(); 182 } 183 } 184 }, 185 186 GetActiveTaskbar: function() 187 { 188 return this.taskbars[this.activeTaskbarId]; 189 }, 190 191 StartResize: function(e) 192 { 193 if(!e) 194 e = window.event; 195 196 var target = e.target || e.srcElement; 197 if (target.getAttribute('data-bx-tsk-split-but') == 'Y') 198 return true; 199 200 this.freezeOnclickHandler = true; 201 202 var 203 width = this.GetWidth(), 204 overlay = this.editor.dom.resizerOverlay, 205 dX = 0, newWidth, 206 windowScroll = BX.GetWindowScrollPos(), 207 startX = e.clientX + windowScroll.scrollLeft, 208 _this = this; 209 210 overlay.style.display = 'block'; 211 212 function moveResizer(e, bFinish) 213 { 214 if(!e) 215 e = window.event; 216 217 var x = e.clientX + windowScroll.scrollLeft; 218 219 if(startX == x) 220 return; 221 222 dX = startX - x; 223 newWidth = width + dX; 224 225 if (bFinish) 226 { 227 _this.width = Math.max(newWidth, _this.closedWidth + _this.MIN_CLOSED_WIDTH); 228 if (isNaN(_this.width)) 229 { 230 _this.width = _this.closedWidth + _this.MIN_CLOSED_WIDTH; 231 } 232 } 233 else 234 { 235 _this.width = newWidth; 236 } 237 238 if (newWidth > _this.closedWidth + (bFinish ? 20 : 0)) 239 { 240 _this.Show(); 241 } 242 else 243 { 244 _this.Hide(); 245 } 246 } 247 248 function finishResizing(e) 249 { 250 moveResizer(e, true); 251 BX.unbind(document, 'mousemove', moveResizer); 252 BX.unbind(document, 'mouseup', finishResizing); 253 overlay.style.display = 'none'; 254 setTimeout(function(){_this.freezeOnclickHandler = false;}, 10); 255 BX.PreventDefault(e); 256
257 _this.editor.SaveOption('taskbar_width', _this.GetWidth(true)); 258 } 259 260 BX.bind(document, 'mousemove', moveResizer); 261 BX.bind(document, 'mouseup', finishResizing); 262 }, 263 264 Resize: function(w, h) 265 { 266 var topHeight = parseInt(this.pTopCont.offsetHeight, 10); 267 for(var id in this.taskbars) 268 { 269 if (this.taskbars.hasOwnProperty(id) && this.taskbars[id].pTreeCont) 270 { 271 this.taskbars[id].pTreeCont.style.height = (h - topHeight - 42) + 'px'; 272 } 273 } 274 275 this.pSearchCont.style.width = w + 'px'; 276 if (!BX.browser.IsDoctype()) 277 { 278 this.pSearchAli.style.width = (w - 20) + 'px'; 279 } 280 281 var _this = this; 282 if (this.resizeTimeout) 283 { 284 this.resizeTimeout = clearTimeout(this.resizeTimeout); 285 } 286 287 this.resizeTimeout = setTimeout(function() 288 { 289 if (parseInt(_this.pTopCont.offsetHeight, 10) !== topHeight) 290 { 291 _this.Resize(w, h); 292 } 293 }, 100); 294 }, 295 296 TaskbarSearch: function(e) 297 { 298 var 299 taskbar = this.GetActiveTaskbar(), 300 value = this.pSearchInput.value; 301 302 if (e && e.keyCode == this.editor.KEY_CODES['escape']) 303 { 304 value = this.pSearchInput.value = ''; 305 } 306 307 if (value.length < 2) 308 { 309 taskbar.ClearSearchResult(); 310 } 311 else 312 { 313 taskbar.Search(value); 314 } 315 } 316 }; 317 318 319 /* 320 * 321 * 322 * */ 323 function Taskbar(editor) 324 { 325 this.editor = editor; 326 this.manager = this.editor.taskbarManager; 327 this.searchIndex = []; 328 this._searchResult = []; 329 this._searchResultSect = []; 330 331 BX.addCustomEvent(this.manager, 'taskbargroupTitleClick', BX.proxy(this.OnGroupTitleClick, this)); 332 BX.addCustomEvent(this.manager, 'taskbarelementClick', BX.proxy(this.OnElementClick, this)); 333 BX.addCustomEvent(this.manager, 'taskbarTitleClick', BX.proxy(this.OnTitleClick, this)); 334 BX.addCustomEvent(this.manager, 'taskbarMenuClick', BX.proxy(this.OnMenuClick, this)); 335 } 336 337 Taskbar.prototype = { 338 GetCont: function() 339 { 340 return this.pTreeCont; 341 }, 342 343 GetTitleCont: function() 344 { 345 return this.pTitleCont; 346 }, 347 348 BuildSceleton: function() 349 { 350 // Build title & menu 351 this.pTitleCont = BX.create("span", {props: {className: "bxhtmled-split-btn"},html: '<span class="bxhtmled-split-btn-l"><span class="bxhtmled-split-btn-bg">' + this.title + '</span></span><span class="bxhtmled-split-btn-r"><span data-bx-type="taskbar_top_menu" data-bx-taskbar="' + this.id + '" class="bxhtmled-split-btn-bg"></span></span>'}); 352 this.pTitleCont.setAttribute('data-bx-type', 'taskbar_title_but'); 353 this.pTitleCont.setAttribute('data-bx-taskbar', this.id); 354 355 this.pTreeCont = BX.create("DIV", {props: {className: "bxhtmled-taskbar-tree-cont"}}); 356 this.pTreeInnerCont = this.pTreeCont.appendChild(BX.create("DIV", {props: {className: "bxhtmled-taskbar-tree-inner-cont"}})); 357 }, 358 359 BuildTree: function(sections, elements) 360 { 361 BX.cleanNode(this.pTreeCont); 362 this.treeSectionIndex = {}; 363 this.BuildTreeSections(sections); 364 this.BuildTreeElements(elements); 365 }, 366 367 BuildTreeSections: function(sections) 368 { 369 this.sections = []; 370 for (var i = 0; i < sections.length; i++) 371 { 372 this.BuildSection(sections[i]); 373 } 374 }, 375 376 GetSectionsTreeInfo: function() 377 { 378 return this.sections; 379 }, 380 381 BuildSection: function(section) 382 { 383 var 384 parentCont = this.GetSectionContByPath(section.path), 385 pGroup = BX.create("DIV", {props: {className: "bxhtmled-tskbr-sect-outer"}}), 386 pGroupTitle = pGroup.appendChild(BX.create("DIV", {props: {className: "bxhtmled-tskbr-sect"}})), 387 icon = pGroupTitle.appendChild(BX.create("SPAN", {props: {className: "bxhtmled-tskbr-sect-icon"}})), 388 title = pGroupTitle.appendChild(BX.create("SPAN", {props: {className: "bxhtmled-tskbr-sect-title"}, text: section.title || section.name})), 389 childCont = pGroup.appendChild(BX.create("DIV", {props: {className: "bxhtmled-tskb-child"}})), 390 elementsCont = pGroup.appendChild(BX.create("DIV", {props: {className: "bxhtmled-tskb-child-elements"}})); 391 392 var key = section.path == '' ? section.name : section.path + ',' + section.name; 393 var depth = section.path == '' ? 0 : 1; // Todo.... 394 395 var sect = { 396 key: key, 397 children: [], 398 section: section 399 } 400 401 this.treeSectionIndex[key] = { 402 icon: icon, 403 outerCont: pGroup, 404 cont: pGroupTitle, 405 childCont: childCont, 406 elementsCont: elementsCont, 407 sect: sect 408 }; 409 410 this.GetSectionByPath(section.path).push(sect); 411 412 if (depth > 0) 413 { 414 BX.addClass(pGroupTitle, "bxhtmled-tskbr-sect-" + depth); 415 BX.addClass(icon, "bxhtmled-tskbr-sect-icon-" + depth); 416 } 417 418 pGroupTitle.setAttribute('data-bx-type', 'taskbargroup_title'); 419 pGroupTitle.setAttribute('data-bx-taskbar', this.id); 420 421 pGroup.setAttribute('data-bx-type', 'taskbargroup'); 422 pGroup.setAttribute('data-bx-path', key); 423 pGroup.setAttribute('data-bx-taskbar', this.id); 424 425 parentCont.appendChild(pGroup); 426 }, 427 428 BuildTreeElements: function(elements) 429 { 430 this.elements = elements; 431 for (var i in elements) 432 { 433 if (elements.hasOwnProperty(i)) 434 { 435 this.BuildElement(elements[i]); 436 } 437 } 438 }, 439 440 BuildElement: function(element) 441 {
442 const _this = this; 443 const parentCont = this.GetSectionContByPath(element.key || element.path, true); 444 const pElement = BX.create('DIV', { 445 props: { className: 'bxhtmled-tskbr-element' }, 446 html: '<span class="bxhtmled-tskbr-element-icon"></span><span class="bxhtmled-tskbr-element-text">' 447 + BX.Text.encode(element.title) 448 + '</span>', 449 }); 450 451 var dd = pElement.appendChild(BX.create("IMG", {props: { 452 src: this.editor.util.GetEmptyImage(), 453 className: "bxhtmled-drag" 454 }})); 455 456 this.HandleElementEx(pElement, dd, element); 457 458 this.searchIndex.push({ 459 content: (BX.Text.encode(element.title) + ' ' + element.name).toLowerCase(), 460 element: pElement 461 }); 462 463 dd.onmousedown = function (e) 464 { 465 if (!e) 466 { 467 e = window.event; 468 } 469 470 var 471 target = e.target || e.srcElement, 472 bxTag = _this.editor.GetBxTag(target); 473 474 return _this.OnElementMouseDownEx(e, target, bxTag); 475 }; 476 477 dd.ondblclick = function(e) 478 { 479 var 480 target = e.target || e.srcElement, 481 bxTag = _this.editor.GetBxTag(target); 482 483 return _this.OnElementDoubleClick(e, target, bxTag); 484 }; 485 486 dd.ondragend = function (e) 487 { 488 if (!e) 489 { 490 e = window.event; 491 } 492 _this.OnDragEndHandler(e, this); 493 }; 494 495 pElement.setAttribute('data-bx-type', 'taskbarelement'); 496 497 parentCont.appendChild(pElement); 498 }, 499 500 HandleElementEx: function(dd) 501 { 502 503 }, 504 505 GetSectionContByPath: function(path, bElement) 506 { 507 if (path == '' || !this.treeSectionIndex[path]) 508 { 509 return this.pTreeCont; 510 } 511 else 512 { 513 return bElement ? this.treeSectionIndex[path].elementsCont : this.treeSectionIndex[path].childCont; 514 } 515 }, 516 517 GetSectionByPath: function(path) 518 { 519 if (path == '' || !this.treeSectionIndex[path]) 520 { 521 return this.sections; 522 } 523 else 524 { 525 return this.treeSectionIndex[path].sect.children; 526 } 527 }, 528 529 // Open or close 530 ToggleGroup: function(cont, bOpen) 531 { 532 // TODO: animation 533 var path = cont.getAttribute('data-bx-path'); 534 if (path) 535 { 536 var group = this.treeSectionIndex[path]; 537 if (!group) 538 { 539 return; 540 } 541 542 if (bOpen !== undefined) 543 { 544 group.opened = !bOpen; 545 } 546 547 if (group.opened) 548 { 549 BX.removeClass(group.cont, 'bxhtmled-tskbr-sect-open'); 550 BX.removeClass(group.icon, 'bxhtmled-tskbr-sect-icon-open'); 551 BX.removeClass(group.outerCont, 'bxhtmled-tskbr-sect-outer-open'); 552 group.childCont.style.display = 'none'; 553 group.elementsCont.style.display = 'none'; 554 group.opened = false; 555 } 556 else 557 { 558 BX.addClass(group.cont, 'bxhtmled-tskbr-sect-open'); 559 BX.addClass(group.icon, 'bxhtmled-tskbr-sect-icon-open'); 560 BX.addClass(group.outerCont, 'bxhtmled-tskbr-sect-outer-open'); 561 group.childCont.style.display = 'block'; 562 group.elementsCont.style.display = group.elementsCont.childNodes.length > 0 ? 'block' : 'none'; 563 group.opened = true; 564 } 565 } 566 }, 567 568 OnDragEndHandler: function(e, node) 569 { 570 var _this = this; 571 this.editor.skipPasteHandler = true; 572 this.editor.skipPasteControl = true; 573 574 if (this.editor.iframeView.pasteHandlerTimeout) 575 this.editor.iframeView.pasteHandlerTimeout = clearTimeout(this.editor.iframeView.pasteHandlerTimeout); 576 577 setTimeout(function() 578 { 579 var dd = _this.editor.GetIframeElement(node.id); 580 if (dd && dd.parentNode) 581 { 582 var sur = _this.editor.util.CheckSurrogateNode(dd.parentNode); 583 if (sur) 584 { 585 _this.editor.util.InsertAfter(dd, sur); 586 } 587 } 588 _this.editor.synchro.FullSyncFromIframe(); 589 590 _this.editor.skipPasteHandler = false; 591 _this.editor.skipPasteControl = false; 592 if (_this.editor.iframeView.pasteLoader && _this.editor.iframeView.pasteLoader.hide) 593 { 594 _this.editor.iframeView.pasteLoader.hide(); 595 } 596 }, 20); 597 }, 598 599 OnElementMouseDownEx: function(e) 600 { 601 return true; 602 }, 603 604 OnElementClick: function(e) 605 { 606 this.OnElementClickEx(); 607 return true; 608 }, 609 610 OnElementClickEx: function() 611 { 612 return true; 613 }, 614 615 OnElementDoubleClick: function(e, target, bxTag) 616 { 617 if (target) 618 { 619 var dd = target.cloneNode(true); 620 this.editor.Focus(); 621 this.editor.selection.InsertNode(dd); 622 this.editor.synchro.FullSyncFromIframe(); 623 } 624 }, 625 626 OnGroupTitleClick: function(pElement) 627 { 628 if (pElement && pElement.getAttribute('data-bx-taskbar') == this.id) 629 { 630 return this.ToggleGroup(pElement.parentNode); 631 } 632 return true; 633 }, 634 635 OnTitleClick: function(pElement) 636 { 637 if (pElement && pElement.getAttribute('data-bx-taskbar') == this.id) 638 {
639 return this.manager.ShowTaskbar(this.id); 640 } 641 return true; 642 }, 643 644 OnMenuClick: function(pElement) 645 { 646 if (pElement && pElement.getAttribute('data-bx-taskbar') == this.id) 647 return this.ShowMenu(pElement); 648 return true; 649 }, 650 651 Activate: function() 652 { 653 this.pTreeCont.style.display = 'block'; 654 this.bActive = true; 655 return true; 656 }, 657 658 Deactivate: function() 659 { 660 this.pTreeCont.style.display = 'none'; 661 this.bActive = false; 662 return true; 663 }, 664 665 IsActive: function() 666 { 667 return !!this.bActive; 668 }, 669 670 ShowMenu: function(pElement) 671 { 672 var arItems = this.GetMenuItems(); 673 BX.PopupMenu.destroy(this.uniqueId + "_menu"); 674 BX.PopupMenu.show(this.uniqueId + "_menu", pElement, arItems, { 675 overlay: {opacity: 0.1}, 676 events: { 677 onPopupClose: function(){BX.removeClass(this.bindElement, "bxec-add-more-over");} 678 }, 679 offsetLeft: 1, 680 zIndex: 3005 681 } 682 ); 683 return true; 684 }, 685 686 GetMenuItems: function() 687 { 688 return []; 689 }, 690 691 Search: function(value) 692 { 693 this.ClearSearchResult(); 694 var 695 bFoundItems = false, 696 pSect, el, 697 i, l = this.searchIndex.length; 698 699 value = BX.util.trim(value.toLowerCase()); 700
701 BX.addClass(this.pTreeCont, 'bxhtmled-taskbar-tree-cont-search'); 702 BX.addClass(this.manager.pSearchCont, 'bxhtmled-search-cont-res'); 703 704 for(i = 0; i < l; i++) 705 { 706 el = this.searchIndex[i]; 707 if (el.content.indexOf(value) !== -1) // Show element 708 { 709 bFoundItems = true; 710 BX.addClass(el.element, 'bxhtmled-tskbr-search-res'); 711 this._searchResult.push(el.element); 712 713 pSect = BX.findParent(el.element, function(node) 714 { 715 return node.getAttribute && node.getAttribute('data-bx-type') == 'taskbargroup'; 716 }, this.pTreeCont); 717 718 while (pSect) 719 { 720 BX.addClass(pSect, 'bxhtmled-tskbr-search-res'); 721 this.ToggleGroup(pSect, true); 722 this._searchResultSect.push(pSect); 723 724 pSect = BX.findParent(pSect, function(node) 725 { 726 return node.getAttribute && node.getAttribute('data-bx-type') == 'taskbargroup'; 727 }, this.pTreeCont); 728 } 729 } 730 } 731 732 if (!bFoundItems) 733 { 734 this.manager.pSearchNothingNotice.style.display = 'block'; 735 } 736 }, 737 738 ClearSearchResult: function() 739 {
740 BX.removeClass(this.pTreeCont, 'bxhtmled-taskbar-tree-cont-search'); 741 BX.removeClass(this.manager.pSearchCont, 'bxhtmled-search-cont-res'); 742 this.manager.pSearchNothingNotice.style.display = 'none'; 743 var i; 744 if (this._searchResult) 745 { 746 for(i = 0; i < this._searchResult.length; i++) 747 { 748 BX.removeClass(this._searchResult[i], 'bxhtmled-tskbr-search-res'); 749 } 750 this._searchResult = []; 751 } 752 if (this._searchResultSect) 753 { 754 for(i = 0; i < this._searchResultSect.length; i++) 755 { 756 BX.removeClass(this._searchResultSect[i], 'bxhtmled-tskbr-search-res'); 757 this.ToggleGroup(this._searchResultSect[i], false); 758 } 759 this._searchResultSect = []; 760 } 761 }, 762 763 GetId: function() 764 { 765 return this.id; 766 } 767 }; 768 769 function ComponentsControl(editor) 770 { 771 // Call parrent constructor 772 ComponentsControl.superclass.constructor.apply(this, arguments); 773 774 this.id = 'components'; 775 this.title = BX.message('ComponentsTitle'); 776 this.templateId = this.editor.templateId; 777 this.uniqueId = 'taskbar_' + this.editor.id + '_' + this.id; 778 this.searchPlaceholder = BX.message('BXEdCompSearchPlaceHolder'); 779 780 this.Init(); 781 } 782 783 BX.extend(ComponentsControl, Taskbar); 784 785 ComponentsControl.prototype.Init = function() 786 { 787 this.BuildSceleton(); 788 // Build structure 789 var list = this.editor.components.GetList(); 790 this.BuildTree(list.groups, list.items); 791 }; 792 793 ComponentsControl.prototype.HandleElementEx = function(wrap, dd, params) 794 { 795 this.editor.SetBxTag(dd, {tag: "component_icon", params: params}); 796 if (params.complex == "Y") 797 { 798 params.className = 'bxhtmled-surrogate-green'; 799 BX.addClass(wrap, 'bxhtmled-tskbr-element-green'); 800 wrap.title = BX.message('BXEdComplexComp'); 801 } 802 }; 803 804 ComponentsControl.prototype.OnElementMouseDownEx = function(e, target, bxTag) 805 { 806 if (!bxTag || bxTag.tag !== 'component_icon') 807 { 808 return false; 809 } 810 811 this.editor.components.LoadParamsList({ 812 name: bxTag.params.name 813 }); 814 }; 815 816 ComponentsControl.prototype.GetMenuItems = function() 817 { 818 var _this = this; 819 return [ 820 { 821 text : BX.message('RefreshTaskbar'), 822 title : BX.message('RefreshTaskbar'), 823 className : "", 824 onclick: function() 825 { 826 _this.editor.componentsTaskbar.ClearSearchResult(); 827 _this.editor.components.ReloadList(); 828 BX.PopupMenu.destroy(_this.uniqueId + "_menu"); 829 } 830 } 831 ]; 832 }; 833 834 // Editor dialog 835 function Dialog(editor, params) 836 { 837 this.editor = editor; 838 this.id = params.id; 839 this.params = params; 840 this.className = "bxhtmled-dialog" + (params.className ? ' ' + params.className : ''); 841 this.zIndex = params.zIndex || 3008; 842 this.firstFocus = false; 843 this.Init(); 844 } 845 846 Dialog.prototype = { 847 Init: function() 848 { 849 var 850 _this = this, 851 config = { 852 title : this.params.title || this.params.name || '', 853 width: this.params.width || 600, 854 resizable: false 855 }; 856 857 if (this.params.resizable) 858 { 859 config.resizable = true; 860 config.min_width = this.params.min_width || 400; 861 config.min_height = this.params.min_height || 250; 862 config.resize_id = this.params.resize_id || this.params.id + '_res'; 863 } 864 865 this.oDialog = new BX.CDialog(config); 866 config.height = this.params.height || false; 867 868 BX.addCustomEvent(this.oDialog, 'onWindowResize', BX.proxy(this.OnResize, this)); 869 BX.addCustomEvent(this.oDialog, 'onWindowResizeFinished', BX.proxy(this.OnResizeFinished, this)); 870 BX.addClass(this.oDialog.PARTS.CONTENT, this.className); 871 872 // Clear dialog height for auto resizing 873 if (!config.height) 874 { 875 this.oDialog.PARTS.CONTENT_DATA.style.height = null; 876 } 877 878 // Buttons 879 this.oDialog.SetButtons([ 880 new BX.CWindowButton( 881 { 882 title: BX.message('DialogSave'), 883 className: 'adm-btn-save', 884 action: function() 885 { 886 BX.onCustomEvent(_this, "OnDialogSave"); 887 _this.oDialog.Close(); 888 } 889 }), 890 this.oDialog.btnCancel 891 ]); 892 893 BX.addCustomEvent(this.oDialog, 'onWindowUnRegister', function() 894 { 895 BX.unbind(window, "keydown", BX.proxy(_this.OnKeyDown, _this)); 896 _this.dialogShownTimeout = setTimeout(function(){_this.editor.dialogShown = false;}, 300); 897 _this.RestoreWindowOverflow(); 898 }); 899 }, 900 901 Show: function() 902 { 903 var _this = this; 904 this.editor.dialogShown = true; 905 if (this.dialogShownTimeout) 906 { 907 this.dialogShownTimeout = clearTimeout(this.dialogShownTimeout); 908 } 909 this.oDialog.Show(); 910 911 var 912 top = parseInt(this.oDialog.DIV.style.top) - 180, 913 scrollPos = BX.GetWindowScrollPos(document), 914 scrollTop = scrollPos.scrollTop, 915 minTop = scrollTop + 50; 916 917 this.oDialog.DIV.style.top = (top > minTop ? top : minTop) + 'px'; 918 BX.bind(window, "keydown", BX.proxy(this.OnKeyDown, this)); 919 920 this.savedBodyOverflow = this.savedScrollLeft = this.savedScrollTop = false;
921 922 setTimeout(function() 923 { 924 // Hack for Opera 925 if (BX.browser.IsOpera()) 926 _this.oDialog.Move(1, 1); 927 928 _this.oDialog.__resizeOverlay(); 929 930 if (_this.firstFocus) 931 { 932 BX.focus(_this.firstFocus); 933 if (_this.selectFirstFocus) 934 _this.firstFocus.select(); 935 } 936 }, 937 100 938 ); 939 }, 940 941 BuildTabControl: function(pCont, arTabs) 942 { 943 var 944 i, 945 pTabsWrap = BX.create('DIV', {props: {className: 'bxhtmled-dlg-tabs-wrap'}}), 946 pContWrap = BX.create('DIV', {props: {className: 'bxhtmled-dlg-cont-wrap'}}); 947 948 for (i = 0; i < arTabs.length; i++) 949 { 950 arTabs[i].tab = pTabsWrap.appendChild(BX.create('SPAN', {props: {className: 'bxhtmled-dlg-tab' + (i == 0 ? ' bxhtmled-dlg-tab-active' : '')}, attrs: {'data-bx-dlg-tab-ind': i.toString()}, text: arTabs[i].name})); 951 arTabs[i].cont = pContWrap.appendChild(BX.create('DIV', {props: {className: 'bxhtmled-dlg-cont'}, style: {'display' : i == 0 ? '' : 'none'}})); 952 } 953 954 BX.bind(pTabsWrap, 'click', function(e) 955 { 956 var 957 ind, 958 target = e.target || e.srcElement; 959 960 if (target && target.getAttribute) 961 { 962 ind = parseInt(target.getAttribute('data-bx-dlg-tab-ind')); 963 if (!isNaN(ind)) 964 { 965 for (i = 0; i < arTabs.length; i++) 966 { 967 if (i == ind) 968 { 969 arTabs[i].cont.style.display = ''; 970 BX.addClass(arTabs[i].tab, 'bxhtmled-dlg-tab-active'); 971 } 972 else 973 { 974 arTabs[i].cont.style.display = 'none'; 975 BX.removeClass(arTabs[i].tab, 'bxhtmled-dlg-tab-active'); 976 } 977 } 978 } 979 } 980 }); 981 982 pCont.appendChild(pTabsWrap); 983 pCont.appendChild(pContWrap); 984 985 return { 986 cont: pCont, 987 tabsWrap : pTabsWrap, 988 contWrap : pContWrap, 989 tabs: arTabs 990 }; 991 }, 992 993 OnKeyDown: function(e) 994 { 995 if (e.keyCode == 13 && this.closeByEnter !== false) 996 { 997 var target = e.target || e.srcElement; 998 if (target && target.nodeName !== 'TEXTAREA') 999 { 1000 this.oDialog.PARAMS.buttons[0].emulate(); 1001 } 1002 } 1003 }, 1004 1005 SetContent: function(html) 1006 { 1007 return this.oDialog.SetContent(html); 1008 }, 1009 1010 SetTitle: function(title) 1011 { 1012 return this.oDialog.SetTitle(title); 1013 }, 1014 1015 OnResize: function() 1016 { 1017 }, 1018 1019 OnResizeFinished: function() 1020 { 1021 }, 1022 1023 GetContentSize: function() 1024 { 1025 return { 1026 width : this.oDialog.PARTS.CONTENT_DATA.offsetWidth, 1027 height : this.oDialog.PARTS.CONTENT_DATA.offsetHeight 1028 }; 1029 }, 1030 1031 Save: function() 1032 { 1033 if (this.savedRange) 1034 { 1035 this.editor.selection.SetBookmark(this.savedRange); 1036 } 1037 1038 if (this.action && this.editor.action.IsSupported(this.action)) 1039 { 1040 this.editor.action.Exec(this.action, this.GetValues()); 1041 } 1042 }, 1043 1044 Close: function() 1045 { 1046 if (this.IsOpen()) 1047 { 1048 this.oDialog.Close(); 1049 } 1050 }, 1051 1052 IsOpen: function() 1053 { 1054 return this.oDialog.isOpen; 1055 }, 1056 1057 DisableKeyCheck: function() 1058 { 1059 this.closeByEnter = false; 1060 BX.WindowManager.disableKeyCheck(); 1061 }, 1062 1063 EnableKeyCheck: function() 1064 { 1065 var _this = this; 1066 setTimeout(function() 1067 { 1068 _this.closeByEnter = true; 1069 BX.WindowManager.enableKeyCheck(); 1070 }, 200); 1071 }, 1072 1073 AddTableRow: function (tbl, firstCell) 1074 { 1075 var r, c1, c2; 1076 1077 r = tbl.insertRow(-1); 1078 c1 = r.insertCell(-1); 1079 c1.className = 'bxhtmled-left-c'; 1080 1081 if (firstCell && firstCell.label) 1082 { 1083 c1.appendChild(BX.create('LABEL', {props: {className: firstCell.required ? 'bxhtmled-req' : ''}, text: firstCell.label})).setAttribute('for', firstCell.id); 1084 } 1085 1086 c2 = r.insertCell(-1); 1087 c2.className = 'bxhtmled-right-c'; 1088 return {row: r, leftCell: c1, rightCell: c2}; 1089 }, 1090 1091 SetValues: BX.DoNothing, 1092 GetValues: BX.DoNothing, 1093 1094 CheckSize: function(timeout) 1095 { 1096 var _this = this; 1097 1098 if (this.checkSizeTimeout) 1099 this.checkSizeTimeout = clearTimeout(this.checkSizeTimeout); 1100 1101 if (timeout !== true) 1102 { 1103 this.checkSizeTimeout = setTimeout(function() 1104 { 1105 _this.CheckSize(true); 1106 }, 50); 1107 return; 1108 } 1109 1110 var 1111 innerSize = BX.GetWindowInnerSize(document), 1112 dialogBottom = this.oDialog.DIV.offsetHeight + 50; 1113 1114 if (dialogBottom >
1114= innerSize.innerHeight) 1115 { 1116 var scrollPos = BX.GetWindowScrollPos(document); 1117 this.savedBodyOverflow = document.body.style.overflow; 1118 this.savedScrollTop = scrollPos.scrollTop; 1119 this.savedScrollLeft = scrollPos.scrollLeft; 1120 document.body.style.overflow = "auto"; 1121 1122 if (this.editor.expanded) 1123 BX.unbind(window, "scroll", BX.proxy(this.editor.PreventScroll, this.editor)); 1124 } 1125 else 1126 { 1127 this.RestoreWindowOverflow(); 1128 } 1129 }, 1130 1131 RestoreWindowOverflow: function() 1132 { 1133 if (this.savedBodyOverflow !== false) 1134 { 1135 document.body.style.overflow = this.savedBodyOverflow; 1136 this.savedBodyOverflow = false; 1137 } 1138 1139 if (this.savedScrollTop !== false) 1140 { 1141 window.scrollTo(this.savedScrollLeft, this.savedScrollTop); 1142 this.savedScrollLeft = this.savedScrollTop = false; 1143 } 1144 1145 if (this.editor.expanded) 1146 BX.bind(window, "scroll", BX.proxy(this.editor.PreventScroll, this.editor)); 1147 } 1148 }; 1149 1150 function ContextMenu(editor) 1151 { 1152 this.editor = editor; 1153 BX.addCustomEvent(this.editor, 'OnIframeContextMenu', BX.delegate(this.Show, this)); 1154 this.Init(); 1155 } 1156 1157 ContextMenu.prototype = { 1158 Init: function() 1159 { 1160 var 1161 _this = this, 1162 defaultItem = { 1163 TEXT: BX.message('ContMenuDefProps'), 1164 ACTION: function() 1165 { 1166 _this.editor.selection.SetBookmark(_this.savedRange); 1167 _this.editor.GetDialog('Default').Show(false, _this.savedRange); 1168 _this.Hide(); 1169 } 1170 }; 1171 1172 // Remove format ? 1173 // Replace Node by children ? 1174 1175 this.items = { 1176 // Surrogates 1177 'php' : [ 1178 { 1179 TEXT: BX.message('BXEdContMenuPhpCode'), 1180 ACTION: function() 1181 { 1182 var items = _this.GetTargetItem(); 1183 if (items && items.php) 1184 { 1185 _this.editor.GetDialog('Source').Show(items.php.bxTag); 1186 } 1187 _this.Hide(); 1188 } 1189 } 1190 ], 1191 'anchor' : [ 1192 { 1193 TEXT: BX.message('BXEdEditAnchor'), 1194 ACTION: function() 1195 { 1196 var items = _this.GetTargetItem(); 1197 if (items && items.anchor) 1198 { 1199 _this.editor.GetDialog('Anchor').Show(items.anchor.bxTag); 1200 } 1201 _this.Hide(); 1202 } 1203 } 1204 ], 1205 'javascript' : [ 1206 { 1207 TEXT: BX.message('BXEdContMenuJavascript'), 1208 ACTION: function() 1209 { 1210 var items = _this.GetTargetItem(); 1211 if (items && items.javascript) 1212 { 1213 _this.editor.GetDialog('Source').Show(items.javascript.bxTag); 1214 } 1215 _this.Hide(); 1216 } 1217 } 1218 ], 1219 'htmlcomment' : [ 1220 { 1221 TEXT: BX.message('BXEdContMenuHtmlComment'), 1222 ACTION: function() 1223 { 1224 var items = _this.GetTargetItem(); 1225 if (items && items.htmlcomment) 1226 { 1227 _this.editor.GetDialog('Source').Show(items.htmlcomment.bxTag); 1228 } 1229 _this.Hide(); 1230 } 1231 } 1232 ], 1233 'iframe' : [ 1234 { 1235 TEXT: BX.message('BXEdContMenuIframe'), 1236 ACTION: function() 1237 { 1238 var items = _this.GetTargetItem(); 1239 if (items && items.iframe) 1240 { 1241 _this.editor.GetDialog('Source').Show(items.iframe.bxTag); 1242 } 1243 _this.Hide(); 1244 } 1245 } 1246 ], 1247 'style' : [ 1248 { 1249 TEXT: BX.message('BXEdContMenuStyle'), 1250 ACTION: function() 1251 { 1252 var items = _this.GetTargetItem(); 1253 if (items && items.style) 1254 { 1255 _this.editor.GetDialog('Source').Show(items.style.bxTag); 1256 } 1257 _this.Hide(); 1258 } 1259 } 1260 ], 1261 'object' : [ 1262 { 1263 TEXT: BX.message('BXEdContMenuObject'), 1264 ACTION: function() 1265 { 1266 var items = _this.GetTargetItem(); 1267 if (items && items.object) 1268 { 1269 _this.editor.GetDialog('Source').Show(items.object.bxTag); 1270 } 1271 _this.Hide(); 1272 } 1273 } 1274 ], 1275 'component' : [ 1276 { 1277 TEXT: BX.message('BXEdContMenuComponent'), 1278 ACTION: function() 1279 { 1280 var items = _this.GetTargetItem(); 1281 if (items && items.component) 1282 { 1283 // Show dialog 1284 _this.editor.components.ShowPropertiesDialog(items.component.bxTag.params, _this.editor.GetBxTag(items.component.bxTag.surrogateId)); 1285 } 1286 _this.Hide(); 1287 } 1288 }, 1289 { 1290 TEXT: BX.message('BXEdContMenuComponentRemove'), 1291 ACTION: function() 1292 { 1293 var items = _this.GetTargetItem(); 1294 if (items && items.component) 1295 { 1296 BX.remove(items.component.element); 1297 } 1298 _this.Hide(); 1299 } 1300 } 1301 ], 1302 'printbreak' : [ 1303 { 1304 TEXT: BX.message('NodeRemove'), 1305 ACTION: function(e) 1306 { 1307 var node = _this.GetTargetItem('printbreak'); 1308 if (node && node.element) 1309 { 1310 _this.editor.selection.RemoveNode(node.element); 1311 } 1312 _this.Hide(); 1313 } 1314 } 1315 ], 1316 'video': [ 1317 { 1318 TEXT: BX.message('BXEdVideoProps'), 1319 bbMode: true, 1320 ACTION: function() 1321 { 1322 var node = _this.GetTargetItem('video'); 1323 if (node) 1324 { 1325 _this.editor.GetDialog('Video').Show(node.bxTag); 1326 } 1327 _this.Hide(); 1328 } 1329 }, 1330 { 1331 TEXT: BX.message('BXEdVideoDel'), 1332 bbMode: true, 1333 ACTION: function(e) 1334 { 1335 var node = _this.GetTargetItem('video'); 1336 if (node && node.element) 1337 { 1338 _this.editor.selection.RemoveNode(node.element); 1339 } 1340 _this.Hide(); 1341 } 1342 } 1343 ], 1344 'smile' : [], 1345 1346 // Nodes 1347 'A' : [ 1348 { 1349 TEXT: BX.message('ContMenuLinkEdit'), 1350 bbMode: true, 1351 ACTION: function() 1352 { 1353 var node = _this.GetTargetItem('A'); 1354 if (node) 1355 { 1356 _this.editor.GetDialog('Link').Show([node], this.savedRange); 1357 } 1358 _this.Hide(); 1359 } 1360 }, 1361 { 1362 TEXT: BX.message('ContMenuLinkDel'), 1363 bbMode: true, 1364 ACTION: function() 1365 { 1366 var link = _this.GetTargetItem('A'); 1367 if (link && _this.editor.action.IsSupported('removeLink')) 1368 { 1369 _this.editor.action.Exec('removeLink', [link]); 1370 } 1371 _this.Hide(); 1372 } 1373 } 1374 ], 1375 'IMG': [ 1376 { 1377 TEXT: BX.message('ContMenuImgEdit'), 1378 bbMode: true, 1379 ACTION: function() 1380 { 1381 var node = _this.GetTargetItem('IMG'); 1382 if (node) 1383 { 1384 _this.editor.GetDialog('Image').Show([node], _this.savedRange); 1385 } 1386 _this.Hide(); 1387 } 1388 }, 1389 { 1390 TEXT: BX.message('ContMenuImgDel'), 1391 bbMode: true, 1392 ACTION: function() 1393 { 1394 var node = _this.GetTargetItem('IMG'); 1395 if (node) 1396 { 1397 _this.editor.selection.RemoveNode(node); 1398 } 1399 _this.Hide(); 1400 } 1401 } 1402 ], 1403 'DIV': [ 1404 { 1405 TEXT: BX.message('ContMenuCleanDiv'), 1406 title: BX.message('ContMenuCleanDiv_Title'), 1407 ACTION: function() 1408 { 1409 var node = _this.GetTargetItem('DIV'); 1410 if (node) 1411 { 1412 _this.editor.On('OnHtmlContentChangedByControl'); 1413 _this.editor.util.ReplaceWithOwnChildren(node); 1414 _this.editor.synchro.FullSyncFromIframe(); 1415 } 1416 _this.Hide(); 1417 } 1418 }, 1419 defaultItem 1420 ], 1421 'TABLE': [ 1422 1423 { 1424 TEXT: BX.message('BXEdTableInsertMenu'), 1425 HIDE_ITEM: function() 1426 { 1427 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1428 return !cells || cells.length != 1; 1429 }, 1430 MENU: [ 1431 // Column 1432 { 1433 TEXT: BX.message('BXEdTableInsColLeft'), 1434 ACTION: function() 1435 { 1436 _this.editor.action.Exec('tableOperation', { 1437 actionType: 'insertColumnLeft', 1438 tableNode: _this.GetTargetItem('TABLE'),
1439 range: _this.savedRange 1440 }); 1441 _this.Hide(); 1442 } 1443 }, 1444 { 1445 TEXT: BX.message('BXEdTableInsColRight'), 1446 ACTION: function() 1447 { 1448 _this.editor.action.Exec('tableOperation', { 1449 actionType: 'insertColumnRight', 1450 tableNode: _this.GetTargetItem('TABLE'), 1451 range: _this.savedRange 1452 }); 1453 _this.Hide(); 1454 } 1455 }, 1456 // Row 1457 { 1458 TEXT: BX.message('BXEdTableInsRowUpper'), 1459 ACTION: function() 1460 { 1461 _this.editor.action.Exec('tableOperation', { 1462 actionType: 'insertRowUpper', 1463 tableNode: _this.GetTargetItem('TABLE'), 1464 range: _this.savedRange 1465 }); 1466 _this.Hide(); 1467 } 1468 }, 1469 { 1470 TEXT: BX.message('BXEdTableInsRowLower'), 1471 ACTION: function() 1472 { 1473 _this.editor.action.Exec('tableOperation', { 1474 actionType: 'insertRowLower', 1475 tableNode: _this.GetTargetItem('TABLE'), 1476 range: _this.savedRange 1477 }); 1478 _this.Hide(); 1479 } 1480 }, 1481 // Cell 1482 { 1483 TEXT: BX.message('BXEdTableInsCellBefore'), 1484 ACTION: function() 1485 { 1486 _this.editor.action.Exec('tableOperation', { 1487 actionType: 'insertCellLeft', 1488 tableNode: _this.GetTargetItem('TABLE'), 1489 range: _this.savedRange 1490 }); 1491 _this.Hide(); 1492 } 1493 }, 1494 { 1495 TEXT: BX.message('BXEdTableInsCellAfter'), 1496 ACTION: function() 1497 { 1498 _this.editor.action.Exec('tableOperation', { 1499 actionType: 'insertCellRight', 1500 tableNode: _this.GetTargetItem('TABLE'), 1501 range: _this.savedRange 1502 }); 1503 _this.Hide(); 1504 } 1505 } 1506 ] 1507 }, 1508 { 1509 TEXT: BX.message('BXEdTableRemoveMenu'), 1510 MENU: [ 1511 { 1512 TEXT: BX.message('BXEdTableDelCol'), 1513 ACTION: function() 1514 { 1515 _this.editor.action.Exec('tableOperation', { 1516 actionType: 'removeColumn', 1517 tableNode: _this.GetTargetItem('TABLE'), 1518 range: _this.savedRange 1519 }); 1520 _this.Hide(); 1521 }, 1522 HIDE_ITEM: function() 1523 { 1524 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1525 return !cells || cells.length != 1; 1526 } 1527 }, 1528 { 1529 TEXT: BX.message('BXEdTableDelRow'), 1530 ACTION: function() 1531 { 1532 _this.editor.action.Exec('tableOperation', { 1533 actionType: 'removeRow', 1534 tableNode: _this.GetTargetItem('TABLE'), 1535 range: _this.savedRange 1536 }); 1537 _this.Hide(); 1538 }, 1539 HIDE_ITEM: function() 1540 { 1541 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1542 return !cells || cells.length != 1; 1543 } 1544 }, 1545 { 1546 TEXT: BX.message('BXEdTableDellCell'), 1547 ACTION: function() 1548 { 1549 _this.editor.action.Exec('tableOperation', { 1550 actionType: 'removeCell', 1551 tableNode: _this.GetTargetItem('TABLE'), 1552 range: _this.savedRange 1553 }); 1554 _this.Hide(); 1555 }, 1556 HIDE_ITEM: function() 1557 { 1558 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1559 return !cells || cells.length != 1; 1560 } 1561 }, 1562 { 1563 TEXT: BX.message('BXEdTableDellSelectedCells'), 1564 ACTION: function() 1565 { 1566 _this.editor.action.Exec('tableOperation', { 1567 actionType: 'removeSelectedCells', 1568 tableNode: _this.GetTargetItem('TABLE'), 1569 range: _this.savedRange 1570 }); 1571 _this.Hide(); 1572 }, 1573 HIDE_ITEM: function() 1574 { 1575 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1576 return !cells || cells.length === 1; 1577 } 1578 } 1579 ] 1580 }, 1581 { 1582 TEXT: BX.message('BXEdTableMergeMenu'), 1583 MENU: [ 1584 { 1585 TEXT: BX.message('BXEdTableMergeSelectedCells'), 1586 ACTION: function() 1587 { 1588 _this.editor.action.Exec('tableOperation', { 1589 actionType: 'mergeSelectedCells', 1590 tableNode: _this.GetTargetItem('TABLE'),
1591 range: _this.savedRange 1592 }); 1593 _this.Hide(); 1594 }, 1595 HIDE_ITEM: function() 1596 { 1597 if (!_this.savedRange.collapsed) 1598 { 1599 return !_this.editor.action.actions.tableOperation.canBeMerged(false, _this.savedRange, _this.GetTargetItem('TABLE')); 1600 } 1601 1602 return true; 1603 } 1604 }, 1605 { 1606 TEXT: BX.message('BXEdTableMergeRight'), 1607 ACTION: function() 1608 { 1609 _this.editor.action.Exec('tableOperation', { 1610 actionType: 'mergeRightCell', 1611 tableNode: _this.GetTargetItem('TABLE'), 1612 range: _this.savedRange 1613 }); 1614 _this.Hide(); 1615 }, 1616 HIDE_ITEM: function() 1617 { 1618 return !_this.editor.action.actions.tableOperation.canBeMergedWithRight(_this.savedRange, _this.GetTargetItem('TABLE')); 1619 } 1620 }, 1621 { 1622 TEXT: BX.message('BXEdTableMergeBottom'), 1623 ACTION: function() 1624 { 1625 _this.editor.action.Exec('tableOperation', { 1626 actionType: 'mergeBottomCell', 1627 tableNode: _this.GetTargetItem('TABLE'), 1628 range: _this.savedRange 1629 }); 1630 _this.Hide(); 1631 }, 1632 HIDE_ITEM: function() 1633 { 1634 return !_this.editor.action.actions.tableOperation.canBeMergedWithBottom(_this.savedRange, _this.GetTargetItem('TABLE')); 1635 } 1636 }, 1637 { 1638 TEXT: BX.message('BXEdTableMergeRowCells'), 1639 ACTION: function() 1640 { 1641 _this.editor.action.Exec('tableOperation', { 1642 actionType: 'mergeRow', 1643 tableNode: _this.GetTargetItem('TABLE'), 1644 range: _this.savedRange 1645 }); 1646 _this.Hide(); 1647 }, 1648 HIDE_ITEM: function() 1649 { 1650 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1651 return !cells || cells.length > 1; 1652 } 1653 }, 1654 { 1655 TEXT: BX.message('BXEdTableMergeColCells'), 1656 ACTION: function() 1657 { 1658 _this.editor.action.Exec('tableOperation', { 1659 actionType: 'mergeColumn', 1660 tableNode: _this.GetTargetItem('TABLE'), 1661 range: _this.savedRange 1662 }); 1663 _this.Hide(); 1664 }, 1665 HIDE_ITEM: function() 1666 { 1667 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1668 return !cells || cells.length > 1; 1669 } 1670 } 1671 ] 1672 }, 1673 { 1674 TEXT: BX.message('BXEdTableSplitMenu'), 1675 HIDE_ITEM: function() 1676 { 1677 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1678 return !cells || cells.length != 1; 1679 }, 1680 MENU: [ 1681 { 1682 TEXT: BX.message('BXEdTableSplitCellHor'), 1683 ACTION: function() 1684 { 1685 _this.editor.action.Exec('tableOperation', { 1686 actionType: 'splitHorizontally', 1687 tableNode: _this.GetTargetItem('TABLE'), 1688 range: _this.savedRange 1689 }); 1690 _this.Hide(); 1691 } 1692 }, 1693 { 1694 TEXT: BX.message('BXEdTableSplitCellVer'), 1695 ACTION: function() 1696 { 1697 _this.editor.action.Exec('tableOperation', { 1698 actionType: 'splitVertically', 1699 tableNode: _this.GetTargetItem('TABLE'), 1700 range: _this.savedRange 1701 }); 1702 _this.Hide(); 1703 } 1704 } 1705 ] 1706 }, 1707 {SEPARATOR: true}, 1708 1709 { 1710 TEXT: BX.message('BXEdTableTableCellProps'), 1711 ACTION: function() 1712 { 1713 var node = _this.GetTargetItem('TABLE'); 1714 if (node) 1715 { 1716 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1717 _this.editor.GetDialog('Default').Show(cells, _this.savedRange); 1718 } 1719 _this.Hide(); 1720 }, 1721 HIDE_ITEM: function() 1722 { 1723 var cells = _this.editor.action.actions.tableOperation.getSelectedCells(_this.savedRange, _this.GetTargetItem('TABLE')); 1724 return !cells || cells.length != 1; 1725 } 1726 }, 1727 1728 { 1729 TEXT: BX.message('BXEdTableTableProps'), 1730 ACTION: function() 1731 { 1732 var node = _this.GetTargetItem('TABLE'); 1733 if (node) 1734 { 1735 _this.editor.GetDialog('Table').Show([node], _this.savedRange); 1736 } 1737 _this.Hide(); 1738 } 1739 }, 1740 { 1741 TEXT: BX.message('BXEdTableDeleteTable'), 1742 bbMode: true, 1743 ACTION: function() 1744 { 1745 var node = _this.GetTargetItem('TABLE'); 1746 if (node) 1747 { 1748 _this.editor.selection.RemoveNode(node); 1749 } 1750 _this.Hide(); 1751 } 1752 } 1753 ], 1754 // ... 1755 'DEFAULT': [defaultItem] 1756 }; 1757 }, 1758 1759 Show: function(e, target, collapsedSelection) 1760 { 1761 //open context menu only in admin html-editor 1762 const targetBxTag = this.editor.GetBxTag(target); 1763 if (targetBxTag.tag === 'diskfile0' || targetBxTag.hideContextMenu) 1764 { 1765 return; 1766 } 1767 1768 this.savedRange = this.editor.selection.GetBookmark(); 1769 this.Hide(); 1770 1771 this.editor.contextMenuShown = true; 1772 if (this.contextMenuShownTimeout) 1773 { 1774 this.contextMenuShownTimeout = clearTimeout(this.contextMenuShownTimeout); 1775 } 1776 this.nodes = []; 1777 this.tagIndex = {}; 1778 var 1779 bxTag, 1780 i, j, k, menuItems, item, itemGr, 1781 arItems = [], 1782 maxIter = 20, iter = 0, 1783 element = target, 1784 label; 1785 1786 this.targetItems = {}; 1787 while (true) 1788 { 1789 if (element.nodeName && element.nodeName.toUpperCase() != 'BODY') 1790 { 1791 if (element.nodeType != 3) 1792 { 1793 bxTag = this.editor.GetBxTag(element); 1794 1795 if (bxTag && bxTag.tag == 'surrogate_dd') 1796 { 1797 var origTag = this.editor.GetBxTag(bxTag.params.origId); 1798 element = this.editor.GetIframeElement(origTag.id); 1799 this.PushTargetItem(origTag.tag, {element: element, bxTag: origTag}); 1800 this.nodes = [element]; 1801 this.tagIndex[origTag.tag] = 0; 1802 iter = 0; 1803 element = element.parentNode; 1804 continue; 1805 } 1806 else if (bxTag && bxTag.tag && this.items[bxTag.tag]) 1807 { 1808 this.nodes = [element]; 1809 this.PushTargetItem(bxTag.tag, {element: element, bxTag: bxTag.tag}); 1810 this.nodes = [element]; 1811 this.tagIndex[bxTag.tag] = 0; 1812 iter = 0; 1813 element = element.parentNode; 1814 continue; 1815 } 1816 1817 label = element.nodeName; 1818 this.PushTargetItem(label, element); 1819 this.nodes.push(element); 1820 this.tagIndex[label] = this.nodes.length - 1; 1821 } 1822 iter++; 1823 } 1824 1825 if (!element || 1826 element.nodeName && element.nodeName.toUpperCase() == 'BODY' || 1827 iter >= maxIter) 1828 { 1829 break; 1830 } 1831 1832 element = element.parentNode; 1833 } 1834 1835 for (i in this.items) 1836 { 1837 if (this.items.hasOwnProperty(i) && this.tagIndex[i] != undefined) 1838 { 1839 if (arItems.length > 0) 1840 { 1841 arItems.push({SEPARATOR : true}); 1842 } 1843 1844 for (j = 0; j < this.items[i].length; j++) 1845 { 1846 if (typeof this.items[i][j].HIDE_ITEM == 'function' && this.items[i][j].HIDE_ITEM() === true) 1847 continue; 1848 1849 if (this.editor.bbCode && !this.items[i][j].bbMode) 1850 continue; 1851 1852 if (this.items[i][j].MENU) 1853 { 1854 itemGr = BX.clone(this.items[i][j]); 1855 menuItems = []; 1856 for (k = 0; k < itemGr.MENU.length; k++) 1857 { 1858 item = itemGr.MENU[k]; 1859 if (typeof item.HIDE_ITEM == 'function' && item.HIDE_ITEM() === true) 1860 continue; 1861 1862 if (this.editor.bbCode && !item.bbMode) 1863 continue; 1864 1865 menuItems.push(item); 1866 } 1867 1868 if (menuItems.length === 0) 1869 continue; 1870 1871 itemGr.MENU = menuItems; 1872 1873 arItems.push(itemGr); 1874 } 1875 else 1876 { 1877 arItems.push(this.items[i][j]); 1878 } 1879 } 1880 } 1881 } 1882
1883 if (arItems.length == 0 && (!this.editor.bbCode || this.items['DEFAULT'].bbMode)) 1884 { 1885 if (!this.savedRange || (!this.savedRange.collapsed && !collapsedSelection)) 1886 { 1887 for (j = 0; j < this.items['DEFAULT'].length; j++) 1888 { 1889 arItems.push(this.items['DEFAULT'][j]); 1890 } 1891 } 1892 } 1893 1894 var 1895 x = e.clientX, 1896 y = e.clientY; 1897 1898 if (!this.dummyTarget) 1899 { 1900 this.dummyTarget = this.editor.dom.iframeCont.appendChild(BX.create('DIV', {props: {className: 'bxhtmled-dummy-target'}})); 1901 } 1902 1903 this.dummyTarget.style.left = x + 'px'; 1904 this.dummyTarget.style.top = y + 'px'; 1905 this.dummyTarget.style.zIndex = '2002'; 1906 1907 if (arItems.length > 0) 1908 { 1909 this.OPENER = new BX.COpener({ 1910 DIV: this.dummyTarget, 1911 MENU: arItems, 1912 TYPE: 'click', 1913 ACTIVE_CLASS: 'adm-btn-active', 1914 CLOSE_ON_CLICK: true 1915 }); 1916 this.OPENER.Open(); 1917 var popupDiv = this.OPENER.GetMenu().DIV; 1918 popupDiv.id = 'bx-admin-prefix'; 1919 BX.addClass(popupDiv, 'bx-core-popup-menu-editor'); 1920 1921 this.isOpened = true; 1922 BX.addCustomEvent(this.editor, 'OnIframeClick', BX.proxy(this.Hide, this)); 1923 BX.addCustomEvent(this.editor, 'OnIframeKeyup', BX.proxy(this.CheckEscapeClose, this)); 1924 return BX.PreventDefault(e); 1925 } 1926 }, 1927 1928 Hide: function() 1929 { 1930 if (this.OPENER) 1931 { 1932 var _this = this; 1933 this.contextMenuShownTimeout = setTimeout(function(){_this.editor.contextMenuShown = false;}, 300); 1934 this.OPENER.bMenuInit = true; 1935 this.OPENER.Close(); 1936 this.isOpened = false; 1937 BX.removeCustomEvent(this.editor, 'OnIframeClick', BX.proxy(this.Hide, this)); 1938 BX.removeCustomEvent(this.editor, 'OnIframeKeyup', BX.proxy(this.CheckEscapeClose, this)); 1939 } 1940 }, 1941 1942 CheckEscapeClose: function(e, keyCode) 1943 { 1944 if (keyCode == this.editor.KEY_CODES['escape']) 1945 this.Hide(); 1946 }, 1947 1948 GetTargetItem: function(tag) 1949 { 1950 return tag ? (this.targetItems[tag] || null) : this.targetItems; 1951 }, 1952 1953 PushTargetItem: function(key, tag) 1954 { 1955 if (!this.targetItems[key]) 1956 this.targetItems[key] = tag; 1957 } 1958 }; 1959 1960 function Toolbar(editor, topControls) 1961 { 1962 this.editor = editor; 1963 this.pCont = editor.dom.toolbar; 1964 this.controls = {}; 1965 this.bCompact = false; 1966 this.topControls = topControls; 1967 this.showMoreButton = false; 1968 this.shown = true; 1969 this.height = null; 1970 this.Init(); 1971 } 1972 1973 Toolbar.prototype = { 1974 Init: function() 1975 { 1976 this.BuildControls(); 1977 // Init Event handlers 1978 BX.addCustomEvent(this.editor, "OnIframeFocus", BX.delegate(this.EnableWysiwygButtons, this)); 1979 BX.addCustomEvent(this.editor, "OnTextareaFocus", BX.delegate(this.DisableWysiwygButtons, this)); 1980 BX.bind(this.pCont, 'scroll', BX.proxy(this.SetScrollShadows, this)); 1981 }, 1982 1983 SetScrollShadows: function() 1984 { 1985 const scrollWidth = this.pCont.scrollWidth; 1986 const width = this.pCont.offsetWidth; 1987 let scrollLeft = this.pCont.scrollLeft; 1988 let scrollRight = scrollWidth - width - scrollLeft; 1989 if (scrollRight < 0) 1990 { 1991 scrollLeft += scrollRight; 1992 scrollRight = 0; 1993 } 1994 if (scrollLeft > 20 && scrollRight > 20) 1995 { 1996 this.pCont.parentNode.classList.remove('has-tools-on-left'); 1997 this.pCont.parentNode.classList.remove('has-tools-on-right'); 1998 this.pCont.parentNode.classList.add('has-tools-on-sides'); 1999 } 2000 else if (scrollLeft > 20) 2001 { 2002 this.pCont.parentNode.classList.add('has-tools-on-left'); 2003 this.pCont.parentNode.classList.remove('has-tools-on-right'); 2004 this.pCont.parentNode.classList.remove('has-tools-on-sides'); 2005 } 2006 else if (scrollRight > 20) 2007 { 2008 this.pCont.parentNode.classList.remove('has-tools-on-left'); 2009 this.pCont.parentNode.classList.add('has-tools-on-right'); 2010 this.pCont.parentNode.classList.remove('has-tools-on-sides'); 2011 } 2012 else if (scrollLeft < 20 && scrollRight < 20) 2013 { 2014 this.pCont.parentNode.classList.remove('has-tools-on-left'); 2015 this.pCont.parentNode.classList.remove('has-tools-on-right'); 2016 this.pCont.parentNode.classList.remove('has-tools-on-sides'); 2017 } 2018 }, 2019 2020 BuildControls: function() 2021 { 2022 BX.cleanNode(this.pCont); 2023 var 2024 i, 2025 wrap, moreCont, cont, 2026 map = this.GetControlsMap(), 2027 wraps = { 2028 left: this.pCont.appendChild(BX.create('span', {props: {className: 'bxhtmled-top-bar-left-wrap'}, style: {display: 'none'}})), 2029 main: this.pCont.appendChild(BX.create('span', {props: {className: 'bxhtmled-top-bar-wrap'}, style: {display: 'none'}})), 2030 right: this.pCont.appendChild(BX.create('span', {props: {className: 'bxhtmled-top-bar-right-wrap'}, style: {display: 'none'}})), 2031 hidden: this.pCont.appendChild(BX.create('span', {props: {className: 'bxhtmled-top-bar-hidden-wrap'}})) 2032 }; 2033 2034 this.hiddenWrap = wraps.hidden; 2035 2036 this.editor.normalWidth = this.editor.NORMAL_WIDTH; 2037 for (i = 0; i < map.length; i++) 2038 { 2039 if(map[i].hidden) 2040 { 2041 map[i].wrap = 'hidden'; 2042 this.showMoreButton = true; 2043 } 2044 else if (map[i].checkWidth && map[i].offsetWidth) 2045 { 2046 this.editor.normalWidth += map[i].offsetWidth; 2047 } 2048 2049 wrap = wraps[(map[i].wrap || 'main')]; 2050 2051 if (!wrap) 2052 { 2053 // We trying to find wrap as dom element by Id 2054 wrap = BX(map[i].wrap); 2055 if (wrap) 2056 { 2057 wraps[map[i].wrap] = wrap; 2058 } 2059 else 2060 { 2061 wrap = wraps['main']; 2062 } 2063 } 2064 2065 if (wrap.style.display == 'none') 2066 wrap.style.display = ''; 2067 2068 if (map[i].separator) 2069 { 2070 wrap.appendChild(this.GetSeparator()); // Show separator 2071 }
2072 else if(this.topControls[map[i].id]) 2073 { 2074 if (!this.controls[map[i].id]) 2075 { 2076 this.controls[map[i].id] = new this.topControls[map[i].id](this.editor, wrap); 2077 } 2078 else 2079 { 2080 cont = this.controls[map[i].id].GetPopupBindCont ? this.controls[map[i].id].GetPopupBindCont() : this.controls[map[i].id].GetCont(); 2081 2082 if (this.controls[map[i].id].CheckBeforeShow && !this.controls[map[i].id].CheckBeforeShow()) 2083 continue; 2084 2085 if (this.controls.More && ((this.bCompact && !map[i].compact) || map[i].hidden)) 2086 { 2087 if (!moreCont) 2088 { 2089 moreCont = this.controls.More.GetPopupCont(); 2090 } 2091 moreCont.appendChild(cont); 2092 } 2093 else 2094 { 2095 wrap.appendChild(cont); 2096 } 2097 } 2098 } 2099 } 2100 2101 for (i in wraps) 2102 { 2103 if (wraps.hasOwnProperty(i) && i !== 'main' && i !== 'left' && i !== 'right' && i !== 'hidden' && wraps[i].getAttribute('data-bx-check-command') !== 'N') 2104 { 2105 wraps[i].setAttribute('data-bx-check-command', 'N'); 2106 BX.bind(wraps[i], "click", BX.proxy(function(e) 2107 { 2108 this.editor.CheckCommand(e.target || e.srcElement); 2109 }, this)); 2110 } 2111 } 2112 }, 2113 2114 GetControlsMap: function() 2115 { 2116 if (this.controlsMap) 2117 return this.controlsMap; 2118 2119 var res = this.editor.config.controlsMap; 2120 if (!res) 2121 { 2122 res = [ 2123 //{id: 'SearchButton', wrap: 'left', compact: true}, 2124 {id: 'ChangeView', wrap: 'left', compact: true, sort: 10}, 2125 {id: 'placeholder_selector', compact: true, sort: 15}, 2126 {id: 'Undo', compact: false, sort: 20}, 2127 {id: 'Redo', compact: false, sort: 30}, 2128 {id: 'StyleSelector', compact: true, sort: 40}, 2129 {id: 'FontSelector', compact: false, sort: 50}, 2130 {id: 'FontSize', compact: false, sort: 60}, 2131 {separator: true, compact: false, sort: 70}, 2132 {id: 'Bold', compact: true, sort: 80}, 2133 {id: 'Italic', compact: true, sort: 90}, 2134 {id: 'Underline', compact: true, sort: 100}, 2135 {id: 'Strikeout', compact: true, sort: 110}, 2136 {id: 'RemoveFormat', compact: true, sort: 120}, 2137 {id: 'Color', compact: true, sort: 130}, 2138 {separator: true, compact: false, sort: 140}, 2139 {id: 'OrderedList', compact: true, sort: 150}, 2140 {id: 'UnorderedList', compact: true, sort: 160}, 2141 {id: 'IndentButton', compact: true, sort: 170}, 2142 {id: 'OutdentButton', compact: true, sort: 180}, 2143 {id: 'AlignList',compact: true, sort: 190}, 2144 {separator: true, compact: false, sort: 200}, 2145 {id: 'InsertLink', compact: true, sort: 210}, 2146 {id: 'InsertImage', compact: true, sort: 220}, 2147 {id: 'InsertVideo', compact: true, sort: 230}, 2148 {id: 'InsertAnchor', compact: false, sort: 240}, 2149 {id: 'InsertTable', compact: false, sort: 250}, 2150 {id: 'InsertChar', compact: false, hidden: true, sort: 260}, 2151 {id: 'PrintBreak', compact: false, hidden: true, sort: 270}, 2152 {id: 'PageBreak', compact: false, hidden: true, sort: 275}, 2153 {id: 'Spellcheck', compact: false, hidden: true, sort: 280}, 2154 {id: 'InsertHr', compact: false, hidden: true, sort: 290}, 2155 {id: 'Sub', compact: false, hidden: true, sort: 310}, 2156 {id: 'Sup', compact: false, hidden: true, sort: 320}, 2157 {id: 'TemplateSelector', compact: false, sort: 330}, 2158 {id: 'Fullscreen', compact: true, sort: 340}, 2159 2160 {id: 'More', compact: true, sort: 400}, 2161 {id: 'Settings', wrap: 'right', compact: true, sort: 500} 2162 ]; 2163 } 2164 2165 this.editor.On("GetControlsMap", [res]); 2166 res = res.sort(function(a, b){return a.sort - b.sort}); 2167 this.controlsMap = res; 2168 return res; 2169 }, 2170 2171 GetSeparator: function() 2172 { 2173 return BX.create('span', {props: {className: 'bxhtmled-top-bar-separator'}}); 2174 }, 2175 2176 GetHeight: function() 2177 { 2178 var res = 0; 2179 if (this.shown) 2180 { 2181 if (!this.height) 2182 { 2183 this.height = parseInt(this.editor.dom.toolbarCont.offsetHeight); 2184 } 2185 if (this.height === 0) 2186 { 2187 this.height = parseInt(getComputedStyle(this.editor.dom.toolbarCont).height); 2188 } 2189 2190 res = this.height; 2191 } 2192 return res; 2193 }, 2194 2195 DisableWysiwygButtons: function(bDisable) 2196 { 2197 bDisable = bDisable !== false; 2198 for (var i in this.controls) 2199 { 2200 if (this.controls.hasOwnProperty(i) && typeof this.controls[i].Disable == 'function' && this.controls[i].disabledForTextarea !== false) 2201 this.controls[i].Disable(bDisable); 2202 } 2203 }, 2204 2205 ShowControl: function(controlName) 2206 { 2207 if (this.controls[controlName]) 2208 { 2209 this.controls[controlName].pCont.style.display = ''; 2210 } 2211 }, 2212 2213 HideControl: function(controlName) 2214 { 2215 if (this.controls[controlName]) 2216 { 2217 this.controls[controlName].pCont.style.display = 'none'; 2218 } 2219 }, 2220 2221 EnableWysiwygButtons: function() 2222 { 2223 this.DisableWysiwygButtons(false); 2224 }, 2225 2226 AdaptControls: function(width) 2227 { 2228 this.SetScrollShadows(); 2229 var bCompact = width < this.editor.normalWidth; 2230 if (this.controls.More) 2231 { 2232 if (bCompact || this.showMoreButton) 2233 { 2234 this.controls.More.GetCont().style.display = ''; 2235 } 2236 else 2237 { 2238 this.controls.More.GetCont().style.display = 'none'; 2239 } 2240 2241 if (this.controls.More.pCont && this.controls.More.pCont.style.display !== 'none') 2242 this.controls.More.Close(); 2243 } 2244 2245 if (!bCompact && this.showMoreButton) 2246 { 2247 var moreCont = this.controls.More.GetPopupCont(); 2248 while (this.hiddenWrap.firstChild) 2249 { 2250 moreCont.appendChild(this.hiddenWrap.firstChild); 2251 } 2252 } 2253 2254 if (this.bCompact != bCompact) 2255 { 2256 this.bCompact = bCompact; 2257 this.BuildControls(); 2258 } 2259 }, 2260 2261 Hide: function() 2262 { 2263 this.shown = false;
2264 this.editor.dom.toolbarCont.style.display = 'none'; 2265 this.editor.ResizeSceleton(); 2266 }, 2267 2268 Show: function() 2269 { 2270 this.shown = true; 2271 this.editor.dom.toolbarCont.style.display = ''; 2272 this.editor.ResizeSceleton(); 2273 }, 2274 2275 IsShown: function() 2276 { 2277 return this.shown; 2278 } 2279 }; 2280 2281 function NodeNavi(editor) 2282 { 2283 this.editor = editor; 2284 this.bShown = false; 2285 this.pCont = editor.dom.navCont; 2286 this.controls = {}; 2287 this.height = 28; 2288 this.Init(); 2289 } 2290 2291 NodeNavi.prototype = { 2292 Init: function() 2293 { 2294 BX.addCustomEvent(this.editor, "OnIframeMouseDown", BX.proxy(this.OnIframeMousedown, this)); 2295 BX.addCustomEvent(this.editor, "OnIframeKeyup", BX.proxy(this.OnIframeKeyup, this)); 2296 BX.addCustomEvent(this.editor, "OnTextareaFocus", BX.delegate(this.Disable, this)); 2297 BX.addCustomEvent(this.editor, "OnHtmlContentChangedByControl", BX.delegate(this.OnIframeKeyup, this)); 2298 BX.bind(this.pCont, 'click', BX.delegate(this.ShowMenu, this)); 2299 2300 var _this = this; 2301 2302 this.items = { 2303 // Surrogates 2304 'php' : function(node, bxTag) 2305 { 2306 _this.editor.GetDialog('Source').Show(bxTag); 2307 }, 2308 'anchor' : function(node, bxTag) 2309 { 2310 _this.editor.GetDialog('Anchor').Show(bxTag); 2311 }, 2312 'javascript' : function(node, bxTag) 2313 { 2314 _this.editor.GetDialog('Source').Show(bxTag); 2315 }, 2316 'htmlcomment' : function(node, bxTag) 2317 { 2318 _this.editor.GetDialog('Source').Show(bxTag); 2319 }, 2320 'iframe' : function(node, bxTag) 2321 { 2322 _this.editor.GetDialog('Source').Show(bxTag); 2323 }, 2324 'style' : function(node, bxTag) 2325 { 2326 _this.editor.GetDialog('Source').Show(bxTag); 2327 }, 2328 'video' : function(node, bxTag) 2329 { 2330 _this.editor.GetDialog('Video').Show(bxTag); 2331 }, 2332 'component' : function(node, bxTag) 2333 { 2334 _this.editor.components.ShowPropertiesDialog(bxTag.params, _this.editor.GetBxTag(bxTag.surrogateId)); 2335 }, 2336 'printbreak' : false, 2337 2338 // Nodes 2339 'A' : function(node) 2340 { 2341 _this.editor.GetDialog('Link').Show([node]); 2342 }, 2343 'IMG' : function(node) 2344 { 2345 _this.editor.GetDialog('Image').Show([node]); 2346 }, 2347 'TABLE' : function(node) 2348 { 2349 _this.editor.GetDialog('Table').Show([node]); 2350 }, 2351 'DEFAULT' : function(node) 2352 { 2353 _this.editor.GetDialog('Default').Show([node]); 2354 } 2355 }; 2356 }, 2357 2358 Show: function(bShow) 2359 { 2360 this.bShown = bShow = bShow !== false; 2361 this.pCont.style.display = bShow ? 'block' : 'none'; 2362 }, 2363 2364 GetHeight: function() 2365 { 2366 if (!this.bShown) 2367 return 0; 2368 2369 if (!this.height) 2370 this.height = parseInt(this.pCont.offsetHeight); 2371 2372 return this.height; 2373 }, 2374 2375 OnIframeMousedown: function(e, target, bxTag) 2376 { 2377 this.BuildNavi(target); 2378 }, 2379 2380 OnIframeKeyup: function(e, keyCode, target) 2381 { 2382 this.BuildNavi(target); 2383 }, 2384 2385 BuildNavi: function(node) 2386 { 2387 BX.cleanNode(this.pCont); 2388 if (!node) 2389 { 2390 node = this.editor.GetIframeDoc().body; 2391 } 2392 this.nodeIndex = []; 2393 var itemCont, label, bxTag; 2394 while (node) 2395 { 2396 if (node.nodeType != 3) 2397 { 2398 bxTag = this.editor.GetBxTag(node); 2399 if (bxTag.tag) 2400 { 2401 if (bxTag.tag == "surrogate_dd") 2402 { 2403 node = node.parentNode; 2404 continue; 2405 } 2406 2407 BX.cleanNode(this.pCont); 2408 this.nodeIndex = []; 2409 2410 label = bxTag.name || bxTag.tag; 2411 } 2412 else 2413 { 2414 label = node.nodeName; 2415 } 2416 2417 itemCont = BX.create("SPAN", {props: {className: "bxhtmled-nav-item"}, text: label}); 2418 itemCont.setAttribute('data-bx-node-ind', this.nodeIndex.length.toString()); 2419 2420 this.nodeIndex.push({node: node, bxTag: bxTag.tag}); 2421 2422 if (this.pCont.firstChild) 2423 { 2424 this.pCont.insertBefore(itemCont, this.pCont.firstChild); 2425 if(!this.AdjustSize()) 2426 { 2427 break; 2428 } 2429 } 2430 else 2431 { 2432 this.pCont.appendChild(itemCont); 2433 } 2434 } 2435 if (node.nodeName && node.nodeName.toUpperCase() == 'BODY') 2436 { 2437 break; 2438 } 2439 node = node.parentNode; 2440 } 2441 2442 this.AdjustSize(); 2443 }, 2444 2445 AdjustSize: function() 2446 { 2447 if (this.pCont.lastChild && this.pCont.lastChild.offsetTop > 0) 2448 { 2449 BX.remove(this.pCont.firstChild); 2450 return false;
2451 } 2452 return true; 2453 }, 2454 2455 ShowMenu: function(e) 2456 { 2457 if (!this.nodeIndex) 2458 { 2459 return; 2460 } 2461 2462 var 2463 _this = this, 2464 nodeIndex, 2465 origNode, 2466 target; 2467 2468 if (e.target) 2469 { 2470 target = e.target; 2471 } 2472 else if (e.srcElement) 2473 { 2474 target = e.srcElement; 2475 } 2476 if (target.nodeType == 3) 2477 { 2478 target = target.parentNode; 2479 } 2480 2481 if (target) 2482 { 2483 nodeIndex = target.getAttribute('data-bx-node-ind'); 2484 if (!this.nodeIndex[nodeIndex]) 2485 { 2486 target = BX.findParent(target, function(node) 2487 { 2488 return node == _this.pCont || (node.getAttribute && node.getAttribute('data-bx-node-ind') >= 0); 2489 }, this.pCont); 2490 nodeIndex = target.getAttribute('data-bx-node-ind') 2491 } 2492 2493 if (this.nodeIndex[nodeIndex]) 2494 { 2495 var id = 'bx_node_nav_' + Math.round(Math.random() * 1000000000); 2496 origNode = this.nodeIndex[nodeIndex].node; 2497 2498 var arItems = []; 2499 if (origNode.nodeName && origNode.nodeName.toUpperCase() != 'BODY') 2500 { 2501 if (!this.nodeIndex[nodeIndex].bxTag || !this.editor.phpParser.surrogateTags[this.nodeIndex[nodeIndex].bxTag]) 2502 { 2503 arItems.push({ 2504 text : BX.message('NodeSelect'), 2505 title : BX.message('NodeSelect'), 2506 className : "", 2507 onclick: function() 2508 { 2509 _this.editor.action.Exec('selectNode', origNode); 2510 this.popupWindow.close(); 2511 this.popupWindow.destroy(); 2512 } 2513 }); 2514 } 2515 2516 arItems.push({ 2517 text : BX.message('NodeRemove'), 2518 title : BX.message('NodeRemove'), 2519 className : "", 2520 onclick: function() 2521 { 2522 if (origNode && origNode.parentNode) 2523 { 2524 _this.BuildNavi(origNode.parentNode); 2525 _this.editor.selection.RemoveNode(origNode); 2526 } 2527 this.popupWindow.close(); 2528 this.popupWindow.destroy(); 2529 } 2530 }); 2531 2532 var showProps = !(this.nodeIndex[nodeIndex] && this.nodeIndex[nodeIndex].bxTag && this.items[this.nodeIndex[nodeIndex].bxTag] == false); 2533 if (showProps) 2534 { 2535 arItems.push({ 2536 text : BX.message('NodeProps'), 2537 title : BX.message('NodeProps'), 2538 className : "", 2539 onclick: function() 2540 { 2541 _this.ShowNodeProperties(origNode); 2542 this.popupWindow.close(); 2543 this.popupWindow.destroy(); 2544 } 2545 }); 2546 } 2547 } 2548 else 2549 { 2550 arItems = [ 2551 { 2552 text : BX.message('NodeSelectBody'), 2553 title : BX.message('NodeSelectBody'), 2554 className : "", 2555 onclick: function() 2556 { 2557 _this.editor.iframeView.CheckContentLastChild(); 2558 _this.editor.action.Exec('selectNode', origNode); 2559 _this.editor.Focus(); 2560 this.popupWindow.close(); 2561 this.popupWindow.destroy(); 2562 } 2563 }, 2564 { 2565 text : BX.message('NodeRemoveBodyContent'), 2566 title : BX.message('NodeRemoveBodyContent'), 2567 className : "", 2568 onclick: function() 2569 { 2570 _this.BuildNavi(origNode); 2571 _this.editor.On('OnHtmlContentChangedByControl'); 2572 _this.editor.iframeView.Clear(); 2573 _this.editor.util.Refresh(origNode); 2574 _this.editor.synchro.FullSyncFromIframe(); 2575 _this.editor.Focus(); 2576 2577 this.popupWindow.close(); 2578 this.popupWindow.destroy(); 2579 } 2580 } 2581 ]; 2582 } 2583 2584 2585 BX.PopupMenu.show(id + "_menu", target, arItems, { 2586 overlay: {opacity: 1}, 2587 events: { 2588 onPopupClose: function() 2589 { 2590 //BX.removeClass(this.bindElement, "bxec-add-more-over"); 2591 } 2592 }, 2593 offsetLeft: 1, 2594 zIndex: 4000, 2595 bindOptions: { position: "top" } 2596 } 2597 ); 2598 } 2599 } 2600 }, 2601 2602 ShowNodeProperties: function(node) 2603 { 2604 var bxTag, key; 2605 if (node.nodeName && node.nodeType == 1) 2606 { 2607 bxTag = this.editor.GetBxTag(node); 2608 key = bxTag.tag ? bxTag.tag : node.nodeName; 2609 2610 if (this.items[key] && typeof this.items[key] == 'function') 2611 { 2612 this.items[key](node, bxTag); 2613 } 2614 else 2615 { 2616 this.items['DEFAULT'](node, bxTag); 2617 } 2618 } 2619 }, 2620 2621 // TODO: hide it ?? 2622 Disable: function() 2623 { 2624 this.BuildNavi(false); 2625 }, 2626 2627 Enable: function() 2628 { 2629 } 2630 }; 2631 2632 function Overlay(editor, params) 2633 { 2634 this.editor = editor; 2635 this.id = 'bxeditor_overlay' + this.editor.id; 2636 this.zIndex = params && params.zIndex ? params.zIndex : 1001; 2637 } 2638 2639 Overlay.prototype = 2640 { 2641 Create: function () 2642 { 2643 this.bCreated = true; 2644 this.bShown = false;
2645 var ws = BX.GetWindowScrollSize(); 2646 this.pWnd = document.body.appendChild(BX.create("DIV", {props: {id: this.id, className: "bxhtmled-overlay"}, style: { width: ws.scrollWidth + "px", height: ws.scrollHeight + "px"}})); 2647 this.pWnd.ondrag = BX.False; 2648 this.pWnd.onselectstart = BX.False; 2649 }, 2650 2651 Show: function(arParams) 2652 { 2653 if (!this.bCreated) 2654 this.Create(); 2655 this.bShown = true; 2656 if (this.shownTimeout) 2657 { 2658 this.shownTimeout = clearTimeout(this.shownTimeout); 2659 } 2660 var ws = BX.GetWindowScrollSize(); 2661 this.pWnd.style.display = 'block'; 2662 this.pWnd.style.width = ws.scrollWidth + "px"; 2663 this.pWnd.style.height = ws.scrollHeight + "px"; 2664 2665 if (!arParams) 2666 { 2667 arParams = {}; 2668 } 2669 2670 this.pWnd.style.zIndex = arParams.zIndex || this.zIndex; 2671 2672 BX.bind(window, "resize", BX.proxy(this.Resize, this)); 2673 return this.pWnd; 2674 }, 2675 2676 Hide: function () 2677 { 2678 if (!this.bShown) 2679 { 2680 return; 2681 } 2682 var _this = this; 2683 _this.shownTimeout = setTimeout(function(){_this.bShown = false;}, 300); 2684 this.pWnd.style.display = 'none'; 2685 BX.unbind(window, "resize", BX.proxy(this.Resize, this)); 2686 this.pWnd.onclick = null; 2687 }, 2688 2689 Resize: function () 2690 { 2691 if (this.bCreated) 2692 { 2693 var ws = BX.GetWindowScrollSize(); 2694 this.pWnd.style.width = ws.scrollWidth + "px"; 2695 this.pWnd.style.height = ws.scrollHeight + "px"; 2696 } 2697 } 2698 } 2699 2700 function Button(editor) 2701 { 2702 this.editor = editor; 2703 this.className = 'bxhtmled-top-bar-btn'; 2704 this.activeClassName = 'bxhtmled-top-bar-btn-active'; 2705 this.disabledClassName = 'bxhtmled-top-bar-btn-disabled'; 2706 this.checkableAction = true; 2707 this.disabledForTextarea = true; 2708 } 2709 2710 Button.prototype = { 2711 Create: function () 2712 { 2713 this.pCont = BX.create("SPAN", {props: {className: this.className, title: this.title || ''}, html: '<i></i>'}); 2714 BX.bind(this.pCont, "click", BX.delegate(this.OnClick, this)); 2715 BX.bind(this.pCont, "mousedown", BX.delegate(this.OnMouseDown, this)); 2716 BX.bind(this.pCont, "dblclick", function(e){return BX.PreventDefault(e);}); 2717 2718 if (this.action) 2719 { 2720 this.pCont.setAttribute('data-bx-type', 'action'); 2721 this.pCont.setAttribute('data-bx-action', this.action); 2722 if (this.value) 2723 this.pCont.setAttribute('data-bx-value', this.value); 2724 2725 if (this.checkableAction) 2726 { 2727 this.editor.RegisterCheckableAction(this.action, { 2728 action: this.action, 2729 control: this, 2730 value: this.value 2731 }); 2732 } 2733 } 2734 }, 2735 2736 GetCont: function() 2737 { 2738 return this.pCont; 2739 }, 2740 2741 Check: function (bFlag) 2742 { 2743 if(bFlag == this.checked || this.disabled) 2744 return; 2745 2746 this.checked = bFlag; 2747 if(this.checked) 2748 { 2749 BX.addClass(this.pCont, this.activeClassName); 2750 } 2751 else 2752 { 2753 BX.removeClass(this.pCont, this.activeClassName); 2754 } 2755 }, 2756 2757 Disable: function(bFlag) 2758 { 2759 if(bFlag != this.disabled) 2760 { 2761 this.disabled = !!bFlag; 2762 if(bFlag) 2763 { 2764 if (this.action) 2765 { 2766 this.pCont.setAttribute('data-bx-type', ''); 2767 } 2768 BX.addClass(this.pCont, this.disabledClassName); 2769 } 2770 else 2771 { 2772 if (this.action) 2773 { 2774 this.pCont.setAttribute('data-bx-type', 'action'); 2775 } 2776 BX.removeClass(this.pCont, this.disabledClassName); 2777 } 2778 } 2779 }, 2780 2781 OnClick: BX.DoNothing, 2782 OnMouseUp: function() 2783 { 2784 if(!this.checked) 2785 { 2786 BX.removeClass(this.pCont, this.activeClassName); 2787 } 2788 BX.unbind(document, 'mouseup', BX.proxy(this.OnMouseUp, this)); 2789 BX.removeCustomEvent(this.editor, "OnIframeMouseUp", BX.proxy(this.OnMouseUp, this)); 2790 2791 if (this.editor.toolbar && this.editor.toolbar.controls && this.editor.toolbar.controls.More) 2792 { 2793 this.editor.toolbar.controls.More.Close(); 2794 } 2795 }, 2796 2797 OnMouseDown: function() 2798 { 2799 if (!this.disabled) 2800 { 2801 if (this.disabledForTextarea || !this.editor.synchro.IsFocusedOnTextarea()) 2802 { 2803 this.savedRange = this.editor.selection.SaveBookmark(); 2804 } 2805 BX.addClass(this.pCont, this.activeClassName); 2806 BX.bind(document, 'mouseup', BX.proxy(this.OnMouseUp, this)); 2807 BX.addCustomEvent(this.editor, "OnIframeMouseUp", BX.proxy(this.OnMouseUp, this)); 2808 } 2809 }, 2810 2811 GetValue: function() 2812 { 2813 return !!this.checked; 2814 }, 2815 2816 SetValue: function(value) 2817 { 2818 this.Check(value); 2819 } 2820 }; 2821 2822 // List 2823 function DropDown(editor) 2824 { 2825 this.editor = editor; 2826 this.className = 'bxhtmled-top-bar-btn'; 2827 this.activeClassName = 'bxhtmled-top-bar-btn-active'; 2828 this.activeListClassName = 'bxhtmled-top-bar-btn-active'; 2829 this.arValues = []; 2830 this.checkableAction = true; 2831 this.disabledForTextarea = true; 2832 this.posOffset = {top: 6, left: -4}; 2833 this.zIndex = 3005; 2834 } 2835 2836 DropDown.prototype = { 2837 Create: function () 2838 { 2839 this.pCont = BX.create("SPAN", {props: {className: this.className}, html: '<i></i>'}); 2840 this.pValuesCont = BX.create("DIV", {props: {className: "bxhtmled-popup bxhtmled-dropdown-cont"}, html: '<div class="bxhtmled-popup-corner"></div>'}); 2841 if (this.title) 2842 { 2843 this.pCont.title = this.title; 2844 } 2845 2846 if(this.zIndex) 2847 { 2848 this.pValuesCont.style.zIndex = this.zIndex; 2849 } 2850 2851 this.valueIndex = {}; 2852 this.pValuesContWrap = this.pValuesCont.appendChild(BX.create("DIV")); 2853 var but, value, _this = this; 2854 for (var i = 0; i < this.arValues.length; i++) 2855 { 2856 value = this.arValues[i]; 2857 but = this.pValuesContWrap.appendChild(BX.create("SPAN", {props: {title: value.title, className: value.className}, html: '<i></i>'})); 2858 but.setAttribute('data-bx-dropdown-value', value.id); 2859 this.valueIndex[value.id] = i; 2860 2861 if (value.action) 2862 { 2863 but.setAttribute('data-bx-type', 'action'); 2864 but.setAttribute('data-bx-action', value.action); 2865 if (value.value) 2866 { 2867 but.setAttribute('data-bx-value', value.value); 2868 } 2869 } 2870 2871 BX.bind(but, 'mousedown', function(e) 2872 { 2873 _this.SelectItem(this.getAttribute('data-bx-dropdown-value')); 2874 _this.editor.CheckCommand(this); 2875 _this.Close(); 2876 }); 2877 2878 this.arValues[i].listCont = but; 2879 } 2880 2881 if (this.action && this.checkableAction) 2882 { 2883 this.editor.RegisterCheckableAction(this.action, { 2884 action: this.action, 2885 control: this 2886 }); 2887 } 2888 2889 BX.bind(this.pCont, 'click', BX.proxy(this.OnClick, this)); 2890 BX.bind(this.pCont, "mousedown", BX.delegate(this.OnMouseDown, this)); 2891 }, 2892 2893 GetCont: function() 2894 { 2895 return this.pCont; 2896 }, 2897 2898 GetPopupBindCont: function() 2899 { 2900 return this.pCont; 2901 }, 2902 2903 Disable: function(bFlag) 2904 { 2905 if(bFlag != this.disabled) 2906 { 2907 this.disabled = !!bFlag; 2908 if(bFlag) 2909 { 2910 BX.addClass(this.pCont, 'bxhtmled-top-bar-btn-disabled'); 2911 } 2912 else 2913 { 2914 BX.removeClass(this.pCont, 'bxhtmled-top-bar-btn-disabled'); 2915 } 2916 } 2917 }, 2918 2919 OnKeyDown: function(e) 2920 { 2921 if(e.keyCode == 27) 2922 { 2923 this.Close(); 2924 } 2925 }, 2926 2927 OnClick: function() 2928 { 2929 if(!this.disabled) 2930 { 2931 if (this.bOpened) 2932 { 2933 this.Close(); 2934 } 2935 else 2936 { 2937 this.Open(); 2938 } 2939 } 2940 }, 2941 2942 OnMouseUp: function() 2943 { 2944 this.editor.selection.RestoreBookmark(); 2945 if(!this.checked) 2946 { 2947 BX.removeClass(this.pCont, this.activeClassName); 2948 } 2949 BX.unbind(document, 'mouseup', BX.proxy(this.OnMouseUp, this)); 2950 BX.removeCustomEvent(this.editor, "OnIframeMouseUp", BX.proxy(this.OnMouseUp, this)); 2951 }, 2952 2953 OnMouseDown: function() 2954 { 2955 if (!this.disabled) 2956 { 2957 if (this.disabledForTextarea || !this.editor.synchro.IsFocusedOnTextarea()) 2958 { 2959 this.savedRange = this.editor.selection.SaveBookmark(); 2960 } 2961 2962 BX.addClass(this.pCont, this.activeClassName); 2963 BX.bind(document, 'mouseup', BX.proxy(this.OnMouseUp, this)); 2964 BX.addCustomEvent(this.editor, "OnIframeMouseUp", BX.proxy(this.OnMouseUp, this)); 2965 } 2966 }, 2967 2968 Close: function () 2969 { 2970 var _this = this;
2971 this.popupShownTimeout = setTimeout(function(){_this.editor.popupShown = false;}, 300); 2972 BX.removeClass(this.pCont, this.activeClassName); 2973 this.pValuesCont.style.display = 'none'; 2974 this.editor.overlay.Hide(); 2975 2976 BX.unbind(window, "keydown", BX.proxy(this.OnKeyDown, this)); 2977 BX.unbind(document, 'mousedown', BX.proxy(this.CheckClose, this)); 2978 2979 BX.onCustomEvent(this, "OnPopupClose"); 2980 2981 this.bOpened = false; 2982 }, 2983 2984 CheckClose: function(e) 2985 { 2986 if (!this.bOpened) 2987 { 2988 return BX.unbind(document, 'mousedown', BX.proxy(this.CheckClose, this)); 2989 } 2990 2991 var pEl; 2992 if (e.target) 2993 pEl = e.target; 2994 else if (e.srcElement) 2995 pEl = e.srcElement; 2996 if (pEl.nodeType == 3) 2997 pEl = pEl.parentNode; 2998 2999 if (!BX.findParent(pEl, {className: 'bxhtmled-popup'})) 3000 { 3001 this.Close(); 3002 } 3003 }, 3004 3005 Open: function () 3006 { 3007 this.editor.popupShown = true; 3008 if (this.popupShownTimeout) 3009 { 3010 this.popupShownTimeout = clearTimeout(this.popupShownTimeout); 3011 } 3012 3013 var firstOpen = this.pValuesCont.parentNode === null; 3014 document.body.appendChild(this.pValuesCont); 3015 3016 if (firstOpen) 3017 { 3018 BX.ZIndexManager.register(this.pValuesCont); 3019 } 3020 3021 var component = BX.ZIndexManager.bringToFront(this.pValuesCont); 3022 var zIndex = component.getZIndex(); 3023 3024 this.pValuesCont.style.display = 'block'; 3025 BX.addClass(this.pCont, this.activeClassName); 3026 var 3027 pOverlay = this.editor.overlay.Show({ zIndex: zIndex - 1 }), 3028 bindCont = this.GetPopupBindCont(), 3029 pos = BX.pos(bindCont), 3030 left = Math.round(pos.left - this.pValuesCont.offsetWidth / 2 + bindCont.offsetWidth / 2 + this.posOffset.left), 3031 top = Math.round(pos.bottom + this.posOffset.top), 3032 _this = this; 3033 3034 BX.bind(window, "keydown", BX.proxy(this.OnKeyDown, this)); 3035 pOverlay.onclick = function(){_this.Close()}; 3036 3037 this.pValuesCont.style.top = top + 'px'; 3038 this.pValuesCont.style.left = left + 'px'; 3039 this.bOpened = true; 3040 3041 setTimeout(function() 3042 { 3043 BX.bind(document, 'mousedown', BX.proxy(_this.CheckClose, _this)); 3044 },100); 3045 }, 3046 3047 SelectItem: function(id, val) 3048 { 3049 if (!val) 3050 val = this.arValues[this.valueIndex[id]]; 3051 3052 if (this.lastActiveItem) 3053 BX.removeClass(this.lastActiveItem, this.activeListClassName); 3054 3055 if (val) 3056 { 3057 // Select value in list as active 3058 if (val.listCont) 3059 { 3060 this.lastActiveItem = val.listCont; 3061 BX.addClass(val.listCont, this.activeListClassName); 3062 } 3063 3064 this.pCont.className = val.className; 3065 this.pCont.title = BX.util.htmlspecialchars(val.title || val.name || ''); 3066 } 3067 else 3068 { 3069 this.pCont.className = this.className; 3070 this.pCont.title = this.title; 3071 } 3072 3073 if (this.disabled) 3074 { 3075 this.disabled = false; 3076 this.Disable(true); 3077 } 3078 3079 return val; 3080 }, 3081 3082 SetValue: function() 3083 { 3084 }, 3085 3086 GetValue: function() 3087 { 3088 }, 3089 3090 OnPopupClose: function() 3091 { 3092 } 3093 }; 3094 3095 function DropDownList(editor) 3096 { 3097 // Call parrent constructor 3098 DropDownList.superclass.constructor.apply(this, arguments); 3099 this.className = 'bxhtmled-top-bar-select'; 3100 this.itemClassName = 'bxhtmled-dd-list-item'; 3101 this.activeListClassName = 'bxhtmled-dd-list-item-active'; 3102 this.disabledForTextarea = true; 3103 } 3104 BX.extend(DropDownList, DropDown); 3105 3106 DropDownList.prototype.Create = function () 3107 { 3108 this.pCont = BX.create("SPAN", {props: {className: this.className, title: this.title}, attrs: {unselectable: 'on'}, text: ''}); 3109 if (this.width) 3110 this.pCont.style.width = this.width + 'px'; 3111 3112 this.pValuesCont = BX.create("DIV", {props: {className: "bxhtmled-popup bxhtmled-dropdown-list-cont"}, html: '<div class="bxhtmled-popup-corner"></div>'}); 3113 this.pValuesContWrap = this.pValuesCont.appendChild(BX.create("DIV", {props: {className: "bxhtmled-dd-list-wrap"}})); 3114 this.valueIndex = {}; 3115 3116 if(this.zIndex) 3117 { 3118 this.pValuesCont.style.zIndex = this.zIndex; 3119 } 3120 3121 var but, value, _this = this, itemClass, i, html; 3122 for (i = 0; i < this.arValues.length; i++) 3123 { 3124 value = this.arValues[i]; 3125 itemClass = this.itemClassName; 3126 if (value.className) 3127 itemClass += ' ' + value.className; 3128 3129 html = value.tagName ? ('<' + value.tagName + '>' + value.name + '</' + value.tagName + '>') : value.name; 3130 but = this.pValuesContWrap.appendChild(BX.create("SPAN", {props: {title: value.title || value.name, className: itemClass}, html: html, style: value.style})); 3131 3132 but.setAttribute('data-bx-dropdown-value', value.id); 3133 this.valueIndex[value.id] = i; 3134 3135 if (value.defaultValue) 3136 this.SelectItem(null, value); 3137 3138 if (value.action) 3139 { 3140 but.setAttribute('data-bx-type', 'action'); 3141 but.setAttribute('data-bx-action', value.action); 3142 if (value.value) 3143 but.setAttribute('data-bx-value', value.value); 3144 } 3145 3146 BX.bind(but, 'mousedown', function(e) 3147 { 3148 if (!e) 3149 e = window.event; 3150 _this.SelectItem(this.getAttribute('data-bx-dropdown-value')); 3151 _this.editor.CheckCommand(this); 3152 }); 3153 3154 this.arValues[i].listCont = but; 3155 } 3156 3157 if (this.action && this.checkableAction) 3158 { 3159 this.editor.RegisterCheckableAction(this.action, { 3160 action: this.action, 3161 control: this 3162 }); 3163 } 3164 3165 BX.bind(this.pCont, 'click', BX.proxy(this.OnClick, this)); 3166 }; 3167 3168 DropDownList.prototype.SelectItem = function (valDropdown, val, bClose) 3169 { 3170 bClose = bClose !== false; 3171 if (!val) 3172 { 3173 val = this.arValues[this.valueIndex[valDropdown]]; 3174 } 3175 3176 if (this.lastActiveItem) 3177 { 3178 BX.removeClass(this.lastActiveItem, this.activeListClassName); 3179 } 3180 3181 if (val) 3182 { 3183 this.pCont.innerHTML = BX.util.htmlspecialchars((val.topName || val.name || val.id)); 3184 this.pCont.title = this.title + ': ' + BX.util.htmlspecialchars(val.title || val.name); 3185 3186 3187 // Select value in list as active 3188 if (val.listCont) 3189 { 3190 this.lastActiveItem = val.listCont; 3191 BX.addClass(val.listCont, this.activeListClassName); 3192 } 3193 } 3194 3195 if (this.bOpened && bClose) 3196 { 3197 this.Close(); 3198 } 3199 }; 3200 3201 DropDownList.prototype.SetValue = function(active, state) 3202 { 3203 }; 3204 3205 DropDownList.prototype.SetWidth = function(width) 3206 { 3207 width = parseInt(width, 10); 3208 if (width) 3209 { 3210 this.width = width; 3211 this.pCont.style.width = width + 'px'; 3212 } 3213 }; 3214 3215 DropDownList.prototype.Disable = function(bFlag) 3216 { 3217 if(bFlag != this.disabled) 3218 { 3219 this.disabled = !!bFlag; 3220 if(bFlag) 3221 { 3222 BX.addClass(this.pCont, 'bxhtmled-top-bar-select-disabled'); 3223 } 3224 else 3225 {
3226 BX.removeClass(this.pCont, 'bxhtmled-top-bar-select-disabled'); 3227 } 3228 } 3229 }; 3230 3231 // Combobox with multiple choice of values 3232 function ComboBox(editor, params) 3233 { 3234 this.values = []; 3235 this.pInput = params.input; 3236 this.editor = editor; 3237 this.value = params.value || ''; 3238 this.defaultValue = params.defaultValue || ''; 3239 this.posOffset = {top: 8, left: -4}; 3240 this.zIndex = 3010; 3241 this.SPLIT_SYMBOL = ','; 3242 this.itemClassName = 'bxhtmled-dd-list-item'; 3243 this.itemClassNameActive = 'bxhtmled-dd-list-item-active'; 3244 } 3245 3246 ComboBox.prototype = { 3247 Init: function() 3248 { 3249 BX.bind(this.pInput, 'focus', BX.proxy(this.Focus, this)); 3250 BX.bind(this.pInput, 'click', BX.proxy(this.Focus, this)); 3251 BX.bind(this.pInput, 'blur', BX.proxy(this.Blur, this)); 3252 BX.bind(this.pInput, 'keyup', BX.proxy(this.KeyUp, this)); 3253 3254 this.visibleItemsLength = this.values.length; 3255 this.currentItem = false; 3256 }, 3257 3258 UpdateValues: function(values) 3259 { 3260 this.bCreated = false; 3261 this.values = values; 3262 this.visibleItemsLength = this.values.length; 3263 this.currentItem = false; 3264 if (this.bOpened) 3265 { 3266 this.ClosePopup(); 3267 } 3268 }, 3269 3270 Create: function() 3271 { 3272 this.pValuesCont = BX.create("DIV", {props: {className: "bxhtmled-popup bxhtmled-combo-cont"}, html: '<div class="bxhtmled-popup-corner"></div>'}); 3273 this.pValuesCont.style.zIndex = this.zIndex; 3274 3275 if (this.pValuesContWrap) 3276 { 3277 BX.cleanNode(this.pValuesContWrap); 3278 this.pValuesCont.appendChild(this.pValuesContWrap); 3279 } 3280 else 3281 { 3282 this.pValuesContWrap = this.pValuesCont.appendChild(BX.create("DIV", {props: {className: "bxhtmled-dd-list-wrap"}})); 3283 3284 BX.bind(this.pValuesContWrap, 'mousedown', function(e) 3285 { 3286 var target = e.target || e.srcElement; 3287 if (!target.getAttribute('data-bx-dropdown-value')) 3288 { 3289 target = BX.findParent(target, function(n) 3290 { 3291 return n.getAttribute && n.getAttribute('data-bx-dropdown-value'); 3292 }, _this.pValuesContWrap); 3293 } 3294 3295 if (target) 3296 { 3297 _this.currentItem = parseInt(target.getAttribute('data-bx-dropdown-value'), 10); 3298 _this.SetValueFromList(); 3299 } 3300 3301 _this.ClosePopup(); 3302 }); 3303 } 3304 this.valueIndex = {}; 3305 3306 var but, value, _this = this, itemClass, i, html; 3307 for (i = 0; i < this.values.length; i++) 3308 { 3309 value = this.values[i]; 3310 itemClass = this.itemClassName || ''; 3311 this.values[i].TITLE = this.values[i].TITLE || this.values[i].NAME; 3312 3313 if (this.values[i].VALUE && this.values[i].VALUE !== this.values[i].TITLE) 3314 { 3315 this.values[i].TITLE += ' (' + this.values[i].VALUE + ')'; 3316 } 3317 else 3318 { 3319 this.values[i].VALUE = this.values[i].NAME; 3320 } 3321 3322 but = this.pValuesContWrap.appendChild(BX.create("SPAN", {props: {className: itemClass}, html: value.TITLE})); 3323 but.setAttribute('data-bx-dropdown-value', i); 3324 this.values[i].cont = but; 3325 } 3326 3327 this.bCreated = true; 3328 }, 3329 3330 KeyUp: function(e) 3331 { 3332 var keyCode = e.keyCode; 3333 if (keyCode == this.editor.KEY_CODES['down']) 3334 { 3335 this.SelectItem(1); 3336 } 3337 else if (keyCode == this.editor.KEY_CODES['up']) 3338 { 3339 this.SelectItem(-1); 3340 } 3341 else if (keyCode == this.editor.KEY_CODES['escape']) 3342 { 3343 if (this.bOpened) 3344 { 3345 this.ClosePopup(); 3346 return BX.PreventDefault(e); 3347 } 3348 } 3349 else if (keyCode == this.editor.KEY_CODES['enter']) 3350 { 3351 if (this.bOpened) 3352 { 3353 this.SetValueFromList(); 3354 this.ClosePopup(); 3355 return BX.PreventDefault(e); 3356 } 3357 } 3358 else 3359 { 3360 this.FilterValue(); 3361 } 3362 }, 3363 3364 FilterValue: function() 3365 { 3366 // Range 3367 var 3368 i, val, 3369 splitedVals = this.GetSplitedValues(), 3370 caretPos = this.GetCaretPos(this.pInput); 3371 3372 for (i = 0; i < splitedVals.length; i++) 3373 { 3374 val = splitedVals[i]; 3375 if (caretPos >= val.start && caretPos <= val.end) 3376 { 3377 break; 3378 } 3379 } 3380 3381 // Filter values && highlight values 3382 this.FilterAndHighlight(val.value); 3383 }, 3384 3385 GetSplitedValues: function() 3386 { 3387 var 3388 arVals, i, gStart, gEnd, val, 3389 res = [], 3390 str = this.pInput.value; 3391 3392 if (str.indexOf(this.SPLIT_SYMBOL) === -1 || this.bMultiple === false) 3393 { 3394 res.push( 3395 { 3396 start: 0, 3397 end: str.length, 3398 value: BX.util.trim(str) 3399 } 3400 ); 3401 } 3402 else 3403 {
3404 arVals = str.split(this.SPLIT_SYMBOL); 3405 gStart = 0; 3406 gEnd = 0; 3407 for (i = 0; i < arVals.length; i++) 3408 { 3409 val = arVals[i]; 3410 gEnd += val.length + i; 3411 res.push( 3412 { 3413 start: gStart, 3414 end: gEnd, 3415 value: BX.util.trim(val) 3416 } 3417 ); 3418 gStart = gEnd; 3419 } 3420 } 3421 3422 return res; 3423 }, 3424 3425 FilterAndHighlight: function(needle) 3426 { 3427 needle = BX.util.trim(needle); 3428 var val, i, showPopup = false, pos; 3429 3430 this.visibleItemsLength = 0; 3431 for (i = 0; i < this.values.length; i++) 3432 { 3433 val = this.values[i]; 3434 if (needle === '') 3435 { 3436 showPopup = true; 3437 val.cont.style.display = ''; 3438 this.visibleItemsLength++; 3439 } 3440 else 3441 { 3442 pos = val.TITLE.toLowerCase().indexOf(needle.toLowerCase()); 3443 if (pos !== -1 || needle == '') 3444 { 3445 val.cont.innerHTML = BX.util.htmlspecialchars(val.TITLE.substr(0, pos)) + '<b>' + BX.util.htmlspecialchars(needle) + '</b>' + BX.util.htmlspecialchars(val.TITLE.substr(pos + needle.length)); 3446 showPopup = true; 3447 val.cont.style.display = ''; 3448 val.cont.setAttribute('data-bx-dropdown-value', this.visibleItemsLength); 3449 this.visibleItemsLength++; 3450 } 3451 else 3452 { 3453 val.cont.innerHTML = BX.util.htmlspecialchars(val.TITLE); 3454 val.cont.style.display = 'none'; 3455 } 3456 } 3457 } 3458 3459 this.currentItem = false; 3460 3461 if (showPopup && !this.bOpened) 3462 { 3463 this.ShowPopup(); 3464 } 3465 else if (!showPopup && this.bOpened) 3466 { 3467 this.ClosePopup(); 3468 } 3469 }, 3470 3471 GetCaretPos: function(input) 3472 { 3473 var caretPos = 0; 3474 3475 // IE Support 3476 if (document.selection) 3477 { 3478 BX.focus(input); 3479 var oSel = document.selection.createRange(); 3480 oSel.moveStart ('character', - input.value.length); 3481 // The caret position is selection length 3482 caretPos = oSel.text.length; 3483 } 3484 else if (input.selectionStart || input.selectionStart == '0') 3485 { 3486 caretPos = input.selectionStart; 3487 } 3488 return (caretPos); 3489 }, 3490 3491 SetValue: function(value) 3492 { 3493 this.pInput.value = value; 3494 }, 3495 3496 SetValueFromList: function() 3497 { 3498 var ind = 0, val, i; 3499 for (i = 0; i < this.values.length; i++) 3500 { 3501 val = this.values[i]; 3502 if (val.cont.style.display != 'none') 3503 { 3504 if (ind == this.currentItem) 3505 { 3506 BX.addClass(val.cont, this.itemClassNameActive); 3507 break; 3508 } 3509 ind++; 3510 } 3511 } 3512 3513 var 3514 splVal, 3515 splitedVals = this.GetSplitedValues(), 3516 caretPos = this.GetCaretPos(this.pInput); 3517 3518 for (i = 0; i < splitedVals.length; i++) 3519 { 3520 splVal = splitedVals[i]; 3521 if (caretPos >= splVal.start && caretPos <= splVal.end) 3522 { 3523 break; 3524 } 3525 } 3526 3527 var 3528 glue = this.SPLIT_SYMBOL == ' ' ? ' ' : this.SPLIT_SYMBOL + ' ', 3529 curValue = this.pInput.value, 3530 before = curValue.substr(0, splVal.start), 3531 after = curValue.substr(splVal.end); 3532 3533 before = before.replace(/^[\s\r\n\,]+/g, '').replace(/[\s\r\n\,]+$/g, ''); 3534 after = after.replace(/^[\s\r\n\,]+/g, '').replace(/[\s\r\n\,]+$/g, ''); 3535 3536 this.pInput.value = before + 3537 (before == '' ? '' : glue) + 3538 val.VALUE + 3539 (after == '' ? '' : glue) + 3540 after; 3541 3542 this.FilterAndHighlight(''); 3543 }, 3544 3545 SelectItem: function(delta) 3546 { 3547 var ind, val, i, len; 3548 if (this.currentItem === false) 3549 { 3550 this.currentItem = 0; 3551 } 3552 else if(delta !== undefined) 3553 { 3554 this.currentItem += delta; 3555 3556 if (this.currentItem > this.visibleItemsLength - 1) 3557 { 3558 this.currentItem = 0; 3559 } 3560 else if(this.currentItem < 0) 3561 { 3562 this.currentItem = this.visibleItemsLength - 1; 3563 } 3564 } 3565 3566 if (document.querySelectorAll) 3567 { 3568 var selected = this.pValuesContWrap.querySelectorAll("." + this.itemClassNameActive); 3569 if (selected) 3570 { 3571 for (i = 0; i < selected.length; i++) 3572 { 3573 BX.removeClass(selected[i], this.itemClassNameActive); 3574 } 3575 } 3576 } 3577 3578 ind = 0; 3579 len = this.values.length; 3580 for (i = 0; i < this.values.length; i++) 3581 { 3582 val = this.values[i]; 3583 if (val.cont.style.display != 'none') 3584 { 3585 if (ind == this.currentItem) 3586 { 3587 BX.addClass(val.cont, this.itemClassNameActive); 3588 break; 3589 } 3590 ind++; 3591 } 3592 } 3593 }, 3594 3595 Focus: function(e) 3596 { 3597 if (this.values.length > 0 && !this.bFocused) 3598 { 3599 BX.focus(this.pInput); 3600 this.bFocused = true; 3601 if (this.value == this.defaultValue) 3602 { 3603 this.value = ''; 3604 } 3605 3606 this.ShowPopup(); 3607 } 3608 }, 3609 3610 Blur: function() 3611 { 3612 if (this.values.length > 0 && this.bFocused) 3613 { 3614 this.bFocused = false;
3615 this.ClosePopup(); 3616 } 3617 }, 3618 3619 ShowPopup: function() 3620 { 3621 if (!this.bCreated) 3622 { 3623 this.Create(); 3624 } 3625 3626 this.editor.popupShown = true; 3627 if (this.popupShownTimeout) 3628 { 3629 this.popupShownTimeout = clearTimeout(this.popupShownTimeout); 3630 } 3631 3632 var firstShow = this.pValuesCont.parentNode === null; 3633 document.body.appendChild(this.pValuesCont); 3634 3635 if (firstShow) 3636 { 3637 BX.ZIndexManager.register(this.pValuesCont); 3638 } 3639 3640 BX.ZIndexManager.bringToFront(this.pValuesCont); 3641 3642 this.pValuesCont.style.display = 'block'; 3643 3644 var 3645 i, 3646 pos = BX.pos(this.pInput), 3647 left = pos.left + this.posOffset.left, 3648 top = pos.bottom + this.posOffset.top; 3649 3650 this.pValuesCont.style.top = top + 'px'; 3651 this.pValuesCont.style.left = left + 'px'; 3652 this.bOpened = true; 3653 3654 if (document.querySelectorAll) 3655 { 3656 var selected = this.pValuesContWrap.querySelectorAll("." + this.itemClassNameActive); 3657 if (selected) 3658 { 3659 for (i = 0; i < selected.length; i++) 3660 { 3661 BX.removeClass(selected[i], this.itemClassNameActive); 3662 } 3663 } 3664 } 3665 3666 BX.onCustomEvent(this, "OnComboPopupOpen"); 3667 }, 3668 3669 ClosePopup: function() 3670 { 3671 var _this = this; 3672 this.popupShownTimeout = setTimeout(function(){_this.editor.popupShown = false;}, 300); 3673 this.pValuesCont.style.display = 'none'; 3674 this.editor.overlay.Hide(); 3675 3676 this.bOpened = false; 3677 BX.onCustomEvent(this, "OnComboPopupClose"); 3678 }, 3679 3680 OnChange: function() 3681 { 3682 }, 3683 3684 CheckClose: function(e) 3685 { 3686 if (!this.bOpened) 3687 { 3688 return BX.unbind(document, 'mousedown', BX.proxy(this.CheckClose, this)); 3689 } 3690 3691 var pEl; 3692 if (e.target) 3693 pEl = e.target; 3694 else if (e.srcElement) 3695 pEl = e.srcElement; 3696 if (pEl.nodeType == 3) 3697 pEl = pEl.parentNode; 3698 3699 if (!BX.findParent(pEl, {className: 'bxhtmled-popup'})) 3700 this.Close(); 3701 } 3702 }; 3703 3704 function ClassSelector(editor, params) 3705 { 3706 // Call parrent constructor 3707 ClassSelector.superclass.constructor.apply(this, arguments); 3708 this.filterTag = params.filterTag || ''; 3709 this.lastTemplateId = this.editor.GetTemplateId(); 3710 this.values = this.GetClasses(); 3711 this.SPLIT_SYMBOL = ' '; 3712 this.Init(); 3713 } 3714 BX.extend(ClassSelector, ComboBox); 3715 3716 ClassSelector.prototype.OnChange = function() 3717 { 3718 if (this.lastTemplateId != this.editor.GetTemplateId()) 3719 { 3720 this.lastTemplateId = this.editor.GetTemplateId(); 3721 this.values = this.GetClasses(); 3722 this.bCreated = false; 3723 } 3724 }; 3725 3726 ClassSelector.prototype.GetClasses = function() 3727 { 3728 var 3729 title,
3730 classes = this.editor.GetCurrentCssClasses(this.filterTag); 3731 3732 this.values = []; 3733 if (classes && classes.length > 0) 3734 { 3735 for (var i = 0; i < classes.length; i++) 3736 { 3737 title = null; 3738 if (classes[i].classTitle && typeof classes[i].classTitle == 'object') 3739 { 3740 if (classes[i].classTitle.title) 3741 { 3742 title = classes[i].classTitle.title; 3743 } 3744 else 3745 { 3746 continue; 3747 } 3748 } 3749 else if (classes[i].classTitle) 3750 { 3751 title = classes[i].classTitle; 3752 } 3753 3754 this.values.push( 3755 { 3756 VALUE: classes[i].className, 3757 TITLE: title, 3758 NAME: classes[i].className 3759 } 3760 ); 3761 } 3762 } 3763 return this.values; 3764 }; 3765 3766 function PasteControl(editor) 3767 { 3768 this.editor = editor; 3769 if (this.editor.config.pasteSetColors !== this.editor.config.pasteSetBorders || 3770 this.editor.config.pasteSetColors !== this.editor.config.pasteSetDecor) 3771 { 3772 this.mode = 'default'; 3773 } 3774 else 3775 { 3776 this.mode = this.editor.config.pasteSetColors && 3777 this.editor.config.pasteSetBorders && 3778 this.editor.config.pasteSetDecor ? 'text' : 'rich'; 3779 } 3780 3781 var _this = this; 3782 3783 this.items = []; 3784 if (this.mode == 'default') 3785 { 3786 this.items = [ 3787 { 3788 TEXT: BX.message('BXEdPasteDefault'), 3789 ACTION: function() 3790 { 3791 _this.Hide('default'); 3792 }, 3793 CHECKED: this.mode == 'default', 3794 _MODE: 'default' 3795 } 3796 ]; 3797 } 3798 3799 this.items.push({ 3800 TEXT: BX.message('BXEdPasteText'), 3801 ACTION: function() 3802 { 3803 _this.Hide('text'); 3804 }, 3805 CHECKED: this.mode == 'text', 3806 _MODE: 'text' 3807 }); 3808 this.items.push({ 3809 TEXT: BX.message('BXEdPasteFormattedText'), 3810 ACTION: function() 3811 { 3812 _this.Hide('rich'); 3813 }, 3814 CHECKED: this.mode == 'rich', 3815 _MODE: 'rich' 3816 }); 3817 3818 // mantis: 71968 3819 BX.addCustomEvent('OnComponentParamsDisplay', BX.proxy(this.Hide, this)); 3820 } 3821 3822 PasteControl.prototype = { 3823 CheckAndShow: function () 3824 { 3825 var 3826 isOpened = this.isOpened, 3827 _this = this; 3828 3829 this.savedRange = this.editor.selection.GetBookmark(); 3830 this.isOpened = true; 3831 this.lastPreviewMode = false; 3832 if (this.checkTimeout) 3833 this.checkTimeout = clearTimeout(this.checkTimeout); 3834 3835 this.checkTimeout = setTimeout(function() 3836 { 3837 var skipPasteHandler = _this.editor.skipPasteHandler; 3838 _this.editor.skipPasteHandler = true; 3839 _this.PreviewContent({mode: 'rich', doTimeout: false, skipColors: true}); 3840 var richContent = _this.editor.iframeView.GetValue(); 3841 // Clear images before comparision 3842 richContent = richContent.replace(/<img((?:\s|\S)*?)>/ig, ''); 3843 richContent = richContent.replace(/id="(\s|\S)*?"/ig, ''); 3844 richContent = richContent.replace(/\s+/ig, ' '); 3845 3846 _this.PreviewContent({mode: 'text', doTimeout: false}); 3847 var textContent = _this.editor.iframeView.GetValue(); 3848 // Clear images before comparision 3849 textContent = textContent.replace(/<img((?:\s|\S)*?)>/ig, ''); 3850 textContent = textContent.replace(/id="(\s|\S)*?"/ig, ''); 3851 textContent = textContent.replace(/\s+/ig, ' '); 3852 3853 if (richContent != textContent) 3854 { 3855 _this.isOpened = isOpened; 3856 _this.editor.SetCursorNode(_this.savedRange); 3857 _this.Show(); 3858 } 3859 3860 _this.editor.skipPasteHandler = skipPasteHandler; 3861 }, 200); 3862 }, 3863 3864 Show: function () 3865 { 3866 var _this = this; 3867 this.lastPreviewMode = false; 3868 this.Hide(); 3869 3870 this.pOverlay = this.editor.overlay.Show({zIndex: 1040}); 3871 BX.bind(this.pOverlay, 'click', BX.proxy(this.Hide, this)); 3872 BX.bind(this.pOverlay, 'mousemove', BX.proxy(function(){this.PreviewContent({mode: 'default'});}, this)); 3873 3874 if (!this.dummyTarget) 3875 { 3876 this.dummyTarget = this.editor.dom.iframeCont.appendChild(BX.create('DIV', {props: {className: 'bxhtmled-dummy-target'}})); 3877 } 3878 3879 var 3880 cursorNode = this.editor.GetIframeElement('bx-cursor-node'), 3881 top = 0, left = 0, node; 3882 3883 if (cursorNode) 3884 { 3885 if (cursorNode.parentNode) 3886 { 3887 top += cursorNode.offsetHeight; 3888 node = cursorNode; 3889 do 3890 { 3891 top += node.offsetTop || 0; 3892 left += node.offsetLeft || 0; 3893 node = node.offsetParent; 3894 } while (node && node.nodeName != 'BODY'); 3895 } 3896 } 3897 3898 var scrollPos = BX.GetWindowScrollPos(this.editor.GetIframeDoc()); 3899 3900 top -= scrollPos.scrollTop; 3901 left -= scrollPos.scrollLeft; 3902 3903 var 3904 editorSize = this.editor.GetSceletonSize(), 3905 maxTop = editorSize.height - this.items.length * 40, 3906 maxLeft = editorSize.width - 100; 3907 3908 if (top < 0) 3909 top = 0; 3910 else if (top > maxTop) 3911 top = maxTop; 3912 3913 if (left < 0) 3914 left = 0; 3915 else if (left > maxLeft) 3916 left = maxLeft; 3917 3918 this.dummyTarget.style.left = left + 'px'; 3919 this.dummyTarget.style.top = top + 'px'; 3920 this.dummyTarget.style.zIndex = '2002'; 3921 3922 this.OPENER = new BX.COpener({ 3923 DIV: this.dummyTarget, MENU: this.items, TYPE: 'click', ACTIVE_CLASS: 'adm-btn-active', CLOSE_ON_CLICK: true 3924 }); 3925 this.OPENER.Open(); 3926 3927 var popupDiv = this.OPENER.GetMenu().DIV; 3928 BX.addClass(popupDiv, 'bxhtmled-paste-control bx-core-popup-menu-editor'); 3929
3930 BX.addCustomEvent(this.OPENER.GetMenu(), 'onMenuClose', BX.proxy(this.Hide, this)); 3931 3932 var i, items = BX.findChild(popupDiv, {className: 'bx-core-popup-menu-item'}, 1, 1); 3933 for (i = 0; i < items.length; i++) 3934 { 3935 items[i].setAttribute('data-bx-mode', this.items[i]._MODE); 3936 } 3937 3938 BX.bind(popupDiv, 'mousemove', function(e) 3939 { 3940 var 3941 target = e.target || e.srcElement, 3942 mode = (target && target.getAttribute) ? target.getAttribute('data-bx-mode') : null; 3943 3944 if (!mode) 3945 { 3946 target = BX.findParent(target, function(n) 3947 { 3948 return n == popupDiv || (n.getAttribute && n.getAttribute('data-bx-mode')); 3949 }, popupDiv); 3950 mode = (target && target.getAttribute) ? target.getAttribute('data-bx-mode') : null; 3951 } 3952 3953 _this.PreviewContent({mode: mode}); 3954 }); 3955 3956 this.isOpened = true; 3957 BX.addCustomEvent(this.editor, 'OnIframeKeydown', BX.CMenu.broadcastCloseEvent); 3958 BX.bind(document.body, "keydown", BX.CMenu.broadcastCloseEvent); 3959 }, 3960 3961 Hide: function (mode) 3962 { 3963 if (this.isOpened) 3964 { 3965 this.editor.overlay.Hide(); 3966 if (this.pOverlay) 3967 { 3968 BX.unbind(this.pOverlay, 'click', BX.proxy(this.Hide, this)); 3969 BX.unbind(this.pOverlay, 'mousemove', BX.proxy(this.PreviewContent, this)); 3970 } 3971 3972 BX.removeCustomEvent(this.editor, 'OnIframeKeydown', BX.CMenu.broadcastCloseEvent); 3973 BX.unbind(document.body, "keydown", BX.CMenu.broadcastCloseEvent); 3974 3975 if (!mode || typeof mode !== 'string' || (mode !== 'text' && mode !== 'rich')) 3976 mode = 'default'; 3977 this.PreviewContent({mode: mode}); 3978 this.editor.Focus(); 3979 3980 this.editor.On("OnIframePaste"); 3981 this.editor.On("OnIframeNewWord"); 3982 3983 this.isOpened = false; 3984 } 3985 }, 3986 3987 PreviewContent: function(params) 3988 { 3989 if (this.isOpened) 3990 { 3991 if (this.lastPreviewMode != params.mode || !this.lastPreviewMode) 3992 { 3993 if (params.doTimeout !== false) 3994 { 3995 params.doTimeout = false; 3996 var _this = this; 3997 if (this.previewTimeout) 3998 clearTimeout(this.previewTimeout); 3999 this.previewTimeout = setTimeout(function(){_this.PreviewContent(params);}, 200); 4000 return; 4001 } 4002 4003 if (params.mode == 'rich') 4004 { 4005 this.editor.config.pasteSetColors = !!params.skipColors; 4006 this.editor.config.pasteSetBorders = false; 4007 this.editor.config.pasteSetDecor = false; 4008 } 4009 else if (params.mode == 'text') 4010 { 4011 this.editor.config.pasteSetColors = true; 4012 this.editor.config.pasteSetBorders = true; 4013 this.editor.config.pasteSetDecor = true; 4014 } 4015 else // rich 4016 { 4017 this.editor.config.pasteSetColors = this.defPasteSetColors; 4018 this.editor.config.pasteSetBorders = this.defPasteSetBorders; 4019 this.editor.config.pasteSetDecor = this.defPasteSetDecor; 4020 } 4021 4022 this.editor.pasteHandleMode = true; 4023 this.editor.bbParseContentMode = true; 4024 this.editor.synchro.lastIframeValue = false; 4025 4026 this.editor.iframeView.SetValue(this.pastedContent, false); 4027 this.editor.synchro.FromIframeToTextarea(true, true); 4028 4029 this.editor.pasteHandleMode = false; 4030 this.editor.bbParseContentMode = false; 4031 4032 this.editor.synchro.lastTextareaValue = false; 4033 this.editor.synchro.FromTextareaToIframe(true); 4034 4035 this.editor.RestoreCursor(); 4036 4037 this.editor.skipPasteHandler = false; 4038 4039 // Restore settings 4040 if (params.mode != 'default') 4041 { 4042 this.editor.config.pasteSetColors = this.defPasteSetColors; 4043 this.editor.config.pasteSetBorders = this.defPasteSetBorders; 4044 this.editor.config.pasteSetDecor = this.defPasteSetDecor; 4045 } 4046 } 4047 this.lastPreviewMode = params.mode; 4048 } 4049 }, 4050 4051 SaveIframeContent: function(content) 4052 { 4053 // Save default values 4054 this.defPasteSetColors = this.editor.config.pasteSetColors; 4055 this.defPasteSetBorders = this.editor.config.pasteSetBorders; 4056 this.defPasteSetDecor = this.editor.config.pasteSetDecor; 4057 4058 this.pastedContent = content; 4059 } 4060 }; 4061 4062 function __run() 4063 { 4064 window.BXHtmlEditor.TaskbarManager = TaskbarManager; 4065 window.BXHtmlEditor.Taskbar = Taskbar; 4066 window.BXHtmlEditor.ComponentsControl = ComponentsControl; 4067 window.BXHtmlEditor.ContextMenu = ContextMenu; 4068 window.BXHtmlEditor.Dialog = Dialog; 4069 window.BXHtmlEditor.Toolbar = Toolbar;
4070 window.BXHtmlEditor.NodeNavigator = NodeNavi; 4071 window.BXHtmlEditor.Button = Button; 4072 window.BXHtmlEditor.DropDown = DropDown; 4073 window.BXHtmlEditor.DropDownList = DropDownList; 4074 window.BXHtmlEditor.ComboBox = ComboBox; 4075 window.BXHtmlEditor.ClassSelector = ClassSelector; 4076 window.BXHtmlEditor.Overlay = Overlay; 4077 window.BXHtmlEditor.PasteControl = PasteControl; 4078 4079 BX.onCustomEvent(window.BXHtmlEditor, 'OnEditorBaseControlsDefined'); 4080 } 4081 4082 if (window.BXHtmlEditor) 4083 { 4084 __run(); 4085 } 4086 else 4087 { 4088 BX.addCustomEvent(window, "OnBXHtmlEditorInit", __run); 4089 } 4090})();
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.