Make WordPress Core


Ignore:
Timestamp:
09/13/2006 09:39:53 PM (20 years ago)
Author:
ryan
Message:

AJAX responsiveness improvements from mdawaffe. fixes #3099

File:
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/list-manipulation-js.php

    r4186 r4187  
    11<?php
    2 require_once('admin.php');
     2@require_once('../../wp-config.php');
    33cache_javascript_headers();
    44$handler =  get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php';
     
    88function dimSomething(what,id,dimClass,obj){if(!obj)obj=theList;return obj.ajaxDimmer(what,id,dimClass);}
    99
    10 function WPAjax(file, responseEl){//class WPAjax extends sack
    11         this.getResponseElement=function(r){var p=document.getElementById(r+'-p');if(!p){p=document.createElement('span');p.id=r+'-p';document.getElementById(r).appendChild(p);}this.myResponseElement=p;      }
    12         this.parseAjaxResponse=function(){
    13                 if(isNaN(this.response)){this.myResponseElement.innerHTML='<div class="error"><p>'+this.response+'</p></div>';return false;}
    14                 this.response=parseInt(this.response,10);
    15                 if(-1==this.response){this.myResponseElement.innerHTML="<div class='error'><p><?php _e("You don't have permission to do that."); ?></p></div>";return false;}
    16                 else if(0==this.response){this.myResponseElement.innerHTML="<div class='error'><p><?php _e("Something odd happened. Try refreshing the page? Either that or what you tried to change never existed in the first place."); ?></p></div>";return false;}
    17                 return true;
     10var listMan = Class.create();
     11Object.extend(listMan.prototype, {
     12        ajaxRespEl: 'ajax-response',
     13        ajaxHandler: '<?php echo $handler; ?>',
     14        inputData: '',
     15        clearInputs: [],
     16        showLink: true,
     17        topAdder: false,
     18        alt: 'alternate',
     19        altOffset: 0,
     20        addComplete: null,
     21        delComplete: null,
     22        dimComplete: null,
     23        dataStore: null,
     24        formStore: null,
     25
     26        initialize: function(theListId) {
     27                this.theList = $(theListId ? theListId : 'the-list');
     28                if ( !this.theList )
     29                        return false;
     30                this.theList.cleanWhitespace();
     31        },
     32
     33        // sends add-what and fields contained in where
     34        // recieves html with top element having an id like what-#
     35        ajaxAdder: function( what, where, update ) { // Do NOT wrap TR in TABLE TBODY
     36                var ajaxAdd = new WPAjax( this.ajaxHandler, this.ajaxRespEl );
     37                if ( ajaxAdd.notInitialized() )
     38                        return true;
     39                ajaxAdd.options.parameters += '&action=' + ( update ? 'update-' : 'add-' ) + what + '&' + this.grabInputs( where, ajaxAdd ) + this.inputData;
     40                var tempObj=this;
     41                ajaxAdd.addOnComplete( function(transport) {
     42                        var newItems = $A(transport.responseXML.getElementsByTagName(what));
     43                        if ( newItems ) {
     44                                newItems.each( function(i) {
     45                                        var id = i.getAttribute('id');
     46                                        var exists = $(what+'-'+id);
     47                                        if ( exists )
     48                                                tempObj.replaceListItem( exists, getNodeValue(i,'response_data'), update );
     49                                        else
     50                                                tempObj.addListItem( getNodeValue(i, 'response_data') );
     51                                        if ( tempObj.showLink )
     52                                                tempObj.showLink = id;
     53                                });
     54                        }
     55                        ajaxAdd.myResponseElement.update(tempObj.showLink ? ( "<div id='jumplink' class='updated fade'><p><a href='#" + what + '-' + tempObj.showLink + "'><?php _e('Jump to new item'); ?></a></p></div>" ) : '');
     56                        if ( tempObj.addComplete && typeof tempObj.addComplete == 'function' )
     57                                tempObj.addComplete( what, where, update, transport );
     58                        tempObj.recolorList();
     59                        ajaxAdd.restoreInputs = null;
     60                });
     61                ajaxAdd.addOnWPError( function(transport) { tempObj.restoreForm(ajaxAdd.restoreInputs); });
     62                ajaxAdd.request(ajaxAdd.url);
     63                this.clear();
     64                return false;
     65        },
     66
     67        // sends update-what and fields contained in where
     68        // recieves html with top element having an id like what-#
     69        ajaxUpdater: function( what, where ) { return this.ajaxAdder( what, where, true ); },
     70
     71        // sends delete-what and id#
     72        ajaxDelete: function( what, id ) {
     73                var ajaxDel = new WPAjax( this.ajaxHandler, this.ajaxRespEl );
     74                if( ajaxDel.notInitialized() )
     75                        return true;
     76                var tempObj = this;
     77                var action = 'delete-' + what + '&id=' + id;
     78                var idName = what.replace('-as-spam','') + '-' + id;
     79                ajaxDel.addOnComplete( function(transport) {
     80                        ajaxDel.myResponseElement.update('');
     81                        tempObj.destore(action);
     82                        if( tempObj.delComplete && typeof tempObj.delComplete == 'function' )
     83                                tempObj.delComplete( what, id, transport );
     84                });
     85                ajaxDel.addOnWPError( function(transport) { tempObj.restore(action, true); });
     86                ajaxDel.options.parameters += '&action=' + action + this.inputData;
     87                ajaxDel.request(ajaxDel.url);
     88                this.store(action, idName);
     89                tempObj.removeListItem( idName );
     90                return false;
     91        },
     92
     93        // Toggles class nomes
     94        // sends dim-what and id#
     95        ajaxDimmer: function( what, id, dimClass ) {
     96                ajaxDim = new WPAjax( this.ajaxHandler, this.ajaxRespEl );
     97                if ( ajaxDim.notInitialized() )
     98                        return true;
     99                var tempObj = this;
     100                var action = 'dim-' + what + '&id=' + id;
     101                var idName = what + '-' + id;
     102                ajaxDim.addOnComplete( function(transport) {
     103                        ajaxDim.myResponseElement.update('');
     104                        tempObj.destore(action);
     105                        if ( tempObj.dimComplete && typeof tempObj.dimComplete == 'function' )
     106                                tempObj.dimComplete( what, id, dimClass, transport );
     107                });
     108                ajaxDim.addOnWPError( function(transport) { tempObj.restore(action, true); });
     109                ajaxDim.options.parameters += '&action=' + action + this.inputData;
     110                ajaxDim.request(ajaxDim.url);
     111                this.store(action, idName);
     112                this.dimItem( idName, dimClass );
     113                return false;
     114        },
     115
     116        addListItem: function( h ) {
     117                new Insertion[this.topAdder ? 'Top' : 'Bottom'](this.theList,h);
     118                this.theList.cleanWhitespace();
     119                var id = this.topAdder ? this.theList.firstChild.id : this.theList.lastChild.id;
     120                if ( this.alt )
     121                        if ( this.theList.childNodes.length % 2 )
     122                                $(id).addClassName(this.alt);
     123                Fat.fade_element(id);
     124        },
     125
     126        // only hides the element sa it can be put back again if necessary
     127        removeListItem: function( id, noFade ) {
     128                id = $(id);
     129                if ( !noFade ) {
     130                        Fat.fade_element(id.id,null,700,'#FF3333');
     131                        var tempObj = this;
     132                        var func = function() { id.hide(); tempObj.recolorList(); }
     133                        setTimeout(func, 705);
     134                } else {
     135                        id.hide();
     136                        this.recolorList();
     137                }
     138        },
     139
     140        replaceListItem: function( id, h, update ) {
     141                id = $(id);
     142                if ( !update ) {
     143                        id.remove();
     144                        this.addListItem( h );
     145                        return;
     146                }
     147                id.replace(h);
     148                Fat.fade_element(id.id);
     149        },
     150
     151        // toggles class
     152        dimItem: function( id, dimClass, noFade ) {
     153                id = $(id);
     154                if ( id.hasClassName(dimClass) ) {
     155                        if ( !noFade )
     156                                Fat.fade_element(id.id,null,700,null);
     157                        id.removeClassName(dimClass);
     158                } else {
     159                        if ( !noFade )
     160                                Fat.fade_element(id.id,null,700,'#FF3333');
     161                        id.addClassName(dimClass);
     162                }
     163        },
     164
     165        // store an element in case we need it later
     166        store: function(action, id) {
     167                if ( !this.dataStore )
     168                        this.dataStore = $H();
     169                this.dataStore[action] = $(id).cloneNode(true);
     170        },
     171
     172        // delete from store
     173        destore: function(action) { delete(this.dataStore[action]); },
     174
     175        // restore element from store into existing (possibly hidden) element of same id
     176        restore: function(action, error) {
     177                var id = this.dataStore[action].id;
     178                this.theList.replaceChild(this.dataStore[action], $(id));
     179                delete(this.dataStore[action]);
     180                if ( error ) {
     181                        func = function() { $(id).setStyle( { 'background-color': '#FF3333' } ); }
     182                        func(); setTimeout(func, 705); // Hit it twice in case it's still fading.
     183                }
     184        },
     185
     186        // Like Form.serialize, but excludes action and sets up clearInputs
     187        grabInputs: function( where, ajaxObj ) {
     188                if ( ajaxObj )
     189                        ajaxObj.restoreInputs = [];
     190                var elements = Form.getElements($(where));
     191                var queryComponents = new Array();
     192                for (var i = 0; i < elements.length; i++) {
     193                        if ( 'action' == elements[i].name )
     194                                continue;
     195                        if ( 'hidden' != elements[i].type && 'submit' != elements[i].type && 'button' != elements[i].type ) {
     196                                this.clearInputs.push(elements[i]);
     197                                if ( ajaxObj )
     198                                        ajaxObj.restoreInputs.push([elements[i], elements[i].value]);
     199                        }
     200                        var queryComponent = Form.Element.serialize(elements[i]);
     201                        if (queryComponent) {
     202                                queryComponents.push(queryComponent);
     203                        }
     204                }
     205                return queryComponents.join('&');
     206        },
     207
     208        // form.reset() can only do whole forms.  This can do subsections.
     209        clear: function() {
     210                this.clearInputs.each( function(i) {
     211                        i = $(i);
     212                        if ( 'textarea' == i.tagName.toLowerCase() )
     213                                i.value = '';
     214                        else
     215                                switch ( i.type.toLowerCase() ) {
     216                                        case 'password': case 'text':
     217                                                i.value = '';
     218                                                break;
     219                                        case 'checkbox': case 'radio':
     220                                                i.checked = false;
     221                                                break;
     222                                        case 'select': case 'select-one':
     223                                                i.selectedIndex = null;
     224                                                break;
     225                                        case 'select-multiple':
     226                                                for (var o = 0; o < i.length; o++) i.options[o].selected = false;
     227                                                break;
     228                                }
     229                });
     230                this.clearInputs = [];
     231        },
     232
     233        restoreForm: function(elements) {
     234                elements.each( function(i) {
     235                        i[0].value = i[1];
     236                });
     237        },
     238
     239        recolorList: function() {
     240                if ( !this.alt )
     241                        return;
     242                var alt = this.alt;
     243                var offset = this.altOffset;
     244                var listItems = $A(this.theList.childNodes).findAll( function(i) { return i.visible() } );
     245                listItems.each( function(i,n) {
     246                        if ( ( n + offset ) % 2 )
     247                                i.removeClassName(alt);
     248                        else
     249                                i.addClassName(alt);
     250                });
    18251        }
    19         this.parseAjaxResponseXML=function(){
    20                 if(this.responseXML&&typeof this.responseXML=='object')return true;
    21                 if(isNaN(this.response)){this.myResponseElement.innerHTML='<div class="error"><p>'+this.response+'</p></div>';return false;}
    22                 var r=parseInt(this.response,10);
    23                 if(-1==r){this.myResponseElement.innerHTML="<div class='error'><p><?php _e("You don't have permission to do that."); ?></p></div>";}
    24                 else if(0==r){this.myResponseElement.innerHTML="<div class='error'><p><?php _e("Invalid Entry."); ?></p></div>";}
    25                 return false;
    26         }
    27         this.init(file,responseEl);
    28 }       WPAjax.prototype=new sack;
    29         WPAjax.prototype.init=function(f,r){
    30                 this.encVar('cookie', document.cookie);
    31                 this.requestFile=f?f:'<?php echo $handler; ?>';this.getResponseElement(r);this.method='POST';
    32         }
    33 
    34 function listMan(theListId){
    35         this.theList=null;this.theListId=theListId;
    36         this.ajaxRespEl=null;this.ajaxHandler='<?php echo $handler; ?>';
    37         this.inputData='';this.clearInputs=new Array();this.showLink=1;
    38         this.topAdder=0;this.alt='alternate';this.recolorPos;this.reg_color='#FFFFFF';this.alt_color='#F1F1F1';
    39         this.addComplete=null;this.delComplete=null;this.dimComplete=null;
    40         var listType;var listItems;
    41         self.aTrap=0;
    42 
    43         this.ajaxAdder=function(what,where,update){//for TR, server must wrap TR in TABLE TBODY. this.makeEl cleans it
    44                 if(self.aTrap)return;self.aTrap=1;setTimeout('aTrap=0',300);
    45                 this.ajaxAdd=new WPAjax(this.ajaxHandler,this.ajaxRespEl?this.ajaxRespEl:'ajax-response');
    46                 if(this.ajaxAdd.failed)return true;
    47                 this.grabInputs(where);
    48                 var tempObj=this;
    49                 this.ajaxAdd.onCompletion=function(){
    50                         if(!this.parseAjaxResponseXML())return;
    51                         var newItems=this.responseXML.getElementsByTagName(what);
    52                         if(tempObj.topAdder)tempObj.recolorPos=0;
    53                         if(newItems){for (c=0;c<newItems.length;c++){
    54                                 var id=getNodeValue(newItems[c],'id');
    55                                 var exists=document.getElementById(what+'-'+id);
    56                                 if(exists)tempObj.replaceListItem(exists.id,getNodeValue(newItems[c],'newitem'),newItems.length,update);
    57                                 else tempObj.addListItem(getNodeValue(newItems[c],'newitem'),newItems.length);
    58                         }}
    59                         tempObj.inputData='';
    60                         if(tempObj.showLink){this.myResponseElement.innerHTML='<div id="jumplink" class="updated fade"><p><a href="#'+what+'-'+id+'"><?php _e('Jump to new item'); ?></a></p></div>';}
    61                         else this.myResponseElement.innerHTML='';
    62                         for(var i=0;i<tempObj.clearInputs.length;i++){try{var theI=document.getElementById(tempObj.clearInputs[i]);if(theI.tagName.match(/select/i))theI.selectedIndex=0;else theI.value='';}catch(e){}}
    63                         if(tempObj.addComplete&&typeof tempObj.addComplete=='function')tempObj.addComplete(what,where,update);
    64                         tempObj.recolorList(tempObj.recolorPos,1000);
    65                 }
    66                 this.ajaxAdd.runAJAX('action='+(update?'update-':'add-')+what+this.inputData);
    67                 return false;
    68         }
    69         this.ajaxUpdater=function(what,where){return this.ajaxAdder(what,where,true);}
    70         this.ajaxDelete=function(what,id){
    71                 if(self.aTrap)return;self.aTrap=1;setTimeout('aTrap=0',300);
    72                 this.ajaxDel=new WPAjax(this.ajaxHandler,this.ajaxRespEl?this.ajaxRespEl:'ajax-response');
    73                 if(this.ajaxDel.failed)return true;
    74                 var tempObj=this;
    75                 this.ajaxDel.onCompletion=function(){if(this.parseAjaxResponse()){tempObj.removeListItem(what.replace('-as-spam','')+'-'+id);this.myResponseElement.innerHTML='';if(tempObj.delComplete&&typeof tempObj.delComplete=='function')tempObj.delComplete(what,id);tempObj.recolorList(tempObj.recolorPos,1000)}};
    76                 this.ajaxDel.runAJAX('action=delete-'+what+'&id='+id);
    77                 return false;
    78         }
    79         this.ajaxDimmer=function(what,id,dimClass){
    80                 if(self.aTrap)return;self.aTrap=1;setTimeout('aTrap=0',300);
    81                 this.ajaxDim=new WPAjax(this.ajaxHandler,this.ajaxRespEl?this.ajaxRespEl:'ajax-response');
    82                 if(this.ajaxDim.failed)return true;
    83                 var tempObj=this;
    84                 this.ajaxDim.onCompletion=function(){if(this.parseAjaxResponse()){tempObj.dimItem(what+'-'+id,dimClass);this.myResponseElement.innerHTML='';if(tempObj.dimComplete&&typeof tempObj.dimComplete=='function')tempObj.dimComplete(what,id,dimClass);}};
    85                 this.ajaxDim.runAJAX('action=dim-'+what+'&id='+id);
    86                 return false;
    87         }
    88         this.makeEl=function(h){var fakeItem=document.createElement('div');fakeItem.innerHTML=h;var r=fakeItem.firstChild;while(r.tagName.match(/(table|tbody)/i)){r=r.firstChild;}return r;}
    89         this.addListItem=function(h,tot){
    90                 newItem=this.makeEl(h);
    91                 if(this.topAdder){var firstItem=this.theList.getElementsByTagName('table'==listType?'tr':'li')[0];listItems.unshift(newItem.id);this.recolorPos++}
    92                 else{listItems.push(newItem.id);this.recolorPos=listItems.length;}
    93                 if(this.alt&&!((tot-this.recolorPos)%2))newItem.className+=' '+this.alt;
    94                 if(firstItem)firstItem.parentNode.insertBefore(newItem,firstItem);
    95                 else this.theList.appendChild(newItem);
    96                 Fat.fade_element(newItem.id);
    97         }
    98         this.removeListItem=function(id,noFade){
    99                 if(!noFade)Fat.fade_element(id,null,700,'#FF3333');
    100                 var theItem=document.getElementById(id);
    101                 if(!noFade){var func=encloseFunc(function(a){a.parentNode.removeChild(a);},theItem);setTimeout(func,705);}
    102                 else{theItem.parentNode.removeChild(theItem);}
    103                 var pos=this.getListPos(id);
    104                 listItems.splice(pos,1);
    105         }
    106         this.replaceListItem=function(id,h,tot,update){
    107                 if(!update){this.removeListItem(id,true);this.addListItem(h,tot);return;}
    108                 var newItem=this.makeEl(h);
    109                 var oldItem=document.getElementById(id);
    110                 var pos=this.getListPos(oldItem.id,1);if(this.alt&&!(pos%2))newItem.className+=' '+this.alt;
    111                 oldItem.parentNode.replaceChild(newItem,oldItem);
    112                 Fat.fade_element(newItem.id);
    113         }
    114         this.dimItem=function(id,dimClass,noFade){
    115                 var theItem=document.getElementById(id);
    116                 if(theItem.className.match(dimClass)){if(!noFade)Fat.fade_element(id,null,700,null);theItem.className=theItem.className.replace(dimClass,'');}
    117                 else{if(!noFade)Fat.fade_element(id,null,700,'#FF3333');theItem.className=theItem.className+' '+dimClass;}
    118         }
    119         this.grabInputs=function(elId){//text,password,hidden,textarea,select
    120                 var theItem=document.getElementById(elId);
    121                 var inputs=new Array();
    122                 inputs.push(theItem.getElementsByTagName('input'),theItem.getElementsByTagName('textarea'),theItem.getElementsByTagName('select'));
    123                 for(var a=0;a<inputs.length;a++){
    124                         for(var i=0;i<inputs[a].length;i++){
    125                                 if('action'==inputs[a][i].name)continue;
    126                                 if('text'==inputs[a][i].type||'password'==inputs[a][i].type||'hidden'==inputs[a][i].type||inputs[a][i].tagName.match(/textarea/i)){
    127                                         this.inputData+='&'+inputs[a][i].name+'='+encodeURIComponent(inputs[a][i].value);if('hidden'!=inputs[a][i].type)this.clearInputs.push(inputs[a][i].id);
    128                                 }else if(inputs[a][i].tagName.match(/select/i)){
    129                                         this.inputData+='&'+inputs[a][i].name+'='+encodeURIComponent(inputs[a][i].options[inputs[a][i].selectedIndex].value);this.clearInputs.push(inputs[a][i].id);
    130                                 }
    131                         }       
    132                 }
    133         }
    134         this.getListPos=function(id,n){for(var i=0;i<listItems.length;i++){if(id==listItems[i]){var pos=i;break;}}if(!n){if(pos<this.recolorPos)this.recolorPos=pos;}return pos;}
    135         this.getListItems=function(){
    136                 if(this.theList)return;
    137                 listItems=new Array();
    138                 if(this.theListId){this.theList=document.getElementById(this.theListId);if(!this.theList)return false;}
    139                 else{this.theList=document.getElementById('the-list');if(this.theList)this.theListId='the-list';}
    140                 if(this.theList){
    141                         var items=this.theList.getElementsByTagName('tr');listType='table';
    142                         if(!items[0]){items=this.theList.getElementsByTagName('li');listType='list';}
    143                         for(var i=0;i<items.length;i++){listItems.push(items[i].id);}
    144                         this.recolorPos=listItems.length;
    145                 }
    146         }
    147         this.recolorList=function(pos,dur){
    148                 if(!this.alt)return;if(!pos)pos=0;this.recolorPos=listItems.length;
    149                 for(var i=pos;i<listItems.length;i++){var e=document.getElementById(listItems[i]);if(i%2)e.className=e.className.replace(this.alt,'fade-'+this.alt_color.slice(1));else e.className+=' '+this.alt+' fade-'+this.reg_color.slice(1);e.style.backgroundColor='';}
    150                 Fat.fade_all(dur);
    151                 var func=encloseFunc(function(l){for(var i=0;i<l.length;i++){var e=document.getElementById(l[i]);e.className=e.className.replace(/fade-[a-f0-9]{6}/i,'');}},listItems);
    152                 setTimeout(func,dur+5);
    153         }
    154         this.getListItems();
    155 }
     252});
     253
    156254//No submit unless code returns true.
    157255function killSubmit ( code, e ) {
     
    160258        var t = e.target ? e.target : e.srcElement;
    161259        if ( ( 'text' == t.type && e.keyCode == 13 ) || ( 'submit' == t.type && 'click' == e.type ) ) {
    162                 if ( ( 'string' == typeof code && !eval(code) ) || 'function' == typeof code && !code() ) {
    163                         if ( !eval(code) ) { e.returnValue = false; e.cancelBubble = true; return false; }
     260                if ( ( 'string' == typeof code && !eval(code) ) || ( 'function' == typeof code && !code() ) ) {
     261                        e.returnValue = false; e.cancelBubble = true; return false;
    164262                }
    165263        }
Note: See TracChangeset for help on using the changeset viewer.