[ Index ]
 

Code source de DokuWiki 2006-11-06

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/scripts/ -> edit.js (source)

   1  /**
   2   * Functions for text editing (toolbar stuff)
   3   *
   4   * @todo I'm no JS guru please help if you know how to improve
   5   * @author Andreas Gohr <andi@splitbrain.org>
   6   */
   7  
   8  /**
   9   * Creates a toolbar button through the DOM
  10   *
  11   * Style the buttons through the toolbutton class
  12   *
  13   * @author Andreas Gohr <andi@splitbrain.org>
  14   */
  15  function createToolButton(icon,label,key,id){
  16      var btn = document.createElement('button');
  17      var ico = document.createElement('img');
  18  
  19      // preapare the basic button stuff
  20      btn.className = 'toolbutton';
  21      btn.title = label;
  22      if(key){
  23          btn.title += ' [ALT+'+key.toUpperCase()+']';
  24          btn.accessKey = key;
  25      }
  26  
  27      // set IDs if given
  28      if(id){
  29          btn.id = id;
  30          ico.id = id+'_ico';
  31      }
  32  
  33      // create the icon and add it to the button
  34      ico.src = DOKU_BASE+'lib/images/toolbar/'+icon;
  35      btn.appendChild(ico);
  36  
  37      return btn;
  38  }
  39  
  40  /**
  41   * Creates a picker window for inserting text
  42   *
  43   * The given list can be an associative array with text,icon pairs
  44   * or a simple list of text. Style the picker window through the picker
  45   * class or the picker buttons with the pickerbutton class. Picker
  46   * windows are appended to the body and created invisible.
  47   *
  48   * @author Andreas Gohr <andi@splitbrain.org>
  49   */
  50  function createPicker(id,list,icobase,edid){
  51      var cnt = list.length;
  52  
  53      var picker = document.createElement('div');
  54      picker.className = 'picker';
  55      picker.id = id;
  56      picker.style.position = 'absolute';
  57      picker.style.display  = 'none';
  58  
  59      for(var key in list){
  60          var btn = document.createElement('button');
  61  
  62          btn.className = 'pickerbutton';
  63  
  64          // associative array?
  65          if(isNaN(key)){
  66              var ico = document.createElement('img');
  67              ico.src       = DOKU_BASE+'lib/images/'+icobase+'/'+list[key];
  68              btn.title     = key;
  69              btn.appendChild(ico);
  70              eval("btn.onclick = function(){pickerInsert('"+id+"','"+
  71                                    jsEscape(key)+"','"+
  72                                    jsEscape(edid)+"');return false;}");
  73          }else{
  74              var txt = document.createTextNode(list[key]);
  75              btn.title     = list[key];
  76              btn.appendChild(txt);
  77              eval("btn.onclick = function(){pickerInsert('"+id+"','"+
  78                                    jsEscape(list[key])+"','"+
  79                                    jsEscape(edid)+"');return false;}");
  80          }
  81  
  82          picker.appendChild(btn);
  83      }
  84      var body = document.getElementsByTagName('body')[0];
  85      body.appendChild(picker);
  86  }
  87  
  88  /**
  89   * Called by picker buttons to insert Text and close the picker again
  90   *
  91   * @author Andreas Gohr <andi@splitbrain.org>
  92   */
  93  function pickerInsert(pickerid,text,edid){
  94      // insert
  95      insertAtCarret(edid,text);
  96      // close picker
  97      pobj = document.getElementById(pickerid);
  98      pobj.style.display = 'none';
  99  }
 100  
 101  /**
 102   * Show a previosly created picker window
 103   *
 104   * @author Andreas Gohr <andi@splitbrain.org>
 105   */
 106  function showPicker(pickerid,btn){
 107      var picker = document.getElementById(pickerid);
 108      var x = findPosX(btn);
 109      var y = findPosY(btn);
 110      if(picker.style.display == 'none'){
 111          picker.style.display = 'block';
 112          picker.style.left = (x+3)+'px';
 113          picker.style.top = (y+btn.offsetHeight+3)+'px';
 114      }else{
 115          picker.style.display = 'none';
 116      }
 117  }
 118  
 119  /**
 120   * Create a toolbar
 121   *
 122   * @param  string tbid ID of the element where to insert the toolbar
 123   * @param  string edid ID of the editor textarea
 124   * @param  array  tb   Associative array defining the buttons
 125   * @author Andreas Gohr <andi@splitbrain.org>
 126   */
 127  function initToolbar(tbid,edid,tb){
 128      var toolbar = $(tbid);
 129      if(!toolbar) return;
 130  
 131      //empty the toolbar area:
 132      toolbar.innerHTML='';
 133  
 134      var cnt = tb.length;
 135      for(var i=0; i<cnt; i++){
 136          // create new button
 137          btn = createToolButton(tb[i]['icon'],
 138                                 tb[i]['title'],
 139                                 tb[i]['key']);
 140  
 141          // add button action dependend on type
 142          switch(tb[i]['type']){
 143              case 'format':
 144                  var sample = tb[i]['title'];
 145                  if(tb[i]['sample']){ sample = tb[i]['sample']; }
 146  
 147                  eval("btn.onclick = function(){insertTags('"+
 148                                          jsEscape(edid)+"','"+
 149                                          jsEscape(tb[i]['open'])+"','"+
 150                                          jsEscape(tb[i]['close'])+"','"+
 151                                          jsEscape(sample)+
 152                                      "');return false;}");
 153                  toolbar.appendChild(btn);
 154                  break;
 155              case 'insert':
 156                  eval("btn.onclick = function(){insertAtCarret('"+
 157                                          jsEscape(edid)+"','"+
 158                                          jsEscape(tb[i]['insert'])+
 159                                      "');return false;}");
 160                  toolbar.appendChild(btn);
 161                  break;
 162              case 'signature':
 163                  if(typeof(SIG) != 'undefined' && SIG != ''){
 164                      eval("btn.onclick = function(){insertAtCarret('"+
 165                                              jsEscape(edid)+"','"+
 166                                              jsEscape(SIG)+
 167                                          "');return false;}");
 168                      toolbar.appendChild(btn);
 169                  }
 170                  break;
 171              case 'picker':
 172                  createPicker('picker'+i,
 173                               tb[i]['list'],
 174                               tb[i]['icobase'],
 175                               edid);
 176                  eval("btn.onclick = function(){showPicker('picker"+i+
 177                                      "',this);return false;}");
 178                  toolbar.appendChild(btn);
 179                  break;
 180              case 'mediapopup':
 181                  eval("btn.onclick = function(){window.open('"+
 182                                          jsEscape(tb[i]['url']+NS)+"','"+
 183                                          jsEscape(tb[i]['name'])+"','"+
 184                                          jsEscape(tb[i]['options'])+
 185                                      "');return false;}");
 186                  toolbar.appendChild(btn);
 187                  break;
 188          } // end switch
 189      } // end for
 190  }
 191  
 192  /**
 193   * Format selection
 194   *
 195   * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
 196   * of selection if there is none. Copied and adapted from phpBB
 197   *
 198   * @author phpBB development team
 199   * @author MediaWiki development team
 200   * @author Andreas Gohr <andi@splitbrain.org>
 201   * @author Jim Raynor <jim_raynor@web.de>
 202   */
 203  function insertTags(edid,tagOpen, tagClose, sampleText) {
 204    var txtarea = document.getElementById(edid);
 205    // IE
 206    if(document.selection  && !is_gecko) {
 207      var theSelection = document.selection.createRange().text;
 208      var replaced = true;
 209      if(!theSelection){
 210        replaced = false;
 211        theSelection=sampleText;
 212      }
 213      txtarea.focus();
 214  
 215      // This has change
 216      var text = theSelection;
 217      if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
 218        theSelection = theSelection.substring(0, theSelection.length - 1);
 219        r = document.selection.createRange();
 220        r.text = tagOpen + theSelection + tagClose + " ";
 221      } else {
 222        r = document.selection.createRange();
 223        r.text = tagOpen + theSelection + tagClose;
 224      }
 225      if(!replaced){
 226        r.moveStart('character',-text.length-tagClose.length);
 227        r.moveEnd('character',-tagClose.length);
 228      }
 229      r.select();
 230    // Mozilla
 231    } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
 232      replaced = false;
 233      var startPos = txtarea.selectionStart;
 234      var endPos   = txtarea.selectionEnd;
 235      if(endPos - startPos){ replaced = true; }
 236      var scrollTop=txtarea.scrollTop;
 237      var myText = (txtarea.value).substring(startPos, endPos);
 238      if(!myText) { myText=sampleText;}
 239      if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
 240        subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
 241      } else {
 242        subst = tagOpen + myText + tagClose;
 243      }
 244      txtarea.value = txtarea.value.substring(0, startPos) + subst +
 245                      txtarea.value.substring(endPos, txtarea.value.length);
 246      txtarea.focus();
 247  
 248      //set new selection
 249      if(replaced){
 250        var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
 251        txtarea.selectionStart=cPos;
 252        txtarea.selectionEnd=cPos;
 253      }else{
 254        txtarea.selectionStart=startPos+tagOpen.length;
 255        txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
 256      }
 257      txtarea.scrollTop=scrollTop;
 258    // All others
 259    } else {
 260      var copy_alertText=alertText;
 261      var re1=new RegExp("\\$1","g");
 262      var re2=new RegExp("\\$2","g");
 263      copy_alertText=copy_alertText.replace(re1,sampleText);
 264      copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);
 265  
 266      if (sampleText) {
 267        text=prompt(copy_alertText);
 268      } else {
 269        text="";
 270      }
 271      if(!text) { text=sampleText;}
 272      text=tagOpen+text+tagClose;
 273      //append to the end
 274      txtarea.value += "\n"+text;
 275  
 276      // in Safari this causes scrolling
 277      if(!is_safari) {
 278        txtarea.focus();
 279      }
 280  
 281    }
 282    // reposition cursor if possible
 283    if (txtarea.createTextRange){
 284      txtarea.caretPos = document.selection.createRange().duplicate();
 285    }
 286  }
 287  
 288  /*
 289   * Insert the given value at the current cursor position
 290   *
 291   * @see http://www.alexking.org/index.php?content=software/javascript/content.php
 292   */
 293  function insertAtCarret(edid,value){
 294    var field = document.getElementById(edid);
 295  
 296    //IE support
 297    if (document.selection) {
 298      field.focus();
 299      sel = document.selection.createRange();
 300      sel.text = value;
 301    //MOZILLA/NETSCAPE support
 302    }else if (field.selectionStart || field.selectionStart == '0') {
 303      var startPos  = field.selectionStart;
 304      var endPos    = field.selectionEnd;
 305      var scrollTop = field.scrollTop;
 306      field.value = field.value.substring(0, startPos) +
 307                    value +
 308                    field.value.substring(endPos, field.value.length);
 309  
 310      field.focus();
 311      var cPos=startPos+(value.length);
 312      field.selectionStart=cPos;
 313      field.selectionEnd=cPos;
 314      field.scrollTop=scrollTop;
 315    } else {
 316      field.value += "\n"+value;
 317    }
 318    // reposition cursor if possible
 319    if (field.createTextRange){
 320      field.caretPos = document.selection.createRange().duplicate();
 321    }
 322  }
 323  
 324  
 325  /**
 326   * global var used for not saved yet warning
 327   */
 328  var textChanged = false;
 329  
 330  /**
 331   * Check for changes before leaving the page
 332   */
 333  function changeCheck(msg){
 334    if(textChanged){
 335      var ok = confirm(msg);
 336      if(ok){
 337          // remove a possibly saved draft using ajax
 338          var dwform = $('dw__editform');
 339          if(dwform){
 340              var params = 'call=draftdel';
 341              params += '&id='+encodeURIComponent(dwform.elements.id.value);
 342  
 343              var sackobj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
 344              sackobj.AjaxFailedAlert = '';
 345              sackobj.encodeURIString = false;
 346              sackobj.runAJAX(params);
 347              // we send this request blind without waiting for
 348              // and handling the returned data
 349          }
 350      }
 351      return ok;
 352    }else{
 353      return true;
 354    }
 355  }
 356  
 357  /**
 358   * Add changeCheck to all Links and Forms (except those with a
 359   * JSnocheck class), add handlers to monitor changes
 360   *
 361   * Sets focus to the editbox as well
 362   */
 363  function initChangeCheck(msg){
 364      if(!document.getElementById){ return false; }
 365      // add change check for links
 366      var links = document.getElementsByTagName('a');
 367      for(var i=0; i < links.length; i++){
 368          if(links[i].className.indexOf('JSnocheck') == -1){
 369              links[i].onclick = function(){
 370                                      var rc = changeCheck(msg);
 371                                      if(window.event) window.event.returnValue = rc;
 372                                      return rc;
 373                                 };
 374              links[i].onkeypress = function(){
 375                                      var rc = changeCheck(msg);
 376                                      if(window.event) window.event.returnValue = rc;
 377                                      return rc;
 378                                 };
 379          }
 380      }
 381      // add change check for forms
 382      var forms = document.forms;
 383      for(i=0; i < forms.length; i++){
 384          if(forms[i].className.indexOf('JSnocheck') == -1){
 385              forms[i].onsubmit = function(){
 386                                      var rc = changeCheck(msg);
 387                                      if(window.event) window.event.returnValue = rc;
 388                                      return rc;
 389                                 };
 390          }
 391      }
 392  
 393      // reset change memory var on submit
 394      var btn_save        = document.getElementById('edbtn__save');
 395      btn_save.onclick    = function(){ textChanged = false; };
 396      btn_save.onkeypress = function(){ textChanged = false; };
 397      var btn_prev        = document.getElementById('edbtn__preview');
 398      btn_prev.onclick    = function(){ textChanged = false; };
 399      btn_prev.onkeypress = function(){ textChanged = false; };
 400  
 401      // add change memory setter
 402      var edit_text   = document.getElementById('wiki__text');
 403      edit_text.onchange = function(){
 404          textChanged = true; //global var
 405          summaryCheck();
 406      };
 407      edit_text.onkeyup  = summaryCheck;
 408      var summary = document.getElementById('edit__summary');
 409      addEvent(summary, 'change', summaryCheck);
 410      addEvent(summary, 'keyup', summaryCheck);
 411  
 412      // set focus
 413      edit_text.focus();
 414  }
 415  
 416  /**
 417   * Checks if a summary was entered - if not the style is changed
 418   *
 419   * @author Andreas Gohr <andi@splitbrain.org>
 420   */
 421  function summaryCheck(){
 422      var sum = document.getElementById('edit__summary');
 423      if(sum.value === ''){
 424          sum.className='missing';
 425      }else{
 426          sum.className='edit';
 427      }
 428  }
 429  
 430  
 431  /**
 432   * Class managing the timer to display a warning on a expiring lock
 433   */
 434  function locktimer_class(){
 435          this.sack     = null;
 436          this.timeout  = 0;
 437          this.timerID  = null;
 438          this.lasttime = null;
 439          this.msg      = '';
 440          this.pageid   = '';
 441  };
 442  var locktimer = new locktimer_class();
 443      locktimer.init = function(timeout,msg,draft){
 444          // init values
 445          locktimer.timeout  = timeout*1000;
 446          locktimer.msg      = msg;
 447          locktimer.draft    = draft;
 448          locktimer.lasttime = new Date();
 449  
 450          if(!$('dw__editform')) return;
 451          locktimer.pageid = $('dw__editform').elements.id.value;
 452          if(!locktimer.pageid) return;
 453  
 454          // init ajax component
 455          locktimer.sack = new sack(DOKU_BASE + 'lib/exe/ajax.php');
 456          locktimer.sack.AjaxFailedAlert = '';
 457          locktimer.sack.encodeURIString = false;
 458          locktimer.sack.onCompletion = locktimer.refreshed;
 459  
 460          // register refresh event
 461          addEvent($('dw__editform').elements.wikitext,'keyup',function(){locktimer.refresh();});
 462  
 463          // start timer
 464          locktimer.reset();
 465      };
 466  
 467      /**
 468       * (Re)start the warning timer
 469       */
 470      locktimer.reset = function(){
 471          locktimer.clear();
 472          locktimer.timerID = window.setTimeout("locktimer.warning()", locktimer.timeout);
 473      };
 474  
 475      /**
 476       * Display the warning about the expiring lock
 477       */
 478      locktimer.warning = function(){
 479          locktimer.clear();
 480          alert(locktimer.msg);
 481      };
 482  
 483      /**
 484       * Remove the current warning timer
 485       */
 486      locktimer.clear = function(){
 487          if(locktimer.timerID !== null){
 488              window.clearTimeout(locktimer.timerID);
 489              locktimer.timerID = null;
 490          }
 491      };
 492  
 493      /**
 494       * Refresh the lock via AJAX
 495       *
 496       * Called on keypresses in the edit area
 497       */
 498      locktimer.refresh = function(){
 499          var now = new Date();
 500          // refresh every minute only
 501          if(now.getTime() - locktimer.lasttime.getTime() > 30*1000){ //FIXME decide on time
 502              var params = 'call=lock&id='+encodeURIComponent(locktimer.pageid);
 503              if(locktimer.draft){
 504                  var dwform = $('dw__editform');
 505                  params += '&prefix='+encodeURIComponent(dwform.elements.prefix.value);
 506                  params += '&wikitext='+encodeURIComponent(dwform.elements.wikitext.value);
 507                  params += '&suffix='+encodeURIComponent(dwform.elements.suffix.value);
 508                  params += '&date='+encodeURIComponent(dwform.elements.date.value);
 509              }
 510              locktimer.sack.runAJAX(params);
 511              locktimer.lasttime = now;
 512          }
 513      };
 514  
 515  
 516      /**
 517       * Callback. Resets the warning timer
 518       */
 519      locktimer.refreshed = function(){
 520          var data  = this.response;
 521          var error = data.charAt(0);
 522              data  = data.substring(1);
 523  
 524          $('draft__status').innerHTML=data;
 525          if(error != '1') return; // locking failed
 526          locktimer.reset();
 527      };
 528  // end of locktimer class functions
 529  


Généré le : Tue Apr 3 20:47:31 2007 par Balluche grâce à PHPXref 0.7