<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-29877930</id><updated>2012-01-11T05:59:54.852-08:00</updated><category term='javascript invalid range in character class error console Firebug'/><category term='php validate email addresses filter_var FILTER_VALIDATE_EMAIL'/><category term='copy text to clipboard javascript flash 10 zero clipboard jhuckaby instantiate multiple copy button instances'/><category term='Balabolka text-to-speech TTS engine screen text readers Windows OS'/><category term='speed up torrent peer to peer p2p downloads windows 7 vista xp tcpip.sys lvllord.de'/><category term='gmail strikethrough greasemonkey chrome firefox'/><category term='failed to find flength file error uber-uploader'/><category term='firefox aggressive caching development servers JavaScript CSS'/><category term='gzip g-zip compression php text-based files 1and1 shared hosting'/><category term='Microsoft Windows IMAP migrate email Gmail to Gmail including chats'/><category term='compress g-zip gzip cspan perl cgi-scripts 1and1 shared hosting'/><category term='JavaScript createContextualFragment MSIE9 IE9 Internet Explorer 9 range'/><category term='getting setting class attribute classname internet explorer ie getattribute setattribute javascript cross-browser'/><category term='javasscript range selection getselection preserve html clonecontents'/><category term='XML EntityRef php htmlspecialchars javascript error solved HTMLentities HTML entities reserved xml name'/><category term='easily compress minify combine javascript css http requests 1and1 shared servers hosting speed up page loads'/><category term='xupload'/><category term='javascript fade animation object-oriented class-based this keyword'/><category term='Google Chrome FirePHP ChromePHP add-on extension debug PHP Python'/><category term='ajax throbbers spinners web 2.0 ajaxload.info status progress indicator'/><category term='unblock .chm help file won&apos;t open windows vista xp navigation to the webpage was canceled'/><category term='javascript python interactive shell jsfiddle firebug variable hoisting php cross-training'/><category term='Gregwired CamStudio YouTube synching audio and video Any Video Converter'/><category term='chmod'/><category term='ad redirection imediablast rouge sites annoyances'/><category term='Mac OSX IMAP migrate email Gmail to Gmail including chats'/><category term='mootools moo tools element constructors instantiation adoption JavaScript'/><category term='minify html php strip whitespace ob_start ob_end_flush linux'/><title type='text'>mrrena</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-29877930.post-1410412886415725589</id><published>2011-10-30T17:43:00.000-07:00</published><updated>2011-11-13T15:40:28.325-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft Windows IMAP migrate email Gmail to Gmail including chats'/><title type='text'>How to migrate mail from one Gmail account to another on Windows, including Chats</title><content type='html'>&lt;br /&gt;&lt;h4 style="margin-bottom: 1.0em;"&gt;This is the Microsoft Windows version of this article (though it contains screen shots from Mac). The Mac OSX version can &lt;a href="http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail.html"&gt;be found here&lt;/a&gt;.&lt;/h4&gt;Recently &lt;a href="http://www.iws-web.com/" target="_blank"&gt;at work&lt;/a&gt;, we got a new Gmail domain and had to switch from one Gmail account to another.&lt;br /&gt;&lt;br /&gt;You can migrate your mail easily &lt;a href="http://lifehacker.com/352401/migrate-all-your-old-gmail-to-a-new-gmail-address" target="_blank" title="http://lifehacker.com/352401/migrate-all-your-old-gmail-to-a-new-gmail-address"&gt;using POP3&lt;/a&gt;, but POP3 won't get your chats or preserve your labels. The superior solution is IMAP, even if it's a little more cumbersome. And even if you have already migrated using POP3, IMAP will still allow you to retrieve your chats and work for you on a tag-by-tag basis.&lt;br /&gt;&lt;br /&gt;IMAP requires bit of a work-around—you must first fully download all your files to your machine, and only then can you migrate them back again into your new Gmail account.&lt;br /&gt;&lt;br /&gt;Here's everything you need to get set up.&lt;br /&gt;&lt;br /&gt;First, the downloads.&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Download &lt;a href="http://www.mozilla.org/en-US/thunderbird/download/?product=thunderbird-7.0.1" target="_blank" title="http://www.mozilla.org/en-US/thunderbird/download/?product=thunderbird-7.0.1"&gt;Mozilla Thunderbird&lt;/a&gt; and install on your machine.&lt;/li&gt;&lt;li&gt;Download and unzip the &lt;a href="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/" target="_blank" title="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/"&gt;toIMAP files&lt;/a&gt; (we'll set these up later)&lt;/li&gt;&lt;/ol&gt;Now log in to your usual (old) Gmail account.&lt;br /&gt;&lt;br /&gt;Then:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Click the gear icon in the upper-right corner and select &lt;b&gt;Mail settings&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s1600/migrate1_gear.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s1600/migrate1_gear.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; Click the &lt;b&gt;Forwarding and POP/IMAP&lt;/b&gt; tab, scroll down to &lt;b&gt;IMAP Access&lt;/b&gt;, and make sure it is turned on:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Zda2pjprhC4/Tq3aGcqWMgI/AAAAAAAAAVw/6Y59Aq9undU/s1600/Gmail_IMAP_settings.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Zda2pjprhC4/Tq3aGcqWMgI/AAAAAAAAAVw/6Y59Aq9undU/s320/Gmail_IMAP_settings.png" width="420" height="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; Click &lt;b&gt;Labels&lt;/b&gt; and make sure that &lt;b&gt;Chats&lt;/b&gt; and any other labels you want migrated are checked. (&lt;b&gt;Note:&lt;/b&gt; If you already used the POP3 solution, you might want to limit only to &lt;b&gt;Chats&lt;/b&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-u5a5hkp4g2U/Tq3aMgqwF1I/AAAAAAAAAWQ/In37Rx4nrlA/s1600/migrate1_labels.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-u5a5hkp4g2U/Tq3aMgqwF1I/AAAAAAAAAWQ/In37Rx4nrlA/s320/migrate1_labels.png" width="420" height="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt; Open Thunderbird, click &lt;b&gt;Create a new account&lt;/b&gt; and use the address you want to pull the mail from, then click &lt;b&gt;Continue&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ZaIbWYzZghg/Tq3aQghlUQI/AAAAAAAAAWg/V45YD4wpelg/s1600/migrate1_thunderbird1.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-ZaIbWYzZghg/Tq3aQghlUQI/AAAAAAAAAWg/V45YD4wpelg/s320/migrate1_thunderbird1.png" width="420" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; The wizard should smartly detect the proper settings; if not, you can click &lt;b&gt;Manual config&lt;/b&gt; and enter the IMAP and SMTP settings shown below:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MoR52dYpWdg/Tq3aR8if2YI/AAAAAAAAAWo/5ta-2iJp2DY/s1600/migrate1_thunderbird2.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="245" src="http://2.bp.blogspot.com/-MoR52dYpWdg/Tq3aR8if2YI/AAAAAAAAAWo/5ta-2iJp2DY/s320/migrate1_thunderbird2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;5.&lt;/b&gt; Click &lt;b&gt;Create Account&lt;/b&gt; and let Thunderbird start downloading; this may take hours, and it goes without saying that the more mail you have, the longer the process will be. If you have to shut down for a while, to easily restart where you left off, just open Thunderbird, right-click, and click &lt;b&gt;Get Messages&lt;/b&gt; in the context menu:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-OrpgEZOFBck/Tq3aTVpIvcI/AAAAAAAAAWw/o5CHEaCGaZU/s1600/migrate1_thunderbird3.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-OrpgEZOFBck/Tq3aTVpIvcI/AAAAAAAAAWw/o5CHEaCGaZU/s320/migrate1_thunderbird3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt; Log in to your new account and repeat steps 1 and 2 above for it. Make sure that you re-create any custom labels you used in your old account:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Rf-vgmS_2T0/Tq3aHkP8BOI/AAAAAAAAAV4/MUSdLfOztXg/s1600/migrate1_create_labels.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Rf-vgmS_2T0/Tq3aHkP8BOI/AAAAAAAAAV4/MUSdLfOztXg/s1600/migrate1_create_labels.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now... go find something else to do for a few hours and come back to step 7 after Thunderbird (eventually) finishes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7.&lt;/b&gt; Yay! Your e-mail finally downloaded! Rejoicing, right-click your account name, and click &lt;b&gt;Settings&lt;/b&gt; (last option in the screen shot for step 5). Navigate to &lt;b&gt;Server Settings&lt;/b&gt;, and copy the &lt;b&gt;Local directory&lt;/b&gt; path at the bottom.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-YeFUanAa1b4/Tq3aVd4_wJI/AAAAAAAAAW4/Qti-ghcN7Cg/s1600/migrate1_thunderbird4.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-YeFUanAa1b4/Tq3aVd4_wJI/AAAAAAAAAW4/Qti-ghcN7Cg/s320/migrate1_thunderbird4.png" width="420" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;8.&lt;/b&gt; Open a new folder, and paste this address in the location bar. Keep this window open, as you'll need it for the following steps:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-gHffh_KrlKE/Tq3aPCnvR3I/AAAAAAAAAWY/jNLBivx46fY/s1600/migrate1_mail_folders.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-gHffh_KrlKE/Tq3aPCnvR3I/AAAAAAAAAWY/jNLBivx46fY/s320/migrate1_mail_folders.png" width="442" height="279" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;9.&lt;/b&gt; Go to &lt;b&gt;Start &gt; All Programs &gt; Accessories &gt; Notepad&lt;/b&gt; and start the program. Use it to open the &lt;tt&gt;toIMAP.cfg&lt;/tt&gt; file in the &lt;tt&gt;toIMAP&lt;/tt&gt; folder you downloaded to your Desktop. Make sure your configuration file is set up like the one below, subbing in your username and password:&lt;br /&gt;&lt;pre class="code js"&gt;{&lt;br /&gt;     'host'&amp;nbsp;: 'imap.googlemail.com',&lt;br /&gt;     'user':'YOU@gmail.com',&lt;br /&gt;     'password':'YOURPASSWORD',&lt;br /&gt;     'ssl': True&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;10.&lt;/b&gt; Save the file and close it. Your configuration file is now set; all that is left is to run the file.&lt;br /&gt;&lt;br /&gt;Go to your Windows Start menu and type &lt;tt&gt;cmd.exe&lt;/tt&gt; in the search box, pressing ENTER. The Windows command-line prompt will open.&lt;br /&gt;&lt;br /&gt;You'll need to be at the same level as the file; for Microsoft Vista, the path would be (where "YOU" is your username): &lt;tt&gt;C:\Users\YOU\Desktop\toIMAP&lt;/tt&gt;. To do this, you'll need to change directories (&lt;tt&gt;cd&lt;/tt&gt;) into the folder on your desktop:&lt;br /&gt;&lt;pre class="code js"&gt;cd C:\Users\YOU\Desktop\toIMAP&lt;/pre&gt;To run the uploader script, you'll use the following convention while still sitting at the level in step 9: &lt;pre class="code js"&gt;toIMAP.exe -m path_i_just_copied/FOLDER_NAME -f FOLDER_NAME&lt;br /&gt;&lt;/pre&gt;For example, if I want to upload the folder "admin stuff" (shown in step 8), I would type (surrounding my file path with quotation marks to bypass the space between "admin" and "stuff"):&lt;br /&gt;&lt;pre class="code js"&gt;toIMAP.exe -m "C:\Users\YOU\AppData\Roaming\Thunderbird\Profiles\76sexgps.default\ImapMail\imap.googlemail.com\admin stuff" -f "admin stuff"&lt;br /&gt;&lt;/pre&gt;Some Gmail flags like &lt;b&gt;Starred&lt;/b&gt; may need to omit the &lt;tt&gt;-f "admin stuff"&lt;/tt&gt; part.&lt;br /&gt;&lt;br /&gt;To specify a different Gmail tag than the name of the Thunderbird folder, just pass &lt;tt&gt;-f&lt;/tt&gt; the new name, making sure that the tag already exists in your new account per step 6.&lt;br /&gt;&lt;br /&gt;For example, to move your chats, you will not be able to use the same "Chats" name for your tag as that is reserved by Google. You'll need to create a new tag in your new account&amp;#8212;I used "Archived Chats"&amp;#8212;then import using the additional &lt;tt&gt;-f&lt;/tt&gt; flag:&lt;pre class="code js"&gt;toIMAP.exe -m "C:\Users\YOU\AppData\Roaming\Thunderbird\Profiles\76sexgps.default\ImapMail\imap.googlemail.com\[Gmail].sbd\Chats" -f "Archived Chats"&lt;/pre&gt;If your upload gets interrupted at any point, see the &lt;a href="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/" target="_blank" title="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/"&gt;toIMAP directions&lt;/a&gt; on how to resume where you left off.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;11.&lt;/b&gt; Repeat step 10 for as many folders as you need to migrate. Once you have gone through every folder you want backed up, you're done. Bliss is yours.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-1410412886415725589?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/1410412886415725589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail_30.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1410412886415725589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1410412886415725589'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail_30.html' title='How to migrate mail from one Gmail account to another on Windows, including Chats'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s72-c/migrate1_gear.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-9012759347192230148</id><published>2011-10-30T17:01:00.000-07:00</published><updated>2011-11-15T16:15:08.063-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mac OSX IMAP migrate email Gmail to Gmail including chats'/><title type='text'>How to migrate mail from one Gmail account to another on Mac OSX, including Chats</title><content type='html'>&lt;br /&gt;&lt;h4 style="margin-bottom: 1.5em;"&gt;This is the Mac OSX version of this article. The Windows version can &lt;a href="http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail_30.html"&gt;be found here&lt;/a&gt;.&lt;/h4&gt;Recently &lt;a href="http://www.iws-web.com/" target="_blank"&gt;at work&lt;/a&gt;, we got a new Gmail domain and had to switch from one Gmail account to another.&lt;br /&gt;&lt;br /&gt;You can migrate your mail easily &lt;a href="http://lifehacker.com/352401/migrate-all-your-old-gmail-to-a-new-gmail-address" target="_blank" title="http://lifehacker.com/352401/migrate-all-your-old-gmail-to-a-new-gmail-address"&gt;using POP3&lt;/a&gt;, but POP3 won't get your chats or preserve your labels. The superior solution is IMAP, even if it's a little more cumbersome. And even if you have already migrated using POP3, IMAP will still allow you to retrieve your chats and work for you on a tag-by-tag basis.&lt;br /&gt;&lt;br /&gt;IMAP requires bit of a work-around—you must first fully download all your files to your machine, and only then can you migrate them back again into your new Gmail account.&lt;br /&gt;&lt;br /&gt;Here's everything you need to get set up.&lt;br /&gt;&lt;br /&gt;First, the downloads.&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Download the &lt;a href="http://www.mozilla.org/en-US/thunderbird/download/?product=thunderbird-7.0.1&amp;amp;os=osx&amp;amp;lang=en-US" target="_blank" title="http://www.mozilla.org/en-US/thunderbird/download/?product=thunderbird-7.0.1&amp;amp;os=osx&amp;amp;lang=en-US"&gt;Mac edition of Mozilla Thunderbird&lt;/a&gt; and install on your machine.&lt;/li&gt;&lt;li&gt;Download and untar the &lt;a href="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/" target="_blank" title="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/"&gt;toIMAP files&lt;/a&gt; (we'll set these up later)&lt;/li&gt;&lt;/ol&gt;Now log in to your usual (old) Gmail account.&lt;br /&gt;&lt;br /&gt;Then:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Click the gear icon in the upper-right corner and select &lt;b&gt;Mail settings&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s1600/migrate1_gear.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s1600/migrate1_gear.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; Click the &lt;b&gt;Forwarding and POP/IMAP&lt;/b&gt; tab, scroll down to &lt;b&gt;IMAP Access&lt;/b&gt;, and make sure it is turned on:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Zda2pjprhC4/Tq3aGcqWMgI/AAAAAAAAAVw/6Y59Aq9undU/s1600/Gmail_IMAP_settings.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-Zda2pjprhC4/Tq3aGcqWMgI/AAAAAAAAAVw/6Y59Aq9undU/s320/Gmail_IMAP_settings.png" width="420" height="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; Click &lt;b&gt;Labels&lt;/b&gt; and make sure that &lt;b&gt;Chats&lt;/b&gt; and any other labels you want migrated are checked. (&lt;b&gt;Note:&lt;/b&gt; If you already used the POP3 solution, you might want to limit only to &lt;b&gt;Chats&lt;/b&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-u5a5hkp4g2U/Tq3aMgqwF1I/AAAAAAAAAWQ/In37Rx4nrlA/s1600/migrate1_labels.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-u5a5hkp4g2U/Tq3aMgqwF1I/AAAAAAAAAWQ/In37Rx4nrlA/s320/migrate1_labels.png" width="420" height="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt; Open Thunderbird, click &lt;b&gt;Create a new account&lt;/b&gt; and use the address you want to pull the mail from, then click &lt;b&gt;Continue&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ZaIbWYzZghg/Tq3aQghlUQI/AAAAAAAAAWg/V45YD4wpelg/s1600/migrate1_thunderbird1.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-ZaIbWYzZghg/Tq3aQghlUQI/AAAAAAAAAWg/V45YD4wpelg/s320/migrate1_thunderbird1.png" width="420" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; The wizard should smartly detect the proper settings; if not, you can click &lt;b&gt;Manual config&lt;/b&gt; and enter the IMAP and SMTP settings shown below:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MoR52dYpWdg/Tq3aR8if2YI/AAAAAAAAAWo/5ta-2iJp2DY/s1600/migrate1_thunderbird2.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="245" src="http://2.bp.blogspot.com/-MoR52dYpWdg/Tq3aR8if2YI/AAAAAAAAAWo/5ta-2iJp2DY/s320/migrate1_thunderbird2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;5.&lt;/b&gt; Click &lt;b&gt;Create Account&lt;/b&gt; and let Thunderbird start downloading; this may take hours, and it goes without saying that the more mail you have, the longer the process will be. If you have to shut down for a while, to easily restart where you left off, just open Thunderbird, right-click, and click &lt;b&gt;Get Messages&lt;/b&gt; in the context menu:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-OrpgEZOFBck/Tq3aTVpIvcI/AAAAAAAAAWw/o5CHEaCGaZU/s1600/migrate1_thunderbird3.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-OrpgEZOFBck/Tq3aTVpIvcI/AAAAAAAAAWw/o5CHEaCGaZU/s320/migrate1_thunderbird3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt; Log in to your new account and repeat steps 1 and 2 above for it. Make sure that you re-create any custom labels you used in your old account:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Rf-vgmS_2T0/Tq3aHkP8BOI/AAAAAAAAAV4/MUSdLfOztXg/s1600/migrate1_create_labels.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Rf-vgmS_2T0/Tq3aHkP8BOI/AAAAAAAAAV4/MUSdLfOztXg/s1600/migrate1_create_labels.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now... go find something else to do for a few hours and come back to step 7 after Thunderbird (eventually) finishes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7.&lt;/b&gt; Yay! Your e-mail finally downloaded! Rejoicing, right-click your account name, and click &lt;b&gt;Settings&lt;/b&gt; (last option shown in the screen shot for step 5). Navigate to &lt;b&gt;Server Settings&lt;/b&gt;, and copy the &lt;b&gt;Local directory&lt;/b&gt; path at the bottom.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-YeFUanAa1b4/Tq3aVd4_wJI/AAAAAAAAAW4/Qti-ghcN7Cg/s1600/migrate1_thunderbird4.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-YeFUanAa1b4/Tq3aVd4_wJI/AAAAAAAAAW4/Qti-ghcN7Cg/s320/migrate1_thunderbird4.png" width="420" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;8.&lt;/b&gt; Open Finder, and select &lt;b&gt;Go &amp;gt; Go To Folder&lt;/b&gt;, then paste the path you just copied. Keep this window open, as you'll need it for the following steps:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-FH1MgSJjnjo/Tq3aJ6DLSaI/AAAAAAAAAWA/XeRQc5SKIck/s1600/migrate1_finder.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="206" src="http://2.bp.blogspot.com/-FH1MgSJjnjo/Tq3aJ6DLSaI/AAAAAAAAAWA/XeRQc5SKIck/s320/migrate1_finder.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-gHffh_KrlKE/Tq3aPCnvR3I/AAAAAAAAAWY/jNLBivx46fY/s1600/migrate1_mail_folders.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-gHffh_KrlKE/Tq3aPCnvR3I/AAAAAAAAAWY/jNLBivx46fY/s320/migrate1_mail_folders.png" width="442" height="279" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;9.&lt;/b&gt; Open a new terminal window and type the following lines on your Mac:&lt;br /&gt;&lt;pre class="code js"&gt;cd ~/Desktop/toIMAP&lt;br /&gt;vim toIMAP.cfg&lt;br /&gt;i&lt;br /&gt;&lt;/pre&gt;The "i" puts you in insert mode; make sure your configuration file is set up like the one below, subbing in your username and password:&lt;br /&gt;&lt;pre class="code js"&gt;{&lt;br /&gt;     'host'&amp;nbsp;: 'imap.googlemail.com',&lt;br /&gt;     'user':'YOU@gmail.com',&lt;br /&gt;     'password':'YOURPASSWORD',&lt;br /&gt;     'ssl': True&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Then press ESC to exit insert mode, and type:&lt;br /&gt;&lt;pre class="code js"&gt;:wq!&lt;br /&gt;&lt;/pre&gt;to write and quit (save and exit) your configuration file.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;10.&lt;/b&gt; Your configuration file is set; now all that is left is to run the file. Unfortunately, it does not appear that the script is smart enough to parse all folders at once, so you'll need to parse a single folder at a time, hence the opened Finder window in step 8 so you can reference each of your mail folders.&lt;br /&gt;&lt;br /&gt;To run the file, you'll use the following convention while still sitting at the level in step 9:&lt;br /&gt;&lt;pre class="code js"&gt;python toIMAP.py -m path_i_just_copied/FOLDER_NAME -f FOLDER_NAME&lt;br /&gt;&lt;/pre&gt;For example, if I want to upload the folder "admin stuff" (shown in step 8), I would type (using a backslash to escape the space between "admin" and "stuff"):&lt;br /&gt;&lt;pre class="code js"&gt;python toIMAP.py -m ~/Library/Thunderbird/Profiles/76sexgps.default/ImapMail/imap.googlemail.com/admin\ stuff -f "admin stuff"&lt;br /&gt;&lt;/pre&gt;Some Gmail flags like Starred may need to omit the &lt;tt&gt;-f "admin stuff"&lt;/tt&gt; part.&lt;br /&gt;&lt;br /&gt;To specify a different Gmail tag than the name of the Thunderbird folder, just pass &lt;tt&gt;-f&lt;/tt&gt; the new name, making sure that the tag already exists in your new account per step 5.&lt;br /&gt;&lt;br /&gt;For example, to move your chats, you will not be able to use the same "Chats" name for your tag as that is reserved by Google. You'll need to create a new tag in your new account&amp;#8212;I used "Archived Chats"&amp;#8212;then import using the additional &lt;tt&gt;-f&lt;/tt&gt; flag:&lt;pre class="code js"&gt;python toIMAP.py -m ~/Library/Thunderbird/Profiles/76sexgps.default/ImapMail/imap.googlemail.com/[Gmail].sbd/Chats -f "Archived Chats"&lt;/pre&gt;If your upload gets interrupted at any point, see the &lt;a href="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/" target="_blank" title="http://www.swampgas.com/index.php/tools/togmail-export-thunderbird-mailboxes-into-gmail/"&gt;toIMAP directions&lt;/a&gt; on how to resume where you left off.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;11.&lt;/b&gt; Repeat step 10 for as many folders as you need to migrate. Once you have gone through every folder you want backed up, you're done. Bliss is yours.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-9012759347192230148?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/9012759347192230148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9012759347192230148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9012759347192230148'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/10/how-to-migrate-mail-from-one-gmail.html' title='How to migrate mail from one Gmail account to another on Mac OSX, including Chats'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-romOKJFuqM8/Tq3aK-yBgtI/AAAAAAAAAWI/Da2WBCPibWw/s72-c/migrate1_gear.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-1074060702461741463</id><published>2011-10-02T08:52:00.000-07:00</published><updated>2011-10-02T13:52:21.693-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php validate email addresses filter_var FILTER_VALIDATE_EMAIL'/><title type='text'>PHP: Simple and Effective Way to Validate Email Addresses</title><content type='html'>&lt;br /&gt;There are a number of regular expression solutions that have been written to test the validity of user-entered email addresses in PHP, some of them quite good. However, the most consistent and reliable way to validate email addresses takes advantage of PHP's built-in functionality.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://php.net/manual/en/function.filter-var.php" target="_blank"&gt;&lt;tt&gt;filter_var&lt;/tt&gt;&lt;/a&gt; does just what it says: it filters a variable using a variety of pre-defined filters (see &lt;a href="http://www.php.net/manual/en/filter.filters.php" target="_blank"&gt;the complete list of filters categorized by type&lt;/a&gt;); when you are validating email addresses, the filter you want is &lt;tt&gt;FILTER_VALIDATE_EMAIL&lt;/tt&gt;:&lt;br /&gt;&lt;pre class="code js"&gt;&lt;br /&gt;if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {&lt;br /&gt;     exit('E-mail is not valid.');&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-1074060702461741463?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/1074060702461741463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/10/php-simple-and-effective-way-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1074060702461741463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1074060702461741463'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/10/php-simple-and-effective-way-to.html' title='PHP: Simple and Effective Way to Validate Email Addresses'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-8931145114197772355</id><published>2011-08-27T09:57:00.000-07:00</published><updated>2011-10-02T09:04:35.788-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript createContextualFragment MSIE9 IE9 Internet Explorer 9 range'/><title type='text'>Object doesn't support property or method 'createContextualFragment': Solved Internet Exporer 9 JavaScript Error</title><content type='html'>&lt;br /&gt;&lt;b style="color: #c05f04;"&gt;Object doesn't support property or method 'createContextualFragment'&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I use a rich-text editor on my site, and received this JavaScript error when trying to view it on IE9. An easy solution exists, however, which I found in &lt;a href="http://www.sencha.com/forum/showthread.php?125869-Menu-shadow-probolem-in-IE9&amp;p=579336" target="_blank"&gt;a discussion thread&lt;/a&gt;; simply add the following lines of code at the top of your file or before the method where you use &lt;tt&gt;createContextualFragment&lt;/tt&gt; which makes it available to the &lt;tt&gt;Range&lt;/tt&gt; object via prototyping.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code js"&gt;&lt;br /&gt;if ((typeof Range !== 'undefined') &amp;&amp; !Range.prototype.createContextualFragment) {&lt;br /&gt;    Range.prototype.createContextualFragment = function(html) {&lt;br /&gt;        var frag = document.createDocumentFragment(); &lt;br /&gt;        var div = document.createElement('div');&lt;br /&gt;        frag.appendChild(div);&lt;br /&gt;        div.outerHTML = html;&lt;br /&gt;        return frag;&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-8931145114197772355?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/8931145114197772355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/08/object-doesnt-support-property-or.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8931145114197772355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8931145114197772355'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/08/object-doesnt-support-property-or.html' title='Object doesn&apos;t support property or method &apos;createContextualFragment&apos;: Solved Internet Exporer 9 JavaScript Error'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-7021630270695465677</id><published>2011-08-12T22:48:00.000-07:00</published><updated>2011-08-13T19:36:06.889-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google Chrome FirePHP ChromePHP add-on extension debug PHP Python'/><title type='text'>ChromePHP: Google Chrome's PHP Debugging "FirePHP" Extension</title><content type='html'>&lt;br /&gt;&lt;a href="http://getfirebug.com/" target="_blank"&gt;Firebug&lt;/a&gt; is by far the most popular developer's tool for Firefox. &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/firephp/" target="_blank"&gt;FirePHP&lt;/a&gt; is another well-known add-on that allows for debugging PHP. Unquestionably great dev tools.&lt;br /&gt;&lt;br /&gt;Google Chrome's built-in debugger is arguably parallel in features and performance to Firefox's Firebug. A lot of devs like using Chrome, but they don't know that they can also debug their PHP in it as well. An extension called &lt;a href="http://www.chromephp.com/" target="_blank"&gt;ChromePHP&lt;/a&gt; bridges that gap.&lt;br /&gt;&lt;br /&gt;Still haven't heard of any console debuggers for Python in Chrome. Looks like your only choice of a command-line debugger for now is Firefox/Firebug using &lt;a href="http://www.firephp.org/Wiki/Libraries/Python" target="_blank"&gt;FirePy&lt;/a&gt;, though it probably wouldn't take too much work to use Python's &lt;a href="http://docs.python.org/library/logging.html" target="_blank"&gt;built-in logger&lt;/a&gt; to capture and log to the console via JavaScript.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-7021630270695465677?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/7021630270695465677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/08/chromephp-google-chromes-php-debugging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7021630270695465677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7021630270695465677'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/08/chromephp-google-chromes-php-debugging.html' title='ChromePHP: Google Chrome&apos;s PHP Debugging &quot;FirePHP&quot; Extension'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-6202822926657064231</id><published>2011-07-04T10:41:00.000-07:00</published><updated>2011-07-23T17:40:41.734-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript python interactive shell jsfiddle firebug variable hoisting php cross-training'/><title type='text'>JavaScript "Interactive Shell" (like Python) and Variable Hoisting</title><content type='html'>&lt;br /&gt;When I first started working at &lt;a href="http://www.iws-web.com" target="_blank"&gt;IWS&lt;/a&gt;, there were two teams, the front-end or "Interface" team and the back-end or "Systems" team. I was part of the Interface team writing JavaScript; the Systems team wrote Python. We have now gone to a new approach in development, the two teams merging into a single "Engineering" team. Though most of us have written at least some code in both languages, we've been knee-deep in cross-training.&lt;br /&gt;&lt;br /&gt;As part of our cross-training, the new Engineering team has been further divided into "squadrons" of three with team members consisting of both (previous) Python and JavaScript developers working together on small projects. My team includes two Python developers who know relatively little about JavaScript, so the responsibility of catching them up to speed has fallen on my shoulders.&lt;br /&gt;&lt;br /&gt;In working with my two teammates, I mentioned the concept of "hoisting" where variables are lifted to the top of function blocks by the interpreter. I also shared with them the PyCon video &lt;a href="http://ontwik.com/javascript/pycon-2011-javascript-for-people-who-know-python/" target="_blank"&gt;PyCon 2011: Javascript For People Who Know Python&lt;/a&gt; which offers a decent overview of JavaScript for the Python-minded.&lt;br /&gt;&lt;br /&gt;The PyCon video suggested two things I want to mention: first, it suggested that JavaScript's behavior has an undeserved reputation for being unpredictable, and second, in the Q&amp;A there was a question asked about an interactive shell for JavaScript. I'll come back to the former in a moment; regarding the latter, the video didn't mention it, but did you know &lt;a href="http://getfirebug.com/" target="_blank"&gt;Firebug&lt;/a&gt; provides its own interactive shell?&lt;br /&gt;&lt;br /&gt;To use Firebug's "command editor" (as it is called), click the arrow next to the &lt;b&gt;Console&lt;/b&gt; tab, then select &lt;b&gt;Command Editor&lt;/b&gt; from the context menu:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wlndJecmqTY/ThHxIBWwd8I/AAAAAAAAAKw/R8NaywLgdMk/s1600/command_editor.png" imageanchor="1" style="margin-left:1em; margin-bottom:1em" target="_blank"&gt;&lt;img border="0" height="364" width="373" src="http://4.bp.blogspot.com/-wlndJecmqTY/ThHxIBWwd8I/AAAAAAAAAKw/R8NaywLgdMk/s400/command_editor.png" /&gt;&lt;/a&gt;&lt;/div&gt;The command editor offers a side window on the right; simply type or paste raw JavaScript and click &lt;b&gt;Run&lt;/b&gt; to see the results in the console:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Q3H6oMVYbW8/ThHx4tG318I/AAAAAAAAAK4/Sipk8FJEcLU/s1600/in-action.png" imageanchor="1" style="margin-left:1em; margin-right:1em" target="_blank"&gt;&lt;img border="0" height="166" width="524" src="http://1.bp.blogspot.com/-Q3H6oMVYbW8/ThHx4tG318I/AAAAAAAAAK4/Sipk8FJEcLU/s400/in-action.png" target="_blank" /&gt;&lt;/a&gt;&lt;/div&gt;If you don't use Firefox, the MooTools' team has created the excellent &lt;a href="http://jsfiddle.net/" target="_blank"&gt;JSFiddle&lt;/a&gt;, which comes with virtually all the major JS frameworks on board (not just MooTools) and which can be embedded directly in web pages and/or created examples can be saved and linked to: very cool stuff.&lt;br /&gt;&lt;br /&gt;Okay, so now that we have an interaction shell, a large step toward understanding the "unpredictable" nature of JavaScript is to understand fully how hoisting works. I've been writing JavaScript for years now, and I'll have to say that if I was given an exam with the two examples listed at the beginning of &lt;a href="http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting" target="_blank"&gt;JavaScript Scoping and Hoisting&lt;/a&gt;, I would have failed miserably.&lt;br /&gt;&lt;br /&gt;The reason I would have failed is because JavaScript is normally backward to Python or PHP. Defining a private (definition scoped) variable in Python involves nothing more than declaring it in an assignment. If you want it to be global, you have to explicitly use the &lt;tt&gt;global&lt;/tt&gt; keyword, exactly as you do in PHP (except in PHP, a semi-colon is mandatory).&lt;br /&gt;&lt;br /&gt;But in JavaScript, if you want a private variable scoped to the function, you have to use the &lt;tt&gt;var&lt;/tt&gt; keyword. If you omit the &lt;tt&gt;var&lt;/tt&gt; keyword, the variable becomes available globally&amp;#8212;define a variable &lt;i&gt;without&lt;/i&gt; the &lt;tt&gt;var&lt;/tt&gt; keyword anywhere in a script, and it's instantly global. (That said, if you declare a variable using the &lt;tt&gt;var&lt;/tt&gt; keyword outside any functions or classes, it is also global&amp;#8212;we might say that it is "private to the global scope" because though it was declared with the &lt;tt&gt;var&lt;/tt&gt; keyword, it was nevertheless defined globally, outside a containing function or class.)&lt;br /&gt;&lt;br /&gt;With this &lt;tt&gt;var&lt;/tt&gt; / no &lt;tt&gt;var&lt;/tt&gt; knowledge in place, that's why I would have failed an exam with the two examples from the article above: I did not understand &lt;i&gt;exactly&lt;/i&gt; how hoisting worked, and this articles does an excellent job of taking another level of unpredictability out of JavaScript's run-time behavior.&lt;br /&gt;&lt;br /&gt;So, check out &lt;a href="http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting" target="_blank"&gt;JavaScript Scoping and Hoisting&lt;/a&gt; and put the claims to the test: fire up Firebug's command editor or try out &lt;a href="http://jsfiddle.net/" target="_blank"&gt;JSFiddle&lt;/a&gt; and verify for yourself that the results accord with the claims made, then read the rest of the article to see why the results are counter-intuitive, and, ultimately, highly predictable once you understand what's going on under the hood.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-6202822926657064231?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/6202822926657064231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/07/javascript-interactive-shell-like.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/6202822926657064231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/6202822926657064231'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/07/javascript-interactive-shell-like.html' title='JavaScript &quot;Interactive Shell&quot; (like Python) and Variable Hoisting'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-wlndJecmqTY/ThHxIBWwd8I/AAAAAAAAAKw/R8NaywLgdMk/s72-c/command_editor.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-9149208245852948221</id><published>2011-07-04T10:38:00.000-07:00</published><updated>2011-07-05T15:14:32.897-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gmail strikethrough greasemonkey chrome firefox'/><title type='text'>Strikethrough in Gmail: At Long Last! (For Chrome and Firefox)</title><content type='html'>&lt;br /&gt;Gmail has come a long ways since I first started using it. However, one feature that is conspicuously absent is &lt;span class="s"&gt;strikethrough&lt;/span&gt; text, which I often want to use because I'm proofreading someone else's writing and want to show the parts that I recommend deleting.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ed_bBo0b61M/ThH6YVHiq4I/AAAAAAAAALE/JLInZ-Qujk0/s1600/strikethrough.png" imageanchor="1" style="margin-left:1em; margin-right:1em" target="_blank"&gt;&lt;img border="0" height="58" width="524" src="http://3.bp.blogspot.com/-ed_bBo0b61M/ThH6YVHiq4I/AAAAAAAAALE/JLInZ-Qujk0/s400/strikethrough.png" /&gt;&lt;/a&gt;&lt;/div&gt;Now there is a way that I can have my cake and eat it too. If you're using Google Chrome, just click the &lt;b&gt;Install&lt;/b&gt; button at &lt;a href="http://userscripts.org/scripts/show/57725" target="_blank"&gt;Gmail Strikethrough Button&lt;/a&gt;. If you are using Firefox, first install the add-on &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/" target="_blank"&gt;Greasemonkey&lt;/a&gt; (if it isn't already installed), restart, then click &lt;b&gt;Install&lt;/b&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-9149208245852948221?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/9149208245852948221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/07/strikethrough-in-gmail-at-long-last.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9149208245852948221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9149208245852948221'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/07/strikethrough-in-gmail-at-long-last.html' title='Strikethrough in Gmail: At Long Last! (For Chrome and Firefox)'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-ed_bBo0b61M/ThH6YVHiq4I/AAAAAAAAALE/JLInZ-Qujk0/s72-c/strikethrough.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-4741381405105189820</id><published>2011-05-20T22:20:00.000-07:00</published><updated>2011-06-17T19:34:40.114-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Balabolka text-to-speech TTS engine screen text readers Windows OS'/><title type='text'>Balabolka: A Free Text-To-Speech (TTS) Swiss Army Knife for Windows Operating Systems</title><content type='html'>&lt;br /&gt;&lt;h4&gt;Let Your Computer Read to You&lt;/h4&gt;Typically when I'm home, I've set the company Mac aside and fallen back on a wide-screen Windows PC. I've gotten lazy as I've gotten older: I rather like having the computer read things to me I don't necessarily feel like reading myself. :)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.cross-plus-a.com/balabolka.htm" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em" title="Balabolka" target="_blank"&gt;&lt;img border="0" height="180" width="196" src="http://www.cross-plus-a.com/data/logo_balabolka.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Being read to is especially enjoyable when I'm either working on another task or I want to completely relax without having my eyes glued to the screen.&lt;br /&gt;&lt;br /&gt;Enter &lt;tt&gt;Balabolka&lt;/tt&gt; (Russian for "chatterer"), the free Windows text-to-speech (TTS) engine.&lt;br /&gt;&lt;br /&gt;Balabolka is easy to use, and works with any TTS voice currently installed on your system (my current preference being "VW Kate"), and the documentation points you to additional voices you can download free of charge.&lt;br /&gt;&lt;br /&gt;It supports a range of reading options including text-based documents of assorted types, pasted text, or the contents of the clipboard.&lt;br /&gt;&lt;br /&gt;Balabolka has all the features you'd expect without getting carried off to bloat-land. Like most quality software, a lot of the best things about it are its most basic.&lt;br /&gt;&lt;br /&gt;Two bread-and-butter features I needed that work especially well include the ability to save MP3s* and to "train" the dictionary to correct mispronunciations.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-bOAuLLtsWQ0/TddCmKSrZZI/AAAAAAAAAKg/m3lVIyzCm0Q/s1600/Balabolka.png" imageanchor="1" style="margin-left:1em; margin-right:1em" target="_blank" title="Click image to enlarge"&gt;&lt;div class="c"&gt;Click image to enlarge&lt;/div&gt;&lt;img border="0" height="398" width="500" src="http://1.bp.blogspot.com/-bOAuLLtsWQ0/TddCmKSrZZI/AAAAAAAAAKg/m3lVIyzCm0Q/s400/Balabolka.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-size:90%;opacity:0.9;color:#7B3904"&gt;* In addition to MP3, Balabolka supports seven other file export formats: WAV, OGG, WMA, MP4, M4A, M4B, and AWB.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It also comes with the ability to save ID3 meta information to MP3s (though since I've been using Balabolka to record chapters in audio books, I prefer to bulk edit this info using another first-rate freeware program called &lt;tt&gt;Tag Scanner&lt;/tt&gt; featured in &lt;a href="http://www.techsupportalert.com/best-free-mp3-tag-editor.htm" target="_blank"&gt;Best Free MP3 Tag Editor&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Other useful features are the ability to have multiple documents open displayed as tabs along the top or bottom (your choice set in &lt;b&gt;Options -&gt; Settings&lt;/b&gt;) and the ability to use context menus while Balabolka is reading (both pictured in the screen shot shown above).&lt;br /&gt;&lt;br /&gt;Balabolka is an all-around useful program that works well and is easy to use, and it comes in a portable version as well if you want to stick it on a USB drive and go. Just &lt;a href="http://www.cross-plus-a.com/balabolka.htm" target="_blank"&gt;grab yourself a free copy&lt;/a&gt; today. Cheers! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-4741381405105189820?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/4741381405105189820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/05/balabolka-swiss-army-knife-for-text-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4741381405105189820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4741381405105189820'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/05/balabolka-swiss-army-knife-for-text-to.html' title='Balabolka: A Free Text-To-Speech (TTS) Swiss Army Knife for Windows Operating Systems'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-bOAuLLtsWQ0/TddCmKSrZZI/AAAAAAAAAKg/m3lVIyzCm0Q/s72-c/Balabolka.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-9085735492537766690</id><published>2011-02-26T13:52:00.000-08:00</published><updated>2011-08-12T23:49:17.534-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='minify html php strip whitespace ob_start ob_end_flush linux'/><title type='text'>How to Minify HTML using PHP and Minify (including final HTML output of PHP files)</title><content type='html'>&lt;br /&gt;&lt;span  style="color: #7b3904;"&gt;&lt;b&gt;Full disclaimer:&lt;/b&gt; I did not actually implement this method in the project where I had it set up. I explain why below.&lt;/span&gt;&lt;p style="font-size:12px" class="b"&gt;Before Doing Anything Else, Gzip Your Pages!&lt;/p&gt;The first line of defense in reducing the payload of an HTML page is to &lt;a href="http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html" target="_blank"&gt;gzip, or compress, your files&lt;/a&gt;. Make sure you have taken that step first if you haven't before doing anything else mentioned here, as that will provide the biggest pay-off.&lt;p style="font-size:10px" class="b"&gt;Benchmark Your Speed, Before and After&lt;/p&gt;I said I didn't implement this method on the particular project I was working on: often after your pages are gzipped, the benefits you get from further compression are either negligible or actually decrease load speed, the very thing you're hoping to improve.&lt;br /&gt;&lt;br /&gt;Therefore, testing the speed of your pages before and after minification is advised: there are several free, online solutions available, and I happened to be using &lt;a href="http://webwait.com/" target="_blank"&gt;Webwait&lt;/a&gt;, which I liked because it is simple, does not require registration, and does not place restrictions.&lt;br /&gt;&lt;br /&gt;In my case, results revealed that I was actually suffering a slight penalty in load time when stripping whitespace. That said, I have a writing site that has massive HTML pages, and when I have time, I will likely try it again there: I suspect that for very large files, minification by PHP before page load would provide a benefit.&lt;br /&gt;&lt;br /&gt;Enough preamble.&lt;br /&gt;&lt;br /&gt;&lt;p style="font-size:13px" class="b"&gt;Whitespace Removal: Basic Steps&lt;/p&gt;There are several steps you need to take to set it up and get it working.&lt;p style="font-size:12px" class="b"&gt;PHP Check:&lt;/p&gt;First, is PHP already being used to render your page? If so, you're good to go as is&amp;#8212;skip this paragraph. If not, does the page have an "htm," "html", or "shtml" file extension and does that extension matter? If the answer to the second question is no, just change your file extension to "php" and if your web service provides PHP you should be good. If the file extension does matter and you're hosted on an Apache server, take a look at &lt;a href="http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html#step4" target="_blank"&gt;Step 4 here&lt;/a&gt; on how to give PHP control of rendering your pages.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #7b3904; font-size: 80%;"&gt;&lt;i&gt;&lt;b&gt;Note:&lt;/b&gt; If your extension is "shtml" and you currently make full use of server-side includes (SSI), you will need to reconfigure your pages to &lt;a href="http://www.w3schools.com/PHP/php_includes.asp" target="blank"&gt;use PHP for the same task&lt;/a&gt; or else find a different solution. The beauty is, PHP can do everything Apache's support of SSI can and more.&lt;/i&gt;&lt;/span&gt;&lt;p style="font-size:12px" class="b"&gt;Basic PHP Function with Associated "Gotchas" Explained:&lt;/p&gt;Now we need to write a PHP function, so let's create a new file called &lt;tt&gt;compress_html.php&lt;/tt&gt; that we include on all our pages we want to minify. Open the IDE or text editor of your choice and create this new file.&lt;br /&gt;&lt;br /&gt;Now let's type a simple function.&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;//This function is probably too simple to use: It can bite.&lt;br /&gt;function replace_tabs_newlines($content) {&lt;br /&gt;    return preg_replace('(\r|\n|\t)', '', $content);&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;/pre&gt;A very simple function like this that strips newline characters and tabs might be all you'd need. The danger with this approach though happens when your site includes any inline JavaScript or CDATA that uses single-line comments (double slashes) or any pre-filled textareas that need to have newline characters for human readability. For example...&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;//click event&lt;br /&gt;myFormElement.onclick = function() {&lt;br /&gt;     this.submit();&lt;br /&gt;};&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;...our simple PHP function would cause all the JavaScript below the "click event" comment to fail, because it's just stripping newlines and tabs from the entire HTML page indiscriminately. Once the document gets parsed by the browser, as far as the interpreter is concerned, without the newlines the &lt;tt&gt;script&lt;/tt&gt; tag contains nothing but a big, long comment: &lt;tt&gt;//click eventmyFormElement.onclick = function() {this.submit();};&lt;/tt&gt;. That means, of course, that your click event just died a horrid death.&lt;br /&gt;&lt;br /&gt;And if you have any textareas on your page with text already included in them, you'll also see just one big, long string. Probably not what you want.&lt;p style="font-size:12px" class="b"&gt;Wrapper Function Using Minify:&lt;/p&gt;My approach was to use Minify's little-documented and still-experimental HTML minifier instead. Simply download &lt;a href="http://code.google.com/p/minify/" target="_blank"&gt;Minify&lt;/a&gt;, and check out &lt;a href="http://mrrena.blogspot.com/2009/02/how-to-easily-compress-javascript-and.html" target="_blank"&gt;this page&lt;/a&gt; on getting it set up and running.&lt;br /&gt;&lt;br /&gt;Once Minify's in place, here's the new and improved, as before assumed to be saved to a file named &lt;tt&gt;compress_html.php&lt;/tt&gt;; there's still nothing exotic about our now wrapper function, and if you know PHP, you could probably write a better one (and if you do, please post it here and share with the rest of us), but this one will at least get your foot through the door.&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;function replace_tabs_newlines($content) {&lt;br /&gt;    require_once 'min/lib/Minify/HTML.php';&lt;br /&gt;    require_once 'min/lib/Minify/CSS.php';&lt;br /&gt;    require_once 'min/lib/JSMin.php';&lt;br /&gt;    $content = Minify_HTML::minify($content, array(&lt;br /&gt;        'cssMinifier' =&amp;gt; array('Minify_CSS', 'minify'),&lt;br /&gt;        'jsMinifier' =&amp;gt; array('JSMin', 'minify')&lt;br /&gt;    ));&lt;br /&gt;    return $content;&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;With some sort of callback method in place (such as the one above using Minify), you've now ensured that JavaScript and CSS at least should get handled correctly.&lt;p style="font-size:12px" class="b"&gt;Serving Minified HTML on a Platter:&lt;/p&gt;Now, simply include in the very top line of the PHP or HTML page you want to minify the following code, which includes the file that contains our &lt;tt&gt;replace_tabs_newlines&lt;/tt&gt; function and calls &lt;a href="http://php.net/manual/en/function.ob-start.php" target="_blank"&gt;&lt;tt&gt;ob_start&lt;/tt&gt;&lt;/a&gt;:&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;//includes are relative to the including file: this example&lt;br /&gt;//assumes compress_html.php lives at the same directory level&lt;br /&gt;//as the file in which you'll include these lines&lt;br /&gt;include('compress_html.php'); &lt;br /&gt;ob_start('replace_tabs_newlines');&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;tt&gt;ob_start&lt;/tt&gt; tells PHP to output any file contents to its internal memory buffer rather than the screen (think "&lt;b&gt;o.&lt;/b&gt;utput &lt;b&gt;b.&lt;/b&gt;uffering start"&amp;#8212;you are turning on output buffering). The "replace_tabs_newlines" tells &lt;tt&gt;ob_start&lt;/tt&gt; to send the raw output from the buffer through the function we just wrote and included in a separate file. Notice the quotation marks—single or double doesn't matter: &lt;tt&gt;ob_start&lt;/tt&gt; expects the function reference to be a string.&lt;br /&gt;&lt;br /&gt;Then, at the very bottom of the file after all other code and markup, include the following:&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;ob_end_flush();&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;This does just what it says: it ends, or turns back off, output buffering, then flushes the contents previously held in the buffer either to the screen (if &lt;tt&gt;ob_start&lt;/tt&gt; is passed no callback method) or through "replace_tabs_newlines" (or any other callback method, if one is specified).&lt;p style="font-size:12px" class="b"&gt;Final Check:&lt;/p&gt;View your source code, and you should see that white space and newlines &lt;a href="#a9085735492537766690"&gt;&lt;span style="color:#600"&gt;*&lt;/span&gt;&lt;/a&gt; were stripped before the page was rendered.&lt;br /&gt;&lt;br /&gt;That's it! Make sure to test your page speed before and after: &lt;a href="http://webwait.com/" target="_blank"&gt;Webwait&lt;/a&gt; or however. If you are seeing any performance increase, go for it! :)&lt;br /&gt;&lt;br /&gt;&lt;div style="border: dashed 1px #999;padding:3px;background-color:#eee"&gt;&lt;div class="b c"&gt;Update on Getting a Totally Blank Output Page&lt;/div&gt;&lt;br /&gt;I host through &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt;, and ran into a caveat when testing this on my writing site (which incidentally &lt;b&gt;did&lt;/b&gt; improve speed performance for the large pages): I had to edit the file &lt;a href="http://code.google.com/p/minify/source/browse/trunk/min/lib/Minify/CSS.php" target="_blank"&gt;&lt;tt&gt;min/lib/Minify/CSS.php&lt;/tt&gt;&lt;/a&gt;, taking out the three references to &lt;tt&gt;Minify&lt;/tt&gt; in the &lt;tt&gt;require_once&lt;/tt&gt; statements:&lt;pre class="code js"&gt;&lt;br /&gt;//edits made to "min/lib/Minify/CSS.php"&lt;br /&gt;&lt;br /&gt;public static function minify($css, $options = array()) &lt;br /&gt;    {&lt;br /&gt;        require_once 'CSS/Compressor.php';//removed "Minify/" from the front&lt;br /&gt;        if (isset($options['preserveComments']) &lt;br /&gt;            &amp;&amp; !$options['preserveComments']) {&lt;br /&gt;            $css = Minify_CSS_Compressor::process($css, $options);&lt;br /&gt;        } else {&lt;br /&gt;            require_once 'CommentPreserver.php';//removed "Minify/" from the front&lt;br /&gt;            $css = Minify_CommentPreserver::process(&lt;br /&gt;                $css&lt;br /&gt;                ,array('Minify_CSS_Compressor', 'process')&lt;br /&gt;                ,array($options)&lt;br /&gt;            );&lt;br /&gt;        }&lt;br /&gt;        if (! isset($options['currentDir']) &amp;&amp; ! isset($options['prependRelativePath'])) {&lt;br /&gt;            return $css;&lt;br /&gt;        }&lt;br /&gt;        require_once 'CSS/UriRewriter.php';//removed "Minify/" from the front&lt;br /&gt;        if (isset($options['currentDir'])) {&lt;br /&gt;            return Minify_CSS_UriRewriter::rewrite(&lt;br /&gt;                $css&lt;br /&gt;                ,$options['currentDir']&lt;br /&gt;                ,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']&lt;br /&gt;                ,isset($options['symlinks']) ? $options['symlinks'] : array()&lt;br /&gt;            );  &lt;br /&gt;        } else {&lt;br /&gt;            return Minify_CSS_UriRewriter::prepend(&lt;br /&gt;                $css&lt;br /&gt;                ,$options['prependRelativePath']&lt;br /&gt;            );&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;Note that (a) I am using the Minify library a directory level deeper (&lt;tt&gt;/some_dir/min&lt;/tt&gt;), and (b) I only ran into problems when including it in files that lived in directories deeper than root, not at the root level itself.&lt;br /&gt;&lt;br /&gt;However, I suspect that even if (a) were not an issue, (b) would probably still apply, and since &lt;tt&gt;CSS.php&lt;/tt&gt; physically lives in the &lt;tt&gt;Minify&lt;/tt&gt; directory, there should be no reason that directory should have to be specified at the front of the &lt;tt&gt;require_once&lt;/tt&gt; path anyway, as includes are relative to the including file.&lt;br /&gt;&lt;br /&gt;I can also verify that modifying this file in this way works equally well in root as it does any number of directory levels deeper.&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size:80%"&gt;&lt;b style="color:#600" id="a9085735492537766690"&gt;*&lt;/b&gt; Minify does not necessarily strip all newlines depending on its heuristics and your particular page. If you can be assured that stripping all newlines and tabs will have no effect on your particular setup, you can replace "&lt;tt style="font-size:10px"&gt;return $content;&lt;/tt&gt;" with the return found in the otherwise too-simple first example. Minify will have safely stripped all comments from the CSS and JS and you'll be stripping any whitespace it "missed," but you've still got any pre-populated textareas to consider, inputs Minify knows to leave well enough alone.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-9085735492537766690?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/9085735492537766690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2011/02/how-to-minify-html-using-php-and-minify.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9085735492537766690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9085735492537766690'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2011/02/how-to-minify-html-using-php-and-minify.html' title='How to Minify HTML using PHP and Minify (including final HTML output of PHP files)'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-7501408972792904646</id><published>2010-09-30T20:32:00.000-07:00</published><updated>2011-07-23T17:58:34.524-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript fade animation object-oriented class-based this keyword'/><title type='text'>Simple Class-Based JavaScript Fade Animation: An Object-Oriented Reworking</title><content type='html'>&lt;h2&gt;Simple Object-Oriented Fade Animation&lt;/h2&gt;Normally, I'd just use &lt;a href="http://mootools.net/" target="_blank"&gt;MooTools&lt;/a&gt; for fade animations, but a long-time client wanted a simple, one-time popup that notified her patients that her doctor's office had moved—a temporary courtesy to be removed in a few months.&lt;br /&gt;&lt;br /&gt;To make the custom popup just a little nicer, I wanted a simple fade effect without the extra framework code. Of course, I could have just copied and pasted the methods in MooTools, but I was feeling creative and shopped around to see if any native JS solutions existed.&lt;br /&gt;&lt;br /&gt;I found &lt;a href="http://www.switchonthecode.com/tutorials/javascript-tutorial-simple-fade-animation" target="_blank"&gt;a solution I liked&lt;/a&gt;, though it lacks the greater flexibility of a more object-oriented approach. It also sets foreign attributes, &lt;b&gt;FadeState&lt;/b&gt;&amp;nbsp;and&amp;nbsp;&lt;b&gt;FadeTimeLeft&lt;/b&gt;, directly on the element&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;div id="fadeEl" FadeState="-2" FadeTimeLeft="33"&gt;&lt;br /&gt;    I am the fade element.&lt;br /&gt;&amp;lt;/div&gt;&lt;/pre&gt;and passes a spliced-together variable that looks up the same element over and over again: &lt;tt style="font-size:12px"&gt;document.getElementById(eid)&lt;/tt&gt;,&lt;br /&gt;&lt;pre class="code js"&gt;setTimeout("animateFade(" + new Date().getTime() + ",'" + eid + "')", 33);&lt;/pre&gt;neither of which are optimal.&lt;br /&gt;&lt;br /&gt;The logic was there, however, and it wasn't hard to convert into an object. The nice thing about objects is that an object is just that: A flexible model of something that once modeled can be easily reused. So, I revamped the function provided there to make it less intrusive and more modular.&lt;br /&gt;&lt;br /&gt;I'd originally posted the following re-working in the comments on that site, but this is a slightly more polished example.&lt;br /&gt;&lt;h2&gt;Basic Object&lt;/h2&gt;&lt;h3&gt;The AnimateFade Class&lt;/h3&gt;&lt;pre class="code js"&gt;//declare class so we can use the "new" keyword to create unique instances&lt;br /&gt;var AnimateFade = function(elmOrElmId, duration, state) {&lt;br /&gt;    this.setOptions(elmOrElmId, duration, state);&lt;br /&gt;    this.animate();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//prototype its methods&lt;br /&gt;AnimateFade.prototype = {&lt;br /&gt;&lt;br /&gt;    setOptions: function(elmOrElmId, duration, state) {&lt;br /&gt;        this.fadeDuration = duration;&lt;br /&gt;        this.element = (typeof elmOrElmId == 'string') ? document.getElementById(elmOrElmId) : elmOrElmId;&lt;br /&gt;        this.fadeState = (state &amp;&amp; state == 1) ? 1 : 0;&lt;br /&gt;        this.fadeTimeLeft = duration;&lt;br /&gt;        this.lastTick = this.newTick();&lt;br /&gt;    },&lt;br /&gt;&lt;br /&gt;    newTick: function() {&lt;br /&gt;        return (new Date).getTime();&lt;br /&gt;    },&lt;br /&gt;&lt;br /&gt;    getElapsedTicks: function() {&lt;br /&gt;        return this.currentTick - this.lastTick;&lt;br /&gt;    },&lt;br /&gt;&lt;br /&gt;    animate: function() {&lt;br /&gt;&lt;br /&gt;        this.currentTick = this.newTick();&lt;br /&gt;&lt;br /&gt;        var self = this;&lt;br /&gt;        var elapsedTicks = this.getElapsedTicks();&lt;br /&gt;&lt;br /&gt;        //helper function, called in the timeout below,&lt;br /&gt;        //recurses with correct reference to "this"&lt;br /&gt;        var helper = function() {&lt;br /&gt;            self.animate();&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        if (this.fadeTimeLeft &lt;= elapsedTicks) {&lt;br /&gt;            this.element.style.opacity = this.fadeState;&lt;br /&gt;            this.element.style.filter = 'alpha(opacity = ' + (this.fadeState * 100) + ')';&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        this.fadeTimeLeft -= elapsedTicks;&lt;br /&gt;&lt;br /&gt;        var newOptVal = this.fadeTimeLeft / this.fadeDuration;&lt;br /&gt;&lt;br /&gt;        newOptVal = (this.fadeState == 1) ? (1 - newOptVal) : newOptVal;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        this.element.style.opacity = newOptVal;&lt;br /&gt;        this.element.style.filter = 'alpha(opacity = ' + (newOptVal * 100) + ')';&lt;br /&gt;&lt;br /&gt;        this.lastTick = this.currentTick;&lt;br /&gt;        this.currentTick = this.newTick();&lt;br /&gt;&lt;br /&gt;        setTimeout(helper, 24);&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//initializer function&lt;br /&gt;var init = function(elmsOrElmIdArr, duration, state) {&lt;br /&gt;    for (var i = 0, l = elmsOrElmIdArr.length; i &lt; l; i++) {&lt;br /&gt;        //"new" keyword creates unique instance&lt;br /&gt;        new AnimateFade(elmsOrElmIdArr[i], duration, state);&lt;br /&gt;    }&lt;br /&gt;};&lt;/pre&gt;&lt;h2&gt;Instantiations&lt;/h2&gt;&lt;h3&gt;Single/Multiple Elements, Single Duration and Fade State&lt;/h3&gt;To instantiate with one or more elements that will all fade in or out for the same duration:&lt;pre class="code js"&gt;//pass in either string id or element reference&lt;br /&gt;&lt;br /&gt;//Example A: fade just one element&lt;br /&gt;var myOnlyElement = ['myUniqueId'];&lt;br /&gt;&lt;br /&gt;//Example B: fade multiple elements&lt;br /&gt;var myMultElms = ['myId', document.getElementsByTagName('div')[7], 'anotherId'];&lt;br /&gt;&lt;br /&gt;//how long fade should last&lt;br /&gt;var myDuration = 1000;//1,000 milliseconds, or 1 second&lt;br /&gt;&lt;br /&gt;//start fading out&lt;br /&gt;init(myMultElms, myDuration);&lt;br /&gt;//or fading in&lt;br /&gt;init(myMultElms, myDuration, 1);&lt;/pre&gt;&lt;h3&gt;Multiple Elements, Durations, and Fade States&lt;/h3&gt;Or retool the initializer function...&lt;pre class="code js"&gt;//initializer function capitalizing on parallel arrays&lt;br /&gt;var init = function(elmsOrElmIdArr, duration, state) {&lt;br /&gt;    for (var i = 0, l = elmsOrElmIdArr.length; i &lt; l; i++) {&lt;br /&gt;        //"new" keyword creates unique instance&lt;br /&gt;        new AnimateFade(elmsOrElmIdArr[i], duration[i], state[i]);&lt;br /&gt;    }&lt;br /&gt;};&lt;/pre&gt;...to take full advantage of arrays, simultaneously fading multiple elements in and out for different lengths of time:&lt;pre class="code js"&gt;//set parallel arrays&lt;br /&gt;var myElms = [elm1, elm2, elm3];&lt;br /&gt;var myDurations = [1000, 2500, 300];&lt;br /&gt;var myStates = [0, 1, 0];&lt;br /&gt;&lt;br /&gt;//start effects&lt;br /&gt;init(myElms, myDurations, myStates);&lt;br /&gt;&lt;br /&gt;//elm1 fades out in 1 second&lt;br /&gt;//elm2 fades in in 2-and-a-half seconds&lt;br /&gt;//elm3 fades out in 3/10ths of a second&lt;/pre&gt;This could be useful if you wanted to fade in one set of elements while simultaneously fading out another set, perhaps a confirmation dialog and its acknowledge that the user's choice has either been implemented or canceled. Or whatever.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-7501408972792904646?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/7501408972792904646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2010/09/simple-class-based-javascript-fade.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7501408972792904646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7501408972792904646'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2010/09/simple-class-based-javascript-fade.html' title='Simple Class-Based JavaScript Fade Animation: An Object-Oriented Reworking'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-996111556102869960</id><published>2010-08-06T20:58:00.000-07:00</published><updated>2010-08-06T21:09:06.724-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox aggressive caching development servers JavaScript CSS'/><title type='text'>Make Caching Less Aggressive in Firefox on Development Machines</title><content type='html'>I have been having some issues with Firefox caching files too aggressively on my development machine at work: not good when you write client-side code.&lt;br /&gt;&lt;br /&gt;My first attempt to resolve the issue was to disable caching entirely using the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/60/" target="_blank"&gt;Web Developer&lt;/a&gt; toolbar &lt;span style="font-size:80%"&gt;(Disable &gt; Disable Cache)&lt;/span&gt;. However, that is not optimal, as every page resource gets downloaded every time you refresh the page.&lt;br/&gt;&lt;br/&gt;So I did some reading up, and, just as I suspected, there is a Firefox configuration setting that forces a 304 request each time you refresh the page. This solution is superior to disabling the cache, as only resources that have changed are downloaded again.&lt;br/&gt;&lt;br/&gt;If you have caching problems (or you're concerned that you might), you'll need to change a value in Firefox's "power-user" configuration settings. Here's how:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;Open a new tab, type &lt;b&gt;about:config&lt;/b&gt; into your address bar, and promise Firefox you'll be careful. ;)&lt;/li&gt;&lt;li&gt;Enter &lt;b&gt;browser.cache.check_doc_frequency&lt;/b&gt; into the &lt;b&gt;filter&lt;/b&gt; field.&lt;/li&gt;&lt;li&gt;Change the value of 3 to 1, which tells Firefox to check the server for updated resources on every refresh.&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;Further Information:&lt;/b&gt; For the full reference see &lt;a href="http://kb.mozillazine.org/Browser.cache.check_doc_frequency" target="_blank"&gt;here&lt;/a&gt;, and for a list of the seven hidden pages in Firefox, see &lt;a href="http://www.lifespy.com/2007/firefox-quick-tip-the-seven-hidden-pages/" target="_blank"&gt;The Seven "Hidden" Pages&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-996111556102869960?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/996111556102869960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2010/08/make-caching-less-aggressive-in-firefox.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/996111556102869960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/996111556102869960'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2010/08/make-caching-less-aggressive-in-firefox.html' title='Make Caching Less Aggressive in Firefox on Development Machines'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-2109284215953317474</id><published>2010-06-19T19:02:00.000-07:00</published><updated>2010-06-21T18:56:46.944-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ajax throbbers spinners web 2.0 ajaxload.info status progress indicator'/><title type='text'>Slick Ajax Site for Creating Throbbers / Spinners</title><content type='html'>Ajax &lt;i&gt;throbbers&lt;/i&gt; (or &lt;i&gt;spinners&lt;/i&gt; as they are often informally called) are a hallmark of Web 2.0 applications, invaluable for showing the user that something is happening, at least when an accurate and detailed progress indicator is not required. Now, thanks to Yannick Croissant, creating custom variations is easy (and free).&lt;br /&gt;&lt;br /&gt;You can set the foreground and background colors, or set to transparent (though depending on the colors you choose, it may cause the image to look a little ragged around the edges). What is more, this free service could not be easier to use.&lt;br /&gt;&lt;br /&gt;Just go to &lt;b&gt;&lt;a href="http://www.ajaxload.info/" target="_blank"&gt;ajaxload.info&lt;/a&gt;&lt;/b&gt; to get started. :)&lt;br /&gt;&lt;br /&gt;&lt;b style="color:#555"&gt;A few examples that took less than a minute to create playing off the colors of this blog:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh3.ggpht.com/_O3igLjSA20U/TB5_l1gBf5I/AAAAAAAAAIQ/LbJ0f9b5HZk/s128/38-1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;border:0"&gt;&lt;img style="border:0" src="http://lh3.ggpht.com/_O3igLjSA20U/TB5_l1gBf5I/AAAAAAAAAIQ/LbJ0f9b5HZk/s128/38-1.gif" /&gt;&lt;/a&gt;&lt;a href="http://lh3.ggpht.com/_O3igLjSA20U/TB5_lsGyrZI/AAAAAAAAAII/gx0rXjM82h8/s128/31-0.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em; border: 0;"&gt;&lt;img style="border:0" src="http://lh3.ggpht.com/_O3igLjSA20U/TB5_lsGyrZI/AAAAAAAAAII/gx0rXjM82h8/s128/31-0.gif" /&gt;&lt;/a&gt;&lt;a href="http://lh6.ggpht.com/_O3igLjSA20U/TB6D-eUCaVI/AAAAAAAAAIw/6q5xekf3N2o/20-1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em; border: 0"&gt;&lt;img style="border:0" src="http://lh6.ggpht.com/_O3igLjSA20U/TB6D-eUCaVI/AAAAAAAAAIw/6q5xekf3N2o/20-1.gif" /&gt;&lt;/a&gt;&lt;a href="http://lh6.ggpht.com/_O3igLjSA20U/TB6DDmx1_HI/AAAAAAAAAIk/-9TbQWSOLfk/s128/36-1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em; border: 0"&gt;&lt;img style="border:0" src="http://lh6.ggpht.com/_O3igLjSA20U/TB6DDmx1_HI/AAAAAAAAAIk/-9TbQWSOLfk/s128/36-1.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-2109284215953317474?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/2109284215953317474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2010/06/slick-ajax-site-for-creating-throbbers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/2109284215953317474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/2109284215953317474'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2010/06/slick-ajax-site-for-creating-throbbers.html' title='Slick Ajax Site for Creating Throbbers / Spinners'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_O3igLjSA20U/TB5_l1gBf5I/AAAAAAAAAIQ/LbJ0f9b5HZk/s72-c/38-1.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-1154281428797390282</id><published>2010-01-27T21:58:00.000-08:00</published><updated>2010-10-20T21:45:09.580-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='getting setting class attribute classname internet explorer ie getattribute setattribute javascript cross-browser'/><title type='text'>Cross-Browser: Getting/Setting the Class Attribute of an Element Using JavaScript</title><content type='html'>It is common knowledge that getting and setting the class of an element in Internet Explorer requires a bit of a work-around from the standard JavaScript solution that works with all other browsers.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Usual Way&lt;/h3&gt;For example, using &lt;b&gt;setAttribute&lt;/b&gt; to set the class requires two different values depending on whether the browser is Internet Explorer (&lt;b&gt;className&lt;/b&gt;) or all others (&lt;b&gt;class&lt;/b&gt;):&lt;br /&gt;&lt;pre class="code js"&gt;//a conditional statement specifies class or className&lt;br /&gt;var klass = (isIE) ? 'className' : 'class';&lt;br /&gt;element.setAttribute(klass, 'new_class');&lt;br /&gt;&lt;/pre&gt;The same is also true when attempting to get the class value with &lt;b&gt;getAttribute&lt;/b&gt;:&lt;br /&gt;&lt;pre class="code js"&gt;element.getAttribute('className'); //for IE&lt;br /&gt;element.getAttribute('class'); //everybody else&lt;br /&gt;&lt;/pre&gt;But what if you could both get and set the values on all browsers without any conditional logic? Apparently, you can.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;A Better Way&lt;/h3&gt;The following solution works in all versions of IE from at least 6 onward, Firefox 3, Chrome, Safari, and Opera 10. I haven't tried it on Konqueror or any of the Linux browsers yet, but I would be surprised if it did not work there equally well.&lt;br /&gt;&lt;pre class="code js"&gt;element.className; //get class(es)&lt;br /&gt;element.className = 'new_class'; //(re)set to single class&lt;br /&gt;&lt;br /&gt;//or, if you don't want to tamper with any existing&lt;br /&gt;//classes: note the space before the new class name&lt;br /&gt;element.className = element.className + ' new_class';&lt;br /&gt;&lt;br /&gt;//examples&lt;br /&gt;if (/new_class/.test(element.className) { //test&lt;br /&gt;    element.style.border = 'solid 1px #555';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (someVariable == someValue) { //add "new_class" class&lt;br /&gt;    element.className = element.className + ' new_class';&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I have created a simple example page. In this case, the script toggles a &lt;b&gt;show&lt;/b&gt; and &lt;b&gt;hide&lt;/b&gt; class on table rows. Just &lt;a href="https://docs.google.com/leaf?id=0B8HqaklTTSPmYjE1NWRmMDAtNjU4YS00Nzk0LThlMTgtYWU5Y2YxZDk3Njk5&amp;amp;hl=en" target="_blank"&gt;download a copy from Google Docs&lt;/a&gt;, open in your litany of browsers, and enjoy. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-1154281428797390282?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/1154281428797390282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2010/01/cross-browser-setting-class-attribute.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1154281428797390282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/1154281428797390282'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2010/01/cross-browser-setting-class-attribute.html' title='Cross-Browser: Getting/Setting the Class Attribute of an Element Using JavaScript'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-4922733072091862905</id><published>2009-12-16T23:06:00.000-08:00</published><updated>2010-06-22T22:29:10.378-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mootools moo tools element constructors instantiation adoption JavaScript'/><title type='text'>$dom2mootools: MooTools JavaScript Element Construction / Adoption Just Got Easier!</title><content type='html'>&lt;style type="text/css"&gt;  #demo_div h3 {   color: #333;   margin-bottom: 0  }  textarea#input, textarea#output {   height: 225px;   width: 500px;   border: solid 1px #999;   padding: 5px  }  #sub {   margin:auto;text-align:center !important  }  textarea#output {   margin-bottom: 1.0em  }  #holderdiv {   position: fixed;   top: -120000px;   left: -600000px;   visibility: hidden;  }  #flatten_div {   font-size: 11px;  }  #flatten_divs {   position:relative;   top:2px;  }  .hiLight {   padding: 2px 6px;   border: dashed 1px #f91;  }  .directions {margin:2.0em auto}  .c {text-align: center}  .l {text-align: left}  .i {font-style: italic}&lt;/style&gt;&lt;div id="demo_div"&gt;&lt;h2&gt;$dom2mootools&lt;/h2&gt;&lt;p class="l"&gt;&lt;b&gt;Overview:&lt;/b&gt; $dom2mootools drastically speeds up the process of JavaScript element construction when using the &lt;a href="http://mootools.net/" target="_blank"&gt;MooTools&lt;/a&gt; framework. Given any element node, it produces MooTools element constructors and should perform nearly seamless parent-child adoption (including a final adoption at the end and a reminder to reassign to your own root node).&lt;/p&gt;&lt;p class="l"&gt;&lt;b&gt;Accreditation:&lt;/b&gt; Idea suggested by Jessie Yeagle and implemented by Eric Knickerbocker, both JavaScript developers at &lt;a href="http://www.iws-web.com/" target="_blank"&gt;Intuitive Web Solutions&lt;/a&gt;.&lt;/p&gt;&lt;p class="l"&gt;&lt;b&gt;Creation Date:&lt;/b&gt; November 20, 2009. Last updated June 23, 2010.&lt;/p&gt;&lt;p class="l"&gt;&lt;b&gt;URL:&lt;/b&gt; &lt;a href="http://mrrena.blogspot.com/2009/12/dom2mootools.html"&gt;http://mrrena.blogspot.com/2009/12/dom2mootools.html&lt;/a&gt;.&lt;/p&gt;&lt;p class="c i directions"&gt;Simply paste the HTML source code you want&lt;br /&gt;to convert into the text box below and click &lt;b&gt;Submit&lt;/b&gt;.&lt;/p&gt;&lt;h3&gt;Input&lt;/h3&gt;&lt;textarea id="input"&gt;&lt;/textarea&gt;&lt;div id="sub"&gt;&lt;div id="flatten_div" title="Any non-text nodes inside a div element will be flattened into an innerHTML string instead of processing as nodes: 'html': 'Blah blah &amp;lt;b&amp;gt;blah&amp;lt;/b&amp;gt; blah &amp;lt;small&amp;gt;blah&amp;lt;/small&amp;gt;'"&gt;&lt;input type="checkbox" id="flatten_divs" /&gt; Check to flatten div HTML.&lt;/div&gt;&lt;input id="me" type="button" value=" Submit " /&gt;&lt;/div&gt;&lt;h3&gt;Output&lt;/h3&gt;&lt;textarea id="output"&gt;&lt;/textarea&gt;&lt;/div&gt;&lt;script src="http://www.mrrena.com/scripts/dom2mootools.js" type="text/javascript"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-4922733072091862905?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/4922733072091862905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/12/dom2mootools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4922733072091862905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4922733072091862905'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/12/dom2mootools.html' title='$dom2mootools: MooTools JavaScript Element Construction / Adoption Just Got Easier!'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-9174069711689392656</id><published>2009-10-19T13:13:00.000-07:00</published><updated>2011-04-15T20:13:01.036-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chmod'/><category scheme='http://www.blogger.com/atom/ns#' term='failed to find flength file error uber-uploader'/><category scheme='http://www.blogger.com/atom/ns#' term='xupload'/><title type='text'>"Failed To Find Flength File": Uber-Uploader Error SOLVED</title><content type='html'>&lt;br /&gt;&lt;span style="color: #c05f04;"&gt;"&lt;b&gt;Failed to find flength file.&lt;/b&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I moved a new application we're developing from the development server onto the one that we hope to release live soon. As part of this package, we make use of &lt;a href="http://uber-uploader.sourceforge.net/" target="_blank"&gt;Uber-Uploader&lt;/a&gt; and experienced no problems with the dev server, which was set up identically to the soon-to-be-live configuration. However, I kept getting a "Failed to find flength file" error on the new server.&lt;br /&gt;&lt;br /&gt;I first consulted the page from Uber Uploader entitled &lt;a href="http://uber-uploader.sourceforge.net/?section=flength" target="_blank"&gt;Flength File Help "Failed To Find Flength File&lt;/a&gt;." That was clearly not the problem&amp;#8212;I did not even have the &lt;span style="font-weight: bold;"&gt;mod_security&lt;/span&gt; module for Apache configured. I then ended up in a discussion forum related to the &lt;a href="http://www.sibsoft.net/xupload.html" target="_blank"&gt;XUpload&lt;/a&gt; solution. Still no joy, though looking back, some people may have been on the right track, just not able to clearly communicate the solution.&lt;br /&gt;&lt;br /&gt;In short, it was a file permissions issue. As most of you reading these words probably know, Linux has file permission settings and your Perl/CGI uploader script needs to chmod-ed to 755 or similar&amp;#8212;it needs to be fully executable, in other words. No doubt the same issue would be true of an MS server with permissions set as well.&lt;br /&gt;&lt;br /&gt;Don't know how to set script permissions? Most FTP programs offer that functionality, including the open-source program &lt;a href="http://filezilla-project.org/download.php?type=client" target="_blank"&gt;FileZilla&lt;/a&gt;&amp;#8212;right click the Perl upload file, as shown below, and set your permissions to fully executable:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_O3igLjSA20U/Stzinpa4tZI/AAAAAAAAAFg/05YEjd-J9oA/s1600-h/chmod1.png" target="_blank"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 155px;" src="http://1.bp.blogspot.com/_O3igLjSA20U/Stzinpa4tZI/AAAAAAAAAFg/05YEjd-J9oA/s320/chmod1.png" alt="" id="BLOGGER_PHOTO_ID_5394435624444409234" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_O3igLjSA20U/StzioWc-1tI/AAAAAAAAAFo/NNJzGc3cnVs/s1600-h/chmod2.png" target="_blank"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 222px; height: 320px;" src="http://2.bp.blogspot.com/_O3igLjSA20U/StzioWc-1tI/AAAAAAAAAFo/NNJzGc3cnVs/s320/chmod2.png" alt="" id="BLOGGER_PHOTO_ID_5394435636532795090" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-9174069711689392656?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/9174069711689392656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/10/failed-to-find-flength-file-uber.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9174069711689392656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9174069711689392656'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/10/failed-to-find-flength-file-uber.html' title='&quot;Failed To Find Flength File&quot;: Uber-Uploader Error SOLVED'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_O3igLjSA20U/Stzinpa4tZI/AAAAAAAAAFg/05YEjd-J9oA/s72-c/chmod1.png' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-8908101376750111516</id><published>2009-07-08T12:48:00.000-07:00</published><updated>2011-03-04T20:31:14.766-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML EntityRef php htmlspecialchars javascript error solved HTMLentities HTML entities reserved xml name'/><title type='text'>"EntityRef: expecting ';' at line 1": XML Error SOLVED</title><content type='html'>&lt;br /&gt;&lt;span style="color: #c05f04;"&gt;"&lt;b&gt;EntityRef: expecting ';' at line 1&lt;/b&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was using the &lt;a href="http://uber-uploader.sourceforge.net/" target="_blank"&gt;Uber Uploader&lt;/a&gt; script for a project, and ran into the error above in the Firebug console. In my case, I had been passing a URL with a query string that needed to have HTML entities for the ampersands.&lt;br /&gt;&lt;br /&gt;In other words, the following URL:&lt;blockquote&gt;http://somesite.com/file.php?c=1&lt;b style="color: #c05f04;"&gt;&amp;amp;&lt;/b&gt;d=2&lt;b style="color: #c05f04;"&gt;&amp;amp;&lt;/b&gt;e=3&lt;/blockquote&gt;was creating an error in the XML file. The ampersands had to be encoded, which solved the error:&lt;blockquote&gt;http://somesite.com/file.php?c=1&lt;b style="color: #c05f04;"&gt;&amp;amp;amp;&lt;/b&gt;d=2&lt;b style="color: #c05f04;"&gt;&amp;amp;amp;&lt;/b&gt;e=3&lt;/blockquote&gt;Wikipedia &lt;a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined_entities_in_XML" target="_blank"&gt;has a list&lt;/a&gt; of all the characters that must be encoded when using XML. I list them below with the symbol followed by the HTML entity you will need to use to replace it with. If you are receiving the same error (or the error "Reserved XML Name"), you most likely need to make sure that these symbols are encoded (and with the latter error, watch out for deadly white space and newline characters).&lt;blockquote style="margin-bottom:0"&gt;&lt;table cellspacing="2" style="text-align:left;margin-top:0;padding-top:0"&gt;&lt;tr&gt;&lt;th&gt;Symbol:&lt;/th&gt;&lt;th&gt;HTML Entity:&lt;/th&gt;&lt;th&gt;Description:&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;"&lt;/td&gt;&lt;td&gt;&amp;amp;quot;&lt;/td&gt;&lt;td&gt;&lt;i&gt;(double)&lt;/i&gt; quotation mark&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;amp;&lt;/td&gt;&lt;td&gt;&amp;amp;amp;&lt;/td&gt;&lt;td&gt;ampersand&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;'&lt;/td&gt;&lt;td&gt;&amp;amp;apos; or &amp;amp;quot;&lt;/td&gt;&lt;td&gt;apostrophe &lt;i&gt;(= apostrophe-quote)&lt;/i&gt;&lt;/td&gt; &lt;br /&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;&lt;/td&gt;&lt;td&gt;&amp;amp;lt;&lt;/td&gt;&lt;td&gt;less-than sign&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;gt;&lt;/td&gt;  &lt;br /&gt;&lt;td&gt;&amp;amp;gt;&lt;/td&gt;&lt;td&gt;greater-than sign&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/blockquote&gt;&lt;br /&gt;Note that if you are using PHP, &lt;a href="http://php.net/manual/en/function.htmlspecialchars.php" target="_blank"&gt;htmlspecialchars&lt;/a&gt; and &lt;a href="http://www.php.net/manual/en/function.htmlspecialchars-decode.php"&gt;htmlspecialchars_decode&lt;/a&gt; should give you everything you need for XML; for JavaScript, you'll want a custom solution &lt;a href="http://dracoblue.net/dev/encodedecode-special-xml-characters-in-javascript/155/" target="_blank"&gt;such as this one&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-8908101376750111516?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/8908101376750111516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/07/entityref-expecting-at-line-1.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8908101376750111516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8908101376750111516'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/07/entityref-expecting-at-line-1.html' title='&quot;EntityRef: expecting &apos;;&apos; at line 1&quot;: XML Error SOLVED'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-4086872047425604633</id><published>2009-04-10T12:28:00.000-07:00</published><updated>2009-04-10T14:02:05.665-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Gregwired CamStudio YouTube synching audio and video Any Video Converter'/><title type='text'>Gregwired Blogs about Synching Audio and Video in Cam Studio, Especially for YouTube</title><content type='html'>&lt;br /&gt;My friend &lt;a href="http://www.gregwired.com" target="_blank"&gt;Greg&lt;/a&gt; has recently taken an interest in creating YouTube content and has put together an arsenal of free, quality tools for that purpose. Among these is &lt;a href="http://camstudio.org/" target="_blank"&gt;CamStudio&lt;/a&gt; (which can be used to record anything that appears on your screen), as well as &lt;a href="http://www.any-video-converter.com/products/for_video_free/" target="_blank"&gt;Any Video Converter&lt;/a&gt; that allows you to easily configure a variety of different options, providing conversion both to and from a range of popular video formats (including, but not limited to, avi, asf, mov, rm, rmvb, flv, mkv, mpg, 3gp, m4v, and vob).&lt;br /&gt;&lt;br /&gt;However, the default settings on CamStudio are not optimized for online content and it is frequently the case that audio and visual are not synced properly. That of course is not unique to CamStudio; out-of-sync videos can be especially noticeable in YouTube where the phenomenon has achieved no little notoriety.&lt;br /&gt;&lt;br /&gt;In any case, quality information on optimal CamStudio settings (and perhaps most especially on curing sync problems) is all but non-existent on the Internet, so Greg has both blogged about the issue as well as created a YouTube video taking you step by step through the optimized settings, with a special eye toward creating content to publish on YouTube. To read his blog entry, &lt;a href="http://gregwired.blogspot.com/2009/04/for-those-having-trouble-getting-audio.html" target="_blank"&gt;click here&lt;/a&gt;; to watch his YouTube "how to," &lt;a href="http://www.youtube.com/watch?v=m4kOx3eQQz8" target="_blank"&gt;click here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-4086872047425604633?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/4086872047425604633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/04/gregwired-blogs-about-synching-audio.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4086872047425604633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/4086872047425604633'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/04/gregwired-blogs-about-synching-audio.html' title='Gregwired Blogs about Synching Audio and Video in Cam Studio, Especially for YouTube'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-779952417674840303</id><published>2009-03-05T11:45:00.000-08:00</published><updated>2009-04-10T14:21:56.116-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='speed up torrent peer to peer p2p downloads windows 7 vista xp tcpip.sys lvllord.de'/><title type='text'>Speed up Torrent and Peer to Peer (P2P) Downloads on Vista and other Windows Platforms</title><content type='html'>&lt;br /&gt;As a security precaution, Windows XP and Vista and the new Windows 7 limit the number of so-called "half-open" outbound TCP connection attempts to 10. Normally, that poses no problems, but if you do any downloading with torrent files or other peer-to-peer (P2P) networking, that can significantly slow your downloads.&lt;br /&gt;&lt;br /&gt;Many XP users have relied on the &lt;a href="http://lvllord.de/?lang=en&amp;url=downloads" target="_blank"&gt;lvllord.de patch&lt;/a&gt; for their solution, but that only works for XP and it modifies the tcpip.sys file, which has been known to have disastrous results for Vista users. Fortunately, there is a simple and elegant solution that works not only on XP (and better than the patch), but on Vista and 7 as well.&lt;br /&gt;&lt;br /&gt;TCP-Z is a small GUI program for Windows that you can use to change the number of allowed half-open connections on the fly (up to 251) without restarting the computer &lt;span style="font-size:90%;"&gt;(click image for full-size view)&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try{parent.deselectBloggerImageGracefully();}catch(e){}" href="http://1.bp.blogspot.com/_O3igLjSA20U/Scg1mJAWylI/AAAAAAAAACo/EE5WuVqATcA/s1600-h/TCP.png"&gt;&lt;img style="display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:273px;height:320px" src="http://1.bp.blogspot.com/_O3igLjSA20U/Scg1mJAWylI/AAAAAAAAACo/EE5WuVqATcA/s320/TCP.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5316558289479584338" /&gt;&lt;/a&gt;To find out more about this program&amp;#8212;and most importantly to download a copy for yourself&amp;#8212;just head over to the &lt;a href="http://deepxw.blogspot.com/2009/01/tcp-z-center.html" target="_blank"&gt;TCP-Z Network Monitor&lt;/a&gt; site.&lt;br /&gt;&lt;br /&gt;&lt;i style="color: rgb(102, 51, 51);"&gt;&lt;b&gt;Note:&lt;/b&gt; To open the downloaded file, you may need a copy of the excellent and free &lt;a href="http://www.7-zip.org/download.html" target="_blank"&gt;7-Zip&lt;/a&gt; (which in my opinion works better than the native Windows zip program), as the native program does not recognize the .7z file extension. (7-Zip recognizes its own extension and many others, including all the standards.)&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-779952417674840303?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/779952417674840303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/03/speed-up-torrent-and-peer-to-peer-p2p.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/779952417674840303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/779952417674840303'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/03/speed-up-torrent-and-peer-to-peer-p2p.html' title='Speed up Torrent and Peer to Peer (P2P) Downloads on Vista and other Windows Platforms'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_O3igLjSA20U/Scg1mJAWylI/AAAAAAAAACo/EE5WuVqATcA/s72-c/TCP.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-2813984469024040117</id><published>2009-02-26T18:31:00.000-08:00</published><updated>2011-03-16T23:29:27.450-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='easily compress minify combine javascript css http requests 1and1 shared servers hosting speed up page loads'/><title type='text'>How to Easily Combine, Minify, and Cache JavaScript and CSS with 1&amp;1 (And Other Web Hosts)</title><content type='html'>&lt;br /&gt;&lt;div style="padding:3px;background-color:#eee;border:dotted 1px #999"&gt;&lt;p style="font-size:11px;font-weight:bold" class="c"&gt;Sections Covered:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="#opening_word"&gt;An Opening Word&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="#setup_basic_use"&gt;Setup And Basic Use&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="#setting_long_cache_life"&gt;Setting a Long Cache Life for Your Pages&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="#use_in_subdirectory"&gt;Note on Use Inside A Sub-Directory&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style="font-size:12px;font-weight:bold" id="opening_word"&gt;An Opening Word&lt;/p&gt;In &lt;a href="http://mrrena.blogspot.com/2009/01/how-to-compress-perl-cgi-scripts-with-1.html"&gt;How to Compress Perl/CGI-Scripts...&lt;/a&gt; and &lt;a href="http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html"&gt;How to Compress PHP and Other Text-Based Files...&lt;/a&gt;, I write about achieving better standards according to Yahoo’s &lt;a href="http://developer.yahoo.com/performance/rules.html#gzip" target="_blank"&gt;Best Practices for Speeding up Websites&lt;/a&gt; guide.&lt;br /&gt;&lt;br /&gt;If your server supports PHP5, now there is an incredibly easy way to minify both JavaScript and CSS files on the fly, PLUS a way to combine a number of different files into a single HTTP request. &lt;span style="font-size:90%"&gt;(See &lt;b&gt;Step 4&lt;/b&gt; of &lt;a href="http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html#step4" target="_blank"&gt;my blog entry on compressing PHP scripts&lt;/a&gt; to convert your site to PHP5, particularly if you are using a &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt; shared hosting package.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Thanks to &lt;a href="http://wonko.com/" target="_blank"&gt;Ryan Grove&lt;/a&gt; and &lt;a href="http://mrclay.org/" target="_blank"&gt;Steve Clay&lt;/a&gt;, &lt;span style="font-weight: bold;"&gt;Minify!&lt;/span&gt; is now here &lt;span style="font-size:90%"&gt;(&lt;a href="http://code.google.com/p/minify/" target="_blank"&gt;download link&lt;/a&gt;)&lt;/span&gt;. As the source page on GoogleCode suggests, it &lt;i&gt;combines, minifies, and caches JavaScript and CSS files on demand to speed up page loads.&lt;/i&gt;&lt;p style="font-size:12px;font-weight:bold" id="setup_basic_use"&gt;Setup and Basic Use&lt;/p&gt;Just download the zip file and drop the &lt;tt&gt;min&lt;/tt&gt; folder in your root directory.&lt;br /&gt;&lt;br /&gt;Then, to include single resources on your page, just set them up like the following with &lt;tt&gt;?f=&lt;/tt&gt; (&lt;tt&gt;f&lt;/tt&gt; short for "file"), followed by the URL of the resource:&lt;pre class="code js" style="overflow-x: auto"&gt;&lt;br /&gt;//css&lt;br /&gt;&amp;lt;link rel="stylesheet" href="/min/?f=/path_to_file/file.css" type="text/css" /&gt;&lt;br /&gt;//js&lt;br /&gt;&amp;lt;script type="text/javascript" src="/min/?f=/path_to_file/file.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;You can also use URL-rewriting if your host supports it (see &lt;a style="color: rgb(102, 51, 51);" href="#mod_rewrite_note"&gt;&lt;b&gt;Note&lt;/b&gt;&lt;/a&gt; below):&lt;pre class="code js"&gt;&lt;br /&gt;//js -- notice the "?" before the "f" has been dropped&lt;br /&gt;&amp;lt;script type="text/javascript" src="/min/f=/path_to_file/file.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;Minify comes with its own URL-builder for easily creating and checking links which you can access at &lt;tt&gt;http://name_of_your_site_here.com/min/index.php&lt;/tt&gt; once you have it installed on your server.&lt;br /&gt;&lt;br /&gt;The builder interface itself will teach you how to serve groups of files as a single, minified resource by adding a few lines to &lt;tt&gt;/min/groupsConfig.php&lt;/tt&gt;, but we'll go ahead and look at it here anyway:&lt;pre class="code js"&gt;&lt;br /&gt;//In /min/groupsConfig.php, I set up the unique identifier "js"&lt;br /&gt;//to specify a group of 5 hypothetical JS files&lt;br /&gt;return array(&lt;br /&gt;    'js' =&gt; array(&lt;br /&gt;        '//js/file1.js',&lt;br /&gt;        '//js/file2.js',&lt;br /&gt;        '//js/file3.js',&lt;br /&gt;        '//js/file4.js',&lt;br /&gt;        '//js/file5.js'&lt;br /&gt;    )&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;You can then include this group of files in your HTML tag by specifying &lt;tt&gt;g&lt;/tt&gt; (for "group"), followed by your unique &lt;tt&gt;js&lt;/tt&gt; identifier.&lt;pre class="code js"&gt;&amp;lt;script type="text/javascript" src="/min/g=js"&gt;&amp;lt;/script&gt;&lt;/pre&gt;Or you can take full advantage of comma-delimited arrays and set up as many sets of files paired with unique identifiers as you want (of course including any CSS files using the &lt;tt&gt;link&lt;/tt&gt; tag, as shown in the first example on this page):&lt;pre class="code js"&gt;&lt;br /&gt;//"js" and "css" file groups set in /min/groupsConfig.php&lt;br /&gt;return array(&lt;br /&gt;    'js' =&gt; array(&lt;br /&gt;        '//js/file1.js',&lt;br /&gt;        '//js/file2.js',&lt;br /&gt;        '//js/file3.js',&lt;br /&gt;        '//js/file4.js',&lt;br /&gt;        '//js/file5.js'&lt;br /&gt;    ),&lt;br /&gt;    'css' =&gt; array(&lt;br /&gt;        '//css/file1.css',&lt;br /&gt;        '//css/file2.css',&lt;br /&gt;        '//css/file2.css'&lt;br /&gt;    )&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;p style="font-size:12px;font-weight:bold;margin-top:18px" id="setting_long_cache_life"&gt;Setting a Long Cache Life for Your Pages&lt;/p&gt;Minify's default cache life is 30 minutes for CSS and JS files. This works well for development servers, but for production servers with stable code, a longer cache time is recommended. Your can easily implement a year-long cache life in the HTML simply by appending a number (yes, any number) as a query string variable.&lt;pre class="code js" style="overflow-x: auto"&gt;&lt;br /&gt;//css&lt;br /&gt;&amp;lt;link rel="stylesheet" href="/min/g=css&amp;1" type="text/css" /&gt;&lt;br /&gt;//js&lt;br /&gt;&amp;lt;script type="text/javascript" src="/min/g=js&amp;1"&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;However, you &lt;b&gt;must&lt;/b&gt; update this number if you make changes to these files and it is important that users have the latest versions. For this reason, I recommend starting off with the number 1 and incrementing it as your changes dictate, though as long as the numbers are always different, it makes no difference how you do it.&lt;br /&gt;&lt;br /&gt;Since this approach requires manual editing, this may not be optimal for you. For the full spectrum of caching possibilities, see the developer doc &lt;a href="http://code.google.com/p/minify/wiki/HttpCaching" target="_blank"&gt;HttpCaching&lt;/a&gt;; for advanced options of specifying a different cache system (as well as other advanced uses) see the &lt;a href="http://code.google.com/p/minify/wiki/CookBook" target="_blank"&gt;CookBook&lt;/a&gt; doc.&lt;br /&gt;&lt;br /&gt;For more general use ideas, including how to specify a &lt;tt&gt;b&lt;/tt&gt; for "base directory" when a group of single files all share the same root directory path, see the developer README file beginning with the heading "&lt;a href="http://code.google.com/p/minify/source/browse/tags/release_2.1.3/min/README.txt#18" target="_blank"&gt;Minifying a Single File&lt;/a&gt;"; for advanced usage beyond the scope of the examples here, see the developer comments at &lt;a href="http://code.google.com/p/minify/wiki/CustomSource" target="_blank"&gt;CustomSource&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 51, 51);"&gt;&lt;span style="font-weight: bold;" id="mod_rewrite_note"&gt;Note:&lt;/span&gt; If you want to use rewritten urls and you are using a Linux shared hosting package with &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt; (and maybe even if you're not), you will probably need to make a small adjustment to the included &lt;tt&gt;.htaccess&lt;/tt&gt; file in the &lt;span style="font-weight:bold;"&gt;min&lt;/span&gt; directory. The line in the native code you're after reads as follows:&lt;blockquote&gt;RewriteRule ^([a-z]=.*)  index.php?$1  [L,NE]&lt;/blockquote&gt;but you will probably need to change it:&lt;blockquote style="overflow: auto;"&gt;RewriteRule ([a-z]=.*) /min/index.php?$1 [L,NE]&lt;/blockquote&gt;Also to point out the obvious, make sure if you put the &lt;tt&gt;min&lt;/tt&gt; directory a level deeper (see below), you specify the sub-directory: for example, /&lt;span style="color: rgb(153, 51, 0); font-weight: bold;"&gt;myscripts&lt;/span&gt;/min/index.php.&lt;/span&gt;&lt;p style="font-size:12px;font-weight:bold" id="use_in_subdirectory"&gt;Note on Use Inside A Sub-Directory&lt;/p&gt;By default, Minify is intended to have the &lt;tt&gt;min&lt;/tt&gt; directory parked at the root level. It works just fine a directory level deeper, however, though this sometimes causes problems with the URL-building interface. The developer docs recommend a solution that uses PHP; see &lt;a href="http://code.google.com/p/minify/wiki/AlternateFileLayouts"&gt;AlternateFileLayouts&lt;/a&gt;. &lt;span style="background-color:#ddd"&gt;&lt;b&gt;Update:&lt;/b&gt; I also ran into a small issue when minifying HTML: see the gray box at the end of &lt;a href="http://mrrena.blogspot.com/2011/02/how-to-minify-html-using-php-and-minify.html" target="_blank"&gt;How to Minify HTML using PHP and Minify (including final HTML output of PHP files&lt;/a&gt;) for the work-around.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you prefer to hatch a solution to the builder interface in JavaScript, you'll need to modify the code slightly. Use your IDE or text editor to open the &lt;tt&gt;_index.js&lt;/tt&gt; file found in the &lt;tt&gt;builder&lt;/tt&gt; directory.&lt;br /&gt;&lt;br /&gt;The first block of code currently reads as follows; our interest here all deal with &lt;tt&gt;_minRoot&lt;/tt&gt;:&lt;pre class="code js"&gt;var MUB = {&lt;br /&gt;    _uid : 0&lt;br /&gt;    ,_minRoot : '/min/?'&lt;br /&gt;    ,checkRewrite : function () {&lt;br /&gt;        var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1);&lt;br /&gt;        function fail() {&lt;br /&gt;            $('#minRewriteFailed')[0].className = 'topNote';&lt;br /&gt;        };&lt;br /&gt;        $.ajax({&lt;br /&gt;            url : '../f=' + testUri + '&amp;' + (new Date()).getTime()&lt;br /&gt;            ,success : function (data) {&lt;br /&gt;                if (data === '1') {&lt;br /&gt;                    MUB._minRoot = '/min/';&lt;br /&gt;                    $('span.minRoot').html('/min/');&lt;br /&gt;                } else&lt;br /&gt;                    fail();                &lt;br /&gt;            }&lt;br /&gt;            ,error : fail&lt;br /&gt;        });&lt;br /&gt;    }&lt;/pre&gt;Replace this with the following code, which is not particularly pretty, but is "smart" and will read the location of the directory when the script is called, no matter how many levels deep. The three changes are marked below by the comment &lt;tt style="color:#63d627;background-color:#1e2029"&gt;//here&lt;/tt&gt;.&lt;pre class="code js"&gt;var MUB = {&lt;br /&gt;    _uid : 0&lt;br /&gt;    ,_minRoot : location.pathname.replace('/builder/', '') + '?'//here&lt;br /&gt;    ,checkRewrite : function () {&lt;br /&gt;        var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1);&lt;br /&gt;        function fail() {&lt;br /&gt;            $('#minRewriteFailed')[0].className = 'topNote';&lt;br /&gt;        };&lt;br /&gt;        $.ajax({&lt;br /&gt;            url : '../f=' + testUri + '&amp;' + (new Date()).getTime()&lt;br /&gt;            ,success : function (data) {&lt;br /&gt;                if (data === '1') {&lt;br /&gt;                    MUB._minRoot = MUB._minRoot.replace('?', '');//here&lt;br /&gt;                    $('span.minRoot').html(MUB._minRoot);//here&lt;br /&gt;                } else&lt;br /&gt;                    fail();                &lt;br /&gt;            }&lt;br /&gt;            ,error : fail&lt;br /&gt;        });&lt;br /&gt;    }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-2813984469024040117?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/2813984469024040117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/02/how-to-easily-compress-javascript-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/2813984469024040117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/2813984469024040117'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/02/how-to-easily-compress-javascript-and.html' title='How to Easily Combine, Minify, and Cache JavaScript and CSS with 1&amp;1 (And Other Web Hosts)'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-9016517358052891930</id><published>2009-02-26T18:12:00.000-08:00</published><updated>2011-02-26T16:01:06.631-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='copy text to clipboard javascript flash 10 zero clipboard jhuckaby instantiate multiple copy button instances'/><title type='text'>Copy to Clipboard Functionality with JavaScript and Flash 10: Creating a Loop to Instantitate Multiple Copy Buttons</title><content type='html'>As a security precaution, JavaScript is not allowed to read from or write to the system clipboard. Up until Flash 10 came out with a new security feature that required copying to the clipboard to be instantiated directly from a user clicking on a Flash control, it was a simple thing to download a tiny Flash file, include it invisibly on a web page, and send it information intended for the clipboard via JavaScript. When Flash 10 came out, however, that functionality was broken.&lt;br /&gt;&lt;br /&gt;Not any more. There is a project on GoogleCode developed by &lt;a href="http://www.linkedin.com/in/jhuckaby" target="_blank"&gt;Joseph Huckaby&lt;/a&gt; known as &lt;a href="http://code.google.com/p/zeroclipboard/" target="_blank"&gt;zeroclipboard&lt;/a&gt; that is also backwards compatible with Flash 9:&lt;br /&gt;&lt;blockquote&gt;The &lt;span style="font-weight: bold;"&gt;Zero Clipboard&lt;/span&gt; library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie, and a JavaScript interface. The "Zero" signifies that the library is invisible and the user interface is left entirely up to you.&lt;br /&gt;&lt;br /&gt;This library is fully compatible with Flash Player 10, which requires that the clipboard copy operation be initiated by a user click event inside the Flash movie. This is achieved by automatically floating the invisible movie on top of a DOM element of your choice. Standard mouse events are even propagated out to your DOM element, so you can still have rollover and mouse down effects.&lt;/blockquote&gt;To date, adding the functionality to multiple controls requires you to call multiple instances, &lt;span style="font-style: italic;"&gt;unless&lt;/span&gt; the size of the control remains constant. Joe put together a demo version of the latter using JQuery on &lt;a href="http://bowser.macminicolo.net/%7Ejhuckaby/zeroclipboard/multiple.html" target="_blank"&gt;this page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I also put together a non-JQuery technique using straight JavaScript below. The code is heavily commented to explain what I am doing in each step and where everything goes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Step 1:&lt;/span&gt; Find the "glue" function and space it down one space to open a blank line. Paste the following "addon" function (including ending comma!) directly above the "glue" function in the space you opened--it recreates only that portion of the "glue" function that we still need to get hover effects to work properly.&lt;br /&gt;&lt;pre class="code js"&gt;addon: function (elem) {&lt;br /&gt;    this.domElement = ZeroClipboard.$(elem);&lt;br /&gt;},&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Step 2:&lt;/span&gt; Replace the original &lt;span style="font-weight:bold;"&gt;ZeroClipboard.Client()&lt;/span&gt; function with the following, which remembers the unique ID of each copy button (that's what the "divId" is about):&lt;br /&gt;&lt;pre class="code js"&gt;//modified ZeroClipboard.Client() function&lt;br /&gt;Client: function (elem, divId) {&lt;br /&gt;    // constructor for new simple upload client&lt;br /&gt;    this.handlers = {};&lt;br /&gt;&lt;br /&gt;    // unique ID&lt;br /&gt;    this.id = ZeroClipboard.nextId++;&lt;br /&gt;    this.movieId = 'ZeroClipboardMovie_' + this.id;&lt;br /&gt;&lt;br /&gt;    // register client with singleton to receive flash events&lt;br /&gt;    ZeroClipboard.register(this.id, this);&lt;br /&gt;&lt;br /&gt;    // create movie&lt;br /&gt;    if (elem) this.glue(elem);&lt;br /&gt;&lt;br /&gt;    // if passed, register the unique div id&lt;br /&gt;    if (divId) this.divId = divId&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Step 3:&lt;/span&gt; The following &lt;span style="font-weight:bold;"&gt;init()&lt;/span&gt; function is meant to replace the existing one. It loops through all objects of a given type looking for a particular class. Your HTML page will need to assign both a common class and a unique ID to these elements in order for it to work.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Example:&lt;/span&gt;&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;div id="unique1" class="common"&gt;Copy!&amp;lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;div id="unique2" class="common"&gt;Copy!&amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;and so on.&lt;br /&gt;&lt;br /&gt;Make sure you change the SOME_CLASS_NAME variable to whatever common class name you are using. As with the original script, you will also need to determine what text to copy and work out how that will be performed.&lt;br /&gt;&lt;pre class="code js"&gt;function init() {&lt;br /&gt;    //set the SOME_CLASS_NAME variable to whatever common class you are&lt;br /&gt;    //using. Our example above uses the class "common"&lt;br /&gt;    var SOME_CLASS_NAME = 'common';&lt;br /&gt;    //Gather together all the elements we're interested in 'divs' variable&lt;br /&gt;    //(could be any element including '*' to grab all elements), and&lt;br /&gt;    //initialize 'node' variable.&lt;br /&gt;    var divs = document.getElementsByTagName('div'),&lt;br /&gt;        node = '';&lt;br /&gt;&lt;br /&gt;    //This kind of unorthodox looping has been shown to be faster with&lt;br /&gt;    //benchmarking tests when looping over DOM elements&lt;br /&gt;    //(http://blogs.sun.com/greimer/entry/best_way_to_code_a). Note that&lt;br /&gt;    //'node' is the unique instance of the container in each loop.&lt;br /&gt;    for (; node = divs[i++];) {&lt;br /&gt;&lt;br /&gt;        //If the elements we've collected together have the class&lt;br /&gt;        //'SOME_CLASS_NAME' set, we want them. We need to&lt;br /&gt;        //ensure that they have a unique id specified as well.&lt;br /&gt;        if (node.className &amp;&amp; /SOME_CLASS_NAME/.test(node.className)) {&lt;br /&gt;&lt;br /&gt;            //We read the id of the element automatically (the reason a unique ID&lt;br /&gt;            //needs to be set in the first place).&lt;br /&gt;            var buttonId = node.id;&lt;br /&gt;            //We send the newly read ID for registration in the modified&lt;br /&gt;            //ZeroClipboard.Client function shown above.&lt;br /&gt;            clip = new ZeroClipboard.Client('', buttonId);&lt;br /&gt;            //We take advantage of new 'addon' function above.&lt;br /&gt;            clip.addon(buttonId);&lt;br /&gt;            clip.setHandCursor(true);&lt;br /&gt;            clip.addEventListener('mouseOver', function (client) {&lt;br /&gt;&lt;br /&gt;                //'client' is the unique instance of our movie container, so we need it&lt;br /&gt;                //to prefix the setText function. (Our example below uses the instantiated&lt;br /&gt;                //id of the copy button div to grab its value--$(client.divId).value&lt;br /&gt;                //--though it is not likely that this will be the copy element we want.&lt;br /&gt;                //A little ingenuity is probably in order here for the setText text.) &lt;br /&gt;                client.setText($(client.divId).value);&lt;br /&gt;&lt;br /&gt;                //Here we pass the copy button id on mouseover.&lt;br /&gt;                ZeroClipboard.$(buttonId).addClass('hover');&lt;br /&gt;            });&lt;br /&gt;            clip.addEventListener('mouseOut', function (client) {&lt;br /&gt;                //We again pass the copy button id on mouseout.&lt;br /&gt;                ZeroClipboard.$(buttonId).removeClass('hover');&lt;br /&gt;            });&lt;br /&gt;&lt;br /&gt;            //We read/set button_width and button_height.&lt;br /&gt;            var button_width = $(buttonId).offsetWidth,&lt;br /&gt;                button_height = $(buttonId).offsetHeight;&lt;br /&gt;&lt;br /&gt;            //We create a floating DIV...&lt;br /&gt;            var div = document.createElement('div'),&lt;br /&gt;                zIndex = 99;&lt;br /&gt;            //Check the z-index...&lt;br /&gt;            if ($(buttonId).style &amp;&amp; $(buttonId).style.zIndex) {&lt;br /&gt;                zIndex = parseInt($(buttonId).style.zIndex) + 1;&lt;br /&gt;            }&lt;br /&gt;            div.style.position = 'absolute';&lt;br /&gt;            div.style.left = 0;&lt;br /&gt;            div.style.top = 0;&lt;br /&gt;            div.style.width = button_width + 'px';&lt;br /&gt;            div.style.height = button_height + 'px';&lt;br /&gt;            div.style.zIndex = zIndex;&lt;br /&gt;            //We need the button id so that we can append its movie instance.&lt;br /&gt;            $(buttonId).appendChild(div);&lt;br /&gt;            //All finished! :)&lt;br /&gt;            div.innerHTML = clip.getHTML(button_width, button_height);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Step 4:&lt;/span&gt; As mentioned on the issue report above, I also ran into a tiny (and easily fixable) error in the &lt;span style="font-weight: bold;"&gt;ZeroClipboard.$&lt;/span&gt; function dealing with the &lt;span style="font-weight: bold;"&gt;removeClass&lt;/span&gt; function inside of it. Those lines can be replaced by these; we just test to see if the class attribute is present, and if not, we set it to an empty value:&lt;br /&gt;&lt;pre class="code js"&gt;if (this.className) {&lt;br /&gt;    this.className = this.className.replace(new&lt;br /&gt;    RegExp('\\s*' + name + '\\s*'), ' ').replace(/^\s+/, '').replace(/\s+$/, '');&lt;br /&gt;}&lt;br /&gt;else this.className = '';&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-9016517358052891930?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/9016517358052891930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/02/copy-to-clipboard-functionality-with.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9016517358052891930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/9016517358052891930'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/02/copy-to-clipboard-functionality-with.html' title='Copy to Clipboard Functionality with JavaScript and Flash 10: Creating a Loop to Instantitate Multiple Copy Buttons'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-6236355622035933429</id><published>2009-02-26T17:46:00.001-08:00</published><updated>2009-02-26T20:04:08.074-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unblock .chm help file won&apos;t open windows vista xp navigation to the webpage was canceled'/><title type='text'>Opening/Unblocking .CHM Help Files on Windows XP SP2 or Vista</title><content type='html'>&lt;br /&gt;In one of my coding projects, I created a .chm help file, and loaded it to the server. However, it didn't survive the round trip: when I attempted to open a downloaded copy in Windows Vista, I saw the following message (click to view full size):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try{parent.deselectBloggerImageGracefully();}catch(e){}" href="http://3.bp.blogspot.com/_O3igLjSA20U/SadGcxHq3lI/AAAAAAAAABQ/henViA7Kn3k/s1600-h/nav_canceled.png" target="_blogger"&gt;&lt;img style="display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:320px;height:229px" src="http://3.bp.blogspot.com/_O3igLjSA20U/SadGcxHq3lI/AAAAAAAAABQ/henViA7Kn3k/s320/nav_canceled.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5307288145915207250" /&gt;&lt;/a&gt;&lt;br /&gt;I did not for certain what was wrong, though I suspected it was some kind of security issue on Vista. I was correct.&lt;br /&gt;&lt;br /&gt;.chm files that have been downloaded from the Internet are considered a security risk on both Windows XP and Vista. Bill Evjen blogs about the solution &lt;a href="http://geekswithblogs.net/evjen/archive/2006/06/29/83567.aspx" target="_blank"&gt;here&lt;/a&gt;; the solution, as he reports, is simple. Just right-click the file, select &lt;b&gt;Properties&lt;/b&gt;, and then click &lt;b&gt;Unblock&lt;/b&gt; (click to view full size):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try{parent.deselectBloggerImageGracefully();}catch(e){}" href="http://1.bp.blogspot.com/_O3igLjSA20U/SadKGzmgW2I/AAAAAAAAAB8/GuNlmGOafLo/s1600-h/unblock.png" target="_blogger"&gt;&lt;img style="display:block;margin:0px auto 10px;text-align:center;cursor:pointer;cursor:hand;width:235px;height:320px" src="http://1.bp.blogspot.com/_O3igLjSA20U/SadKGzmgW2I/AAAAAAAAAB8/GuNlmGOafLo/s320/unblock.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5307292166670801762" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-6236355622035933429?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/6236355622035933429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/02/openingunblocking-chm-help-files-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/6236355622035933429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/6236355622035933429'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/02/openingunblocking-chm-help-files-on.html' title='Opening/Unblocking .CHM Help Files on Windows XP SP2 or Vista'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_O3igLjSA20U/SadGcxHq3lI/AAAAAAAAABQ/henViA7Kn3k/s72-c/nav_canceled.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-8451207780231535086</id><published>2009-02-14T07:18:00.001-08:00</published><updated>2010-10-09T19:39:08.496-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javasscript range selection getselection preserve html clonecontents'/><title type='text'>Getting the HTML of a Range Created in JavaScript</title><content type='html'>&lt;br /&gt;Working on a mainly JavaScript-driven rich-text editor for the discussion forum on &lt;a href="http://www.mrrena.com" target="_blank"&gt;Mr. Renaissance&lt;/a&gt;, I wanted to include a feature that automatically inserted block quotations. Two days after the editor's debut, I suddenly noticed that this feature was losing its formatting: all line breaks and markup were gone, in its place one large, crunched-together paragraph that even ran sentences together in places.&lt;br /&gt;&lt;br /&gt;A bit of Googling revealed that using range to retrieve the user's selection returns plain text (at least in non-IE browsers), not its formatted HTML:&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;The contents of &lt;span style="font-family:courier"&gt;userSelection&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The userSelection variable is now either a Mozilla Selection or a Microsoft Text Range object. As such it grants access to all methods and properties defined on such objects.&lt;br /&gt;&lt;br /&gt;However, the Mozilla Selection object that userSelection refers to in W3C-compliant browsers also contains the text the user has selected (&lt;span style="font-weight:bold;"&gt;as text, not as HTML&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:90%"&gt;From &lt;a href="http://www.quirksmode.org/dom/range_intro.html" target="_blank"&gt;Introduction to Range&lt;/a&gt;, emphasis mine.&lt;/span&gt;&lt;/blockquote&gt;Frustrating, to say the least. I won't go into a list of all the things I tried, but I finally found the following (slightly modified) snippet of code at &lt;a href="http://snipplr.com/view/10912/get-html-of-selection/" target="_blank"&gt;Snipplr&lt;/a&gt;, courtesy of David King of the entirely open-source &lt;a href="http://oopstudios.com/" target="_blank"&gt;OOPStudios&lt;/a&gt; in Newcastle, UK:&lt;br /&gt;&lt;pre class="code js"&gt;var getSelectionHTML = function() {&lt;br /&gt;    var s;&lt;br /&gt;    if (window.getSelection) {&lt;br /&gt;        //W3C Ranges&lt;br /&gt;        s = window.getSelection();&lt;br /&gt;        //Get the range:&lt;br /&gt;        if (s.getRangeAt) var r = s.getRangeAt(0);&lt;br /&gt;        else {&lt;br /&gt;            var r = document.createRange();&lt;br /&gt;            r.setStart(s.anchorNode, s.anchorOffset);&lt;br /&gt;            r.setEnd(s.focusNode, s.focusOffset);&lt;br /&gt;        }&lt;br /&gt;        //And the HTML:&lt;br /&gt;        var clonedSelection = r.cloneContents(),&lt;br /&gt;            div = document.createElement('div');&lt;br /&gt;        div.appendChild(clonedSelection);&lt;br /&gt;        return div.innerHTML;&lt;br /&gt;    } else if (document.selection) {&lt;br /&gt;        //Explorer selection, return the HTML&lt;br /&gt;        s = document.selection.createRange();&lt;br /&gt;        return s.htmlText;&lt;br /&gt;    } else {&lt;br /&gt;        return '';&lt;br /&gt;    }&lt;br /&gt;};&lt;/pre&gt;I am pleased to report that David has created a wonderful little function that returns the HTML of the user's selection rather than just plain, unformatted text.&lt;br /&gt;&lt;br /&gt;&lt;i style="color: rgb(102, 51, 51);"&gt;&lt;b&gt;Note:&lt;/b&gt; If you want to simulate the action of &lt;b&gt;Cut&lt;/b&gt; (rather than &lt;b&gt;Paste&lt;/b&gt;), change &lt;b&gt;r.cloneContents()&lt;/b&gt; to &lt;b&gt;r.extractContents()&lt;/b&gt;. Normally, there would be no reason to do so, but it is a possibility.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-8451207780231535086?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/8451207780231535086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/02/getting-html-of-range-created-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8451207780231535086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8451207780231535086'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/02/getting-html-of-range-created-in.html' title='Getting the HTML of a Range Created in JavaScript'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-7264481371816694258</id><published>2009-02-13T09:09:00.000-08:00</published><updated>2011-03-18T22:58:17.685-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript invalid range in character class error console Firebug'/><title type='text'>"invalid range in character class": JavaScript Error Solved</title><content type='html'>&lt;br /&gt;&lt;span style="color: #c05f04;"&gt;"&lt;b&gt;invalid range in character class&lt;/b&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It was maddening. &lt;a href="http://getfirebug.com/" target="_blank"&gt;Firebug&lt;/a&gt; showed this error, but gave no additional information: not even a script or function name, much less a line number. Googling didn't help very much: it suggested that it was an error involving regular expressions. Thousands and thousands of lines of code and at least half a dozen external JavaScript files later, I'm pleased to say that I discovered what the message means and now want to pass along the knowledge in hopes of saving someone else endless hours.&lt;br /&gt;&lt;br /&gt;The short answer is that the word &lt;span style="color: #c05f04;"&gt;range&lt;/span&gt; refers to a "range of values," say the range from 1 to 100 typically written as &lt;span style="font-weight: bold;"&gt;1-100&lt;/span&gt;. Notice that my shorthand for range involves a dash or minus sign between the &lt;span style="font-weight: bold;"&gt;1&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;100&lt;/span&gt;. Therein lies the problem. If you want a regular expression to test for the presence of a dash/minus sign &lt;span style="font-style: italic;"&gt;as&lt;/span&gt; a dash/minus sign, it needs to be escaped with a backslash, or else some browsers (Firefox 2 in this case) think that you are attempting to express a range instead and freak out accordingly.&lt;br /&gt;&lt;br /&gt;In particular, I had one tiny function that was used on only one form dealing with phone numbers. Valid data included a blank space, any number, a dash, or a right or left parenthesis to accommodate a number such as &lt;span style="font-weight: bold;"&gt;(555) 555-5555&lt;/span&gt;. It wasn't crucial that users type in their phone number in any certain way, I just try to get in the practice of filtering my data both client and server side.&lt;br /&gt;&lt;br /&gt;In a test copy of the production environment, I first eliminated my scripts one by one until the offending error disappeared. Then I brought that script back, eliminating each function body until the error disappeared. It turned out to be this tiny function, short for "is integer" though obviously adding the space, dash, and parentheses:&lt;br /&gt;&lt;pre class="code js"&gt;var isInt = function(s) {&lt;br /&gt;    s.value = s.value.replace(/[^\d-()\s]+/g, '');&lt;br /&gt;};&lt;/pre&gt;Notice that the &lt;span style="font-weight: bold;color: #c05f04;"&gt;-&lt;/span&gt; character is not escaped. Now here's the fix:&lt;br /&gt;&lt;pre class="code js"&gt;var isInt = function(s) {&lt;br /&gt;    s.value = s.value.replace(/[^\d\-()\s]+/g, '');&lt;br /&gt;};&lt;/pre&gt;I have now added the escape &lt;span style="font-weight: bold;color: #c05f04;"&gt;\&lt;/span&gt;-, and thousands of lines of code are now working again. Hopefully this post will save someone else hours of frustration.&lt;br /&gt;&lt;br/&gt;&lt;span style="background-color:#ddd"&gt;&lt;b&gt;Update:&lt;/b&gt; As Earl suggests in his comment below, you can also move the dash to the end of your regular expression square brackets without using an escape: &lt;tt&gt;/[^\d()\s-]+/g&lt;/tt&gt;. 5n1p3r also brings up the point below that if you're using the RegExp object and an escape, you need two backslashes, the first to escape your escape.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-7264481371816694258?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/7264481371816694258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/02/invalid-range-in-character-class.html#comment-form' title='32 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7264481371816694258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/7264481371816694258'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/02/invalid-range-in-character-class.html' title='&quot;invalid range in character class&quot;: JavaScript Error Solved'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>32</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-351676102372868959</id><published>2009-01-27T17:59:00.000-08:00</published><updated>2011-06-04T17:43:22.596-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gzip g-zip compression php text-based files 1and1 shared hosting'/><title type='text'>How to Compress PHP and Other Text-Based Files with 1&amp;1 (and Other Shared Hosts)</title><content type='html'>&lt;br /&gt;If you have a shared Linux hosting package through &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt;, you have no doubt discovered that &lt;a href="http://www.blog.highub.com/apache/http-server/htaccess-gzip-for-faster-loading-and-bandwidth-saving/" target="_blank"&gt;the usual method&lt;/a&gt; of changing your .htaccess file does not allow you to compress your files using Apache because 1&amp;amp;1 has disabled the mod_deflate and mod_gzip modules; you also cannot specify php values in .htaccess files in 1&amp;amp;1 shared packages, so a solution &lt;a href="http://www.jhuskisson.com/articles/adding-gzip-compression-to-your-site-via-htaccess" target="_blank"&gt;like this one&lt;/a&gt; also will not work. However, there is a solution that does work, and it works even on the most basic &lt;a href="http://order.1and1.com/xml/order/Hosting?k_id=7887069&amp;amp;__frame=_top" target="_blank"&gt;1&amp;amp;1 Beginner’s Package&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i style="color: #663333;"&gt;&lt;b&gt;Note:&lt;/b&gt; If you plan to implement the Minify! option I blog about in &lt;a href="http://mrrena.blogspot.com/2009/02/how-to-easily-compress-javascript-and.html" target="_blank"&gt;How to Easily Combine, Minify, and Cache JavaScript and CSS...&lt;/a&gt;, you can safely skip steps 1 and 2 and include only the first line shown in step 3.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 1:&lt;/h2&gt;Determine what your root path is; if you are using a 1&amp;amp;1 package, it will look something like this:&lt;br /&gt;&lt;pre class="code js"&gt;/kunden/homepages/12/d123456789/htdocs/&lt;/pre&gt;You can do that by creating a text file in Notepad or other editor,&lt;span style="color:#900"&gt;*&lt;/span&gt; entering the following lines, then saving it with as &lt;tt&gt;phpinfo&lt;/tt&gt; (or whatever you want) followed by the &lt;tt&gt;.php&lt;/tt&gt; extension.&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;phpinfo();&lt;br /&gt;?&amp;gt;&lt;/pre&gt;&lt;span style="font-size: 80%;"&gt;(&lt;span style="color:#900"&gt;*&lt;/span&gt; If you’re using Notepad, you’ll probably want to put quotation marks around the name "phpinfo.php" when saving, to keep it from saving the file as &lt;tt style="font-size:10px"&gt;phpinfo.php.txt&lt;/tt&gt;. Personally, I like either &lt;a href="http://www.geany.org/" target="_blank"&gt;Geany&lt;/a&gt; or &lt;a href="http://notepad-plus.sourceforge.net/uk/download.php" target="_blank"&gt;Notepad++&lt;/a&gt; on Windows or &lt;a href="http://www.activestate.com/komodo-edit" target="_blank"&gt;Komodo Edit&lt;/a&gt; on Mac; Komodo Edit and Geany come in all three flavors, Windows, Linux, or Mac, with Geany supporting the Mac only &lt;a href="http://www.macports.org/ports.php?by=name&amp;substr=geany" target="_blank"&gt;via a port&lt;/a&gt;. Notepad++ is a Windows-only program. All three IDEs rely on the &lt;a href="http://www.scintilla.org/" target="_blank"&gt;Scintilla editor&lt;/a&gt; as their base.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now browse to the newly uploaded file with your web browser and search for &lt;tt&gt;DOCUMENT_ROOT&lt;/tt&gt;. This variable will tell you what the exact path is to your server.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 2:&lt;/h2&gt;Now create another php file in the same way, this time adding the following information so that when you compress your CSS and JS files, they are served with the right headers, or else they will not load properly in Firefox and other browsers:&lt;br /&gt;&lt;pre class="code js"&gt;&amp;lt;?php&lt;br /&gt;$pathinfo = pathinfo($_ENV['SCRIPT_FILENAME']);&lt;br /&gt;$extension = $pathinfo['extension'];&lt;br /&gt;if ($extension == 'css') {&lt;br /&gt;    header('Content-type: text/css; charset=utf-8');&lt;br /&gt;}&lt;br /&gt;if ($extension == 'js') {&lt;br /&gt;    header('Content-type: text/javascript; charset=utf-8');&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;/pre&gt;Make sure that you &lt;a href="http://www.php.net/manual/en/function.header.php" target="_blank"&gt;don’t space down between the lines or add an extra space at the end&lt;/a&gt;, and save this file as &lt;tt&gt;headers.php&lt;/tt&gt;, uploading it to wherever you keep your scripts. For the sake of this example, I will assume that you store your scripts in a directory named &lt;tt&gt;webscripts&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color:#ddd"&gt;[&lt;b&gt;Update:&lt;/b&gt; As Brett reminds me in the comment below, you have now given PHP control of rendering your pages, so you will also need to include in this file any other header information you know you’ll need by declaring each header on its own line. For example, to set the "Vary" header, you'd add this extra line:&lt;br /&gt;&lt;tt style="margin-left:30px"&gt;header('Vary: Accept Encoding');&lt;/tt&gt;&lt;br /&gt;Based on the readership of these articles, this will be particularly useful when optimizing for speed using a free tool like Google's &lt;a href="http://code.google.com/speed/page-speed/download.html" target="_blank"&gt;Page Speed&lt;/a&gt;. Add as many extra headers as you need, one per line.]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 3:&lt;/h2&gt;Create a third file, this time a PHP configuration file, entering the following information (though of course changed with the information you looked up in step 1 and whatever directory you use for step 2—unfortunately, you can’t use environmental variables in .ini files, as they are straight ASCII):&lt;br /&gt;&lt;pre class="code js"&gt;&lt;br /&gt;output_handler=ob_gzhandler&lt;br /&gt;auto_prepend_file=/kunden/homepages/12/d123456789/htdocs/webscripts/headers.php&lt;/pre&gt;Name your configuration file the conventional &lt;tt&gt;php.ini&lt;/tt&gt; and save it.&lt;br /&gt;&lt;br /&gt;The first line tells the server to use PHP’s built-in g-zip handler for compression; the second line points to the exact location of the file you created in step 2: &lt;tt&gt;/kunden/homepages/12/d123456789/htdocs/&lt;/tt&gt; is the document root you located in step 1, and &lt;tt&gt;webscripts/&lt;/tt&gt; is the directory where you uploaded the &lt;tt&gt;headers.php&lt;/tt&gt; script. &lt;tt&gt;auto_prepend_file&lt;/tt&gt; tells the server to automatically “prepend,” or “attach to the beginning of” all pages it serves &lt;span style="font-size: 90%;"&gt;(versus &lt;tt style="font-size: 11px;"&gt;auto_append_file&lt;/tt&gt;, which would “append,” or “attach to the end” of all files)&lt;/span&gt;. The if/then conditional statements in step 2 ensures that the &lt;tt&gt;headers.php&lt;/tt&gt; file will only attach headers if the file in question has a .css or .js extension.&lt;br /&gt;&lt;br /&gt;&lt;i style="color: #663333;"&gt;&lt;b&gt;Note:&lt;/b&gt; Check with your web host. With 1&amp;amp;1, at least, you will need to upload a copy of your &lt;tt&gt;php.ini&lt;/tt&gt; file to EVERY directory containing files you want compressed.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2 id="step4"&gt;Step 4:&lt;/h2&gt;Create an .htaccess file or modify your existing one by adding the following line &lt;span style="font-size: 90%;"&gt;(if you’re not familiar with an .htaccess file, see &lt;a href="http://www.bloghash.com/2006/11/beginners-guide-to-htaccess-file-with-examples/" target="_blank"&gt;here&lt;/a&gt;)&lt;/span&gt;:&lt;br /&gt;&lt;pre class="code js"&gt;&lt;br /&gt;AddType x-mapp-php5 .php .shtml .html .htm .txt .js .css&lt;/pre&gt;This line tells the server to process all the file extensions specified through PHP5; change it to x-mapp-php4 if you want to use PHP4 instead. You can add other extensions or take away from the ones here: whatever extensions are listed on the line after the &lt;tt&gt;x-mapp-php5&lt;/tt&gt; will be processed via PHP.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #663300; font-weight: bold; font-size: 80%"&gt;CAUTION:&lt;/span&gt;&lt;span style="color: #663300;"&gt; If you plan to implement the Minify! solution I blog about in &lt;a href="http://mrrena.blogspot.com/2009/02/how-to-easily-compress-javascript-and.html" style="color: #663300;" target="_blank"&gt;How to Easily Combine, Minify, and Cache JavaScript and CSS...&lt;/a&gt;, I &lt;span style="color: #663300; font-weight: bold;"&gt;do not&lt;/span&gt; recommend including the .css and .js file extensions on this line. Doing so processes these files twice, as Minify! already has its own mechanism for compressing files. And, as a result of double compression, certain versions of Internet Explorer choke and die silently.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="background-color:#ddd"&gt;[&lt;b&gt;June 4, 2011 Update:&lt;/b&gt; I was setting up my sister's site recently, also on a 1&amp;amp;1 Beginner&amp;#8217;s Package, and the style sheets were not working correctly. The fix was to add this line to the .htaccess file immediately above the line shown in the example above:&lt;pre class="code js"&gt;&lt;br /&gt;RemoveHandler .css&lt;br /&gt;&lt;/pre&gt;I first tried removing &lt;i&gt;all&lt;/i&gt; file extensions I was using, including &lt;tt&gt;.htm&lt;/tt&gt;, but this caused problems. Just know that you have the option of removing file handlers and play around with it as needed.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 5:&lt;/h2&gt;Now test to see whether or not your pages are being compressed by using the free tool from &lt;a href="http://www.gidnetwork.com/tools/gzip-test.php" target="_blank"&gt;GIDNetwork&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-351676102372868959?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/351676102372868959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html#comment-form' title='25 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/351676102372868959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/351676102372868959'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/01/how-to-compress-php-and-other-text.html' title='How to Compress PHP and Other Text-Based Files with 1&amp;1 (and Other Shared Hosts)'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>25</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-8040225755960506191</id><published>2009-01-20T06:15:00.000-08:00</published><updated>2011-03-08T17:42:32.633-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compress g-zip gzip cspan perl cgi-scripts 1and1 shared hosting'/><title type='text'>How to Compress Perl/CGI-Scripts with 1&amp;1 (and Other Shared Hosts)</title><content type='html'>According to Yahoo’s &lt;a href="http://developer.yahoo.com/performance/rules.html#gzip" target="_blank"&gt;Best Practices for Speeding up Websites&lt;/a&gt;, it is a good idea to compress (gzip) all text-based files, including php, css, javascript, and the topic of today: Perl CGI scripts. However, if you are hosting your website on &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt; (or other shared hosting package&lt;a href="#ast" id="back"&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;*&lt;/span&gt;&lt;/a&gt;), you probably know of no easy way to g-zip your files. I first tried the method outlined in the article &lt;a href="http://encodable.com/install_perl_modules_on_shared_hosting/" target="_blank"&gt;How To Install Perl Modules On Shared Hosting&lt;/a&gt;, but I couldn’t get it to work quite like the author suggested. With a little experimentation, however, I found a way to gzip Perl files on a &lt;a href="http://order.1and1.com/xml/order/Hosting?k_id=7887069&amp;amp;__frame=_top" target="_blank"&gt;1&amp;amp;1 Beginner’s Package&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1:&lt;/b&gt;&lt;br /&gt;Download a copy of &lt;a href="http://cpan.uwinnipeg.ca/dist/CGI-WebGzip" target="_blank"&gt;CGI-WebGzip&lt;/a&gt; from CSPAN. Unzip it, and extract WebGzip.pm, the file you need. &lt;span class="p10"&gt;(If you don’t have the software to unzip tar.gz files, download a copy of the free &lt;a href="http://www.7-zip.org/download.html" target="_blank"&gt;7-zip&lt;/a&gt; for your operating system, and tell your computer to use the 7-Zip File Manager (7zFM.exe) to open files with the tar.gz extension. Such files are zipped twice, so you'll have to unzip the .gz part, then the .tar part before you finally get to your files.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 2:&lt;/b&gt;&lt;br /&gt;Open WebGzip.pm and take out take out the &lt;tt&gt;CGI::&lt;/tt&gt; on the very first line, changing it from:&lt;br /&gt;&lt;pre class="code js"&gt;package CGI::WebGzip;&lt;/pre&gt;to:&lt;br /&gt;&lt;pre class="code js"&gt;package WebGzip;&lt;/pre&gt;&lt;b&gt;Step 3:&lt;/b&gt;&lt;br /&gt;Upload the WebGzip.pm file to the same directory where the Perl CGI-scripts you want to compress live.&lt;br /&gt;&lt;br /&gt;Now open your Perl file. On the second line under the &lt;a href="http://www.computerhope.com/jargon/s/shebang.htm" target="_blank"&gt;Perl shebang&lt;/a&gt; (#!/usr/local/bin/perl), add the following:&lt;br /&gt;&lt;pre class="code js"&gt;use lib "$ENV{DOCUMENT_ROOT}/path_to_Perl_scripts"&lt;/pre&gt;where you change &lt;tt&gt;path_to_Perl_scripts&lt;/tt&gt; to the directory from root in which they live.&lt;br /&gt;&lt;br /&gt;For example, if you have your Perl files stored in a directory called &lt;tt&gt;Perl&lt;/tt&gt; inside another directory called &lt;tt&gt;scripts&lt;/tt&gt;, the line would read &lt;tt&gt;use lib "$ENV{DOCUMENT_ROOT}/scripts/Perl"&lt;/tt&gt;. This tells the script to use the library located in such-and-such directory from the root.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 4:&lt;/b&gt;&lt;br /&gt;Somewhere in your Perl script should be the following line or one very similar:&lt;br /&gt;&lt;pre class="code js"&gt;print "Content-type: text/html\n\n";&lt;/pre&gt;which tells the script to print the output to the screen as HTML. Directly above that line, add the following line:&lt;br /&gt;&lt;pre class="code js"&gt;use WebGzip;&lt;br /&gt;print "Content-type: text/html\n\n";&lt;/pre&gt;This line tells the script to include the module you just uploaded when it outputs its contents.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 5:&lt;/b&gt;&lt;br /&gt;First check and make sure that your Perl script loads as expected: it is possible that you left a semi-colon off somewhere or got something a bit out of place. Once that is done, test to see that your file is being compressed by entering the URL into the free testing tool from &lt;a href="http://www.gidnetwork.com/tools/gzip-test.php" target="_blank"&gt;GIDNetwork&lt;/a&gt;. If your page is being compressed, it will show you a green &lt;b style="color: rgb(0, 153, 0);"&gt;Yes&lt;/b&gt;, if not you’ll see a red &lt;b style="color: rgb(255, 0, 0);"&gt;No&lt;/b&gt;. If it is not working correctly, go back to step four and see if there are any other such lines in the script. If you are not using a &lt;a href="http://www.1and1.com/?k_id=7887069" target="_blank"&gt;1&amp;amp;1&lt;/a&gt; hosting package, you might also look at the asterisk below.&lt;a href="#ast"&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;*&lt;/span&gt;&lt;/a&gt;&lt;p  style="font-size:90%;"&gt;&lt;a id="ast" href="#back"&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;*&lt;/span&gt;&lt;/a&gt; Your server will need to have the Compress::Zlib module installed. It is possible, even if it is not installed, you could use a method similar to the one outlined in this document to include it: you can &lt;a href="http://search.cpan.org/dist/Compress-Zlib/" target="_blank"&gt;download it here&lt;/a&gt;. If you’re not sure if you have it installed and you’re not sure how to check, try the directions here and see if it works. If it works, you have Compress::Zlib installed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-8040225755960506191?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/8040225755960506191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/01/how-to-compress-perl-cgi-scripts-with-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8040225755960506191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/8040225755960506191'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/01/how-to-compress-perl-cgi-scripts-with-1.html' title='How to Compress Perl/CGI-Scripts with 1&amp;amp;1 (and Other Shared Hosts)'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-29877930.post-3161329266202134398</id><published>2009-01-20T00:34:00.000-08:00</published><updated>2010-10-09T19:45:17.316-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ad redirection imediablast rouge sites annoyances'/><title type='text'>Stay Away From Imediablast.com! Ad Redirection Annoyance</title><content type='html'>If you are a web content provider, you might think twice before doing business with imediablast.com. They employ rouge ads that forcibly redirect users from the webpage they intended to view. A recent ad campaign involving bigbrandpromotions.com uses the following URL:&lt;br /&gt;&lt;br /&gt;http://imediablast.com/adserve/www/delivery/ajs.php&lt;br /&gt;&lt;br /&gt;The original link that led to bigbrandpromotions actually had a lot more garbage appended to the end of it: right-click &lt;a href="http://imediablast.com/adserve/www/delivery/ajs.php?zoneid=139&amp;amp;source=_blank&amp;amp;target=_blank&amp;amp;cb=77416316793&amp;amp;charset=ISO-8859-1&amp;amp;loc=fill_in_the_server&amp;amp;referer=fill_in_the_server&amp;amp;ct0=http%253A%252F%252Fredvase.bravenet.com%252Ftrack%252Fclick%252F10505%252F138%252F1232434119%253Furl%253D" target="_blank"&gt;here&lt;/a&gt; and select "Copy Link Location" if you want to see it--otherwise, you can safely click on it.&lt;br /&gt;&lt;br /&gt;If you click on it, it will serve up a raw JavaScript file pre-processed via PHP. It uses a random variable prefixed with &lt;span style="font-weight: bold;"&gt;OX_&lt;/span&gt; to help ensure it isn't blocked. Specifically, if you click on that link, this is what you'll see (except that the variable, being random, will differ somewhat):&lt;br /&gt;&lt;pre class="code js"&gt;var OX_600eac89 = ''; &lt;br /&gt;OX_600eac89 += "&lt;"+"script type=\"text/JavaScript\"&gt;\n"; &lt;br /&gt;OX_600eac89 += "&lt;"+"!--\n";&lt;br /&gt;//below is the offending line&lt;br /&gt;OX_600eac89 += "setTimeout(\"top.location.href = \'http://www.incentaclick.com/nclick.php?id=13735&amp;cid=5677\';\",1000);\n";&lt;br /&gt;//above is the offending line&lt;br /&gt;OX_600eac89 += "--&gt;\n"; &lt;br /&gt;OX_600eac89 += "&lt;"+"/script&gt;&lt;"+"div id=\'beacon_de907c62c2\' style=\'position: absolute; left: 0px; top: 0px;&lt;br /&gt;visibility: hidden;\'&gt;&lt;"+"img src=\'http://imediablast.com/adserve/www/delivery/lg.php?bannerid=626&amp;amp;campaignid=87&amp;amp;zoneid=139&amp;amp;source=_blank&amp;amp;channel_ids=,&amp;amp;loc=fill_in_the_server&amp;amp;referer=fill_in_the_server&amp;amp;cb=de907c62c2\'&lt;br /&gt;width=\'0\' height=\'0\' alt=\'\' style=\'width: 0px; height: 0px;\' /&gt;&lt;"+"/div&gt;\n";&lt;br /&gt;document.write(OX_600eac89);&lt;/pre&gt;I have marked the offending line with comments. Basically, it sets a second-long time-out, then redirects to a click tracker that in turn redirects to a come-on from bigbrandpromotions.com. If you are familiar with JavaScript, you'll easily recognize the &lt;span style="font-weight: bold;"&gt;top.location.href =&lt;/span&gt; line, which is responsible for the redirect. So, users who wanted to access a completely different webpage suddenly find themselves forcibly redirected to the page shown in the screen shot below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_O3igLjSA20U/SXWbL7SGjXI/AAAAAAAAAAM/uvQtB75P1bk/s1600-h/full.png" target="_blank"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 280px;" src="http://1.bp.blogspot.com/_O3igLjSA20U/SXWbL7SGjXI/AAAAAAAAAAM/uvQtB75P1bk/s320/full.png" alt="" id="BLOGGER_PHOTO_ID_5293307566238371186" border="0" /&gt;&lt;/a&gt;So then, stay away from imediablast.com if you value your clients! (I also find it interesting that it seems to be tied with bravenet.com as well, notorious for junking things up with billions of blinking ads.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/29877930-3161329266202134398?l=mrrena.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrrena.blogspot.com/feeds/3161329266202134398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrrena.blogspot.com/2009/01/stay-away-from-imediablastcom.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/3161329266202134398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/29877930/posts/default/3161329266202134398'/><link rel='alternate' type='text/html' href='http://mrrena.blogspot.com/2009/01/stay-away-from-imediablastcom.html' title='Stay Away From Imediablast.com! Ad Redirection Annoyance'/><author><name>mrrena</name><uri>http://www.blogger.com/profile/03300734490313630686</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='25' src='http://2.bp.blogspot.com/_O3igLjSA20U/Sc1B69Jv_QI/AAAAAAAAAC0/ff_q385OHEk/S220/Admin.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_O3igLjSA20U/SXWbL7SGjXI/AAAAAAAAAAM/uvQtB75P1bk/s72-c/full.png' height='72' width='72'/><thr:total>6</thr:total></entry></feed>
