Jump to content

User:John Vandenberg/delsort.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// [[Wikipedia:WikiProject Deletion sorting]] <pre><nowiki>
// This is a development version of [[Wikipedia:WikiProject Deletion sorting/delsort.js]]

if( typeof( DelsortConfig ) == 'undefined' ) {
    DelsortConfig = function() {};
}

DelsortConfig.compactPage = 'Wikipedia:WikiProject_Deletion_sorting/Compact';

var Delsort = function() {};

// Used to emulate CSS columns in Opera
function add_opera_delsort_compact_css() {

   if ( wgNamespaceNumber == 4 && wgPageName == DelsortConfig.compactPage ) {
        if( navigator.userAgent.indexOf("Opera") != -1 ) {
           importStylesheet('Wikipedia:WikiProject Deletion sorting/compact opera.css');
       }
   }
}



// adds 'delsort' tab to p-cactions
function add_delsort_tab() 
{
    if ( DelsortConfig['debugLevel'] > 0 ) {
        Delsort.displayPopup( '', "Setting up buttons.." );
        Status.init( window['delsortWindow'].content );
        Delsort.debug ('Adding delsort button ...');
    }
 
    var tabs = document.getElementById('p-cactions').getElementsByTagName('ul')[0];

    var ul = addlimenu(tabs, 'delsort', 'delsort');

    if ( DelsortConfig['debugLevel'] > 0 ) Delsort.debug ('ul = ' + ul.tagName);

    var menuitem = ul.previousSibling;

    menuitem.setAttribute('href','javascript:showDelsortFrame()');

    // when the user is in edit mode, save a reference to it
    Delsort.afdForm = document.getElementById( 'editform' );

    // support deprecated shortcut list
    if ( window['delsortPages'] )
        DelsortConfig.shortcuts = window['delsortPages'];

    // add each shortcut
    if ( DelsortConfig['shortcuts'] && 
         DelsortConfig['shortcuts']['length'] ) {

        for (i = 0; i < DelsortConfig.shortcuts.length; i++) {
            if ( DelsortConfig['debugLevel'] > 0 ) Delsort.debug ('adding shortcut "' + 
                                                                  DelsortConfig.shortcuts[i] + '"');

            mw.util.addPortletLink('delsort',
                           'javascript:delsortArticle("' + DelsortConfig.shortcuts[i] + '")',
                           DelsortConfig.shortcuts[i],
                           '');
        }
    }

    if ( DelsortConfig['debugLevel'] > 0 ) {
        Delsort.debug ('done');
    }
}

