<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Novak in Academia</title>
	<atom:link href="http://brooknovak.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://brooknovak.wordpress.com</link>
	<description>Overcoming the "ARGS!" in software development</description>
	<lastBuildDate>Mon, 07 Feb 2011 06:35:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='brooknovak.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Novak in Academia</title>
		<link>http://brooknovak.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://brooknovak.wordpress.com/osd.xml" title="Novak in Academia" />
	<atom:link rel='hub' href='http://brooknovak.wordpress.com/?pushpress=hub'/>
		<item>
		<title>First public release of the Seaweed Plugin</title>
		<link>http://brooknovak.wordpress.com/2010/01/07/first-public-release-of-the-seaweed-plugin/</link>
		<comments>http://brooknovak.wordpress.com/2010/01/07/first-public-release-of-the-seaweed-plugin/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 22:49:56 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[editing]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[experiment]]></category>
		<category><![CDATA[plugin. wordpress plugin]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[seamless]]></category>
		<category><![CDATA[seaweed]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wpmu]]></category>
		<category><![CDATA[wysiwyg]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=345</guid>
		<description><![CDATA[First release of my Seaweed plugin for Wordpress available today!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=345&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the past year I have been developing a JavaScript API called &#8220;Seaweed&#8221; (The seamless web editor &#8211; see http://seaweed-editor.com) for my masters project at the University of Waikato. The API allows people to directly edito content on a web page without switching to edit mode. (It is kinda of like the &#8220;contentEditable&#8221; attribute &#8211; but with more control and better browser support). Play with a demo at <a href="http://seaweed-editor.com/demo">http://seaweed-editor.com/demo</a>.</p>
<p>My research is to investigate various aspects of &#8220;seamless editing&#8221;. I decided to use WordPress to power this investigation by developing a plugin that allows WordPress users to edit their posts/pages/comments directly on their Blog &#8211; without the need to use the administrator! Try it now at <a href="http://wordpress.org/extend/plugins/seaweed">http://wordpress.org/extend/plugins/seaweed</a>. NOTE: WordPress.com users may have to wait a while for WordPress.com to host the plugin.</p>
<p>Seamless editing is cool, it beats WYSIWYG editing and HTML source editing any day (of coarse there are situations where the old-school way of editing may be more beneficial). When users install this plugin, they must first sign up to my Experiment which gathers usage data. If you have WordPress and you can install plugins &#8211; please install mine and sign up now! <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />Posted in News Tagged: ajax, editing, editor, experiment, plugin. wordpress plugin, release, research, seamless, seaweed, software, wordpress, wpmu, wysiwyg <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/345/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/345/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/345/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=345&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2010/01/07/first-public-release-of-the-seaweed-plugin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
		<item>
		<title>Inferring the Locale text direction with Javascript</title>
		<link>http://brooknovak.wordpress.com/2009/10/03/inferring-the-locale-text-direction-with-javascript/</link>
		<comments>http://brooknovak.wordpress.com/2009/10/03/inferring-the-locale-text-direction-with-javascript/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 11:07:09 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Programming Problems - Resolved]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css2]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[detect]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[dir]]></category>
		<category><![CDATA[direction]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[locale]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[text-direction]]></category>
		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=339</guid>
		<description><![CDATA[A hack to detect which is the locale text direction (e.g. left-to-right for English or right-to-left for Hebrew) using JavaScript.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=339&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a hack to detect which is the locale text direction (e.g. left-to-right for English or right-to-left for Hebrew) using JavaScript:</p>
<p><pre class="brush: jscript;">
/**
 * Detects locale text direction...
 * @return {String} &quot;ltr&quot; or &quot;rtl&quot;
 */
function detectTextDir() {
   var container = document.createElement(&quot;p&quot;);
    container.style.margin = &quot;0 0 0 0&quot;;
    container.style.padding = &quot;0 0 0 0&quot;;
    // container.style.textAlign = &quot;start&quot;; // If CSS 3+ 
    container.style.textAlign = &quot;&quot;; // Explicitly override text align that might be assigned via style sheets
    
    var span = document.createElement(&quot;span&quot;);
    span.innerHTML = &quot;X&quot;;
    
    container.appendChild(span);
    document.body.appendChild(container);
    
    // LTR if text position is nearer left of container, RTL if text position is nearer right of container
    var localeDirection = span.offsetLeft &lt; (container.offsetWidth - (span.offsetLeft + span.offsetWidth)) ?
        &quot;ltr&quot; : 
        &quot;rtl&quot;;
       
    document.body.removeChild(container);

    return localeDirection;
}

</pre></p>
<p>A limitation is that it doesn&#8217;t work if there is a style sheet present which explicitly assigns a text-align value other than &#8220;start&#8221; for paragraphs directly in the document body. You could probably tweak the idea to use something more obscure like an address block to reduce chances of this happening.</p>
<br />Posted in Programming Problems - Resolved, Web Programming Tagged: code, css, css2, css3, detect, detection, dir, direction, hack, html, javascript, js, jscript, language, locale, script, text-direction, web 2.0 <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/339/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/339/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/339/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=339&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/10/03/inferring-the-locale-text-direction-with-javascript/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
		<item>
		<title>A Simple Javascript Model-View-Controller API</title>
		<link>http://brooknovak.wordpress.com/2009/09/30/a-simple-javascript-model-view-controller-api/</link>
		<comments>http://brooknovak.wordpress.com/2009/09/30/a-simple-javascript-model-view-controller-api/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 11:15:09 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[abstractsubject]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[fireevent]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[listener]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[model-view-controller]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[notify]]></category>
		<category><![CDATA[oo]]></category>
		<category><![CDATA[pattern]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[subject]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=330</guid>
		<description><![CDATA[Model-View-Controller is such a useful and powerful design pattern.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=330&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Model-View-Controller is such a useful and powerful design pattern. You can use MVC for more than just physical views (i.e. GUI&#8217;s), but abstract views as well (e.g. pure data structures). You can even use MVC as an event mechanism.<br />
<span id="more-330"></span><br />
I have written an easy-to-use MVC API for your Javascript applications. The following MVC example uses the API. The model is the <code>userdoc</code>, the views are the <code>toolbar</code> and <code>menu</code>, the controller is the user clicks/edits:</p>
<p><pre class="brush: jscript;">

// The user document model
var userdoc = function() {

  // Model data
  var data = &quot;&quot;, selStart, selEnd;

  var ud = {

    /**
    * Sets the document data.
    * @param {String} newData The new data to set.
    */
    setData : function(newData) {
      data = newData;
      this.fireEvent(&quot;DataChanged&quot;, newData);
    }
  };

  // Controller: user clicks adjusts selection model data
  document.getElementById(&quot;userdoc&quot;).onclick = function(e) {
    // Set cursor/selection logic
    ud.fireEvent(&quot;SelectionChanged&quot;, selStart, selEnd, e || window.event);
  }

  return ud;

}();

// Make the userdoc a Model
declareModel(userDoc);

// The tool bar view
var toolBar = {

  // .. Interface code...

  /**
  * Listener function
  */
  onSelectionChanged : function(selStart, selEnd) {
     // Update GUI Buttons according to selection
  }
};
userDoc.addObserver(toolBar);

// Add observer for the main menu
userDoc.addObserver({
  onDataChanged : function(data) {
    menu.saveButton.setEnabled(data != lastSavedData)
  },
  onSelectionChanged : function(selStart, selEnd) {
    // Update revelent buttons according to selection
  }
}, menu);

for (var button in menu) {
  if (button.requiresSelection) {
    // Observe the document selection state
    // and synchronize this buttons enable
    // state according to the selection state
    userDoc.addObserver({
      onSelectionChanged : function(selStart, selEnd) {
        // this points to a button - which is enabled only 
        // if there is selection in the document
        this.setEnabled(selStart ? true : false);
      }
    }, button);
  }
}

</pre></p>
<p>To declare a model you just invoke the <code>declareModel</code> function passing the model object.  </p>
<p>Whenever model data has changed (or when ever you want to raise an event), a <code>fireEvent</code> function will be present in the model object. There is no need to declare event types, you can just fire which ever event name you want. For example, if you fire an event named &#8220;Click&#8221;, all attached observers which a function called <code>onClick</code> will be invoked along with any extra/optional arguments passed to the <code>fireEvent</code> call. </p>
<p>The context which the observer event listener functions are called defaults to the observer objects themselves, otherwise you can provide a specific object. For example; in the code above observers are added to the user document model for every button which requires selection to be enabled, so during registration of each observer the context is set as the button objects (via the second argument). In the observer event code the <code>this</code> identifier points to the corresponding button.</p>
<p>The script for the MVC API:</p>
<p><pre class="brush: jscript;">

/**
 * Extends the given instance into a model (wrt MVC).
 * 
 * @param {Object} subject The subject containing model data to be observed.
 */
function declareModel(subject) {
    
    // The list of registered observers for this subject
    var observers = [];

    /**
     * 
     * Notifies all observers that a specific event occured.
     * Extra arguments will be passed to the observer's relevent event functions.
     * 
     * @param {String} event   The event name to fire (excluding the &quot;on&quot; prefix).
     *                         For example, &quot;KeyDown&quot; would invoke &quot;onKeyDown&quot; in all observers
     *                         
     */
    subject.fireEvent = function(event){
        
        if (observers.length &gt; 0) {
            
            // Construct additional arguments array
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            
            for (var i in observers) {
                var observer = observers[i];
                
                // If the observer has declared a listener function for this event invoke it
                if (typeof observer.ref[&quot;on&quot; + event] == &quot;function&quot;)
                	observer.ref[&quot;on&quot; + event].apply(observer.context, args);
            }
        }
    };
    
    /**
     * Adds an observer for receiving event notifications.
     * If the observer already exists in the observer set it will not be added twice.
     * 
     * @param {Object} observer         An observer to add to the set.
     * 
     * @param {Object} context          (Optional) The context at which the events should be invoked in.
     *                                  Will default to the observer object.
     *                                  
     * @param {Boolean} notifiedFirst   (Optional) True to be the first observer to be notified in the current list.
     *                                  Otherwise it will be added to the end of the list
     */
    subject.addObserver = function(observer, context, notifiedFirst){
        
        // Ensure that observer array is a set
        if (observerIndex(observer) != -1)
            return;
            
        // Create observer instance
        observer = {
            ref : observer,
            context : context || observer
        };
        
        // Add to list depending on requested order
        if (notifiedFirst) observers.unshift(observer);
        else observers.push(observer);
        
    };
    
    /**
     * Removes an observer from the subjects observer list.
     * 
     * @param {Object} observer An observer to remove from the set
     */
    subject.removeObserver = function(observer) {
        var index = observerIndex(observer);
        if (index &gt;= 0) observers.splice(index, 1);
    };
    
    /**
     * @param {Object} observerRef The observer reference to check
     * 
     * @return {Number} The index in the observers array at which observerRef exists.
     *                  -1 if not found.
     */
    function observerIndex(observerRef) {
        for (var i = 0; i &lt; observers.length; i++) {
            if (observers[i].ref == observerRef)
                return i;
        }
        return -1;
    }
    
}
</pre></p>
<br />Posted in Uncategorized Tagged: abstractsubject, API, application, code, controller, design, design pattern, development, event, fireevent, gui, javascript, js, listener, model, model-view-controller, mvc, notify, oo, pattern, script, subject, view, web, web 2.0 <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/330/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/330/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/330/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=330&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/09/30/a-simple-javascript-model-view-controller-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
		<item>
		<title>IE Whitespace madness</title>
		<link>http://brooknovak.wordpress.com/2009/08/23/ie-whitespace-madness/</link>
		<comments>http://brooknovak.wordpress.com/2009/08/23/ie-whitespace-madness/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 05:07:59 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Programming Problems - Resolved]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[4.01]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dhtml]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[dom tree]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html2js]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[innerhtml]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[newlines]]></category>
		<category><![CDATA[outerhtml]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[structure]]></category>
		<category><![CDATA[w3]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[white-space]]></category>
		<category><![CDATA[whitespace]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=294</guid>
		<description><![CDATA[Internet Explorer's DOM has a few issues regarding whitespace, specifically its innerHTML and outerHTML  properties.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=294&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Internet Explorer&#8217;s DOM has a few issues regarding whitespace. Whitespace symbols in HTML 4.01 are any of the following symbols:</p>
<p><span id="more-294"></span></p>
<ul>
<li>ASCII space (&#38;#x20;)</li>
<li>ASCII tab (&#38;#x09;)</li>
<li>ASCII form feed (&#38;#x0C;)</li>
<li>Zero-width space (&#38;#x200B;)</li>
</ul>
<p>Refer to <a href="http://www.w3.org/TR/html401/struct/text.html#h-9.1">w3&#8242;s specifications here</a>.</p>
<h2>Querying InnerHTML and outerHTML</h2>
<p>Now IE&#8217;s <code>innerHTML</code> and <code>outerHTML</code> adds all sorts of whitespaces when querying these properties. For example:</p>
<p><pre class="brush: jscript;">
    var container = document.createElement(&quot;div&quot;);
    container.innerHTML = &quot;&lt;div&gt;&lt;ul&gt;&lt;li&gt;I &lt;em&gt;like&lt;/em&gt; sushi!&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&quot;
    alert(container.innerHTML);
</pre></p>
<p>Prints:</p>
<p><pre class="brush: xml;">
&lt;DIV&gt;[][]&lt;UL&gt;[][]&lt;LI&gt;I &lt;EM&gt;like&lt;/EM&gt; sushi!&lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
</pre></p>
<p>Where the &#8220;[]&#8221; symbols denote whitespace symbols. In this example the added whitespaces causes the alert to break them (probably a newline and carriage return) thus physically displaying:</p>
<p><pre class="brush: xml;">
&lt;DIV&gt;
&lt;UL&gt;
&lt;LI&gt;I &lt;EM&gt;like&lt;/EM&gt; sushi!&lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
</pre></p>
<p>Maybe the implementor was trying to be helpful by adding these mysterious newline symbols before every block-level element for automatic readability. What a damn fool.</p>
<p>Is there a fix? Well, if you really need <code>innerHTML</code> to be precise you could walk the DOM tree yourself and spit out the markup as you traverse. You could bite the bullet can parse the string using regular expressions &#8211; and for every opening block-level element tag check for preceding whitespace symbols and eat them.</p>
<h2>Creating DOM trees via innerHTML</h2>
<p>When creating DOM trees via <code>innerHTML</code>, IE does not always create a DOM tree to reflect the exact HTML contents you pass it. This is because IE automatically collapses whitespace (normalization on the fly). For example:</p>
<p><pre class="brush: jscript;">
    var container = document.createElement(&quot;div&quot;);
    container.innerHTML = &quot;\n Apples \n&quot;
    alert(container.firstChild.nodeValue.length);
</pre></p>
<p>All browsers except for IE print &#8220;10&#8243;, IE collapses the surrounding whitespace and prints &#8220;7&#8243;.</p>
<p>To over come this: don&#8217;t use <code>innerHTML</code> &#8211; if you need the DOM tree to be precise, manually create the DOM structures yourself. I tried using &#8220;pre&#8221; white-space styles but it still normalized. You could use a pre element but if you HTML contains block-level elements the markup will be invalid (pre only allows a select few of inline-level elements).</p>
<p><em>Note:</em> you may find this useful: <a href="http://brooknovak.wordpress.com/software-projects/html2js">JS2HTML</a></p>
<p>See <a href="http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html">this bug report at quirksmode</a> for more details.</p>
<p>Hope this article relieves some of your IE headaches&#8230; it probably just aggravated you.</p>
<br />Posted in Programming Problems - Resolved, Web Programming Tagged: 4.01, browser, code, dhtml, dom, dom tree, html, html2js, ie, innerhtml, internet explorer, javascript, js, jscript, newlines, outerhtml, Programming, structure, w3, web, white-space, whitespace <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/294/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=294&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/08/23/ie-whitespace-madness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
		<item>
		<title>IE&#8217;s cloneNode doesn&#8217;t actually clone!</title>
		<link>http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/</link>
		<comments>http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 05:04:45 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Programming Problems - Resolved]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[clonenode]]></category>
		<category><![CDATA[cloning]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[dom level 2]]></category>
		<category><![CDATA[element]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[textnode]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=304</guid>
		<description><![CDATA[IE's cloneNode method does not clone the exact DOM structure!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=304&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>When you want to deeply clone a node you use the <code>cloneNode(true)</code> method on the element you want to clone (see <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html">w3&#8242;s DOM Level 2 specifications</a>)</p>
<p><div id="attachment_307" class="wp-caption aligncenter" style="width: 309px"><a href="http://brooknovak.files.wordpress.com/2009/08/6a00d83451901369e200e5507e82b98834-800wi.jpg"><img src="http://brooknovak.files.wordpress.com/2009/08/6a00d83451901369e200e5507e82b98834-800wi.jpg?w=450" alt="IE Cant even clone" title="IE Cant even clone"   class="size-full wp-image-307" /></a><p class="wp-caption-text">IE Cant even clone</p></div><br />
<span id="more-304"></span></p>
<p>I found that IE&#8217;s <code>cloneNode</code> method is broken. Yes, broken! If you want the cloned DOM structure to be <em>exactly</em> the same (i.e. a clone) then don&#8217;t use <code>cloneNode</code>. Take this example:</p>
<p><pre class="brush: jscript;">
    var container = document.createElement(&quot;div&quot;);
    container.appendChild(document.createTextNode(&quot;Apples&quot;));
    container.appendChild(document.createTextNode(&quot;Oranges&quot;));
    alert(container.firstChild.nodeValue); // Will Print &quot;Apples&quot;

    container = container.cloneNode(true);
    alert(container.firstChild.nodeValue); // Prints &quot;ApplesOranges&quot; on IE!
</pre></p>
<p>As pointed out by the comments in the example above, the <code>cloneNode</code> operation consolidates the two text nodes together as one! This is incorrect!</p>
<p>If you need <code>cloneNode</code> to keep the structure cloned, then you could write your own deep-clone method. Here is an implementation:</p>
<p><pre class="brush: jscript;">
    /**
     * Deeply clones a node
     * @param {Node} node A node to clone
     * @return {Node} A clone of the given node and all its children
     */
    function cloneNode(node) {
    	// If the node is a text node, then re-create it rather than clone it
        var clone = node.nodeType == 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
   
        // Recurse     
        var child = node.firstChild;
        while(child) {
            clone.appendChild(cloneNode(child));
            child = child.nextSibling;
        }
        
        return clone;
    }
</pre></p>
<p>Happy coding!</p>
<br />Posted in Programming Problems - Resolved, Web Programming Tagged: browser, clonenode, cloning, code, dom, dom level 2, element, html, ie, internet explorer, javascript, js, node, Programming, textnode, w3c, web <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/304/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/304/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/304/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=304&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>

		<media:content url="http://brooknovak.files.wordpress.com/2009/08/6a00d83451901369e200e5507e82b98834-800wi.jpg" medium="image">
			<media:title type="html">IE Cant even clone</media:title>
		</media:content>
	</item>
		<item>
		<title>Webkit clipboard security hole</title>
		<link>http://brooknovak.wordpress.com/2009/07/28/webkit-clipboard-security-hole/</link>
		<comments>http://brooknovak.wordpress.com/2009/07/28/webkit-clipboard-security-hole/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 02:07:55 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[access]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[copy]]></category>
		<category><![CDATA[dhtml]]></category>
		<category><![CDATA[execcommand]]></category>
		<category><![CDATA[hole]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[iframe]]></category>
		<category><![CDATA[insecure]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=276</guid>
		<description><![CDATA[Stumbled across a low-threat security hole in Webkit: Anyone can have the ability to copy text to the system clipboard in any context on-demand.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=276&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://brooknovak.wordpress.com/2009/07/28/accessing-the-system-clipboard-with-javascript/">While on a search for accessing the System clipboard via JavaScript</a>, it seems I discovered a security hole in Webkit.<br />
<a href="http://brooknovak.files.wordpress.com/2009/07/network-security.jpg"><img src="http://brooknovak.files.wordpress.com/2009/07/network-security.jpg?w=300&#038;h=224" alt="Network Security" title="Network Security" width="300" height="224" class="aligncenter size-medium wp-image-292" /></a><br />
Usually system clipboard access is restricted in clipboard events like <code>oncopy</code> and <code>onpaste</code>. However I found that you can set the system clipboard in any context (e.g. a timer event).<br />
<span id="more-276"></span><br />
This can be achieved by adding an <code>IFrame</code> containing a text input element into the document, and turning its design-mode / content-editable on. The <code>execCommand</code> will then become available via the added <code>IFrame</code> document. So to copy text to the system clipboard, you set the text input&#8217;s value (in the <code>IFrame</code>) to the text to be copied, then you select and focus the text input control, and finally issue a execCommand(&#8220;copy&#8221;) on the <code>IFrame</code>.</p>
<p><a href="http://www.cs.waikato.ac.nz/~bjn8/wpress/jsclipboard/webkitexploit.html">Click here for a demo</a>, this has an example with malicious intent: where it hijacks the system clipboard by constantly setting its content to a malicious URL (note it does not harm your computer and it ends when you close the page). Extra efforts can be made to avoid scrolling issues when focusing/selection the text input by using absolute floats. The example also is triggered via a mouse click &#8211; a malicious script would probably start the copying as soon as it&#8217;s loaded.</p>
<p>I&#8217;m not sure if the developers of Webkit would consider this a security hole or not. I have tested it on Safari 3 (Windows and Mac) and Chrome 2 (in which it works). I have reported it to them.</p>
<br />Posted in General, News, Web Programming Tagged: access, chrome, clipboard, code, copy, dhtml, execcommand, hole, html, iframe, insecure, javascript, safari, security, web, webkit <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/276/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/276/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/276/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=276&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/07/28/webkit-clipboard-security-hole/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>

		<media:content url="http://brooknovak.files.wordpress.com/2009/07/network-security.jpg?w=300" medium="image">
			<media:title type="html">Network Security</media:title>
		</media:content>
	</item>
		<item>
		<title>Accessing the System Clipboard with JavaScript – A Holy Grail?</title>
		<link>http://brooknovak.wordpress.com/2009/07/28/accessing-the-system-clipboard-with-javascript/</link>
		<comments>http://brooknovak.wordpress.com/2009/07/28/accessing-the-system-clipboard-with-javascript/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 01:28:09 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Programming Problems - Resolved]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[applet]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[clip]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[copy]]></category>
		<category><![CDATA[cross]]></category>
		<category><![CDATA[cut]]></category>
		<category><![CDATA[dhtml]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[ecma]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jscript]]></category>
		<category><![CDATA[liveconnect]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[paste]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[sandbox]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[silverlight]]></category>
		<category><![CDATA[sun microsystems]]></category>
		<category><![CDATA[system]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[webkit]]></category>
		<category><![CDATA[xul]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=258</guid>
		<description><![CDATA[Explores several approaches to accessing the system clipboard on a variety of web platforms using JavaScript.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=258&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I am developing an API written in JavaScript for a project which requires the ability to copy data to, and retrieve data from, a<em> </em>clipboard within a web browser. A simple/common problem definition – but due to tight browser security, finding a solution is a bit of a nightmare. This article outlines and discusses a number of approaches for implementing a clipboard feature into your JavaScript applications.</p>
<p><a href="http://brooknovak.files.wordpress.com/2009/07/copy-paste.jpg"><img src="http://brooknovak.files.wordpress.com/2009/07/copy-paste.jpg?w=225&#038;h=300" alt="copy-paste" title="copy-paste" width="225" height="300" class="aligncenter size-medium wp-image-289" /></a><br />
<span id="more-258"></span></p>
<h2>The Ideal JavaScript Clipboard Interface</h2>
<p>The concept of the &#8220;clipboard&#8221; is simple;  it is essentially a place for storing and retrieving a single unit/piece of cloned data. The code snippet below describes this clipboard concept in terms of a JavaScript interface.</p>
<p><pre class="brush: jscript;">
Clipboard = {
    copy : function(data) {
        //... implemention …
    },
     getData : function() {
        // … implementation …
     }
};
</pre></p>
<p>A simple concept, a self explanatory interface. However, the description above is vague; it does not state where &#8220;the clipboard&#8221; resides, nor does it mention if there can be more than one clipboard.</p>
<h3>Multiple Clipboards</h3>
<p>Unfortunately there can be more than one clipboard present.  There is one &#8220;System clipboard&#8221; present when a user is logged into their profile/account (some strange people might install/configure some features on their OS to support multiple system clipboards). Ideally, all applications should use the system clipboard when copying and pasting so its users can copy and paste between all applications. However this is not always the case. For example, Cygwin uses its own clipboard for Cygwin applications and unless the user explicitly turns on a clipboard integration option, the user cannot copy and paste between Cygwin applications and non-Cygwin applications.</p>
<h3>The Web&#8217;s Sandbox Environment</h3>
<p>Web applications run in a sandbox environment to prevent malicious scripts from infecting a visitor&#8217;s computer. The sandbox environment restricts access to system resources, such as the file system, and unfortunately, the system clipboard. Check out <a href="http://news.cnet.com/8301-1009_3-10021715-83.html">this article</a> for one example why the system clipboard is a restricted resource. Fortunately restrictions for accessing the system clipboard can be overcome. There are many approaches for accessing the system clipboard &#8211; each approach has its own trade-offs.</p>
<h2>Internet Explorer&#8217;s clipboardData Object</h2>
<p>Microsoft&#8217;s Internet Explorer family makes life very easy to access the system clipboard. To set the system clipboard&#8217;s text,  just use the <a href="http://msdn.microsoft.com/en-us/library/ms535220%28VS.85%29.aspx"><code>clipboardData</code></a> object. Here is an example:</p>
<p><pre class="brush: jscript;">
var didSucceed = window.clipboardData.setData('Text', 'text to copy');
</pre></p>
<p>To access the system&#8217;s clipboard data (in a textual format) you simply invoke:</p>
<p><pre class="brush: jscript;">
var clipText = window.clipboardData.getData('Text');
</pre></p>
<p>The first time the <code>clipboardData</code> object is accessed IE will prompt the user to allow the script to access the system clipboard (note: if you run the script locally IE does not bother with the confirmation and automatically allows it). <a href="http://support.microsoft.com/kb/224993">IE version 6 and below</a> will not bother asking the users (unless they have some non-default security features set to a &#8220;high level&#8221;). We cannot assume that users will choose to allow the script to access the system clipboard. If they decline, the <code>clipboardData.setData</code> method returns false. Unfortunately the <code>clipboardData.getData</code> method is vague: as it returns an empty string if the user chooses to decline. This is ambiguous since the system clipboard&#8217;s contents could actually be empty! Ideally it would return null. You could either always assume that empty string is a signal for failure to access the clipboard and try use a different method (read on), or you could attempt to verify that it was a failure:</p>
<p><pre class="brush: jscript;">
var clipText = window.clipboardData.getData('Text');
if (clipText == “”) { // Could be empty, or failed
	// Verify failure
	if (!window.clipboardData.setData('Text', clipText))
		clipText = null;
}
</pre></p>
<p><strong>Note:</strong> <em>the verification method will not display two prompts, since the first prompt will be remembered for the session.</em></p>
<h2>A Sketchy Work-around: The Flash Copy Hack</h2>
<p>Jeffrey Larson came up with a <a href="http://www.jeffothy.com/weblog/clipboard-copy/">nifty solution</a> using Adobe Flash. To copy text to the system clipboard a small flash object is embedded into the document by manipulating the DOM, and the text to be copied is passed as a parameter to the embedded object. The Flash program then takes this text and copies it to the system clipboard via the Flash API. This was a security hole in Flash up-to and including versions 9, and was patched in version 10 so that <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer10_uia_requirements.html">unsolicited access to the system clipboard is denied</a>. That is, Flash requires users to physically trigger the ActionScript clipboard code via a mouse click in order to grant access.</p>
<p>There still exists a workaround using that is supported by Flash 9 and 10. A small JavaScript library called <a href="http://code.google.com/p/zeroclipboard/">ZeroClipboard</a> exploits Flash, and fools the users, by placing invisible Flash movies over button elements. Whenever a user clicks on these invisible flash movies, ZeroClipboard successfully copies text to the system clipboard since the access is technically not &#8220;unsolicited.&#8221; This is a bit cheeky, some people are calling this process &#8220;click jacking.&#8221; It could be seen as a security flaw, and later Flash releases might put an end to this clipboard exploitation mayhem once and for all – who knows.</p>
<p>Using ZeroClipboard will only allow copying of text to the system clipboard on mouse-clicks. It does not allow access in any other contexts, such as timers, or CTRL+C keyboard events. It is a specific solution intended for Copy buttons.</p>
<p>One drawback is that this option does require the browsers to have the adobe flash plugin installed. So detection of Flash support is essential. Adobe has released a simple-to-use <a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">detection kit</a> which would do the trick. Another simple one can be found <a href="http://www.featureblend.com/javascript-flash-detection-library.html">here</a>.</p>
<p>Flash version 9 has a <a href="http://bugs.adobe.com/jira/browse/FP-80">bug in Linux systems</a> where Web browsers are unable to support transparency for embedded Flash movies. Thus ZeroClipboard is <a href="http://code.google.com/p/zeroclipboard/issues/detail?id=5">not suitable</a> on clients with this setup.</p>
<p>ZeroClipboard should be named ZeroSysCopy or something similar since it only provide unidirectional access to the system clipboard. I attempted to pursue a bidirectional implementation, but the ActionScript API <a href="http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00002187.html">does not provide any way of clipboard retrieval</a> due to security risks. Adobe&#8217;s ActionScript API for the Flex environment does provide <a href="http://livedocs.adobe.com/flex/3/langref/flash/desktop/Clipboard.html">ways of getting to the system clipboard</a>, but only on paste events from a paste button click on a context menu, or paste commands like CTRL+V.</p>
<h2>Using Java Applets</h2>
<p>Jeffrey Larson&#8217;s Flash copy hack got me thinking: what about taking a similar approach using Java applets instead of Flash movies. The beauty of Java is that it can communicate directly with JavaScript, thus can support both copy and paste operations. This is possible via a technology called Liveconnect. This solution has some pricey trade-offs though.</p>
<h3>Liveconnect</h3>
<p>Netscape developed an API called NP API (Netscape Plugin API) which is a cross browser plugin architecture supported by all major browsers except IE today (although some IE browsers do support it – IE&#8217;s equivalent is ActiveX). Liveconnect is one way to implement NP API-based plugins using JavaScript and Java. It was first supported in Netscape 4. A plugin could implement and return an instance to a Java class. The public methods exposed by this class was the scriptable interface for the plugin. The class could be called from JavaScript and even from other Java applets running within the page with the browser marshalling the calls between the various contexts. (see <a href="http://en.wikipedia.org/wiki/NPAPI#LiveConnect">http://en.wikipedia.org/wiki/NPAPI#LiveConnect</a>). The technology has matured since then and is still supported by Mozilla browsers, and Opera. Webkit does not seem to support it anymore.</p>
<p>Some browsers, such as Firefox, do not ship with a Java Virtual Machine plugin, since it &#8220;bloats&#8221; the browsers download size. So like the Flash hack, it depends on a plugin, which is a bit of a concern since the JVM plugins are relatively large to download.</p>
<p>Sun has respecified and reimplemented the Liveconnect technology as of version <a href="http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect">6 update 10</a>, which to my understandings just means that it is faster, more reliable and contains a bunch of extra features not needed for the purposes of some simple clipboard code.</p>
<h3>Implementation</h3>
<p>There are many issues and quirks with this technology. Luckily the code will be very small and simple for the clipboard. Most browsers support the ability to directly use Java inside of JavaScript, but some browsers have issues with some things such as creating new class instances. A more reliable approach would be to store the Java clipboard code into an applet.</p>
<p><a href="#">Try the demo here(missing)</a>. <a href="#">Click here(missing)</a> for the applet source. Note that it only works on some browsers, and most probably not on IE.</p>
<p>Hopefully the demo code is self-explanatory. In order to break out of the JVM sandbox environment  <code>java.security.AccessController.doPrivileged</code> is used. Unfortunately that is not enough; after running a small test &#8211; the clipboard was found to be sandboxed. In order to access the system clipboard, the script must be digitally signed. You can sign the applet privately for free to get it running on your machine, but this is probably not practical for you. To digitally sign your applet publicly, you have to go somewhere like <a href="http://www.verisign.com/">Verisign</a> and purchase a certificate for your applet. This currently costs $500 (US) for one year.</p>
<p>Another implication worth noting is that on the first time the JavaScript talks to the Java applet, it will take a little while to load the JVM (several seconds). Once the JVM is loaded it runs smoothly.</p>
<h2>Using Silverlight?</h2>
<p>To the point: None of the Silverlight versions (currently up to version 3) <a href="http://blogs.msdn.com/codingadventures/archive/2009/05/26/copying-data-to-the-clipboard-in-silverlight.aspx">does not provide system clipboard access</a>. This is a shame because it interacts well with JavaScript and is supported by all the common browsers (even on Linux via Moonlight).</p>
<h2>Mozilla&#8217;s XUL Approach</h2>
<p>Mozilla has this inbuilt plugin called “clipboard helper” which can be accessed with JavaScript using the XUL API. <a href="http://almaer.com/blog/supporting-the-system-clipboard-in-your-web-applications-what-a-pain">Dion Almaer explored this approach</a>, <a href="#">click here(missing)</a> for a demo (try downloading it and viewing it locally on your machine).</p>
<p>The XUL approach has some issues, as pointed out by Dion. If you run the script locally an ugly dialog pops up containing a vague (and scary) message warning the user about the possibility of malicious code being executed. The user&#8217;s decision can be remembered. However it fails to access the clipboard when not running script from a local file. This can be overcome: One option is to set some obscure user preferences for Mozilla to allow access. This might not be practical, especially if you are planning to use the script on public sites. Another option is to digitally sign the JavaScript containing the XUL clipboard code – which of coarse is a pricey option.</p>
<h2>Making use of execCommand</h2>
<p>The <code>execCommand</code> JavaScript function is supported by all <a href="http://www.quirksmode.org/dom/execCommand.html">major browsers</a>. The browsers all support the &#8220;Copy&#8221; and &#8220;Paste&#8221; commands. All browsers except for IE only expose the <code>execCommand</code> function for documents with design-mode turned on (for wizzywig editing).</p>
<p>Webkit does not protect the copy command, I wrote a <a href="http://brooknovak.wordpress.com/2009/07/27/webkit-clipboard-security-hole/">post</a> about this security hole. In both Chrome 2 and Safari 4 (on windows and mac) I managed to copy text to the system clipboard without any security warnings/promptings what-so-ever via <code>execCommand</code>. My assumption is that this will be the same for older versions of Webkit. <em>This is very concerning</em>. Mozilla throws security exceptions which can be only avoided via setting the user preferences or signing the JavaScript code. Opera and Konqueror just does not work. For IE it is possible to use this approach, as well as other approaches with <code>MicrosoftTextRange</code> objects, but it has no benefits over using the <code>clipboardData</code> object since it safeguards the copy and paste operations in the same way.</p>
<h3>Implementation</h3>
<p><a href="#">Try it out here(missing)</a>. The first time the copy operation is invoked, an inline document in design mode is dynamically created and appended to the main document – thus exposing the <code>execCommand</code>. The inline document contains an <code>textarea</code> and is always hidden from the user. So to copy text to the system clipboard, the <code>textarea</code>&#8216;s value is set to the text to be copied, then the <code>textarea</code> is displayed, focused and selected, and finally the <code>execCommand("copy")</code> method is invoked. The <code>textarea</code> will never be rendered (i.e. the user will not see a random flash on the page) because it is hidden straight after the copy command has executed (the UI will not refresh until after the script finishes executing).</p>
<p>The demo does have a scrolling issue: since the <code>textarea</code> is selected and focused the scrollbars will change if the <code>iframe</code> is not in view. You can easily overcome this behavior this by placing the <code>iframe</code> in a float (<a href="#fallthrough">see below</a> regarding keyboard events).</p>
<p>This script will work in IE, the first time the copy operation is executed a dialog will pop up asking the user for the script for permission to access the clipboard. Unfortunately there is no way of telling whether the user allowed or denied access. The <a href="http://msdn.microsoft.com/en-us/library/ms536419%28VS.85%29.aspx">MSDN docs</a> specifies that <code>execCommand</code> returns true of false depending if the command succeeds or fails, however it will always return true even if the user denies access. Furthermore, while the prompt is displayed the users will see the internal frame rendered which might be confusing for the user (although this could be better concealed by <a href="#fallthrough">using floats</a>). The <code>window.clipboardData</code> object would be a better option, even if the user denies access via <code>window.clipboardData</code>, you probably would not want to blast them with any more security-risk dialogs.</p>
<h2>Fabricating DOM Events</h2>
<p>This is merely an idea, which is a similar approach to the <code>execCommand</code> approach. If it were possible to manually fire CTRL+C and CTRL+V events such that the browsers execute their &#8220;default&#8221; handlers, then by using similar trickery used with the <code>execCommand</code> implementation on demand access to the clipboard would be possible. However, the Web&#8217;s sandbox environment does not let JavaScript simulate user interactions (that would be very bad!). Just a thought.</p>
<h2>Clipboard Events</h2>
<p>IE, Webkit and FF 3+ supports up to six different clipboard events which can be invoked from context menus or key-commands like CTRL+C:</p>
<ul>
<li><strong>onbeforecut</strong>
<ul>
<li>FF does not support this.</li>
<li>IE raises this event before a context menu is displayed and something in the document is selected.</li>
<li>IE only raises these on editable elements.</li>
</ul>
</li>
<li><strong>oncut</strong>
<ul>
<li> IE only raises these on editable elements.</li>
</ul>
</li>
<li> <strong>onbeforecopy</strong>
<ul>
<li> FF does not support this.</li>
<li> IE and Safari raises this event 		before a context menu is displayed and something in the document is 		selected.</li>
</ul>
</li>
<li> <strong>oncopy</strong>
<ul>
<li> Only executed when about to copy 		something in the default handler.</li>
<li> Webkit exposes <code>clipboardData</code> on 		the event object.</li>
</ul>
</li>
<li> <strong>onbeforepaste</strong>
<ul>
<li> FF does not support this.</li>
<li> IE raises this event before a 		context menu is displayed and something in the document is 		selected.</li>
</ul>
</li>
<li> <strong>onpaste</strong>
<ul>
<li> IE only raises these on editable 		elements.</li>
</ul>
</li>
</ul>
<p>Webkit exposes the <code>clipboardData</code> object in <a href="http://developer.apple.com/DOCUMENTATION/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/CopyAndPaste.html">clipboard events</a> by attaching it to the event objects. Webkit&#8217;s  <code>clipboardData</code> object is implemented in the same way as IE&#8217;s <code>clipboardData</code> object.</p>
<p>In order to get text from the clipboard, <code>clipboardData.getData</code> can only be accessed in the <code>onpaste</code> event. This is nice and simple:</p>
<p><pre class="brush: jscript;">
		document.body.onpaste = function(e) {
			alert(e.clipboardData.getData(&quot;Text&quot;));
			e.preventDefault();
		}
</pre></p>
<p><strong>Note</strong>: <em>preventing the default behavior is necessary if you are planning to handle the event, but if your code is just sniffing, then exclude the <code>e.preventDefault()</code> call.</em></p>
<p>Ideally the code would be similar for setting the clipboard data upon copy events. Unfortunately Webkit has a <a href="https://bugs.webkit.org/show_bug.cgi?id=17645">bug</a> where you cannot set clipboard data in any of the clipboard events! You can use a work-around by using the same approach in the following section.</p>
<h2><a name="fallthrough">Using Keyboard Events</a></h2>
<p>In most Web applications you do not have to worry about setting/getting the system clipboard data via key presses like CTRL+C, all browsers implement this for you. However, my API needs to get/set system clipboard data whenever the user presses clipboard key combinations like CTRL+C, on an non-editable document. Specifically: on CTRL/CMD+C/X keystrokes, the text to be copied is not the selected text in the document. And, on CTRL/CMD+V keystrokes, no matter where the focus is, the API must be able to retrieve the system clipboard text.</p>
<p>Webkit and FF3+ browsers&#8217; default handlers for copying, cutting and pasting occur in the <code>oncopy</code>, <code>oncut</code> and <code>onpaste</code> events respectively. Browsers which do not use clipboard events execute their copy and paste code in their keydown/keypress default handlers.</p>
<p><a href="#">Click here for the demo(missing)</a>. Whenever a clipboard command is raised from a keyboard stroke, a <code>textarea</code> appears and is selected/focused. The browser&#8217;s default handler then executes its clipboard command on the selected <code>textarea</code>. A timer event is scheduled with no delay so that once the browsers default handler has executed its clipboard command, the timer event is queued afterward &#8211; where it then hides the <code>textarea</code> from view.</p>
<p>This approach was inspired from Webkit&#8217;s lack of support for using <code>clipboardData.setData</code>, I started with a  solution which used the <code>oncopy</code> event, which was then generalized to use keyboard events. You may want to use oncopy/onpaste in Webkit/FF3+ browsers instead of keyboard commands – however there is no real benefit from this except for Chrome: Chrome&#8217;s copy button in its window&#8217;s context menu is clickable, even if nothing in the document is selected (which raises the <code>oncopy</code> event).</p>
<p>The <code>textarea</code> element is <em>very</em> small and usually displayed outside of the view-port. If the vertical and horizontal scrollbars are not at the hard top or left of the document then the <code>textarea</code> is briefly flashed at the top right section of the window. If for example, the float is positioned at an absolute left position of -100 (out of viewport) but the horozontial scrollbars are scrolled to 40 pixels, the scrollbars would scroll to zero (hard left) whenever the <code>textarea</code> is selected/focused. (Note: restoring them to their original values will just create an ugly scrollbar jolting effect).</p>
<p>Originally I developed a <a href="#">bulky solution(missing)</a> without floats,  but I stumbled across a <a href="http://almaer.com/blog/supporting-the-system-clipboard-in-your-web-application-part-two">blog</a> that had happened to use this same approach but instead using floats (many thanks to Dion).</p>
<p>It is important to avoid race conditions while showing and hiding the <code>textarea</code> before and after the browsers&#8217; default handlers for clipboard operations. Clipboard events are guaranteed to work. Opera queues a <code>settimeout</code> with zero delay after all events in the current event batch &#8211; <code>onkeydown</code>, <code>onkeypress</code>, <code>onkeyup</code> event sequence is seen as an event batch (see <a href="http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/">timing-and-synchronization-in-javascript</a>) &#8211; so it is safe to use <code>onkeydown</code> in Opera. From my own experiments, my observations are that Firefox&#8217;s clipboard operations are executed on <code>keypress</code> events. IE and Webkit can only use <code>keydown</code> since clipboard key combinations do not get <code>keypress</code> events. There was no luck with getting Konqureror to work with this approach – KHTML has problems with selecting and focusing on an input element (it works sometimes).</p>
<h2>Summary</h2>
<p><a href="#">Go here to see a summary(missing)</a> of the explored approaches and their demos (sorry about the external link but my blog layout does not handle large tables!).</p>
<h2>Conclusion</h2>
<p>The “ideal interface” previously discussed is not possible: there are different contexts in which you may want to copy and retrieve data to and from the clipboard, so packaging up a universal clipboard solution is not realistic.</p>
<p>There is a lot of (hacky) code to get cut, copy and paste in a JavaScript application. Is it really worth the time and effort to support copy and paste? I think so. Copy and paste is extremely useful, especially for some type of web-page editor. Microsoft found that paste was the most commonly used operation in their Word application, and copy was the third most common (see <a href="http://blogs.msdn.com/jensenh/archive/2005/11/07/489864.aspx">http://blogs.msdn.com/jensenh/archive/2005/11/07/489864.aspx</a><a href="http://blogs.msdn.com/jensenh/archive/2005/11/07/489864.aspx"> </a> and <a href="http://www.pluggd.in/microsoft/most-used-features-commands-in-microsoft-word-and-a-few-design-lessons-2600/">most-used-features-commands-in-microsoft-word-and-a-few-design-lessons</a>).</p>
<p>Please post feedback&#8230; don&#8217;t be shy!</p>
<h2>Other Helpful Links/References</h2>
<ul>
<li><a href="http://ajaxian.com/archives/seeding-the-clipboard-in-flash10-with-zero-clipboard">http://ajaxian.com/archives/seeding-the-clipboard-in-flash10-with-zero-clipboard</a></li>
<li><a href="http://srp.stanford.edu/demo/">http://srp.stanford.edu/demo/</a></li>
<li><a href="http://trephine.org/t/index.php?title=Understanding_LiveConnectExplorer">http://trephine.org/t/index.php?title=Understanding_LiveConnectExplorer</a></li>
<li><a href="http://blog.pengoworks.com/index.cfm/2008/2/19/Accessing-privileged-methods-in-a-Java-Applet-via-JavaScript">http://blog.pengoworks.com/index.cfm/2008/2/19/Accessing-privileged-methods-in-a-Java-Applet-</a><a href="http://blog.pengoworks.com/index.cfm/2008/2/19/Accessing-privileged-methods-in-a-Java-Applet-via-JavaScript">via-JavaScript</a></li>
<li><a href="http://imagingexperts.typepad.com/imaging_experts/2006/10/javascripting_i.html">http://imagingexperts.typepad.com/imaging_experts/2006/10/javascripting_i.html</a></li>
</ul>
<p><strong>August 24th 09: SORRY BUT ALL DEMO LINKS HAVE BEEN BROKEN! All my wordpress files have been lost on my University web server! GRRRR!</strong></p>
<br />Posted in Programming Problems - Resolved, Web Programming Tagged: adobe, applet, browser, chrome, clip, clipboard, copy, cross, cut, dhtml, dom, ecma, events, firefox, flash, flex, html, ie, Java, javascript, jscript, liveconnect, microsoft, mozilla, opera, paste, safari, sandbox, script, security, silverlight, sun microsystems, system, web, web 2.0, webkit, xul <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/258/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=258&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/07/28/accessing-the-system-clipboard-with-javascript/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>

		<media:content url="http://brooknovak.files.wordpress.com/2009/07/copy-paste.jpg?w=225" medium="image">
			<media:title type="html">copy-paste</media:title>
		</media:content>
	</item>
		<item>
		<title>Retrieving Inherited CSS Styles with DOM</title>
		<link>http://brooknovak.wordpress.com/2009/06/23/retrieving-inherited-css-styles-with-dom/</link>
		<comments>http://brooknovak.wordpress.com/2009/06/23/retrieving-inherited-css-styles-with-dom/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 00:00:51 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[compatability]]></category>
		<category><![CDATA[cross]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[currentstyle]]></category>
		<category><![CDATA[derived]]></category>
		<category><![CDATA[dhtml]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[getcomputedstyle]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[inherit]]></category>
		<category><![CDATA[inheritance]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[quirksmode]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[specification]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[webpage]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=253</guid>
		<description><![CDATA[If you need to get a CSS style from an element in a document, you cannot just test the style of the element directly. That is: Element.style.nameOfStyle won&#8217;t work. Take this example: The immediate white space style of the bold element in the DOM will be normal (default for bold element). However the style is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=253&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you need to get a CSS style from an element in a document, you cannot just test the style of the element directly. That is: <code>Element.style.nameOfStyle</code> won&#8217;t work. Take this example:</p>
<p><pre class="brush: xml;">
&lt;p style=&quot;white-space:pre&quot;&gt;
  Hello world - &lt;b&gt; A  B  C  D &lt;/b&gt;
&lt;/p&gt;
</pre></p>
<p>The immediate white space style of the bold element in the DOM will be <code>normal</code> (default for bold element). However the style is actually <code>pre</code>, since it inherits it from the paragraph ancestor element.<br />
<span id="more-253"></span><br />
Quirksmode nicely addresses how to go about this. <a href="http://www.quirksmode.org/dom/getstyles.html">Check it out.</a><br />
However their script is not practical because the style you want to request must be formatted in a way depending on how their script will execute. Here is an improved solution which addresses this:<br />
<pre class="brush: jscript;">
/**
 * Retreives a CSS style directly set for or inherited by a given dom node.
 * 
 * @see www.quirksmode.org/dom/getstyles.html
 * 
 * @param {Node} node A dom node.
 * @param {String} styleProp A CSS style property, formatted in CSS notation.
 * @return {String} The inherited style of the given node. Undefined if the node does not have the style.
 *                 If the node is not an element, then the first ancestor element is selected.
 *                 
 */
function getStyle(node, styleProp) {
    
    while (node &amp;&amp; node.nodeType != Node.ELEMENT_NODE) {
        node = node.parentNode;
    }
    if (!node) return;
    
    if (window.getComputedStyle) { // DOM Spec
       return document.defaultView.getComputedStyle(node,&quot;&quot;).getPropertyValue(styleProp)
       
    } else if (node.currentStyle) { // MS HTML
    
        // Convert CSS Style notation to Javascript notation
        var index = styleProp.indexOf(&quot;-&quot;);
        while (index &gt; -1) {
            styleProp = (index == (styleProp.length-1)) ? 
                styleProp.substr(0, index) :
                styleProp.substr(0, index) + styleProp.charAt(index+1).toUpperCase() + styleProp.substr(index + 2);
            index = styleProp.indexOf(&quot;-&quot;);
        }
        
        return node.currentStyle[styleProp];
        
    }
    // Otherwise undefined...
}
</pre></p>
<p>So if the browser supports the <code>getComputedStyle</code> it will use that. Otherwise it will go the &#8220;Explorer way&#8221; and format the style argument from CSS notation to Javascript notation (camal case) and index into the associative array <code>currentStyle</code>.</p>
<p>Opera can support both ways, but will choose the first option since in this implementation is potentially faster. You can switch the precedence around to have Explorer browsers in favor; where its method is tested first and the style argument is formatted in javascript notation. </p>
<p>Hope that is helpful.<br />
If you find an incompatible browser please post the details <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />Posted in Web Programming Tagged: browser, code, compatability, cross, css, currentstyle, derived, dhtml, dom, getcomputedstyle, html, inherit, inheritance, javascript, quirksmode, script, specification, style, w3c, web, web 2.0, webpage <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/253/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/253/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/253/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=253&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/06/23/retrieving-inherited-css-styles-with-dom/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
		<item>
		<title>Enlightenment 17 (Window manager+) for Ubuntu (8.04 LTS)</title>
		<link>http://brooknovak.wordpress.com/2009/05/12/enlightenment-17-window-manager-for-ubuntu-8-4-lts/</link>
		<comments>http://brooknovak.wordpress.com/2009/05/12/enlightenment-17-window-manager-for-ubuntu-8-4-lts/#comments</comments>
		<pubDate>Tue, 12 May 2009 07:38:21 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[8.04]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[e17]]></category>
		<category><![CDATA[enlightenment]]></category>
		<category><![CDATA[entrance]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[heron]]></category>
		<category><![CDATA[latest]]></category>
		<category><![CDATA[LTS]]></category>
		<category><![CDATA[manager]]></category>
		<category><![CDATA[os]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[usplash]]></category>
		<category><![CDATA[window]]></category>
		<category><![CDATA[ydl]]></category>
		<category><![CDATA[yellow dog linux]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=209</guid>
		<description><![CDATA[You can get enlightenment 16 via the synaptic package manager &#8211; since its the latest stable version. It&#8217;s actually quite a bit old, I had a play round with it and didn&#8217;t like it that much. You want e17. People have made debian packages for e17, however most of the links are broken, and all [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=209&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>You can get enlightenment 16 via the synaptic package manager &#8211; since its the latest stable version. It&#8217;s actually quite a bit old, I had a play round with it and didn&#8217;t like it that much. You want e17.</p>
<p>People have made debian packages for e17, however most of the links are broken, and all the ones I personally tried failed to install. I suggest going for a SVN version.</p>
<p><strong>Caveat</strong>: E17 is the milestone at which the development community is striving for. The SVN repositories are tagged with versions that begin 0.16.999.x and will be eventually become 0.17 on stable release &#8211; which is really confusing since e17 is a complete rewrite of e16!</p>
<p>You can try and install an SVN version via synaptic package manager by following the steps in this comprehensive forum: <a href="http://ubuntuforums.org/showthread.php?t=916690">http://ubuntuforums.org/showthread.php?t=916690</a>. However that failed for me.</p>
<h3>Step 1: Get easy-e17.sh</h3>
<p>First get the famous bash script called easy-e17.sh from <a href="http://omicron.homeip.net/projects/">here</a>. This is sooo helpful. It painlessly automates the installation and update process for you.</p>
<h3>Step 2: Install dependencies</h3>
<p>You must install some development tools like automake and svn. When you run bash script, it will tell you if your missing any tools before it tries anything (errr, so if it does, install them! &#8211; e.g. run &#8220;<code>sudo apt-get install svn</code> to install SVN).</p>
<p><a href="http://ubuntuforums.org/showthread.php?t=916690">This forum</a> mentioned to install CVS as well, because of some old package that is still using CVS. I don&#8217;t think that&#8217;s necessary, but what the hey, install it anyway (run  &#8220;<code>sudo apt-get install cvs</code>). </p>
<h3>Step 3: Preparation for installing e17 login manager</h3>
<p>Before you go willy-nilly and run the script, your gonna want to do some configuration first. The easy_e17 script doesn&#8217;t install everything, and if your a bit of a perfectionist like me, you might want to include e17&#8242;s graphical login manager in the installation. By default Ubuntu uses GNOME&#8217;s login manager called GDM. We will switch them later (if you choose). </p>
<p>You can run &#8220;<code>bash easy_e17.sh --help</code>&#8220;. This will show you all the options you can use with this magnificent script. Note you can run this anywhere so keep it in a logical place &#8211; you might want to use it later for updates etc. You can also specify where you want your source to live. Personally I chuck it all in a /usr/lib/easy_E17 directory.</p>
<p>If /etc/easy_e17.conf does not exist, create it:<br />
<pre class="brush: bash;">
sudo touch /etc/easy_e17.conf
</pre><br />
Then set the contents to become:<br />
<pre class="brush: bash;">
--skip=enhance,exml,imlib2,edb,edje_editor,edje_player,edje_viewer,emotion,eclair,evfs,evolve,elicit,elitaire,emphasis,empower,engycad,entrance_edit_gui,entropy,ephoto,estickies,expedite,exquisite,extrackt,engage,enthrall,exalt-client,exhibit,rage,emu,flame,moon,news,penguins,rain,snow,language,photo,efm_path,efm_nav,e_phys,mpdule,notification,b_and_w
</pre><br />
This is the standard config with &#8220;entrance&#8221; and &#8220;esmart&#8221; removed in the &#8211;skip list. &#8220;Entrance&#8221; is E17&#8242;s login manager, and it depends on &#8220;esmart.&#8221;</p>
<p><strong>Note</strong>: easy_e17 lets you define your own path to a config file, however I would stay away from that because it will fist look for the /etc/easy_e17.conf, then one in ~/easy_e17.conf, then one in the current directory&#8230; the changes of your config to be used is small and can cause you some headaches.</p>
<h3>Step 4: Download and Install</h3>
<p>Run the script:<br />
<pre class="brush: bash;">
sudo bash easy_e17.sh -i
</pre><br />
It will download the source and compile it and install it! Yay! </p>
<p>The first time I ran this it actually failed because I missed some steps above. If it does fail, try and install it via the debian-svn package in <a href="http://ubuntuforums.org/showthread.php?t=916690">this forum</a>. If that fails, then try installing it via the easy_e17 script again and it should work. It worked for me. I think the debian package installed some hidden dependancies the easy_17 script wasn&#8217;t picking up.</p>
<h3>Step 5: switching from GNOME to E17</h3>
<p>In order to access e17 session, you need to create a file that describes it. Create the file:<br />
<pre class="brush: bash;">
sudo touch /usr/share/xsessions/Enlightenment-0.17.desktop
</pre><br />
Then set its contents to contain:<br />
<pre class="brush: bash;">
[Desktop Entry]
Encoding=UTF-8
Name=Enlightenment 0.17
Comment=
Exec=/opt/e17/bin/enlightenment_start
Icon=
Type=Application
</pre><br />
Now its time to try it. Logout (e.g. CTRL+ALT+BACKSPACE), then in &#8220;Options&#8221; or &#8220;Sessions&#8221; (depending on what GDM your using) select Enlightenment 17 for the next session. Then login..</p>
<h3>Step 6: Switching to the Entrance login manager</h3>
<p>This was a mission. Ok first create the following symbolic link:<br />
<pre class="brush: bash;">
sudo ln -s /opt/e17/etc/init.d/entrance /etc/init.d/entrance
</pre><br />
Now we need to switch from GDM to Entrance by editing the run level configurations. I suggest using BUM. First install bum if you don&#8217;t have it:<br />
<pre class="brush: bash;">
apt-get install bum
</pre><br />
Then invoke bum (Now that&#8217;s a weird sentence):<br />
<pre class="brush: bash;">
sudo bum
</pre><br />
Once its loaded scroll down to the &#8220;entrance&#8221; item and check it. Also, uncheck GDM, otherwise it will try and attach itself to the XDM after entrance has done so and funny things will happen! click the apply button at the top of the window in bum and exit. It might logout after closing bum, if not, logout to check out entrance <img src='http://s2.wp.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p><strong>Note</strong>: Disabling GDM from the bootloader loading it up will save resources, it avoids running two window managers simultaneously.</p>
<h3>Step 7: Complete the package: An enlightenment USpash</h3>
<p>To make your setup complete and consistent, you might want to install an e17 splash screen when loading the Ubuntu OS (aka bootscreen). Ubuntu uses usplash for displaying its splash screen. </p>
<p>I found one for e17 <a href="http://art4linux.org/node/290">here</a>, which is for specifically for Elbuntu (e17 with Ubuntu 7). Personally I didn&#8217;t like this one, also the screen resolution support is bad (on my setup I get a large black area around the splash). I tried looking for others but they weren&#8217;t the flavor I was looking for. So I created my own. Here&#8217;s a screenshot:</p>
<p><a href="http://brooknovak.files.wordpress.com/2009/05/e17clean.png"><img src="http://brooknovak.files.wordpress.com/2009/05/e17clean.png?w=300&#038;h=224" alt="E17 Clean usplash theme" title="E17 Clean usplash theme" width="300" height="224" class="alignnone size-medium wp-image-223" /></a></p>
<p>To get this theme download it <a href="http://www.cs.waikato.ac.nz/~bjn8/wpress/usplash-e17clean.tar.gz">here</a> (it&#8217;s GPL licensed &#8211; I based it on the Xubuntu source). Extract it, then move the binary &#8220;usplash-theme-e17clean.so&#8221; into <code>/usr/lib/usplash/</code>:<br />
<pre class="brush: bash;">
sudo mv usplash-theme-e17clean.so /usr/lib/usplash/.
</pre><br />
Next remove your current usplash theme:<br />
<pre class="brush: bash;">
sudo rm /usr/lib/usplash/usplash-artwork.so
</pre><br />
Then link in the e17 clean theme:<br />
<pre class="brush: bash;">
sudo ln -s /usr/lib/usplash/usplash-theme-e17clean.so /usr/lib/usplash/usplash-artwork.so
</pre><br />
Then to properly apply the changes:<br />
<pre class="brush: bash;">
sudo dpkg-reconfigure linux-image-`uname -r`
</pre></p>
<h3>Step 8: Icing on the cake: change your GTK theme</h3>
<p>At this point, any application using GTK will look really crude. You may want to change the GTK theme to suit your selected e17 theme. For example if you use the &#8220;black and white&#8221; e17 you may want to try <a href="http://www.gnome-look.org/content/show.php/E17+B_and_W?content=95680">this theme</a>. If you are using applications that are based on qt, it goes without saying that you probably will want to update your Qt theme to.</p>
<p>Usually you would use gnomes&#8217; &#8220;gnome-appearance-properties&#8221; application to switch the GTK theme, this is not available within e17 (if you&#8217;ve disabled GDM from running simultaneously to e17&#8242;s window manager &#8211; see step 6). To switch the GTK theme you are going to need to install the gtk-theme-switch package (if you don&#8217;t already have it):<br />
<pre class="brush: bash;">
sudo apt-get install gtk-theme-switch
</pre><br />
This will install two programs: &#8220;gtk-theme-switch&#8221; and &#8220;gtk-theme-switch2,&#8221; where the latter is used for switching GTK2 themes (what you want). </p>
<p>When you download a GTK theme it will usually be in a compressed tarbell form. Uncompress them to you &#8220;~/.themes&#8221; directory. Make sure that the top-level folder of the extracted theme contains a &#8220;index.theme&#8221; file. Then invoke:<br />
<pre class="brush: bash;">
gtk-theme-switch2 ~/.theme/TOP-DIR-OF-YOUR-THEME
</pre><br />
You should see the changes apply straight away!</p>
<p><strong>Note</strong>: If you decide on a dark theme, like the current default black and white theme, not all GTK applications will look nice. For example Firefox uses Mozillas XUL engine for rendering not just the various HTML forms, but also all its chrome. XUL always renders black for its text in the buttons etc.. which you will need to manually configure yourself.</p>
<p>You may also want to change your icon theme to go with your GTK/E17 Themes too.</p>
<h3>Step 9: Extras</h3>
<p>Ok I promise I&#8217;ll stop. But there are more quirks you may want to know:</p>
<p><strong>File manager</strong><br />
E17&#8242;s integrated file manager is still in development. It&#8217;s buggy and I personally find it very annoying to use. You can use nautilus, Ubuntu&#8217;s file manager used with GNOME. I personally recommend getting Thunar, it seems faster and has the same feel as nautilus anyway. Here are the commands:<br />
<pre class="brush: bash;">
sudo apt-get install thunar
sudo apt-get install thunar-volman
sudo apt-get install thunar-archive-plugin
</pre></p>
<p><strong>Note</strong>: You may be able to find a later stable release than ubuntu&#8217;s apt sources.</p>
<p>Now in the main enlightenment menu, goto Settings-&gt;Modules. Then unload the filemanager (Notice in its about info it says that it&#8217;s under construction!). You will lose file-management on your desktop&#8230; a small price to pay i say. It will also remove the &#8220;files&#8221; menu in the main enlightenment menu. </p>
<p>If you choose to disable E17&#8242;s file manager and want to have shortcuts to common places like &#8220;home&#8221; and &#8220;documents,&#8221; then you will have to manually create them. There is a &#8220;places&#8221; module that I believe provides shortcuts to directories on the menu which can be easily configured to use thunar, but mine was bugging out. E17 does not let you create custom menus (errr, without have to delve into their code!). You can edit the applications menu and also the favorite-applications menu. </p>
<p>You could use the  favorite-applications menu. To do so, first you need to create applications for your shortcuts, yes, this is a hacky approach (please let me know if you find a better way). Go into the main menu: settings-&gt;settings-panel. Go into the apps view. For each directory you are wanting to add, follow these steps:</p>
<ol>
<li>Click New Application</li>
<li>Name: &#8230; e.g. &#8220;Home&#8221; </li>
<li>Executable: thunar &#8220;PATH-TO-DIR&#8221; </li>
<li>If your pedantic like me, add a icon that fits</li>
</ol>
<p>Then in that same settings window, goto the Menus view, then click on the Favorites Menu. Then add your &#8220;applications&#8221; hahaha. </p>
<p><strong>A note on GNOME</strong><br />
By default Ubuntu will have lots of GNOME based apps installed. Some things are a little slow at starting up since they have to pull in some GNOME desktop libraries in order to launch. (which is usually loaded, but if you disabled GDM to save resources/use Entrance then the libraries wont be). You may want to switch to using alternative apps, for example using xzgv for viewing images rather than &#8220;eye of gnome.&#8221; Or if your feeling real adventurous you can keep on configuring your Linux scripts to preload GNOME and GTK2 libraries etc&#8230; But if your going to do that you should just use a dist like OpenGEU which does all the hard work for you!</p>
<p>And your done! Enjoy your e17 experience!</p>
<br />Posted in linux Tagged: 8.04, configuration, e17, enlightenment, entrance, hardy, heron, latest, linux, LTS, manager, os, productivity, svn, ubuntu, usplash, window, ydl, yellow dog linux <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/209/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/209/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/209/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=209&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/05/12/enlightenment-17-window-manager-for-ubuntu-8-4-lts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>

		<media:content url="http://brooknovak.files.wordpress.com/2009/05/e17clean.png?w=300" medium="image">
			<media:title type="html">E17 Clean usplash theme</media:title>
		</media:content>
	</item>
		<item>
		<title>Extended the YUI Compressor Tool</title>
		<link>http://brooknovak.wordpress.com/2009/05/09/extended-the-yui-compressor-tool/</link>
		<comments>http://brooknovak.wordpress.com/2009/05/09/extended-the-yui-compressor-tool/#comments</comments>
		<pubDate>Sat, 09 May 2009 09:04:16 +0000</pubDate>
		<dc:creator>brooknovak</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Web Programming]]></category>
		<category><![CDATA[compressor]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[extended]]></category>
		<category><![CDATA[global]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[modified]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[namespace]]></category>
		<category><![CDATA[object]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[removal]]></category>
		<category><![CDATA[remove]]></category>
		<category><![CDATA[rhino]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://brooknovak.wordpress.com/?p=205</guid>
		<description><![CDATA[I extended the YUI compressor tool to have the ability to remove global namespaces from your javascripts. Check it out here! Posted in General, News, Web Programming Tagged: compressor, debug, extended, global, javascript, js, modified, mozilla, namespace, object, release, removal, remove, rhino, tool, web, YUI<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=205&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I extended the YUI compressor tool to have the ability to remove global namespaces from your javascripts. <a href="/software-projects/yui-compressor-ext/">Check it out here!</a></p>
<br />Posted in General, News, Web Programming Tagged: compressor, debug, extended, global, javascript, js, modified, mozilla, namespace, object, release, removal, remove, rhino, tool, web, YUI <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/brooknovak.wordpress.com/205/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/brooknovak.wordpress.com/205/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/brooknovak.wordpress.com/205/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=brooknovak.wordpress.com&amp;blog=4667000&amp;post=205&amp;subd=brooknovak&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://brooknovak.wordpress.com/2009/05/09/extended-the-yui-compressor-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/fee3836d377eb161cf3499dacd679679?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">brooknovak</media:title>
		</media:content>
	</item>
	</channel>
</rss>
