Changeset 1044
- Timestamp:
- 10/02/08 17:07:26 (5 years ago)
- Location:
- trunk
- Files:
-
- 18 added
- 4 removed
- 27 modified
-
Xinha.css (modified) (6 diffs)
-
XinhaCore.js (modified) (18 diffs)
-
modules/ColorPicker/ColorPicker.js (modified) (1 diff)
-
modules/CreateLink/dialog.html (added)
-
modules/CreateLink/link.js (modified) (4 diffs)
-
modules/CreateLink/pluginMethods.js (added)
-
modules/Dialogs/XinhaDialog.js (added)
-
modules/Dialogs/inline-dialog.js (deleted)
-
modules/Gecko/Gecko.js (modified) (3 diffs)
-
modules/InlineStyler (added)
-
modules/InlineStyler/InlineStyler.js (added)
-
modules/InsertImage/dialog.html (added)
-
modules/InsertImage/insert_image.js (modified) (3 diffs)
-
modules/InsertImage/pluginMethods.js (added)
-
modules/InsertTable/dialog.html (added)
-
modules/InsertTable/insert_table.js (modified) (2 diffs)
-
modules/InsertTable/pluginMethods.js (added)
-
modules/InternetExplorer/InternetExplorer.js (modified) (5 diffs)
-
modules/Opera/Opera.js (modified) (2 diffs)
-
modules/WebKit/WebKit.js (modified) (3 diffs)
-
plugins/Abbreviation/abbreviation.js (modified) (2 diffs)
-
plugins/Abbreviation/dialog.html (added)
-
plugins/Abbreviation/popups (deleted)
-
plugins/BackgroundImage/background-image.js (modified) (1 diff)
-
plugins/BackgroundImage/dialog.html (added)
-
plugins/BackgroundImage/popups (deleted)
-
plugins/CharacterMap/CharacterMap.css (modified) (1 diff)
-
plugins/CharacterMap/character-map.js (modified) (3 diffs)
-
plugins/InsertAnchor/dialog.html (added)
-
plugins/InsertAnchor/insert-anchor.js (modified) (5 diffs)
-
plugins/Linker/linker.js (modified) (1 diff)
-
plugins/Linker/pluginMethods.js (added)
-
plugins/PasteText/lang/de.js (modified) (1 diff)
-
plugins/PasteText/paste-text.js (modified) (3 diffs)
-
plugins/PasteText/popups/paste_text.html (modified) (1 diff)
-
plugins/SmartReplace/dialog.html (modified) (1 diff)
-
plugins/SmartReplace/smart-replace.js (modified) (7 diffs)
-
plugins/Stylist/stylist.js (modified) (6 diffs)
-
plugins/SuperClean/dialog.html (modified) (1 diff)
-
plugins/SuperClean/lang/de.js (modified) (1 diff)
-
plugins/SuperClean/pluginMethods.js (added)
-
plugins/SuperClean/super-clean.js (modified) (6 diffs)
-
plugins/TableOperations/popups/dialogMergeCells.html (added)
-
plugins/TableOperations/popups/dialogRowCell.html (added)
-
plugins/TableOperations/popups/dialogTable.html (added)
-
plugins/TableOperations/table-operations.js (modified) (20 diffs)
-
plugins/UnFormat/dialog.html (added)
-
plugins/UnFormat/popups (deleted)
-
plugins/UnFormat/un-format.js (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Xinha.css
r980 r1044 114 114 .dialog { 115 115 color: ButtonText; 116 background: ButtonFace; 117 } 118 116 background: ButtonFace; 117 border: 1px outset; 118 border-color: WindowFrame; 119 } 120 div.dialog { 121 padding-bottom:10px; 122 } 123 .xinha_dialog_background { 124 filter: alpha(opacity=0); 125 -moz-opacity: 0; 126 opacity: 0; 127 border:none; 128 } 129 .xinha_dialog_background.modal.greyout { 130 background-color:#666; 131 filter: alpha(opacity=70) !IMPORTANT; 132 -moz-opacity: 0.7; 133 opacity: 0.7; 134 } 135 .xinha_dialog_background.modal { 136 filter: alpha(opacity=0) !IMPORTANT; 137 -moz-opacity: 0; 138 opacity: 0; 139 border:none; 140 } 141 body.xinha_dialog_background.modal.greyout { 142 filter: alpha(opacity=100) !IMPORTANT; 143 } 144 body.xinha_dialog_background.modal { 145 filter: alpha(opacity=0); 146 } 119 147 .dialog .content { padding: 2px; } 120 148 … … 127 155 .dialog .title, .dialog h1 128 156 { 129 background: #008;130 color: #ff8;157 background: ActiveCaption; 158 color: CaptionText; 131 159 border-bottom: 1px solid #000; 132 160 padding: 1px 0px 2px 5px; … … 134 162 font-weight: bold; 135 163 cursor: default; 136 } 137 .dialog h1 { margin:0px;} 164 letter-spacing: 0.01em; 165 } 166 .dialog h1 { margin:0;} 138 167 .dialog .title .button { 139 168 float: right; … … 148 177 149 178 .dialog button { 150 width: 5 em;179 width: 5.5em; 151 180 padding: 0px; 152 181 } 153 182 .dialog .closeButton { 183 padding: 0px; 184 cursor: default; 185 border: 1px solid; 186 border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; 187 height : 11px; 188 width : 11px; 189 vertical-align : top; 190 position : absolute; 191 top : 3px; 192 right : 2px; 193 background-color: ButtonFace; 194 color: ButtonText; 195 font-size: 13px; 196 font-family: Tahoma,Verdana,sans-serif; 197 text-align:center; 198 letter-spacing:0; 199 overflow:hidden; 200 } 154 201 .dialog .buttonColor { 155 202 width :1em; … … 179 226 .dialog .label { text-align: right; width: 6em; } 180 227 .dialog .value input { width: 100%; } 181 .dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }182 228 183 229 .dialog legend { font-weight: bold; } 184 230 .dialog fieldset table { margin: 2px 0px; } 185 231 232 .dialog .buttons { 233 234 padding: 1em; 235 text-align: center; 236 } 237 .dialog .resizeHandle { 238 -moz-appearance : resizer; 239 width: 12px; 240 height: 12px; 241 border-bottom: 2px solid #000; 242 border-right: 2px solid #000; 243 cursor : nw-resize; 244 } 186 245 .popupwin { 187 246 padding: 0px; … … 229 288 230 289 .htmlarea .panel h1 { 231 background: ButtonFace;232 border: 1px solid;233 border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;234 margin: 0px;235 padding: 0px;236 font-size:100%;237 font-weight:bold;238 padding: 2px;239 290 clear:left; 240 241 } 242 243 .htmlarea .panel { overflow:hidden; } 291 font-size:0.9em; 292 } 293 294 .htmlarea .panel { 295 overflow:hidden; 296 background-color:white; 297 padding-bottom:0 !IMPORTANT; 298 border: none !IMPORTANT; 299 } 244 300 .htmlarea .panels.left .panel { border-right:none; border-left:none; } 245 301 .htmlarea .panels.left h1 { border-right:none; } -
trunk/XinhaCore.js
r1032 r1044 977 977 "Formatted": "pre" 978 978 }; 979 980 this.dialogOptions = 981 { 982 'centered' : true, //true: dialog is shown in the center the screen, false dialog is shown near the clicked toolbar button 983 'greyout':true, //true: when showing modal dialogs, the page behind the dialoge is greyed-out 984 'closeOnEscape':true 985 }; 986 979 987 /** ?? 980 988 * Default: <code>{}</code> … … 1782 1790 function(ev) 1783 1791 { 1784 ev = Xinha.is_ie ? window.event : ev;1785 editor.btnClickEvent = ev;1792 ev = ev || window.event; 1793 editor.btnClickEvent = {clientX : ev.clientX, clientY : ev.clientY}; 1786 1794 if ( obj.enabled ) 1787 1795 { … … 2100 2108 } 2101 2109 2102 if ( typeof Xinha.Dialog == 'undefined' && !Xinha._loadback( _editor_url + 'modules/Dialogs/ inline-dialog.js' , this.generate, this ) )2110 if ( typeof Xinha.Dialog == 'undefined' && !Xinha._loadback( _editor_url + 'modules/Dialogs/XinhaDialog.js' , this.generate, this ) ) 2103 2111 { 2104 2112 return false; … … 2259 2267 fw.table.appendChild(fw.tbody); 2260 2268 2261 var xinha = this._framework.table;2269 var xinha = fw.table; 2262 2270 this._htmlArea = xinha; 2263 2271 Xinha.freeLater(this, '_htmlArea'); … … 2265 2273 2266 2274 // create the toolbar and put in the area 2267 this._framework.tb_cell.appendChild( this._createToolbar() );2275 fw.tb_cell.appendChild( this._createToolbar() ); 2268 2276 2269 2277 // create the IFRAME & add to container … … 2271 2279 iframe.src = this.popupURL(editor.config.URIs.blank); 2272 2280 iframe.id = "XinhaIFrame_" + this._textArea.id; 2273 this._framework.ed_cell.appendChild(iframe);2281 fw.ed_cell.appendChild(iframe); 2274 2282 this._iframe = iframe; 2275 2283 this._iframe.className = 'xinha_iframe'; … … 2278 2286 // creates & appends the status bar 2279 2287 var statusbar = this._createStatusBar(); 2280 this._framework.sb_cell.appendChild(statusbar);2288 fw.sb_cell.appendChild(statusbar); 2281 2289 2282 2290 // insert Xinha before the textarea. … … 2287 2295 // extract the textarea and insert it into the xinha framework 2288 2296 Xinha.removeFromParent(textarea); 2289 this._framework.ed_cell.appendChild(textarea);2297 fw.ed_cell.appendChild(textarea); 2290 2298 2291 2299 // if another editor is activated while this one is in text mode, toolbar is disabled … … 2469 2477 this._risizing = true; 2470 2478 2479 var framework = this._framework; 2480 2471 2481 this.notifyOf('before_resize', {width:width, height:height}); 2472 2482 this.firePluginEvent('onBeforeResize', width, height); … … 2580 2590 // } 2581 2591 2582 this._framework.tb_cell.colSpan = col_span;2583 this._framework.tp_cell.colSpan = col_span;2584 this._framework.bp_cell.colSpan = col_span;2585 this._framework.sb_cell.colSpan = col_span;2592 framework.tb_cell.colSpan = col_span; 2593 framework.tp_cell.colSpan = col_span; 2594 framework.bp_cell.colSpan = col_span; 2595 framework.sb_cell.colSpan = col_span; 2586 2596 2587 2597 // Put in the panel rows, top panel goes above editor row 2588 if ( ! this._framework.tp_row.childNodes.length )2589 { 2590 Xinha.removeFromParent( this._framework.tp_row);2598 if ( !framework.tp_row.childNodes.length ) 2599 { 2600 Xinha.removeFromParent(framework.tp_row); 2591 2601 } 2592 2602 else 2593 2603 { 2594 if ( !Xinha.hasParentNode( this._framework.tp_row) )2595 { 2596 this._framework.tbody.insertBefore(this._framework.tp_row, this._framework.ler_row);2604 if ( !Xinha.hasParentNode(framework.tp_row) ) 2605 { 2606 framework.tbody.insertBefore(framework.tp_row, framework.ler_row); 2597 2607 } 2598 2608 } 2599 2609 2600 2610 // bp goes after the editor 2601 if ( ! this._framework.bp_row.childNodes.length )2602 { 2603 Xinha.removeFromParent( this._framework.bp_row);2611 if ( !framework.bp_row.childNodes.length ) 2612 { 2613 Xinha.removeFromParent(framework.bp_row); 2604 2614 } 2605 2615 else 2606 2616 { 2607 if ( !Xinha.hasParentNode( this._framework.bp_row) )2608 { 2609 this._framework.tbody.insertBefore(this._framework.bp_row, this._framework.ler_row.nextSibling);2617 if ( !Xinha.hasParentNode(framework.bp_row) ) 2618 { 2619 framework.tbody.insertBefore(framework.bp_row, framework.ler_row.nextSibling); 2610 2620 } 2611 2621 } … … 2614 2624 if ( !this.config.statusBar ) 2615 2625 { 2616 Xinha.removeFromParent( this._framework.sb_row);2626 Xinha.removeFromParent(framework.sb_row); 2617 2627 } 2618 2628 else 2619 2629 { 2620 if ( !Xinha.hasParentNode( this._framework.sb_row) )2621 { 2622 this._framework.table.appendChild(this._framework.sb_row);2630 if ( !Xinha.hasParentNode(framework.sb_row) ) 2631 { 2632 framework.table.appendChild(framework.sb_row); 2623 2633 } 2624 2634 } 2625 2635 2626 2636 // Size and set colspans, link up the framework 2627 this._framework.lp_cell.style.width = this.config.panel_dimensions.left;2628 this._framework.rp_cell.style.width = this.config.panel_dimensions.right;2629 this._framework.tp_cell.style.height = this.config.panel_dimensions.top;2630 this._framework.bp_cell.style.height = this.config.panel_dimensions.bottom;2631 this._framework.tb_cell.style.height = this._toolBar.offsetHeight + 'px';2632 this._framework.sb_cell.style.height = this._statusBar.offsetHeight + 'px';2637 framework.lp_cell.style.width = this.config.panel_dimensions.left; 2638 framework.rp_cell.style.width = this.config.panel_dimensions.right; 2639 framework.tp_cell.style.height = this.config.panel_dimensions.top; 2640 framework.bp_cell.style.height = this.config.panel_dimensions.bottom; 2641 framework.tb_cell.style.height = this._toolBar.offsetHeight + 'px'; 2642 framework.sb_cell.style.height = this._statusBar.offsetHeight + 'px'; 2633 2643 2634 2644 var edcellheight = height - this._toolBar.offsetHeight - this._statusBar.offsetHeight; … … 3944 3954 Xinha.prototype.updateToolbar = function(noStatus) 3945 3955 { 3956 if (this.suspendUpdateToolbar) return; 3957 3946 3958 var doc = this._doc; 3947 3959 var text = (this._editMode == "textmode"); … … 4714 4726 } 4715 4727 } 4728 4729 /* If this.currentModal is not null, then there's a modal dialog 4730 /* on screen, and we kill the event. This eliminates the possibility 4731 /* of a user 'tabbing' out of a modal dialog and re-activating the editor. 4732 /* This fixes the bug reported in ticket #1259 4733 /* http://xinha.webfactional.com/ticket/1259 */ 4734 if (this.currentModal) 4735 { 4736 return false; 4737 } 4738 4716 4739 // update the toolbar state after some time 4717 4740 if ( editor._timerToolbar ) … … 4719 4742 clearTimeout(editor._timerToolbar); 4720 4743 } 4744 if (!this.suspendUpdateToolbar) 4745 { 4721 4746 editor._timerToolbar = setTimeout( 4722 4747 function() … … 4726 4751 }, 4727 4752 250); 4753 } 4728 4754 }; 4729 4755 … … 5485 5511 }; 5486 5512 5513 Xinha.getEvent = function(ev) 5514 { 5515 return ev || window.event; 5516 } 5487 5517 /** 5488 5518 * Prepares an element to receive more than one DOM-0 event handler … … 6179 6209 s += prop + ' = ' + o[prop] + '\n'; 6180 6210 } 6181 6182 6211 } 6183 6212 if (s) … … 6789 6818 scope = (scope) ? scope : window; 6790 6819 var x,y; 6791 if ( scope.pageYOffset) // all except Explorer6820 if (typeof scope.pageYOffset != 'undefined') // all except Explorer 6792 6821 { 6793 6822 x = scope.pageXOffset; 6794 6823 y = scope.pageYOffset; 6795 6824 } 6796 else if (scope.document.documentElement && document.documentElement.scrollTop)6825 else if (scope.document.documentElement && typeof document.documentElement.scrollTop != 'undefined') 6797 6826 // Explorer 6 Strict 6798 6827 { -
trunk/modules/ColorPicker/ColorPicker.js
r1024 r1044 372 372 this.table.style.position = 'fixed'; 373 373 } 374 top +=e.offsetTop - e.scrollTop;375 left +=e.offsetLeft - e.scrollLeft;374 top += e.offsetTop - e.scrollTop; 375 left += e.offsetLeft - e.scrollLeft; 376 376 377 377 e = e.offsetParent; -
trunk/modules/CreateLink/link.js
r1001 r1044 1 2 1 /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- 3 2 -- Xinha (is not htmlArea) - http://xinha.org … … 16 15 -- which provides the functionality to insert a hyperlink in the editor. 17 16 -- 18 -- he file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded.17 -- The file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded. 19 18 -- 20 19 -- … … 24 23 -- $LastChangedBy:ray $ 25 24 --------------------------------------------------------------------------*/ 25 26 function CreateLink(editor) { 27 this.editor = editor; 28 var cfg = editor.config; 29 var self = this; 30 31 editor.config.btnList.createlink[3] = function() { self.show(self._getSelectedAnchor()); } 32 } 33 26 34 CreateLink._pluginInfo = { 27 35 name : "CreateLink", 28 36 origin : "Xinha Core", 29 version : "$LastChangedRevision :990$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'),37 version : "$LastChangedRevision$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'), 30 38 developer : "The Xinha Core Developer Team", 31 developer_url : "$HeadURL :http://svn.xinha.webfactional.com/trunk/modules/CreateLink/link.js$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'),39 developer_url : "$HeadURL$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'), 32 40 sponsor : "", 33 41 sponsor_url : "", … … 35 43 }; 36 44 37 function CreateLink(editor) { 38 } 45 CreateLink.prototype._lc = function(string) { 46 return Xinha._lc(string, 'Xinha'); 47 }; 39 48 40 Xinha.prototype._createLink = function(link) 49 50 CreateLink.prototype.onGenerateOnce = function() 41 51 { 42 var editor = this; 43 var outparam = null; 44 if ( typeof link == "undefined" ) 45 { 46 link = this.getParentElement(); 47 if ( link ) 48 { 49 while (link && !/^a$/i.test(link.tagName)) 50 { 51 link = link.parentNode; 52 } 53 } 54 } 55 if ( !link ) 56 { 57 var sel = editor.getSelection(); 58 var range = editor.createRange(sel); 59 var compare = 0; 60 if ( Xinha.is_ie ) 61 { 62 if ( sel.type == "Control" ) 63 { 64 compare = range.length; 65 } 66 else 67 { 68 compare = range.compareEndPoints("StartToEnd", range); 69 } 70 } 71 else 72 { 73 compare = range.compareBoundaryPoints(range.START_TO_END, range); 74 } 75 if ( compare === 0 ) 76 { 77 alert(Xinha._lc("You need to select some text before creating a link")); 78 return; 79 } 80 outparam = 81 { 82 f_href : '', 83 f_title : '', 84 f_target : '', 85 f_usetarget : editor.config.makeLinkShowsTarget 86 }; 87 } 88 else 89 { 90 outparam = 91 { 92 f_href : Xinha.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"), 93 f_title : link.title, 94 f_target : link.target, 95 f_usetarget : editor.config.makeLinkShowsTarget 96 }; 97 } 98 Dialog( 99 editor.config.URIs.link, 100 function(param) 101 { 102 if ( !param ) 103 { 104 return false; 105 } 106 var a = link; 107 if ( !a ) 108 { 109 try 110 { 111 var tmp = Xinha.uniq('http://www.example.com/Link'); 112 editor._doc.execCommand('createlink', false, tmp); 52 CreateLink.loadAssets(); 53 }; 113 54 114 // Fix them up 115 var anchors = editor._doc.getElementsByTagName('a'); 116 for(var i = 0; i < anchors.length; i++) 117 { 118 var anchor = anchors[i]; 119 if(anchor.href == tmp) 120 { 121 // Found one. 122 if (!a) a = anchor; 123 anchor.href = param.f_href; 124 if (param.f_target) anchor.target = param.f_target; 125 if (param.f_title) anchor.title = param.f_title; 126 } 127 } 128 } catch(ex) {} 129 } 130 else 131 { 132 var href = param.f_href.trim(); 133 editor.selectNodeContents(a); 134 if ( href === '' ) 135 { 136 editor._doc.execCommand("unlink", false, null); 137 editor.updateToolbar(); 138 return false; 139 } 140 else 141 { 142 a.href = href; 143 } 144 } 145 if ( ! ( a && a.tagName.toLowerCase() == 'a' ) ) 146 { 147 return false; 148 } 149 a.target = param.f_target.trim(); 150 a.title = param.f_title.trim(); 151 editor.selectNodeContents(a); 152 editor.updateToolbar(); 153 }, 154 outparam); 55 CreateLink.loadAssets = function() 56 { 57 var self = CreateLink; 58 if (self.loading) return; 59 self.loading = true; 60 Xinha._getback(_editor_url + 'modules/CreateLink/dialog.html', function(getback) { self.html = getback; self.dialogReady = true; }); 61 Xinha._getback(_editor_url + 'modules/CreateLink/pluginMethods.js', function(getback) { eval(getback); self.methodsReady = true; }); 62 } 63 64 CreateLink.prototype.onUpdateToolbar = function() 65 { 66 if (!(CreateLink.dialogReady && CreateLink.methodsReady)) 67 { 68 this.editor._toolbarObjects.createlink.state("enabled", false); 69 } 70 else this.onUpdateToolbar = null; 155 71 }; 72 73 CreateLink.prototype.prepareDialog = function() 74 { 75 var self = this; 76 var editor = this.editor; 77 78 var dialog = this.dialog = new Xinha.Dialog(editor, CreateLink.html, 'Xinha',{width:400}) 79 // Connect the OK and Cancel buttons 80 dialog.getElementById('ok').onclick = function() {self.apply();} 81 82 dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 83 84 if (!editor.config.makeLinkShowsTarget) 85 { 86 dialog.getElementById("f_target_label").style.visibility = "hidden"; 87 dialog.getElementById("f_target").style.visibility = "hidden"; 88 dialog.getElementById("f_other_target").style.visibility = "hidden"; 89 } 90 91 dialog.getElementById('f_target').onchange= function() 92 { 93 var f = dialog.getElementById("f_other_target"); 94 if (this.value == "_other") { 95 f.style.visibility = "visible"; 96 f.select(); 97 f.focus(); 98 } else f.style.visibility = "hidden"; 99 }; 100 101 102 this.dialogReady = true; 103 }; -
trunk/modules/Gecko/Gecko.js
r1001 r1044 576 576 Xinha.prototype.restoreSelection = function(savedSelection) 577 577 { 578 try 579 { 578 580 var sel = this.getSelection(); 579 581 sel.removeAllRanges(); 580 582 sel.addRange(savedSelection); 583 } 584 catch (e) {} 581 585 } 582 586 /** … … 585 589 * 586 590 * @param node DomNode 587 * @param pos Set to a numeric position inside the node to collapse the cursor here if possible.588 */ 589 590 Xinha.prototype.selectNodeContents = function(node, pos)591 * @param collapseToStart A boolean that, when supplied, says to collapse the selection. True collapses to the start, and false to the end. 592 */ 593 594 Xinha.prototype.selectNodeContents = function(node, collapseToStart) 591 595 { 592 596 this.focusEditor(); 593 597 this.forceRedraw(); 594 598 var range; 595 var collapsed = typeof pos== "undefined" ? true : false;599 var collapsed = typeof collapseToStart == "undefined" ? true : false; 596 600 var sel = this.getSelection(); 597 601 range = this._doc.createRange(); … … 609 613 { 610 614 range.selectNodeContents(node); 611 //(collapsed) && range.collapse(pos);612 615 } 613 616 sel.removeAllRanges(); 614 617 sel.addRange(range); 618 if (typeof collapseToStart != "undefined") 619 { 620 if (collapseToStart) 621 { 622 sel.collapse(range.startContainer, range.startOffset); 623 } else 624 { 625 sel.collapse(range.endContainer, range.endOffset); 626 } 627 } 615 628 }; 616 629 -
trunk/modules/InsertImage/insert_image.js
r1001 r1044 1 2 1 /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:-- 3 2 -- Xinha (is not htmlArea) - http://xinha.org … … 8 7 -- Copyright (c) 2005-2008 Xinha Developer Team and contributors 9 8 -- 10 -- This is the standard implementation of the Xinha.prototype._insertImage method, 11 -- which provides the functionality to insert an image in the editor. 9 -- This is the Xinha standard implementation of an image insertion plugin 12 10 -- 13 -- The file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded.11 -- he file is loaded as a special plugin by the Xinha Core when no alternative method (plugin) is loaded. 14 12 -- 15 13 -- 16 -- $HeadURL :http://svn.xinha.webfactional.com/trunk/modules/InsertImage/insert_image.js$17 -- $LastChangedDate :2008-04-12 23:02:13 +0200 (Sa, 12 Apr 2008)$18 -- $LastChangedRevision :992$19 -- $LastChangedBy :ray$14 -- $HeadURL$ 15 -- $LastChangedDate$ 16 -- $LastChangedRevision$ 17 -- $LastChangedBy$ 20 18 --------------------------------------------------------------------------*/ 19 21 20 InsertImage._pluginInfo = { 22 21 name : "InsertImage", 23 22 origin : "Xinha Core", 24 version : "$LastChangedRevision :992$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'),23 version : "$LastChangedRevision$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'), 25 24 developer : "The Xinha Core Developer Team", 26 developer_url : "$HeadURL :http://svn.xinha.webfactional.com/trunk/modules/InsertImage/insert_image.js$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'),25 developer_url : "$HeadURL$".replace(/^[^:]*:\s*(.*)\s*\$$/, '$1'), 27 26 sponsor : "", 28 27 sponsor_url : "", … … 31 30 32 31 function InsertImage(editor) { 33 } 32 this.editor = editor; 33 var cfg = editor.config; 34 var self = this; 34 35 35 // Called when the user clicks on "InsertImage" button. If an image is already 36 // there, it will just modify it's properties. 37 Xinha.prototype._insertImage = function(image) 38 { 39 var editor = this; // for nested functions 40 var outparam; 41 if ( typeof image == "undefined" ) 42 { 43 image = this.getParentElement(); 44 if ( image && image.tagName.toLowerCase() != 'img' ) 45 { 46 image = null; 47 } 36 editor.config.btnList.insertimage[3] = function() { self.show(); } 48 37 } 49 38 50 var base; 51 if ( typeof editor.config.baseHref != 'undefined' && editor.config.baseHref !== null ) { 52 base = editor.config.baseHref; 39 InsertImage.prototype._lc = function(string) { 40 return Xinha._lc(string, 'Xinha'); 41 }; 42 43 InsertImage.prototype.onGenerateOnce = function() 44 { 45 InsertImage.loadAssets(); 46 }; 47 48 InsertImage.loadAssets = function() 49 { 50 var self = InsertImage; 51 if (self.loading) return; 52 self.loading = true; 53 Xinha._getback(_editor_url + 'modules/InsertImage/dialog.html', function(getback) { self.html = getback; self.dialogReady = true; }); 54 Xinha._getback(_editor_url + 'modules/InsertImage/pluginMethods.js', function(getback) { eval(getback); self.methodsReady = true; }); 55 }; 56 InsertImage.prototype.onUpdateToolbar = function() 57 { 58 if (!(InsertImage.dialogReady && InsertImage.methodsReady)) 59 { 60 this.editor._toolbarObjects.insertimage.state("enabled", false); 53 61 } 54 else { 55 var bdir = window.location.toString().split("/"); 56 bdir.pop(); 57 base = bdir.join("/"); 58 } 62 else this.onUpdateToolbar = null; 63 }; 59 64 60 if ( image)65 InsertImage.prototype.prepareDialog = function() 61 66 { 62 function getSpecifiedAttribute(element,attribute) 63 { 64 var a = element.attributes; 65 for (var i=0;i<a.length;i++) 66 { 67 if (a[i].nodeName == attribute && a[i].specified) 68 { 69 return a[i].value; 70 } 71 } 72 return ''; 73 } 74 /* if you want to understand why the above function is required, uncomment the two lines below and launch InsertImage in both Mozilla & IE with an image selected that hath neither value set and compare the results 75 alert(image.vspace +' '+ image.getAttribute('vspace') + ' ' + image.getAttribute('vspace',2) + ' ' + getSpecifiedAttribute(image,'vspace') ); 76 alert(image.hspace +' '+ image.getAttribute('hspace') + ' ' + image.getAttribute('hspace',2) + ' ' + getSpecifiedAttribute(image,'hspace') ); 77 */ 78 outparam = 79 { 80 f_base : base, 81 f_url : this.stripBaseURL(image.getAttribute('src',2)), // the second parameter makes IE return the value as it is set, as opposed to an "interpolated" (as MSDN calls it) value 82 f_alt : image.alt, 83 f_border : image.border, 84 f_align : image.align, 85 f_vert : getSpecifiedAttribute(image,'vspace'), 86 f_horiz : getSpecifiedAttribute(image,'hspace'), 87 f_width : image.width, 88 f_height : image.height 89 }; 90 } 91 else{ 92 outparam = 93 { 94 f_base : base, 95 f_url : "" 96 }; 97 } 67 var self = this; 68 var editor = this.editor; 98 69 99 Dialog( 100 editor.config.URIs.insert_image, 101 function(param) 102 { 103 // user must have pressed Cancel 104 if ( !param ) 105 { 70 var dialog = this.dialog = new Xinha.Dialog(editor, InsertImage.html, 'Xinha',{width:410}) 71 // Connect the OK and Cancel buttons 72 dialog.getElementById('ok').onclick = function() {self.apply();} 73 74 dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 75 76 dialog.getElementById('preview').onclick = function() { 77 var f_url = dialog.getElementById("f_url"); 78 var url = f_url.value; 79 var base = dialog.getElementById("f_base").value; 80 if (!url) { 81 alert(dialog._lc("You must enter the URL")); 82 f_url.focus(); 106 83 return false; 107 84 } 108 var img = image; 109 if ( !img ) 85 dialog.getElementById('ipreview').src = Xinha._resolveRelativeUrl(base, url); 86 return false; 87 } 88 this.dialog.onresize = function () 110 89 { 111 if ( Xinha.is_ie ) 112 { 113 var sel = editor.getSelection(); 114 var range = editor.createRange(sel); 115 editor._doc.execCommand("insertimage", false, param.f_url); 116 img = range.parentElement(); 117 // wonder if this works... 118 if ( img.tagName.toLowerCase() != "img" ) 119 { 120 img = img.previousSibling; 90 91 92 var newHeightForPreview = 93 parseInt(this.height,10) 94 - this.getElementById('h1').offsetHeight 95 - this.getElementById('buttons').offsetHeight 96 - this.getElementById('inputs').offsetHeight 97 - parseInt(this.rootElem.style.paddingBottom,10); // we have a padding at the bottom, gotta take this into acount 98 99 100 this.getElementById("ipreview").style.height = ((newHeightForPreview > 0) ? newHeightForPreview : 0) + "px"; // no-go beyond 0 101 102 this.getElementById("ipreview").style.width = this.width - 2 + 'px'; // and the width 103 121 104 } 122 } 123 else 124 { 125 img = document.createElement('img'); 126 img.src = param.f_url; 127 editor.insertNodeAtSelection(img); 128 if ( !img.tagName ) 129 { 130 // if the cursor is at the beginning of the document 131 img = range.startContainer.firstChild; 132 } 133 } 134 } 135 else 136 { 137 img.src = param.f_url; 138 } 139 140 for ( var field in param ) 141 { 142 var value = param[field]; 143 switch (field) 144 { 145 case "f_alt": 146 if (value) 147 img.alt = value; 148 else 149 img.removeAttribute("alt"); 150 break; 151 case "f_border": 152 if (value) 153 img.border = parseInt(value || "0"); 154 else 155 img.removeAttribute("border"); 156 break; 157 case "f_align": 158 if (value) 159 img.align = value; 160 else 161 img.removeAttribute("align"); 162 break; 163 case "f_vert": 164 if (value != "") 165 img.vspace = parseInt(value || "0"); 166 else 167 img.removeAttribute("vspace"); 168 break; 169 case "f_horiz": 170 if (value != "") 171 img.hspace = parseInt(value || "0"); 172 else 173 img.removeAttribute("hspace"); 174 break; 175 case "f_width": 176 if (value) 177 img.width = parseInt(value || "0"); 178 else 179 img.removeAttribute("width"); 180 break; 181 case "f_height": 182 if (value) 183 img.height = parseInt(value || "0"); 184 else 185 img.removeAttribute("height"); 186 break; 187 } 188 } 189 }, 190 outparam); 105 this.dialogReady = true; 191 106 }; -
trunk/modules/InsertTable/insert_table.js
r1001 r1044 13 13 -- This copyright notice MUST stay intact for use. 14 14 -- 15 -- This is the standard implementation of the Xinha.prototype._insertTable method, 16 -- which provides the functionality to insert an image in the editor. 15 -- This is the Xinha standard implementation of a table insertion plugin 17 16 -- 18 -- he file is loaded as a special pluginby the Xinha Core when no alternative method (plugin) is loaded.17 -- The file is loaded by the Xinha Core when no alternative method (plugin) is loaded. 19 18 -- 20 19 -- … … 36 35 37 36 function InsertTable(editor) { 38 } 37 this.editor = editor; 38 var cfg = editor.config; 39 var self = this; 39 40 40 Xinha.prototype._insertTable = function() 41 editor.config.btnList.inserttable[3] = function() { self.show(); } 42 } 43 44 InsertTable.prototype._lc = function(string) { 45 return Xinha._lc(string, 'Xinha'); 46 }; 47 48 49 InsertTable.prototype.onGenerateOnce = function() 41 50 { 42 var sel = this.getSelection(); 43 var range = this.createRange(sel); 44 var editor = this; // for nested functions 45 Dialog( 46 editor.config.URIs.insert_table, 47 function(param) 48 { 49 // user must have pressed Cancel 50 if ( !param ) 51 { 52 return false; 53 } 54 var doc = editor._doc; 55 // create the table element 56 var table = doc.createElement("table"); 57 // assign the given arguments 51 InsertTable.loadAssets(); 52 }; 53 InsertTable.loadAssets = function() 54 { 55 var self = InsertTable; 56 if (self.loading) return; 57 self.loading = true; 58 Xinha._getback(_editor_url + 'modules/InsertTable/dialog.html', function(getback) { self.html = getback; self.dialogReady = true; }); 59 Xinha._getback(_editor_url + 'modules/InsertTable/pluginMethods.js', function(getback) { eval(getback); self.methodsReady = true; }); 60 }; 58 61 59 for ( var field in param ) 60 { 61 var value = param[field]; 62 if ( !value ) 63 { 64 continue; 65 } 66 switch (field) 67 { 68 case "f_width": 69 table.style.width = value + param.f_unit; 70 break; 71 case "f_align": 72 table.align = value; 73 break; 74 case "f_border": 75 table.border = parseInt(value, 10); 76 break; 77 case "f_spacing": 78 table.cellSpacing = parseInt(value, 10); 79 break; 80 case "f_padding": 81 table.cellPadding = parseInt(value, 10); 82 break; 83 } 84 } 85 var cellwidth = 0; 86 if ( param.f_fixed ) 87 { 88 cellwidth = Math.floor(100 / parseInt(param.f_cols, 10)); 89 } 90 var tbody = doc.createElement("tbody"); 91 table.appendChild(tbody); 92 for ( var i = 0; i < param.f_rows; ++i ) 93 { 94 var tr = doc.createElement("tr"); 95 tbody.appendChild(tr); 96 for ( var j = 0; j < param.f_cols; ++j ) 97 { 98 var td = doc.createElement("td"); 99 // @todo : check if this line doesnt stop us to use pixel width in cells 100 if (cellwidth) 101 { 102 td.style.width = cellwidth + "%"; 103 } 104 tr.appendChild(td); 105 // Browsers like to see something inside the cell ( ). 106 td.appendChild(doc.createTextNode('\u00a0')); 107 } 108 } 109 if ( Xinha.is_ie ) 110 { 111 range.pasteHTML(table.outerHTML); 112 } 113 else 114 { 115 // insert the table 116 editor.insertNodeAtSelection(table); 117 } 118 return true; 119 }, 120 null 121 ); 62 InsertTable.prototype.onUpdateToolbar = function() 63 { 64 if (!(InsertTable.dialogReady && InsertTable.methodsReady)) 65 { 66 this.editor._toolbarObjects.inserttable.state("enabled", false); 67 } 68 else this.onUpdateToolbar = null; 122 69 }; 70 71 InsertTable.prototype.prepareDialog = function() 72 { 73 var self = this; 74 var editor = this.editor; 75 76 var dialog = this.dialog = new Xinha.Dialog(editor, InsertTable.html, 'Xinha',{width:400}) 77 // Connect the OK and Cancel buttons 78 dialog.getElementById('ok').onclick = function() {self.apply();} 79 dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 80 81 this.borderColorPicker = new Xinha.colorPicker.InputBinding(dialog.getElementById('border_color')); 82 83 this.dialog.onresize = function () 84 { 85 this.getElementById("layout_fieldset").style.width =(this.width / 2) + 50 + 'px'; 86 this.getElementById("spacing_fieldset").style.width =(this.width / 2) - 120 + 'px'; 87 } 88 89 this.dialogReady = true; 90 }; -
trunk/modules/InternetExplorer/InternetExplorer.js
r1001 r1044 147 147 html = html.replace(/(<script|<!--)/i," $1"); 148 148 149 // We've got a workaround for certain issues with saving and restoring 150 // selections that may cause us to fill in junk span tags. We'll clean 151 // those here 152 html = html.replace(/<span[^>]+id="__InsertSpan_Workaround_[a-z]+".*?>([\s\S]*?)<\/span>/i,"$1"); 153 149 154 return html; 150 155 } … … 154 159 // remove space added before first script on the page 155 160 html = html.replace(/ (\s*)(<script|<!--)/i,"$1$2"); 161 162 // We've got a workaround for certain issues with saving and restoring 163 // selections that may cause us to fill in junk span tags. We'll clean 164 // those here 165 html = html.replace(/<span[^>]+id="__InsertSpan_Workaround_[a-z]+".*?>([\s\S]*?)<\/span>/i,"$1"); 156 166 157 167 return html; … … 441 451 Xinha.prototype.restoreSelection = function(savedSelection) 442 452 { 453 // In order to prevent triggering the IE bug mentioned below, we will try to 454 // optimize by not restoring the selection if it happens to match the current 455 // selection. 456 var range = this.createRange(this.getSelection()); 457 458 // We can't compare two selections that come from different documents, so we 459 // must make sure they're from the same document. 460 var findDoc = function(el) 461 { 462 for (var root=el; root; root=root.parentNode) 463 { 464 if (root.tagName.toLowerCase() == 'html') 465 { 466 return root.parentNode; 467 } 468 } 469 return null; 470 } 471 472 if (findDoc(savedSelection.parentElement()) == findDoc(range.parentElement())) 473 { 474 if ((0 == range.compareEndPoints('StartToStart',savedSelection)) && 475 (0 == range.compareEndPoints('EndToEnd',savedSelection))) 476 { 477 // The selection hasn't moved, no need to restore. 478 return; 479 } 480 } 481 443 482 try { savedSelection.select() } catch (e) {}; 483 range = this.createRange(this.getSelection()); 484 if (range.parentElement() != savedSelection.parentElement()) 485 { 486 // IE has a problem with selections at the end of text nodes that 487 // immediately precede block nodes. Example markup: 488 // <div>Text Node<p>Text in Block</p></div> 489 // ^ 490 // The problem occurs when the cursor is after the 'e' in Node. 491 492 var solution = editor.config.selectWorkaround || 'InsertSpan'; 493 switch (solution) 494 { 495 case 'SimulateClick': 496 // Try to get the bounding box of the selection and then simulate a 497 // mouse click in the upper right corner to return the cursor to the 498 // correct location. 499 500 // No code yet, fall through to InsertSpan 501 case 'InsertSpan': 502 // This workaround inserts an empty span element so that we are no 503 // longer trying to select a text node, 504 var parentDoc = findDoc(savedSelection.parentElement()); 505 506 // A function used to generate a unique ID for our temporary span. 507 var randLetters = function(count) 508 { 509 // Build a list of 26 letters. 510 var Letters = ''; 511 for (var index = 0; index<26; ++index) 512 { 513 Letters += String.fromCharCode('a'.charCodeAt(0) + index); 514 } 515 516 var result = ''; 517 for (var index=0; index<count; ++index) 518 { 519 result += Letters.substr(Math.floor(Math.random()*Letters.length + 1), 1); 520 } 521 return result; 522 } 523 524 // We'll try to find a unique ID to use for finding our element. 525 var keyLength = 1; 526 var tempId = '__InsertSpan_Workaround_' + randLetters(keyLength); 527 while (parentDoc.getElementById(tempId)) 528 { 529 // Each time there's a collision, we'll increase our key length by 530 // one, making the chances of a collision exponentially more rare. 531 keyLength += 1; 532 tempId = '__InsertSpan_Workaround_' + randLetters(keyLength); 533 } 534 535 // Now that we have a uniquely identifiable element, we'll stick it and 536 // and use it to orient our selection. 537 savedSelection.pasteHTML('<span id="' + tempId + '"></span>'); 538 var tempSpan = parentDoc.getElementById(tempId); 539 savedSelection.moveToElementText(tempSpan); 540 savedSelection.select(); 541 break; 542 case 'JustificationHack': 543 // Setting the justification on an element causes IE to alter the 544 // markup so that the selection we want to make is possible. 545 // Unfortunately, this can force block elements to be kicked out of 546 // their containing element, so it is not recommended. 547 548 // Set a non-valid character and use it to anchor our selection. 549 var magicString = String.fromCharCode(1); 550 savedSelection.pasteHTML(magicString); 551 savedSelection.findText(magicString,-1); 552 savedSelection.select(); 553 554 // I don't know how to find out if there's an existing justification on 555 // this element. Hopefully, you're doing all of your styling outside, 556 // so I'll just clear. I already told you this was a hack. 557 savedSelection.execCommand('JustifyNone'); 558 savedSelection.pasteHTML(''); 559 break; 560 case 'VisiblePrompt': 561 default: 562 // This method will insert a little box character to hold our selection 563 // in the desired spot. We're depending on the user to see this ugly 564 // box and delete it themselves. 565 var magicString = String.fromCharCode(1); 566 savedSelection.pasteHTML(magicString); 567 savedSelection.findText(magicString,-1); 568 savedSelection.select(); 569 } 570 } 444 571 } 445 572 … … 449 576 * 450 577 * @param node DomNode 451 * @param pos Set to a numeric position inside the node to collapse the cursor here if possible.452 */ 453 454 Xinha.prototype.selectNodeContents = function(node, pos)578 * @param collapseToStart A boolean that, when supplied, says to collapse the selection. True collapses to the start, and false to the end. 579 */ 580 581 Xinha.prototype.selectNodeContents = function(node, collapseToStart) 455 582 { 456 583 this.focusEditor(); 457 584 this.forceRedraw(); 458 585 var range; 459 var collapsed = typeof pos== "undefined" ? true : false;586 var collapsed = typeof collapseToStart == "undefined" ? true : false; 460 587 // Tables and Images get selected as "objects" rather than the text contents 461 588 if ( collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|select|textarea/) ) … … 467 594 { 468 595 range = this._doc.body.createTextRange(); 596 if (3 == node.nodeType) 597 { 598 // Special handling for text nodes, since moveToElementText fails when 599 // attempting to select a text node 600 601 // Since the TextRange has a quite limited API, our strategy here is to 602 // select (where possible) neighboring nodes, and then move our ranges 603 // endpoints to be just inside of neighboring selections. 604 if (node.parentNode) 605 { 606 range.moveToElementText(node.parentNode); 607 } else 608 { 609 range.moveToElementText(this._doc.body); 610 } 611 var trimmingRange = this._doc.body.createTextRange(); 612 613 // In rare situations (mostly html that's been monkeyed about with by 614 // javascript, but that's what we're doing) there can be two adjacent 615 // text nodes. Since we won't be able to handle these, we'll have to 616 // hack an offset by 'move'ing the number of characters they contain. 617 var texthackOffset = 0; 618 var borderElement=node.previousSibling; 619 for (; borderElement && (1 != borderElement.nodeType); borderElement = borderElement.previousSibling) 620 { 621 if (3 == borderElement.nodeType) 622 { 623 // IE doesn't count '\r' as a character, so we have to adjust the offset. 624 texthackOffset += borderElement.nodeValue.length-borderElement.nodeValue.split('\r').length-1; 625 } 626 } 627 if (borderElement && (1 == borderElement.nodeType)) 628 { 629 trimmingRange.moveToElementText(borderElement); 630 range.setEndPoint('StartToEnd', trimmingRange); 631 } 632 if (texthackOffset) 633 { 634 // We now need to move the selection forward the number of characters 635 // in all text nodes in between our text node and our ranges starting 636 // border. 637 range.moveStart('character',texthackOffset); 638 } 639 640 // Youpi! Now we get to repeat this trimming on the right side. 641 texthackOffset = 0; 642 borderElement=node.nextSibling; 643 for (; borderElement && (1 != borderElement.nodeType); borderElement = borderElement.nextSibling) 644 { 645 if (3 == borderElement.nodeType) 646 { 647 // IE doesn't count '\r' as a character, so we have to adjust the offset. 648 texthackOffset += borderElement.nodeValue.length-borderElement.nodeValue.split('\r').length-1; 649 if (!borderElement.nextSibling) 650 { 651 // When a text node is the last child, IE adds an extra selection 652 // "placeholder" for the newline character. We need to adjust for 653 // this character as well. 654 texthackOffset += 1; 655 } 656 } 657 } 658 if (borderElement && (1 == borderElement.nodeType)) 659 { 660 trimmingRange.moveToElementText(borderElement); 661 range.setEndPoint('EndToStart', trimmingRange); 662 } 663 if (texthackOffset) 664 { 665 // We now need to move the selection backward the number of characters 666 // in all text nodes in between our text node and our ranges ending 667 // border. 668 range.moveEnd('character',-texthackOffset); 669 } 670 if (!node.nextSibling) 671 { 672 // Above we performed a slight adjustment to the offset if the text 673 // node contains a selectable "newline". We need to do the same if the 674 // node we are trying to select contains a newline. 675 range.moveEnd('character',-1); 676 } 677 } 678 else 679 { 469 680 range.moveToElementText(node); 470 //(collapsed) && range.collapse(pos); 681 } 682 } 683 if (typeof collapseToStart != "undefined") 684 { 685 range.collapse(collapseToStart); 686 if (!collapseToStart) 687 { 688 range.moveStart('character',-1); 689 range.moveEnd('character',-1); 690 } 471 691 } 472 692 range.select(); -
trunk/modules/Opera/Opera.js
r1001 r1044 576 576 * 577 577 * @param node DomNode 578 * @param pos Set to a numeric position inside the node to collapse the cursor here if possible.579 */ 580 581 Xinha.prototype.selectNodeContents = function(node, pos)578 * @param collapseToStart A boolean that, when supplied, says to collapse the selection. True collapses to the start, and false to the end. 579 */ 580 581 Xinha.prototype.selectNodeContents = function(node, collapseToStart) 582 582 { 583 583 this.focusEditor(); 584 584 this.forceRedraw(); 585 585 var range; 586 var collapsed = typeof pos== "undefined" ? true : false;586 var collapsed = typeof collapseToStart == "undefined" ? true : false; 587 587 var sel = this.getSelection(); 588 588 range = this._doc.createRange(); … … 595 595 { 596 596 range.selectNodeContents(node); 597 //(collapsed) && range.collapse(pos);598 597 } 599 598 sel.removeAllRanges(); 600 599 sel.addRange(range); 600 if (typeof collapseToStart != "undefined") 601 { 602 if (collapseToStart) 603 { 604 sel.collapse(range.startContainer, range.startOffset); 605 } else 606 { 607 sel.collapse(range.endContainer, range.endOffset); 608 } 609 } 601 610 }; 602 611 -
trunk/modules/WebKit/WebKit.js
r1001 r1044 574 574 * 575 575 * @param node DomNode 576 * @param pos Set to a numeric position inside the node to collapse the cursor here if possible.577 */ 578 579 Xinha.prototype.selectNodeContents = function(node, pos)576 * @param collapseToStart A boolean that, when supplied, says to collapse the selection. True collapses to the start, and false to the end. 577 */ 578 579 Xinha.prototype.selectNodeContents = function(node, collapseToStart) 580 580 { 581 581 this.focusEditor(); 582 582 this.forceRedraw(); 583 583 var range; 584 var collapsed = typeof pos== "undefined" ? true : false;584 var collapsed = typeof collapseToStart == "undefined" ? true : false; 585 585 var sel = this.getSelection(); 586 586 range = this._doc.createRange(); … … 593 593 { 594 594 range.selectNodeContents(node); 595 //(collapsed) && range.collapse(pos);596 595 } 597 596 sel.removeAllRanges(); 598 597 sel.addRange(range); 598 if (typeof collapseToStart != "undefined") 599 { 600 if (collapseToStart) 601 { 602 sel.collapse(range.startContainer, range.startOffset); 603 } else 604 { 605 sel.collapse(range.endContainer, range.endOffset); 606 } 607 } 599 608 }; 600 609 … … 685 694 Xinha.prototype.isKeyEvent = function(event) 686 695 { 687 return event.type == "key press";696 return event.type == "keydown"; 688 697 } 689 698 -
trunk/plugins/Abbreviation/abbreviation.js
r999 r1044 15 15 cfg.registerButton({ 16 16 id : "abbreviation", 17 tooltip : this._lc("Abbreviation"),17 tooltip : Xinha._lc("Abbreviation", "Abbreviation"), 18 18 image : editor.imgURL("ed_abbreviation.gif", "Abbreviation"), 19 19 textMode : false, 20 20 action : function(editor) { 21 self. buttonPress(editor);21 self.show(); 22 22 } 23 }) 23 }); 24 24 cfg.addToolbarElement("abbreviation", "inserthorizontalrule", 1); 25 25 } … … 36 36 }; 37 37 38 Abbreviation.prototype._lc = function(string) { 39 return Xinha._lc(string, 'Abbreviation'); 38 // Fills in the text field if the acronym is either known (i.e., in the [lang].js file) 39 // or if we're editing an existing abbreviation. 40 Abbreviation.prototype.fillText = function() { 41 var editor = this.editor; 42 var text = this.html.toUpperCase(); 43 var abbr = Xinha.getPluginDir(this.constructor.name) + "/abbr/" + _editor_lang + ".js"; 44 var abbrData = Xinha._geturlcontent(abbr); 45 46 if (abbrData) { 47 eval('abbrObj = ' + abbrData); 48 if (abbrObj != "") { 49 var dest = this.dialog.getElementById("title"); 50 dest.value = this.title || ""; 51 for (var i in abbrObj) { 52 same = (i.toUpperCase()==text); 53 if (same) 54 dest.value = abbrObj[i]; 55 } 56 } 57 } 58 } 59 60 Abbreviation.prototype.onGenerateOnce = function(editor) { 61 this.editor.addEditorStylesheet(Xinha.getPluginDir('Abbreviation') + '/abbreviation.css'); 62 this.methodsReady = true; //remove this? 63 var self = Abbreviation; 64 Xinha._getback(Xinha.getPluginDir('Abbreviation') + '/dialog.html', function(getback) { self.html = getback; self.dialogReady = true; }); 40 65 }; 41 66 42 Abbreviation.prototype.onGenerate = function() { 43 this.editor.addEditorStylesheet(Xinha.getPluginDir('Abbreviation') + '/abbreviation.css'); 44 }; 67 Abbreviation.prototype.OnUpdateToolbar = function(editor) { 68 if (!(Abbreviation.dialogReady && Abbreviation.methodsReady)) 69 { 70 this.editor._toolbarObjects.Abbreviation.state("enabled", false); 71 } 72 else this.onUpdateToolbar = null; 73 } 45 74 46 Abbreviation.prototype.buttonPress = function(editor, context, updatecontextclass) { 47 var outparam = null; 48 var html = editor.getSelectedHTML(); 75 Abbreviation.prototype.prepareDialog = function(html) { 76 var self = this; 77 var editor = this.editor; 78 var dialog = this.dialog = new Xinha.Dialog(editor, Abbreviation.html, 'Xinha', {width: 260, height:140}); 79 80 dialog.getElementById('ok').onclick = function() { self.apply(); }; 81 dialog.getElementById('delete').onclick = function() { self.ondelete(); }; 82 dialog.getElementById('cancel').onclick = function() { self.dialog.hide(); }; 83 84 this.dialogReady = true; 85 } 86 87 Abbreviation.prototype.show = function(editor) { 88 var editor = this.editor; 89 this.html = editor.getSelectedHTML(); 90 if (!this.dialog) this.prepareDialog(); 91 var self = this; 92 var doc = editor._doc; 49 93 var sel = editor._getSelection(); 50 94 var range = editor._createRange(sel); 51 95 var abbr = editor._activeElement(sel); 96 52 97 if(!(abbr != null && abbr.tagName.toLowerCase() == "abbr")) { 53 98 abbr = editor._getFirstAncestor(sel, 'abbr'); 54 99 } 55 if (abbr != null && abbr.tagName.toLowerCase() == "abbr") 56 outparam = { title : abbr.title, 57 text : abbr.innerHTML}; 58 else 59 outparam = { title : '', 60 text : html}; 100 this.abbr = abbr; 101 102 if (abbr) this.title = abbr.title; 103 this.fillText(); 61 104 62 editor._popupDialog( "plugin://Abbreviation/abbreviation", function( param ) { 63 if ( param ) { 64 var title = param["title"]; 65 if (title == "" || title == null) { 66 if (abbr) { 67 var child = abbr.innerHTML; 68 abbr.parentNode.removeChild(abbr); 69 editor.insertHTML(child); 105 this.dialog.getElementById("inputs").onsubmit = function() { 106 self.apply(); 107 return false; 108 } 109 110 this.dialog.show(); 111 this.dialog.getElementById("title").select(); 112 } 113 114 Abbreviation.prototype.apply = function() { 115 var editor = this.editor; 116 var doc = editor._doc; 117 var abbr = this.abbr; 118 var html = this.html; 119 var param = this.dialog.hide(); 120 121 if ( param ) { 122 var title = param["title"]; 123 if (title == "" || title == null) { 124 if (abbr) { 125 var child = abbr.innerHTML; 126 abbr.parentNode.removeChild(abbr); 127 editor.insertHTML(child); // FIX: This doesn't work in Safari 3 128 } 129 return; 130 } 131 try { 132 if (!abbr) { 133 abbr = doc.createElement("abbr"); 134 abbr.title = title; 135 abbr.innerHTML = html; 136 if (Xinha.is_ie) { 137 range.pasteHTML(abbr.outerHTML); 138 } else { 139 editor.insertNodeAtSelection(abbr); 70 140 } 71 return; 141 } else { 142 abbr.title = title; 72 143 } 73 try {74 var doc = editor._doc;75 if (!abbr) {76 abbr = doc.createElement("abbr");77 abbr.title = title;78 abbr.innerHTML = html;79 if (Xinha.is_ie) {80 range.pasteHTML(abbr.outerHTML);81 } else {82 editor.insertNodeAtSelection(abbr);83 }84 } else {85 abbr.title = title;86 }87 }88 catch (e) { }89 144 } 90 }, outparam); 91 }; 145 catch (e) { } 146 } 147 } 148 149 150 Abbreviation.prototype.ondelete = function() { 151 this.dialog.getElementById('title').value = ""; 152 this.apply(); 153 } -
trunk/plugins/BackgroundImage/background-image.js
r856 r1044 9 9 function BackgroundImage(editor) { 10 10 this.editor = editor; 11 var cfg = editor.config;12 var self = this;11 var cfg = editor.config; 12 var self = this; 13 13 cfg.registerButton({ 14 id : "bgImage",15 tooltip : this._lc("Set page background image"),16 image : editor.imgURL("ed_bgimage.gif", "BackgroundImage"),17 textMode : false,18 action : function(editor) {19 self.buttonPress(editor);20 }21 })22 cfg.addToolbarElement("bgImage", "inserthorizontalrule", 1);14 id : "bgImage", 15 tooltip : Xinha._lc("Set page background image", 'BackgroundImage'), 16 image : editor.imgURL("ed_bgimage.gif", "BackgroundImage"), 17 textMode : false, 18 action : function(editor) { 19 self.show(); 20 } 21 }) 22 cfg.addToolbarElement("bgImage", "inserthorizontalrule", 1); 23 23 } 24 24 25 25 BackgroundImage._pluginInfo = { 26 name : "BackgroundImage",27 version : "1.0",28 developer : "Udo Schmal",29 developer_url : "http://www.schaffrath-neuemedien.de/",30 c_owner : "Udo Schmal & Schaffrath NeueMedien",31 sponsor : "L.N.Schaffrath NeueMedien",32 sponsor_url : "http://www.schaffrath-neuemedien.de.de/",33 license : "htmlArea"26 name : "BackgroundImage", 27 version : "1.0", 28 developer : "Udo Schmal", 29 developer_url : "http://www.schaffrath-neuemedien.de/", 30 c_owner : "Udo Schmal & Schaffrath NeueMedien", 31 sponsor : "L.N.Schaffrath NeueMedien", 32 sponsor_url : "http://www.schaffrath-neuemedien.de.de/", 33 license : "htmlArea" 34 34 }; 35 35 36 BackgroundImage.prototype._lc = function(string) { 37 return Xinha._lc(string, 'BackgroundImage'); 36 BackgroundImage.prototype.onGenerateOnce = function(editor){ 37 // Load assets 38 var self = BackgroundImage; 39 if (self.loading) return; 40 41 // A list of jpgs that are expected to be in ./backgrounds with thumbnails. 42 var backgrounds = {blufur:'',palecnvs:'', ppplcnvs:'', ylwsand:''}; 43 44 self.loading = true; 45 self.methodsReady = true; 46 47 // When we get back from loading the dialog, we'll process our image template to handle as many images as specified. 48 Xinha._getback(_editor_url + 'plugins/BackgroundImage/dialog.html', function(getback) { 49 50 // Replace the template line with one line per image. 51 self.html = getback.replace(/<template>(.*?)<\/template>/ig, function(fullString, template) { 52 var replacement = ''; 53 54 for (bg in backgrounds) 55 { 56 var thumbURL = _editor_url + 'plugins/BackgroundImage/backgrounds/thumbnails/' + bg + '.jpg'; 57 var imageURL = _editor_url + 'plugins/BackgroundImage/backgrounds/' + bg + '.jpg'; 58 replacement += template.replace(/%thumbnail%/,thumbURL).replace(/%image%/,imageURL); 59 } 60 return replacement; 61 }); 62 self.dialogReady = true; 63 }); 64 } 65 66 BackgroundImage.prototype.onUpdateToolbar = function(editor){ 67 // Keep our toolbar image greyed until we're fully loaded. 68 if (!(BackgroundImage.dialogReady && BackgroundImage.methodsReady)) 69 { 70 this.editor._toolbarObjects.BackgroundImage.state("enabled", false); 71 } 72 else this.onUpdateToolbar = null; 73 74 } 75 76 BackgroundImage.prototype.prepareDialog = function(editor){ 77 var self = this; 78 var editor = this.editor; 79 80 var dialog = this.dialog = new Xinha.Dialog(editor, BackgroundImage.html, 'Xinha',{width:400}) 81 // 82 // Hookup the buttons with our actions 83 dialog.getElementById('set').onclick = function() {self.apply();} 84 dialog.getElementById('delete').onclick = function() {self.deleteBg();} 85 dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 86 87 this.dialogReady = true; 88 } 89 90 BackgroundImage.prototype.show = function(editor){ 91 if (!this.dialog) this.prepareDialog(); 92 93 var editor = this.editor; 94 95 // After clearing the background property, it returns the current URL, and so 96 // we need to check the extension to find out if it really has a background. 97 if (editor._doc.body.background.split('.').pop() in {jpg:'', gif:'', png:'', jpeg:'', tiff:''}) 98 { 99 var background = editor._doc.body.background; 100 } 101 else 102 { 103 var background = ''; 104 } 105 var values = 106 { 107 "background" : background 108 } 109 110 // now calling the show method of the Xinha.Dialog object to set the values and show the actual dialog 111 this.dialog.show(values); 112 } 113 114 BackgroundImage.prototype.deleteBg = function(){ 115 var editor = this.editor; 116 this.dialog.hide(); 117 118 if (Xinha.is_ie) 119 editor.focusEditor(); 120 121 editor._doc.body.background = ""; 122 } 123 124 BackgroundImage.prototype.apply = function(){ 125 var editor = this.editor; 126 var doc = editor._doc; 127 128 // selection is only restored on dialog.hide() 129 var param = this.dialog.hide(); 130 // assign the given arguments 131 132 if (Xinha.is_ie) 133 editor.focusEditor(); 134 135 doc.body.background = param.background; 38 136 }; 39 40 BackgroundImage.prototype.buttonPress = function(editor) {41 //var doc = this.editor._doc;42 editor._popupDialog( "plugin://BackgroundImage/bgimage", function( bgImage ) {43 if(bgImage) {44 if(Xinha.is_ie) editor.focusEditor();45 if(bgImage=="*") {46 editor._doc.body.background = "";47 } else {48 editor._doc.body.background = bgImage;49 }50 }51 }, null);52 }; -
trunk/plugins/CharacterMap/CharacterMap.css
r677 r1044 1 .CharacterMap { } 1 .CharacterMap { 2 background-color:white; 3 } 2 4 .CharacterMap a.entity { 3 5 font-size:12px; -
trunk/plugins/CharacterMap/character-map.js
r856 r1044 14 14 image : editor.imgURL( 'ed_charmap.gif', 'CharacterMap' ), 15 15 textMode : false, 16 action : function( editor ) { self.buttonPress( editor); }16 action : function() { self.show(); } 17 17 } 18 18 ); 19 19 cfg.addToolbarElement('insertcharacter', 'createlink', -1); 20 20 21 if ( cfg.CharacterMap.mode == 'panel' )22 {23 editor._CharacterMap = editor.addPanel( 'right' );24 Xinha._addClass( editor._CharacterMap, 'CharacterMap' );25 26 editor.notifyOn( 'modechange',27 function( e, args )28 {29 if ( args.mode == 'text' ) editor.hidePanel( editor._CharacterMap );30 }31 );32 33 var entites =34 [35 'Ÿ', 'š', '@', '"', '¡', '¢', '£', '¤', '¥', '¦',36 '§', '¨', '©', 'ª', '«', '¬', '¯', '°', '±', '²',37 '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼',38 '½', '¾', '¿', '×', 'Ø', '÷', 'ø', 'ƒ', 'ˆ',39 '˜', '–', '—', '‘', '’', '‚', '“', '”', '„',40 '†', '‡', '•', '…', '‰', '‹', '›', '€', '™',41 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È',42 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ',43 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '®', '×', 'Ù', 'Ú',44 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã',45 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì',46 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ',47 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ',48 'ÿ', 'Œ', 'œ', 'Š'49 ];50 51 for ( var i=0; i<entites.length; i++ )52 this.addEntity( entites[i], i );53 54 editor.hidePanel( editor._CharacterMap );55 }56 21 } 57 22 … … 76 41 CharacterMap._isActive = false; 77 42 78 CharacterMap.prototype.buttonPress = function( editor )79 {80 var cfg = editor.config;81 if ( cfg.CharacterMap.mode == 'panel' )82 {83 if ( this._isActive )84 {85 this._isActive = false;86 editor.hidePanel( editor._CharacterMap );87 }88 else89 {90 this._isActive = true;91 editor.showPanel( editor._CharacterMap );92 }93 }94 else95 {96 editor._popupDialog( "plugin://CharacterMap/select_character", function( entity )97 {98 if ( !entity ) return false;99 if ( Xinha.is_ie ) editor.focusEditor();100 editor.insertHTML( entity );101 }, null);102 }103 };104 43 105 44 CharacterMap.prototype.addEntity = function ( entite, pos ) … … 120 59 return false; 121 60 }; 122 editor._CharacterMap.appendChild( a );61 this.dialog.main.appendChild( a ); 123 62 a = null; 124 63 }; 64 65 CharacterMap.prototype.onGenerateOnce = function() 66 { 67 this._prepareDialog(); 68 }; 69 70 CharacterMap.prototype._prepareDialog = function() 71 { 72 var self = this; 73 var editor = this.editor; 74 75 var html = '<h1><l10n>Insert special character</l10n></h1>'; 76 77 // Now we have everything we need, so we can build the dialog. 78 this.dialog = new Xinha.Dialog(editor, html, 'CharacterMap',{width:300},{modal:false}); 79 Xinha._addClass( this.dialog.rootElem, 'CharacterMap' ); 80 81 if (editor.config.CharacterMap.mode == 'panel') this.dialog.attachToPanel('right'); 82 83 var entites = 84 [ 85 'Ÿ', 'š', '@', '"', '¡', '¢', '£', '¤', '¥', '¦', 86 '§', '¨', '©', 'ª', '«', '¬', '¯', '°', '±', '²', 87 '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', 88 '½', '¾', '¿', '×', 'Ø', '÷', 'ø', 'ƒ', 'ˆ', 89 '˜', '–', '—', '‘', '’', '‚', '“', '”', '„', 90 '†', '‡', '•', '…', '‰', '‹', '›', '€', '™', 91 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 92 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 93 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '®', '×', 'Ù', 'Ú', 94 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 95 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 96 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 97 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 98 'ÿ', 'Œ', 'œ', 'Š' 99 ]; 100 101 for ( var i=0; i<entites.length; i++ ) 102 { 103 this.addEntity( entites[i], i ); 104 } 105 106 this.ready = true; 107 //this.hide(); 108 }; 109 110 CharacterMap.prototype.show = function() 111 { 112 if(!this.ready) // if the user is too fast clicking the, we have to make them wait 113 { 114 var self = this; 115 window.setTimeout(function() {self.show();},100); 116 return; 117 } 118 this.dialog.toggle(); 119 }; 120 CharacterMap.prototype.hide = function() 121 { 122 this.dialog.hide(); 123 }; 124 -
trunk/plugins/InsertAnchor/insert-anchor.js
r999 r1044 12 12 image : editor.imgURL("insert-anchor.gif", "InsertAnchor"), 13 13 textMode : false, 14 action : function( editor) {15 self. buttonPress(editor);14 action : function() { 15 self.show(); 16 16 } 17 17 }); … … 50 50 return html; 51 51 } 52 InsertAnchor.prototype.onGenerateOnce = function() 53 { 54 this._prepareDialog(); 55 }; 56 InsertAnchor.prototype._prepareDialog = function() 57 { 58 var self = this; 59 var editor = this.editor; 52 60 53 InsertAnchor.prototype.buttonPress = function(editor) { 54 var outparam = null; 55 var html = editor.getSelectedHTML(); 56 var sel = editor._getSelection(); 57 var range = editor._createRange(sel); 61 if(!this.html) 62 { 63 Xinha._getback(Xinha.getPluginDir("InsertAnchor") + '/dialog.html', function(getback) { self.html = getback; self._prepareDialog(); }); 64 return; 65 } 66 67 // Now we have everything we need, so we can build the dialog. 68 this.dialog = new Xinha.Dialog(editor, this.html, 'InsertAnchor',{width:400}); 69 70 this.dialog.getElementById('ok').onclick = function() {self.apply();} 71 72 this.dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 73 74 this.ready = true; 75 }; 76 77 InsertAnchor.prototype.show = function() 78 { 79 if(!this.ready) // if the user is too fast clicking the, we have to make them wait 80 { 58 81 var self = this; 59 var a = editor._activeElement(sel); 60 if(!(a != null && a.tagName.toLowerCase() == 'a')) { 61 a = editor._getFirstAncestor(sel, 'a'); 82 window.setTimeout(function() {self.show();},100); 83 return; 62 84 } 63 if (a != null && a.tagName.toLowerCase() == 'a') 64 outparam = { name : a.id }; 85 var editor = this.editor; 86 this.selectedHTML = editor.getSelectedHTML(); 87 var sel = editor.getSelection(); 88 var range = editor.createRange(sel); 89 this.a = editor.activeElement(sel); 90 91 if(!(this.a != null && this.a.tagName.toLowerCase() == 'a')) 92 { 93 this.a = editor._getFirstAncestor(sel, 'a'); 94 } 95 96 if (this.a != null && this.a.tagName.toLowerCase() == 'a') 97 { 98 inputs = { name : this.a.id }; 99 } 65 100 else 66 outparam = { name : '' }; 101 { 102 inputs = { name : '' }; 103 } 67 104 68 editor._popupDialog( "plugin://InsertAnchor/insert_anchor", function( param ) { 69 if ( param ) { 70 var anchor = param["name"]; 71 if (anchor == "" || anchor == null) { 72 if (a) { 105 this.dialog.show(inputs); 106 107 this.dialog.getElementById("name").focus(); 108 }; 109 110 InsertAnchor.prototype.apply = function () 111 { 112 var editor = this.editor; 113 var param = this.dialog.hide(); 114 var anchor = param['name']; 115 var a = this.a; 116 var self = this; 117 if (anchor == "" || anchor == null) 118 { 119 if (a) 120 { 73 121 var child = self.outwardHtml(a.innerHTML); 74 122 a.parentNode.removeChild(a); … … 76 124 } 77 125 return; 78 } 79 try { 126 } 127 try 128 { 80 129 var doc = editor._doc; 81 if (!a) { 82 // editor.surroundHTML('<a id="' + anchor + '" name="' + anchor + '" title="' + anchor + '" class="anchor">', '</a>'); 130 if (!a) 131 { 83 132 a = doc.createElement("a"); 84 133 a.id = anchor; … … 87 136 a.className = "anchor"; 88 137 a.innerHTML = self.placeholderImg; 138 var html = editor.getSelectedHTML(); 89 139 if (html) a.innerHTML += html; 90 if (Xinha.is_ie) { 140 if (Xinha.is_ie) 141 { 91 142 range.pasteHTML(a.outerHTML); 92 } else { 143 } 144 else 145 { 93 146 editor.insertNodeAtSelection(a); 94 147 } 95 } else { 148 } 149 else 150 { 96 151 a.id = anchor; 97 152 a.name = anchor; … … 101 156 } 102 157 catch (e) { } 158 103 159 } 104 }, outparam);105 }; -
trunk/plugins/Linker/linker.js
r1027 r1044 51 51 }; 52 52 53 Linker.prototype._createLink = function(a)54 {55 if(!a && this.editor.selectionEmpty(this.editor.getSelection()))56 {57 alert(this._lc("You must select some text before making a new link."));58 return false;59 }60 61 var inputs =62 {63 type: 'url',64 href: 'http://www.example.com/',65 target: '',66 p_width: '',67 p_height: '',68 p_options: ['menubar=no','toolbar=yes','location=no','status=no','scrollbars=yes','resizeable=yes'],69 to: 'alice@example.com',70 subject: '',71 body: '',72 anchor: ''73 };74 75 if(a && a.tagName.toLowerCase() == 'a')76 {77 var href =this.editor.fixRelativeLinks(a.getAttribute('href'));78 var m = href.match(/^mailto:(.*@[^?&]*)(\?(.*))?$/);79 var anchor = href.match(/^#(.*)$/);80 81 if(m)82 {83 // Mailto84 inputs.type = 'mailto';85 inputs.to = m[1];86 if(m[3])87 {88 var args = m[3].split('&');89 for(var x = 0; x<args.length; x++)90 {91 var j = args[x].match(/(subject|body)=(.*)/);92 if(j)93 {94 inputs[j[1]] = decodeURIComponent(j[2]);95 }96 }97 }98 }99 else if (anchor)100 {101 //Anchor-Link102 inputs.type = 'anchor';103 inputs.anchor = anchor[1];104 105 }106 else107 {108 109 110 if(a.getAttribute('onclick'))111 {112 var m = a.getAttribute('onclick').match(/window\.open\(\s*this\.href\s*,\s*'([a-z0-9_]*)'\s*,\s*'([a-z0-9_=,]*)'\s*\)/i);113 114 // Popup Window115 inputs.href = href ? href : '';116 inputs.target = 'popup';117 inputs.p_name = m[1];118 inputs.p_options = [ ];119 120 121 var args = m[2].split(',');122 for(var x = 0; x < args.length; x++)123 {124 var i = args[x].match(/(width|height)=([0-9]+)/);125 if(i)126 {127 inputs['p_' + i[1]] = parseInt(i[2]);128 }129 else130 {131 inputs.p_options.push(args[x]);132 }133 }134 }135 else136 {137 // Normal138 inputs.href = href;139 inputs.target = a.target;140 }141 }142 }143 144 var linker = this;145 146 // If we are not editing a link, then we need to insert links now using execCommand147 // because for some reason IE is losing the selection between now and when doOK is148 // complete. I guess because we are defocusing the iframe when we click stuff in the149 // linker dialog.150 151 this.a = a; // Why doesn't a get into the closure below, but if I set it as a property then it's fine?152 153 var doOK = function()154 {155 //if(linker.a) alert(linker.a.tagName);156 var a = linker.a;157 158 var values = linker._dialog.hide();159 var atr =160 {161 href: '',162 target:'',163 title:'',164 onclick:''165 };166 167 if(values.type == 'url')168 {169 if(values.href)170 {171 atr.href = values.href;172 atr.target = values.target;173 if(values.target == 'popup')174 {175 176 if(values.p_width)177 {178 values.p_options.push('width=' + values.p_width);179 }180 if(values.p_height)181 {182 values.p_options.push('height=' + values.p_height);183 }184 atr.onclick = 'if(window.top && window.top.Xinha){return false}window.open(this.href, \'' + (values.p_name.replace(/[^a-z0-9_]/i, '_')) + '\', \'' + values.p_options.join(',') + '\');return false;';185 }186 }187 }188 else if(values.type == 'anchor')189 {190 if(values.anchor)191 {192 atr.href = values.anchor.value;193 }194 }195 else196 {197 if(values.to)198 {199 atr.href = 'mailto:' + values.to;200 if(values.subject) atr.href += '?subject=' + encodeURIComponent(values.subject);201 if(values.body) atr.href += (values.subject ? '&' : '?') + 'body=' + encodeURIComponent(values.body);202 }203 }204 205 if (atr.href) atr.href = atr.href.trim();206 207 if(a && a.tagName.toLowerCase() == 'a')208 {209 if(!atr.href)210 {211 if(confirm(linker._dialog._lc('Are you sure you wish to remove this link?')))212 {213 var p = a.parentNode;214 while(a.hasChildNodes())215 {216 p.insertBefore(a.removeChild(a.childNodes[0]), a);217 }218 p.removeChild(a);219 linker.editor.updateToolbar();220 return;221 }222 }223 else224 {225 // Update the link226 for(var i in atr)227 {228 a.setAttribute(i, atr[i]);229 }230 231 // If we change a mailto link in IE for some hitherto unknown232 // reason it sets the innerHTML of the link to be the233 // href of the link. Stupid IE.234 if(Xinha.is_ie)235 {236 if(/mailto:([^?<>]*)(\?[^<]*)?$/i.test(a.innerHTML))237 {238 a.innerHTML = RegExp.$1;239 }240 }241 }242 }243 else244 {245 if(!atr.href) return true;246 247 // Insert a link, we let the browser do this, we figure it knows best248 var tmp = Xinha.uniq('http://www.example.com/Link');249 linker.editor._doc.execCommand('createlink', false, tmp);250 251 // Fix them up252 var anchors = linker.editor._doc.getElementsByTagName('a');253 for(var i = 0; i < anchors.length; i++)254 {255 var anchor = anchors[i];256 if(anchor.href == tmp)257 {258 // Found one.259 if (!a) a = anchor;260 for(var j in atr)261 {262 anchor.setAttribute(j, atr[j]);263 }264 }265 }266 }267 linker.editor.selectNodeContents(a);268 linker.editor.updateToolbar();269 };270 271 this._dialog.show(inputs, doOK);272 273 };274 275 Linker.prototype._getSelectedAnchor = function()276 {277 var sel = this.editor.getSelection();278 var rng = this.editor.createRange(sel);279 var a = this.editor.activeElement(sel);280 if(a != null && a.tagName.toLowerCase() == 'a')281 {282 return a;283 }284 else285 {286 a = this.editor._getFirstAncestor(sel, 'a');287 if(a != null)288 {289 return a;290 }291 }292 return null;293 };294 53 295 54 Linker.prototype.onGenerateOnce = function() 296 55 { 297 this._dialog = new Linker.Dialog(this); 56 Linker.loadAssets(); 57 this.loadFiles(); 298 58 }; 299 // Inline Dialog for Linker 59 60 Linker.prototype.onUpdateToolbar = function() 61 { 62 if (typeof dTree == 'undefined' || !Linker.methodsReady || !Linker.html || !this.files) 63 { 64 this.editor._toolbarObjects.createlink.state("enabled", false); 65 } 66 else this.onUpdateToolbar = null; 67 }; 300 68 301 69 Linker.Dialog_dTrees = [ ]; 302 70 71 Linker.loadAssets = function() 72 { 73 var self = Linker; 74 if (self.loading) return; 75 self.loading = true; 76 Xinha._getback(Xinha.getPluginDir("Linker") + '/pluginMethods.js', function(getback) { eval(getback); self.methodsReady = true; }); 77 Xinha._loadback( Xinha.getPluginDir("Linker") + '/dTree/dtree.js', function() {Linker.dTreeReady = true; } ); 78 Xinha._getback( Xinha.getPluginDir("Linker") + '/dialog.html', function(getback) { self.html = getback; } ); 79 } 303 80 304 Linker. Dialog = function (linker)81 Linker.prototype.loadFiles = function() 305 82 { 306 var lDialog = this; 307 this.Dialog_nxtid = 0; 308 this.linker = linker; 309 this.id = { }; // This will be filled below with a replace, nifty 310 311 this.ready = false; 312 this.files = false; 313 this.html = false; 314 this.dialog = false; 315 316 // load the dTree script 317 this._prepareDialog(); 318 319 }; 320 321 Linker.Dialog.prototype._prepareDialog = function() 322 { 323 var lDialog = this; 324 var linker = this.linker; 325 326 // We load some stuff up int he background, recalling this function 327 // when they have loaded. This is to keep the editor responsive while 328 // we prepare the dialog. 329 if(typeof dTree == 'undefined') 330 { 331 Xinha._loadback(Xinha.getPluginDir("Linker") + '/dTree/dtree.js', 332 function() {lDialog._prepareDialog(); } 333 ); 334 return; 335 } 336 337 if(this.files === false) 338 { 83 var linker = this; 339 84 if(linker.lConfig.backend) 340 85 { 341 //get files from backend342 Xinha._postback(linker.lConfig.backend,343 linker.lConfig.backend_data,86 //get files from backend 87 Xinha._postback(linker.lConfig.backend, 88 linker.lConfig.backend_data, 344 89 function(txt) { 345 90 try { 346 l Dialog.files = eval(txt);91 linker.files = eval(txt); 347 92 } catch(Error) { 348 l Dialog.files = [ {url:'',title:Error.toString()} ];93 linker.files = [ {url:'',title:Error.toString()} ]; 349 94 } 350 lDialog._prepareDialog();});95 }); 351 96 } 352 97 else if(linker.lConfig.files != null) 353 98 { 354 99 //get files from plugin-config 355 lDialog.files = linker.lConfig.files; 356 lDialog._prepareDialog(); 100 linker.files = linker.lConfig.files; 357 101 } 358 return; 359 } 360 var files = this.files; 361 362 if(this.html == false) 363 { 364 Xinha._getback(Xinha.getPluginDir("Linker") + '/dialog.html', function(txt) { lDialog.html = txt; lDialog._prepareDialog(); }); 365 return; 366 } 367 var html = this.html; 368 369 // Now we have everything we need, so we can build the dialog. 370 var dialog = this.dialog = new Xinha.Dialog(linker.editor, this.html, 'Linker'); 371 var dTreeName = Xinha.uniq('dTree_'); 372 373 this.dTree = new dTree(dTreeName, Xinha.getPluginDir("Linker") + '/dTree/'); 374 eval(dTreeName + ' = this.dTree'); 375 376 this.dTree.add(this.Dialog_nxtid++, -1, linker.lConfig.treeCaption , null, linker.lConfig.treeCaption); 377 this.makeNodes(files, 0); 378 379 // Put it in 380 var ddTree = this.dialog.getElementById('dTree'); 381 //ddTree.innerHTML = this.dTree.toString(); 382 ddTree.innerHTML = ''; 383 ddTree.style.position = 'absolute'; 384 ddTree.style.left = 1 + 'px'; 385 ddTree.style.top = 0 + 'px'; 386 ddTree.style.overflow = 'auto'; 387 ddTree.style.backgroundColor = 'white'; 388 this.ddTree = ddTree; 389 this.dTree._linker_premade = this.dTree.toString(); 390 391 var options = this.dialog.getElementById('options'); 392 options.style.position = 'absolute'; 393 options.style.top = 0 + 'px'; 394 options.style.right = 0 + 'px'; 395 options.style.width = 320 + 'px'; 396 options.style.overflow = 'auto'; 397 398 // Hookup the resizer 399 this.dialog.onresize = function() 400 { 401 var h = parseInt(dialog.height) - dialog.getElementById('h1').offsetHeight; 402 var w = parseInt(dialog.width) - 322 ; 403 // An error is thrown with IE when trying to set a negative width or a negative height 404 // But perhaps a width / height of 0 is not the minimum required we need to set 405 if (w<0) w = 0; 406 if (h<0) h = 0; 407 options.style.height = ddTree.style.height = h + 'px'; 408 ddTree.style.width = w + 'px'; 409 } 410 411 this.ready = true; 412 }; 413 414 Linker.Dialog.prototype.makeNodes = function(files, parent) 415 { 416 for(var i = 0; i < files.length; i++) 417 { 418 if(typeof files[i] == 'string') 419 { 420 this.dTree.add(Linker.nxtid++, parent, 421 files[i].replace(/^.*\//, ''), 422 'javascript:document.getElementsByName(\'' + this.dialog.id.href + '\')[0].value=decodeURIComponent(\'' + encodeURIComponent(files[i]) + '\');document.getElementsByName(\'' + this.dialog.id.type + '\')[0].click();document.getElementsByName(\'' + this.dialog.id.href + '\')[0].focus();void(0);', 423 files[i]); 424 } 425 else if(typeof files[i]=="object" && files[i] && typeof files[i].length==="number") // there seems to be a strange bug in IE that requires this complicated check, see #1197 426 { 427 var id = this.Dialog_nxtid++; 428 this.dTree.add(id, parent, files[i][0].replace(/^.*\//, ''), null, files[i][0]); 429 this.makeNodes(files[i][1], id); 430 } 431 else if(typeof files[i] == 'object') 432 { 433 if(files[i].children) { 434 var id = this.Dialog_nxtid++; 435 } else { 436 var id = Linker.nxtid++; 437 } 438 439 if(files[i].title) var title = files[i].title; 440 else if(files[i].url) var title = files[i].url.replace(/^.*\//, ''); 441 else var title = "no title defined"; 442 if(files[i].url) var link = 'javascript:document.getElementsByName(\'' + this.dialog.id.href + '\')[0].value=decodeURIComponent(\'' + encodeURIComponent(files[i].url) + '\');document.getElementsByName(\'' + this.dialog.id.type + '\')[0].click();document.getElementsByName(\'' + this.dialog.id.href + '\')[0].focus();void(0);'; 443 else var link = ''; 444 445 this.dTree.add(id, parent, title, link, title); 446 if(files[i].children) { 447 this.makeNodes(files[i].children, id); 448 } 449 } 450 } 451 }; 452 453 Linker.Dialog.prototype._lc = Linker.prototype._lc; 454 455 Linker.Dialog.prototype.show = function(inputs, ok, cancel) 456 { 457 if(!this.ready) 458 { 459 var lDialog = this; 460 window.setTimeout(function() {lDialog.show(inputs,ok,cancel);},100); 461 return; 462 } 463 464 if(this.ddTree.innerHTML == '') 465 { 466 this.ddTree.innerHTML = this.dTree._linker_premade; 467 } 468 469 if(inputs.type=='url') 470 { 471 this.dialog.getElementById('urltable').style.display = ''; 472 this.dialog.getElementById('mailtable').style.display = 'none'; 473 this.dialog.getElementById('anchortable').style.display = 'none'; 474 } 475 else if(inputs.type=='anchor') 476 { 477 this.dialog.getElementById('urltable').style.display = 'none'; 478 this.dialog.getElementById('mailtable').style.display = 'none'; 479 this.dialog.getElementById('anchortable').style.display = ''; 480 } 481 else 482 { 483 this.dialog.getElementById('urltable').style.display = 'none'; 484 this.dialog.getElementById('mailtable').style.display = ''; 485 this.dialog.getElementById('anchortable').style.display = 'none'; 486 } 487 488 if(inputs.target=='popup') 489 { 490 this.dialog.getElementById('popuptable').style.display = ''; 491 } 492 else 493 { 494 this.dialog.getElementById('popuptable').style.display = 'none'; 495 } 496 497 var anchor = this.dialog.getElementById('anchor'); 498 for(var i=anchor.length;i>=0;i--) { 499 anchor[i] = null; 500 } 501 502 var html = this.linker.editor.getHTML(); 503 var anchors = new Array(); 504 505 var m = html.match(/<a[^>]+name="([^"]+)"/gi); 506 if(m) 507 { 508 for(i=0;i<m.length;i++) 509 { 510 var n = m[i].match(/name="([^"]+)"/i); 511 if(!anchors.contains(n[1])) anchors.push(n[1]); 512 } 513 } 514 m = html.match(/id="([^"]+)"/gi); 515 if(m) 516 { 517 for(i=0;i<m.length;i++) 518 { 519 n = m[i].match(/id="([^"]+)"/i); 520 if(!anchors.contains(n[1])) anchors.push(n[1]); 521 } 522 } 523 524 for(i=0;i<anchors.length;i++) 525 { 526 var opt = new Option(anchors[i],'#'+anchors[i],false,(inputs.anchor == anchors[i])); 527 anchor[anchor.length] = opt; 528 } 529 530 //if no anchors found completely hide Anchor-Link 531 if(anchor.length==0) { 532 this.dialog.getElementById('anchorfieldset').style.display = "none"; 533 } 534 535 // if we're not editing an existing link, hide the remove link button 536 if (inputs.href == 'http://www.example.com/' && inputs.to == 'alice@example.com') { 537 this.dialog.getElementById('clear').style.display = "none"; 538 } 539 else { 540 this.dialog.getElementById('clear').style.display = ""; 541 } 542 // Connect the OK and Cancel buttons 543 var dialog = this.dialog; 544 var lDialog = this; 545 if(ok) 546 { 547 this.dialog.getElementById('ok').onclick = ok; 548 } 549 else 550 { 551 this.dialog.getElementById('ok').onclick = function() {lDialog.hide();}; 552 } 553 554 if(cancel) 555 { 556 this.dialog.getElementById('cancel').onclick = cancel; 557 } 558 else 559 { 560 this.dialog.getElementById('cancel').onclick = function() { lDialog.hide()}; 561 } 562 563 // Show the dialog 564 this.linker.editor.disableToolbar(['fullscreen','linker']); 565 566 this.dialog.show(inputs); 567 568 // Init the sizes 569 this.dialog.onresize(); 570 }; 571 572 Linker.Dialog.prototype.hide = function() 573 { 574 this.linker.editor.enableToolbar(); 575 return this.dialog.hide(); 576 }; 102 } -
trunk/plugins/PasteText/lang/de.js
r677 r1044 2 2 // LANG: "de", ENCODING: UTF-8 3 3 { 4 "Paste as Plain Text": "unformatierten Text einfÌgen" 4 "Paste as Plain Text": "unformatierten Text einfÌgen", 5 "Insert text in new paragraph" : "Neue AbsÀtze eifÌgen" 5 6 }; -
trunk/plugins/PasteText/paste-text.js
r999 r1044 8 8 var cfg = editor.config; 9 9 var self = this; 10 10 11 11 cfg.registerButton({ 12 id : "pastetext", 13 tooltip : this._lc("Paste as Plain Text"), 14 image : editor.imgURL("ed_paste_text.gif", "PasteText"), 15 textMode : false, 16 action : function(editor) { 17 self.buttonPress(editor); 18 } 19 }); 12 id : "pastetext", 13 tooltip : this._lc("Paste as Plain Text"), 14 image : editor.imgURL("ed_paste_text.gif", "PasteText"), 15 textMode : false, 16 action : function() { self.show(); } 17 }); 20 18 21 19 cfg.addToolbarElement("pastetext", ["paste", "killword"], 1); … … 34 32 35 33 PasteText.prototype._lc = function(string) { 36 return Xinha._lc(string, 'PasteText');34 return Xinha._lc(string, 'PasteText'); 37 35 }; 38 36 … … 43 41 } 44 42 45 PasteText.prototype.buttonPress = function(editor) { 43 PasteText.prototype.onGenerateOnce = function() 44 { 45 var self = PasteText; 46 if (self.loading) return; 47 self.loading = true; 48 Xinha._getback(Xinha.getPluginDir("PasteText") + '/popups/paste_text.html', function(getback) { self.html = getback;}); 49 }; 46 50 51 PasteText.prototype._prepareDialog = function() 52 { 53 var self = this; 47 54 var editor = this.editor; 48 var outparam = editor.config.PasteText; 49 var action = function( ret ) { 50 var html = ret.text; 51 var insertParagraphs = ret.insertParagraphs; 52 html = html.replace(/</g, "<"); 53 html = html.replace(/>/g, ">"); 54 if ( ret.insertParagraphs) 55 { 56 html = html.replace(/\t/g," "); 57 html = html.replace(/\n/g,"</p><p>"); 58 html="<p>" + html + "</p>"; 59 if (Xinha.is_ie) 60 { 61 editor.insertHTML(html); 62 } 63 else 64 { 65 editor.execCommand("inserthtml",false,html); 66 } 55 56 var self = this; 57 58 /// Now we have everything we need, so we can build the dialog. 59 this.dialog = new Xinha.Dialog(editor, PasteText.html, 'PasteText',{width:350}) 60 61 // Connect the OK and Cancel buttons 62 this.dialog.getElementById('ok').onclick = function() {self.apply();} 63 64 this.dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 65 66 // do some tweaking 67 if (editor.config.PasteText.showParagraphOption) 68 { 69 this.dialog.getElementById("paragraphOption").style.display = ""; 70 } 71 if (editor.config.PasteText.newParagraphDefault) 72 { 73 this.dialog.getElementById("insertParagraphs").checked = true; 74 } 75 76 // we can setup a custom function that cares for sizes etc. when the dialog is resized 77 this.dialog.onresize = function () 78 { 79 this.getElementById("inputArea").style.height = 80 parseInt(this.height,10) // the actual height of the dialog 81 - this.getElementById('h1').offsetHeight // the title bar 82 - this.getElementById('buttons').offsetHeight // the buttons 83 - parseInt(this.rootElem.style.paddingBottom,10) // we have a padding at the bottom, gotta take this into acount 84 + 'px'; // don't forget this ;) 85 86 this.getElementById("inputArea").style.width =(this.width - 2) + 'px'; // and the width 87 88 } 89 }; 90 91 PasteText.prototype.show = function() 92 { 93 if (!this.dialog) this._prepareDialog(); 94 95 // here we can pass values to the dialog 96 // each property pair consists of the "name" of the input we want to populate, and the value to be set 97 var inputs = 98 { 99 inputArea : '' // we want the textarea always to be empty on showing 100 } 101 // now calling the show method of the Xinha.Dialog object to set the values and show the actual dialog 102 this.dialog.show(inputs); 103 104 // Init the sizes (only if we have set up the custom resize function) 105 this.dialog.onresize(); 106 107 this.dialog.getElementById("inputArea").focus(); 108 }; 109 110 // and finally ... take some action 111 PasteText.prototype.apply = function() 112 { 113 // the hide method of the dialog object returns the values of the inputs AND hides the dialog 114 // could also use this.dialog.getValues() here and hide it at the end 115 var returnValues = this.dialog.hide(); 116 117 var html = returnValues.inputArea; 118 var insertParagraphs = returnValues.insertParagraphs; 119 html = html.replace(/</g, "<"); 120 html = html.replace(/>/g, ">"); 121 if ( returnValues.insertParagraphs) 122 { 123 html = html.replace(/\t/g," "); 124 html = html.replace(/\n/g,"</p><p>"); 125 html="<p>" + html + "</p>"; 126 if (Xinha.is_ie) 127 { 128 this.editor.insertHTML(html); 67 129 } 68 130 else 69 131 { 70 html = html.replace(/\n/g,"<br />"); 71 editor.insertHTML(html); 132 this.editor.execCommand("inserthtml",false,html); 72 133 } 73 134 } 74 Dialog( Xinha.getPluginDir("PasteText")+ "/popups/paste_text.html", action, outparam); 135 else 136 { 137 html = html.replace(/\n/g,"<br />"); 138 this.editor.insertHTML(html); 139 } 75 140 }; -
trunk/plugins/PasteText/popups/paste_text.html
r858 r1044 1 <!DOCTYPE html 2 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 5 <head> 6 <title>Paste Text</title> 7 <link rel="stylesheet" type="text/css" href="../../../popups/popup.css" /> 8 <script type="text/javascript" src="../../../popups/popup.js"></script> 9 <script type="text/javascript"> 10 11 function init() { 12 13 __dlg_translate("PasteText"); 14 __dlg_init(null,{width:600,height:480}); 15 16 var param = window.dialogArguments; 17 document.getElementById("paragraphOption").style.display = (param.showParagraphOption) ? '' : 'none'; 18 document.getElementById("insertParagraphs").checked = param.newParagraphDefault; 19 document.getElementById("inputArea").focus(); 20 } 21 22 function onCancel() { 23 __dlg_close( null ); 24 return false; 25 } 26 27 function onOK() { 28 var ret = {}; 29 ret.text = document.getElementById("inputArea").value; 30 ret.insertParagraphs = document.getElementById("insertParagraphs").checked; 31 __dlg_close( ret ); 32 } 33 window.onload = init; 34 </script> 35 </head> 36 37 <body class="dialog"> 38 <div class="title">Paste as Plain Text</div> 39 <form> 40 <div> 41 <textarea name="inputArea" id="inputArea" cols=22 rows=5 style="width: 100%; height: 315px; margin-top: 8px; margin-bottom: 4px; font-family: monospace; font-size: 11px;"></textarea> 42 <div id="buttons"> 43 <label for="insertParagraphs" style="float:left;display:none" id="paragraphOption"> 44 <input type="checkbox" id="insertParagraphs" /> Insert text in new paragraph 1 <h1 id="[h1]"><l10n>Paste as Plain Text</l10n></h1> 2 <textarea name="[inputArea]" id="[inputArea]" style="font-family:monospace;height:300px;border:none;"></textarea> 3 <div class="buttons" id="[buttons]"> 4 <label style="float:left;display:none" id="[paragraphOption]"> 5 <input type="checkbox" id="[insertParagraphs]" name="[insertParagraphs]" /> <l10n>Insert text in new paragraph</l10n> 45 6 </label> 46 <button type="button" name="ok" onclick="return onOK();">OK</button>47 <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>7 <input type="button" id="[ok]" value="_(OK)" /> 8 <input type="button" id="[cancel]" value="_(Cancel)" /> 48 9 </div> 49 </div>50 </form>51 </body>52 </html> -
trunk/plugins/SmartReplace/dialog.html
r752 r1044 8 8 <tr> 9 9 <td style="width:15px"><input type="checkbox" id="[convert]" name="[convert]" /></td> 10 <td style="text-align:left"><l10n>Convert all quotes and dashes in the current document</l10n> </td>10 <td style="text-align:left"><l10n>Convert all quotes and dashes in the current document</l10n> <input style="display:none" type="button" id="[ok]" value="_(OK)" /></td> 11 11 </tr> 12 12 </table> 13 <div style="margin-top: 10px;">14 <input type="button" id="[ok]" value="_(OK)" />15 <input type="button" id="[cancel]" value="_(Cancel)" />16 </div>17 13 </div> 14 <div class="buttons"> 15 16 </div> -
trunk/plugins/SmartReplace/smart-replace.js
r999 r1044 26 26 version : "1.0", 27 27 developer : "Raimund Meyer", 28 developer_url : "http:// x-webservice.net",28 developer_url : "http://rheinauf.de", 29 29 c_owner : "Raimund Meyer", 30 30 sponsor : "", 31 31 sponsor_url : "", 32 license : " LGPL"32 license : "htmlArea" 33 33 }; 34 34 … … 99 99 100 100 SmartReplace.prototype.keyEvent = function(ev) 101 { 101 { 102 102 if ( !this.active) return true; 103 103 var editor = this.editor; … … 152 152 r.moveStart('character', +1); 153 153 r.text = closing; 154 155 154 } 156 155 else … … 224 223 return true; 225 224 } 226 227 225 228 226 SmartReplace.prototype.replaceAll = function() … … 264 262 this.editor.setHTML(html); 265 263 } 266 SmartReplace.prototype.dialog = function() 264 265 SmartReplace.prototype.buttonPress = function(opts, obj) 267 266 { 268 267 var self = this; 269 var action = function (param) 270 { 271 self.toggleActivity(param.enable); 272 if (param.convert) 273 { 274 self.replaceAll(); 275 } 276 } 277 var init = this; 278 Dialog(Xinha.getPluginDir('SmartReplace')+'/popups/dialog.html', action, init); 279 } 280 281 282 SmartReplace.prototype.buttonPress = function(opts, obj) 283 { 284 var self = this; 285 286 if ( this._dialog.dialog.rootElem.style.display != 'none') 287 { 288 return this._dialog.hide(); 268 269 if ( this.dialog.rootElem.style.display != 'none') 270 { 271 return this.dialog.hide(); 289 272 } 290 273 var doOK = function() 291 274 { 292 var opts = self. _dialog.hide();275 var opts = self.dialog.hide(); 293 276 self.toggleActivity((opts.enable) ? true : false); 294 277 if (opts.convert) 295 278 { 296 279 self.replaceAll(); 297 self. _dialog.dialog.getElementById("convert").checked = false;280 self.dialog.getElementById("convert").checked = false; 298 281 } 299 282 } … … 303 286 convert: '' 304 287 }; 305 this. _dialog.show(inputs, doOK);288 this.show(inputs, doOK); 306 289 }; 307 290 308 291 SmartReplace.prototype.onGenerateOnce = function() 309 292 { 310 if( !this._dialog)311 {312 this._dialog = new SmartReplace.Dialog(this);313 }314 };315 316 SmartReplace.Dialog = function (mainPluginObject)317 {318 this.Dialog_nxtid = 0;319 this.mainPluginObject = mainPluginObject;320 this.id = { }; // This will be filled below with a replace, nifty321 322 this.ready = false;323 this.files = false;324 this.html = false;325 this.dialog = false;326 327 293 this._prepareDialog(); 328 329 }; 330 331 SmartReplace.Dialog.prototype._prepareDialog = function() 332 { 333 var pluginDialogObject = this; 334 var editor = this.mainPluginObject.editor; 335 336 if(this.html == false) 337 { 338 Xinha._getback(Xinha.getPluginDir('SmartReplace') + '/dialog.html', function(getback) { pluginDialogObject.html = getback; pluginDialogObject._prepareDialog(); }); 294 }; 295 296 SmartReplace.prototype._prepareDialog = function() 297 { 298 var self = this; 299 var editor = this.editor; 300 301 if(!this.html) 302 { 303 Xinha._getback( Xinha.getPluginDir("SmartReplace") + '/dialog.html', function(getback) { self.html = getback; self._prepareDialog(); }); 339 304 return; 340 305 } 341 306 342 307 // Now we have everything we need, so we can build the dialog. 343 this.dialog = new Xinha.Dialog(editor, this.html, 'SmartReplace'); 344 308 this.dialog = new Xinha.Dialog(editor, this.html, 'SmartReplace',{},{modal:false}); 309 this.dialog.attachToPanel('top'); 310 311 this.dialog.getElementById('enable').onchange = function () 312 { 313 self.toggleActivity(this.checked); 314 } 315 this.dialog.getElementById('convert').onchange = function () 316 { 317 self.dialog.getElementById('ok').style.display = ( this.checked ) ? '' : 'none'; 318 } 319 this.dialog.getElementById('ok').onclick = function () 320 { 321 self.replaceAll(); 322 self.dialog.getElementById('convert').checked = false; 323 this.style.display = 'none'; 324 } 345 325 this.ready = true; 346 326 }; 347 327 348 SmartReplace.Dialog.prototype._lc = SmartReplace.prototype._lc; 349 350 SmartReplace.Dialog.prototype.show = function(inputs, ok, cancel) 328 SmartReplace.prototype.show = function(inputs) 351 329 { 352 330 if(!this.ready) 353 331 { 354 var pluginDialogObject= this;355 window.setTimeout(function() {pluginDialogObject.show(inputs,ok,cancel);},100);332 var self = this; 333 window.setTimeout(function() {self.show(inputs,ok,cancel);},100); 356 334 return; 357 335 } 358 336 359 337 // Connect the OK and Cancel buttons 360 var dialog = this.dialog; 361 var pluginDialogObject = this; 362 if(ok) 363 { 364 this.dialog.getElementById('ok').onclick = ok; 365 } 366 else 367 { 368 this.dialog.getElementById('ok').onclick = function() {pluginDialogObject.hide();}; 369 } 370 371 if(cancel) 372 { 373 this.dialog.getElementById('cancel').onclick = cancel; 374 } 375 else 376 { 377 this.dialog.getElementById('cancel').onclick = function() { pluginDialogObject.hide()}; 378 } 379 380 // Show the dialog 381 this.mainPluginObject.editor.disableToolbar(['fullscreen','smartreplace']); 338 var self = this; 382 339 383 340 this.dialog.show(inputs); … … 386 343 this.dialog.onresize(); 387 344 }; 388 389 SmartReplace.Dialog.prototype.hide = function()390 {391 this.mainPluginObject.editor.enableToolbar();392 return this.dialog.hide();393 }; -
trunk/plugins/Stylist/stylist.js
r1031 r1044 66 66 Xinha.prototype._fillStylist = function() 67 67 { 68 if(!this._stylist) return false; 69 this.plugins.Stylist.instance.main.innerHTML = ''; 68 if(!this.plugins.Stylist.instance.dialog) return false; 69 var main = this.plugins.Stylist.instance.dialog.main; 70 main.innerHTML = ''; 70 71 71 72 var may_apply = true; … … 180 181 { 181 182 var anch = document.createElement('a'); 182 if ( Xinha.is_real_gecko ) anch.onfocus = function () { this.blur() } // prevent dotted line around link that causes horizontal scrollbar in Mozilla183 anch.onfocus = function () { this.blur() } // prevent dotted line around link that causes horizontal scrollbar 183 184 anch._stylist_className = className.trim(); 184 185 anch._stylist_applied = applied; … … 215 216 } 216 217 217 this.plugins.Stylist.instance.main.appendChild(anch);218 main.appendChild(anch); 218 219 } 219 220 } … … 484 485 RE_rule = /\{(.|\r|\n)*?\}/g; 485 486 css = css.replace(RE_comment, ''); 486 css = css.replace(RE_comment, '');487 487 css = css.replace(RE_rule, ','); 488 488 … … 527 527 Stylist.prototype.onGenerateOnce = function() 528 528 { 529 var cfg = this.editor.config; 530 if(typeof cfg.css_style != 'undefined' && Xinha.objectProperties(cfg.css_style).length != 0) 531 { 532 this._prepareDialog(); 533 } 534 535 }; 536 Stylist.prototype._prepareDialog = function() 537 { 529 538 var editor = this.editor; 530 539 var stylist = this; 531 if(typeof editor.config.css_style != 'undefined' && Xinha.objectProperties(editor.config.css_style).length != 0) 532 { 533 editor._stylist = null; // This needs to be changes to be Stylist::_stylist sometime 534 editor._stylist = editor.addPanel('right'); 535 Xinha.addClass(editor._stylist, 'stylist'); 536 537 this.caption = document.createElement("h1"); 538 this.caption.innerHTML = Xinha._lc('Styles', 'Stylist'); 539 editor._stylist.appendChild(this.caption); 540 this.main = document.createElement("div"); 541 this.main.style.overflow = "auto"; 542 this.main.style.height = this.editor._framework.ed_cell.offsetHeight - this.caption.offsetHeight + 'px'; 543 544 editor._stylist.appendChild(this.main); 545 546 Xinha.freeLater(this,"caption"); 547 Xinha.freeLater(this,"main"); 548 549 editor.notifyOn('modechange', 550 function(e,args) 551 { 552 switch(args.mode) 553 { 554 case 'text': 555 { 556 editor.hidePanel(editor._stylist); 557 break; 558 } 559 case 'wysiwyg': 560 { 561 editor.showPanel(editor._stylist); 562 break; 563 } 564 } 565 } 566 ); 567 editor.notifyOn('panel_change', 568 function(e,args) 569 { 570 switch (args.action) 571 { 572 case 'show': 573 var newHeight = stylist.main.offsetHeight - args.panel.offsetHeight; 574 stylist.main.style.height = ((newHeight > 0) ? stylist.main.offsetHeight - args.panel.offsetHeight : 0) + 'px'; 575 editor._stylist.style.height = stylist.caption.offsetHeight + "px"; 576 editor.sizeEditor(); 577 break; 578 case 'hide': 579 stylist.resize(); 580 break; 581 } 582 } 583 ); 584 editor.notifyOn('before_resize', 585 function() 586 { 587 editor._stylist.style.height = stylist.caption.offsetHeight + "px"; 588 } 589 ); 590 editor.notifyOn('resize', 591 function() 592 { 593 stylist.resize(); 594 } 595 ); 596 } 597 598 }; 540 541 var html = '<h1><l10n>Styles</l10n></h1>'; 542 543 this.dialog = new Xinha.Dialog(editor, html, 'Stylist',{width:200},{modal:false,closable:false}); 544 Xinha._addClass( this.dialog.rootElem, 'Stylist' ); 545 this.dialog.attachToPanel('right'); 546 this.dialog.show(); 547 548 var dialog = this.dialog; 549 var main = this.dialog.main; 550 var caption = this.dialog.captionBar; 551 552 main.style.overflow = "auto"; 553 main.style.height = this.editor._framework.ed_cell.offsetHeight - caption.offsetHeight + 'px'; 554 555 editor.notifyOn('modechange', 556 function(e,args) 557 { 558 if (!dialog.attached) 559 { 560 return; 561 } 562 switch(args.mode) 563 { 564 case 'text': 565 { 566 dialog.hide(); 567 break; 568 } 569 case 'wysiwyg': 570 { 571 dialog.show(); 572 break; 573 } 574 } 575 } 576 ); 577 editor.notifyOn('panel_change', 578 function(e,args) 579 { 580 if (!dialog.attached) 581 { 582 return; 583 } 584 switch (args.action) 585 { 586 case 'show': 587 var newHeight = main.offsetHeight - args.panel.offsetHeight; 588 main.style.height = ((newHeight > 0) ? main.offsetHeight - args.panel.offsetHeight : 0) + 'px'; 589 dialog.rootElem.style.height = caption.offsetHeight + "px"; 590 editor.sizeEditor(); 591 break; 592 case 'hide': 593 stylist.resize(); 594 break; 595 } 596 } 597 ); 598 editor.notifyOn('before_resize', 599 function() 600 { 601 if (!dialog.attached) 602 { 603 return; 604 } 605 dialog.rootElem.style.height = caption.offsetHeight + "px"; 606 } 607 ); 608 editor.notifyOn('resize', 609 function() 610 { 611 if (!dialog.attached) 612 { 613 return; 614 } 615 stylist.resize(); 616 } 617 ); 618 } 599 619 Stylist.prototype.resize = function() 600 620 { 601 621 var editor = this.editor; 602 var panelContainer = editor._stylist.parentNode; 622 var rootElem = this.dialog.rootElem; 623 624 if (rootElem.style.display == 'none') return; 625 626 var panelContainer = rootElem.parentNode; 603 627 604 628 var newSize = panelContainer.offsetHeight; 605 629 for (var i=0; i < panelContainer.childNodes.length;++i) 606 630 { 607 if (panelContainer.childNodes[i] ==editor._stylist|| !panelContainer.childNodes[i].offsetHeight)631 if (panelContainer.childNodes[i] == rootElem || !panelContainer.childNodes[i].offsetHeight) 608 632 { 609 633 continue; … … 611 635 newSize -= panelContainer.childNodes[i].offsetHeight; 612 636 } 613 editor._stylist.style.height = newSize+ 'px';614 this. main.style.height = newSize - this.caption.offsetHeight+ 'px';637 rootElem.style.height = newSize-5 + 'px'; 638 this.dialog.main.style.height = newSize - this.dialog.captionBar.offsetHeight -5 + 'px'; 615 639 } 616 640 617 641 Stylist.prototype.onUpdateToolbar = function() 618 642 { 619 if(this. editor._stylist)643 if(this.dialog) 620 644 { 621 645 if(this._timeoutID) -
trunk/plugins/SuperClean/dialog.html
r728 r1044 1 1 <h1 id="[h1]"><l10n>Clean up HTML</l10n></h1> 2 <div style="margin-left: 10px;" >2 <div style="margin-left: 10px;" id="[main]"> 3 3 <l10n>Please select from the following cleaning options...</l10n> 4 4 <!--filters--> 5 <div style="margin-top: 10px;">6 <input type="button" id="[ok]" value="_(OK)" />7 <input type="button" id="[cancel]" value="_(Cancel)" />8 </div>9 5 </div> 6 7 <div id="[waiting]" style="display:none;margin:3em 1em;text-align:center"><l10n>Please stand by while cleaning in process...</l10n></div> 8 <div id="[alert]" style="display:none;margin:3em 1em;text-align:center"></l10n></div> 9 10 <div class="buttons" id="[buttons]"> 11 <input type="button" id="[ok]" value="_(OK)" /> 12 <input type="button" id="[cancel]" value="_(Cancel)" /> 13 </div> -
trunk/plugins/SuperClean/lang/de.js
r677 r1044 14 14 "Cancel": "Abbrechen", 15 15 "Tidy failed. Check your HTML for syntax errors.": "SÀubern fehlgeschlagen. ÃberprÃŒfen Sie Ihren Code auf Fehler.", 16 "You don't have anything to tidy!": "Es gibt nichts zu sÀubern...!" 16 "You don't have anything to tidy!": "Es gibt nichts zu sÀubern...!", 17 "Please stand by while cleaning in process..." : "Bitte warten Sie, wÀhrend die SÀuberung lÀuft..." 17 18 }; -
trunk/plugins/SuperClean/super-clean.js
r999 r1044 1 // Make our right side panel and insert appropriatly 1 /** superClean combines HTMLTidy, Word Cleaning and font stripping into a single function 2 * it works a bit differently in how it asks for parameters */ 3 2 4 function SuperClean(editor, args) 3 5 { … … 25 27 SuperClean.prototype._lc = function(string) { 26 28 return Xinha._lc(string, 'SuperClean'); 27 };28 29 /** superClean combines HTMLTidy, Word Cleaning and font stripping into a single function30 * it works a bit differently in how it asks for parameters */31 32 SuperClean.prototype._superClean = function(opts, obj)33 {34 var superclean = this;35 36 // Do the clean if we got options37 var doOK = function()38 {39 var opts = superclean._dialog.hide();40 var editor = superclean.editor;41 42 if(opts.word_clean) editor._wordClean();43 var D = editor.getInnerHTML();44 45 for(var filter in editor.config.SuperClean.filters)46 {47 if(filter=='tidy' || filter=='word_clean') continue;48 if(opts[filter])49 {50 D = SuperClean.filterFunctions[filter](D, editor);51 }52 }53 54 D = D.replace(/(style|class)="\s*"/gi, '');55 D = D.replace(/<(font|span)\s*>/gi, '');56 57 editor.setHTML(D);58 59 if(opts.tidy)60 {61 var callback = function(javascriptResponse)62 {63 eval("var response = " + javascriptResponse);64 switch (response.action)65 {66 case 'setHTML':67 editor.setHTML(response.value);68 break;69 case 'alert':70 alert(superclean._lc(response.value));71 break;72 }73 }74 Xinha._postback(editor.config.SuperClean.tidy_handler, {'content' : editor.getInnerHTML()},callback);75 }76 return true;77 }78 79 if(this.editor.config.SuperClean.show_dialog)80 {81 var inputs = {};82 this._dialog.show(inputs, doOK);83 }84 else85 {86 var editor = this.editor;87 var html = editor.getInnerHTML();88 for(var filter in editor.config.SuperClean.filters)89 {90 if(filter=='tidy') continue; //call tidy last91 html = SuperClean.filterFunctions[filter](html, editor);92 }93 94 html = html.replace(/(style|class)="\s*"/gi, '');95 html = html.replace(/<(font|span)\s*>/gi, '');96 97 editor.setHTML(html);98 99 if(editor.config.SuperClean.filters.tidy)100 {101 SuperClean.filterFunctions.tidy(html, editor);102 }103 }104 29 }; 105 30 … … 131 56 }, 132 57 //if false all filters are applied, if true a dialog asks what filters should be used 133 'show_dialog': true58 'show_dialog': false 134 59 }; 135 60 136 61 SuperClean.filterFunctions = { }; 137 SuperClean.filterFunctions.remove_colors = function(D)138 {139 D = D.replace(/color="?[^" >]*"?/gi, '');140 // { (stops jedit's fold breaking)141 D = D.replace(/([^-])color:[^;}"']+;?/gi, '$1');142 return(D);143 };144 SuperClean.filterFunctions.remove_sizes = function(D)145 {146 D = D.replace(/size="?[^" >]*"?/gi, '');147 // { (stops jedit's fold breaking)148 D = D.replace(/font-size:[^;}"']+;?/gi, '');149 return(D);150 };151 SuperClean.filterFunctions.remove_faces = function(D)152 {153 D = D.replace(/face="?[^" >]*"?/gi, '');154 // { (stops jedit's fold breaking)155 D = D.replace(/font-family:[^;}"']+;?/gi, '');156 return(D);157 };158 SuperClean.filterFunctions.remove_lang = function(D)159 {160 D = D.replace(/lang="?[^" >]*"?/gi, '');161 return(D);162 };163 SuperClean.filterFunctions.word_clean = function(html, editor)164 {165 editor.setHTML(html);166 editor._wordClean();167 return editor.getInnerHTML();168 };169 170 SuperClean.filterFunctions.remove_fancy_quotes = function(D)171 {172 D = D.replace(new RegExp(String.fromCharCode(8216),"g"),"'");173 D = D.replace(new RegExp(String.fromCharCode(8217),"g"),"'");174 D = D.replace(new RegExp(String.fromCharCode(8218),"g"),"'");175 D = D.replace(new RegExp(String.fromCharCode(8219),"g"),"'");176 D = D.replace(new RegExp(String.fromCharCode(8220),"g"),"\"");177 D = D.replace(new RegExp(String.fromCharCode(8221),"g"),"\"");178 D = D.replace(new RegExp(String.fromCharCode(8222),"g"),"\"");179 D = D.replace(new RegExp(String.fromCharCode(8223),"g"),"\"");180 return D;181 };182 183 SuperClean.filterFunctions.tidy = function(html, editor)184 {185 Xinha._postback(editor.config.SuperClean.tidy_handler, {'content' : html},186 function(javascriptResponse) { eval(javascriptResponse) });187 };188 62 189 63 64 SuperClean.prototype.onGenerateOnce = function() 65 { 190 66 191 SuperClean.prototype.onGenerate = function()192 {193 if(this.editor.config.SuperClean.show_dialog && !this._dialog)194 {195 this._dialog = new SuperClean.Dialog(this);196 }197 67 if(this.editor.config.tidy_handler) 198 68 { … … 205 75 this.editor.config.filters.tidy = null; 206 76 } 77 SuperClean.loadAssets(); 78 this.loadFilters(); 79 }; 207 80 81 SuperClean.prototype.onUpdateToolbar = function() 82 { 83 if (!(SuperClean.methodsReady && SuperClean.html)) 84 { 85 this.editor._toolbarObjects.superclean.state("enabled", false); 86 } 87 else this.onUpdateToolbar = null; 88 }; 89 90 SuperClean.loadAssets = function() 91 { 92 var self = SuperClean; 93 if (self.loading) return; 94 self.loading = true; 95 Xinha._getback(Xinha.getPluginDir("SuperClean") + '/pluginMethods.js', function(getback) { eval(getback); self.methodsReady = true; }); 96 Xinha._getback( Xinha.getPluginDir("SuperClean") + '/dialog.html', function(getback) { self.html = getback; } ); 97 }; 98 99 SuperClean.prototype.loadFilters = function() 100 { 208 101 var sc = this; 209 102 //load the filter-functions 210 103 for(var filter in this.editor.config.SuperClean.filters) 211 104 { 105 if (/^(remove_colors|remove_sizes|remove_faces|remove_lang|word_clean|remove_fancy_quotes|tidy)$/.test(filter)) continue; //skip built-in functions 106 212 107 if(!SuperClean.filterFunctions[filter]) 213 108 { … … 222 117 function(func) { 223 118 eval('SuperClean.filterFunctions.'+filter+'='+func+';'); 224 sc. onGenerate();119 sc.loadFilters(); 225 120 }); 226 121 } … … 229 124 } 230 125 }; 231 // Inline Dialog for SuperClean232 233 234 SuperClean.Dialog = function (SuperClean)235 {236 var lDialog = this;237 this.Dialog_nxtid = 0;238 this.SuperClean = SuperClean;239 this.id = { }; // This will be filled below with a replace, nifty240 241 this.ready = false;242 this.files = false;243 this.html = false;244 this.dialog = false;245 246 // load the dTree script247 this._prepareDialog();248 249 };250 251 SuperClean.Dialog.prototype._prepareDialog = function()252 {253 var lDialog = this;254 var SuperClean = this.SuperClean;255 256 if(this.html == false)257 {258 Xinha._getback(Xinha.getPluginDir("SuperClean") + '/dialog.html', function(txt) { lDialog.html = txt; lDialog._prepareDialog(); });259 return;260 }261 262 var htmlFilters = "";263 for(var filter in this.SuperClean.editor.config.SuperClean.filters)264 {265 htmlFilters += " <div>\n";266 var filtDetail = this.SuperClean.editor.config.SuperClean.filters[filter];267 if(typeof filtDetail.label == 'undefined')268 {269 htmlFilters += " <input type=\"checkbox\" name=\"["+filter+"]\" id=\"["+filter+"]\" checked />\n";270 htmlFilters += " <label for=\"["+filter+"]\">"+this.SuperClean.editor.config.SuperClean.filters[filter]+"</label>\n";271 }272 else273 {274 htmlFilters += " <input type=\"checkbox\" name=\"["+filter+"]\" id=\"["+filter+"]\" " + (filtDetail.checked ? "checked" : "") + " />\n";275 htmlFilters += " <label for=\"["+filter+"]\">"+filtDetail.label+"</label>\n";276 }277 htmlFilters += " </div>\n";278 }279 this.html = this.html.replace('<!--filters-->', htmlFilters);280 281 var html = this.html;282 283 // Now we have everything we need, so we can build the dialog.284 var dialog = this.dialog = new Xinha.Dialog(SuperClean.editor, this.html, 'SuperClean');285 286 this.ready = true;287 };288 289 SuperClean.Dialog.prototype._lc = SuperClean.prototype._lc;290 291 SuperClean.Dialog.prototype.show = function(inputs, ok, cancel)292 {293 if(!this.ready)294 {295 var lDialog = this;296 window.setTimeout(function() {lDialog.show(inputs,ok,cancel);},100);297 return;298 }299 300 // Connect the OK and Cancel buttons301 var dialog = this.dialog;302 var lDialog = this;303 if(ok)304 {305 this.dialog.getElementById('ok').onclick = ok;306 }307 else308 {309 this.dialog.getElementById('ok').onclick = function() {lDialog.hide();};310 }311 312 if(cancel)313 {314 this.dialog.getElementById('cancel').onclick = cancel;315 }316 else317 {318 this.dialog.getElementById('cancel').onclick = function() { lDialog.hide()};319 }320 321 // Show the dialog322 this.SuperClean.editor.disableToolbar(['fullscreen','SuperClean']);323 324 this.dialog.show(inputs);325 326 // Init the sizes327 this.dialog.onresize();328 };329 330 SuperClean.Dialog.prototype.hide = function()331 {332 this.SuperClean.editor.enableToolbar();333 return this.dialog.hide();334 }; -
trunk/plugins/TableOperations/table-operations.js
r999 r1044 11 11 // http://dynarch.com/mishoo 12 12 // 13 // $Id :table-operations.js 988 2008-04-12 13:46:09Z ray$13 // $Id$ 14 14 15 15 // Object that will encapsulate all the table operations provided by … … 18 18 { 19 19 'showButtons' : true // Set to false to hide all but inserttable and toggleborders buttons on the toolbar 20 // this is useful if you have the ContextMenu plugin and want to save toolbar space21 // (the context menu can perform all the button operations)20 // this is useful if you have the ContextMenu plugin and want to save toolbar space 21 // (the context menu can perform all the button operations) 22 22 } 23 23 … … 35 35 36 36 var toolbar = ["linebreak", "inserttable", "toggleborders"]; 37 37 38 38 39 39 for (var i = 0; i < bl.length; ++i) { … … 56 56 cfg.toolbar.push(toolbar); 57 57 58 if ( typeof PopupWin == 'undefined' )58 if ( typeof PopupWin == 'undefined' ) 59 59 { 60 Xinha._loadback(_editor_url + 'modules/Dialogs/popupwin.js');60 Xinha._loadback(_editor_url + 'modules/Dialogs/popupwin.js'); 61 61 } 62 if ( typeof Xinha.InlineStyler == 'undefined' ) 63 { 64 Xinha._loadback(_editor_url + 'modules/InlineStyler/InlineStyler.js'); 65 } 66 62 67 } 63 68 … … 74 79 75 80 TableOperations.prototype._lc = function(string) { 76 return Xinha._lc(string, 'TableOperations');81 return Xinha._lc(string, 'TableOperations'); 77 82 }; 78 83 … … 96 101 } 97 102 return ret; 98 };99 100 // this function requires the file PopupDiv/PopupWin to be loaded from browser101 TableOperations.prototype.dialogTableProperties = function() {102 // retrieve existing values103 var table = this.getClosest("table");104 // this.editor.selectNodeContents(table);105 // this.editor.updateToolbar();106 107 var dialog = new PopupWin(this.editor, Xinha._lc("Table Properties", "TableOperations"), function(dialog, params) {108 TableOperations.processStyle(params, table);109 for (var i in params) {110 if(typeof params[i] == 'function') continue;111 var val = params[i];112 switch (i) {113 case "f_caption":114 if (/\S/.test(val)) {115 // contains non white-space characters116 var caption = table.getElementsByTagName("caption")[0];117 if (!caption) {118 caption = dialog.editor._doc.createElement("caption");119 table.insertBefore(caption, table.firstChild);120 }121 caption.innerHTML = val;122 } else {123 // search for caption and delete it if found124 var caption = table.getElementsByTagName("caption")[0];125 if (caption) {126 caption.parentNode.removeChild(caption);127 }128 }129 break;130 case "f_summary":131 table.summary = val;132 break;133 case "f_width":134 table.style.width = ("" + val) + params.f_unit;135 break;136 case "f_align":137 table.align = val;138 break;139 case "f_spacing":140 table.cellSpacing = val;141 break;142 case "f_padding":143 table.cellPadding = val;144 break;145 case "f_borders":146 table.border = val;147 break;148 case "f_frames":149 table.frame = val;150 break;151 case "f_rules":152 table.rules = val;153 break;154 }155 }156 // various workarounds to refresh the table display (Gecko,157 // what's going on?! do not disappoint me!)158 dialog.editor.forceRedraw();159 dialog.editor.focusEditor();160 dialog.editor.updateToolbar();161 var save_collapse = table.style.borderCollapse;162 table.style.borderCollapse = "collapse";163 table.style.borderCollapse = "separate";164 table.style.borderCollapse = save_collapse;165 },166 167 // this function gets called when the dialog needs to be initialized168 function (dialog) {169 170 var f_caption = "";171 var capel = table.getElementsByTagName("caption")[0];172 if (capel) {173 f_caption = capel.innerHTML;174 }175 var f_summary = table.summary;176 var f_width = parseInt(table.style.width);177 isNaN(f_width) && (f_width = "");178 var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';179 var f_align = table.align;180 var f_spacing = table.cellSpacing;181 var f_padding = table.cellPadding;182 var f_borders = table.border;183 var f_frames = table.frame;184 var f_rules = table.rules;185 186 function selected(val) {187 return val ? " selected" : "";188 }189 190 // dialog contents191 dialog.content.style.width = "400px";192 dialog.content.innerHTML = " \193 <div class='title'>" + Xinha._lc("Table Properties", "TableOperations") + "\194 </div> \195 <table style='width:100%'> \196 <tr> \197 <td> \198 <fieldset><legend>" + Xinha._lc("Description", "TableOperations") + "</legend> \199 <table style='width:100%'> \200 <tr> \201 <td class='label'>" + Xinha._lc("Caption", "TableOperations") + ":</td> \202 <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \203 </tr><tr> \204 <td class='label'>" + Xinha._lc("Summary", "TableOperations") + ":</td> \205 <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \206 </tr> \207 </table> \208 </fieldset> \209 </td> \210 </tr> \211 <tr><td id='--HA-layout'></td></tr> \212 <tr> \213 <td> \214 <fieldset><legend>" + Xinha._lc("Spacing and padding", "TableOperations") + "</legend> \215 <table style='width:100%'> \216 "+// <tr> \217 // <td class='label'>" + Xinha._lc("Width", "TableOperations") + ":</td> \218 // <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \219 // <select name='f_unit'> \220 // <option value='%'" + selected(f_unit == "percent") + ">" + Xinha._lc("percent", "TableOperations") + "</option> \221 // <option value='px'" + selected(f_unit == "pixels") + ">" + Xinha._lc("pixels", "TableOperations") + "</option> \222 // </select> " + Xinha._lc("Align", "TableOperations") + ": \223 // <select name='f_align'> \224 // <option value='left'" + selected(f_align == "left") + ">" + Xinha._lc("Left", "TableOperations") + "</option> \225 // <option value='center'" + selected(f_align == "center") + ">" + Xinha._lc("Center", "TableOperations") + "</option> \226 // <option value='right'" + selected(f_align == "right") + ">" + Xinha._lc("Right", "TableOperations") + "</option> \227 // </select> \228 // </td> \229 // </tr> \230 " <tr> \231 <td class='label'>" + Xinha._lc("Spacing", "TableOperations") + ":</td> \232 <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> " + Xinha._lc("Padding", "TableOperations") + ":\233 <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> " + Xinha._lc("pixels", "TableOperations") + "\234 </td> \235 </tr> \236 </table> \237 </fieldset> \238 </td> \239 </tr> \240 <tr> \241 <td> \242 <fieldset><legend>" + Xinha._lc("Frame and borders", "TableOperations") + "</legend> \243 <table width='100%'> \244 <tr> \245 <td class='label'>" + Xinha._lc("Borders", "TableOperations") + ":</td> \246 <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> " + Xinha._lc("pixels", "TableOperations") + "</td> \247 </tr> \248 <tr> \249 <td class='label'>" + Xinha._lc("Frames", "TableOperations") + ":</td> \250 <td> \251 <select name='f_frames'> \252 <option value='void'" + selected(f_frames == "void") + ">" + Xinha._lc("No sides", "TableOperations") + "</option> \253 <option value='above'" + selected(f_frames == "above") + ">" + Xinha._lc("The top side only", "TableOperations") + "</option> \254 <option value='below'" + selected(f_frames == "below") + ">" + Xinha._lc("The bottom side only", "TableOperations") + "</option> \255 <option value='hsides'" + selected(f_frames == "hsides") + ">" + Xinha._lc("The top and bottom sides only", "TableOperations") + "</option> \256 <option value='vsides'" + selected(f_frames == "vsides") + ">" + Xinha._lc("The right and left sides only", "TableOperations") + "</option> \257 <option value='lhs'" + selected(f_frames == "lhs") + ">" + Xinha._lc("The left-hand side only", "TableOperations") + "</option> \258 <option value='rhs'" + selected(f_frames == "rhs") + ">" + Xinha._lc("The right-hand side only", "TableOperations") + "</option> \259 <option value='box'" + selected(f_frames == "box") + ">" + Xinha._lc("All four sides", "TableOperations") + "</option> \260 </select> \261 </td> \262 </tr> \263 <tr> \264 <td class='label'>" + Xinha._lc("Rules", "TableOperations") + ":</td> \265 <td> \266 <select name='f_rules'> \267 <option value='none'" + selected(f_rules == "none") + ">" + Xinha._lc("No rules", "TableOperations") + "</option> \268 <option value='rows'" + selected(f_rules == "rows") + ">" + Xinha._lc("Rules will appear between rows only", "TableOperations") + "</option> \269 <option value='cols'" + selected(f_rules == "cols") + ">" + Xinha._lc("Rules will appear between columns only", "TableOperations") + "</option> \270 <option value='all'" + selected(f_rules == "all") + ">" + Xinha._lc("Rules will appear between all rows and columns", "TableOperations") + "</option> \271 </select> \272 </td> \273 </tr> \274 </table> \275 </fieldset> \276 </td> \277 </tr> \278 <tr> \279 <td id='--HA-style'></td> \280 </tr> \281 </table> \282 ";283 var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);284 var p = dialog.doc.getElementById("--HA-style");285 p.appendChild(st_prop);286 var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);287 p = dialog.doc.getElementById("--HA-layout");288 p.appendChild(st_layout);289 dialog.modal = true;290 dialog.addButtons("OK", "Cancel");291 dialog.showAtElement(dialog.editor._iframe, "c");292 });293 };294 295 // this function requires the file PopupDiv/PopupWin to be loaded from browser296 TableOperations.prototype.dialogRowCellProperties = function(cell) {297 // retrieve existing values298 var element = this.getClosest(cell ? "td" : "tr");299 var table = this.getClosest("table");300 // this.editor.selectNodeContents(element);301 // this.editor.updateToolbar();302 303 var dialog = new PopupWin(this.editor, cell ? Xinha._lc("Cell Properties", "TableOperations") : Xinha._lc("Row Properties", "TableOperations"), function(dialog, params) {304 TableOperations.processStyle(params, element);305 for (var i in params) {306 if(typeof params[i] == 'function') continue;307 var val = params[i];308 switch (i) {309 case "f_align":310 element.align = val;311 break;312 case "f_char":313 element.ch = val;314 break;315 case "f_valign":316 element.vAlign = val;317 break;318 }319 }320 // various workarounds to refresh the table display (Gecko,321 // what's going on?! do not disappoint me!)322 dialog.editor.forceRedraw();323 dialog.editor.focusEditor();324 dialog.editor.updateToolbar();325 var save_collapse = table.style.borderCollapse;326 table.style.borderCollapse = "collapse";327 table.style.borderCollapse = "separate";328 table.style.borderCollapse = save_collapse;329 },330 331 // this function gets called when the dialog needs to be initialized332 function (dialog) {333 334 var f_align = element.align;335 var f_valign = element.vAlign;336 var f_char = element.ch;337 338 function selected(val) {339 return val ? " selected" : "";340 }341 342 // dialog contents343 dialog.content.style.width = "400px";344 dialog.content.innerHTML = " \345 <div class='title'>" + Xinha._lc(cell ? "Cell Properties" : "Row Properties", "TableOperations") + "</div> \346 <table style='width:100%'> \347 <tr> \348 <td id='--HA-layout'> \349 "+// <fieldset><legend>" + Xinha._lc("Layout", "TableOperations") + "</legend> \350 // <table style='width:100%'> \351 // <tr> \352 // <td class='label'>" + Xinha._lc("Align", "TableOperations") + ":</td> \353 // <td> \354 // <select name='f_align'> \355 // <option value='left'" + selected(f_align == "left") + ">" + Xinha._lc("Left", "TableOperations") + "</option> \356 // <option value='center'" + selected(f_align == "center") + ">" + Xinha._lc("Center", "TableOperations") + "</option> \357 // <option value='right'" + selected(f_align == "right") + ">" + Xinha._lc("Right", "TableOperations") + "</option> \358 // <option value='char'" + selected(f_align == "char") + ">" + Xinha._lc("Char", "TableOperations") + "</option> \359 // </select> \360 // " + Xinha._lc("Char", "TableOperations") + ": \361 // <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \362 // </td> \363 // </tr><tr> \364 // <td class='label'>" + Xinha._lc("Vertical align", "TableOperations") + ":</td> \365 // <td> \366 // <select name='f_valign'> \367 // <option value='top'" + selected(f_valign == "top") + ">" + Xinha._lc("Top", "TableOperations") + "</option> \368 // <option value='middle'" + selected(f_valign == "middle") + ">" + Xinha._lc("Middle", "TableOperations") + "</option> \369 // <option value='bottom'" + selected(f_valign == "bottom") + ">" + Xinha._lc("Bottom", "TableOperations") + "</option> \370 // <option value='baseline'" + selected(f_valign == "baseline") + ">" + Xinha._lc("Baseline", "TableOperations") + "</option> \371 // </select> \372 // </td> \373 // </tr> \374 // </table> \375 // </fieldset> \376 " </td> \377 </tr> \378 <tr> \379 <td id='--HA-style'></td> \380 </tr> \381 </table> \382 ";383 var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);384 var p = dialog.doc.getElementById("--HA-style");385 p.appendChild(st_prop);386 var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);387 p = dialog.doc.getElementById("--HA-layout");388 p.appendChild(st_layout);389 dialog.modal = true;390 dialog.addButtons("OK", "Cancel");391 dialog.showAtElement(dialog.editor._iframe, "c");392 });393 103 }; 394 104 … … 519 229 // ROWS 520 230 521 case "TO-row-insert-above":522 case "TO-row-insert-under":231 case "TO-row-insert-above": 232 case "TO-row-insert-under": 523 233 var tr = this.getClosest("tr"); 524 234 if (!tr) { … … 531 241 editor.focusEditor(); 532 242 break; 533 case "TO-row-delete":243 case "TO-row-delete": 534 244 var tr = this.getClosest("tr"); 535 245 if (!tr) { … … 549 259 editor.updateToolbar(); 550 260 break; 551 case "TO-row-split":261 case "TO-row-split": 552 262 var td = this.getClosest("td"); 553 263 if (!td) { … … 559 269 // COLUMNS 560 270 561 case "TO-col-insert-before":562 case "TO-col-insert-after":271 case "TO-col-insert-before": 272 case "TO-col-insert-after": 563 273 var td = this.getClosest("td"); 564 274 if (!td) { … … 567 277 var rows = td.parentNode.parentNode.rows; 568 278 var index = td.cellIndex; 569 var lastColumn = (td.parentNode.cells.length == index + 1);279 var lastColumn = (td.parentNode.cells.length == index + 1); 570 280 for (var i = rows.length; --i >= 0;) { 571 281 var tr = rows[i]; 572 282 var otd = editor._doc.createElement("td"); 573 283 otd.innerHTML = mozbr; 574 if (lastColumn && Xinha.is_ie)575 {576 tr.insertBefore(otd);577 }578 else579 {580 var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];581 tr.insertBefore(otd, ref);582 }284 if (lastColumn && Xinha.is_ie) 285 { 286 tr.insertBefore(otd); 287 } 288 else 289 { 290 var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)]; 291 tr.insertBefore(otd, ref); 292 } 583 293 } 584 294 editor.focusEditor(); 585 295 break; 586 case "TO-col-split":296 case "TO-col-split": 587 297 var td = this.getClosest("td"); 588 298 if (!td) { … … 591 301 splitCol(td); 592 302 break; 593 case "TO-col-delete":303 case "TO-col-delete": 594 304 var td = this.getClosest("td"); 595 305 if (!td) { … … 615 325 // CELLS 616 326 617 case "TO-cell-split":327 case "TO-cell-split": 618 328 var td = this.getClosest("td"); 619 329 if (!td) { … … 622 332 splitCell(td); 623 333 break; 624 case "TO-cell-insert-before":625 case "TO-cell-insert-after":334 case "TO-cell-insert-before": 335 case "TO-cell-insert-after": 626 336 var td = this.getClosest("td"); 627 337 if (!td) { … … 635 345 editor.focusEditor(); 636 346 break; 637 case "TO-cell-delete":347 case "TO-cell-delete": 638 348 var td = this.getClosest("td"); 639 349 if (!td) { … … 650 360 editor.updateToolbar(); 651 361 break; 652 case "TO-cell-merge":362 case "TO-cell-merge": 653 363 //Mozilla, as opposed to IE, allows the selection of several cells, which is fine :) 654 364 var sel = editor._getSelection(); … … 690 400 break; 691 401 } 692 editor._popupDialog("plugin://TableOperations/merge_cells.html", function(param) { 693 if (!param) { // user pressed Cancel 694 return false; 695 } 696 no_cols = parseInt(param['f_cols'],10) + 1; 697 no_rows = parseInt(param['f_rows'],10) + 1; 698 var tr = td.parentNode; 699 var cell_index = td.cellIndex; 700 var row_index = tr.rowIndex; 701 var table = tr.parentNode; 702 cellMerge(table, cell_index, row_index, no_cols, no_rows); 703 }, null); 402 var tr = td.parentNode; 403 var cell_index = td.cellIndex; 404 var row_index = tr.rowIndex; 405 // pass cellMerge and the indices so apply() can call cellMerge and know 406 // what cell was selected when the dialog was opened 407 this.dialogMerge(cellMerge, cell_index, row_index); 704 408 } 705 409 break; … … 707 411 // PROPERTIES 708 412 709 case "TO-table-prop":413 case "TO-table-prop": 710 414 this.dialogTableProperties(); 711 415 break; 712 416 713 case "TO-row-prop":417 case "TO-row-prop": 714 418 this.dialogRowCellProperties(false); 715 419 break; 716 420 717 case "TO-cell-prop":421 case "TO-cell-prop": 718 422 this.dialogRowCellProperties(true); 719 423 break; 720 424 721 default:425 default: 722 426 alert("Button [" + button_id + "] not yet implemented"); 723 427 } … … 727 431 TableOperations.btnList = [ 728 432 // table properties button 729 ["table-prop", "table", "Table properties"],433 ["table-prop", "table", "Table properties"], 730 434 null, // separator 731 435 … … 754 458 ]; 755 459 756 757 758 //// GENERIC CODE [style of any element; this should be moved into a separate 759 //// file as it'll be very useful] 760 //// BEGIN GENERIC CODE ----------------------------------------------------- 761 762 TableOperations.getLength = function(value) { 763 var len = parseInt(value); 764 if (isNaN(len)) { 765 len = ""; 766 } 767 return len; 460 TableOperations.prototype.dialogMerge = function(merge_func, cell_index, row_index) { 461 var table = this.getClosest("table"); 462 var self = this; 463 var editor = this.editor; 464 465 if (!this.dialogMergeCellsHtml) { 466 Xinha._getback(Xinha.getPluginDir("TableOperations") + '/popups/dialogMergeCells.html', function(getback) { self.dialogMergeCellsHtml = getback; self.dialogMerge(merge_func, cell_index, row_index); }); 467 return; 468 } 469 470 if (!this.dialogMergeCells) { 471 this.dialogMergeCells = new Xinha.Dialog(editor, this.dialogMergeCellsHtml, 'TableOperations', {width:400}); 472 this.dialogMergeCells.getElementById('cancel').onclick = function() { self.dialogMergeCells.hide(); }; 473 } 474 475 var dialog = this.dialogMergeCells; 476 function apply() { 477 dialog.hide(); 478 no_cols = parseInt(dialog.getElementById('f_cols').value,10) + 1; 479 no_rows = parseInt(dialog.getElementById('f_rows').value,10) + 1; 480 merge_func(table, cell_index, row_index, no_cols, no_rows); 481 return 482 } 483 484 this.dialogMergeCells.getElementById('ok').onclick = apply; 485 this.dialogMergeCells.show(); 486 this.dialogMergeCells.getElementById('f_cols').focus(); 487 } 488 489 TableOperations.prototype.dialogTableProperties = function() { 490 491 var table = this.getClosest("table"); 492 var self = this; 493 var editor = this.editor; 494 495 if(!this.dialogTablePropertiesHtml){ // retrieve the raw dialog contents 496 Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogTable.html', function(getback) { self.dialogTablePropertiesHtml = getback; self.dialogTableProperties(); }); 497 return; 498 } 499 if (!this.dialogTable) { 500 // Now we have everything we need, so we can build the dialog. 501 this.dialogTable = new Xinha.Dialog(editor, this.dialogTablePropertiesHtml, 'TableOperations',{width:440}) 502 this.dialogTable.getElementById('cancel').onclick = function() { self.dialogTable.hide()}; 503 } 504 var dialog = this.dialogTable; 505 506 var Styler = new Xinha.InlineStyler(table, this.editor); 507 508 function apply() { 509 var params = dialog.hide(); 510 Styler.applyStyle(params); 511 512 for (var i in params) { 513 if(typeof params[i] == 'function') continue; 514 var val = params[i]; 515 if (typeof val == 'object' && val.tagName) val = val.value; 516 switch (i) { 517 case "caption": 518 if (/\S/.test(val)) { 519 // contains non white-space characters 520 var caption = table.getElementsByTagName("caption")[0]; 521 if (!caption) { 522 caption = dialog.editor._doc.createElement("caption"); 523 table.insertBefore(caption, table.firstChild); 524 } 525 caption.innerHTML = val; 526 } else { 527 // search for caption and delete it if found 528 var caption = table.getElementsByTagName("caption")[0]; 529 if (caption) { 530 caption.parentNode.removeChild(caption); 531 } 532 } 533 break; 534 case "summary": 535 table.summary = val; 536 break; 537 case "width": 538 table.style.width = ("" + val) + params.f_unit; 539 break; 540 case "align": 541 table.align = val; 542 break; 543 case "spacing": 544 table.cellSpacing = val; 545 break; 546 case "padding": 547 table.cellPadding = val; 548 break; 549 case "borders": 550 table.border = val; 551 break; 552 case "frames": 553 table.frame = val; 554 break; 555 case "rules": 556 table.rules = val; 557 break; 558 } 559 } 560 561 // various workarounds to refresh the table display (Gecko, 562 // what's going on?! do not disappoint me!) 563 self.editor.forceRedraw(); 564 self.editor.focusEditor(); 565 self.editor.updateToolbar(); 566 var save_collapse = table.style.borderCollapse; 567 table.style.borderCollapse = "collapse"; 568 table.style.borderCollapse = "separate"; 569 table.style.borderCollapse = save_collapse; 570 } 571 572 var st_layout = Styler.createStyleLayoutFieldset(); 573 var p = dialog.getElementById("TO_layout"); 574 p.replaceChild(st_layout,p.firstChild); 575 576 var st_prop = Styler.createStyleFieldset(); 577 p = dialog.getElementById("TO_style"); 578 p.replaceChild(st_prop,p.firstChild); 579 580 this.dialogTable.getElementById('ok').onclick = apply; 581 582 // gather element's values 583 var values = {}; 584 var capel = table.getElementsByTagName("caption")[0]; 585 if (capel) { 586 values['caption'] = capel.innerHTML; 587 } 588 else values['caption'] = ""; 589 values['summary'] = table.summary; 590 591 values['spacing'] = table.cellSpacing; 592 values['padding'] = table.cellPadding; 593 var f_borders = table.border; 594 595 values['frames'] = table.frame; 596 values['rules'] = table.rules; 597 598 this.dialogTable.show(values); 768 599 }; 769 600 770 // Applies the style found in "params" to the given element. 771 TableOperations.processStyle = function(params, element) { 772 var style = element.style; 773 for (var i in params) { 774 if(typeof params[i] == 'function') continue; 775 var val = params[i]; 776 switch (i) { 777 case "f_st_backgroundColor": 778 style.backgroundColor = val; 779 break; 780 case "f_st_color": 781 style.color = val; 782 break; 783 case "f_st_backgroundImage": 784 if (/\S/.test(val)) { 785 style.backgroundImage = "url(" + val + ")"; 786 } else { 787 style.backgroundImage = "none"; 788 } 789 break; 790 case "f_st_borderWidth": 791 style.borderWidth = val; 792 break; 793 case "f_st_borderStyle": 794 style.borderStyle = val; 795 break; 796 case "f_st_borderColor": 797 style.borderColor = val; 798 break; 799 case "f_st_borderCollapse": 800 style.borderCollapse = val ? "collapse" : ""; 801 break; 802 case "f_st_width": 803 if (/\S/.test(val)) { 804 style.width = val + params["f_st_widthUnit"]; 805 } else { 806 style.width = ""; 807 } 808 break; 809 case "f_st_height": 810 if (/\S/.test(val)) { 811 style.height = val + params["f_st_heightUnit"]; 812 } else { 813 style.height = ""; 814 } 815 break; 816 case "f_st_textAlign": 817 if (val == "char") { 818 var ch = params["f_st_textAlignChar"]; 819 if (ch == '"') { 820 ch = '\\"'; 821 } 822 style.textAlign = '"' + ch + '"'; 823 } else if (val == "-") { 824 style.textAlign = ""; 825 } else { 826 style.textAlign = val; 827 } 828 break; 829 case "f_st_verticalAlign": 830 element.vAlign = ""; 831 if (val == "-") { 832 style.verticalAlign = ""; 833 834 } else { 835 style.verticalAlign = val; 836 } 837 break; 838 case "f_st_float": 839 if (Xinha.is_ie) { 840 style.styleFloat = val; 841 } 842 else { 843 style.cssFloat = val; 844 } 845 break; 846 // case "f_st_margin": 847 // style.margin = val + "px"; 848 // break; 849 // case "f_st_padding": 850 // style.padding = val + "px"; 851 // break; 852 } 853 } 601 TableOperations.prototype.dialogRowCellProperties = function(cell) { 602 // retrieve existing values 603 var element = this.getClosest(cell ? "td" : "tr"); 604 var table = this.getClosest("table"); 605 606 var self = this; 607 var editor = this.editor; 608 609 if(!self.dialogRowCellPropertiesHtml) // retrieve the raw dialog contents 610 { 611 Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogRowCell.html', function(getback) { self.dialogRowCellPropertiesHtml = getback; self.dialogRowCellProperties(cell); }); 612 return; 613 } 614 if (!this.dialogRowCell) { 615 // Now we have everything we need, so we can build the dialog. 616 this.dialogRowCell = new Xinha.Dialog(editor, self.dialogRowCellPropertiesHtml, 'TableOperations',{width:440}) 617 this.dialogRowCell.getElementById('cancel').onclick = function() { self.dialogRowCell.hide()}; 618 } 619 620 var dialog = this.dialogRowCell; 621 dialog.getElementById('title').innerHTML = cell ? Xinha._lc("Cell Properties", "TableOperations") : Xinha._lc("Row Properties", "TableOperations"); 622 var Styler = new Xinha.InlineStyler(element, self.editor); 623 624 function apply() { 625 var params = dialog.hide(); 626 Styler.applyStyle(); 627 628 // various workarounds to refresh the table display (Gecko, 629 // what's going on?! do not disappoint me!) 630 self.editor.forceRedraw(); 631 self.editor.focusEditor(); 632 self.editor.updateToolbar(); 633 var save_collapse = table.style.borderCollapse; 634 table.style.borderCollapse = "collapse"; 635 table.style.borderCollapse = "separate"; 636 table.style.borderCollapse = save_collapse; 637 } 638 639 var st_layout = Styler.createStyleLayoutFieldset(); 640 var p = dialog.getElementById("TO_layout"); 641 642 p.replaceChild(st_layout,p.firstChild); 643 644 var st_prop = Styler.createStyleFieldset(); 645 p = dialog.getElementById("TO_style"); 646 p.replaceChild(st_prop,p.firstChild); 647 648 this.dialogRowCell.getElementById('ok').onclick = apply; 649 this.dialogRowCell.show(); 854 650 }; 855 856 // Returns an HTML element for a widget that allows color selection. That is,857 // a button that contains the given color, if any, and when pressed will popup858 // the sooner-or-later-to-be-rewritten select_color.html dialog allowing user859 // to select some color. If a color is selected, an input field with the name860 // "f_st_"+name will be updated with the color value in #123456 format.861 TableOperations.createColorButton = function(doc, editor, color, name) {862 if (!color) {863 color = "";864 } else if (!/#/.test(color)) {865 color = Xinha._colorToRgb(color);866 }867 868 var df = doc.createElement("span");869 var field = doc.createElement("input");870 field.type = "hidden";871 df.appendChild(field);872 field.name = "f_st_" + name;873 field.value = color;874 var button = doc.createElement("span");875 button.className = "buttonColor";876 df.appendChild(button);877 var span = doc.createElement("span");878 span.className = "chooser";879 // span.innerHTML = " ";880 span.style.backgroundColor = color;881 button.appendChild(span);882 button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};883 button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};884 span.onclick = function() {885 if (this.parentNode.disabled) {886 return false;887 }888 editor._popupDialog("select_color.html", function(color) {889 if (color) {890 span.style.backgroundColor = "#" + color;891 field.value = "#" + color;892 }893 }, color);894 };895 var span2 = doc.createElement("span");896 span2.innerHTML = "×";897 span2.className = "nocolor";898 span2.title = Xinha._lc("Unset color", "TableOperations");899 button.appendChild(span2);900 span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};901 span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};902 span2.onclick = function() {903 span.style.backgroundColor = "";904 field.value = "";905 };906 return df;907 };908 909 TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {910 var fieldset = doc.createElement("fieldset");911 var legend = doc.createElement("legend");912 fieldset.appendChild(legend);913 legend.innerHTML = Xinha._lc("Layout", "TableOperations");914 var table = doc.createElement("table");915 fieldset.appendChild(table);916 table.style.width = "100%";917 var tbody = doc.createElement("tbody");918 table.appendChild(tbody);919 920 var tagname = el.tagName.toLowerCase();921 var tr, td, input, select, option, options, i;922 923 if (tagname != "td" && tagname != "tr" && tagname != "th") {924 tr = doc.createElement("tr");925 tbody.appendChild(tr);926 td = doc.createElement("td");927 td.className = "label";928 tr.appendChild(td);929 td.innerHTML = Xinha._lc("Float", "TableOperations") + ":";930 td = doc.createElement("td");931 tr.appendChild(td);932 select = doc.createElement("select");933 td.appendChild(select);934 select.name = "f_st_float";935 options = ["None", "Left", "Right"];936 for (var i = 0; i < options.length; ++i) {937 var Val = options[i];938 var val = options[i].toLowerCase();939 option = doc.createElement("option");940 option.innerHTML = Xinha._lc(Val, "TableOperations");941 option.value = val;942 if (Xinha.is_ie) {943 option.selected = (("" + el.style.styleFloat).toLowerCase() == val);944 }945 else {946 option.selected = (("" + el.style.cssFloat).toLowerCase() == val);947 }948 select.appendChild(option);949 }950 }951 952 tr = doc.createElement("tr");953 tbody.appendChild(tr);954 td = doc.createElement("td");955 td.className = "label";956 tr.appendChild(td);957 td.innerHTML = Xinha._lc("Width", "TableOperations") + ":";958 td = doc.createElement("td");959 tr.appendChild(td);960 input = doc.createElement("input");961 input.type = "text";962 input.value = TableOperations.getLength(el.style.width);963 input.size = "5";964 input.name = "f_st_width";965 input.style.marginRight = "0.5em";966 td.appendChild(input);967 select = doc.createElement("select");968 select.name = "f_st_widthUnit";969 option = doc.createElement("option");970 option.innerHTML = Xinha._lc("percent", "TableOperations");971 option.value = "%";972 option.selected = /%/.test(el.style.width);973 select.appendChild(option);974 option = doc.createElement("option");975 option.innerHTML = Xinha._lc("pixels", "TableOperations");976 option.value = "px";977 option.selected = /px/.test(el.style.width);978 select.appendChild(option);979 td.appendChild(select);980 981 select.style.marginRight = "0.5em";982 td.appendChild(doc.createTextNode(Xinha._lc("Text align", "TableOperations") + ":"));983 select = doc.createElement("select");984 select.style.marginLeft = select.style.marginRight = "0.5em";985 td.appendChild(select);986 select.name = "f_st_textAlign";987 options = ["Left", "Center", "Right", "Justify", "-"];988 if (tagname == "td") {989 options.push("Char");990 }991 input = doc.createElement("input");992 input.name = "f_st_textAlignChar";993 input.size = "1";994 input.style.fontFamily = "monospace";995 td.appendChild(input);996 for (var i = 0; i < options.length; ++i) {997 var Val = options[i];998 var val = Val.toLowerCase();999 option = doc.createElement("option");1000 option.value = val;1001 option.innerHTML = Xinha._lc(Val, "TableOperations");1002 option.selected = ((el.style.textAlign.toLowerCase() == val) || (el.style.textAlign == "" && Val == "-"));1003 select.appendChild(option);1004 }1005 function setCharVisibility(value) {1006 input.style.visibility = value ? "visible" : "hidden";1007 if (value) {1008 input.focus();1009 input.select();1010 }1011 }1012 select.onchange = function() { setCharVisibility(this.value == "char"); };1013 setCharVisibility(select.value == "char");1014 1015 tr = doc.createElement("tr");1016 tbody.appendChild(tr);1017 td = doc.createElement("td");1018 td.className = "label";1019 tr.appendChild(td);1020 td.innerHTML = Xinha._lc("Height", "TableOperations") + ":";1021 td = doc.createElement("td");1022 tr.appendChild(td);1023 input = doc.createElement("input");1024 input.type = "text";1025 input.value = TableOperations.getLength(el.style.height);1026 input.size = "5";1027 input.name = "f_st_height";1028 input.style.marginRight = "0.5em";1029 td.appendChild(input);1030 select = doc.createElement("select");1031 select.name = "f_st_heightUnit";1032 option = doc.createElement("option");1033 option.innerHTML = Xinha._lc("percent", "TableOperations");1034 option.value = "%";1035 option.selected = /%/.test(el.style.height);1036 select.appendChild(option);1037 option = doc.createElement("option");1038 option.innerHTML = Xinha._lc("pixels", "TableOperations");1039 option.value = "px";1040 option.selected = /px/.test(el.style.height);1041 select.appendChild(option);1042 td.appendChild(select);1043 1044 select.style.marginRight = "0.5em";1045 td.appendChild(doc.createTextNode(Xinha._lc("Vertical align", "TableOperations") + ":"));1046 select = doc.createElement("select");1047 select.name = "f_st_verticalAlign";1048 select.style.marginLeft = "0.5em";1049 td.appendChild(select);1050 options = ["Top", "Middle", "Bottom", "Baseline", "-"];1051 for (var i = 0; i < options.length; ++i) {1052 var Val = options[i];1053 var val = Val.toLowerCase();1054 option = doc.createElement("option");1055 option.value = val;1056 option.innerHTML = Xinha._lc(Val, "TableOperations");1057 option.selected = ((el.style.verticalAlign.toLowerCase() == val) || (el.style.verticalAlign == "" && Val == "-"));1058 select.appendChild(option);1059 }1060 1061 return fieldset;1062 };1063 1064 // Returns an HTML element containing the style attributes for the given1065 // element. This can be easily embedded into any dialog; the functionality is1066 // also provided.1067 TableOperations.createStyleFieldset = function(doc, editor, el) {1068 var fieldset = doc.createElement("fieldset");1069 var legend = doc.createElement("legend");1070 fieldset.appendChild(legend);1071 legend.innerHTML = Xinha._lc("CSS Style", "TableOperations");1072 var table = doc.createElement("table");1073 fieldset.appendChild(table);1074 table.style.width = "100%";1075 var tbody = doc.createElement("tbody");1076 table.appendChild(tbody);1077 1078 var tr, td, input, select, option, options, i;1079 1080 tr = doc.createElement("tr");1081 tbody.appendChild(tr);1082 td = doc.createElement("td");1083 tr.appendChild(td);1084 td.className = "label";1085 td.innerHTML = Xinha._lc("Background", "TableOperations") + ":";1086 td = doc.createElement("td");1087 tr.appendChild(td);1088 var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");1089 df.firstChild.nextSibling.style.marginRight = "0.5em";1090 td.appendChild(df);1091 td.appendChild(doc.createTextNode(Xinha._lc("Image URL", "TableOperations") + ": "));1092 input = doc.createElement("input");1093 input.type = "text";1094 input.name = "f_st_backgroundImage";1095 if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {1096 input.value = RegExp.$1;1097 }1098 // input.style.width = "100%";1099 td.appendChild(input);1100 1101 tr = doc.createElement("tr");1102 tbody.appendChild(tr);1103 td = doc.createElement("td");1104 tr.appendChild(td);1105 td.className = "label";1106 td.innerHTML = Xinha._lc("FG Color", "TableOperations") + ":";1107 td = doc.createElement("td");1108 tr.appendChild(td);1109 td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));1110 1111 // for better alignment we include an invisible field.1112 input = doc.createElement("input");1113 input.style.visibility = "hidden";1114 input.type = "text";1115 td.appendChild(input);1116 1117 tr = doc.createElement("tr");1118 tbody.appendChild(tr);1119 td = doc.createElement("td");1120 tr.appendChild(td);1121 td.className = "label";1122 td.innerHTML = Xinha._lc("Border", "TableOperations") + ":";1123 td = doc.createElement("td");1124 tr.appendChild(td);1125 1126 var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");1127 var btn = colorButton.firstChild.nextSibling;1128 td.appendChild(colorButton);1129 // borderFields.push(btn);1130 btn.style.marginRight = "0.5em";1131 1132 select = doc.createElement("select");1133 var borderFields = [];1134 td.appendChild(select);1135 select.name = "f_st_borderStyle";1136 options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];1137 var currentBorderStyle = el.style.borderStyle;1138 // Gecko reports "solid solid solid solid" for "border-style: solid".1139 // That is, "top right bottom left" -- we only consider the first1140 // value.1141 if (currentBorderStyle.match(/([^\s]*)\s/)) currentBorderStyle = RegExp.$1;1142 for (var i=0;i<options.length;i++) {1143 var val = options[i];1144 option = doc.createElement("option");1145 option.value = val;1146 option.innerHTML = val;1147 if (val == currentBorderStyle) option.selected = true;1148 select.appendChild(option);1149 }1150 select.style.marginRight = "0.5em";1151 function setBorderFieldsStatus(value) {1152 for (var i = 0; i < borderFields.length; ++i) {1153 var el = borderFields[i];1154 el.style.visibility = value ? "hidden" : "visible";1155 if (!value && (el.tagName.toLowerCase() == "input")) {1156 el.focus();1157 el.select();1158 }1159 }1160 }1161 select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };1162 1163 input = doc.createElement("input");1164 borderFields.push(input);1165 input.type = "text";1166 input.name = "f_st_borderWidth";1167 input.value = TableOperations.getLength(el.style.borderWidth);1168 input.size = "5";1169 td.appendChild(input);1170 input.style.marginRight = "0.5em";1171 var span = doc.createElement("span");1172 span.innerHTML = Xinha._lc("pixels", "TableOperations");1173 td.appendChild(span);1174 borderFields.push(span);1175 1176 setBorderFieldsStatus(select.value == "none");1177 1178 if (el.tagName.toLowerCase() == "table") {1179 // the border-collapse style is only for tables1180 tr = doc.createElement("tr");1181 tbody.appendChild(tr);1182 td = doc.createElement("td");1183 td.className = "label";1184 tr.appendChild(td);1185 input = doc.createElement("input");1186 input.type = "checkbox";1187 input.name = "f_st_borderCollapse";1188 input.id = "f_st_borderCollapse";1189 var val = (/collapse/i.test(el.style.borderCollapse));1190 input.checked = val ? 1 : 0;1191 td.appendChild(input);1192 1193 td = doc.createElement("td");1194 tr.appendChild(td);1195 var label = doc.createElement("label");1196 label.htmlFor = "f_st_borderCollapse";1197 label.innerHTML = Xinha._lc("Collapsed borders", "TableOperations");1198 td.appendChild(label);1199 }1200 1201 // tr = doc.createElement("tr");1202 // tbody.appendChild(tr);1203 // td = doc.createElement("td");1204 // td.className = "label";1205 // tr.appendChild(td);1206 // td.innerHTML = Xinha._lc("Margin", "TableOperations") + ":";1207 // td = doc.createElement("td");1208 // tr.appendChild(td);1209 // input = doc.createElement("input");1210 // input.type = "text";1211 // input.size = "5";1212 // input.name = "f_st_margin";1213 // td.appendChild(input);1214 // input.style.marginRight = "0.5em";1215 // td.appendChild(doc.createTextNode(Xinha._lc("Padding", "TableOperations") + ":"));1216 1217 // input = doc.createElement("input");1218 // input.type = "text";1219 // input.size = "5";1220 // input.name = "f_st_padding";1221 // td.appendChild(input);1222 // input.style.marginLeft = "0.5em";1223 // input.style.marginRight = "0.5em";1224 // td.appendChild(doc.createTextNode(Xinha._lc("pixels", "TableOperations")));1225 1226 return fieldset;1227 };1228 1229 //// END GENERIC CODE ------------------------------------------------------- -
trunk/plugins/UnFormat/un-format.js
r856 r1044 1 1 // Unormat plugin for Xinha 2 3 4 UnFormat._pluginInfo = { 5 name : "UnFormat", 6 version : "1.0", 7 license : "htmlArea" 8 }; 2 9 3 10 … … 9 16 cfg.registerButton({ 10 17 id : "unformat", 11 tooltip : this._lc("Page Cleaner"),18 tooltip : Xinha._lc("Page Cleaner",'UnFormat'), 12 19 image : editor.imgURL("unformat.gif", "UnFormat"), 13 20 textMode : false, 14 21 action : function(editor) { 15 self. buttonPress(editor);22 self.show(); 16 23 } 17 24 }); … … 20 27 } 21 28 22 UnFormat._pluginInfo = { 23 name : "UnFormat", 24 version : "1.0", 25 license : "htmlArea" 29 UnFormat.prototype.onGenerateOnce = function(editor){ 30 // Load assets 31 var self = UnFormat; 32 if (self.loading) return; 33 self.loading = true; 34 self.methodsReady = true; 35 Xinha._getback(_editor_url + 'plugins/UnFormat/dialog.html', function(getback) { self.html = getback; self.dialogReady = true; }); 36 } 37 UnFormat.prototype.onUpdateToolbar = function(editor){ 38 if (!(UnFormat.dialogReady && UnFormat.methodsReady)) 39 { 40 this.editor._toolbarObjects.UnFormat.state("enabled", false); 41 } 42 else this.onUpdateToolbar = null; 43 44 } 45 UnFormat.prototype.prepareDialog = function(editor){ 46 var self = this; 47 var editor = this.editor; 48 49 var dialog = this.dialog = new Xinha.Dialog(editor, UnFormat.html, 'Xinha',{width:400}) 50 // Connect the OK and Cancel buttons 51 dialog.getElementById('ok').onclick = function() {self.apply();} 52 dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 53 54 this.dialogReady = true; 55 } 56 UnFormat.prototype.show = function(editor){ 57 if (!this.dialog) this.prepareDialog(); 58 59 var editor = this.editor; 60 61 var values = 62 { 63 "cleaning_area" : 'selection', 64 "formatting" : '', 65 "html_all" : '' 66 } 67 // now calling the show method of the Xinha.Dialog object to set the values and show the actual dialog 68 this.dialog.show(values); 69 this.dialog.onresize(); 70 } 71 UnFormat.prototype.apply = function(editor){ 72 var editor = this.editor; 73 var doc = editor._doc; 74 var param = this.dialog.getValues(); 75 76 // selection is only restored on dialog.hide() 77 this.dialog.hide(); 78 // assign the given arguments 79 80 if (param["cleaning_area"] == "all") { 81 var html = editor._doc.body.innerHTML; 82 } else { 83 var html = editor.getSelectedHTML(); 84 } 85 86 if (param.html_all) { 87 html = html.replace(/<[\!]*?[^<>]*?>/g, ""); 88 } 89 90 if (param.formatting) { 91 html = html.replace(/style="[^"]*"/gi, ""); 92 html = html.replace(/<\/?font[^>]*>/gi,""); 93 html = html.replace(/<\/?b>/gi,""); 94 html = html.replace(/<\/?strong[^>]*>/gi,""); 95 html = html.replace(/<\/?i>/gi,""); 96 html = html.replace(/<\/?em[^>]*>/gi,""); 97 html = html.replace(/<\/?u[^>]*>/gi,""); 98 html = html.replace(/<\/?strike[^>]*>/gi,""); 99 html = html.replace(/ align=[^\s|>]*/gi,""); 100 html = html.replace(/ class=[^\s|>]*/gi,""); 101 } 102 if (param["cleaning_area"] == "all") { 103 editor._doc.body.innerHTML = html; 104 } else { 105 editor.insertHTML(html); 106 } 26 107 }; 27 28 29 UnFormat.prototype._lc = function(string) {30 return Xinha._lc(string, 'UnFormat');31 };32 33 UnFormat.prototype.buttonPress = function(editor){34 editor._popupDialog( "plugin://UnFormat/unformat", function( param){35 if (param) {36 if (param["cleaning_area"] == "all") {37 var html = editor._doc.body.innerHTML;38 } else {39 var html = editor.getSelectedHTML();40 }41 42 if (param["html_all"]== true) {43 html = html.replace(/<[\!]*?[^<>]*?>/g, "");44 }45 46 if (param["formatting"] == true) {47 html = html.replace(/style="[^"]*"/gi, "");48 html = html.replace(/<\/?font[^>]*>/gi,"");49 html = html.replace(/<\/?b>/gi,"");50 html = html.replace(/<\/?strong[^>]*>/gi,"");51 html = html.replace(/<\/?i>/gi,"");52 html = html.replace(/<\/?em[^>]*>/gi,"");53 html = html.replace(/<\/?u[^>]*>/gi,"");54 html = html.replace(/<\/?strike[^>]*>/gi,"");55 html = html.replace(/ align=[^\s|>]*/gi,"");56 html = html.replace(/ class=[^\s|>]*/gi,"");57 }58 if (param["cleaning_area"] == "all") {59 editor._doc.body.innerHTML = html;60 } else {61 editor.insertHTML(html);62 }63 } else { return false; }64 }, null);65 };