Delsort.add_inline_ui = function() {
    if ( DelsortConfig['debugLevel'] > 0 ) {
        Delsort.displayPopup( '', "Setting up inline delsort buttons.." );
        Status.init( window['delsortWindow'].content );
        Delsort.debug ('Adding delsort to ...');
    }

    var spans = document.getElementsByTagName('SPAN');
    for (i = 0; i < spans.length; i++) {
        if (spans[i].className == 'editsection') {
            // spans[i] is a section, which is usually the start of a transclude.
            // It could be a section within the transcluded page
            var sectionEditAnchor = spans[i].getElementsByTagName('A');
            if ( sectionEditAnchor ) sectionEditAnchor = sectionEditAnchor[0];
            Delsort.debug ('-- Found section "' + sectionEditAnchor.title + '"');
            if ( sectionEditAnchor && /Wikipedia:Articles for deletion/.exec ( sectionEditAnchor.title ) ) {
                window['wgAfdPage'] = sectionEditAnchor.title;
                Delsort.debug ('Looking for more signs that "' + sectionEditAnchor.title + '" is an Afd...');
            }
            else {
                window['wgAfdPage'] = '';
            }
        }
        if (window['wgAfdPage'] && spans[i].className == 'mw-headline') {

            // span[i] is the beginning of the transcluded Afd content
            if ( window['wgAfdPage'].indexOf ( spans[i].textContent ) > -1 ) {
                window['wgNominatedArticle'] = spans[i].textContent;

                Delsort.debug (' ' + window['wgAfdPage'] + ': ' + window['wgNominatedArticle']);

                parentNode = spans[i].parentNode;
                var laNode = null;
                // try looking for {{la|...}} directly after
                if (parentNode.nextSibling.nodeValue == '\n' &&
                             parentNode.nextSibling.nextSibling.tagName == 'DL' ) {
                    // looks like we have found {{la|...}}
                    laNode = parentNode.nextSibling.nextSibling;
                }
                // try looking for {{la|...}} by skipping a "AfDs for this article" DIV
                if (parentNode.nextSibling.nodeValue == '\n' &&
                             parentNode.nextSibling.nextSibling.tagName == 'DIV' &&
                             parentNode.nextSibling.nextSibling.nextSibling.nodeValue == '\n' &&
                             parentNode.nextSibling.nextSibling.nextSibling.nextSibling.tagName == 'DL' ) {
                    // looks like we have found {{la|...}}
                    laNode = parentNode.nextSibling.nextSibling.nextSibling.nextSibling;
                }
                if (laNode) {
                    if (laNode.childNodes[1].tagName == 'DD') {
                        var viewAfdNode = laNode.childNodes[1].lastChild.previousSibling;
                      if (viewAfdNode) {
                       if (viewAfdNode.textContent == 'View AfD' &&
                           viewAfdNode.previousSibling) {
                        viewAfdNode.previousSibling.nodeValue = ' — (Afd: ';
                        viewAfdNode.firstChild.nodeValue = 'View';
                        var delsortAfdNode = viewAfdNode.cloneNode(true);
                        delsortAfdNode.firstChild.nodeValue = 'Delsort';
                        delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
                        delsortAfdNode = viewAfdNode.parentNode.insertBefore( delsortAfdNode, viewAfdNode.parentNode.lastChild );
                        viewAfdNode.parentNode.insertBefore(  document.createTextNode ( ' | ' ), delsortAfdNode );
                       }
                       else {
                        var delsortAfdNode = document.createElement('A');
                        delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
                        delsortAfdNode.innerHTML = 'Delsort';
                        laNode.appendChild ( document.createTextNode ( ' - ' ) );
                        laNode.appendChild ( delsortAfdNode );
                       }
                      }
                    }
                }
                else {
//                    Delsort.debug ('Skipping nomination "' + window['wgAfdPage'] + '"; expected preamble not present.');
                    var delsortAfdNode = document.createElement('A');
                    delsortAfdNode.setAttribute('href', 'javascript:showDelsortFrame("' + wgAfdPage + '")');
                    delsortAfdNode.innerHTML = 'Delsort';
                    parentNode.parentNode.insertBefore ( document.createTextNode ( ' - ' ), parentNode.nextSibling );
                    parentNode.parentNode.insertBefore ( delsortAfdNode , parentNode.nextSibling );
                }
            }
            else {
                Delsort.debug ('Skipping headline "' + spans[i].textContent + '"');
            }
        }
    }
}

Delsort.status = function( text ) {
    return new Status( text, 'Status', 'status' );
}
Delsort.info = function( text ) {
    return new Status( text, 'Info', 'info' );
}
Delsort.warn = function( text ) {
    return new Status( text, 'Warning', 'error' );
}
Delsort.error = function( text ) {
    return new Status( text, 'Error', 'error' );
}
Delsort.progress = function( text ) {
    // disable the "....." until I can work out how to
    // achieve that again using the new TW framework
    if ( text == '.' ) return;
    return new Status( text, 'Progress', 'info' );
}
Delsort.debug = function( text ) {
    if ( DelsortConfig['debugLevel'] > 0 ) {
        return new Status( text, 'Debug', 'info' );
    }
}

Delsort.init = function() {
    add_opera_delsort_compact_css();

    if ( typeof DelsortConfig.transcludeRE == 'undefined' )
        DelsortConfig.transcludeRE = new RegExp('Wikipedia:Deletion today|Wikipedia:Articles for deletion\/Log\/');

    if ( typeof ( WikiPage ) == 'function' ) {
        // create wgWikiPage for the current page if it doesnt already exist
        if (! window['wgWikiPage'] )
            wgWikiPage = new WikiPage(null,wgPageName);

        if ( DelsortConfig.transcludeRE.test ( wgWikiPage.page ) )
            Delsort.add_inline_ui();

        if ( wgWikiPage.superarticle == 'Articles for deletion' &&
             wgWikiPage.subarticle.substr(0,3) != 'Log' ) {
            window['wgAfdPage'] = wgPageName;
            add_delsort_tab();
        }

        return;
    }

    if ( wgNamespaceNumber == 4 ) {
        var subTitleRE = /^([^/]+)\/(.+)/;

        if ( subTitleRE.exec ( wgTitle ) ) {
            window['wgDirname'] = RegExp.$1;
            window['wgSubTitle'] = RegExp.$2;
        }
        if (!window['wgDirname'] || !window['wgSubTitle'] || wgDirname != 'Articles for deletion') return;

        window['wgAfdPage'] = wgPageName;
        add_delsort_tab();
    }
}
    
