Changeset 762 for branches


Ignore:
Timestamp:
02/24/07 15:47:57 (13 years ago)
Author:
ray
Message:

updated branch

Location:
branches/ray
Files:
10 added
20 edited

Legend:

Unmodified
Added
Removed
  • branches/ray/Xinha.css

    r761 r762  
    108108.dialog { 
    109109  color: ButtonText; 
    110   background: ButtonFace; 
    111 } 
    112  
     110  background: ButtonFace;  
     111  border: 1px outset;  
     112  border-color: WindowFrame; 
     113} 
     114div.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} 
    113124.dialog .content { padding: 2px; } 
    114125 
     
    121132.dialog .title, .dialog h1 
    122133{ 
    123   background: #008; 
    124   color: #ff8; 
     134  background: ActiveCaption; 
     135  color: CaptionText; 
    125136  border-bottom: 1px solid #000; 
    126137  padding: 1px 0px 2px 5px; 
     
    128139  font-weight: bold; 
    129140  cursor: default; 
    130 } 
    131 .dialog h1 { margin:0px;} 
     141  letter-spacing: 0.01em; 
     142} 
     143.dialog h1 { margin:0;} 
    132144.dialog .title .button { 
    133145  float: right; 
     
    142154 
    143155.dialog button { 
    144   width: 5em; 
     156  width: 5.5em; 
    145157  padding: 0px; 
    146158} 
    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} 
    148178.dialog .buttonColor { 
     179  width :1em; 
    149180  padding: 1px; 
    150181  cursor: default; 
     
    153184} 
    154185 
     186.dialog .buttonClick { 
     187  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; 
     188} 
    155189.dialog .buttonColor-hilite { 
    156190  border-color: #000; 
     
    169203.dialog .label { text-align: right; width: 6em; } 
    170204.dialog .value input { width: 100%; } 
    171 .dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; } 
    172205 
    173206.dialog legend { font-weight: bold; } 
    174207.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} 
    176222.popupwin { 
    177223  padding: 0px; 
     
    228274  padding: 2px; 
    229275  clear:left; 
    230    
     276  letter-spacing: 0.01em; 
    231277} 
    232278 
  • branches/ray/XinhaCore.js

    r761 r762  
    507507  this.debug = true; 
    508508 
     509  // ATTENTION: implementing custom image/link/table popups using this uris is DEPRECATED 
    509510  this.URIs = 
    510511  { 
     
    12781279        function(ev) 
    12791280        { 
     1281          ev = Xinha.is_ie ? window.event : ev; 
     1282          editor.btnClickEvent = ev; 
    12801283          if ( obj.enabled ) 
    12811284          { 
     
    12871290            } 
    12881291            obj.cmd(editor, obj.name, obj); 
    1289             Xinha._stopEvent(Xinha.is_ie ? window.event : ev); 
     1292            Xinha._stopEvent(ev); 
    12901293          } 
    12911294        } 
     
    15531556          if ( typeof InsertImage == 'undefined' && typeof Xinha.prototype._insertImage == 'undefined' ) 
    15541557          { 
    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'); 
    15561560            return false; 
    15571561          } 
     
    15611565          if ( typeof CreateLink == 'undefined' && typeof Xinha.prototype._createLink == 'undefined' &&  typeof Linker == 'undefined' ) 
    15621566          { 
    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); 
    15641569            return false; 
    15651570          } 
     
    15691574          if ( typeof InsertTable == 'undefined' && typeof Xinha.prototype._insertTable == 'undefined' ) 
    15701575          { 
    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); 
    15721578            return false; 
    15731579          } 
     
    49995005        } 
    50005006      } 
     5007      else if (req.status == 404) 
     5008      { 
     5009        alert('File not found: ' + url); 
     5010      } 
    50015011      else 
    50025012      { 
    5003         alert('An error has occurred: ' + req.statusText); 
     5013        alert('An error has occurred: ' + req.statusText + '\nURL: ' + url); 
    50045014      } 
    50055015    } 
     
    50275037        handler(req.responseText, req); 
    50285038      } 
     5039      else if (req.status == 404) 
     5040      { 
     5041        alert('File not found: ' + url); 
     5042      } 
    50295043      else 
    50305044      { 
    5031         alert('An error has occurred: ' + req.statusText); 
     5045        alert('An error has occurred: ' + req.statusText + '\nURL: ' + url); 
    50325046      } 
    50335047    } 
  • branches/ray/examples/ext_example-body.html

    r761 r762  
    1212  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    1313  <title>Example of Xinha</title> 
    14   <link rel="stylesheet" type="text/css" href="full_example.css" /> 
     14 
    1515 
    1616  <script type="text/javascript"> 
  • branches/ray/examples/testbed.html

    r761 r762  
    1 <?xml version="1.0" encoding="UTF-8"?> 
    21<!DOCTYPE html 
    32     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     
    5554      xinha_plugins = xinha_plugins ? xinha_plugins : 
    5655      [ 
    57         'CharacterMap', 'SpellChecker', 'Linker' 
     56        'CharacterMap', 'SpellChecker', 'SmartReplace','PasteText','SuperClean' 
     57        //'Linker'//,'GetHtml' 
    5858      ]; 
    5959             // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING  :) 
     
    6767      xinha_editors = xinha_editors ? xinha_editors : 
    6868      [ 
    69         'myTextArea' 
     69      'HAllo',   
     70      'myTextArea' 
     71         
    7072      ]; 
    7173 
     
    8486 
    8587       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; 
    8791       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  ]; 
    88105/* 
    89106       // We can load an external stylesheet like this - NOTE : YOU MUST GIVE AN ABSOLUTE URL 
     
    142159</head> 
    143160 
    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       &lt;html&gt; 
    149       &lt;head&gt; 
    150         &lt;title&gt;Hello&lt;/title&gt; 
    151         &lt;style type="text/css"&gt; 
    152           li { color:red; } 
    153         &lt;/style&gt; 
    154       &lt;/head&gt; 
    155       &lt;body&gt; 
    156       &lt;img src="http://xinha.python-hosting.com/trac/logo.jpg" usemap="#m1"&gt; 
    157       &lt;map name="m1"&gt; 
    158       &lt;area shape="rect" coords="137,101,255,124" href="http://www.mydomain.com"&gt; 
    159       &lt;/map&gt; 
    160  
    161       &lt;p&gt; 
    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       &lt;/p&gt; 
    170  
    171       &lt;ul&gt; 
    172         &lt;li&gt; Phasellus et massa sed diam viverra semper.  &lt;/li&gt; 
    173         &lt;li&gt; Mauris tincidunt felis in odio.              &lt;/li&gt; 
    174         &lt;li&gt; Nulla placerat nunc ut pede.                 &lt;/li&gt; 
    175         &lt;li&gt; Vivamus ultrices mi sit amet urna.           &lt;/li&gt; 
    176         &lt;li&gt; Quisque sed augue quis nunc laoreet volutpat.&lt;/li&gt; 
    177         &lt;li&gt; Nunc sit amet metus in tortor semper mattis. &lt;/li&gt; 
    178       &lt;/ul&gt; 
    179       &lt;/body&gt; 
    180       &lt;/html&gt; 
    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%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr><tr><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</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%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr><tr><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</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%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr><tr><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</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%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr><tr><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</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%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr><tr><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td><td style="width: 25%;">&nbsp;</td></tr></tbody></table><br /></textarea> 
    182198 
    183199    <input type="submit" /> <input type="reset" /> 
  • branches/ray/modules/ColorPicker/ColorPicker.js

    r761 r762  
    132132    this.table.appendChild(this.tbody); 
    133133    this.table.style.border = '1px solid WindowFrame'; 
    134     this.table.style.zIndex = '1000'; 
     134    this.table.style.zIndex = '1050'; 
    135135    // Add a title bar and close button 
    136136    var tr = document.createElement('tr'); 
     
    141141    td.style.fontFamily = 'small-caption,caption,sans-serif'; 
    142142    td.style.fontSize = 'x-small'; 
     143    td.unselectable = "on"; 
     144    td.style.MozUserSelect = "none"; 
    143145    td.appendChild(document.createTextNode(Xinha._lc('Click a color...'))); 
    144146    td.style.borderBottom = '1px solid WindowFrame'; 
     
    829831  return Xinha._lc(string); 
    830832} 
     833Xinha.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} 
     862Xinha.colorPicker.inputBinding.prototype.setColor = function(color) 
     863{ 
     864  this.chooser.style.backgroundColor = color; 
     865} 
  • branches/ray/modules/Dialogs/inline-dialog.js

    r761 r762  
    2121    --  $LastChangedBy$ 
    2222    --------------------------------------------------------------------------*/ 
    23 Xinha.Dialog = function(editor, html, localizer) 
    24 { 
     23Xinha.Dialog = function(editor, html, localizer, size, layer) 
     24{ 
     25  var dialog = this; 
    2526  this.id    = { }; 
    2627  this.r_id  = { }; // reverse lookup id 
    2728  this.editor   = editor; 
    2829  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 
    39104  if(typeof localizer == 'function') 
    40105  { 
     
    78143             ); 
    79144 
    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 
     206Xinha.Dialog.background = []; 
     207Xinha.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 
     218Xinha.Dialog.prototype.onresize = function() 
     219{ 
     220  return true; 
     221}; 
     222 
     223Xinha.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) 
    88315      { 
    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; 
    92317      } 
    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   
    109341  if(typeof values != 'undefined') 
    110342  { 
    111343    this.setValues(values); 
    112344  } 
    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(); 
    118347}; 
    119348 
    120349Xinha.Dialog.prototype.hide = function() 
    121350{ 
    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  {  
    130388    this._lastRange.select(); 
    131389  } 
     390  this.dialogShown = false; 
    132391  this.editor.updateToolbar(); 
    133392  return this.getValues(); 
     
    144403    this.hide(); 
    145404  } 
     405}; 
     406 
     407Xinha.Dialog.prototype.getElementById = function(id) 
     408{ 
     409  return this.document.getElementById(this.id[id] ? this.id[id] : id); 
     410}; 
     411 
     412Xinha.Dialog.prototype.getElementsByName = function(name) 
     413{ 
     414  return this.document.getElementsByName(this.id[name] ? this.id[name] : name); 
     415}; 
     416 
     417Xinha.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 
     436Xinha.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 
     455Xinha.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 
     467Xinha.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 
     486Xinha.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 
     511Xinha.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; 
    146521}; 
    147522 
     
    337712  return values; 
    338713}; 
    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  
    7272   */ 
    7373  function resetScroll() 
    74   { 
     74  {console.log('resetScroll'); 
    7575    if(e._isFullScreen) 
    7676    { 
  • branches/ray/plugins/ImageManager/Classes/ImageEditor.php

    r761 r762  
    1 <<<<<<< .working 
    21<?php 
    32/** 
     
    87 */ 
    98 
    10 require_once('Transform.php'); 
     9require_once('../ImageManager/Classes/Transform.php'); 
    1110 
    1211/** 
     
    449448 
    450449?> 
    451 ======= 
    452 <?php 
    453 /** 
    454  * Image Editor. Editing tools, crop, rotate, scale and save. 
    455  * @author $Author$ 
    456  * @version $Id$ 
    457  * @package ImageManager 
    458  */ 
    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 ImageManager 
    467  * @subpackage Editor 
    468  */ 
    469 class ImageEditor  
    470 { 
    471         /** 
    472          * ImageManager instance. 
    473          */ 
    474         var $manager; 
    475  
    476         /** 
    477          * user based on IP address 
    478          */ 
    479         var $_uid; 
    480  
    481         /** 
    482          * tmp file storage time. 
    483          */ 
    484         var $lapse_time =900; //15 mins 
    485  
    486         var $filesaved = 0; 
    487  
    488         /** 
    489          * Create a new ImageEditor instance. Editing requires a  
    490          * tmp file, which is saved in the current directory where the 
    491          * image is edited. The tmp file is assigned by md5 hash of the 
    492          * user IP address. This hashed is used as an ID for cleaning up 
    493          * the tmp files. In addition, any tmp files older than the 
    494          * the specified period will be deleted. 
    495          * @param ImageManager $manager the image manager, we need this 
    496          * 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                 else 
    525                         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                 else 
    543                 { 
    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 a 
    556          * 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 filename 
    560          * @param string $fullpath the fullpath to the image file 
    561          * @return array with image information 
    562          * <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, so 
    605                                         //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                                         else 
    613                                                 $this->filesaved = -1; 
    614                                 } 
    615                                 break; 
    616                 } 
    617                  
    618                 //create the tmp image file 
    619                 $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 information 
    629                 $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 name 
    644          * and the save type. 
    645          * @param string $type image type, 'jpeg', 'png', or 'gif' 
    646          * @return string the filename according to save type 
    647          */ 
    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 unique 
    673          */ 
    674         function getDefaultSaveFile()  
    675         { 
    676                 if(isset($_GET['img'])) 
    677                         $relative = rawurldecode($_GET['img']); 
    678                 else 
    679                         Return null; 
    680  
    681                 Return $this->getUniqueFilename($relative); 
    682         } 
    683  
    684         /** 
    685          * Get a unique filename. If the file exists, the filename 
    686          * base is appended with an increasing integer. 
    687          * @param string $relative the relative filename to the base_dir 
    688          * @return string a unique filename in the current path 
    689          */ 
    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 filename 
    723          * and return the new filename with relative path. 
    724          * i.e. $pathA (-filename) + $file 
    725          * @param string $pathA the relative file 
    726          * @param string $file the new filename 
    727          * @return string relative path with the new filename 
    728          */ 
    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 parameter 
    741          * @return string action parameter 
    742          */ 
    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 characters 
    754          * @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 prefix 
    764          * specified in config.inc.php plus  
    765          * 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 file 
    769          * @return string a unique filename for that path 
    770          * 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 exists 
    781         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 path  
    794          * 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 GD 
    858          * mainly to check that GD can read and save GIFs 
    859          * @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                 else 
    866                         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                 else 
    880                         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                 else 
    896                         Return -1; 
    897         } 
    898 } 
    899  
    900 ?> 
    901 >>>>>>> .merge-right.r760 
  • branches/ray/plugins/ImageManager/Classes/ImageManager.php

    r761 r762  
    1 <<<<<<< .working 
    21<?php 
    32/** 
     
    87 */ 
    98 
    10 require_once('Files.php'); 
     9require_once('../ImageManager/Classes/Files.php'); 
    1110 
    1211// uncomment to turn on debugging 
     
    664663 
    665664?> 
    666 ======= 
    667 <?php 
    668 /** 
    669  * ImageManager, list images, directories, and thumbnails. 
    670  * @author $Author$ 
    671  * @version $Id$ 
    672  * @package ImageManager 
    673  */ 
    674  
    675 require_once('../ImageManager/Classes/Files.php'); 
    676  
    677 // uncomment to turn on debugging 
    678  
    679 // _ddtOn(); 
    680  
    681 /** 
    682  * ImageManager Class. 
    683  * @author $Author$ 
    684  * @version $Id$ 
    685  */ 
    686 class ImageManager  
    687 { 
    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.php 
    701          */ 
    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.php 
    710          */ 
    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.php 
    719          */ 
    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 contain 
    742          * the relative path (relative to the base dir) as key and the  
    743          * full path as value. 
    744          * @return array of sub directries 
    745          * <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 list 
    760          * of accessable directories. 
    761          * @param string $base the full path to the current directory 
    762          * @param string $path the relative path name 
    763          * @return array of accessiable sub-directories 
    764          * <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 with 
    779                         // a dot, and if is it not the thumbnail directory 
    780                         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 directory 
    824                         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 folder 
    859          * 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) == false 
    874                                         && $this->isTmpFile($entry) == false 
    875                                         && $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 file 
    888          * @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 checked 
    899          * @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                 else 
    907                         Return false; 
    908         } 
    909  
    910         /** 
    911          * Check if the given directory is a thumbnail directory. 
    912          * @param string $entry directory name 
    913          * @return true if it is a thumbnail directory, false otherwise 
    914          */ 
    915         function isThumbDir($entry)  
    916         { 
    917                 if($this->config['thumbnail_dir'] == false 
    918                         || strlen(trim($this->config['thumbnail_dir'])) == 0) 
    919                         Return false;            
    920                 else 
    921                         Return ($entry == $this->config['thumbnail_dir']); 
    922         } 
    923  
    924         /** 
    925          * Check if the given file is a tmp file. 
    926          * @param string $file file name 
    927          * @return boolean true if it is a tmp file, false otherwise 
    928          */ 
    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                 else 
    935                         Return false;            
    936         } 
    937  
    938         /** 
    939          * For a given image file, get the respective thumbnail filename 
    940          * no file existence check is done. 
    941          * @param string $fullpathfile the full path to the image file 
    942          * @return string of the thumbnail file 
    943          */ 
    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                 else 
    955                 { 
    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 the 
    965          * given base_url in config.inc.php 
    966          * @param string $relative the relative image file name,  
    967          * relative to the base_dir path 
    968          * @return string the url of the thumbnail 
    969          */ 
    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'] == true 
    980                         || strlen(trim($this->config['thumbnail_dir'])) == 0) 
    981                 { 
    982                         Return Files::makeFile($this->getImagesURL(),$thumbnail); 
    983                 } 
    984                 else 
    985                 { 
    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 filename 
    1006          * no file existence check is done. 
    1007          * @param string $fullpathfile the full path to the image file 
    1008          * @param integer $width the intended width 
    1009          * @param integer $height the intended height 
    1010          * @param boolean $mkDir whether to attempt to make the resized_dir if it doesn't exist 
    1011          * @return string of the resized filename 
    1012          */ 
    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                 else 
    1024                 { 
    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 subdirectories 
    1034          * under the base_dir. 
    1035          * @param string $path the relative path to be checked 
    1036          * @return boolean true if the path exists, false otherwise 
    1037          */ 
    1038         function validRelativePath($path)  
    1039         { 
    1040                 $dirs = $this->getDirs(); 
    1041                 if($path == '/') 
    1042                         Return true; 
    1043                 //check the path given in the url against the  
    1044                 //list of paths in the system. 
    1045                 for($i = 0; $i < count($dirs); $i++) 
    1046                 { 
    1047                         $key = key($dirs); 
    1048                         //we found the path 
    1049                         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 in  
    1059          * $_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 with 
    1062          * image dimensions will be accepted. 
    1063          * @return null 
    1064          */ 
    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                 else 
    1075                         return; 
    1076  
    1077                 //check for the file, and must have valid relative path 
    1078                 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 an  
    1086          * uploaded file. If 'validate_images' is set to 
    1087          * true, only images will be processed. Any duplicate 
    1088          * file will be renamed. See Files::copyFile for details 
    1089          * on renaming. 
    1090          * @param string $relative the relative path where the file 
    1091          * should be copied to. 
    1092          * @param array $file the uploaded file from $_FILES 
    1093          * @return boolean true if the file was processed successfully,  
    1094          * false otherwise 
    1095          */ 
    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 file 
    1127                 $path = Files::makePath($this->getImagesDir(),$relative); 
    1128                 $result = Files::copyFile($file['tmp_name'], $path, $file['name']); 
    1129  
    1130                 //no copy error 
    1131                 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 the  
    1145          * base_url given in config.inc.php 
    1146          * @param string $relative a file the relative to the base_dir 
    1147          * @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 if  
    1167          * the thumbnail doesn't exist. 
    1168          */ 
    1169         function getDefaultThumb()  
    1170         { 
    1171  
    1172                 // FIXME: hack 
    1173  
    1174                 Return $this->config['default_thumbnail']; 
    1175  
    1176                 if(is_file($this->config['default_thumbnail'])) 
    1177                         { 
    1178                         Return $this->config['default_thumbnail']; 
    1179                         } 
    1180                 else  
    1181                         Return ''; 
    1182         } 
    1183  
    1184  
    1185         /** 
    1186          * Get the thumbnail url to be displayed.  
    1187          * If the thumbnail exists, and it is up-to-date 
    1188          * the thumbnail url will be returns. If the  
    1189          * file is not an image, a default image will be returned. 
    1190          * If it is an image file, and no thumbnail exists or  
    1191          * the thumbnail is out-of-date (i.e. the thumbnail  
    1192          * 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 thumbnail 
    1195          * on the fly. If the image is less than the dimensions 
    1196          * 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 it 
    1199          * actually thumbnail or a script to generate the 
    1200          * 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 image 
    1218                 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 and 
    1230                 // it is up-to-date, return the thumbnail url 
    1231                 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.php 
    1242                 //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 otherwise 
    1249          */ 
    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 otherwise 
    1259          */ 
    1260         function deleteDirs()  
    1261         { 
    1262                  if(isset($_GET['deld'])) 
    1263                         return $this->_delDir(rawurldecode($_GET['deld']));              
    1264                  else 
    1265                          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 image 
    1278                 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                 else 
    1289                         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                 else 
    1303                         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  
    9999  </fieldset> 
    100100 
    101   <div style="text-align:right"> 
     101  <div class="buttons"> 
    102102    <input type="button" id="[ok]"     value="_(OK)"     /> 
    103     <input type="button" id="[clear]"  value="_(Remove Link)" onclick="this.form['[href]'].value='';this.form['[to]'].value='';document.getElementById('[ok]').click();" /> 
     103    <input type="button" id="[clear]" value="_(Remove Link)" onclick="this.form['[href]'].value='';this.form['[to]'].value='';document.getElementById('[ok]').click();" /> 
    104104    <input type="button" id="[cancel]" value="_(Cancel)" /> 
    105105  </div> 
  • branches/ray/plugins/Linker/linker.js

    r761 r762  
    366366 
    367367  // 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}); 
    369369  var dTreeName = Xinha.uniq('dTree_'); 
    370370 
     
    379379  //ddTree.innerHTML = this.dTree.toString(); 
    380380  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'; 
    384384  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  } 
    385394  ddTree.style.backgroundColor = 'white'; 
    386395  this.ddTree = ddTree; 
     
    388397 
    389398  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'; 
    393402  options.style.width    = 320 + 'px'; 
    394403  options.style.overflow = 'auto'; 
    395404 
    396405  // Hookup the resizer 
     406  this.dialog.rootElem.style.paddingBottom ="0"; 
    397407  this.dialog.onresize = function() 
    398408    { 
    399409      var h = parseInt(dialog.height) - dialog.getElementById('h1').offsetHeight; 
    400       var w = parseInt(dialog.width)  - 322 ; 
     410      var w = parseInt(dialog.width)  - 330 ; 
     411 
    401412      // An error is thrown with IE when trying to set a negative width or a negative height 
    402413      // But perhaps a width / height of 0 is not the minimum required we need to set 
    403414      if (w<0) w = 0; 
    404415      if (h<0) h = 0; 
    405       options.style.height = ddTree.style.height = h + 'px'; 
     416      //options.style.height = 
     417       ddTree.style.height = h + 'px'; 
    406418      ddTree.style.width  = w + 'px'; 
    407419    } 
    408  
    409420  this.ready = true; 
    410421}; 
  • branches/ray/plugins/PasteText/paste-text.js

    r761 r762  
    88        var cfg = editor.config; 
    99        var self = this; 
    10          
     10 
    1111        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        }); 
    2018 
    2119        cfg.addToolbarElement("pastetext", ["paste", "killword"], 1); 
     
    3432 
    3533PasteText.prototype._lc = function(string) { 
    36     return Xinha._lc(string, 'PasteText'); 
     34        return Xinha._lc(string, 'PasteText'); 
    3735}; 
    3836 
     
    4341} 
    4442 
    45 PasteText.prototype.buttonPress = function(editor) { 
     43PasteText.prototype.onGenerateOnce = function() 
     44{ 
     45        this._prepareDialog(); 
     46}; 
    4647 
     48PasteText.prototype._prepareDialog = function() 
     49{ 
     50        var self = this; 
    4751        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, "&lt;"); 
    53                 html = html.replace(/>/g, "&gt;"); 
    54                 if ( ret.insertParagraphs) 
    55                 { 
    56                         html = html.replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;"); 
    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 
     93PasteText.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 
     117PasteText.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, "&lt;"); 
     126        html = html.replace(/>/g, "&gt;"); 
     127        if ( returnValues.insertParagraphs) 
     128        { 
     129                html = html.replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;"); 
     130                html = html.replace(/\n/g,"</p><p>"); 
     131                html="<p>" + html + "</p>"; 
     132                if (Xinha.is_ie) 
     133                { 
     134                        this.editor.insertHTML(html); 
    67135                } 
    68136                else 
    69137                { 
    70                         html = html.replace(/\n/g,"<br />"); 
    71                         editor.insertHTML(html); 
     138                        this.editor.execCommand("inserthtml",false,html); 
    72139                } 
    73140        } 
    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        } 
    75146}; 
  • 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  
    436</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)" /> 
    469</div> 
    47 </body> 
    48 </html> 
  • branches/ray/plugins/SmartReplace/dialog.html

    r761 r762  
    1111  </tr> 
    1212</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> 
    1713</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  
    263263        var self = this; 
    264264 
    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(); 
    268268        } 
    269269        var doOK = function() 
    270270        { 
    271                 var opts = self._dialog.hide(); 
     271                var opts = self.dialog.hide(); 
    272272                self.toggleActivity((opts.enable) ? true : false);  
    273273                if (opts.convert) 
    274274                { 
    275275                        self.replaceAll(); 
    276                         self._dialog.dialog.getElementById("convert").checked = false; 
     276                        self.dialog.getElementById("convert").checked = false; 
    277277                } 
    278278        } 
     
    282282                convert: '' 
    283283        }; 
    284         this._dialog.show(inputs, doOK); 
     284        this.show(inputs, doOK); 
    285285}; 
    286286 
    287287SmartReplace.prototype.onGenerateOnce = function() 
    288288{ 
    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, nifty 
    300  
    301   this.ready = false; 
    302   this.files  = false; 
    303   this.html   = false; 
    304   this.dialog = false; 
    305  
    306289  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 
     292SmartReplace.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(); }); 
    318300    return; 
    319301  } 
    320302   
    321303  // 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}); 
    323305 
    324306  this.ready = true; 
    325307}; 
    326308 
    327 SmartReplace.Dialog.prototype._lc = SmartReplace.prototype._lc; 
    328  
    329 SmartReplace.Dialog.prototype.show = function(inputs, ok, cancel) 
     309SmartReplace.prototype.show = function(inputs, ok, cancel) 
    330310{ 
    331311  if(!this.ready) 
    332312  { 
    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); 
    335315    return; 
    336316  } 
    337317 
    338318  // Connect the OK and Cancel buttons 
    339   var dialog = this.dialog; 
    340   var pluginDialogObject = this; 
     319  var self = this; 
    341320  if(ok) 
    342321  { 
     
    345324  else 
    346325  { 
    347     this.dialog.getElementById('ok').onclick = function() {pluginDialogObject.hide();}; 
     326    this.dialog.getElementById('ok').onclick = function() {self.dialog.hide();}; 
    348327  } 
    349328 
     
    354333  else 
    355334  { 
    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  } 
    361337 
    362338  this.dialog.show(inputs); 
     
    365341  this.dialog.onresize(); 
    366342}; 
    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  
    8383    var className = x.trim(); 
    8484    var applicable = true; 
     85    var idApplicable = false; 
    8586    var apply_to   = active_elem; 
    8687 
     
    9697      // No class name, just redefines a tag 
    9798      applicable = false; 
     99   
     100      if (className.indexOf('#') >= 0) 
     101      { 
     102        idApplicable = true; 
     103      } 
    98104    } 
    99105 
     
    147153    } 
    148154 
    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      } 
    156224 
    157225      if(apply_to == null) 
     
    170238    } 
    171239 
    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) 
    176252    { 
    177253      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(); 
    179258      anch._stylist_applied   = applied; 
    180259      anch._stylist_appliedTo = applied_to; 
     
    185264      anch.href = 'javascript:void(0)'; 
    186265      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        } 
    198295      } 
    199296 
     
    253350    this.updateToolbar(); 
    254351  }; 
     352   
     353HTMLArea.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  };   
    255386 
    256387/** 
     
    266397    this.updateToolbar(); 
    267398  }; 
     399   
     400HTMLArea.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  };   
    268409 
    269410HTMLArea.prototype._stylistRemoveClassesFull = function(el, classes) 
     
    336477}; 
    337478 
     479HTMLArea.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 
    338548/** 
    339549 * Change the tag of an element 
     
    427637 
    428638          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 
     656HTMLArea.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) 
    429694          { 
    430695            found_all = false; 
  • branches/ray/plugins/SuperClean/dialog.html

    r761 r762  
    11<h1 id="[h1]"><l10n>Clean up HTML</l10n></h1> 
    2 <div style="margin-left: 10px;"> 
     2<div style="margin-left: 10px;" id="[main]"> 
    33    <l10n>Please select from the following cleaning options...</l10n> 
    44    <!--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> 
    95</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  
    1414  "Cancel": "Abbrechen", 
    1515  "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..." 
    1718}; 
  • branches/ray/plugins/SuperClean/super-clean.js

    r761 r762  
    3737  var doOK = function() 
    3838  { 
    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(); 
    4044    var editor = superclean.editor; 
    4145 
     
    6670          case 'setHTML': 
    6771            editor.setHTML(response.value); 
     72            superclean._dialog.hide(); 
    6873          break; 
    6974          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(); 
    7183          break; 
    7284        } 
    7385      } 
    7486      Xinha._postback(editor.config.SuperClean.tidy_handler, {'content' : editor.getInnerHTML()},callback); 
     87    } 
     88    else 
     89    { 
     90      superclean._dialog.hide(); 
    7591    } 
    7692    return true; 
     
    189205 
    190206 
    191 SuperClean.prototype.onGenerate = function() 
     207SuperClean.prototype.onGenerateOnce = function() 
    192208{ 
    193209  if(this.editor.config.SuperClean.show_dialog && !this._dialog) 
     
    282298 
    283299  // 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}); 
    285301 
    286302  this.ready = true; 
     
    331347{ 
    332348  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 = ""; 
    333354  return this.dialog.hide(); 
    334355}; 
  • branches/ray/plugins/SuperClean/tidy.php

    r761 r762  
    116116    ob_end_clean(); 
    117117 
    118     if(!strlen($content)) 
     118    if(strlen($content) < 5) 
    119119    { 
    120120      // Tidy on the local machine failed, try a post 
Note: See TracChangeset for help on using the changeset viewer.