Streber PM PHP Cross Reference Groupware Applications

Source: /js/jquery.jeditable.1.5.x.js - 460 lines - 19789 bytes - Text - Print

Description: Version 1.5.x

   1  /*
   2   * Jeditable - jQuery in place edit plugin
   3   *
   4   * Copyright (c) 2006-2008 Mika Tuupola, Dylan Verheul
   5   *
   6   * Licensed under the MIT license:
   7   *   http://www.opensource.org/licenses/mit-license.php
   8   *
   9   * Project home:
  10   *   http://www.appelsiini.net/projects/jeditable
  11   *
  12   * Based on editable by Dylan Verheul <dylan_at_dyve.net>:
  13   *    http://www.dyve.net/jquery/?editable
  14   *
  15   * Revision: $Id: jquery.jeditable.js 372 2008-05-22 19:25:32Z tuupola $
  16   *
  17   */
  18  
  19  /**
  20    * Version 1.5.x
  21    *
  22    * @name  Jeditable
  23    * @type  jQuery
  24    * @param String  target             POST URL or function name to send edited content
  25    * @param Hash    options            additional options 
  26    * @param Function options[callback] Function to run after submitting edited content
  27    * @param String  options[name]      POST parameter name of edited content
  28    * @param String  options[id]        POST parameter name of edited div id
  29    * @param Hash    options[submitdata] Extra parameters to send when submitting edited content.
  30    * @param String  options[type]      text, textarea or select
  31    * @param Integer options[rows]      number of rows if using textarea
  32    * @param Integer options[cols]      number of columns if using textarea
  33    * @param Mixed   options[height]    'auto', 'none' or height in pixels
  34    * @param Mixed   options[width]     'auto', 'none' or width in pixels 
  35    * @param String  options[loadurl]   URL to fetch input content before editing
  36    * @param String  options[loadtype]  Request type for load url. Should be GET or POST.
  37    * @param String  options[loadtext]  Text to display while loading external content.
  38    * @param Hash    options[loaddata]  Extra parameters to pass when fetching content before editing.
  39    * @param String  options[data]      Or content given as paramameter.
  40    * @param String  options[indicator] indicator html to show when saving
  41    * @param String  options[tooltip]   optional tooltip text via title attribute
  42    * @param String  options[event]     jQuery event such as 'click' of 'dblclick'
  43    * @param String  options[onblur]    'cancel', 'submit', 'ignore' or function
  44    * @param String  options[submit]    submit button value, empty means no button
  45    * @param String  options[cancel]    cancel button value, empty means no button
  46    * @param String  options[cssclass]  CSS class to apply to input form. 'inherit' to copy from parent.
  47    * @param String  options[style]     Style to apply to input form 'inherit' to copy from parent.
  48    * @param String  options[select]    true or false, when true text is highlighted
  49    * @param String  options[placeholder] Placeholder text or html to insert when element is empty.
  50    *             
  51    */
  52  
  53  (function($) {
  54  
  55      $.fn.editable = function(target, options) {
  56      
  57          var settings = {
  58              target     : target,
  59              name       : 'value',
  60              id         : 'id',
  61              type       : 'text',
  62              width      : 'auto',
  63              height     : 'auto',
  64              event      : 'click',
  65              onblur     : 'cancel',
  66              loadtype   : 'GET',
  67              loadtext   : 'Loading...',
  68              placeholder: 'Click to edit',
  69              loaddata   : {},
  70              submitdata : {}
  71          };
  72          
  73          if(options) {
  74              $.extend(settings, options);
  75          }
  76      
  77          /* setup some functions */
  78          var plugin   = $.editable.types[settings.type].plugin || function() { };
  79          var submit   = $.editable.types[settings.type].submit || function() { };
  80          var buttons  = $.editable.types[settings.type].buttons 
  81                      || $.editable.types['defaults'].buttons;
  82          var content  = $.editable.types[settings.type].content 
  83                      || $.editable.types['defaults'].content;
  84          var element  = $.editable.types[settings.type].element 
  85                      || $.editable.types['defaults'].element;
  86          var reset    = $.editable.types[settings.type].reset 
  87                      || $.editable.types['defaults'].reset;
  88          var callback = settings.callback || function() { };
  89          
  90          /* add custom event if it does not exist */
  91          if  (!$.isFunction($(this)[settings.event])) {
  92              $.fn[settings.event] = function(fn){
  93                    return fn ? this.bind(settings.event, fn) : this.trigger(settings.event);
  94                }
  95          }
  96            
  97          /* TODO: remove this when form is displayed */
  98          $(this).attr('title', settings.tooltip);
  99          
 100          settings.autowidth  = 'auto' == settings.width;
 101          settings.autoheight = 'auto' == settings.height;
 102  
 103          return this.each(function() {
 104  
 105              /* save this to self because this changes when scope changes */
 106              var self = this;  
 107                     
 108              /* inlined block elements lose their width and height after first edit */
 109              /* save them for later use as workaround */
 110              var savedwidth  = $(self).width();
 111              var savedheight = $(self).height();
 112              
 113              /* if element is empty add something clickable (if requested) */
 114              if (!$.trim($(this).html())) {
 115                  $(this).html(settings.placeholder);
 116              }
 117              
 118              $(this)[settings.event](function(e) {
 119  
 120                  /* prevent throwing an exeption if edit field is clicked again */
 121                  if (self.editing) {
 122                      return;
 123                  }
 124  
 125                  /* figure out how wide and tall we are, saved width and height */
 126                  /* are workaround for http://dev.jquery.com/ticket/2190 */
 127                  if (0 == $(self).width()) {
 128                      //$(self).css('visibility', 'hidden');
 129                      settings.width  = savedwidth;
 130                      settings.height = savedheight;
 131                  } else {
 132                      if (settings.width != 'none') {
 133                          settings.width = 
 134                              settings.autowidth ? $(self).width()  : settings.width;
 135                      }
 136                      if (settings.height != 'none') {
 137                          /*
 138                          * pixtur: added min size page
 139                          */
 140                          if ($(self).height() < 100) {
 141                              settings.height = 100;
 142                          }
 143                          else {
 144                              settings.height = 
 145                                  settings.autoheight ? $(self).height() : settings.height;
 146                          }
 147                      }
 148                  }
 149                  //$(this).css('visibility', '');
 150                  
 151                  /* remove placeholder text, replace is here because of IE */
 152                  if ($(this).html().toLowerCase().replace(/;/, '') == 
 153                      settings.placeholder.toLowerCase().replace(/;/, '')) {
 154                          $(this).html('');
 155                  }
 156                                  
 157                  self.editing    = true;
 158                  self.revert     = $(self).html();
 159                  $(self).html('');
 160  
 161                  /* create the form object */
 162                  var form = $('<form/>');
 163                  
 164                  /* apply css or style or both */
 165                  if (settings.cssclass) {
 166                      if ('inherit' == settings.cssclass) {
 167                          form.attr('class', $(self).attr('class'));
 168                      } else {
 169                          form.attr('class', settings.cssclass);
 170                      }
 171                  }
 172  
 173                  if (settings.style) {
 174                      if ('inherit' == settings.style) {
 175                          form.attr('style', $(self).attr('style'));
 176                          /* IE needs the second line or display wont be inherited */
 177                          form.css('display', $(self).css('display'));                
 178                      } else {
 179                          form.attr('style', settings.style);
 180                      }
 181                  }
 182  
 183                  /* add main input element to form and store it in input */
 184                  var input = element.apply(form, [settings, self]);
 185  
 186                  /* set input content via POST, GET, given data or existing value */
 187                  var input_content;
 188                  
 189                  if (settings.loadurl) {
 190                      var t = setTimeout(function() {
 191                          input.disabled = true;
 192                          content.apply(form, [settings.loadtext, settings, self]);
 193                      }, 100);
 194  
 195                      var loaddata = {};
 196                      loaddata[settings.id] = self.id;
 197                      if ($.isFunction(settings.loaddata)) {
 198                          $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
 199                      } else {
 200                          $.extend(loaddata, settings.loaddata);
 201                      }
 202                      $.ajax({
 203                         type : settings.loadtype,
 204                         url  : settings.loadurl,
 205                         data : loaddata,
 206                         async : false,
 207                         success: function(result) {
 208                               window.clearTimeout(t);
 209                               input_content = result;
 210                            input.disabled = false;
 211                         }
 212                      });
 213                  } else if (settings.data) {
 214                      input_content = settings.data;
 215                      if ($.isFunction(settings.data)) {
 216                          input_content = settings.data.apply(self, [self.revert, settings]);
 217                      }
 218                  } else {
 219                      input_content = self.revert; 
 220                  }
 221                  content.apply(form, [input_content, settings, self]);
 222  
 223                  input.attr('name', settings.name);
 224          
 225                  /* add buttons to the form */
 226                  buttons.apply(form, [settings, self]);
 227           
 228                  /* add created form to self */
 229                  $(self).append(form);
 230           
 231                  /* attach 3rd party plugin if requested */
 232                  plugin.apply(form, [settings, self]);
 233  
 234                  /* focus to first visible form element */
 235                  $(':input:visible:enabled:first', form).focus();
 236  
 237                  /* highlight input contents when requested */
 238                  if (settings.select) {
 239                      input.select();
 240                  }
 241          
 242                  /* discard changes if pressing esc */
 243                  input.keydown(function(e) {
 244                      if (e.keyCode == 27) {
 245                          e.preventDefault();
 246                          //self.reset();
 247                          reset.apply(form, [settings, self]);
 248                      }
 249                  });
 250  
 251                  /* discard, submit or nothing with changes when clicking outside */
 252                  /* do nothing is usable when navigating with tab */
 253                  var t;
 254                  if ('cancel' == settings.onblur) {
 255                      input.blur(function(e) {
 256                          //t = setTimeout(self.reset, 500);
 257                          t = setTimeout(function() {
 258                              reset.apply(form, [settings, self]);
 259                          }, 500);
 260                      });
 261                  } else if ('submit' == settings.onblur) {
 262                      input.blur(function(e) {
 263                          form.submit();
 264                      });
 265                  } else if ($.isFunction(settings.onblur)) {
 266                      input.blur(function(e) {
 267                          settings.onblur.apply(self, [input.val(), settings]);
 268                      });
 269                  } else {
 270                      input.blur(function(e) {
 271                        /* TODO: maybe something here */
 272                      });
 273                  }
 274  
 275                  form.submit(function(e) {
 276  
 277                      if (t) { 
 278                          clearTimeout(t);
 279                      }
 280  
 281                      /* do no submit */
 282                      e.preventDefault(); 
 283              
 284                      /* call before submit hook. if it returns false abort submitting */
 285                      if (false !== submit.apply(form, [settings, self])) { 
 286                        
 287                        /* check if given target is function */
 288                        if ($.isFunction(settings.target)) {
 289                            var str = settings.target.apply(self, [input.val(), settings]);
 290                            $(self).html(str);
 291                            self.editing = false;
 292                            callback.apply(self, [self.innerHTML, settings]);
 293                            /* TODO: this is not dry */                              
 294                            if (!$.trim($(self).html())) {
 295                                $(self).html(settings.placeholder);
 296                            }
 297                        } else {
 298                            /* add edited content and id of edited element to POST */
 299                            var submitdata = {};
 300                            submitdata[settings.name] = input.val();
 301                            submitdata[settings.id] = self.id;
 302                            /* add extra data to be POST:ed */
 303                            if ($.isFunction(settings.submitdata)) {
 304                                $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
 305                            } else {
 306                                $.extend(submitdata, settings.submitdata);
 307                            }          
 308  
 309                            /* show the saving indicator */
 310                            $(self).html(settings.indicator);
 311                            $.post(settings.target, submitdata, function(str) {
 312                                $(self).html(str);
 313                                self.editing = false;
 314                                callback.apply(self, [self.innerHTML, settings]);
 315                                /* TODO: this is not dry */                              
 316                                if (!$.trim($(self).html())) {
 317                                    $(self).html(settings.placeholder);
 318                                }
 319                            });
 320                        }
 321                        
 322                      }
 323                       
 324                      return false;
 325                  });
 326              });
 327              
 328              /* privileged methods */
 329              this.reset = function() {
 330                  $(self).html(self.revert);
 331                  self.editing   = false;
 332                  if (!$.trim($(self).html())) {
 333                      $(self).html(settings.placeholder);
 334                  }
 335              }            
 336          });
 337  
 338      };
 339  
 340  
 341      $.editable = {
 342          types: {
 343              defaults: {
 344                  element : function(settings, original) {
 345                      var input = $('<input type="hidden">');                
 346                      $(this).append(input);
 347                      return(input);
 348                  },
 349                  content : function(string, settings, original) {
 350                      $(':input:first', this).val(string);
 351                  },
 352                  reset : function(settings, original) {
 353                    original.reset();
 354                  },
 355                  buttons : function(settings, original) {
 356                      var form = this;
 357                      if (settings.submit) {
 358                          /* if given html string use that */
 359                          if (settings.submit.match(/>$/)) {
 360                              var submit = $(settings.submit).click(function() {
 361                                  form.submit();
 362                              });
 363                          /* otherwise use button with given string as text */
 364                          } else {
 365                              var submit = $('<button type="submit">');
 366                              submit.html(settings.submit);                            
 367                          }
 368                          $(this).append(submit);
 369                      }
 370                      if (settings.cancel) {
 371                          /* if given html string use that */
 372                          if (settings.cancel.match(/>$/)) {
 373                              var cancel = $(settings.cancel);
 374                          /* otherwise use button with given string as text */
 375                          } else {
 376                              var cancel = $('<button type="cancel">');
 377                              cancel.html(settings.cancel);
 378                          }
 379                          $(this).append(cancel);
 380  
 381                          $(cancel).click(function(event) {
 382                              //original.reset();
 383                              if ($.isFunction($.editable.types[settings.type].reset)) {
 384                                  var reset = $.editable.types[settings.type].reset;                                                                
 385                              } else {
 386                                  var reset = $.editable.types['defaults'].reset;                                
 387                              }
 388                              reset.apply(form, [settings, original]);
 389                              return false;
 390                          });
 391                      }
 392                  }
 393              },
 394              text: {
 395                  element : function(settings, original) {
 396                      var input = $('<input>');
 397                      if (settings.width  != 'none') { input.width(settings.width);  }
 398                      if (settings.height != 'none') { input.height(settings.height); }
 399                      /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
 400                      //input[0].setAttribute('autocomplete','off');
 401                      input.attr('autocomplete','off');
 402                      $(this).append(input);
 403                      return(input);
 404                  }
 405              },
 406              textarea: {
 407                  element : function(settings, original) {
 408                      var textarea = $('<textarea>');
 409                      if (settings.rows) {
 410                          textarea.attr('rows', settings.rows);
 411                      } else {
 412                          textarea.height(settings.height);
 413                      }
 414                      if (settings.cols) {
 415                          textarea.attr('cols', settings.cols);
 416                      } else {
 417                          textarea.width(settings.width);
 418                      }
 419                      $(this).append(textarea);
 420                      return(textarea);
 421                  }
 422              },
 423              select: {
 424                  element : function(settings, original) {
 425                      var select = $('<select>');
 426                      $(this).append(select);
 427                      return(select);
 428                  },
 429                  content : function(string, settings, original) {
 430                      if (String == string.constructor) {      
 431                          eval ('var json = ' + string);
 432                          for (var key in json) {
 433                              if (!json.hasOwnProperty(key)) {
 434                                  continue;
 435                              }
 436                              if ('selected' == key) {
 437                                  continue;
 438                              } 
 439                              var option = $('<option>').val(key).append(json[key]);
 440                              $('select', this).append(option);      
 441                          }
 442                      }
 443                      /* Loop option again to set selected. IE needed this... */ 
 444                      $('select', this).children().each(function() {
 445                          if ($(this).val() == json['selected'] || 
 446                              $(this).text() == original.revert) {
 447                                  $(this).attr('selected', 'selected');
 448                          };
 449                      });
 450                  }
 451              }
 452          },
 453  
 454          /* Add new input type */
 455          addInputType: function(name, input) {
 456              $.editable.types[name] = input;
 457          }
 458      };
 459  
 460  })(jQuery);

title

Description

title

Description

title

Description

title

title

Body