// ==UserScript==
// @name                Bulk image uploader
// @version             1.0
// @date                2009-02-09
// @author              Ian Malpass ( ian AT etsyhacks DOT com )
// @namespace           etsy.com
// @description         Allows you to upload multiple listing images at once
// @include             http://www.etsy.com/create_listing4.php*
// @include             http://www.etsy.com/edit_listing4.php*
// ==/UserScript==

// Determine where we'll redirect to after we've uploaded
var bits = document.location.href.match( /(create|edit)_listing4.php\?.*listing_id=(\d+)/ );
var url = bits[ 1 ] + '_listing4.php?listing_id=' + bits[ 2 ];

// Global to store the number of files left to upload
var to_upload = 0;

// Useful nodes we'll need later
var form = document.forms[ 1 ];
var uploadb = form.elements.namedItem( 'uploadb' );
var icon = document.getElementById( 'ajaxLoaderIcon' ).cloneNode( true );
icon.removeAttribute( 'id' );

// How many image slots do we have left?
var empty = Number( getElementsByClassName( 'sortable-element-list-empty-slot-class' ).length ) / 2;

// if we have one or zero empty slots, leave the UI as-is
if ( empty > 1 ) {
    var uploadNode = form.elements.namedItem( 'uploaded_image' );
    var table = uploadNode.parentNode.parentNode.parentNode;

    // a few text and display tweaks
    table.rows[ 0 ].cells[ 0 ].innerHTML = 'First, find your images (you can leave some blank):';
    table.rows[ 4 ].cells[ 0 ].innerHTML = 'Next, upload them:';
    table.rows[ 8 ].style.display = 'none';

    // replace the file selector with a table of file selectors
    var cell = uploadNode.parentNode;
    var html = '<table>';
    for ( var i = 0; i < empty; i++ ) {
        html += '<tr><td style="padding: 3px">' + ( i + 1 ) + ':</td><td style="padding: 3px"><input type="file" name="uploaded_image_' + i + '" /></td></tr>';
    }
    html += '</table>';
    cell.innerHTML = html;

    // and grab a NodeList of out new inputs
    var nodes = cell.getElementsByTagName( 'input' );

    // jiggery-pokery to get a swirling "busy" icon next to the submit button
    var t = document.createElement( 'table' );
    t.insertRow( 0 );
    t.rows[ 0 ].insertCell( 0 );
    t.rows[ 0 ].insertCell( 1 );
    uploadb.parentNode.appendChild( t );
    t.rows[ 0 ].cells[ 0 ].appendChild( uploadb );
    t.rows[ 0 ].cells[ 1 ].appendChild( icon );
    icon.style.marginLeft = '10px';

    // remove the click handler - replace it with our own
    uploadb.removeAttribute( 'onclick' );
    uploadb.addEventListener( 'click', function () { uploadb.disabled = true; uploadb.value = 'Upload in progress...' }, true );

    // add the submit handler that does the fun stuff
    form.addEventListener( 'submit', genSubmit( form, nodes ), false );
}

// generate a submit handler function
function genSubmit ( form, nodes ) {
    return function ( event ) {
        event.preventDefault(); // not actually going to submit
        for ( var n = 0; n < nodes.length; n++ ) {
            // make sure we have some images to upload
            if( nodes[ n ].value ) to_upload++;
        }
        if ( to_upload == 0 ) {
            // we don't - put the submit button back the way it was
            uploadb.disabled = false;
            uploadb.value = 'Upload';
        } else {
            // we have images to upload - look busy
            icon.style.visibility = 'visible';
            for ( var n = 0; n < nodes.length; n++ ) {
                if( nodes[ n ].value ) {
                    // we have a value - create a hidden iframe
                    var id = 'f' + Math.floor(Math.random() * 99999);
                    var div = document.createElement( 'div' );
                    div.innerHTML = '<iframe style="display: none" src="about:blank" id="' + id + '" name="' + id + '"></iframe>';
                    // add an on-load handler to the iframe
                    div.firstChild.addEventListener( 'load', genLoaded( id ), false );
                    // and add it to the document
                    document.body.appendChild( div );

                    // point the upload form at it
                    form.target = id;
                    // make our current node the one the server's looking for
                    var oldName = nodes[ n ].name;
                    nodes[ n ].name = 'uploaded_image';
                    // submit the form (to the iframe)
                    form.submit();
                    // and return the input it to its former self
                    nodes[ n ].name = oldName;
                }
            }
        }
    }
}

function genLoaded ( id ) {
    return function () {
        if (document.getElementById( id ).contentDocument.location.href == "about:blank") {
            // this is just the iframe initialising
            return;
        }
        loaded(); // we finished loading an image
    };
}

// track the number of uploads, and reload the page when we're done
function loaded () {
    to_upload--;
    if ( to_upload == 0 ) {
        document.location = url;
    }
}

// utility function to replicate getElementsByClassName() on older Firefoxes
function getElementsByClassName ( class, node ) {
    if ( node == null ) node = document;
    if ( node.getElementsByClassName ) {
        return node.getElementsByClassName( class );
    } else {
        var classElements = new Array();
        var els = node.getElementsByTagName( '*' );
        var elsLen = els.length;
        var pattern = new RegExp("(^|\\s)"+class+"(\\s|$)");
        for (i = 0, j = 0; i < elsLen; i++) {
            if ( pattern.test(els[i].className) ) {
                classElements[j] = els[i];
                j++;
            }
        }
        return classElements;
    }
}