$(Delsort.init);


function showDelsortFrame(pAfdPage) {
    if (pAfdPage)
        window['wgAfdPage'] = pAfdPage;

    // The frame contents are cached
    if ( Delsort['PopupContents'] )
        Delsort.displayPopup( Delsort.PopupContents, "Select deletion sorting criteria" );
    else
        Delsort.loadFrameContents();
}

Delsort.loadFrameContents = function () {
    try {
        delsortCompatList = sajax_init_object();
        delsortCompatList.overrideMimeType('text/xml');

        var query = {
            'title': DelsortConfig.compactPage
        };

        delsortCompatList.onreadystatechange = showDelsortFrameCallback;

        delsortCompatList.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
        delsortCompatList.send( null );
    } catch(e) {
        if( e instanceof Exception ) {
            Delsort.error( 'Error: ' + e.what() );
        } else {
            Delsort.error( 'Error: ' + e );
        }
    }
}

function showDelsortFrameCallback() {
    if ( delsortCompatList.readyState != 4 ){
        return;
    }

    if( delsortCompatList.status != 200 ){
        Delsort.error('Bad status , bailing out; status = ' + delsortCompatList.status );
        return;
    }

    var doc = delsortCompatList.responseXML;

    var list = doc.getElementById('bodyContent').cloneNode(true);

    if(! list ) {
        Delsort.error( 'Unable to get the list, aborting.');
        return;
    }

    var currentNode = list.firstChild;
    var node;

    // remove the heading
    do {
       node = currentNode;
       currentNode = node.nextSibling;

       list.removeChild ( node );
    } while (node.id != 'toc');

    // remove the edit links
    var spans = list.getElementsByTagName('span');
    var i = 0;
    for (i = 0; i < spans.length; i++) {
        if (spans[i].className == 'editsection') {
            spans[i].parentNode.removeChild ( spans[i] );
        }
    }

    var delsortLinkRE = new RegExp ('\/wiki\/Wikipedia:WikiProject_Deletion_sorting\/(.*)');

    // remove the edit links
    var anchors = list.getElementsByTagName('a');
    var i = 0;
    for (i = 0; i < anchors.length; i++) {
        if ( anchors[i].href && delsortLinkRE.exec(anchors[i].href) ) {
            pType = RegExp.$1;
            pType = pType.replace(/_/g,' ');

           if( navigator.userAgent.indexOf("Opera") != -1 ) {
            anchors[i].href = "#";
            anchors[i].onclick = new Function("delsortArticle('" + pType  + "')");
           }
           else {
               anchors[i].href = "javascript:delsortArticle('" + pType  + "')";
           }
        }
    }

    Delsort.PopupContents = list;
    
    Delsort.displayPopup( list, "Select deletion sorting criteria" );
}

Delsort.displayPopup = function(pContent, pTitle) {
    if ( DelsortConfig['debugLevel'] > 0 )
       Status.debugLevel = DelsortConfig.debugLevel;

    if (!window['delsortWindow']) {
        delsortWindow = new SimpleWindow( 800, 400 );
    }

    if (pTitle)
        delsortWindow.setTitle( pTitle )

    if (pContent)
        delsortWindow.setContent( pContent );

    delsortWindow.display();
}

