Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
//<source lang="javascript">
 
/*
  Support for quick deletions and closing of deletion requests at the Commons.
 
  Author: [[User:Lupo]], October 2007 - January 2008
  Author: [[User:Wuzur]], December 2008 - January 2009
  Author: [[User:DerHexer]], January 2009
  License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)
 
  Choose whichever license of these you like best :-)
 
  Tested only in Firefox.
*/

/**** Guard against double inclusions */
 
if (typeof (DelReqHandler) == 'undefined') {
 
/**** Some things may not be defined in some cases */
 
var DelReqUtils =
{
  /* userIsInGroup (from MediaWiki:Utilities.js) sometimes isn't defined even after the
     call to importScript below because page loading is asynchronous. Define our own. */
  userIsInGroup : function (group)
  {
    if (wgUserGroups) {
      if (!group || group.length == 0) group = '*';
      for (var i=0; i < wgUserGroups.length; i++) {
        if (wgUserGroups[i] == group) return true;
      }
    }
    return false;
  },
 
  // The following function is defined in several places, and unfortunately, it is defined
  // wrongly in some places. (For instance, in [[:en:User:Lupin/popups.js]]: it should use
  // decodeURIComponent, not decodeURI!!!) Make sure we've got the right version here:
  getParamValue : function (paramName)
  {
    var cmdRe = RegExp ('[&?]' + paramName + '=([^&]*)');
    var h = document.location.href;
    var m = cmdRe.exec (document.location.href);
    if (m) {
      try {
        return decodeURIComponent (m[1]);
      } catch (someError) {}
    }
    return null;
  }
 
} // End of DelReqUtils
 
/**** Enable the whole shebang only for sysops. */
if (DelReqUtils.userIsInGroup ('sysop')) {
 
/**** Import needed files. */
importScript( 'MediaWiki:Utilities.js' );
 
/**** Another file import */
importScript( 'MediaWiki:AjaxSubmit.js' );
 
var DelReqHandler =
{
 
/*------------------------------------------------------------------------------------------
  Deletion request closing: add "[d][del]" and "[k][keep]" links to the left of the section edit
  links of a deletion request. [d] and [k] open the deletion request for editing in a new window
  (or tab), add "delh" and "delf" with "Deleted." or "Kept." plus the signature (four tildes)
  and then save and close the tab. [del] and [keep] do the same, but don't save and close the
  window, so that the user may enter an additional comment.
  ------------------------------------------------------------------------------------------*/
 
  lupo_close_del     : 'close_del',
  lupo_close_keep    : 'close_keep',
  lupo_vote_del      : 'vote_del',
  lupo_vote_keep     : 'vote_keep',
  lupo_quick_closure : '&lupo_quick_closure=1',
  close_del_summary  : 'Deleted',
  close_keep_summary : 'Kept',
  close_add_summary  : 'per discussion.',
  close_one_summary  : 'per nomination.',
  vote_del_summary   : '{{vd}}',
  vote_keep_summary  : '{{vk}}',
  label              : 'Reason:',
 
  closeRequestLinks : function ()
  {
    function addClosingLinks (name, href, before, parent)
    {
      parent.insertBefore (document.createTextNode ('['), before);
      parent.insertBefore
        (makeRawLink (  name.substring (0, 1)
                      , href + DelReqHandler.lupo_quick_closure
                      , '_blank'), before);
      parent.insertBefore (document.createTextNode (']'), before);
 
      parent.insertBefore (document.createTextNode ('['), before);
      parent.insertBefore (makeRawLink (name, href, '_blank'), before);
      parent.insertBefore (document.createTextNode (']'), before);
    }
    function addVotingLinks (name, href, before, parent)
    {
      parent.insertBefore (document.createTextNode ('['), before);
      parent.insertBefore (makeRawLink (name, href, '_blank'), before);
      parent.insertBefore (document.createTextNode (']'), before);
    }
 
    var param = DelReqUtils.getParamValue ('fakeaction');
 
    if (param == null &&
        (document.URL.indexOf ('Commons:Deletion_requests') >= 0 ||
         wgPageName == 'Commons:Deletion_requests')) // To catch the 'COM:DEL' shortcut...
    {
      // We're on COM:DEL or one of its daily subpages
      var edit_lks = getElementsByClassName (document, 'span', 'editsection');
      for (i = 0; i < edit_lks.length; i++) {
        // Find the A within:
        var anchors = edit_lks[i].getElementsByTagName ('a');
        if (anchors != null && anchors.length > 0) {
          var anchor = anchors[0];
          var href   = anchor.getAttribute ('href');
          if (href.indexOf ('Commons:Deletion_requests/20') < 0 &&
              href.indexOf ('Commons:Deletion_requests/') > 0)
          {
            var offset = href.indexOf ('&section=1');
            var len = 10;
            if (offset < 0) {
              offset = href.indexOf ('&section=T-1'); // Fix for MW 1.13alpha
              len = 12;
            }
            if (offset > 0 && offset + len == href.length) {
              // It's really an edit lk to a deletion request subpage, and not a section
              // edit for a daily subpage or something else
              href = href.substring (0, offset);
              var orig_bracket = edit_lks[i].firstChild;
              // [d][del]
              addClosingLinks
                ('del', href + '&fakeaction=' + DelReqHandler.lupo_close_del,
                 orig_bracket, edit_lks[i]);
              // [vd]
              addVotingLinks
                ('vd', href + '&fakeaction=' + DelReqHandler.lupo_vote_del,
                 orig_bracket, edit_lks[i]);
              // [k][keep]
              addClosingLinks
                ('keep', href + '&fakeaction=' + DelReqHandler.lupo_close_keep,
                 orig_bracket, edit_lks[i]);
              // [vk]
              addVotingLinks
                ('vk', href + '&fakeaction=' + DelReqHandler.lupo_vote_keep,
                 orig_bracket, edit_lks[i]);
            }
          }
        }
      }
    } else if (param != null) {
      // We're on a deletion request subpage
      var summary = null;
      var summaryV = null;
      if(DelReqHandler.oneedit(wgPageName)) {
        var addsum = DelReqHandler.close_one_summary;
      } else {
        var addsum = DelReqHandler.close_add_summary;
      }
      if (param == DelReqHandler.lupo_close_del) {
        summary = DelReqHandler.close_del_summary;
      } else if (param == DelReqHandler.lupo_close_keep) {
        summary = DelReqHandler.close_keep_summary;
      } else if (param == DelReqHandler.lupo_vote_del) {
        summaryV = DelReqHandler.vote_del_summary;
      } else if (param == DelReqHandler.lupo_vote_keep) {
        summaryV = DelReqHandler.vote_keep_summary;
      }
      if (summary != null) {
        if (DelReqUtils.getParamValue ('lupo_quick_closure') == '1') {
          var text = document.editform.wpTextbox1;
          text.value =
            '\{\{delh\}\}\n'
            + text.value
            + '----\n'
            + '\'\'\'' + summary + '\'\'\' ' + addsum + ' \~\~\~\~\n'
            + '\{\{delf\}\}';
           setEditSummary (summary + '.');
           submitAndClose (document.editform);
        } else {
          reason = prompt (DelReqHandler.label, '');
          if (reason == null) { window.close(); }
          var text = document.editform.wpTextbox1;
          text.value =
            '\{\{delh\}\}\n'
            + text.value
            + '----\n'
            + '\'\'\'' + summary + '\'\'\' ' + reason + ' \~\~\~\~\n'
            + '\{\{delf\}\}';
           setEditSummary (summary + '.');
           submitAndClose (document.editform);
        }
      }
      if (summaryV != null) {
          reason = prompt (DelReqHandler.label, '');
          if (reason == null) { window.close(); }
          var text = document.editform.wpTextbox1;
          text.value = text.value
            + '\n'
            + '* ' + summaryV + ' ' + reason + ' \~\~\~\~\n'
           setEditSummary (summaryV + '.');
           submitAndClose (document.editform);
      }
    }
  },
 
  /*------------------------------------------------------------------------------------------
    Links on every non-deleted image mentioned on a deletion request page. The "[del]" link
    triggers deletion (auto-completed!) of the image, with a deletion summary linking to the
    deletion request. If the image has a talk page, it is deleted as well. The "[keep]" link
    automatically removes the "delete" template from the image page and adds the "kept" template
    to the image talk page, both linking back to the deletion request.
    ------------------------------------------------------------------------------------------*/
 
  lupo_del_reason  : 'delreason',
  lupo_keep_reason : 'keepreason',
 
  last_reason      : "",
 
  /* promptForReason
   *
   * Execute the del or keep link (by opening a new window), but prompt for a reason first.
   *
   * Parameters:
   *   href                     String  The del/keep href, already prepared.
   *   default_reason  optional String  If set, use this reason if the user doesn't enter one.
   *                                    If no default_reason is given and the user doesn't enter
   *                                    anything, nothing is executed.
   *   use_last        optional boolean If true, use the last entered reason as the default.
   *                                    Defaults to false.
   */
  promptForReason : function (href, default_reason, use_last)
  {
    var reason = null;
    var label = 'Reason:';
    var default_string = default_reason;
    if (use_last) default_string = DelReqHandler.last_reason;
    if (default_string == null) default_string = "";
    reason = prompt (label, default_string);
    DelReqHandler.last_reason = reason;
    if (reason && reason.length > 0) {
      window.open (href + encodeURIComponent (reason), '_blank');
    }
    return false;
  },
 
  /* addDelKeepLinks
   *
   * Add [del] and [keep] links after all the links given.
   *
   * Parameters:
   *   lks                 Array     Static array of DOM elements, which must be links.
   *   do_keep    optional boolean   If true, also add [keep] links. Otherwise, only add [del]
   *                                 links. Defaults to false.
   *   on_del_req optional boolean   If true, try to automatically set a deletion reason by
   *                                 figuring out the deletion request (but if a reason is given,
   *                                 use that). Otherwise, use 'reason'. Defaults to false.
   *   use_last   optional boolean   If true and the prompting links are used, make the prompt
   *                                 default to the last used reason.
   *   reason     optional String    Reason to use. If not set or set to the empty string,
   *                                 generate links that prompt for a reason, unless
   *                                 'on_del_req' is true. Defaults to null (not set).
   */
  addDelKeepLinks : function (lks, do_keep, on_del_req, use_last, reason)
  {
    var with_keep = do_keep || false;
    var is_del_req = on_del_req || false;
 
    for (i = 0; i < lks.length; i++) {
      var href      = lks[i].getAttribute ('href');
      var classes   = lks[i].getAttribute ('class') || "";
      var lk_title  = lks[i].getAttribute ('title') || "";
 
      if (   classes.search (/\bnew\b/) < 0
          && href != null && href.length > 0 && href.charAt(0) == '/')
      {
        // Internal link to existing thingy. Check whether to add the links
        var lk_through_img = classes.search (/\bimage\b/) >= 0;        
        var isImgLk          =
            lk_through_img
         || (lk_title.indexOf ('Image:') == 0 || lk_title.indexOf ('File:') == 0)
            && (lk_title.indexOf ('/') < 0);
        var gallerybox       = null;
        if (lk_through_img) {
          var parent           = lks[i].parentNode;
          while (   gallerybox == null && parent != null
                 && parent.nodeName.toLowerCase () == 'div')
          {
            if (parent.getAttribute ('class') == 'gallerybox') gallerybox = parent;
            parent = parent.parentNode;
          }
          if (gallerybox != null) {
            if (wgNamespaceNumber == 14) {
              // Galleries on category pages (NamespaceNumber == 14) have a link to the image in
              // in the "gallerytext"; so don't add a link for this one; we'll add one for the
              // textual link instead.
              isImgLk = false;
            } else {
              gallerybox = gallerybox.firstChild;
              while (   gallerybox != null
                     && (   typeof (gallerybox.getAttribute) != 'function'
                         || gallerybox.getAttribute ('class') != 'gallerytext'))
              {
                // The test for typeof (gallerybox.getAttribute) is needed because newlines
                // between XHTML elements may be present in the DOM tree as text nodes! And
                // Firefox 2 at least doesn't have 'getAttribute' for text nodes...
                gallerybox = gallerybox.nextSibling;
              }
              if (gallerybox == null || gallerybox.nodeName.toLowerCase () != 'div') {
                // Gallerytext not found. Don't insert links
                isImgLk = false;
              }
            }
          } else {
            // Apparently not in a gallery
            isImgLk = false;
          }
        } // end if lk_through_img
        if (isImgLk) {
          // Insert small [del][keep] small after the link
          var curr_lk  = lks[i];
          var del_href = href + '?action=delete&' + DelReqHandler.lupo_del_reason + '=';
          var keep_href = href + '?action=edit&' + DelReqHandler.lupo_keep_reason + '=';
          var del_reason = reason;
          if (is_del_req && !del_reason) {
            var curr_elem = i-1;
            // Figure out the actual deletion request by finding the previous editsection link,
            // or alternatively, the previous link that already has a delreason (must be within
            // the same deletion request, otherwise the editsection link is found first).
            while (del_reason == null && curr_elem >= 0) {
              var curr_href = lks[curr_elem].getAttribute ('href');
              if (curr_href != null) {
                if (curr_href.indexOf (DelReqHandler.lupo_close_del) > 0) {
                  del_reason = curr_href.substring (curr_href.indexOf ('title=') + 6);
                  var idx = del_reason.indexOf ("&")
                  if (idx >= 0) del_reason = del_reason.substring (0, idx);
                  del_reason = encodeURIComponent ('[[')
                               + del_reason 
                               + encodeURIComponent (']]');
                } else {
                  var offset = curr_href.indexOf (DelReqHandler.lupo_del_reason + '=');
                  if (offset > 0) {
                    del_reason =
                      curr_href.substring (offset + DelReqHandler.lupo_del_reason.length + 1);
                  }
                }
              }
              curr_elem = curr_elem - 1;
            }
          }
          // Add the links
          var toInsert = document.createElement ('small');
          var new_link;
          if (del_reason)
            new_link = makeRawLink ('del', del_href + del_reason, '_blank');
          else
            new_link = makeActiveLink (
                          'del'
                        , 'DelReqHandler.promptForReason ("'
                          + del_href
                          + '", null'   // No default reason here!
                          + (use_last ? ', true);' : ');')
                          + ' void 0;');
          toInsert.appendChild (document.createTextNode (' ['));
          toInsert.appendChild (new_link);
          toInsert.appendChild (document.createTextNode (']'));
          if (with_keep) {
            toInsert.appendChild (document.createTextNode (' ['));
            if (del_reason)
              toInsert.appendChild (makeRawLink ('keep', keep_href + del_reason, '_blank'));
            else
              toInsert.appendChild (
                makeActiveLink (
                   'keep'
                 , 'DelReqHandler.promptForReason ("'
                   + keep_href
                   + '", "Kept."'  // Use a default reason here.
                   + (use_last ? ', true);' : ');')
                   + ' void 0;'));
            toInsert.appendChild (document.createTextNode (']'));
          }
          if (gallerybox != null) {
            // Insert the links at the beginning of the gallerytext
            gallerybox.insertBefore (toInsert, gallerybox.firstChild);
          } else {
            // Append the links after the current link
            curr_lk.parentNode.insertBefore (toInsert, curr_lk.nextSibling);
          }
          if (is_del_req) {
            // Replace the link just handled by the new one to have a sentinel that does have a
            // deletion request attribute.
            lks[i] = new_link;
          }
        } // end if isImgLk
      } // end if
    } // end for all links
  },
 
  delRequestLinks : function ()
  {
    if (document.URL.indexOf ('Commons:Deletion_requests') < 0 &&
        wgPageName != 'Commons:Deletion_requests') // To catch the 'COM:DEL' shortcut...
    {
      return;
    }
 
    // Ok, it's really a deletion request page (either individual, or daily, monthly, overall)
    var lks = getElementsByTagNameStatic ('a', document.getElementById ('bodyContent'));
    // Do *not* use getElementsByTagName directly: it returns a live NodeList of 'a'-tags, and
    // since we are going to add more anchors, we might end up traversing our newly added
    // links, too! Using a static (i.e., non-live) list is much faster anyway.
    DelReqHandler.addDelKeepLinks (lks, true, true, true);
  },
 
  autodelete : function ()
  {
    if (document.forms == null || document.forms[0] == null) {
      // Something went wrong. Maybe the page or the image has already been deleted.
      window.close ();
    } else {
      var param = DelReqUtils.getParamValue (DelReqHandler.lupo_del_reason);
      var reason = document.getElementById ('wpReason');
      var is_page = (param != null && param.length > 2 && param.substring (0, 2) == '\[\[');
 
      if (is_page)
        reason.value = 'per ' + param;
      else
        reason.value = param;
 
      // Also delete the talk page, if there is one.
      try {
        var back_link = document.getElementById ('contentSub').getElementsByTagName ('a')[0];
 
        if (back_link != null) {
          var href = back_link.getAttribute ('href');
          var offset = href.indexOf ('Image:');
          if (offset < 0) offset = href.indexOf ('File:')
          if (offset > 0) {
            var talk_link = document.getElementById ('ca-talk').getElementsByTagName ('a')[0];
            var talk_href = talk_link.getAttribute ('href');
            if (talk_href.indexOf ('&action=edit') < 0) {
              // Talk page exists
              href = talk_href
                   + '?action=delete&' + DelReqHandler.lupo_del_reason + '=';
              if (is_page)
                href = href + encodeURIComponent ('Talk page of file deleted per ' + param);
              else
                href = href + encodeURIComponent ('Talk page of deleted file: ' + param);
              window.open (href, '_blank');
            }
          }
        }
      } catch (e) {
      }
      submitAndClose (document.forms[0]);
    }
  },
 
  months : new Array ("January", "February", "March", "April", "May", "June",
                      "July", "August", "September", "October", "November", "December"),
 
  autokeep : function ()
  {
    var edit_form = document.getElementById ('editform');
    if (edit_form == null) {window.close (); return;}
    var edit_text = document.getElementById ('wpTextbox1');
    if (edit_text == null) {window.close (); return;}
    var text = edit_text.value;
 
    var success = false;
    if (wgNamespaceNumber == 6) {
 
      // IF we're on the image page:
      // Search for the "delete" tag (beware of nested transclusions, such as the reason
      // containing a "tl" template)
 
      var start = text.indexOf ('\{\{delete');
      if (start < 0) start = text.indexOf ('\{\{Delete');
      if (start < 0) start = text.indexOf ('\{\{vfd');
      if (start < 0) start = text.indexOf ('\{\{Vfd');
      if (start < 0) start = text.indexOf ('\{\{ifd');
      if (start < 0) start = text.indexOf ('\{\{Ifd');
      if (start >= 0) {
        var level = 0;
        var curr = start + 2;
        var end = 0;
        while (curr < text.length && end == 0) {
          var opening = text.indexOf ('\{\{', curr);
          var closing = text.indexOf ('\}\}', curr);
          if (opening >= 0 && opening < closing) {
            level = level + 1;
            curr = opening + 2;
          } else {
            if (closing < 0) {
              // No closing braces found
              curr = text.length;
            } else {
              if (level > 0) level = level - 1; else end = closing + 2;
              curr = closing + 2;
            }
          }
        }
        if (end > start) {
          // Also strip whitespace after the "delete" template
          if (start > 0) {
            edit_text.value = text.substring (0, start)
                            + text.substring (end).replace(/^\s*/, '');
          } else {
            edit_text.value = text.substring (end).replace(/^\s*/, '');
          }
          setEditSummary (  'Kept per '
                          + DelReqUtils.getParamValue (DelReqHandler.lupo_keep_reason));
          success = true;
        } else {
          setEditSummary ('ERROR: End of deletion tag not found');
        }
      } else {
        setEditSummary ('ERROR: No deletion tag found.');
      }
      // Open the talk page for editing
      var talk_link = document.getElementById ('ca-talk').getElementsByTagName ('a')[0];
      var talk_href = talk_link.getAttribute ('href');
      if (talk_href.indexOf ('&action=edit') < 0) talk_href = talk_href + '?action=edit';
      talk_href = talk_href
                + '&' + DelReqHandler.lupo_keep_reason + '='
                + encodeURIComponent
                   (DelReqUtils.getParamValue (DelReqHandler.lupo_keep_reason));
      if (success) {
        // Don't close the window but re-load the talk page into it!
        ajaxSubmit
          (document.forms[0], null, function() { window.location.href = talk_href; });
      } else {
        // Don't submit and close the image description page, but *do* continue with the talk
        // page.
        window.setTimeout(function() { window.open (talk_href, '_blank'); }, 100);
      }
    } else if (wgNamespaceNumber == 7) {
      // We're on the talk page: just append "kept"
      setEditSummary ('\{\{kept\}\}');
      try {
        var del_req_page = DelReqUtils.getParamValue (DelReqHandler.lupo_keep_reason);
        // Strip the [[ and ]]
        del_req_page = del_req_page.substring (2, del_req_page.length - 2);
        // Find the date by getting the timestamp of the earliest revision of the deletion request.
        var request = sajax_init_object();
        if (request != null) {
          var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?action=query'
                  + '&prop=revisions&rvlimit=1'                    // Exactly one revision
                  + '&titles=' + encodeURIComponent (del_req_page) // Of the deletion request
                  + '&rvprop=timestamp'                            // Only the timestamp
                  + '&rvdir=newer'                                 // Start at the oldest revision
                  + '&format=json&callback=DelReqHandler.addKeepToTalk';
          // Make the call
          request.open ('GET', uri, true);
          request.setRequestHeader ('Pragma', 'cache=no');
          request.setRequestHeader ('Cache-Control', 'no-transform');
          request.onreadystatechange =
            function()
            {
              if (request.readyState != 4) return; // Request not completed yet
              if (request.status != 200)   return; // Request failed
              eval (request.responseText);
            };
          request.send (null); // No POST data
        } else {
          // We don't have XMLHttp...
          edit_text.value = edit_text.value + '\n\{\{kept||' + del_req_page + '\}\}';
          // We cannot close the window either, we can just submit the form.
          document.forms[0].submit ();
        }
      } catch (e) {
        // TODO: Improve error handling. Just propagate the exception?
        alert ('Exception: ' + e);
      }
    }
  },
 

  newRequest : function () {
   try {
      if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
      } else {
        return new ActiveXObject("MSXML2.XMLHTTP");
      }
   } catch (e) {
      return false;
   }
  },
 
  oneedit : function (page) {
    if (req = DelReqHandler.newRequest()) {
    var text = "/w/api.php?format=xml&action=query&prop=revisions&titles="+page+"&rvlimit=2";
    req.open("GET", text, false);
    req.send("");
 
    var revisions = req.responseXML.getElementsByTagName("rev");
    if (revisions.length == 1) {return true; } else { return false; }
 
    }
  },

  addKeepToTalk : function (results) // JSON callback
  {
    if (!results || !results.query || !results.query.pages) return;
    var success   = false;
    var edit_text = document.getElementById ('wpTextbox1'); // We *know* this exists
    try {
      var del_req_page = DelReqUtils.getParamValue (DelReqHandler.lupo_keep_reason);
      del_req_page = del_req_page.substring (2, del_req_page.length - 2);
      for (var page in results.query.pages) {
        // There should be only one, but the for-loop is the easiest to get the unknown page id used
        // as the sub-object selector...
        var p = results.query.pages[page];
        if (p.revisions && p.revisions.length > 0) {
          var ts = p.revisions[0].timestamp;
          if (ts && ts.length > 10) {
            // Extract year, month, and day from the timestamp. We don't care about the
            // exact time.
            var year  = ts.substr (0, 4);
            var month = parseInt (ts.substr (5, 2), 10); // Specify the radix
            var day   = parseInt (ts.substr (8, 2), 10); // Specify the radix
            // Note: we must specify the radix here, otherwise, "08" and "09" will be
            // treated as invalid octal numbers!
            edit_text.value = edit_text.value
                            + '\n\{\{kept|'
                            + DelReqHandler.months[month-1]
                            + ' ' + day + ', ' + year
                            + '|' + del_req_page + '\}\}';
            success = true;
          }
        }
        break;
      }
    } catch (ex) {
      // Swallow
    }
    if (!success) {
      // Huh? Somehow, we couldn't get the date.
      edit_text.value = edit_text.value + '\n\{\{kept||' + del_req_page + '\}\}';
    }
    submitAndClose (document.forms[0]);
  },
 
  setupAutoDel : function ()
  {
    // Wait until the included scripts have loaded.
    if (typeof (ajaxSubmit) != 'function' || typeof (setEditSummary) != 'function')
      window.setTimeout (DelReqHandler.setupAutoDel, 100);
    else {
      // Everything's loaded now
      if (document.URL.indexOf (DelReqHandler.lupo_del_reason) > 0) {
        DelReqHandler.autodelete ();
      } else if (document.URL.indexOf (DelReqHandler.lupo_keep_reason) > 0) {
        DelReqHandler.autokeep ();
      } else {
        DelReqHandler.closeRequestLinks();
        DelReqHandler.delRequestLinks();
      }
    }
  }
 
} // End of DelReqHandler
 
$ (DelReqHandler.setupAutoDel);
 
} // End of sysop check
 
} // End of idempotency check
 
//</source>