Gmail - dynamic Add Attachment - Reverse Engineering

Discussion in 'Javascript' started by JavaScriptRocks, Aug 4, 2005.

  1. I've been trying to imitate / reverse engineer the add attachment
    feature in gmail composer. I managed to do it to say about 80% but its
    giving me trouble in IE on WinXP-Sp2. I am using PHP to do the upload.
    It works well on Firefox/DeerPark, but in IE, the file selected just
    vanishes. You can verify it by commenting the lines marked "//IE
    Trouble". Commenting those lines will remove IE specific code, except
    the el.click() whick sends the Click event to the newly added file
    upload input element.


    Please someone help me.


    _________________________
    Here is the code
    -------------------------
    <?
    include_once('../modules/file_­upload/lib_upload.php');
    ?>

    <script language="JavaScript">

    function Table_AddRow(tblName, pos)
    {
    if(typeof(pos) == 'undefined')
    pos = '_LAST_';


    var tbl = document.getElementById(tblNam­e);
    switch(pos)
    {
    case '_LAST_':
    pos = tbl.rows.length;
    default:
    pos = parseInt(pos, 10);
    if(isNaN(pos))
    {
    pos = 0;
    }
    else if (pos > tbl.rows.length)
    {
    pos = tbl.rows.length;
    }
    }


    var today = new Date();
    var rowID = tblName + today.getTime() + tbl.rows.length;


    var row = tbl.insertRow(pos);
    if(document.all) row.style.display = 'none';
    //IE Trouble
    var cellRight = row.insertCell(row.length);
    cellRight.setAttribute('id', rowID);


    var el = document.createElement('input'­);
    el.setAttribute('type', 'FILE');
    el.setAttribute('name', 'upload_files[]');
    if(document.all) el.style.display = 'none';
    //IE Trouble
    cellRight.appendChild(el);


    if(document.all)
    {
    //IE Trouble
    el.click();
    if(el.value == '')
    //IE Trouble
    {
    //IE Trouble
    DeleteCurRow(row);
    //IE Trouble
    }
    //IE Trouble
    else
    //IE Trouble
    {
    //IE Trouble
    row.style.display = '';
    //IE Trouble
    var fn = document.createElement("strong­");
    //IE Trouble
    fn.innerHTML = el.value;
    //IE Trouble
    cellRight.appendChild(fn);
    //IE Trouble
    }
    //IE Trouble
    }
    var spc = document.createElement("span")­;
    spc.innerHTML = "&nbsp;";
    cellRight.appendChild(spc);


    var aa = document.createElement("a");
    aa.setAttribute('href', 'javascript:;');
    var clickName = new
    Function("Table_DeleteRowByID(­'"+tblName+"','"+rowID+"')");
    aa.onclick = clickName;
    aa.innerHTML = "remove";
    cellRight.appendChild(aa);



    }


    function Table_DeleteRow(x)
    {
    while (x.tagName.toLowerCase() !='tr')
    {
    if(x.parentElement)
    x=x.parentElement;
    else if(x.parentNode)
    x=x.parentNode;
    else
    return;
    }
    var rowNum=x.rowIndex;
    while (x.tagName.toLowerCase() !='table')
    {
    if(x.parentElement)
    x=x.parentElement;
    else if(x.parentNode)
    x=x.parentNode;
    else
    return;
    }
    x.deleteRow(rowNum);


    }


    function Table_DeleteRowByIndex(tblName­, row)
    {
    var tbl = document.getElementById(tblNam­e);
    x.deleteRow(row);


    }


    function Table_DeleteRowByID(tblName, rowID)
    {
    var tbl = document.getElementById(tblNam­e);
    var row = document.getElementById(rowID)­;
    while (row.tagName.toLowerCase() !='tr')
    {
    if(row.parentElement)
    row = row.parentElement;
    else if(row.parentNode)
    row = row.parentNode;
    else
    return;
    }
    var rowNum = row.rowIndex;
    tbl.deleteRow(rowNum);


    }


    </script>

    <form method="post" enctype="multipart/form-data">
    <table id="tblSample" border="0" cellspacing="2"
    cellpadding="2">
    <tr id="tblSample_row0">
    <td><a href="javascript:;"
    onClick="Table_AddRow('tblSamp­le', 0); return false;">Add
    File</a></td>
    </tr></table><input type="hidden" name="MAX_FILE_SIZE"
    value="512000"><input type=submit>
    </form>


    <?php
    if($REQUEST_METHOD == "POST")
    {
    $newNames = array();
    if(($newFile = UploadFile('upload_files', '.', 1, $newNames,
    array('application/x-zip-compr­essed', 'application/zip'))) === false)

    {
    ?><font color=red><b>Upload of <?= sizeof($APP_ERR)?>
    file(s) failed.</font><br><strong>Erro­r: </strong><?
    print_r($APP_ERR)?><?
    }
    else
    {
    ?><font color=green><b><?= sizeof($newNames)?> file(s)
    uploaded.<br></font>&nbsp;&nbs­p;&nbsp;New filename: <?
    print_r($newNames) ?><?
    }
    }


    ?>

    _________________________
    lib_upload.php
    -------------------------
    sorry for the un-pro coding, one of my
    early creations, not well maintained
    -------------------------
    function UploadFile($name, $path, $mandatory = 0, &$newName,
    $mimeAllowed = array())
    {
    global $APP_ERR;
    global $HTTP_POST_FILES;
    global $PATH_TRANSLATED;
    global $HTTP_POST_VARS;
    global $UPLOAD_MAX_FILESIZE;

    $UPLOAD_MAX_FILESIZE = get_cfg_var('upload_max_filesize');
    $x = substr($UPLOAD_MAX_FILESIZE, -1);
    switch($x)
    {
    case 'T':
    $x = 1099511627776;
    break;
    case 'G':
    $x = 1073741824;
    break;
    case 'M':
    $x = 1048576;
    break;
    case 'K':
    $x = 1024;
    break;
    default:
    $x = 1;
    break;
    }
    $UPLOAD_MAX_FILESIZE = intval($UPLOAD_MAX_FILESIZE) * $x;
    $scrMaxSize = intval($HTTP_POST_VARS['MAX_FILE_SIZE']);
    $UPLOAD_MAX_FILESIZE = $scrMaxSize < $UPLOAD_MAX_FILESIZE?
    $scrMaxSize: $UPLOAD_MAX_FILESIZE;
    unset($x, $scrMaxSize);

    if(isset($name) && isset($path))
    {
    $APP_ERR = NULL;

    set_time_limit(60);
    $MimeType = array(
    'application/x-drm' => 'dnp',
    'image/x-tiff' => 'tif',
    'image/x-targa' => 'tga',
    'image/x-quicktime' => 'qti',
    'image/x-png' => 'png',
    'image/x-pict' => 'pic',
    'image/pict' => 'pic',
    'image/x-macpaint' => 'mac',
    'image/x-photoshop' => 'psd',
    'image/x-sgi' => 'sgi',
    'application/x-rtsp' => 'rts',
    'audio/vnd.qcelp' => 'qcp',
    'video/flc' => 'flc',
    'application/asx' => 'asx',
    'audio/x-rmf' => false,
    'audio/rmf' => false,
    'audio/midi' => 'mid',
    'audio/nspaudio' => 'lma',
    'audio/x-nspaudio' => 'lma',
    'text/xml' => 'xml',
    'audio/wav64' => 'w64',
    'application/x-cnet-vsl' => 'vsl',
    'text/iuls' => 'uls',
    'application/x-shockwave-flash' => 'swf',
    'application/vnd.ms-pki.stl' => 'stl',
    'application/vnd.ms-pki.certstore' => 'sst',
    'application/futuresplash' => 'spl',
    'application/forge' => 'sfw',
    'audio/sfa' => 'sfa',
    'audio/x-sd2' => 'sd2',
    'text/scriptlet' => false,
    'application/vnd.adobe.asset-catalog' => 'sac',
    'audio/x-pn-realaudio-plugin' => 'rpm',
    'application/rat-file' => 'rat',
    'application/pics-rules' => 'prf',
    'application/vnd.ms-pki.pko' => 'pko',
    'audio/pca' => 'pca',
    'application/pkcs7-signature' => 'p7s',
    'application/x-pkcs7-certreqresp' => 'p7r',
    'application/pkcs7-mime' => 'p7m',
    'application/x-pkcs7-certificates' => 'p7b',
    'application/x-pkcs12' => 'p12',
    'application/pkcs10' => 'p10',
    'audio/ogg' => 'ogg',
    'application/x-mmxp' => 'mxp',
    'audio/mid' => 'mid',
    'application/msaccess' => 'mdb',
    'application/x-troff-man' => 'man',
    'image/pjpeg' => 'jfif',
    'application/x-iphone' => 'iii',
    'image/x-icon' => 'ico',
    'Icon Library' => 'icl',
    'text/webviewhtml' => 'htt',
    'text/x-component' => 'htc',
    'application/hta' => 'hta',
    'application/vnd.fdf' => 'fdf',
    'message/rfc822' => 'eml',
    'video/x-dv' => 'dv',
    'application/x-speedbit-daf' => 'daf',
    'application/x-ctm' => 'ctm',
    'text/css' => 'css',
    'application/pkix-crl' => 'crl',
    'application/x-x509-ca-cert' => 'cer',
    'application/x-cdf' => 'cdf',
    'application/vnd.ms-pki.seccat' => 'cat',
    'image/bmp' => false,
    'text/h323' => '323',
    'application/x-vpeg005' => 'vpg',
    'application/vnd.rn-realsystem-rjt' => 'rjt',
    'audio/blue-matter-song' => 'bmt',
    'text/blue-matter-content-ref' => 'bmr',
    'audio/blue-matter-offer' => 'bmo',
    'audio/x-liquid-file' => 'la1',
    'application/x-laplayer-reg' => 'lar',
    'audio/x-liquid-secure' => 'lavs',
    'audio/x-la-lqt' => 'lqt',
    'audio/x-la-lms' => 'lmsff',
    'audio/x-mei-aac' => 'acp',
    'text/vnd.rn-realtext3d' => 'r3t',
    'audio/x-pn-aiff' => 'aif',
    'audio/x-pn-au' => 'au',
    'audio/x-pn-windows-pcm' => 'wav',
    'audio/x-pn-windows-acm' => 'wav',
    'audio/x-pn-wav' => 'wav',
    'audio/wav' => 'wav',
    'application/vnd.rn-realsystem-rmj' => 'rmj',
    'application/vnd.rn-realmedia-vbr' => 'rmvb',
    'video/vnd.rn-realvideo-secure' => 'rms',
    'audio/x-realaudio-secure' => 'rms',
    'application/vnd.rn-realaudio-secure' => 'rms',
    'application/vnd.rn-realmedia-secure' => 'rms',
    'audio/x-musicnet-download' => 'mnd',
    'audio/x-musicnet-stream' => 'mns',
    'application/vnd.rn-realsystem-rom' => 'rom',
    'application/vnd.rn-realsystem-r1m' => 'r1m',
    'video/x-mpg' => 'mpa',
    'audio/mp2' => 'mp2',
    'audio/mp1' => 'mp1',
    'video/mpg' => 'mpg',
    'audio/rn-mpeg' => 'mpga',
    'audio/mpeg' => 'mpga',
    'application/x-sdp' => 'sdp',
    'application/sdp' => 'sdp',
    'image/vnd.rn-realpix' => 'rp',
    'text/vnd.rn-realtext' => 'rt',
    'image/vnd.rn-realflash' => 'rf',
    'video/vnd.rn-realvideo' => 'rv',
    'application/vnd.rn-realmedia' => 'rm',
    'audio/x-realaudio' => 'ra',
    'audio/vnd.rn-realaudio' => 'ra',
    'application/vnd.rn-realsystem-rjs' => 'rjs',
    'application/vnd.rn-realsystem-rmx' => 'rmx',
    'application/vnd.rn-rn_music_package' => 'rmp',
    'application/vnd.rn-realplayer' => 'rnx',
    'application/vnd.rn-rsml' => 'rsml',
    'application/streamingmedia' => 'ssm',
    'application/smil' => 'smi',
    'audio/mpegurl' => 'm3u',
    'audio/mpg' => 'mpg',
    'audio/mp3' => 'mp3',
    'audio/x-mpg' => 'mpg',
    'audio/x-mp3' => 'mp3',
    'audio/scpls' => 'pls',
    'audio/x-scpls' => 'pls',
    'video/x-ms-wvx' => 'wvx',
    'video/x-ms-wmv' => 'wmv',
    'video/x-ms-wm' => 'wm',
    'video/x-ms-asf' => false,
    'video/x-mpeg2a' => 'mp2',
    'video/x-mpeg' => 'mpe',
    'video/x-ivf' => 'ivf',
    'video/msvideo' => 'avi',
    'video/avi' => 'avi',
    'midi/mid' => 'mid',
    'audio/x-ms-wma' => 'wma',
    'audio/x-ms-wax' => 'wax',
    'audio/x-mpegurl' => 'm3u',
    'audio/x-midi' => 'mid',
    'application/pps' => 'pps',
    'application/pot' => 'pot',
    'application/ppt' => 'ppt',
    'application/xlc' => 'xlc',
    'application/msexcel' => 'xls',
    'audio/aiff' => 'aif',
    'application/x-compress' => 'z',
    'application/wordperfect5.1' => 'wpd',
    'application/vnd.lotus-screencam' => 'scm',
    'application/vnd.lotus-organizer' => 'org',
    'application/vnd.lotus-freelance' => 'pre',
    'application/vnd.lotus-wordpro' => 'lwp',
    'application/vnd.ms-schedule' => 'sch',
    'application/vnd.ms-powerpoint' => false,
    'application/vnd.ms-access' => false,
    'application/vnd.ms-excel' => false,
    'application/msword' => 'doc',
    'application/x-pkcs7-crl' => 'crl',
    'application/pre-encrypted' => 'enc',
    'application/x-pkcs7-signature' => 'p7s',
    'application/x-pkcs7-mime' => 'p7m',
    'application/x-javascript-config' => 'jsc',
    'application/x-ns-proxy-autoconfig' => 'pac',
    'application/x-javascript' => 'js',
    'application/x-perl' => 'pl',
    'application/x-tcl' => 'tcl',
    'application/x-sh' => 'sh',
    'application/x-csh' => 'csh',
    'application/postscript' => false,
    'application/octet-stream' => false,
    'application/java-archive' => 'jar',
    'application/x-cpio' => 'cpio',
    'application/x-gtar' => 'gtar',
    'application/x-tar' => 'tar',
    'application/x-shar' => 'shar',
    'application/x-zip-compressed' => 'zip',
    'application/x-stuffit' => 'sit',
    'application/mac-binhex40' => 'hqx',
    'video/x-msvideo' => 'avi',
    'video/quicktime' => false,
    'video/x-mpeg2' => 'mpv2',
    'video/mpeg' => 'mpg',
    'audio/x-pn-realaudio' => 'ram',
    'audio/x-mpeg' => 'mpga',
    'audio/x-wav' => 'wav',
    'audio/x-aiff' => 'aif',
    'audio/basic' => 'snd',
    'application/fractals' => 'fif',
    'image/ief' => 'ief',
    'image/png' => 'png',
    'image/x-photo-cd' => 'pcd',
    'image/x-MS-bmp' => 'bmp',
    'image/x-rgb' => 'rgb',
    'image/x-portable-pixmap' => 'ppm',
    'image/x-portable-graymap' => 'pgm',
    'image/x-portable-bitmap' => 'pbm',
    'image/x-portable-anymap' => 'pnm',
    'image/x-xwindowdump' => 'xwd',
    'image/x-xpixmap' => 'xpm',
    'image/x-xbitmap' => 'xbm',
    'image/x-cmu-raster' => 'ras',
    'image/tiff' => 'tif',
    'image/jpeg' => 'jpg',
    'image/gif' => 'gif',
    'text/x-vcard' => 'vcf',
    'application/x-texinfo' => 'texinfo',
    'application/x-dvi' => 'dvi',
    'application/x-latex' => 'latex',
    'application/x-tex' => 'tex',
    'application/pdf' => 'pdf',
    'application/rtf' => 'rtf',
    'application/zip' => 'zip',
    'text/html' => 'htm',
    'text/plain' => 'txt'
    );

    if(substr($path, 0, 1) != '/')
    $path = dirname($PATH_TRANSLATED).'/'.$path;
    $path .= substr($path, -1) != '/'? '/': '';

    list($usec, $sec) = explode(' ', microtime());
    list(, $usec) = explode('.', $usec);
    $fnBase = $sec.$usec;

    $errStat = count($APP_ERR);
    for($i = 0; $i < sizeof($HTTP_POST_FILES[$name]['name']); $i++)
    {
    if(empty($HTTP_POST_FILES[$name]['name'][$i]))
    {
    if(is_array($mandatory) && $mandatory[$i])
    $APP_ERR[$i] = 'File was not uploaded.';
    }

    if((sizeof($mimeAllowed) > 0) &&
    !in_array($HTTP_POST_FILES[$name]['type'][$i], $mimeAllowed))
    {
    $APP_ERR[$i] = 'File type not allowed.';
    }

    if(!empty($HTTP_POST_FILES[$name]['name'][$i]) &&
    isset($MimeType[$HTTP_POST_FILES[$name]['type'][$i]]))
    {
    if(!isset($newName[$i])) $newName[$i] = "$fnBase$i";

    if(false === strrchr($newName[$i], '.'))
    {
    $newName[$i] .= '.';
    $newName[$i] .= $MimeType[$HTTP_POST_FILES[$name]['type'][$i]] ===
    false
    ? substr($HTTP_POST_FILES[$name]['name'][$i],
    strrpos($HTTP_POST_FILES[$name]['name'][$i], '.'))
    : $MimeType[$HTTP_POST_FILES[$name]['type'][$i]];
    }
    continue;
    }
    else
    {
    $APP_ERR[$i] = 'Unknown file type.';
    }
    unset($newName[$i]);
    }

    if($errStat == count($APP_ERR) && (!is_array($mandatory) &&
    $mandatory === count($newName)))
    {
    for($i = 0; $i < sizeof($HTTP_POST_FILES[$name]['name']); $i++)
    {
    if(false ===
    move_uploaded_file($HTTP_POST_FILES[$name]['tmp_name'][$i],
    $path.$newName[$i]))
    {
    $APP_ERR[$i] = true;
    unset($newName[$i]);
    continue;
    }
    }
    }

    return sizeof($APP_ERR) > 0 ? false: $newName;
    }
    }
     
    JavaScriptRocks, Aug 4, 2005
    #1
    1. Advertising

  2. JavaScriptRocks

    RobG Guest

    JavaScriptRocks wrote:
    > I've been trying to imitate / reverse engineer the add attachment
    > feature in gmail composer. I managed to do it to say about 80% but its
    > giving me trouble in IE on WinXP-Sp2. I am using PHP to do the upload.
    > It works well on Firefox/DeerPark, but in IE, the file selected just
    > vanishes. You can verify it by commenting the lines marked "//IE
    > Trouble". Commenting those lines will remove IE specific code, except
    > the el.click() whick sends the Click event to the newly added file
    > upload input element.
    >
    >
    > Please someone help me.
    >
    >
    > _________________________
    > Here is the code
    > -------------------------
    > <?
    > include_once('../modules/file_­upload/lib_upload.php');
    > ?>
    >
    > <script language="JavaScript">


    language is depreciated, type is required.

    >
    > function Table_AddRow(tblName, pos)
    > {
    > if(typeof(pos) == 'undefined')
    > pos = '_LAST_';
    >
    >
    > var tbl = document.getElementById(tblNam­e);
    > switch(pos)
    > {
    > case '_LAST_':
    > pos = tbl.rows.length;
    > default:
    > pos = parseInt(pos, 10);
    > if(isNaN(pos))
    > {
    > pos = 0;
    > }
    > else if (pos > tbl.rows.length)
    > {
    > pos = tbl.rows.length;
    > }
    > }


    That appears to be an inordinate amount of code just to check 'pos'.
    Given that you pass 'pos' from your own code, how about:

    function Table_AddRow(tblName, pos) {
    var tbl = document.getElementById(tblNam­e);
    var rlen = tbl.length;
    if ( pos > rlen || pos < 0 ) pos = -1;

    If 'pos' is not a valid index to the table, it will be set to -1 so that
    the new row will be appended as the last row (which is what I think
    your code is doing). I would also guess that any feature testing for
    getElementById) is done up front before the rest of the script is attempted.

    >
    > var today = new Date();
    > var rowID = tblName + today.getTime() + tbl.rows.length;
    >
    > var row = tbl.insertRow(pos);
    > if(document.all) row.style.display = 'none';
    > //IE Trouble


    What is the point of testing document.all? If you want to see if the
    style object is supported, test that:

    if ( row.style) row.style.display = 'none';

    It would also be better to do it once and deal with it once.

    > var cellRight = row.insertCell(row.length);
    > cellRight.setAttribute('id', rowID);


    Simpler to access the cell attributes directly. And since you know that
    the row has a length of zero (you just created it):

    var cellRight = row.insertCell(0);
    cellRight.id = rowID;

    Which makes me think 'rowID' should be 'cellID'.

    >
    >
    > var el = document.createElement('input'­);
    > el.setAttribute('type', 'FILE');
    > el.setAttribute('name', 'upload_files[]');


    accessing attribute directly is simpler:

    el.type = 'file';
    el.name = 'upload_files[]';

    > if(document.all) el.style.display = 'none';
    > //IE Trouble
    > cellRight.appendChild(el);
    >
    > if(document.all)
    > {
    > //IE Trouble
    > el.click();


    el is type 'file', which does not have a 'click' method:

    <URL:http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-2651361>

    > if(el.value == '')
    > //IE Trouble
    > {
    > //IE Trouble
    > DeleteCurRow(row);


    Where is 'DeleteCurRow' defined?

    > //IE Trouble
    > }
    > //IE Trouble
    > else
    > //IE Trouble
    > {
    > //IE Trouble
    > row.style.display = '';
    > //IE Trouble
    > var fn = document.createElement("strong­");
    > //IE Trouble
    > fn.innerHTML = el.value;
    > //IE Trouble
    > cellRight.appendChild(fn);


    Mixing of DOM methods with innerHTML can be unreliable - it is likely
    better to use one or the other. Since tables are involved, say stick to
    DOM:

    fn.appendChild(document.createTextNode( el.value ));
    cellRight.appendChild(fn);

    > //IE Trouble
    > }
    > //IE Trouble
    > }
    > var spc = document.createElement("span")­;
    > spc.innerHTML = "&nbsp;";


    Same here:

    spc.appendChild(document.createTextNode('\u00A0'));

    where \u00A0 will insert a non-breaking space.

    > cellRight.appendChild(spc);
    >
    >
    > var aa = document.createElement("a");
    > aa.setAttribute('href', 'javascript:;');
    > var clickName = new
    > Function("Table_DeleteRowByID(­'"+tblName+"','"+rowID+"')");
    > aa.onclick = clickName;


    You start using the javascript pseudo protocol in the HREF attribute
    then use an onclick. Why use an 'a' element at all? Why not a span
    with an onclick or an input button?

    You may also be having issues with closures here with references to
    tblName and rowID (I didn't test it but it seems likely).

    You could use (see below):

    aa.onclick = function() { Table_DeleteRowByID( rowID ); }

    Provided the issue with closure is dealt with.

    > aa.innerHTML = "remove";


    aa.appendChild(document.createTextNode('remove'));

    > cellRight.appendChild(aa);
    > }
    >
    >
    > function Table_DeleteRow(x)
    > {
    > while (x.tagName.toLowerCase() !='tr')
    > {
    > if(x.parentElement)
    > x=x.parentElement;
    > else if(x.parentNode)
    > x=x.parentNode;
    > else
    > return;


    More efficient:
    while ( x.parentNode && 'tr' != x.nodeName.toLowerCase() ) {
    x = x.parentNode;
    }

    > }
    > var rowNum=x.rowIndex;
    > while (x.tagName.toLowerCase() !='table')
    > {
    > if(x.parentElement)
    > x=x.parentElement;
    > else if(x.parentNode)
    > x=x.parentNode;
    > else
    > return;
    > }
    > x.deleteRow(rowNum);
    >


    All of the above can be replaced with:

    if ( 'tr' == x.nodeName.toLowerCase() ) {
    x.parentNode.removeChild( x );
    }

    But this function is not used anyway.

    >
    > }
    >
    >
    > function Table_DeleteRowByIndex(tblName­, row)
    > {
    > var tbl = document.getElementById(tblNam­e);
    > x.deleteRow(row);
    >
    >
    > }


    Does not appear to be used.

    >
    >
    > function Table_DeleteRowByID(tblName, rowID)
    > {
    > var tbl = document.getElementById(tblNam­e);
    > var row = document.getElementById(rowID)­;
    > while (row.tagName.toLowerCase() !='tr')
    > {
    > if(row.parentElement)
    > row = row.parentElement;
    > else if(row.parentNode)
    > row = row.parentNode;
    > else
    > return;
    > }
    > var rowNum = row.rowIndex;
    > tbl.deleteRow(rowNum);
    >
    >
    > }


    Presuming you want to delete the row with a particular ID, then the
    above can be replaced with:

    function Table_DeleteRowByID( rowID ) {
    var row = document.getElementById( rowID );
    if ( row ) row.parentNode.removeChild( row );
    }

    Which can be used as a generic method to delete any element with an id:

    function deleteElementById( elID ) {
    var el = document.getElementById( elID );
    if ( el ) el.parentNode.removeChild( el );
    }


    >
    >
    > </script>

    [...]


    --
    Rob
     
    RobG, Aug 4, 2005
    #2
    1. Advertising

  3. JavaScriptRocks

    Kingstonian Guest

    Thanks for the reply.

    I am actually a beginner in JavaScript DOM scripting. Was putting
    together some scripts found on internet and making them to work in the
    way I want (my way of expanding my knowledge of JavaScript).

    After reading your reply, I feel that I have failed to convey my aim in
    my posting. I am actually trying to mimic the gmail's attachment GUi
    element. If you look at it, in IE, it doesnt show the actual browse
    button, instead it just shows the file name that you have added, along
    with a remove link. I wanted to mimic it exactly. Thats why I had to
    put those if(document.all) checkings.

    I need some time to put together the changes that you have suggested
    and will post the resulting code.


    RobG wrote:
    > JavaScriptRocks wrote:
    > > I've been trying to imitate / reverse engineer the add attachment
    > > feature in gmail composer. I managed to do it to say about 80% but its
    > > giving me trouble in IE on WinXP-Sp2. I am using PHP to do the upload.
    > > It works well on Firefox/DeerPark, but in IE, the file selected just
    > > vanishes. You can verify it by commenting the lines marked "//IE
    > > Trouble". Commenting those lines will remove IE specific code, except
    > > the el.click() whick sends the Click event to the newly added file
    > > upload input element.
    > >
    > >
    > > Please someone help me.
    > >
    > >
    > > _________________________
    > > Here is the code
    > > -------------------------
    > > <?
    > > include_once('../modules/file_­upload/lib_upload.php');
    > > ?>
    > >
    > > <script language="JavaScript">

    >
    > language is depreciated, type is required.
    >
    > >
    > > function Table_AddRow(tblName, pos)
    > > {
    > > if(typeof(pos) == 'undefined')
    > > pos = '_LAST_';
    > >
    > >
    > > var tbl = document.getElementById(tblNam­e);
    > > switch(pos)
    > > {
    > > case '_LAST_':
    > > pos = tbl.rows.length;
    > > default:
    > > pos = parseInt(pos, 10);
    > > if(isNaN(pos))
    > > {
    > > pos = 0;
    > > }
    > > else if (pos > tbl.rows.length)
    > > {
    > > pos = tbl.rows.length;
    > > }
    > > }

    >
    > That appears to be an inordinate amount of code just to check 'pos'.
    > Given that you pass 'pos' from your own code, how about:
    >
    > function Table_AddRow(tblName, pos) {
    > var tbl = document.getElementById(tblNam­e);
    > var rlen = tbl.length;
    > if ( pos > rlen || pos < 0 ) pos = -1;
    >
    > If 'pos' is not a valid index to the table, it will be set to -1 so that
    > the new row will be appended as the last row (which is what I think
    > your code is doing). I would also guess that any feature testing for
    > getElementById) is done up front before the rest of the script is attempted.
    >
    > >
    > > var today = new Date();
    > > var rowID = tblName + today.getTime() + tbl.rows.length;
    > >
    > > var row = tbl.insertRow(pos);
    > > if(document.all) row.style.display = 'none';
    > > //IE Trouble

    >
    > What is the point of testing document.all? If you want to see if the
    > style object is supported, test that:
    >
    > if ( row.style) row.style.display = 'none';
    >
    > It would also be better to do it once and deal with it once.
    >
    > > var cellRight = row.insertCell(row.length);
    > > cellRight.setAttribute('id', rowID);

    >
    > Simpler to access the cell attributes directly. And since you know that
    > the row has a length of zero (you just created it):
    >
    > var cellRight = row.insertCell(0);
    > cellRight.id = rowID;
    >
    > Which makes me think 'rowID' should be 'cellID'.
    >
    > >
    > >
    > > var el = document.createElement('input'­);
    > > el.setAttribute('type', 'FILE');
    > > el.setAttribute('name', 'upload_files[]');

    >
    > accessing attribute directly is simpler:
    >
    > el.type = 'file';
    > el.name = 'upload_files[]';
    >
    > > if(document.all) el.style.display = 'none';
    > > //IE Trouble
    > > cellRight.appendChild(el);
    > >
    > > if(document.all)
    > > {
    > > //IE Trouble
    > > el.click();

    >
    > el is type 'file', which does not have a 'click' method:
    >
    > <URL:http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-2651361>
    >
    > > if(el.value == '')
    > > //IE Trouble
    > > {
    > > //IE Trouble
    > > DeleteCurRow(row);

    >
    > Where is 'DeleteCurRow' defined?
    >
    > > //IE Trouble
    > > }
    > > //IE Trouble
    > > else
    > > //IE Trouble
    > > {
    > > //IE Trouble
    > > row.style.display = '';
    > > //IE Trouble
    > > var fn = document.createElement("strong­");
    > > //IE Trouble
    > > fn.innerHTML = el.value;
    > > //IE Trouble
    > > cellRight.appendChild(fn);

    >
    > Mixing of DOM methods with innerHTML can be unreliable - it is likely
    > better to use one or the other. Since tables are involved, say stick to
    > DOM:
    >
    > fn.appendChild(document.createTextNode( el.value ));
    > cellRight.appendChild(fn);
    >
    > > //IE Trouble
    > > }
    > > //IE Trouble
    > > }
    > > var spc = document.createElement("span")­;
    > > spc.innerHTML = "&nbsp;";

    >
    > Same here:
    >
    > spc.appendChild(document.createTextNode('\u00A0'));
    >
    > where \u00A0 will insert a non-breaking space.
    >
    > > cellRight.appendChild(spc);
    > >
    > >
    > > var aa = document.createElement("a");
    > > aa.setAttribute('href', 'javascript:;');
    > > var clickName = new
    > > Function("Table_DeleteRowByID(­'"+tblName+"','"+rowID+"')");
    > > aa.onclick = clickName;

    >
    > You start using the javascript pseudo protocol in the HREF attribute
    > then use an onclick. Why use an 'a' element at all? Why not a span
    > with an onclick or an input button?
    >
    > You may also be having issues with closures here with references to
    > tblName and rowID (I didn't test it but it seems likely).
    >
    > You could use (see below):
    >
    > aa.onclick = function() { Table_DeleteRowByID( rowID ); }
    >
    > Provided the issue with closure is dealt with.
    >
    > > aa.innerHTML = "remove";

    >
    > aa.appendChild(document.createTextNode('remove'));
    >
    > > cellRight.appendChild(aa);
    > > }
    > >
    > >
    > > function Table_DeleteRow(x)
    > > {
    > > while (x.tagName.toLowerCase() !='tr')
    > > {
    > > if(x.parentElement)
    > > x=x.parentElement;
    > > else if(x.parentNode)
    > > x=x.parentNode;
    > > else
    > > return;

    >
    > More efficient:
    > while ( x.parentNode && 'tr' != x.nodeName.toLowerCase() ) {
    > x = x.parentNode;
    > }
    >
    > > }
    > > var rowNum=x.rowIndex;
    > > while (x.tagName.toLowerCase() !='table')
    > > {
    > > if(x.parentElement)
    > > x=x.parentElement;
    > > else if(x.parentNode)
    > > x=x.parentNode;
    > > else
    > > return;
    > > }
    > > x.deleteRow(rowNum);
    > >

    >
    > All of the above can be replaced with:
    >
    > if ( 'tr' == x.nodeName.toLowerCase() ) {
    > x.parentNode.removeChild( x );
    > }
    >
    > But this function is not used anyway.
    >
    > >
    > > }
    > >
    > >
    > > function Table_DeleteRowByIndex(tblName­, row)
    > > {
    > > var tbl = document.getElementById(tblNam­e);
    > > x.deleteRow(row);
    > >
    > >
    > > }

    >
    > Does not appear to be used.
    >
    > >
    > >
    > > function Table_DeleteRowByID(tblName, rowID)
    > > {
    > > var tbl = document.getElementById(tblNam­e);
    > > var row = document.getElementById(rowID)­;
    > > while (row.tagName.toLowerCase() !='tr')
    > > {
    > > if(row.parentElement)
    > > row = row.parentElement;
    > > else if(row.parentNode)
    > > row = row.parentNode;
    > > else
    > > return;
    > > }
    > > var rowNum = row.rowIndex;
    > > tbl.deleteRow(rowNum);
    > >
    > >
    > > }

    >
    > Presuming you want to delete the row with a particular ID, then the
    > above can be replaced with:
    >
    > function Table_DeleteRowByID( rowID ) {
    > var row = document.getElementById( rowID );
    > if ( row ) row.parentNode.removeChild( row );
    > }
    >
    > Which can be used as a generic method to delete any element with an id:
    >
    > function deleteElementById( elID ) {
    > var el = document.getElementById( elID );
    > if ( el ) el.parentNode.removeChild( el );
    > }
    >
    >
    > >
    > >
    > > </script>

    > [...]
    >
    >
    > --
    > Rob
     
    Kingstonian, Aug 4, 2005
    #3
  4. JavaScriptRocks

    Kingstonian Guest

    Many Thanks RobG

    I have updated the code with your suggestions.
    But its still not working the way I want it to.

    As you had said,
    > el is type 'file', which does not have a 'click' method:


    but how Gmail does it??!! Thats what I want.
    Here in this case, it accepts the click() event but it acts funny.

    __________________________________________

    <?
    include_once('lib_upload.php');
    ?>
    <SCRIPT type="text/javascript">

    function DynUploads_Add(tblName, pos)
    {
    var tbl = document.getElementById(tblName);
    var rowLen = tbl.rows.length;

    pos = parseInt(pos, 10);
    pos = (pos >= 0 || pos < rowLen)? pos: pos = -1;

    var today = new Date();
    var uploadID = tblName + today.getTime() + tbl.rows.length;

    var row = tbl.insertRow(pos);
    // cosmetic: specific to IE - Hide row till user selects a file
    if(document.all) row.style.display = 'none';

    var cellRight = row.insertCell(row.length);
    cellRight.id = uploadID;

    var el = document.createElement('input');
    el.type = 'FILE';
    el.name = 'upload_files[]';
    // cosmetic: specific to IE - Hide control for ever, Gmail style
    if(document.all) el.style.display = 'none';

    cellRight.appendChild(el);

    // cosmetic: specific to IE
    // Instead of the text box and Browse button of the upload form
    element
    // hide the form element and show its value.
    if(document.all)
    {
    el.click();
    if(el.value == '')
    {
    DeleteCurRow(row);
    }
    else
    {
    row.style.display = '';
    var fn = document.createElement("strong");
    fn.appendChild(document.createTextNode( el.value ));
    cellRight.appendChild(fn);
    }
    }

    // cosmetic: just for space
    cellRight.appendChild(document.createTextNode('\u00A0'));

    var aa = document.createElement("a");
    aa.href = 'javascript:;';
    aa.onclick = function() { DynUploads_DeleteByID(tblName, uploadID); };
    aa.appendChild(document.createTextNode('remove'));
    cellRight.appendChild(aa);
    }

    function DynUploads_Delete(x)
    {
    while ( x.parentNode && 'tr' != x.nodeName.toLowerCase() ) {
    x = x.parentNode;
    }

    if ( 'tr' == x.nodeName.toLowerCase() ) {
    x.parentNode.removeChild( x );
    }
    }

    function DynUploads_DeleteByIndex(tblName, row)
    {
    var tbl = document.getElementById(tblName);
    x.deleteRow(row);
    }

    function DynUploads_DeleteByID(tblName, uploadID)
    {
    var row = document.getElementById(uploadID);
    if(row) row.parentNode.removeChild(row);
    }

    </script>

    <form method="post" enctype="multipart/form-data">
    <table id="tblSample" border="0" cellspacing="2" cellpadding="2">
    <tr id="tblSample_row0">
    <td><a href="javascript:;" onClick="DynUploads_Add('tblSample', 1);
    return false;">Add File</a></td>
    </tr></table><input type="hidden" name="MAX_FILE_SIZE"
    value="512000"><input type=submit>
    </form>
     
    Kingstonian, Aug 7, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rastislav Struharik

    Reverse engineering an EDIF file?

    Rastislav Struharik, Nov 10, 2003, in forum: VHDL
    Replies:
    8
    Views:
    7,997
    Joonas Timo Taavetti Kekoni
    Jan 2, 2004
  2. =?Utf-8?B?ZHdvcnRoZW0=?=

    Reverse Engineering-Page Navigation Diagram

    =?Utf-8?B?ZHdvcnRoZW0=?=, Sep 25, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    595
    =?Utf-8?B?ZHdvcnRoZW0=?=
    Sep 25, 2004
  3. Replies:
    0
    Views:
    873
  4. Replies:
    0
    Views:
    630
  5. JavaScriptRocks

    Gmail - Add Attachments - Reverse Engineering

    JavaScriptRocks, Aug 3, 2005, in forum: Javascript
    Replies:
    0
    Views:
    96
    JavaScriptRocks
    Aug 3, 2005
Loading...

Share This Page