function delsortArticle( pType ) {
    pType = unescape(pType);

    window['twDelsortType'] = pType;

    wgAfdPage = unescape(wgAfdPage).replace('_',' ','g');

    Delsort.displayPopup ( null, "Performing deletion sorting" );
    Status.init( window['delsortWindow'].content );

    var subpageRE = new RegExp('Wikipedia:Articles for deletion\/(.*)');
    if ( subpageRE.exec( wgAfdPage ) ) {
        wgNominatedArticle = RegExp.$1;
    }
    else {
        Delsort.error( 'Can not determine article name for "' + wgAfdPage  + '", aborting');
        return;
    }

    var additionalNominationRE = new RegExp(' ([(]([0-9]+..|[a-z]+) [Nn]omination[)])');
    var pRegexResults = additionalNominationRE.exec( wgNominatedArticle );

    wgNominationIndex = '';
    if ( pRegexResults  ) {
        wgNominationIndex = pRegexResults[1];
        wgNominatedArticle = wgNominatedArticle.substr(0, pRegexResults.index);
    }

    Delsort.status( 'Nominated article name: ' + wgNominatedArticle );
    if (wgNominationIndex)
       Delsort.status( 'Nomination index: ' + wgNominationIndex );

    // check the article exists
    try {
        delsortXML = sajax_init_object();
        Delsort.debug( 'delsortXML' + delsortXML );
        delsortXML.overrideMimeType('text/xml');

        var query = {
            'action': 'query',
            'titles': wgNominatedArticle,
            'prop': 'info',
            'format': 'xml'
        };

        Delsort.status( 'Check the article "' + wgNominatedArticle + '" exists ...');

        delsortXML.onreadystatechange = Delsort.verifyArticleExistsCallback;

        if (typeof (query.toSource) == 'undefined') {
            Delsort.debug( 'query:' + query );
        }
        else {
            Delsort.debug( 'query:' + query.toSource() );
        }

        var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?' + QueryString.create( query );
        Delsort.debug( 'url:' + url );
        delsortXML.open( 'GET' , url, true );
        delsortXML.send( null );
    } catch(e) {
        if( e instanceof Exception ) {
            Delsort.error( 'Error: ' + e.what() );
        } else {
            Delsort.error( 'Error: ' + e );
        }
    }
}


Delsort.verifyArticleExistsCallback = function() {
    var doc = Delsort.getAJAXResponse();

    if (typeof doc != 'object') return;

    Delsort.debug( ' Article test responseXML = ' + delsortXML.responseText );

    var pageNode = doc.getElementsByTagName('page');
    if (!pageNode || !pageNode[0] || !pageNode[0].getAttribute('lastrevid')) {
        Delsort.status( 'Article not found' );
        return;
    }

    Delsort.status( ' OK ' );

	try {

		delsortXML = sajax_init_object();
		Delsort.debug( 'delsortXML' + delsortXML );
		delsortXML.overrideMimeType('text/xml');

		var query = {
			'action': 'submit',
			'title': 'Wikipedia:WikiProject Deletion sorting/' + window['twDelsortType'],
			'section': 1
		};

		Delsort.status( 'Grabbing edit form for ' + query.title);

		delsortXML.onreadystatechange = delsortCallback;

		Delsort.debug( 'query:' + query.toSource() );

		delsortXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
		delsortXML.send( null );
	} catch(e) {
		if( e instanceof Exception ) {
			Delsort.error( 'Error: ' + e.what() );
		} else {
			Delsort.error( 'Error: ' + e );
		}
	}
}

