- Timestamp:
- 02/24/07 15:47:57 (13 years ago)
- Location:
- branches/ray
- Files:
-
- 10 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ray/Xinha.css
r761 r762 108 108 .dialog { 109 109 color: ButtonText; 110 background: ButtonFace; 111 } 112 110 background: ButtonFace; 111 border: 1px outset; 112 border-color: WindowFrame; 113 } 114 div.dialog { 115 padding-bottom:10px; 116 } 117 .xinha_dialog_background { 118 background-color:#666; 119 filter: alpha(opacity = 70); 120 -moz-opacity: 0.7; 121 opacity: 0.7; 122 border:none; 123 } 113 124 .dialog .content { padding: 2px; } 114 125 … … 121 132 .dialog .title, .dialog h1 122 133 { 123 background: #008;124 color: #ff8;134 background: ActiveCaption; 135 color: CaptionText; 125 136 border-bottom: 1px solid #000; 126 137 padding: 1px 0px 2px 5px; … … 128 139 font-weight: bold; 129 140 cursor: default; 130 } 131 .dialog h1 { margin:0px;} 141 letter-spacing: 0.01em; 142 } 143 .dialog h1 { margin:0;} 132 144 .dialog .title .button { 133 145 float: right; … … 142 154 143 155 .dialog button { 144 width: 5 em;156 width: 5.5em; 145 157 padding: 0px; 146 158 } 147 159 .dialog .closeButton { 160 padding: 0px; 161 cursor: default; 162 border: 1px solid; 163 border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; 164 height : 11px; 165 width : 11px; 166 vertical-align : top; 167 position : absolute; 168 top : 3px; 169 right : 2px; 170 background-color: ButtonFace; 171 color: ButtonText; 172 font-size: 13px; 173 font-family: Tahoma,Verdana,sans-serif; 174 text-align:center; 175 letter-spacing:0; 176 overflow:hidden; 177 } 148 178 .dialog .buttonColor { 179 width :1em; 149 180 padding: 1px; 150 181 cursor: default; … … 153 184 } 154 185 186 .dialog .buttonClick { 187 border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; 188 } 155 189 .dialog .buttonColor-hilite { 156 190 border-color: #000; … … 169 203 .dialog .label { text-align: right; width: 6em; } 170 204 .dialog .value input { width: 100%; } 171 .dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }172 205 173 206 .dialog legend { font-weight: bold; } 174 207 .dialog fieldset table { margin: 2px 0px; } 175 208 209 .dialog .buttons { 210 211 padding: 1em; 212 text-align: center; 213 } 214 .dialog .resizeHandle { 215 -moz-appearance : resizer; 216 width: 12px; 217 height: 12px; 218 border-bottom: 2px solid #000; 219 border-right: 2px solid #000; 220 cursor : nw-resize; 221 } 176 222 .popupwin { 177 223 padding: 0px; … … 228 274 padding: 2px; 229 275 clear:left; 230 276 letter-spacing: 0.01em; 231 277 } 232 278 -
branches/ray/XinhaCore.js
r761 r762 507 507 this.debug = true; 508 508 509 // ATTENTION: implementing custom image/link/table popups using this uris is DEPRECATED 509 510 this.URIs = 510 511 { … … 1278 1279 function(ev) 1279 1280 { 1281 ev = Xinha.is_ie ? window.event : ev; 1282 editor.btnClickEvent = ev; 1280 1283 if ( obj.enabled ) 1281 1284 { … … 1287 1290 } 1288 1291 obj.cmd(editor, obj.name, obj); 1289 Xinha._stopEvent( Xinha.is_ie ? window.event :ev);1292 Xinha._stopEvent(ev); 1290 1293 } 1291 1294 } … … 1553 1556 if ( typeof InsertImage == 'undefined' && typeof Xinha.prototype._insertImage == 'undefined' ) 1554 1557 { 1555 Xinha.loadPlugin("InsertImage", function() { editor.generate(); } , _editor_url + 'modules/InsertImage/insert_image.js'); 1558 var url = (this.config.URIs.insert_image != _editor_url + "modules/InsertImage/insert_image.html") ? _editor_url + "modules/InsertImage/insert_image.js" : _editor_url + "modules/InsertImage/InsertImage.js"; 1559 Xinha.loadPlugin("InsertImage", function() { editor.generate(); } , _editor_url + 'modules/InsertImage/InsertImage.js'); 1556 1560 return false; 1557 1561 } … … 1561 1565 if ( typeof CreateLink == 'undefined' && typeof Xinha.prototype._createLink == 'undefined' && typeof Linker == 'undefined' ) 1562 1566 { 1563 Xinha.loadPlugin("CreateLink", function() { editor.generate(); } , _editor_url + 'modules/CreateLink/link.js'); 1567 var url = (this.config.URIs.link != _editor_url + "modules/CreateLink/link.html") ? _editor_url + "modules/CreateLink/link.js" : _editor_url + "modules/CreateLink/CreateLink.js"; 1568 Xinha.loadPlugin("CreateLink", function() { editor.generate(); } , url); 1564 1569 return false; 1565 1570 } … … 1569 1574 if ( typeof InsertTable == 'undefined' && typeof Xinha.prototype._insertTable == 'undefined' ) 1570 1575 { 1571 Xinha.loadPlugin("InsertTable", function() { editor.generate(); } , _editor_url + 'modules/InsertTable/insert_table.js'); 1576 var url = (this.config.URIs.insert_table != _editor_url + "modules/InsertTable/insert_table.html") ? _editor_url + "modules/InsertTable/insert_table.js" : _editor_url + "modules/InsertTable/InsertTable.js"; 1577 Xinha.loadPlugin("InsertTable", function() { editor.generate(); } , url); 1572 1578 return false; 1573 1579 } … … 4999 5005 } 5000 5006 } 5007 else if (req.status == 404) 5008 { 5009 alert('File not found: ' + url); 5010 } 5001 5011 else 5002 5012 { 5003 alert('An error has occurred: ' + req.statusText );5013 alert('An error has occurred: ' + req.statusText + '\nURL: ' + url); 5004 5014 } 5005 5015 } … … 5027 5037 handler(req.responseText, req); 5028 5038 } 5039 else if (req.status == 404) 5040 { 5041 alert('File not found: ' + url); 5042 } 5029 5043 else 5030 5044 { 5031 alert('An error has occurred: ' + req.statusText );5045 alert('An error has occurred: ' + req.statusText + '\nURL: ' + url); 5032 5046 } 5033 5047 } -
branches/ray/examples/ext_example-body.html
r761 r762 12 12 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 13 13 <title>Example of Xinha</title> 14 <link rel="stylesheet" type="text/css" href="full_example.css" /> 14 15 15 16 16 <script type="text/javascript"> -
branches/ray/examples/testbed.html
r761 r762 1 <?xml version="1.0" encoding="UTF-8"?>2 1 <!DOCTYPE html 3 2 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" … … 55 54 xinha_plugins = xinha_plugins ? xinha_plugins : 56 55 [ 57 'CharacterMap', 'SpellChecker', 'Linker' 56 'CharacterMap', 'SpellChecker', 'SmartReplace','PasteText','SuperClean' 57 //'Linker'//,'GetHtml' 58 58 ]; 59 59 // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING :) … … 67 67 xinha_editors = xinha_editors ? xinha_editors : 68 68 [ 69 'myTextArea' 69 'HAllo', 70 'myTextArea' 71 70 72 ]; 71 73 … … 84 86 85 87 xinha_config = xinha_config ? xinha_config : new Xinha.Config(); 86 xinha_config.fullPage = true; 88 xinha_config.width = 300; 89 xinha_config.height = 300; 90 xinha_config.fullPage = false; 87 91 xinha_config.CharacterMap.mode = 'panel'; 92 xinha_config.toolbar = 93 [ 94 ["popupeditor"], 95 ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"], 96 ["separator","forecolor","hilitecolor","textindicator"], 97 ["separator","subscript","superscript"], 98 ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"], 99 ["separator","insertorderedlist","insertunorderedlist","outdent","indent"], 100 ["separator","inserthorizontalrule","createlink","insertimage","inserttable"], 101 ["linebreak","separator","undo","redo","selectall","print"], (Xinha.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]), 102 ["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright", "righttoleft"], 103 ["separator","htmlmode","showhelp","about"] 104 ]; 88 105 /* 89 106 // We can load an external stylesheet like this - NOTE : YOU MUST GIVE AN ABSOLUTE URL … … 142 159 </head> 143 160 144 <body> 145 146 <form action="javascript:var x = document.getElementById('editors_here');alert(x.myTextArea.value);" id="editors_here" onsubmit="alert(this.myTextArea.value);"> 147 <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320px;"> 148 <html> 149 <head> 150 <title>Hello</title> 151 <style type="text/css"> 152 li { color:red; } 153 </style> 154 </head> 155 <body> 156 <img src="http://xinha.python-hosting.com/trac/logo.jpg" usemap="#m1"> 157 <map name="m1"> 158 <area shape="rect" coords="137,101,255,124" href="http://www.mydomain.com"> 159 </map> 160 161 <p> 162 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 163 Aliquam et tellus vitae justo varius placerat. Suspendisse iaculis 164 velit semper dolor. Donec gravida tincidunt mi. Curabitur tristique 165 ante elementum turpis. Aliquam nisl. Nulla posuere neque non 166 tellus. Morbi vel nibh. Cum sociis natoque penatibus et magnis dis 167 parturient montes, nascetur ridiculus mus. Nam nec wisi. In wisi. 168 Curabitur pharetra bibendum lectus. 169 </p> 170 171 <ul> 172 <li> Phasellus et massa sed diam viverra semper. </li> 173 <li> Mauris tincidunt felis in odio. </li> 174 <li> Nulla placerat nunc ut pede. </li> 175 <li> Vivamus ultrices mi sit amet urna. </li> 176 <li> Quisque sed augue quis nunc laoreet volutpat.</li> 177 <li> Nunc sit amet metus in tortor semper mattis. </li> 178 </ul> 179 </body> 180 </html> 181 </textarea> 161 <body bgcolor="Aqua"> 162 163 <form action="test_dest.php" id="editors_here" onsubmit="alert(this.myTextArea.value);"> 164 <input type="checkbox" name="hallo" /> 165 <select> 166 <option>Test</option> 167 </select> 168 <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320px;"> 169 <table cellspacing="1" cellpadding="1" border="1" style="width: 100%;"><tbody><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr></tbody></table><br /></textarea> 170 171 <input type="submit" /> <input type="reset" /><input type="checkbox" name="hallo" /> 172 <select> 173 <option>Test</option> 174 </select> 175 <textarea name="myTextArea" style="width:100%;height:320px;"> 176 <table cellspacing="1" cellpadding="1" border="1" style="width: 100%;"><tbody><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr></tbody></table><br /></textarea> 177 178 <input type="submit" /> <input type="reset" /><input type="checkbox" name="hallo" /> 179 <select> 180 <option>Test</option> 181 </select> 182 <textarea name="myTextArea" style="width:100%;height:320px;"> 183 <table cellspacing="1" cellpadding="1" border="1" style="width: 100%;"><tbody><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr></tbody></table><br /></textarea> 184 185 <input type="submit" /> <input type="reset" /><input type="checkbox" name="hallo" /> 186 <select> 187 <option>Test</option> 188 </select> 189 <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320px;"> 190 <table cellspacing="1" cellpadding="1" border="1" style="width: 100%;"><tbody><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr></tbody></table><br /></textarea> 191 192 <input type="submit" /> <input type="reset" /><input type="checkbox" name="hallo" /> 193 <select> 194 <option>Test</option> 195 </select> 196 <textarea name="myTextArea" style="width:100%;height:320px;"> 197 <table cellspacing="1" cellpadding="1" border="1" style="width: 100%;"><tbody><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr><tr><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td><td style="width: 25%;"> </td></tr></tbody></table><br /></textarea> 182 198 183 199 <input type="submit" /> <input type="reset" /> -
branches/ray/modules/ColorPicker/ColorPicker.js
r761 r762 132 132 this.table.appendChild(this.tbody); 133 133 this.table.style.border = '1px solid WindowFrame'; 134 this.table.style.zIndex = '10 00';134 this.table.style.zIndex = '1050'; 135 135 // Add a title bar and close button 136 136 var tr = document.createElement('tr'); … … 141 141 td.style.fontFamily = 'small-caption,caption,sans-serif'; 142 142 td.style.fontSize = 'x-small'; 143 td.unselectable = "on"; 144 td.style.MozUserSelect = "none"; 143 145 td.appendChild(document.createTextNode(Xinha._lc('Click a color...'))); 144 146 td.style.borderBottom = '1px solid WindowFrame'; … … 829 831 return Xinha._lc(string); 830 832 } 833 Xinha.colorPicker.inputBinding = function(input) 834 { 835 var main = document.createElement('span'); 836 main.className = "buttonColor"; 837 838 var chooser = this.chooser = document.createElement('span'); 839 chooser.className = "chooser"; 840 chooser.onmouseover = function() {main.style.borderColor='black';chooser.style.borderColor='black'}; 841 chooser.onmouseout = function() {main.style.borderColor='ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight',chooser.style.borderColor='ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight'}; 842 chooser.appendChild(document.createTextNode('\u00a0')); 843 main.appendChild(chooser); 844 var clearColor = document.createElement('span'); 845 clearColor.className = "nocolor"; 846 clearColor.onmouseover = function() {clearColor.style.color='#f00'}; 847 clearColor.onmouseout = function() {clearColor.style.color='#000'}; 848 clearColor.onclick = function() {input.value ='';chooser.style.backgroundColor = ''}; 849 clearColor.appendChild(document.createTextNode('\u00d7')); 850 main.appendChild(clearColor); 851 852 input.parentNode.insertBefore(main,input.nextSibling); 853 854 Xinha._addEvent(input,'change',function() {chooser.style.backgroundColor = this.value;}) 855 856 chooser.onclick = function() 857 { 858 var colPicker = new Xinha.colorPicker({cellsize:'5px',callback:function(color) {chooser.style.backgroundColor = color;input.value=color}}); 859 colPicker.open('left',chooser, input.value ); 860 } 861 } 862 Xinha.colorPicker.inputBinding.prototype.setColor = function(color) 863 { 864 this.chooser.style.backgroundColor = color; 865 } -
branches/ray/modules/Dialogs/inline-dialog.js
r761 r762 21 21 -- $LastChangedBy$ 22 22 --------------------------------------------------------------------------*/ 23 Xinha.Dialog = function(editor, html, localizer) 24 { 23 Xinha.Dialog = function(editor, html, localizer, size, layer) 24 { 25 var dialog = this; 25 26 this.id = { }; 26 27 this.r_id = { }; // reverse lookup id 27 28 this.editor = editor; 28 29 this.document = document; 29 30 this.rootElem = document.createElement('div'); 31 this.rootElem.className = 'dialog'; 32 this.rootElem.style.position = 'absolute'; 33 this.rootElem.style.display = 'none'; 34 this.editor._framework.ed_cell.insertBefore(this.rootElem, this.editor._framework.ed_cell.firstChild); 35 this.rootElem.style.width = this.width = this.editor._framework.ed_cell.offsetWidth + 'px'; 36 this.rootElem.style.height = this.height = this.editor._framework.ed_cell.offsetHeight + 'px'; 37 38 var dialog = this; 30 this.layer = (layer) ? layer : 0; 31 32 if ( !Xinha.Dialog.background[this.layer] ) 33 { 34 Xinha.Dialog.background[this.layer] = []; 35 36 if (Xinha.is_ie) 37 { // IE6 needs the iframe to hide select boxes 38 var backG = document.createElement("iframe"); 39 backG.src = "about:blank"; 40 } 41 else 42 { // Mozilla (<FF3) can't have the iframe, because it hides the caret in text fields 43 // see https://bugzilla.mozilla.org/show_bug.cgi?id=226933 44 // unfortunately https://bugzilla.mozilla.org/show_bug.cgi?id=230701 indicates that this is an issue with pos fixed div, too 45 var backG = document.createElement("div"); 46 } 47 backG.className = "xinha_dialog_background"; 48 with (backG.style) 49 { 50 position = "absolute";//(Xinha.is_ie) ? "absolute" : "fixed"; 51 top = 0; 52 left = 0; 53 border = 'none'; 54 overflow = "hidden"; 55 display = "none"; 56 zIndex = 1001 + this.layer; 57 } 58 document.body.appendChild(backG); 59 Xinha.Dialog.background[this.layer].push(backG); 60 61 backG = document.createElement("div"); 62 with (backG.style) 63 { 64 position = "absolute";//(Xinha.is_ie) ? "absolute" : "fixed"; 65 top = 0; 66 left = 0; 67 overflow = "hidden"; 68 display = "none"; 69 zIndex = 1002+ this.layer; 70 } 71 document.body.appendChild(backG); 72 Xinha.Dialog.background[this.layer].push(backG); 73 } 74 var rootElem = document.createElement('div'); 75 rootElem.style.position = 'absolute'; 76 rootElem.style.zIndex = 1003+ this.layer; 77 rootElem.style.display = 'none'; 78 79 // FIXME: This is nice, but I don't manage to get it switched off on text inputs :( 80 // rootElem.style.MozUserSelect = "none"; 81 82 rootElem.className = 'dialog'; 83 84 // Xinha.Dialog.background[this.layer][1].appendChild(rootElem); 85 document.body.appendChild(rootElem); 86 87 rootElem.style.paddingBottom = "10px"; 88 rootElem.style.width = size.width + 'px'; 89 90 91 this.size = size; 92 if (size.height) 93 { 94 if (Xinha.ie_version < 7) 95 { 96 rootElem.style.height = size.height + 'px'; 97 } 98 else 99 { 100 rootElem.style.minHeight = size.height + 'px'; 101 } 102 } 103 39 104 if(typeof localizer == 'function') 40 105 { … … 78 143 ); 79 144 80 this.rootElem.innerHTML = html; 81 82 83 84 85 this.editor.notifyOn 86 ('resize', 87 function(e, args) 145 rootElem.innerHTML = html; 146 147 //make the first h1 to drag&drop the rootElem 148 var titleBar = rootElem.getElementsByTagName("h1")[0]; 149 titleBar.onmousedown = function(ev) { dialog._dragStart(ev); }; 150 titleBar.style.MozUserSelect = "none"; 151 152 var but = document.createElement('div'); 153 but.className= 'closeButton'; 154 155 but.onmousedown = function(ev) { this.className = "closeButton buttonClick"; Xinha._stopEvent((ev) ? ev : window.event); return false;}; 156 but.onmouseout = function(ev) { this.className = "closeButton"; Xinha._stopEvent((ev) ? ev : window.event); return false;}; 157 but.onmouseup = function() { this.className = "closeButton"; dialog.hide(); return false;}; 158 titleBar.appendChild(but); 159 160 var butX = document.createElement('span'); 161 butX.style.position = 'relative'; 162 butX.style.top = '-3px'; 163 164 butX.appendChild(document.createTextNode('\u00D7')); 165 but.appendChild(butX); 166 167 var icon = document.createElement('img'); 168 icon.src = _editor_url + 'images/xinha-small-icon.gif'; 169 icon.style.position = 'absolute'; 170 icon.style.top = '3px'; 171 icon.style.left = '2px'; 172 titleBar.style.paddingLeft = '30px'; 173 titleBar.appendChild(icon); 174 175 var all = rootElem.getElementsByTagName("*"); 176 177 for (var i=0; i<all.length;i++) 178 { 179 var el = all[i]; 180 if (el.tagName.toLowerCase() == 'textarea' || el.tagName.toLowerCase() == 'input') 181 { 182 // FIXME: this doesn't work 183 //el.style.MozUserSelect = "text"; 184 } 185 else 186 { 187 el.unselectable = "on"; 188 } 189 } 190 191 var resizeHandle = document.createElement('div'); 192 resizeHandle.className = "resizeHandle"; 193 with (resizeHandle.style) 194 { 195 position = "absolute"; 196 bottom = "0px"; 197 right= "0px"; 198 } 199 resizeHandle.onmousedown = function(ev) { dialog._resizeStart(ev); }; 200 rootElem.appendChild(resizeHandle); 201 this.rootElem = rootElem; 202 // for caching size & position after dragging & resizing 203 this.size = {}; 204 }; 205 206 Xinha.Dialog.background = []; 207 Xinha.Dialog.prototype.sizeBackground = function() 208 { 209 var win_dim = Xinha.viewportSize(); 210 Xinha.Dialog.background[this.layer][0].style.width = win_dim.x + 'px'; 211 Xinha.Dialog.background[this.layer][0].style.height = win_dim.y + 'px'; 212 Xinha.Dialog.background[this.layer][1].style.width = win_dim.x + 'px'; 213 Xinha.Dialog.background[this.layer][1].style.height = win_dim.y + 'px'; 214 window.scroll(this.scrollPos.x, this.scrollPos.y); 215 return win_dim; 216 } 217 218 Xinha.Dialog.prototype.onresize = function() 219 { 220 return true; 221 }; 222 223 Xinha.Dialog.prototype.show = function(values) 224 { 225 var rootElem = this.rootElem; 226 var scrollPos = this.scrollPos = this.editor.scrollPos(); 227 var dialog = this; 228 229 function resetScroll() 230 { 231 if ( dialog.dialogShown ) 232 { 233 window.scroll(scrollPos.x,scrollPos.y); 234 window.setTimeout(resetScroll,150); 235 } 236 } 237 Xinha.Dialog.background[this.layer][0].style.left = this.scrollPos.x + 'px'; 238 Xinha.Dialog.background[this.layer][0].style.top = this.scrollPos.y + 'px'; 239 Xinha.Dialog.background[this.layer][1].style.left = this.scrollPos.x + 'px'; 240 Xinha.Dialog.background[this.layer][1].style.top = this.scrollPos.y + 'px'; 241 242 // We need to preserve the selection 243 if(Xinha.is_ie) 244 { 245 this._lastRange = this.editor._createRange(this.editor._getSelection()); 246 } 247 else 248 { 249 this._lastRange = this.editor._createRange(this.editor._getSelection()).cloneRange(); 250 } 251 this.editor.deactivateEditor(); 252 253 // unfortunately we have to hide the editor (iframe/caret bug) 254 if (Xinha.is_gecko) 255 { 256 this._restoreTo = [this.editor._textArea.style.display, this.editor._iframe.style.visibility, this.editor.hidePanels()]; 257 this.editor._textArea.style.display = 'none'; 258 this.editor._iframe.style.visibility = 'hidden'; 259 } 260 if (!this.editor._isFullScreen) 261 { 262 if(Xinha.is_ie && document.compatMode == 'CSS1Compat') 263 { 264 var bod = document.getElementsByTagName('html'); 265 } 266 else 267 { 268 var bod = document.getElementsByTagName('body'); 269 } 270 271 bod[0].style.overflow='hidden'; 272 window.scroll(this.scrollPos.x, this.scrollPos.y); 273 } 274 275 Xinha.Dialog.background[this.layer][0].style.display = ''; 276 Xinha.Dialog.background[this.layer][1].style.display = ''; 277 278 var backgroundSize = this.sizeBackground(); 279 var backgroundHeight = backgroundSize.y; 280 var backgroundWidth = backgroundSize.x; 281 282 this.onResizeWin = function () {dialog.sizeBackground()}; 283 Xinha._addEvent(window, 'resize', this.onResizeWin ); 284 285 286 287 var rootElemStyle = rootElem.style; 288 rootElemStyle.display = ''; 289 290 var dialogHeight = rootElem.offsetHeight; 291 var dialogWidth = rootElem.offsetWidth; 292 293 if (dialogHeight > backgroundHeight) 294 { 295 rootElemStyle.height = backgroundHeight + "px"; 296 if (rootElem.scrollHeight > dialogHeight) 297 { 298 rootElemStyle.overflowY = "auto"; 299 } 300 } 301 302 if(this.size.top && this.size.left) 303 { 304 rootElemStyle.top = parseInt(this.size.top,10) + 'px'; 305 rootElemStyle.left = parseInt(this.size.left,10) + 'px'; 306 } 307 else 308 { 309 if (this.editor.btnClickEvent) 310 { 311 var btnClickEvent = this.editor.btnClickEvent; 312 rootElemStyle.top = btnClickEvent.clientY + this.scrollPos.y +'px'; 313 314 if (dialogHeight + rootElem.offsetTop > backgroundHeight) 88 315 { 89 dialog.rootElem.style.width = dialog.width = dialog.editor._framework.ed_cell.offsetWidth + 'px'; 90 dialog.rootElem.style.height = dialog.height = dialog.editor._framework.ed_cell.offsetHeight + 'px'; 91 dialog.onresize(); 316 rootElemStyle.top = this.scrollPos.y; 92 317 } 93 ); 94 }; 95 96 Xinha.Dialog.prototype.onresize = function() 97 { 98 return true; 99 }; 100 101 Xinha.Dialog.prototype.show = function(values) 102 { 103 // We need to preserve the selection for IE 104 if(Xinha.is_ie) 105 { 106 this._lastRange = this.editor._createRange(this.editor._getSelection()); 107 } 108 318 rootElemStyle.left = btnClickEvent.clientX + this.scrollPos.x +'px'; 319 if (dialogWidth + rootElem.offsetLeft > backgroundWidth) 320 { 321 rootElemStyle.left = btnClickEvent.clientX - dialogWidth + 'px'; 322 if (rootElem.offsetLeft < 0) 323 { 324 rootElemStyle.left = 0; 325 } 326 } 327 this.editor.btnClickEvent = null; 328 } 329 else 330 { 331 var top = ( backgroundHeight - dialogHeight) / 2; 332 var left = ( backgroundWidth - dialogWidth) / 2; 333 rootElemStyle.top = ((top > 0) ? top : 0) +'px'; 334 rootElemStyle.left = ((left > 0) ? left : 0)+'px'; 335 } 336 337 } 338 this.width = dialogWidth; 339 this.height = dialogHeight; 340 109 341 if(typeof values != 'undefined') 110 342 { 111 343 this.setValues(values); 112 344 } 113 this._restoreTo = [this.editor._textArea.style.display, this.editor._iframe.style.visibility, this.editor.hidePanels()]; 114 115 this.editor._textArea.style.display = 'none'; 116 this.editor._iframe.style.visibility = 'hidden'; 117 this.rootElem.style.display = ''; 345 this.dialogShown = true; 346 resetScroll(); 118 347 }; 119 348 120 349 Xinha.Dialog.prototype.hide = function() 121 350 { 122 this.rootElem.style.display = 'none'; 123 this.editor._textArea.style.display = this._restoreTo[0]; 124 this.editor._iframe.style.visibility = this._restoreTo[1]; 125 this.editor.showPanels(this._restoreTo[2]); 126 127 // Restore the selection 128 if(Xinha.is_ie) 129 { 351 this.rootElem.style.display = 'none'; 352 Xinha.Dialog.background[this.layer][0].style.display = 'none'; 353 Xinha.Dialog.background[this.layer][1].style.display = 'none'; 354 var dialog = this; 355 356 Xinha._removeEvent(window, 'resize', this.onResizeWin); 357 358 if (Xinha.is_gecko) 359 { 360 this.editor._textArea.style.display = this._restoreTo[0]; 361 this.editor._iframe.style.visibility = this._restoreTo[1]; 362 this.editor.showPanels(this._restoreTo[2]); 363 } 364 365 if (!this.editor._isFullScreen) 366 { 367 if(Xinha.is_ie && document.compatMode == 'CSS1Compat') 368 { 369 var bod = document.getElementsByTagName('html'); 370 } 371 else 372 { 373 var bod = document.getElementsByTagName('body'); 374 } 375 bod[0].style.overflow=''; 376 window.scroll(this.scrollPos.x, this.scrollPos.y); 377 } 378 // Restore the selection 379 this.editor.activateEditor(); 380 if (Xinha.is_gecko) 381 { 382 var sel = this.editor.getSelection(); 383 sel.removeAllRanges(); 384 sel.addRange(this._lastRange); 385 } 386 else 387 { 130 388 this._lastRange.select(); 131 389 } 390 this.dialogShown = false; 132 391 this.editor.updateToolbar(); 133 392 return this.getValues(); … … 144 403 this.hide(); 145 404 } 405 }; 406 407 Xinha.Dialog.prototype.getElementById = function(id) 408 { 409 return this.document.getElementById(this.id[id] ? this.id[id] : id); 410 }; 411 412 Xinha.Dialog.prototype.getElementsByName = function(name) 413 { 414 return this.document.getElementsByName(this.id[name] ? this.id[name] : name); 415 }; 416 417 Xinha.Dialog.prototype._dragStart = function (ev) 418 { 419 420 var dialog = this; 421 if (dialog.dragging) 422 { 423 return; 424 } 425 dialog.dragging = true; 426 427 var st = dialog.rootElem.style; 428 429 dialog.xOffs = ((Xinha.is_ie) ? window.event.offsetX : ev.layerX); 430 dialog.yOffs = ((Xinha.is_ie) ? window.event.offsetY : ev.layerY); 431 432 Xinha._addEvent(document, "mousemove", function(ev) { dialog.dragIt(ev); } ); 433 Xinha._addEvent(document, "mouseup", function (ev) { dialog.dragEnd(ev); } ); 434 }; 435 436 Xinha.Dialog.prototype.dragIt = function(ev) 437 { 438 var dialog = this; 439 440 if (!dialog.dragging) 441 { 442 return false; 443 } 444 ev = (Xinha.is_ie) ? window.event : ev; 445 446 var posY = ev.clientY + this.scrollPos.y; 447 var posX = ev.clientX + this.scrollPos.x; 448 449 var st = dialog.rootElem.style; 450 451 st.left = (posX - dialog.xOffs) + "px"; 452 st.top = (posY - dialog.yOffs) + "px"; 453 }; 454 455 Xinha.Dialog.prototype.dragEnd = function(ev) 456 { 457 var dialog = this; 458 dialog.dragging = false; 459 460 Xinha._removeEvent(document, "mousemove", function(ev) { dialog.dragIt(ev); } ); 461 Xinha._removeEvent(document, "mouseup", function (ev) { dialog.dragEnd(ev); } ); 462 463 dialog.size.top = dialog.rootElem.style.top; 464 dialog.size.left =dialog.rootElem.style.left; 465 }; 466 467 Xinha.Dialog.prototype._resizeStart = function (ev) { 468 var dialog = this; 469 470 if (dialog.resizing) 471 { 472 return; 473 } 474 dialog.resizing = true; 475 476 var st = dialog.rootElem.style; 477 st.minHeight = ''; 478 st.overflow = 'hidden'; 479 dialog.xOffs = parseInt(st.left,10); 480 dialog.yOffs = parseInt(st.top,10); 481 482 Xinha._addEvent(document, "mousemove", function(ev) { dialog.resizeIt(ev); } ); 483 Xinha._addEvent(document, "mouseup", function (ev) { dialog.resizeEnd(ev); } ); 484 }; 485 486 Xinha.Dialog.prototype.resizeIt = function(ev) 487 { 488 var dialog = this; 489 490 if (!dialog.resizing) { 491 return false; 492 } 493 494 var posY = ev.clientY + dialog.scrollPos.y; 495 var posX = ev.clientX + dialog.scrollPos.x; 496 497 var st = dialog.rootElem.style; 498 499 posX = posX - dialog.xOffs; 500 posY = posY - dialog.yOffs; 501 502 st.width = (( posX > 10) ? posX : 10) + "px"; 503 st.height = (( posY > 10) ? posY : 10) + "px"; 504 505 dialog.width = dialog.rootElem.offsetWidth; 506 dialog.height = dialog.rootElem.offsetHeight; 507 508 dialog.onresize(); 509 }; 510 511 Xinha.Dialog.prototype.resizeEnd = function(ev) 512 { 513 var dialog = this; 514 dialog.resizing = false; 515 516 Xinha._removeEvent(document, "mousemove", function(ev) { dialog.resizeIt(ev); } ); 517 Xinha._removeEvent(document, "mouseup", function (ev) { dialog.resizeEnd(ev); } ); 518 519 dialog.size.width = dialog.rootElem.offsetWidth; 520 dialog.size.height = dialog.rootElem.offsetHeight; 146 521 }; 147 522 … … 337 712 return values; 338 713 }; 339 340 Xinha.Dialog.prototype.getElementById = function(id)341 {342 return this.document.getElementById(this.id[id] ? this.id[id] : id);343 };344 345 Xinha.Dialog.prototype.getElementsByName = function(name)346 {347 return this.document.getElementsByName(this.id[name] ? this.id[name] : name);348 }; -
branches/ray/modules/FullScreen/full-screen.js
r761 r762 72 72 */ 73 73 function resetScroll() 74 { 74 {console.log('resetScroll'); 75 75 if(e._isFullScreen) 76 76 { -
branches/ray/plugins/ImageManager/Classes/ImageEditor.php
r761 r762 1 <<<<<<< .working2 1 <?php 3 2 /** … … 8 7 */ 9 8 10 require_once(' Transform.php');9 require_once('../ImageManager/Classes/Transform.php'); 11 10 12 11 /** … … 449 448 450 449 ?> 451 =======452 <?php453 /**454 * Image Editor. Editing tools, crop, rotate, scale and save.455 * @author $Author$456 * @version $Id$457 * @package ImageManager458 */459 460 require_once('../ImageManager/Classes/Transform.php');461 462 /**463 * Handles the basic image editing capbabilities.464 * @author $Author$465 * @version $Id$466 * @package ImageManager467 * @subpackage Editor468 */469 class ImageEditor470 {471 /**472 * ImageManager instance.473 */474 var $manager;475 476 /**477 * user based on IP address478 */479 var $_uid;480 481 /**482 * tmp file storage time.483 */484 var $lapse_time =900; //15 mins485 486 var $filesaved = 0;487 488 /**489 * Create a new ImageEditor instance. Editing requires a490 * tmp file, which is saved in the current directory where the491 * image is edited. The tmp file is assigned by md5 hash of the492 * user IP address. This hashed is used as an ID for cleaning up493 * the tmp files. In addition, any tmp files older than the494 * the specified period will be deleted.495 * @param ImageManager $manager the image manager, we need this496 * for some file and path handling functions.497 */498 function ImageEditor($manager)499 {500 $this->manager = $manager;501 $this->_uid = md5($_SERVER['REMOTE_ADDR']);502 }503 504 /**505 * Did we save a file?506 * @return int 1 if the file was saved sucessfully,507 * 0 no save operation, -1 file save error.508 */509 function isFileSaved()510 {511 Return $this->filesaved;512 }513 514 /**515 * Process the image, if not action, just display the image.516 * @return array with image information, empty array if not an image.517 * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',518 * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>519 */520 function processImage()521 {522 if(isset($_GET['img']))523 $relative = rawurldecode($_GET['img']);524 else525 Return array();526 527 //$relative = '/Series2004NoteFront.jpg';528 529 $imgURL = $this->manager->getFileURL($relative);530 $fullpath = $this->manager->getFullPath($relative);531 532 $imgInfo = @getImageSize($fullpath);533 if(!is_array($imgInfo))534 Return array();535 536 $action = $this->getAction();537 538 if(!is_null($action))539 {540 $image = $this->processAction($action, $relative, $fullpath);541 }542 else543 {544 $image['src'] = $imgURL;545 $image['dimensions'] = $imgInfo[3];546 $image['file'] = $relative;547 $image['fullpath'] = $fullpath;548 }549 550 Return $image;551 }552 553 /**554 * Process the actions, crop, scale(resize), rotate, flip, and save.555 * When ever an action is performed, the result is save into a556 * temporary image file, see createUnique on the filename specs.557 * It does not return the saved file, alway returning the tmp file.558 * @param string $action, should be 'crop', 'scale', 'rotate','flip', or 'save'559 * @param string $relative the relative image filename560 * @param string $fullpath the fullpath to the image file561 * @return array with image information562 * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',563 * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>564 */565 function processAction($action, $relative, $fullpath)566 {567 $params = '';568 569 if(isset($_GET['params']))570 $params = $_GET['params'];571 572 $values = explode(',',$params,4);573 $saveFile = $this->getSaveFileName($values[0]);574 575 $img = Image_Transform::factory(IMAGE_CLASS);576 $img->load($fullpath);577 578 switch ($action)579 {580 case 'crop':581 $img->crop(intval($values[0]),intval($values[1]),582 intval($values[2]),intval($values[3]));583 break;584 case 'scale':585 $img->resize(intval($values[0]),intval($values[1]));586 break;587 case 'rotate':588 $img->rotate(floatval($values[0]));589 break;590 case 'flip':591 if ($values[0] == 'hoz')592 $img->flip(true);593 else if($values[0] == 'ver')594 $img->flip(false);595 break;596 case 'save':597 if(!is_null($saveFile))598 {599 $quality = intval($values[1]);600 if($quality <0) $quality = 85;601 $newSaveFile = $this->makeRelative($relative, $saveFile);602 $newSaveFile = $this->getUniqueFilename($newSaveFile);603 604 //get unique filename just returns the filename, so605 //we need to make the relative path once more.606 $newSaveFile = $this->makeRelative($relative, $newSaveFile);607 $image['saveFile'] = $newSaveFile;608 $newSaveFullpath = $this->manager->getFullPath($newSaveFile);609 $img->save($newSaveFullpath, $values[0], $quality);610 if(is_file($newSaveFullpath))611 $this->filesaved = 1;612 else613 $this->filesaved = -1;614 }615 break;616 }617 618 //create the tmp image file619 $filename = $this->createUnique($fullpath);620 $newRelative = $this->makeRelative($relative, $filename);621 $newFullpath = $this->manager->getFullPath($newRelative);622 $newURL = $this->manager->getFileURL($newRelative);623 624 //save the file.625 $img->save($newFullpath);626 $img->free();627 628 //get the image information629 $imgInfo = @getimagesize($newFullpath);630 631 $image['src'] = $newURL;632 $image['width'] = $imgInfo[0];633 $image['height'] = $imgInfo[1];634 $image['dimensions'] = $imgInfo[3];635 $image['file'] = $newRelative;636 $image['fullpath'] = $newFullpath;637 638 Return $image;639 640 }641 642 /**643 * Get the file name base on the save name644 * and the save type.645 * @param string $type image type, 'jpeg', 'png', or 'gif'646 * @return string the filename according to save type647 */648 function getSaveFileName($type)649 {650 if(!isset($_GET['file']))651 Return null;652 653 $filename = Files::escape(rawurldecode($_GET['file']));654 $index = strrpos($filename,'.');655 $base = substr($filename,0,$index);656 $ext = strtolower(substr($filename,$index+1,strlen($filename)));657 658 if($type == 'jpeg' && !($ext=='jpeg' || $ext=='jpg'))659 {660 Return $base.'.jpeg';661 }662 if($type=='png' && $ext != 'png')663 Return $base.'.png';664 if($type=='gif' && $ext != 'gif')665 Return $base.'.gif';666 667 Return $filename;668 }669 670 /**671 * Get the default save file name, used by editor.php.672 * @return string a suggestive filename, this should be unique673 */674 function getDefaultSaveFile()675 {676 if(isset($_GET['img']))677 $relative = rawurldecode($_GET['img']);678 else679 Return null;680 681 Return $this->getUniqueFilename($relative);682 }683 684 /**685 * Get a unique filename. If the file exists, the filename686 * base is appended with an increasing integer.687 * @param string $relative the relative filename to the base_dir688 * @return string a unique filename in the current path689 */690 function getUniqueFilename($relative)691 {692 $fullpath = $this->manager->getFullPath($relative);693 694 $pathinfo = pathinfo($fullpath);695 696 $path = Files::fixPath($pathinfo['dirname']);697 $file = Files::escape($pathinfo['basename']);698 699 $filename = $file;700 701 $dotIndex = strrpos($file, '.');702 $ext = '';703 704 if(is_int($dotIndex))705 {706 $ext = substr($file, $dotIndex);707 $base = substr($file, 0, $dotIndex);708 }709 710 $counter = 0;711 while(is_file($path.$filename))712 {713 $counter++;714 $filename = $base.'_'.$counter.$ext;715 }716 717 Return $filename;718 719 }720 721 /**722 * Specifiy the original relative path, a new filename723 * and return the new filename with relative path.724 * i.e. $pathA (-filename) + $file725 * @param string $pathA the relative file726 * @param string $file the new filename727 * @return string relative path with the new filename728 */729 function makeRelative($pathA, $file)730 {731 $index = strrpos($pathA,'/');732 if(!is_int($index))733 Return $file;734 735 $path = substr($pathA, 0, $index);736 Return Files::fixPath($path).$file;737 }738 739 /**740 * Get the action GET parameter741 * @return string action parameter742 */743 function getAction()744 {745 $action = null;746 if(isset($_GET['action']))747 $action = $_GET['action'];748 Return $action;749 }750 751 /**752 * Generate a unique string based on md5(microtime()).753 * Well not so uniqe, as it is limited to 6 characters754 * @return string unique string.755 */756 function uniqueStr()757 {758 return substr(md5(microtime()),0,6);759 }760 761 /**762 * Create unique tmp image file name.763 * The filename is based on the tmp file prefix764 * specified in config.inc.php plus765 * the UID (basically a md5 of the remote IP)766 * and some random 6 character string.767 * This function also calls to clean up the tmp files.768 * @param string $file the fullpath to a file769 * @return string a unique filename for that path770 * NOTE: it only returns the filename, path no included.771 */772 function createUnique($file)773 {774 $pathinfo = pathinfo($file);775 $path = Files::fixPath($pathinfo['dirname']);776 $imgType = $this->getImageType($file);777 778 $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;779 780 //make sure the the unique temp file does not exists781 while (file_exists($path.$unique_str))782 {783 $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;784 }785 786 $this->cleanUp($path,$pathinfo['basename']);787 788 Return $unique_str;789 }790 791 /**792 * Delete any tmp image files.793 * @param string $path the full path794 * where the clean should take place.795 */796 function cleanUp($path,$file)797 {798 $path = Files::fixPath($path);799 800 if(!is_dir($path))801 Return false;802 803 $d = @dir($path);804 805 $tmp = $this->manager->getTmpPrefix();806 $tmpLen = strlen($tmp);807 808 $prefix = $tmp.$this->_uid;809 $len = strlen($prefix);810 811 while (false !== ($entry = $d->read()))812 {813 //echo $entry."<br>";814 if(is_file($path.$entry) && $this->manager->isTmpFile($entry))815 {816 if(substr($entry,0,$len)==$prefix && $entry != $file)817 Files::delFile($path.$entry);818 else if(substr($entry,0,$tmpLen)==$tmp && $entry != $file)819 {820 if(filemtime($path.$entry)+$this->lapse_time < time())821 Files::delFile($path.$entry);822 }823 }824 }825 $d->close();826 }827 828 /**829 * Get the image type base on an image file.830 * @param string $file the full path to the image file.831 * @return string of either 'gif', 'jpeg', 'png' or 'bmp'832 * otherwise it will return null.833 */834 function getImageType($file)835 {836 $imageInfo = @getImageSize($file);837 838 if(!is_array($imageInfo))839 Return null;840 841 switch($imageInfo[2])842 {843 case 1:844 Return 'gif';845 case 2:846 Return 'jpeg';847 case 3:848 Return 'png';849 case 6:850 Return 'bmp';851 }852 853 Return null;854 }855 856 /**857 * Check if the specified image can be edit by GD858 * mainly to check that GD can read and save GIFs859 * @return int 0 if it is not a GIF file, 1 is GIF is editable, -1 if not editable.860 */861 function isGDEditable()862 {863 if(isset($_GET['img']))864 $relative = rawurldecode($_GET['img']);865 else866 Return 0;867 if(IMAGE_CLASS != 'GD')868 Return 0;869 870 $fullpath = $this->manager->getFullPath($relative);871 872 $type = $this->getImageType($fullpath);873 if($type != 'gif')874 Return 0;875 876 if(function_exists('ImageCreateFrom'+$type)877 && function_exists('image'+$type))878 Return 1;879 else880 Return -1;881 }882 883 /**884 * Check if GIF can be edit by GD.885 * @return int 0 if it is not using the GD library, 1 is GIF is editable, -1 if not editable.886 */887 function isGDGIFAble()888 {889 if(IMAGE_CLASS != 'GD')890 Return 0;891 892 if(function_exists('ImageCreateFromGif')893 && function_exists('imagegif'))894 Return 1;895 else896 Return -1;897 }898 }899 900 ?>901 >>>>>>> .merge-right.r760 -
branches/ray/plugins/ImageManager/Classes/ImageManager.php
r761 r762 1 <<<<<<< .working2 1 <?php 3 2 /** … … 8 7 */ 9 8 10 require_once(' Files.php');9 require_once('../ImageManager/Classes/Files.php'); 11 10 12 11 // uncomment to turn on debugging … … 664 663 665 664 ?> 666 =======667 <?php668 /**669 * ImageManager, list images, directories, and thumbnails.670 * @author $Author$671 * @version $Id$672 * @package ImageManager673 */674 675 require_once('../ImageManager/Classes/Files.php');676 677 // uncomment to turn on debugging678 679 // _ddtOn();680 681 /**682 * ImageManager Class.683 * @author $Author$684 * @version $Id$685 */686 class ImageManager687 {688 /**689 * Configuration array.690 */691 var $config;692 693 /**694 * Array of directory information.695 */696 var $dirs;697 698 /**699 * Constructor. Create a new Image Manager instance.700 * @param array $config configuration array, see config.inc.php701 */702 function ImageManager($config)703 {704 $this->config = $config;705 }706 707 /**708 * Get the images base directory.709 * @return string base dir, see config.inc.php710 */711 function getImagesDir()712 {713 Return $this->config['images_dir'];714 }715 716 /**717 * Get the images base URL.718 * @return string base url, see config.inc.php719 */720 function getImagesURL()721 {722 Return $this->config['images_url'];723 }724 725 function isValidBase()726 {727 return is_dir($this->getImagesDir());728 }729 730 /**731 * Get the tmp file prefix.732 * @return string tmp file prefix.733 */734 function getTmpPrefix()735 {736 Return $this->config['tmp_prefix'];737 }738 739 /**740 * Get the sub directories in the base dir.741 * Each array element contain742 * the relative path (relative to the base dir) as key and the743 * full path as value.744 * @return array of sub directries745 * <code>array('path name' => 'full directory path', ...)</code>746 */747 function getDirs()748 {749 if(is_null($this->dirs))750 {751 $dirs = $this->_dirs($this->getImagesDir(),'/');752 ksort($dirs);753 $this->dirs = $dirs;754 }755 return $this->dirs;756 }757 758 /**759 * Recursively travese the directories to get a list760 * of accessable directories.761 * @param string $base the full path to the current directory762 * @param string $path the relative path name763 * @return array of accessiable sub-directories764 * <code>array('path name' => 'full directory path', ...)</code>765 */766 function _dirs($base, $path)767 {768 $base = Files::fixPath($base);769 $dirs = array();770 771 if($this->isValidBase() == false)772 return $dirs;773 774 $d = @dir($base);775 776 while (false !== ($entry = $d->read()))777 {778 //If it is a directory, and it doesn't start with779 // a dot, and if is it not the thumbnail directory780 if(is_dir($base.$entry)781 && substr($entry,0,1) != '.'782 && $this->isThumbDir($entry) == false)783 {784 $relative = Files::fixPath($path.$entry);785 $fullpath = Files::fixPath($base.$entry);786 $dirs[$relative] = $fullpath;787 $dirs = array_merge($dirs, $this->_dirs($fullpath, $relative));788 }789 }790 $d->close();791 792 Return $dirs;793 }794 795 /**796 * Get all the files and directories of a relative path.797 * @param string $path relative path to be base path.798 * @return array of file and path information.799 * <code>array(0=>array('relative'=>'fullpath',...), 1=>array('filename'=>fileinfo array(),...)</code>800 * fileinfo array: <code>array('url'=>'full url',801 * 'relative'=>'relative to base',802 * 'fullpath'=>'full file path',803 * 'image'=>imageInfo array() false if not image,804 * 'stat' => filestat)</code>805 */806 function getFiles($path)807 {808 $files = array();809 $dirs = array();810 811 if($this->isValidBase() == false)812 return array($files,$dirs);813 814 $path = Files::fixPath($path);815 $base = Files::fixPath($this->getImagesDir());816 $fullpath = Files::makePath($base,$path);817 818 819 $d = @dir($fullpath);820 821 while (false !== ($entry = $d->read()))822 {823 //not a dot file or directory824 if(substr($entry,0,1) != '.')825 {826 if(is_dir($fullpath.$entry)827 && $this->isThumbDir($entry) == false)828 {829 $relative = Files::fixPath($path.$entry);830 $full = Files::fixPath($fullpath.$entry);831 $count = $this->countFiles($full);832 $dirs[$relative] = array('fullpath'=>$full,'entry'=>$entry,'count'=>$count);833 }834 else if(is_file($fullpath.$entry) && $this->isThumb($entry)==false && $this->isTmpFile($entry) == false)835 {836 $img = $this->getImageInfo($fullpath.$entry);837 838 if(!(!is_array($img)&&$this->config['validate_images']))839 {840 $file['url'] = Files::makePath($this->config['base_url'],$path).$entry;841 $file['relative'] = $path.$entry;842 $file['fullpath'] = $fullpath.$entry;843 $file['image'] = $img;844 $file['stat'] = stat($fullpath.$entry);845 $files[$entry] = $file;846 }847 }848 }849 }850 $d->close();851 ksort($dirs);852 ksort($files);853 854 Return array($dirs, $files);855 }856 857 /**858 * Count the number of files and directories in a given folder859 * minus the thumbnail folders and thumbnails.860 */861 function countFiles($path)862 {863 $total = 0;864 865 if(is_dir($path))866 {867 $d = @dir($path);868 869 while (false !== ($entry = $d->read()))870 {871 //echo $entry."<br>";872 if(substr($entry,0,1) != '.'873 && $this->isThumbDir($entry) == false874 && $this->isTmpFile($entry) == false875 && $this->isThumb($entry) == false)876 {877 $total++;878 }879 }880 $d->close();881 }882 return $total;883 }884 885 /**886 * Get image size information.887 * @param string $file the image file888 * @return array of getImageSize information,889 * false if the file is not an image.890 */891 function getImageInfo($file)892 {893 Return @getImageSize($file);894 }895 896 /**897 * Check if the file contains the thumbnail prefix.898 * @param string $file filename to be checked899 * @return true if the file contains the thumbnail prefix, false otherwise.900 */901 function isThumb($file)902 {903 $len = strlen($this->config['thumbnail_prefix']);904 if(substr($file,0,$len)==$this->config['thumbnail_prefix'])905 Return true;906 else907 Return false;908 }909 910 /**911 * Check if the given directory is a thumbnail directory.912 * @param string $entry directory name913 * @return true if it is a thumbnail directory, false otherwise914 */915 function isThumbDir($entry)916 {917 if($this->config['thumbnail_dir'] == false918 || strlen(trim($this->config['thumbnail_dir'])) == 0)919 Return false;920 else921 Return ($entry == $this->config['thumbnail_dir']);922 }923 924 /**925 * Check if the given file is a tmp file.926 * @param string $file file name927 * @return boolean true if it is a tmp file, false otherwise928 */929 function isTmpFile($file)930 {931 $len = strlen($this->config['tmp_prefix']);932 if(substr($file,0,$len)==$this->config['tmp_prefix'])933 Return true;934 else935 Return false;936 }937 938 /**939 * For a given image file, get the respective thumbnail filename940 * no file existence check is done.941 * @param string $fullpathfile the full path to the image file942 * @return string of the thumbnail file943 */944 function getThumbName($fullpathfile)945 {946 $path_parts = pathinfo($fullpathfile);947 948 $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];949 950 if( strlen(trim($this->config['thumbnail_dir'])) == 0 || $this->config['safe_mode'] == true)951 {952 Return Files::makeFile($path_parts['dirname'],$thumbnail);953 }954 else955 {956 $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);957 if(!is_dir($path))958 Files::createFolder($path);959 Return Files::makeFile($path,$thumbnail);960 }961 }962 963 /**964 * Similar to getThumbName, but returns the URL, base on the965 * given base_url in config.inc.php966 * @param string $relative the relative image file name,967 * relative to the base_dir path968 * @return string the url of the thumbnail969 */970 function getThumbURL($relative)971 {972 973 _ddt( __FILE__, __LINE__, "getThumbURL(): relative is '$relative'" );974 975 $path_parts = pathinfo($relative);976 $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];977 if($path_parts['dirname']=='\\') $path_parts['dirname']='/';978 979 if($this->config['safe_mode'] == true980 || strlen(trim($this->config['thumbnail_dir'])) == 0)981 {982 Return Files::makeFile($this->getImagesURL(),$thumbnail);983 }984 else985 {986 if(strlen(trim($this->config['thumbnail_dir'])) > 0)987 {988 $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);989 $url_path = Files::makePath($this->getImagesURL(), $path);990 991 _ddt( __FILE__, __LINE__, "getThumbURL(): url_path is '$url_path'" );992 993 Return Files::makeFile($url_path,$thumbnail);994 }995 else //should this ever happen?996 {997 //error_log('ImageManager: Error in creating thumbnail url');998 }999 1000 }1001 }1002 1003 1004 /**1005 * For a given image file, get the respective resized filename1006 * no file existence check is done.1007 * @param string $fullpathfile the full path to the image file1008 * @param integer $width the intended width1009 * @param integer $height the intended height1010 * @param boolean $mkDir whether to attempt to make the resized_dir if it doesn't exist1011 * @return string of the resized filename1012 */1013 function getResizedName($fullpathfile, $width, $height, $mkDir = TRUE)1014 {1015 $path_parts = pathinfo($fullpathfile);1016 1017 $thumbnail = $this->config['resized_prefix']."_{$width}x{$height}_{$path_parts['basename']}";1018 1019 if( strlen(trim($this->config['resized_dir'])) == 0 || $this->config['safe_mode'] == true )1020 {1021 Return Files::makeFile($path_parts['dirname'],$thumbnail);1022 }1023 else1024 {1025 $path = Files::makePath($path_parts['dirname'],$this->config['resized_dir']);1026 if($mkDir && !is_dir($path))1027 Files::createFolder($path);1028 Return Files::makeFile($path,$thumbnail);1029 }1030 }1031 1032 /**1033 * Check if the given path is part of the subdirectories1034 * under the base_dir.1035 * @param string $path the relative path to be checked1036 * @return boolean true if the path exists, false otherwise1037 */1038 function validRelativePath($path)1039 {1040 $dirs = $this->getDirs();1041 if($path == '/')1042 Return true;1043 //check the path given in the url against the1044 //list of paths in the system.1045 for($i = 0; $i < count($dirs); $i++)1046 {1047 $key = key($dirs);1048 //we found the path1049 if($key == $path)1050 Return true;1051 1052 next($dirs);1053 }1054 Return false;1055 }1056 1057 /**1058 * Process uploaded files, assumes the file is in1059 * $_FILES['upload'] and $_POST['dir'] is set.1060 * The dir must be relative to the base_dir and exists.1061 * If 'validate_images' is set to true, only file with1062 * image dimensions will be accepted.1063 * @return null1064 */1065 function processUploads()1066 {1067 if($this->isValidBase() == false)1068 return;1069 1070 $relative = null;1071 1072 if(isset($_POST['dir']))1073 $relative = rawurldecode($_POST['dir']);1074 else1075 return;1076 1077 //check for the file, and must have valid relative path1078 if(isset($_FILES['upload']) && $this->validRelativePath($relative))1079 {1080 $this->_processFiles($relative, $_FILES['upload']);1081 }1082 }1083 1084 /**1085 * Process upload files. The file must be an1086 * uploaded file. If 'validate_images' is set to1087 * true, only images will be processed. Any duplicate1088 * file will be renamed. See Files::copyFile for details1089 * on renaming.1090 * @param string $relative the relative path where the file1091 * should be copied to.1092 * @param array $file the uploaded file from $_FILES1093 * @return boolean true if the file was processed successfully,1094 * false otherwise1095 */1096 function _processFiles($relative, $file)1097 {1098 1099 if($file['error']!=0)1100 {1101 Return false;1102 }1103 1104 if(!is_file($file['tmp_name']))1105 {1106 Return false;1107 }1108 1109 if(!is_uploaded_file($file['tmp_name']))1110 {1111 Files::delFile($file['tmp_name']);1112 Return false;1113 }1114 1115 1116 if($this->config['validate_images'] == true)1117 {1118 $imgInfo = @getImageSize($file['tmp_name']);1119 if(!is_array($imgInfo))1120 {1121 Files::delFile($file['tmp_name']);1122 Return false;1123 }1124 }1125 1126 //now copy the file1127 $path = Files::makePath($this->getImagesDir(),$relative);1128 $result = Files::copyFile($file['tmp_name'], $path, $file['name']);1129 1130 //no copy error1131 if(!is_int($result))1132 {1133 Files::delFile($file['tmp_name']);1134 Return true;1135 }1136 1137 //delete tmp files.1138 Files::delFile($file['tmp_name']);1139 Return false;1140 }1141 1142 /**1143 * Get the URL of the relative file.1144 * basically appends the relative file to the1145 * base_url given in config.inc.php1146 * @param string $relative a file the relative to the base_dir1147 * @return string the URL of the relative file.1148 */1149 function getFileURL($relative)1150 {1151 Return Files::makeFile($this->getImagesURL(),$relative);1152 }1153 1154 /**1155 * Get the fullpath to a relative file.1156 * @param string $relative the relative file.1157 * @return string the full path, .ie. the base_dir + relative.1158 */1159 function getFullPath($relative)1160 {1161 Return Files::makeFile($this->getImagesDir(),$relative);;1162 }1163 1164 /**1165 * Get the default thumbnail.1166 * @return string default thumbnail, empty string if1167 * the thumbnail doesn't exist.1168 */1169 function getDefaultThumb()1170 {1171 1172 // FIXME: hack1173 1174 Return $this->config['default_thumbnail'];1175 1176 if(is_file($this->config['default_thumbnail']))1177 {1178 Return $this->config['default_thumbnail'];1179 }1180 else1181 Return '';1182 }1183 1184 1185 /**1186 * Get the thumbnail url to be displayed.1187 * If the thumbnail exists, and it is up-to-date1188 * the thumbnail url will be returns. If the1189 * file is not an image, a default image will be returned.1190 * If it is an image file, and no thumbnail exists or1191 * the thumbnail is out-of-date (i.e. the thumbnail1192 * modified time is less than the original file)1193 * then a thumbs.php?img=filename.jpg is returned.1194 * The thumbs.php url will generate a new thumbnail1195 * on the fly. If the image is less than the dimensions1196 * of the thumbnails, the image will be display instead.1197 * @param string $relative the relative image file.1198 * @return string the url of the thumbnail, be it1199 * actually thumbnail or a script to generate the1200 * thumbnail on the fly.1201 */1202 function getThumbnail($relative)1203 {1204 1205 global $IMConfig;1206 1207 _ddt( __FILE__, __LINE__, "getThumbnail(): top with '$relative'" );1208 1209 $fullpath = Files::makeFile($this->getImagesDir(),$relative);1210 1211 //not a file???1212 if(!is_file($fullpath))1213 Return $this->getDefaultThumb();1214 1215 $imgInfo = @getImageSize($fullpath);1216 1217 //not an image1218 if(!is_array($imgInfo))1219 Return $this->getDefaultThumb();1220 1221 //the original image is smaller than thumbnails,1222 //so just return the url to the original image.1223 if ($imgInfo[0] <= $this->config['thumbnail_width']1224 && $imgInfo[1] <= $this->config['thumbnail_height'])1225 Return $this->getFileURL($relative);1226 1227 $thumbnail = $this->getThumbName($fullpath);1228 1229 //check for thumbnails, if exists and1230 // it is up-to-date, return the thumbnail url1231 if(is_file($thumbnail))1232 {1233 if(filemtime($thumbnail) >= filemtime($fullpath))1234 {1235 _ddt( __FILE__, __LINE__, "getThumbnail(): returning url '" . $this->getThumbURL($relative) . "'" );1236 1237 Return $this->getThumbURL($relative);1238 }1239 }1240 1241 //well, no thumbnail was found, so ask the thumbs.php1242 //to generate the thumbnail on the fly.1243 Return $IMConfig['backend_url'] . '__function=thumbs&img='.rawurlencode($relative);1244 }1245 1246 /**1247 * Delete and specified files.1248 * @return boolean true if delete, false otherwise1249 */1250 function deleteFiles()1251 {1252 if(isset($_GET['delf']))1253 $this->_delFile(rawurldecode($_GET['delf']));1254 }1255 1256 /**1257 * Delete and specified directories.1258 * @return boolean true if delete, false otherwise1259 */1260 function deleteDirs()1261 {1262 if(isset($_GET['deld']))1263 return $this->_delDir(rawurldecode($_GET['deld']));1264 else1265 Return false;1266 }1267 1268 /**1269 * Delete the relative file, and any thumbnails.1270 * @param string $relative the relative file.1271 * @return boolean true if deleted, false otherwise.1272 */1273 function _delFile($relative)1274 {1275 $fullpath = Files::makeFile($this->getImagesDir(),$relative);1276 1277 //check that the file is an image1278 if($this->config['validate_images'] == true)1279 {1280 if(!is_array($this->getImageInfo($fullpath)))1281 return false; //hmmm not an Image!!???1282 }1283 1284 $thumbnail = $this->getThumbName($fullpath);1285 1286 if(Files::delFile($fullpath))1287 Return Files::delFile($thumbnail);1288 else1289 Return false;1290 }1291 1292 /**1293 * Delete directories recursively.1294 * @param string $relative the relative path to be deleted.1295 * @return boolean true if deleted, false otherwise.1296 */1297 function _delDir($relative)1298 {1299 $fullpath = Files::makePath($this->getImagesDir(),$relative);1300 if($this->countFiles($fullpath) <= 0)1301 return Files::delFolder($fullpath,true); //delete recursively.1302 else1303 Return false;1304 }1305 1306 /**1307 * Create new directories.1308 * If in safe_mode, nothing happens.1309 * @return boolean true if created, false otherwise.1310 */1311 function processNewDir()1312 {1313 if($this->config['safe_mode'] == true)1314 Return false;1315 1316 if(isset($_GET['newDir']) && isset($_GET['dir']))1317 {1318 $newDir = rawurldecode($_GET['newDir']);1319 $dir = rawurldecode($_GET['dir']);1320 $path = Files::makePath($this->getImagesDir(),$dir);1321 $fullpath = Files::makePath($path, Files::escape($newDir));1322 if(is_dir($fullpath))1323 Return false;1324 1325 Return Files::createFolder($fullpath);1326 }1327 }1328 }1329 1330 ?>1331 >>>>>>> .merge-right.r760 -
branches/ray/plugins/Linker/dialog.html
r761 r762 99 99 </fieldset> 100 100 101 <div style="text-align:right">101 <div class="buttons"> 102 102 <input type="button" id="[ok]" value="_(OK)" /> 103 <input type="button" id="[clear]" 103 <input type="button" id="[clear]" value="_(Remove Link)" onclick="this.form['[href]'].value='';this.form['[to]'].value='';document.getElementById('[ok]').click();" /> 104 104 <input type="button" id="[cancel]" value="_(Cancel)" /> 105 105 </div> -
branches/ray/plugins/Linker/linker.js
r761 r762 366 366 367 367 // Now we have everything we need, so we can build the dialog. 368 var dialog = this.dialog = new Xinha.Dialog(linker.editor, this.html, 'Linker' );368 var dialog = this.dialog = new Xinha.Dialog(linker.editor, this.html, 'Linker',{width:600,height:400}); 369 369 var dTreeName = Xinha.uniq('dTree_'); 370 370 … … 379 379 //ddTree.innerHTML = this.dTree.toString(); 380 380 ddTree.innerHTML = ''; 381 ddTree.style.position = 'absolute';382 ddTree.style.left = 1 + 'px';383 ddTree.style.top = 0 + 'px';381 // ddTree.style.position = 'absolute'; 382 // ddTree.style.left = 1 + 'px'; 383 // ddTree.style.top = 0 + 'px'; 384 384 ddTree.style.overflow = 'auto'; 385 ddTree.style.height = '300px'; 386 if ( Xinha.is_ie ) 387 { 388 ddTree.style.styleFloat = "left"; 389 } 390 else 391 { 392 ddTree.style.cssFloat = "left"; 393 } 385 394 ddTree.style.backgroundColor = 'white'; 386 395 this.ddTree = ddTree; … … 388 397 389 398 var options = this.dialog.getElementById('options'); 390 options.style.position = 'absolute';391 options.style.top = 0 + 'px';392 options.style.right = 0 + 'px';399 //options.style.position = 'absolute'; 400 //options.style.top = 0 + 'px'; 401 //options.style.right = 0 + 'px'; 393 402 options.style.width = 320 + 'px'; 394 403 options.style.overflow = 'auto'; 395 404 396 405 // Hookup the resizer 406 this.dialog.rootElem.style.paddingBottom ="0"; 397 407 this.dialog.onresize = function() 398 408 { 399 409 var h = parseInt(dialog.height) - dialog.getElementById('h1').offsetHeight; 400 var w = parseInt(dialog.width) - 322 ; 410 var w = parseInt(dialog.width) - 330 ; 411 401 412 // An error is thrown with IE when trying to set a negative width or a negative height 402 413 // But perhaps a width / height of 0 is not the minimum required we need to set 403 414 if (w<0) w = 0; 404 415 if (h<0) h = 0; 405 options.style.height = ddTree.style.height = h + 'px'; 416 //options.style.height = 417 ddTree.style.height = h + 'px'; 406 418 ddTree.style.width = w + 'px'; 407 419 } 408 409 420 this.ready = true; 410 421 }; -
branches/ray/plugins/PasteText/paste-text.js
r761 r762 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 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 this._prepareDialog(); 46 }; 46 47 48 PasteText.prototype._prepareDialog = function() 49 { 50 var self = this; 47 51 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 } 52 53 if(!this.html) // retrieve the raw dialog contents 54 { 55 Xinha._getback(_editor_url + 'plugins/PasteText/popups/paste_text.html', function(getback) { self.html = getback; self._prepareDialog(); }); 56 return; 57 } 58 59 // Now we have everything we need, so we can build the dialog. 60 this.dialog = new Xinha.Dialog(editor, this.html, 'PasteText',{width:350}) 61 62 // Connect the OK and Cancel buttons 63 this.dialog.getElementById('ok').onclick = function() {self.apply();} 64 65 this.dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 66 67 // do some tweaking 68 if (editor.config.PasteText.showParagraphOption) 69 { 70 this.dialog.getElementById("paragraphOption").style.display = ""; 71 } 72 if (editor.config.PasteText.newParagraphDefault) 73 { 74 this.dialog.getElementById("insertParagraphs").checked = true; 75 } 76 77 // we can setup a custom function that cares for sizes etc. when the dialog is resized 78 this.dialog.onresize = function () 79 { 80 this.getElementById("inputArea").style.height = 81 parseInt(this.height,10) // the actual height of the dialog 82 - this.getElementById('h1').offsetHeight // the title bar 83 - this.getElementById('buttons').offsetHeight // the buttons 84 - parseInt(this.rootElem.style.paddingBottom,10) // we have a padding at the bottom, gotta take this into acount 85 + 'px'; // don't forget this ;) 86 87 this.getElementById("inputArea").style.width =(this.width - 2) + 'px'; // and the width 88 89 } 90 this.ready = true; 91 }; 92 93 PasteText.prototype.show = function() 94 { 95 if(!this.ready) // if the user is too fast clicking the, we have to make them wait 96 { 97 var self = this; 98 window.setTimeout(function() {self.show();},100); 99 return; 100 } 101 // here we can pass values to the dialog 102 // each property pair consists of the "name" of the input we want to populate, and the value to be set 103 var inputs = 104 { 105 inputArea : '' // we want the textarea always to be empty on showing 106 } 107 // now calling the show method of the Xinha.Dialog object to set the values and show the actual dialog 108 this.dialog.show(inputs); 109 110 // Init the sizes (only if we have set up the custom resize function) 111 this.dialog.onresize(); 112 113 this.dialog.getElementById("inputArea").focus(); 114 }; 115 116 // and finally ... take some action 117 PasteText.prototype.apply = function() 118 { 119 // the hide method of the dialog object returns the values of the inputs AND hides the dialog 120 // could also use this.dialog.getValues() here and hide it at the end 121 var returnValues = this.dialog.hide(); 122 123 var html = returnValues.inputArea; 124 var insertParagraphs = returnValues.insertParagraphs; 125 html = html.replace(/</g, "<"); 126 html = html.replace(/>/g, ">"); 127 if ( returnValues.insertParagraphs) 128 { 129 html = html.replace(/\t/g," "); 130 html = html.replace(/\n/g,"</p><p>"); 131 html="<p>" + html + "</p>"; 132 if (Xinha.is_ie) 133 { 134 this.editor.insertHTML(html); 67 135 } 68 136 else 69 137 { 70 html = html.replace(/\n/g,"<br />"); 71 editor.insertHTML(html); 138 this.editor.execCommand("inserthtml",false,html); 72 139 } 73 140 } 74 Dialog( _editor_url+ "plugins/PasteText/popups/paste_text.html", action, outparam); 141 else 142 { 143 html = html.replace(/\n/g,"<br />"); 144 this.editor.insertHTML(html); 145 } 75 146 }; -
branches/ray/plugins/PasteText/popups/paste_text.html
r761 r762 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 <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> 40 <div id="buttons"> 41 <label for="insertParagraphs" style="float:left;display:none" id="paragraphOption"> 42 <input type="checkbox" id="insertParagraphs" /> Insert text in new paragraph 1 <h1 id="[h1]">Paste as Plain Text</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]" /> Insert text in new paragraph 43 6 </label> 44 <button type="button" name="ok" onclick="return onOK();">OK</button>45 <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)" /> 46 9 </div> 47 </body>48 </html> -
branches/ray/plugins/SmartReplace/dialog.html
r761 r762 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 <input type="button" id="[ok]" value="_(OK)" /> 16 <input type="button" id="[cancel]" value="_(Cancel)" /> 17 </div> -
branches/ray/plugins/SmartReplace/smart-replace.js
r761 r762 263 263 var self = this; 264 264 265 if ( this. _dialog.dialog.rootElem.style.display != 'none')266 { 267 return this. _dialog.hide();265 if ( this.dialog.rootElem.style.display != 'none') 266 { 267 return this.dialog.hide(); 268 268 } 269 269 var doOK = function() 270 270 { 271 var opts = self. _dialog.hide();271 var opts = self.dialog.hide(); 272 272 self.toggleActivity((opts.enable) ? true : false); 273 273 if (opts.convert) 274 274 { 275 275 self.replaceAll(); 276 self. _dialog.dialog.getElementById("convert").checked = false;276 self.dialog.getElementById("convert").checked = false; 277 277 } 278 278 } … … 282 282 convert: '' 283 283 }; 284 this. _dialog.show(inputs, doOK);284 this.show(inputs, doOK); 285 285 }; 286 286 287 287 SmartReplace.prototype.onGenerateOnce = function() 288 288 { 289 if( !this._dialog)290 {291 this._dialog = new SmartReplace.Dialog(this);292 }293 };294 295 SmartReplace.Dialog = function (mainPluginObject)296 {297 this.Dialog_nxtid = 0;298 this.mainPluginObject = mainPluginObject;299 this.id = { }; // This will be filled below with a replace, nifty300 301 this.ready = false;302 this.files = false;303 this.html = false;304 this.dialog = false;305 306 289 this._prepareDialog(); 307 308 }; 309 310 SmartReplace.Dialog.prototype._prepareDialog = function() 311 { 312 var pluginDialogObject = this; 313 var editor = this.mainPluginObject.editor; 314 315 if(this.html == false) 316 { 317 Xinha._getback(_editor_url + 'plugins/SmartReplace/dialog.html', function(getback) { pluginDialogObject.html = getback; pluginDialogObject._prepareDialog(); }); 290 }; 291 292 SmartReplace.prototype._prepareDialog = function() 293 { 294 var self = this; 295 var editor = this.editor; 296 297 if(!this.html) 298 { 299 Xinha._getback(_editor_url + 'plugins/SmartReplace/dialog.html', function(getback) { self.html = getback; self._prepareDialog(); }); 318 300 return; 319 301 } 320 302 321 303 // Now we have everything we need, so we can build the dialog. 322 this.dialog = new Xinha.Dialog(editor, this.html, 'SmartReplace' );304 this.dialog = new Xinha.Dialog(editor, this.html, 'SmartReplace',{width:300}); 323 305 324 306 this.ready = true; 325 307 }; 326 308 327 SmartReplace.Dialog.prototype._lc = SmartReplace.prototype._lc; 328 329 SmartReplace.Dialog.prototype.show = function(inputs, ok, cancel) 309 SmartReplace.prototype.show = function(inputs, ok, cancel) 330 310 { 331 311 if(!this.ready) 332 312 { 333 var pluginDialogObject= this;334 window.setTimeout(function() { pluginDialogObject.show(inputs,ok,cancel);},100);313 var self = this; 314 window.setTimeout(function() {self.show(inputs,ok,cancel);},100); 335 315 return; 336 316 } 337 317 338 318 // Connect the OK and Cancel buttons 339 var dialog = this.dialog; 340 var pluginDialogObject = this; 319 var self = this; 341 320 if(ok) 342 321 { … … 345 324 else 346 325 { 347 this.dialog.getElementById('ok').onclick = function() { pluginDialogObject.hide();};326 this.dialog.getElementById('ok').onclick = function() {self.dialog.hide();}; 348 327 } 349 328 … … 354 333 else 355 334 { 356 this.dialog.getElementById('cancel').onclick = function() { pluginDialogObject.hide()}; 357 } 358 359 // Show the dialog 360 this.mainPluginObject.editor.disableToolbar(['fullscreen','smartreplace']); 335 this.dialog.getElementById('cancel').onclick = function() { self.dialog.hide()}; 336 } 361 337 362 338 this.dialog.show(inputs); … … 365 341 this.dialog.onresize(); 366 342 }; 367 368 SmartReplace.Dialog.prototype.hide = function()369 {370 this.mainPluginObject.editor.enableToolbar();371 return this.dialog.hide();372 }; -
branches/ray/plugins/Stylist/stylist.js
r761 r762 83 83 var className = x.trim(); 84 84 var applicable = true; 85 var idApplicable = false; 85 86 var apply_to = active_elem; 86 87 … … 96 97 // No class name, just redefines a tag 97 98 applicable = false; 99 100 if (className.indexOf('#') >= 0) 101 { 102 idApplicable = true; 103 } 98 104 } 99 105 … … 147 153 } 148 154 149 if(applicable) 150 { 151 // Remove the first . 152 className = className.substring(className.indexOf('.'), className.length); 153 154 // Replace any futher ones with spaces (for multiple class definitions) 155 className = className.replace('.', ' '); 155 if (idApplicable) // IDs 156 { 157 // requires specific html tag 158 tag = className.substring(0, className.indexOf('#')).toLowerCase(); 159 var idName = className.substring(className.indexOf('#'), className.length); 160 161 // To apply we must have an ancestor tag that is the right type 162 if(active_elem != null && active_elem.tagName.toLowerCase() == tag) 163 { 164 idApplicable = true; 165 apply_to = active_elem; 166 } 167 else 168 { 169 if(this._getFirstAncestor(this._getSelection(), [tag]) != null) 170 { 171 idApplicable = true; 172 apply_to = this._getFirstAncestor(this._getSelection(), [tag]); 173 } 174 else 175 { 176 // alert (this._getFirstAncestor(this._getSelection(), tag)); 177 // If we don't have an ancestor, but it's a div/span/p/hx stle, we can make one 178 if(( tag == 'div' || tag == 'span' || tag == 'p' 179 || (tag.substr(0,1) == 'h' && tag.length == 2 && tag != 'hr'))) 180 { 181 if(!this._selectionEmpty(this._getSelection())) 182 { 183 idApplicable = true; 184 apply_to = 'new'; 185 } 186 else 187 { 188 // See if we can get a paragraph or header that can be converted 189 apply_to = this._getFirstAncestor(sel, ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7']); 190 if(apply_to != null) 191 { 192 idApplicable = true; 193 } 194 } 195 } 196 else 197 { 198 idApplicable = false; 199 } 200 } 201 } 202 } 203 204 205 if(applicable || idApplicable) 206 { 207 208 if (idApplicable) 209 { 210 // Remove the first . 211 idName = idName.substring(idName.indexOf('#'), idName.length); 212 213 // Replace any futher ones with spaces (for multiple id definitions (yes it happens)) 214 idName = idName.replace('#', ' '); 215 } 216 else 217 { 218 // Remove the first . 219 className = className.substring(className.indexOf('.'), className.length); 220 221 // Replace any futher ones with spaces (for multiple class definitions) 222 className = className.replace('.', ' '); 223 } 156 224 157 225 if(apply_to == null) … … 170 238 } 171 239 172 var applied = (this._ancestorsWithClasses(sel, tag, className).length > 0 ? true : false); 173 var applied_to = this._ancestorsWithClasses(sel, tag, className); 174 175 if(applicable) 240 if (idApplicable) 241 { 242 var applied = (this._ancestorsWithIDs(sel, tag, idName).length > 0 ? true : false); 243 var applied_to = this._ancestorsWithIDs(sel, tag, idName); 244 } 245 else 246 { 247 var applied = (this._ancestorsWithClasses(sel, tag, className).length > 0 ? true : false); 248 var applied_to = this._ancestorsWithClasses(sel, tag, className); 249 } 250 251 if(applicable || idApplicable) 176 252 { 177 253 var anch = document.createElement('a'); 178 anch._stylist_className = className.trim(); 254 if (idApplicable) 255 anch._stylist_idName = idName.trim(); 256 else 257 anch._stylist_className = className.trim(); 179 258 anch._stylist_applied = applied; 180 259 anch._stylist_appliedTo = applied_to; … … 185 264 anch.href = 'javascript:void(0)'; 186 265 var editor = this; 187 anch.onclick = function() 188 { 189 if(this._stylist_applied == true) 190 { 191 editor._stylistRemoveClasses(this._stylist_className, this._stylist_appliedTo); 192 } 193 else 194 { 195 editor._stylistAddClasses(this._stylist_applyTo, this._stylist_applyTag, this._stylist_className); 196 } 197 return false; 266 if (idApplicable) 267 { 268 anch.onclick = function() 269 { 270 if(this._stylist_applied == true) 271 { 272 editor._stylistRemoveIDs(this._stylist_idName, this._stylist_appliedTo); 273 } 274 else 275 { 276 editor._stylistAddIDs(this._stylist_applyTo, this._stylist_applyTag, this._stylist_idName); 277 } 278 return false; 279 } 280 } 281 else 282 { 283 anch.onclick = function() 284 { 285 if(this._stylist_applied == true) 286 { 287 editor._stylistRemoveClasses(this._stylist_className, this._stylist_appliedTo); 288 } 289 else 290 { 291 editor._stylistAddClasses(this._stylist_applyTo, this._stylist_applyTag, this._stylist_className); 292 } 293 return false; 294 } 198 295 } 199 296 … … 253 350 this.updateToolbar(); 254 351 }; 352 353 HTMLArea.prototype._stylistAddIDs = function(el, tag, ids) 354 { 355 if(el == 'new') 356 { 357 this.insertHTML('<' + tag + ' id="' + ids + '">' + this.getSelectedHTML() + '</' + tag + '>'); 358 } 359 else 360 { 361 if(tag != null && el.tagName.toLowerCase() != tag) 362 { 363 // Have to change the tag! 364 var new_el = this.switchElementTag(el, tag); 365 366 if(typeof el._stylist_usedToBe != 'undefined') 367 { 368 new_el._stylist_usedToBe = el._stylist_usedToBe; 369 new_el._stylist_usedToBe[new_el._stylist_usedToBe.length] = {'tagName' : el.tagName, 'id' : el.getAttribute('id')}; 370 } 371 else 372 { 373 new_el._stylist_usedToBe = [{'tagName' : el.tagName, 'id' : el.getAttribute('id')}]; 374 } 375 376 HTMLArea.addIDs(new_el, ids); 377 } 378 else 379 { 380 HTMLArea._addIDs(el, ids); 381 } 382 } 383 this.focusEditor(); 384 this.updateToolbar(); 385 }; 255 386 256 387 /** … … 266 397 this.updateToolbar(); 267 398 }; 399 400 HTMLArea.prototype._stylistRemoveIDs = function(ids, from) 401 { 402 for(var x = 0; x < from.length; x++) 403 { 404 this._stylistRemoveIDsFull(from[x], ids); 405 } 406 this.focusEditor(); 407 this.updateToolbar(); 408 }; 268 409 269 410 HTMLArea.prototype._stylistRemoveClassesFull = function(el, classes) … … 336 477 }; 337 478 479 HTMLArea.prototype._stylistRemoveIDsFull = function(el, ids) 480 { 481 if(el != null) 482 { 483 var thiers = el.id.trim().split(' '); 484 var new_thiers = [ ]; 485 var ours = ids.split(' '); 486 for(var x = 0; x < thiers.length; x++) 487 { 488 var exists = false; 489 for(var i = 0; exists == false && i < ours.length; i++) 490 { 491 if(ours[i] == thiers[x]) 492 { 493 exists = true; 494 } 495 } 496 if(exists == false) 497 { 498 new_thiers[new_thiers.length] = thiers[x]; 499 } 500 } 501 502 if(new_thiers.length == 0 && el._stylist_usedToBe && el._stylist_usedToBe.length > 0 && el._stylist_usedToBe[el._stylist_usedToBe.length - 1].id != null) 503 { 504 // Revert back to what we were IF the classes are identical 505 var last_el = el._stylist_usedToBe[el._stylist_usedToBe.length - 1]; 506 var last_ids = HTMLArea.arrayFilter(last_el.id.trim().split(' '), function(c) { if (c == null || c.trim() == '') { return false;} return true; }); 507 508 if( 509 (new_thiers.length == 0) 510 || 511 ( 512 HTMLArea.arrayContainsArray(new_thiers, last_ids) 513 && HTMLArea.arrayContainsArray(last_ids, new_thiers) 514 ) 515 ) 516 { 517 el = this.switchElementTag(el, last_el.tagName); 518 new_thiers = last_ids; 519 } 520 else 521 { 522 // We can't rely on the remembered tags any more 523 el._stylist_usedToBe = [ ]; 524 } 525 } 526 527 if( new_thiers.length > 0 528 || el.tagName.toLowerCase() != 'span' 529 || (el.id && el.id != '') 530 ) 531 { 532 el.id = new_thiers.join(' ').trim(); 533 } 534 else 535 { 536 // Must be a span with no classes and no id, so we can splice it out 537 var prnt = el.parentNode; 538 var childs = el.childNodes; 539 for(var x = 0; x < childs.length; x++) 540 { 541 prnt.insertBefore(childs[x], el); 542 } 543 prnt.removeChild(el); 544 } 545 } 546 }; 547 338 548 /** 339 549 * Change the tag of an element … … 427 637 428 638 if(!found_class) 639 { 640 found_all = false; 641 break; 642 } 643 } 644 645 if(found_all) ancestors[ancestors.length] = prnt; 646 } 647 if(prnt.tagName.toLowerCase() == 'body') break; 648 if(prnt.tagName.toLowerCase() == 'table' ) break; 649 } 650 prnt = prnt.parentNode; 651 } 652 653 return ancestors; 654 }; 655 656 HTMLArea.prototype._ancestorsWithIDs = function(sel, tag, ids) 657 { 658 var ancestors = [ ]; 659 var prnt = this._activeElement(sel); 660 if(prnt == null) 661 { 662 try 663 { 664 prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer); 665 } 666 catch(e) 667 { 668 return ancestors; 669 } 670 } 671 var search_ids = ids.trim().split(' '); 672 673 while(prnt) 674 { 675 if(prnt.nodeType == 1 && prnt.id) 676 { 677 if(tag == null || prnt.tagName.toLowerCase() == tag) 678 { 679 var ids = prnt.id.trim().split(' '); 680 var found_all = true; 681 for(var i = 0; i < search_ids.length; i++) 682 { 683 var found_id = false; 684 for(var x = 0; x < ids.length; x++) 685 { 686 if(search_ids[i] == ids[x]) 687 { 688 found_id = true; 689 break; 690 } 691 } 692 693 if(!found_id) 429 694 { 430 695 found_all = false; -
branches/ray/plugins/SuperClean/dialog.html
r761 r762 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> -
branches/ray/plugins/SuperClean/lang/de.js
r761 r762 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 }; -
branches/ray/plugins/SuperClean/super-clean.js
r761 r762 37 37 var doOK = function() 38 38 { 39 var opts = superclean._dialog.hide(); 39 superclean._dialog.dialog.getElementById("main").style.display = "none"; 40 superclean._dialog.dialog.getElementById("waiting").style.display = ""; 41 superclean._dialog.dialog.getElementById("buttons").style.display = "none"; 42 43 var opts = superclean._dialog.dialog.getValues(); 40 44 var editor = superclean.editor; 41 45 … … 66 70 case 'setHTML': 67 71 editor.setHTML(response.value); 72 superclean._dialog.hide(); 68 73 break; 69 74 case 'alert': 70 alert(superclean._lc(response.value)); 75 superclean._dialog.dialog.getElementById("buttons").style.display = ""; 76 superclean._dialog.dialog.getElementById("ok").style.display = "none"; 77 superclean._dialog.dialog.getElementById("waiting").style.display = "none"; 78 superclean._dialog.dialog.getElementById("alert").style.display = ""; 79 superclean._dialog.dialog.getElementById("alert").innerHTML = superclean._lc(response.value); 80 break; 81 default: // make the dialog go away if sth goes wrong, who knows... 82 superclean._dialog.hide(); 71 83 break; 72 84 } 73 85 } 74 86 Xinha._postback(editor.config.SuperClean.tidy_handler, {'content' : editor.getInnerHTML()},callback); 87 } 88 else 89 { 90 superclean._dialog.hide(); 75 91 } 76 92 return true; … … 189 205 190 206 191 SuperClean.prototype.onGenerate = function()207 SuperClean.prototype.onGenerateOnce = function() 192 208 { 193 209 if(this.editor.config.SuperClean.show_dialog && !this._dialog) … … 282 298 283 299 // 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' );300 var dialog = this.dialog = new Xinha.Dialog(SuperClean.editor, this.html, 'SuperClean',{width:400}); 285 301 286 302 this.ready = true; … … 331 347 { 332 348 this.SuperClean.editor.enableToolbar(); 349 this.dialog.getElementById("main").style.display = ""; 350 this.dialog.getElementById("buttons").style.display = ""; 351 this.dialog.getElementById("waiting").style.display = "none"; 352 this.dialog.getElementById("alert").style.display = "none"; 353 this.dialog.getElementById("ok").style.display = ""; 333 354 return this.dialog.hide(); 334 355 }; -
branches/ray/plugins/SuperClean/tidy.php
r761 r762 116 116 ob_end_clean(); 117 117 118 if( !strlen($content))118 if(strlen($content) < 5) 119 119 { 120 120 // Tidy on the local machine failed, try a post
Note: See TracChangeset
for help on using the changeset viewer.