Gmail Attachment Information

By Leona Last update Apr 11, 2008 — Installed 594 times.
// ==UserScript==
// @name           Gmail Attachment Information
// @namespace      http://simasima.org/
// @include        http*://mail.google.com/*
// @version        1.3
// @description    inserts the information of attached files when you click the paper clip icon after the filenames turn to be blue.
// ==/UserScript==


window.addEventListener('load', function() {
    
    if (unsafeWindow.gmonkey) {	// for Gmail 2.0

	unsafeWindow.gmonkey.load('1.0', function(gmail) {

	    //--------------------------------------------------
	    // change here to the words in the right of paper clip shaped icon.
	    var trigWord = "Attach a file";
	    //---------------------------------------------------
	    var GM_AI_DEBUGLEVEL = 0; // 0: no debugging messages  <--> 255: all debugging messages

	    gmail.registerViewChangeCallback( viewTypeTrigger );
	    viewTypeTrigger();
	    
	    //----------------------------------------------------
	    //  composes the message about attached file from fileInfo[[], []]
	    // and inserts it into the message body.
	    //----------------------------------------------------
	    function insertFileInfo(){

		var fileInfo = [[], []];
		fileInfo = getFileInfo();
		
		if( fileInfo['number'] > 0 ){
		    
		    // 
		    //  please edit here to change the message about the attached file.
		    //
		    var msg = "";
		    msg  += "<<< " + fileInfo['number']  + " file(s) attached >>>\n";
		    for(var i=0; i<fileInfo['number']; i++){
			msg += "   " + fileInfo[i]['name'] + " (" + fileInfo[i]['size'] + ")\n";
		    }
		    msg += "\n"
		    //

		    var msgBox = new Array();
		    msgBox = getMessageBox();
		    
		    switch( msgBox['type'] ){
		    case 'text':
			msgBox['node'].value += msg;
			break;
			
		    case 'HTML':
			//var ele = document.createElement("div");
			//var info = document.createTextNode( msg.replace(/\n/g, '<br/>') );
			//ele.appendChild( info );
			msgBox['node'].contentDocument.body.innerHTML += '<div id="attachinfo">';
			msgBox['node'].contentDocument.body.innerHTML += msg.replace(/\n/g, '<br />');
			msgBox['node'].contentDocument.body.innerHTML += '</div>';
			
			break;
			
		    case 'null':
		    default:
			break;
		    }
		}
	    }

	    
	    //-----------------------------------------------------------------------
	    //  gets the file information according to the below line of the subject,
	    // and stores them into fileInfo[[], []]
	    //-----------------------------------------------------------------------
	    function getFileInfo(){

		var activeView;
		var nodeCheckBox;
		var mailBody;

		var fileInfo = new Array();
		
		// aquires the list of attached files by searching checkboxes
		var query = '//input[@type="checkbox" and @name="attach"]/../a';
		activeView = gmail.getActiveViewElement();
		nodeCheckBox = xpath( query, activeView );

		// splits into filename, mimetype, filesize
		// and stores them into fileInfo[fileNo.][] array.
		var fileNum = nodeCheckBox.length;
		dbgMsg(fileNum + ' file(s) found.\n');
		for( var i=0; i<fileNum; i++ ){
		    fileInfo[i] = new Array();
		    
		    dbgMsg('file[' + i + '].innerHTML=>' + nodeCheckBox[i].contentText );

		    fileInfo[i]['mime'] = xpath('//i', nodeCheckBox[i] )[i].innerHTML;
		    var nodeMime = xpath('//i', nodeCheckBox[i].firstChild );
		    if( nodeMime.length > 0 ){
			//
			// why isn't this  "nodeMime[0].innerHTML" ?
			fileInfo[i]['mime'] = nodeMime[i].innerHTML;
			fileInfo[i]['name'] = nodeCheckBox[i].innerHTML.split('(<i>' + fileInfo[i]['mime'] + '</i>)')[0];
			fileInfo[i]['size'] = nodeCheckBox[i].innerHTML.split('(<i>' + fileInfo[i]['mime'] + '</i>)')[1];
			fileInfo[i]['size'] = fileInfo[i]['size'].replace(/\s/g, '');
		    }
		    else{
			fileInfo[i]['mime'] = '(mime-error)';
			fileInfo[i]['name'] = '(name-error)';
			fileInfo[i]['size'] = '(size-error)';
		    }
		    dbgMsg( '  mime=' + fileInfo[i]['mime'], 2 );
		    dbgMsg( '  name=' + fileInfo[i]['name'], 2 );
		    dbgMsg( '  size=' + fileInfo[i]['size'], 2 );
		}
		fileInfo['number'] = nodeCheckBox.length;
		
		return fileInfo;
	    }


	    //---------------------------------------------------
	    // returns the node of the message body box if it exists.
	    //----------------------------------------------------
	    function getMessageBox(){
		
		var activeView = gmail.getActiveViewElement();
		var elems;
		var msgBox = new Array();
		
		elems = xpath('//iframe', activeView);
		if( elems.length > 0 ){
		    msgBox['type'] = 'HTML';
		    msgBox['node'] = elems[0];

		    dbgMsg('msgBox (HTML) found.', 1);
		    dbgMsg('  class=' + msgBox.className, 2 );
		}
		else{

		    elems = xpath('//textarea[@name="body"]', activeView);
		    if( elems.length > 0 ){
			msgBox['type'] = 'text';
			msgBox['node'] = elems[0];

			dbgMsg('msgBox (text) found.', 1);
			dbgMsg('  class=' + msgBox.className, 2 );
			
		    }

		    else{
		    
			msgBox['type'] = 'null';
			msgBox['node'] = null;

			dbgMsg('msgbox not found.', 255);
		    }
		}

		return msgBox;
	    }
	    




	    
	    //---------------------------------------------------------
	    // assigns 'insertFileInfo()' to the gem clip icon.
	    //---------------------------------------------------------
	    //
	    //  As the icon is redrawn by the 'Attach a file' link, so 'addButton()'
	    // observes the link and calls 'addEvent2clipIcon()' when the link pressed.
	    function addButton(){

		var msgBox = new Array();

		msgBox = getMessageBox();
		switch( msgBox['type'] ){
		case 'text':
		case 'HTML':
		    var activeView = gmail.getActiveViewElement();
		    var query = '//span[contains(concat(" ",normalize-space(text())," "), " ' + trigWord + ' ")]';
		    var nodeKeyWord = xpath( query, activeView );

		    if( nodeKeyWord.length > 0 ){
			nodeKeyWord[0].addEventListener('click', addEvent2clipIcon, false);

			dbgMsg('trigWord(' + trigWord + ') found.', 1 );
			dbgMsg('  class=' + nodeKeyWord[0].className, 2 );
		    }
		    break;


		case 'null':
		default:
		    
		    // retries after 500msec until there appears the message body box.
		    //    (in conversation mode, there is no message box until you
		    //     press 'reply' link or 'forward' link.)
		    setTimeout( addButton, 500 );
		    break;
		}
	    }

	    //--------------------------------------------------------
	    // assigns 'insertFileInfo()' to the gem clip icon.
	    //--------------------------------------------------------
	    function addEvent2clipIcon(){
		
		var activeView = gmail.getActiveViewElement();
		var query = '//input[@type="file"]/../../../..';
		var nodeKeyWord = xpath( query, activeView );
		if( nodeKeyWord.length > 0 ){
		    
		    var nodeClipIcon = xpath( 'img', nodeKeyWord[0].previousSibling );
		    if( nodeClipIcon.length > 0 ){
			
			nodeClipIcon[0].removeEventListener('click', insertFileInfo, true);
			nodeClipIcon[0].addEventListener('click', insertFileInfo, true);
			nodeClipIcon[0].addEventListener('mouseover',
							 function(){ nodeClipIcon[0].style.cursor = 'pointer'; }
							 , false );
			nodeClipIcon[0].addEventListener('mouseout',
							 function(){ nodeClipIcon[0].style.cursor = 'default'; }
							 , false );
			

			dbgMsg('clip icon found.', 1);
			dbgMsg('  class=' + nodeClipIcon[0].className, 2 );
		    }
		}
		else{
		    setTimeout( addEvent2clipIcon, 500 );
		}
		
	    }

	    
	    //----------------------------------------------------
	    // xpath function  http://yamanoue.sakura.ne.jp/blog/coding/68
	    //----------------------------------------------------
	    function xpath(query, src) {
		var results = document.evaluate(query, src, null,
		    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		var nodes = new Array();
		for(var i=0; i<results.snapshotLength; i++){
		    nodes.push(results.snapshotItem(i));
		}
		return nodes;
	    }

	    //-------------------------------------------------------
	    // 
	    //-------------------------------------------------------
	    function showAlert(){
		alert('alert!!');
	    }


	    //-------------------------------------------------------
	    // debugging message
	    //-------------------------------------------------------
	    function dbgMsg( str, level ){
		// default arguments
		switch( arguments.length ){
		case 0:
		    str = "";
		case 1:
		    level = 1;
		}
		    
		if( GM_AI_DEBUGLEVEL >= level ){
		    GM_log(str);
		}
	    }



	    //---------------------------------
	    // main routine
	    //---------------------------------
	    function viewTypeTrigger(){

		var view = gmail.getActiveViewType();
		dbgMsg('view=' + view, 1 );
		switch( view ){
		case "co":
		case "cv":
		    addButton();
		    break;
		default:
		    break;
		}
	    }


	}); 			// unsafeWindow.gmonkey.load('1.0', function(gmail) {
    }
    else{
	//for Gmail 1.0?

	
    }
    
}, true);