function delsortCallback() {
    var delsortForm = Delsort.getAJAXEditForm();

    if (typeof delsortForm != 'object') return;

        var doc = delsortForm.ownerDocument;
        var textbox = doc.getElementById( 'wpTextbox1' );

        Delsort.status( 'Checking contents of ' + window['twDelsortType'] + ' list');
        Delsort.debug( 'Looking for ' + wgNominatedArticle + ' in ' + textbox.value);

        if ( (textbox.value.indexOf( wgNominatedArticle + '}}' ) != -1) ||
             (textbox.value.indexOf( wgNominatedArticle.replace(/ /g,'_') + '}}' ) != -1) )
        {
            Delsort.error( wgNominatedArticle + ' already listed on ' + window['twDelsortType']);
            return;
        }

        Delsort.progress( ': ok' );

    // remove (U.S. State) and (country) after Georgia
    var sectionHeaderTitle = window['twDelsortType'].replace(/ [(].*[)]/,'');

    var sectionHeaderRE = new RegExp('(==+ *(.*[^=\n]*) *==+)\n(\n*<[^>]*>)*(\n)*');

    if ( ! sectionHeaderRE.test( textbox.value ) ) {
        Delsort.error( 'Unable to locate where to place the new listing; aborting.' );
        return;
    }

    var sectionHeader = RegExp.$1;

    Delsort.debug( 'Found section ' + sectionHeader );

    var sectionHeaderAcceptRE = new RegExp('(List of deletion discussions|Articles for deletion|General|Other|' + sectionHeaderTitle + ')');

    if ( ! sectionHeaderAcceptRE.test( sectionHeader ) ) {
        Delsort.error( 'The section header title "' + sectionHeader + '" looks a bit odd; aborting.' );
        return;
    }

    var newval = textbox.value.replace(sectionHeaderRE,'$&{{' + wgAfdPage + '}}\n');

    if (textbox.value == newval) {
        Delsort.error( 'Unable to add Afd, will abort.' );
        return;
    }

    textbox.value = newval;

    Delsort.debug('contents = ' + textbox.value);

    Delsort.status( 'Updating the summary...' );

    var summary = "Listing [[" + wgNominatedArticle + "]]";
    if ( wgNominationIndex )
        summary += wgNominationIndex;

    Delsort.progress( summary  );

    // safety valve to prevent bad edit summaries
    if ( summary.indexOf ( 'Log' ) > -1 ) {
        Delsort.error ( 'incorrect summary, aborting' );
        return;
    }

    doc.getElementById( 'wpSummary' ).value = summary; // + TwinkleConfig.summaryAd;

    // Mark adding an article to a delsort list as a major edit
    // to ensure it appears on Watchlists
    doc.getElementById( 'wpMinoredit' ).checked = false;

    if ( DelsortConfig['watchDelsortedLists'] > 0 ) {
        Delsort.debug( ' (Watching the Delsort list) ' );
	doc.getElementById( 'wpWatchthis' ).checked = true;
    }
    if ( DelsortConfig['watchDelsortedLists'] == 0 ) {
        Delsort.debug( ' (Not watching the Delsort list) ' );
	doc.getElementById( 'wpWatchthis' ).checked = false;
    }

    // debugging interrupt to prevent damage
    // return;

    if (! Delsort.submitHiddenForm ( delsortForm ) )
        return;

    Delsort.progress( 'done' );

    // if the user was in edit mode, use the current form
    if (typeof Delsort.afdForm == 'object' && Delsort.afdForm && 
        Delsort.afdForm['tagName'] && Delsort.afdForm['tagName'] == 'FORM') {
        Delsort.debug( ' Found that the Afd is already in edit mode... ' );
        Delsort.markAfdDelsorted( Delsort.afdForm );
        return;
    }

    Delsort.debug( ' Calling markDelsortedArticle()... ' );

    markDelsortedArticle();
}

function markDelsortedArticle( pType ) {
    if ( pType && !window['twDelsortType'])
        window['twDelsortType'] = pType;

    Delsort.debug( ' In markDelsortedArticle... ' );

    try {
        delsortXML = sajax_init_object();
        Delsort.debug( 'delsortXML' + delsortXML );
        delsortXML.overrideMimeType('text/xml');

        var query = {
            'action': 'submit',
            'title': wgAfdPage
        };

        Delsort.status( 'Grabbing edit form for ' + query.title);

        delsortXML.onreadystatechange = markDelsortedCallback;

        Delsort.debug( 'query:' + query.toSource() );

        delsortXML.open( 'GET' , mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + QueryString.create( query ), true );
        delsortXML.send( null );
    } catch(e) {
        if( e instanceof Exception ) {
            Delsort.error( 'Error: ' + e.what() );
        } else {
            Delsort.error( 'Error: ' + e );
        }
    }
}

function markDelsortedCallback() {
    var afdForm = Delsort.getAJAXEditForm ();
    if (typeof afdForm != 'object') return;

    Delsort.markAfdDelsorted ( afdForm  );
}

// returns 0 when still in progress
//         -1 if there was an error
//      or the edit form when successfully obtained
Delsort.getAJAXResponse = function() {
    if ( delsortXML.readyState != 4 ){
        Delsort.progress('.');
        return 0;
    } 

    if( delsortXML.status != 200 ){
        Delsort.error('Bad status , bailing out; status = ' + delsortXML.status);
        return -1;
    }

    var doc = delsortXML.responseXML;

    if( !doc ) {
        Delsort.error( 'Possible failure in receiving document, will abort.' );
        return -1;
    }

    Delsort.progress( 'done' );

    return doc;
}

Delsort.getAJAXEditForm = function() {
    var doc = Delsort.getAJAXResponse();

    if (typeof doc != 'object') return doc;

    var editForm = doc.getElementById( 'editform' );

    if(! editForm ) {
        Delsort.error( 'Possible failure in receiving document, aborting.' + doc);
        return -1;
    }

    return editForm;
}


Delsort.markAfdDelsorted = function( pAfdForm ) {
    var textbox = pAfdForm['wpTextbox1'];

    var modified = ( textbox.value == textbox.defaultValue ) ? 0 : 1;

    // if the last character in the box is a sig, add a new link character
    if (/[~]$/.test ( textbox.value ) )
        textbox.value += "\n";

    textbox.value += "{{subst:" + "delsort|" + window['twDelsortType'] + "}} <small>-- ~~" + "~~</small>";

    Delsort.debug('contents = ' + textbox.value);

    Delsort.status( 'Updating the summary...' );

    // TODO: the " (xth nom)" needs to be stripped
    var summary = "Listing on [[WP:DELSORT]] under " + window['twDelsortType'];

    // preserve any manual comments in the edit summary
    var wpSummaryNode = pAfdForm['wpSummary'];
    if ( wpSummaryNode.value != wpSummaryNode.defaultValue )
        wpSummaryNode.value += '; ' + summary;
    else
        wpSummaryNode.value = summary;

    Delsort.progress( summary );

    wpPreviewMode =  document.getElementById("wikiPreview") ? 1 : 0;

    // Marking article as delsorted is a minor edit
    // unless the the Afd form is in preview mode or the user
    // has manually changed the textbox
    var wpMinoreditNode = pAfdForm['wpMinoredit'];
    if ( wpMinoreditNode.checked == false &&
          !wpPreviewMode && !modified )
        wpMinoreditNode.checked = true;

    if ( DelsortConfig['watchDelsortedAfd'] > 0 ) {
        Delsort.debug( ' (Watching the Afd) ' );
	pAfdForm['wpWatchthis'].checked = true;
    }
    if ( DelsortConfig['watchDelsortedAfd'] == 0 ) {
        Delsort.debug( ' (Not watching the Afd) ' );
	pAfdForm['wpWatchthis'].checked = false;
    }

    // when the Afd has been trancluded onto the currently displayed
    // page (i.e. the logs), the form submission happens in the background
    if ( unescape(wgPageName).replace('_',' ','g') != wgAfdPage ) {
        Delsort.submitHiddenForm(pAfdForm);
        if (window['delsortWindow'] && window['delsortWindow']['frame'] ) {
            try {
                document.body.removeChild( window['delsortWindow'].frame );
            } catch (x) {}
        }
        return;
    }

    // if the form was in edit mode, there is no need to add the from to
    // the document before submission.
    if (! Delsort.afdForm ) {
        Delsort.debug( ' appending the form to the document ' );
        document.body.appendChild( pAfdForm );
    }

    Delsort.status( 'Submitting the form...' );
    pAfdForm.submit();
}


Delsort.getIFrame = function() {
    var iFrameID = 'delsortFrame';

    var iFrame = document.getElementById('delsortFrame');

    if (iFrame) {
        iFrame.setAttribute('src', 'about:blank');
        return iFrame;
    }

    iFrame = document.createElement('IFRAME');

    if(! iFrame ) {
        Delsort.error( 'Unable to create an IFRAME, aborting.');
        return;
    }

    iFrame.setAttribute('src', 'about:blank');
    iFrame.setAttribute('id', iFrameID);
    iFrame.setAttribute('NAME', iFrameID);
    iFrame.style.display = 'none';

    iFrame.style.width = 0;
    iFrame.style.height = 0;

    document.body.appendChild( iFrame );

    return iFrame;
}

Delsort.submitHiddenForm = function(pForm) {
    iFrame = Delsort.getIFrame();

    pForm.target = iFrame.id;

    iFrame.appendChild( pForm);

    Delsort.status( 'Submitting the form...' );
    try {
        pForm.submit();
    } catch(e) {
        if( e instanceof Exception ) {
            Delsort.error( 'Error: ' + e.what() );
        } else {
            Delsort.error( 'Error: ' + e );
        }
        return false;
    }
    return true;
}

// </nowiki></pre>