<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.3" -->
<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/"
	>

<channel>
	<title>Vacuous Virtuoso &#187; Web</title>
	<link>http://lipidity.com</link>
	<description>Despotic Development</description>
	<pubDate>Thu, 05 Nov 2009 00:16:48 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.3</generator>
	<language>en</language>
			<item>
		<title>Speed Cache</title>
		<link>http://lipidity.com/web/speed-cache/</link>
		<comments>http://lipidity.com/web/speed-cache/#comments</comments>
		<pubDate>Thu, 22 Nov 2007 04:17:19 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Web]]></category>

		<category><![CDATA[Wordpress]]></category>

		<category><![CDATA[Download]]></category>

		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://lipidity.com/web/speed-cache/</guid>
		<description><![CDATA[Another WordPress plugin. I&#8217;ve been using this on my own site for a long time and, after people encountered 404s searching for it, have decided to publish it.

Speed Cache basically takes external files such as javascript and CSS and mirrors them on your own server. I&#8217;m not going to go into detail about why you&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p>Another WordPress plugin. I&#8217;ve been using this on my own site for a long time and, after people encountered 404s searching for it, have decided to publish it.</p>

<p>Speed Cache basically takes external files such as javascript and CSS and mirrors them on your own server. I&#8217;m not going to go into detail about why you&#8217;d want to do this - you either do or you don&#8217;t. If you do, then feel free to use the plugin.</p>

<p><a href="http://wordpress.org/extend/plugins/speed-cache/">Here it is</a>.</p>

<p>Support questions in the comments for now, but I&#8217;m not providing any guarantees. This post may be replaced by a proper info page about the plugin sometime in the future, but at the moment that&#8217;s unlikely.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/web/speed-cache/feed/</wfw:commentRss>
		</item>
		<item>
		<title>FancyForm - Pretty checkboxes and radios</title>
		<link>http://lipidity.com/web/javascript-checkbox-radio-replacement/</link>
		<comments>http://lipidity.com/web/javascript-checkbox-radio-replacement/#comments</comments>
		<pubDate>Tue, 28 Aug 2007 09:16:36 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Web]]></category>

		<category><![CDATA[CSS]]></category>

		<category><![CDATA[html]]></category>

		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/javascript-checkbox-radio-replacement</guid>
		<description><![CDATA[Styling form controls has always been limited with HTML and CSS. Not anymore. FancyForm provides the solution by letting you style checkboxes and radio buttons as you would any other elements, while degrading gracefully on older and non-graphical browsers.



Here&#8217;s an example of what&#8217;s possible with the script:



Not only does it let you style the checkboxes, [...]]]></description>
			<content:encoded><![CDATA[<p>Styling form controls has always been limited with HTML and CSS. Not anymore. <a href="http://dev.lipidity.com/fancy-form/">FancyForm</a> provides the solution by letting you style checkboxes and radio buttons as you would any other elements, while degrading gracefully on older and non-graphical browsers.</p>

<!--more-->

<p>Here&#8217;s an example of what&#8217;s possible with the script:</p>

<p class='centre'><img src="http://lipidity.com/images/fancy-20070828-190448.png" title="FancyForm styled checkboxes, before and after" alt="[styled checkboxes]" /></p>

<p>Not only does it let you style the checkboxes, you can also add your own custom JavaScript hooks, events, effects and a whole lot more.</p>

<p><a href="http://dev.lipidity.com/fancy-form/">Find out more</a> and please let me know of any bugs or possible ideas, or jump straight to <a href="http://dev.lipidity.com/fancy-form/demo/">the demo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/web/javascript-checkbox-radio-replacement/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Javascript does Cocoa too</title>
		<link>http://lipidity.com/apple/javascript-cocoa-webkit/</link>
		<comments>http://lipidity.com/apple/javascript-cocoa-webkit/#comments</comments>
		<pubDate>Sat, 28 Jul 2007 08:07:49 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Cocoa]]></category>

		<category><![CDATA[javascript]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tutorial]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/dev/cocoa/javascript-cocoa-webkit</guid>
		<description><![CDATA[Running Objective-C code from Javascript

Java, Python and Ruby can access Cocoa APIs and Objective-C classes. What about the super-extensible yet severely under-appreciated Javascript? With the WebKit framework, you can access Objective-C from any script present in a HTML document.



A `WebScriptObject` is an Objective-C wrapper passed to your application from the scripting environment. You can&#8217;t create [...]]]></description>
			<content:encoded><![CDATA[<p><big>Running Objective-C code from Javascript</big></p>

<p>Java, Python and Ruby can access Cocoa APIs and Objective-C classes. What about the super-extensible yet severely under-appreciated Javascript? With the WebKit framework, you can access Objective-C from any script present in a HTML document.</p>

<!--more-->

<blockquote><p>A `WebScriptObject` is an Objective-C wrapper passed to your application from the scripting environment. You can&#8217;t create an instance directly, but you need to get a `WebScriptObject` by sending `webScriptObject` to a WebView.</p><cite>Paraphrase of <a href="http://developer.apple.com/documentation/Cocoa/Reference/WebKit/Classes/WebScriptObject_Class/Reference/Reference.html#//apple_ref/doc/c_ref/WebScriptObject" title="WebScriptObject Class Reference" target="_blank">WebScriptObject Overview</a></cite></blockquote>

<p>This class, <code>WebScriptObject</code>, lets you &#8220;talk&#8221; and &#8220;listen&#8221; to Javascript (or any other code allowable inside <acronym title="Hyper Text Markup Language">HTML</acronym> <code>&lt;script&gt;</code> tags). That is, you can run Javascript code or functions in the WebView, but you can also let the Javascript run Objective-C methods.</p>

<p>This is the same way Dashboard widgets interact with Cocoa plugins. You know how you access <code>window.widget</code> in your Javascript? That&#8217;s an Objective-C class you&#8217;re referencing. The WebKit framework provides all the necessary classes and functionality for this interaction, making this seemingly difficult task ridiculously easy.</p>

<h4>Exposing an Objective-C class to the scripting environment</h4>

<p>Exposing a class to the scripting environment is very easy. You can use key-value coding methods (for example, <code>setValue:forKey:</code> and <code>valueForKey:</code>) to get and set the properties of a <code>WebScriptObject</code>. These will be accessible as children of the window object in Javascript. Use the <code>removeWebScriptKey:</code> method to remove a scripting object property.</p>

<p>As an example, let&#8217;s say we have a class <code>NSFoo</code>. We&#8217;ve linked to the WebKit framework and <code>webView</code> is a <code>WebView</code>.</p>

<p>We use the delegate method <code>webView:windowScriptObjectAvailable:</code> to ensure that the <code>WebScriptObject</code> is available before we start using it. Then we expose an instance of <code>NSFoo</code> to the scripting environment:</p>

<pre><code>- (void)webView:(WebView *)sender windowScriptObjectAvailable: (WebScriptObject *)windowScriptObject {
    NSFoo *myFoo = [[NSFoo alloc] init];

    scriptObject = windowScriptObject;
    [scriptObject setValue:myFoo forKey:@"foo"];
}
</code></pre>

<p>Now you can access <code>foo</code> through javascript;</p>

<pre><code>&lt;script language='text/javascript'&gt;
var myFoo = foo;
&lt;/script&gt;
</code></pre>

<h4>Allow Javascript access</h4>

<p>For obvious security reasons, no methods or KVC keys are exposed to the Javascript environment by default. This means at this stage while <code>window.foo</code> exists, you can&#8217;t do much with it. To allow Javascript to send messages or get / set properties, the following two class methods need to be utilized:</p>

<pre><code>+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
</code></pre>

<p>So for example, if we want to allow Javascript to send a <code>bar:</code> message to a class, all we have to do is add the following class method to the implementation:</p>

<pre><code>+ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {
    if ( selector == @selector(bar:) ) {
        return NO;
    }
    return YES;
}
</code></pre>

<p>Now running <code>foo.bar_(0)</code> in Javascript will be equivalent to running <code>[myFoo bar:0]</code> in Objective-C. Why the underscore? Selectors accessed from Javascript are renamed using the following rules:</p>

<ul>
<li>Any colon (&quot;:&quot;) in the Objective-C selector is replaced by an underscore (&quot;_&quot;).</li>
<li>Any underscore in the Objective-C selector is prefixed with a dollar sign (&quot;$&quot;).</li>
<li>Any dollar sign in the Objective-C selector is prefixed with another dollar sign.</li>
</ul>

<p>So a method called <code>doAction:(id)action withThing:(id)thing</code> will be turned into <code>doAction_withThing_(action,thing)</code>, while <code>do$This:</code> will become <code>do$$This_</code>. This is often pretty ugly and inconvenient. Fortunately, the Javascript name for the selectors can be changed.</p>

<h4>Change Javascript selector names</h4>

<p>Using <code>+ (NSString *)webScriptNameForSelector:(SEL)sel</code>, we can change the name of the selector in Javascript:</p>

<pre><code>+ (NSString *)webScriptNameForSelector:(SEL)sel
{
    if (sel == @selector(bar:))
        return @"bar";
    return nil;
}
</code></pre>

<p>Now we can run <code>foo.bar(0)</code> in Javascript to equal <code>[myFoo bar:0]</code>. Here are a few more examples:</p>

<pre><code>+ (NSString *)webScriptNameForSelector:(SEL)sel
{
    if (sel == @selector(performTransition))
        return @"performTransition";    // widget.performTransition()
    else if (sel == @selector(prepareForTransition:))
        return @"prepareForTransition"; // widget.prepareForTransition(arg)
    else if (sel == @selector(setPreference:forKey:))
        return @"setPreferenceForKey";  // widget.setPreferenceForKey(pref,key)
    else if (sel == @selector(preferenceForKey:))
        return @"preferenceForKey";     // widget.preferenceForKey(key)
    return nil;
}
</code></pre>

<p>If you want to expose all the instance methods of the class to the scripting environment, just return <code>NO</code> without doing any checks:</p>

<pre><code>+ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector { return NO; }
</code></pre>

<p>Remember: selectors are converted into Javascript functions, so even if the method doesn&#8217;t need any arguments, you still need to add the parenthesis at the end for the Javascript; eg. <code>[object doMethod]</code> becomes <code>object.doMethod()</code>.</p>

<h4>Key-Value-Coding from Javascript</h4>

<p>Exposing KVC keys is a similar procedure. Here we&#8217;re giving access to the &#8220;name&#8221; property:</p>

<pre><code>+ (BOOL)isKeyExcludedFromWebScript:(const char *)property {
    if (strcmp(property, "name") == 0) {
        return NO;
    }
    return YES;
}
</code></pre>

<p>Now in Javascript, we can read and write <code>foo.name</code>. Reading <code>foo.name</code> will be equivalent to <code>[myFoo name]</code> and writing to it (<code>foo.name = "A big foo"</code>) will be the same as running <code>[myFoo setName:@"A big foo"]</code>.</p>

<p>As before, just <code>return NO</code> without any checks to allow all KVC keys to be accessed from the scripting environment.</p>

<h3>Summary</h3>

<ul>
<li>Load WebKit.framework which contains the classes <code>WebView</code> and <code>WebScriptObject</code>.</li>
<li>Send <code>setValue:forKey:</code> to a <code>WebScriptObject</code>; makes an object available to the scripting environment.</li>
<li>Implement <code>+isSelectorExcludedFromWebScript:</code> and <code>+isKeyExcludedFromWebScript:</code> and return NO to allow the scripting environment to run a method or access a key.</li>
<li>Use <code>webScriptNameForSelector:</code> / <code>webScriptNameForKey:</code> to specify the names of your methods / keys as seen by Javascript.</li>
</ul>

<h3>Further reading</h3>

<ul>
<li><a href="http://developer.apple.com/documentation/Cocoa/Reference/WebKit/ObjC_classic/index.html">WebKit Documentation</a></li>
<li><a href="http://developer.apple.com/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/index.html#//apple_ref/doc/uid/TP40003837">WebScripting Documentation</a></li>
<li><a href="http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html">Obj-C From JavaScript</a></li>
<li><a href="http://will.thimbleby.net/script/">TurtleScript</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/javascript-cocoa-webkit/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Make the most of the iPhone SDK</title>
		<link>http://lipidity.com/apple/iphone-webkit-css-3/</link>
		<comments>http://lipidity.com/apple/iphone-webkit-css-3/#comments</comments>
		<pubDate>Tue, 26 Jun 2007 02:00:11 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Design]]></category>

		<category><![CDATA[Web]]></category>

		<category><![CDATA[CSS]]></category>

		<category><![CDATA[iPhone]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/make-the-most-of-the-iphone-sdk</guid>
		<description><![CDATA[<img src="http://dev.lipidity.com/wp-content/uploads/2007/06/safari.jpg" alt="Safari" title="Safari icon" class="fright" />
The iPhone, like Safari and many other browsers, runs on WebKit, which is one of the most blazing fast, powerful, standards-compliant rendering engine ever. Although there is no official Cocoa API for iPhone app development, it's not like we have nothing to work with. Writing web apps for the iPhone will be a pretty good experience for two reasons:

<ol>
<li>We don't have to worry about IE support when writing our web app</li>
<li>WebKit is amazing.</li>
</ol>

Highlighted below are ten CSS rules that make WebKit extra-great. <strong>Many of the previews require a WebKit-based browser like Safari, OmniWeb or Shiira.</strong><br />
<br />]]></description>
			<content:encoded><![CDATA[<h2>WebKit and <abbr title="Cascading Stylesheets">CSS</abbr></h2>

<h3>1. Native Controls</h3>

<p>A feature unique to the later versions of WebKit is the ability to style form controls. For a long time, the form inputs were kept as the operating system&#8217;s native controls, but now they are specifically styled that way. This means, we can easily over-ride that styling, or make elements appear like native controls.</p>

<p>Take a look at these text inputs:</p>

<div class="example">
<input type="text" value="I am a text input" />
<input type="text" style="-webkit-appearance:searchfield;" value="Me too, but I am round" />
<input type="search" value="I am a proper search input" />
</div>

<p>If you&#8217;re running a WebKit-based browser like Safari, you&#8217;ll see the first text input as a normal OS X-style
control, but the second one is a rounded control (like the search input minus the cancel widget).</p>

<p>Now look at these anchors:</p>

<div class="example">
<a href="#top">Go to top</a>
<a href="#top" style="-webkit-appearance:push-button;text-decoration:none;color:black">Go to top</a>
</div>

<p>Both are <code>&lt;a&gt;</code> tags, but the second one appears as a push-button in Safari.</p>

<p>That&#8217;s not all. Here are two button inputs:</p>

<div class="example">
<input type="button" value="I do nothing" />
<input type="button" value="I do nothing" style="-webkit-appearance:square-button" />
</div>

<p>Notice how the second button is a square button?</p>

<p>Have I caught your interest? Here&#8217;s how you do it.</p>

<h4>Mimic native widgets / controls</h4>

<p>Elements are styled to look like native controls for WebKit-based browsers using the <code>-webkit-appearance</code> <abbr title="Cascading Stylesheets">CSS</abbr> property. Some of the values this can take are (in two columns if you&#8217;re on WebKit):</p>

<div style="-webkit-column-count:2;-webkit-column-rule:1px solid rgba(0,0,0,0.1);">
<ul style="padding-left:2em">
<li>checkbox</li>
<li>radio</li>
<li>push-button</li>
<li>square-button</li>
<li>button</li>
<li>button-bevel</li>
<li>listbox</li>
<li>listitem</li>
<li>menulist</li>
<li>menulist-button</li>
<li>menulist-text</li>
<li>menulist-textfield</li>
<li>slider-horizontal</li>
<li>slider-vertical</li>
<li>sliderthumb-horizontal</li>
<li>sliderthumb-vertical</li>
<li>searchfield</li>
<li>searchfield-decoration</li>
<li>searchfield-results-decoration</li>
<li>searchfield-results-button</li>
<li>searchfield-cancel-button</li>
<li>textfield</li>
<li>textarea</li>
</ul>
</div>

<p>Setting <code>-webkit-appearance</code> simply makes the element appear as if it were the control. This could be of enormous use within WebViews inside Cocoa applications or with web apps for the iPhone.</p>

<p>If don&#8217;t have access to a WebKit-based browser, here&#8217;s a screenshot of what some of the &#8220;controls&#8221; look like:</p>

<p class="centre"><img class="feature" src="http://dev.lipidity.com/wp-content/uploads/2007/06/webkit-controls.png" alt="Webkit Controls" title="WebKit OS X Native Controls or Widgets" /></p>

<p>The important thing to note is that although the controls can be made to look like other controls using <code>-webkit-appearance</code>, their function is not affected. That is, textboxes will still accept text when they&#8217;re made to appear like <code>push-button</code> and so on.</p>

<h3>2. Element Drag</h3>

<p><ins class="block"><a href="http://fettig.net/weblog/2007/06/29/a-few-iphone-safari-notes/">Apparently</a> dragging doesn&#8217;t work with the iPhone, as it&#8217;s used for scrolling. That&#8217;s to be expected, I guess.</ins></p>

<p>Generally there is a lot of javascript involved in making an element draggable. Now you can achieve the same thing with only one line of <abbr title="Cascading Stylesheets">CSS</abbr>. Javascript will still be required to have drop targets, etc. but this allows the user to drag the entire element rather than just text or an image.</p>

<p>Try dragging this element (from the side):</p>

<div class="example" style="-webkit-appearance:push-button;-webkit-user-drag:element;-webkit-user-select:ignore">Drag me if you dare</div>

<p>Notice how the whole element is dragged? It&#8217;s just a regular <code>div</code> (made to act as a push-button) with the <abbr title="Cascading Stylesheets">CSS</abbr> rule <code>-webkit-user-drag:element</code> applied to it. Easy!</p>

<h3>3. Edit the webpage</h3>

<p><ins class='block'>Doesn&#8217;t work on the iPhone. You can click in the element, but the keyboard doesn&#8217;t show up. This is likely to work when there are copy-paste functions in the phone.</ins></p>

<p class="feature" style="-webkit-user-modify:read-write-plaintext-only">
This is a paragraph that you can edit if you&#8217;re running a WebKit-based browser like Safari or the iPhone. Just click here and edit the text like a normal textbox.
</p>

<p>To allow users to edit elements of the page (or all of it) in real time, there exists a property <code>-webkit-user-modify</code>. Obviously this defaults to read-only, but you can set it to the following:</p>

<ul>
<li>read-only</li>
<li>read-write</li>
<li>read-write-plaintext-only</li>
</ul>

<p><code>read-write</code> allows the user to copy and paste in <strong>rich</strong> <em>text</em> with formatting, while <code>read-write-plaintext-only</code> pastes in only the text. This could be useful with debugging or as part of a <abbr title="What You See Is What You Get">WYSIWYG</abbr> editor, etc. Just be careful with the security side of things.</p>

<h3>4. Selection (Highlighting)</h3>

<p style="-webkit-user-select:ignore" class="feature">I am a paragraph that you can&#8217;t select (if you&#8217;re running Safari). Try and highlight me and realize that your attempts are futile. Bwah, ha ha&#8230;</p>

<p>To disallow selection (highlighting) of text for a particular element, set the <abbr title="Cascading Stylesheets">CSS</abbr> rule <code>-webkit-user-select:ignore</code>. This may be useful for many web apps, but use it sparingly to avoid irritating the user.</p>

<p class="feature selection_hilite">I am a paragraph that you can select. If your browser supports the `::selection` selector, highlighting this will result in a black background and white text for the highlighted region.</p>

<h3>5. Rounded corners</h3>

<p><big class='example' style='-webkit-border-radius:6px; border:1px solid #000;'>
Rounded corners: Look, no hacks!
</big></p>

<p><code>-webkit-border-radius</code> specifies the radius of the corners. You can specify certain corners only by using one of</p>

<ul>
<li>-webkit-border-top-left-radius</li>
<li>-webkit-border-top-right-radius</li>
<li>-webkit-border-bottom-left-radius</li>
<li>-webkit-border-bottom-right-radius</li>
</ul>

<p>For example, the following has the top-right and bottom-left corners set to a radius of 7px:</p>

<p><big class='example' style='-webkit-border-top-right-radius:7px;-webkit-border-bottom-left-radius:7px;border:1px solid #000;'>
A bit of fancy corner-work
</big></p>

<p>Elliptical corners are possible by specifying two values, eg. <code>-webkit-border-radius: 3px 7px;</code>.</p>

<h3>6. Shadows</h3>

<h4>text-shadow</h4>

<p><big class='example' style='color:#FFF;text-shadow:2px 2px 2px #000;'>
This text has a shadow when viewed with a compliant browser.
</big></p>

<p>For the text-shadow <abbr title="Cascading Stylesheets">CSS</abbr> property, the parameters are</p>

<ol>
<li>horizontal offset (negative is to the left)</li>
<li>vertical offset (negative is up)</li>
<li>blur radius (higher is more blurred)</li>
<li>shadow color</li>
</ol>

<p>For example, using <code>text-shadow: 1px 1px 7px #000;</code> we get:</p>

<p><big class='example' style='color:#fff;text-shadow:1px 1px 7px #000;'>
this excellent text with a blurred, but visible shadow.
</big></p>

<h4>box-shadow</h4>

<p><big class='example' style='-webkit-box-shadow:1px 1px 7px #000;'>
This entire element has a shadow using -webkit-box-shadow:
</big></p>

<p>To add a shadow to the actual element rather than just the text, use <code>-webkit-box-shadow</code>. Parameters are the same as for the <code>text-shadow</code> property.</p>

<ol>
<li>the horizontal offset</li>
<li>the vertical offset</li>
<li>the blur radius</li>
<li>shadow color</li>
</ol>

<p>The shadow automatically compensates for any rounded corners you may have added.</p>

<p><big class='example' style='-webkit-box-shadow:1px 1px 7px #000;-webkit-border-radius:5px;'>
This element has a shadow, but also a border-radius.
</big></p>

<h4>text-stroke</h4>

<p><big class='example' style='-webkit-text-fill-color:yellow;-webkit-text-stroke:1px black;'>
I guess I&#8217;m really just a string of text. Oh, I&#8217;m stroked.
</big></p>

<p>Use <code>-webkit-text-stroke</code> to set a border or stroke around the text. Specify thickness and color.</p>

<p>To change the fill color, use -webkit-text-fill-color; otherwise value for the color property is used.</p>

<h3>7. Backgrounds</h3>

<p>WebKit allows multiple background images using <abbr title="Cascading Stylesheets">CSS</abbr>. If you&#8217;re running Safari or other WebKit-based browser, see <a href="http://www.decaffeinated.org/archives/projects/multibg/background-image.html">this great example</a> of multiple background images with <abbr title="Cascading Stylesheets">CSS</abbr>.</p>

<p>The syntax for multiple backgrounds:</p>

<pre><code>  background-image:    url("first-img"), url("second-img"),
                       url("other-img"), url("another-img");
  background-repeat:   no-repeat, no-repeat,
                       repeat-y, repeat-x;
  background-position: top left, top right,
                       left, top;
</code></pre>

<p>The first image is associated with the first background-repeat, and the first background-position value and so on. The order in which the images appear also determines the stacking order - earlier images are stacked higher.</p>

<p>Shorthand background notation also works, the example above is equivalent to:</p>

<pre><code>background: url("first-img") top left no-repeat,
            url("second-img") top right no-repeat,
            url("other-img") left repeat-y,
            url("another-img") top repeat-x;
</code></pre>

<p>This could be really handy with making the background of a web-app, such as for the iPhone, without the need for multiple nested elements.</p>

<h3>8. Border Image</h3>

<p>To set fancy borders, you often need to use images. However, you can do away with all the javascript and <abbr title="Cascading Stylesheets">CSS</abbr> hacks and use <code>-webkit-border-image</code>.</p>

<p>Syntax:</p>

<pre><code>-webkit-border-image: url("image-url") size fit fit;
</code></pre>

<p>&#8220;image-url&#8221; needs to be an image divided into nine parts for each corner and edge and the content. The size is the height / width of the squares that the image is divided into. Fit can be <code>round</code> or <code>stretch</code>, which are ways of fitting the image into the border. To show the border, you need to actually have a <code>border</code> rule, but that can be integrated into the border-image by using something like:</p>

<pre><code>-webkit-border-image: url("image-url") 27 / 27px round round;
</code></pre>

<p>The <code>/ 27px</code> bit specifies the width of the border and makes it show if it isn&#8217;t already.</p>

<h3>9. Resizing</h3>

<p><big class='example' style="border:1px solid;resize:both;overflow:auto;max-width:100%">
This element is actually resizable.<br />If you&#8217;re using a compatible browser, drag the handle at the bottom right to resize this box.<br />Max-width is restricted to 100%.
</big></p>

<p>Making an element resizable is really easy: just set the <code>resize</code> property to <code>vertical</code>, <code>horizontal</code> or <code>both</code>.</p>

<p><big class='example' style="border:1px solid;resize:horizontal;overflow:auto;max-width:100%">
This box can only be resized horizontally (along the x-axis)
</big></p>

<p>To make scrollbars appear when the content doesn&#8217;t fit completely inside the box, it&#8217;s a good idea to set <code>overflow:auto;</code>.</p>

<p>Restrict the size that an element can be resized to by setting <code>min-width</code>, <code>min-height</code>, <code>max-width</code> and / or <code>max-height</code>.</p>

<h3>10. Colors and Opacity</h3>

<p><big class='example' style="background-color: hsla(100,90%,50%,0.6);">I am a-hued, a-saturated, and a-alpha-ed.</big></p>

<p>Colors can be set using <code>rgb(red, green, blue)</code>, <code>rgba(red, green, blue, alpha)</code>, <code>hsl(hue, saturation, lightness)</code> or <code>hsla(hue, saturation, lightness, alpha)</code>.</p>

<p>The example above has the rule <code>background-color: hsla(100,90%,50%,0.6);</code>.</p>

<hr />

<div class='example' style="background-color: black; opacity: 0.5; color: white"><big>
Easily set opacity. This element has a black background, but an alpha value of 0.5.<br />
<span style='color: yellow'>Opacity is inherited by any child elements.</span>
</big></div>

<p>Set <code>opacity</code> as a number between 0 (completely transparent) and 1 (completely opaque). If you don&#8217;t want the opacity to be inherited by child elements, set the background color using rgba or hsla and specify the alpha value there.</p>

<h2>Further reading:</h2>

<ul>
<li><a href="http://qooxdoo.org/documentation/general/webkit_css_styles">http://qooxdoo.org/documentation/general/webkit_css_styles</a></li>
<li><a href="http://www.css3.info">http://www.css3.info</a></li>
<li><a href="http://andybudd.com/presentations/css3">http://andybudd.com/presentations/css3</a></li>
</ul>

<p><style type="text/css">
    .example {
        display: block;
        padding: 3px;
        text-align: center;
    }
    .selection_hilite::selection {
        background: rgba(2, 2, 2, 0.8);
        color: white;
    }
</style></p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/iphone-webkit-css-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Track Dugg stories for your domain</title>
		<link>http://lipidity.com/web/track-dugg-stories-for-your-domain/</link>
		<comments>http://lipidity.com/web/track-dugg-stories-for-your-domain/#comments</comments>
		<pubDate>Fri, 20 Apr 2007 07:07:15 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Web]]></category>

		<category><![CDATA[API]]></category>

		<category><![CDATA[Digg]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/track-dugg-stories-for-your-domain</guid>
		<description><![CDATA[I can finally talk about it! Yes, sir, <a href="http://apidoc.digg.com/">the Digg API</a> has officially been released.

I've been playing around with it for a few weeks now, so already got a a little mini app together using the Digg API. It's a Dugg story tracking service that creates an RSS feed for the stories that have been Dugg for a particular domain. Essentially, all you have to do is type in a domain or subdomain, and subscribe to the resulting feed that you're presented with. Easy.]]></description>
			<content:encoded><![CDATA[<p><a href='http://digg.lipidity.com/dugg/' title='Digg API Tracking service'><img src='http://dev.lipidity.com/wp-content/uploads/2007/04/diggapi.png' alt='Digg API Tracking service' /></a></p>

<p>See it in action <a href="http://digg.lipidity.com/dugg/" title="Dugg stories tracking service">here</a>.</p>

<p>If anyone has any ideas for a name, that would be very helpful!</p>

<p>This is the best way to stay up-to-date with the Digg status of your site. More accurate and informative than subscribing to a search, with using the just-released Digg API.</p>

<p>Feature-requests are welcome. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/web/track-dugg-stories-for-your-domain/feed/</wfw:commentRss>
		</item>
		<item>
		<title>National API week</title>
		<link>http://lipidity.com/apple/national-api-week/</link>
		<comments>http://lipidity.com/apple/national-api-week/#comments</comments>
		<pubDate>Wed, 18 Apr 2007 08:01:06 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[News]]></category>

		<category><![CDATA[API]]></category>

		<category><![CDATA[Digg]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[Google]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Web]]></category>

		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/apple/national-api-week</guid>
		<description><![CDATA[Two very important APIs were released this week. One is web-based, the other is Mac-based.]]></description>
			<content:encoded><![CDATA[<h3>Digg</h3>

<p>There have been <a href="http://serverboy.net/wiki/Digg">attempts</a> at figuring out the usage of the still-unreleased Digg <abbr title="Application Programming Interface">API</abbr>. However, Digg are yet to release their official <abbr title="Application Programming Interface">API</abbr>.</p>

<p>The staff at Digg were very kind in letting certain people have a play with the <abbr title="Application Programming Interface">API</abbr> before its release, and it&#8217;s looking to be, to put it bluntly, quite excellent. A lot of Digg plugins and services are going to be either made obsolete, or very happy with all the new possibilities that will be&#8230; well, possible!<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p>For example, Lorelle talks about <a href="http://lorelle.wordpress.com/2007/02/24/digg-this-feature-on-wordpresscom-blogs/">keeping track</a> of your Dugg posts by subscribing to the search results RSS. This is only possible if you search for the past 7 or 30 days, and it doesn&#8217;t give you much information about the status, comments or diggs received on your posts. With the Digg <abbr title="Application Programming Interface">API</abbr>, this&#8217;ll be figuratively (because too many people use the word &#8216;literally&#8217; figuratively) a breeze.</p>

<p><abbr title="Application Programming Interface">API</abbr>&#8217;s are important, because they give people the opportunity to extend and use an application or service in a way that they like. A world without <abbr title="Application Programming Interface">API</abbr> is like Xcode without Cocoa or Carbon, or like the Mac without Applescript. An <abbr title="Application Programming Interface">API</abbr> helps to let the user do what they like, and it&#8217;s fun!</p>

<p>So web developers, start your engines for the Digg <abbr title="Application Programming Interface">API</abbr>&#8230;</p>

<h3>Google &amp; Cocoa</h3>

<p>It may be <abbr title="Application Programming Interface">API</abbr> week or something, because Google have also conjured up an open source <abbr title="Application Programming Interface">API</abbr> for Mac developers to use Google data. The <a href="http://code.google.com/p/gdata-objectivec-client/">Google Data APIs Objective-C Library</a> is a framework<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> that enables the use of Google data <abbr title="Application Programming Interface">API</abbr>&#8217;s within Objective C.</p>

<p>Greg Robbins posted some examples of this <abbr title="Application Programming Interface">API</abbr> at the <a href="http://googlemac.blogspot.com/2007/04/google-data-apis-connect-cocoa.html">Google Mac blog</a>. Currently you can work with Google Calendar, Google Base, Google Spreadsheets and access to more services is in development. It seems to be a very nice framework, and I&#8217;m looking forward to seeing third party use of this.</p>

<p>That seems to round off <abbr title="Application Programming Interface">API</abbr> week. Any thoughts?</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>As you can probably tell, it&#8217;s hard to talk about something like this without giving too much away. You&#8217;ll get it when you see it.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>It claims to support <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/"><abbr title="Key-Value Coding">KVC</abbr></a> as well. I&#8217;m glad Google are getting into Mac development.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/national-api-week/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Forget text files - here&#8217;s a .php only database system</title>
		<link>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/</link>
		<comments>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/#comments</comments>
		<pubDate>Tue, 03 Apr 2007 03:35:55 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web]]></category>

		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/forget-text-files-heres-a-php-only-database-system</guid>
		<description><![CDATA[What do you do when you're writing a web app that needs to store data, but using a dedicated relational database system would be overkill? Many developers are taking advantage of PHP's file editing capabilities to use plain text files to store and retrieve data. While this is a more lightweight solution, reading the contents of a file is not always the fastest way to retrieve stored information. Here's my very own technique to use a database-like system with PHP files only, with just one line of code needed to grab the information, ready to be used.

This technique is best suited to situations when speed is required in accessing the data. It works best with small amounts of data, and it's possible to store arrays, strings, numbers, etc. Let's explore the basic theory behind the system.]]></description>
			<content:encoded><![CDATA[<h2>Basic premises</h2>

<ul>
    <li>PHP includes a function called parse_str() that takes a string and parses it as if it were the query section of the URI.</li>
    <li>The fopen / fwrite functions can be used on almost any ASCII files - even PHP files.</li>
    <li>Including a PHP file with a simple include() is much faster than using fopen to connect to and read the contents of a text file.</li>
</ul>

<h2>(Very basic) pseudo-code</h2>

<p>Here&#8217;s essentially what our code needs to do in (partial) pseudo-code. Database.php is the file that&#8217;ll store our data, but we&#8217;ll come to that later. If you don&#8217;t understand this section, just skip it; it&#8217;s only meant to be a brief explanation of how the code needs to be structured.
<code>index.php</code></p>

<pre><code>if ( $_REQUEST['data-type'] is set) {
        include 'database.php'
        get_settings_from_database.php()
        echo relevant_settings
        exit;
}</code></pre>

<p><code>admin.php</code></p>

<pre><code>
        start_session()
        if( user not logged in || logging out ){
                show_login_form()
        } else {
                show_administration()
        }</code></pre>

<h2>The real deal</h2>

<p><code>index.php</code></p>

<p>In index.php, we only need code to echo the relevant settings. In this example, I&#8217;ve outputted the results as javascript to be included in script tags.</p>

<pre><code>
&lt;?php

if( isset($_REQUEST['app']) ){
    include_once 'database.php';
    parse_str($theData, $sets);

    $appInfo = $sets[$_REQUEST['app']];

header("content-type: application/x-javascript");
echo "latest = new Array('";
echo implode ( '', '', $appInfo );
echo "');";
}
exit;
?&gt;</code></pre>

<p><code>admin.php</code>
The admin.php file takes care of the database editing. Note that this example only has one table. You could easily add more if you needed to.</p>

<pre><code>
&lt;?php
session_start();
?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html;charset=utf-8" /&gt;

&lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;
&lt;link rel="shortcut icon" href="favicon.ico" type="image/x-icon"&gt;
&lt;link rel="stylesheet" type="text/css" href="style.css" /&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;?php

// your 'oh so secure' password...
@define('MY_PASSWORD','');

// fields you're going to have in your 'table'.
$fields = array('Build No','Version','Download','Info URL');

// the following could be written better, but there's really no need for this basic example.

if( isset($_SESSION['loggedIn']) &amp;&amp; $_SESSION['loggedIn']== 'LOGGEDIN' ){
    if( isset($_POST['logout']) ){
        $_SESSION['loggedIn'] = 0;
        logInForm();
    } else {
        backEnd();
    }
} else {
    if( isset($_POST['login']) &amp;&amp; $_POST['pwd'] == (MY_PASSWORD) ){
        $_SESSION['loggedIn'] = 'LOGGEDIN';
        backEnd();
    } else {
        logInForm();
    }
}

function logInForm(){
        echo "
&lt;form action='' method='post'&gt;
&lt;input type='password' name='pwd' /&gt;
&lt;input type='submit' name='login' value='Log in' /&gt;
&lt;/form&gt;
";
}

function backEnd(){
    if( isset($_POST['edited']) ){
        set_options();
    }
    backEnd_form();
}

function backEnd_form(){
    $output='';
    $output .= "
&lt;form action='' method='post'&gt;
&lt;input type='submit' name='logout' value='Log out' /&gt;
&lt;/form&gt;
";
    $settings = $GLOBALS['fields'];

    include_once 'database.php';
    parse_str($theData, $sets);

//  print_r ($sets);
    $output .= "&lt;form action='' method='post'&gt;&lt;table&gt;&lt;tbody&gt;";

    foreach( $sets as $key =&gt; $value ){
        if( is_array($value) ){
            $output .= "&lt;tr&gt;
&lt;th&gt;{$key}&lt;/th&gt;
&lt;th&gt;&lt;input type='checkbox' name='del_{$key}' id='{$key}' /&gt;
&lt;label for='{$key}'&gt;delete&lt;/label&gt;&lt;/th&gt;
&lt;/tr&gt;n";
            foreach( $value as $keyd =&gt; $data ){
                $output .= "&lt;tr&gt;
&lt;td&gt;{$settings[$keyd]}&lt;/td&gt;
&lt;td&gt;&lt;input type='text' name='a[{$key}][]' value='{$data}' /&gt;&lt;/td&gt;
&lt;/tr&gt;n";
            }
        }
    }

    $output .= "&lt;tr&gt;
&lt;th colspan='2'&gt;Add new:&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add new:&lt;/td&gt;
&lt;td&gt;&lt;input type='text' name='add' value='' /&gt;&lt;/td&gt;&lt;/tr&gt;n";
    $output .= "&lt;tr&gt;&lt;td colspan='2'&gt;
&lt;input type='submit' value='Edit Updates' name='edited' /&gt;&lt;/td&gt;
&lt;/tr&gt;";
    $output .= "&lt;/tbody&gt;&lt;/table&gt;&lt;/form&gt;";

    echo $output;
}

function set_options(){
    $result = '&lt;?php
    $theData="';
    $num_fields = count($GLOBALS['fields']);

    if( $_POST['a'] ){
        foreach ( $_POST['a'] as $keys =&gt; $keydata ){
            if( !$_POST['del_'.$keys] ){
                foreach ( $keydata as $value ){
                    $result .= $keys."[]=".urlencode($value)."&amp;";
                }
            }
        }
    }
    if( isset($_POST['add']) &amp;&amp; ''!=$_POST['add'] ){
        for ( $k=0; $k&lt;$num_fields; $k++ ) {
            $result .= $_POST['add']."[]=&amp;";
        }
    }
    $result .= '";
    ?&gt;';
    $myFile = "database.php";
    $fh = fopen($myFile, 'w') or die("error");
    fwrite($fh, $result);
    fclose($fh);
}
?&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>

<p><code>database.php</code></p>

<pre><code>
&lt;?php

?&gt;</code></pre>

<h2>Adding info</h2>

<p>Navigate to admin.php, and login with your password. Type in a name in the &#8220;add new&#8221; section and submit the form. You&#8217;ll be presented with an editable list of keys / values that you can configure.</p>

<p><a href="http://dev.lipidity.com/wp-content/uploads/2007/04/phpdb.png" title="PHP DB screenshot" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/04/phpdb.thumbnail.png" alt="PHP DB screenshot" /></a></p>

<p>This procedure is really not recommended for commercial products, but for simple personal applications, this is the perfect way to store data. I use a slightly modified version of this method for the update-checking functionality of my <a href="http://dev.lipidity.com/feature/wp-plugin-gregarious">Gregarious</a> plugin for WordPress.</p>

<h2>Variations on a theme</h2>

<p>Instead of using a php file for a database, you could also use a .ini file. PHP has a built-in function called <code>parse_ini_file</code> which gets the contents of the ini file as an array.</p>

<p>The lesson to be learnt here is that if you&#8217;re after something that&#8217;s not already available - innovate. Plan it, think it, write it.</p>

<p>Now, I know the code above could be written a lot better. I also know that I made claims of this technique being superfast without performing any quantitative tests. So, let me know how this could be improved or any other tips and tricks you know to get the most out of your code.</p>

<h2>Ermm&#8230;</h2>

<p>Just to clarify, the idea presented here is extremely useful - I use it all the time for small scale personal projects. However, please don&#8217;t copy and paste the code straight into your public web app as (at the very least) it needs filtering for php injection. Joachim <a href="#comment-3874">points out</a> that serialize / unserialize is a safer and more robust option for use in this circumstance, and I have used that in the past.</p>

<p>So if it&#8217;s years since you last used SQL or a database is just overkill, now you have an alternative!</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/forget-text-files-heres-a-php-only-database-system/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Subversion Basics</title>
		<link>http://lipidity.com/apple/subversion-basics/</link>
		<comments>http://lipidity.com/apple/subversion-basics/#comments</comments>
		<pubDate>Wed, 21 Mar 2007 11:49:18 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web]]></category>

		<category><![CDATA[svn]]></category>

		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/subversion-basics</guid>
		<description><![CDATA[<abbr title="subversion">SVN</abbr> is the next big productivity and collaboration tool to grace the internet. Subversion is the wiki of development, allowing you to track changes, switch to older versions of your project and work as part of a team. Using SVN is a fairly easy process that can be accomplished with extreme ease through the command line.]]></description>
			<content:encoded><![CDATA[<p>Assuming you have access to a subversion repository (such as a project on <a href="http://dev.wp-plugins.org/">wp-plugins.org</a> like <a href="http://www.wordpress.org/extend/plugins/plugin/gregarious">I do</a>), here&#8217;s how you can go about using svn to track changes and work collaboratively.</p>

<p>Open Terminal.app. We&#8217;re going to be using the command line. If you don&#8217;t normally go near the Terminal, don&#8217;t panic. Using svn through the command line is easier than it seems.</p>

<h2>Check it out</h2>

<p>Before we start developing and updating our application, we need to grab a copy of it first. We do this through the <code>checkout</code> command. Checkout, as the name implies, picks up a copy of your application from the repository and downloads it to a location you specify. The checkout command requires to pieces of information. The location of the subversion repository and the location of the folder you wish to download this to. You can omit the latter argument and have subversion download to the current path. For example, if you run <code><acronym title="Change Directory">cd</acronym> ~/project/</code> before using <code>checkout</code>, the contents of the repository will be deposited in <code>~/project/</code>. Let&#8217;s do an example checkout command:</p>

<pre class="code scroll">svn checkout http://svn.example.org/turfapp/ ~/projects/turf/</pre>

<p>Every subversion command you wish to run must be preceded by <code>svn</code> as in the above example. Running the preceding in the Terminal will download the turfapp project (doesn&#8217;t really exist). Now, we&#8217;re ready to get to work!</p>

<p>Once we&#8217;ve checked out a project, we can make edits and updates to our hearts content.</p>

<h2>Ready to Commit?</h2>

<p>When you&#8217;re happy with the changes made, you may upload your work back to the subversion server. However, if you&#8217;re working on a collaborative project, someone may have made a change after you checked out the project. If you upload your copy, it would over-write their work. For this reason, we run the update command.</p>

<pre class="code scroll">
cd ~/projects/turf/

svn update</pre>

<p>This will tell you which revision you have. If everything is fine, we&#8217;re good to upload our changes. We do this by running the commit command. With the commit command, you also need to specify a message about what changes you have made.</p>

<pre class="code scroll">
svn commit -m "Added the Sparkle framework"</pre>

<p>The above assumes you&#8217;re in the correct directory. The message sent to svn would in the example would be &#8220;Added the Sparkle framework&#8221;. Make your message descriptive so anyone else (or even yourself in six months time) can tell what you&#8217;ve done fairly accurately.</p>

<p>Once you&#8217;ve run commit, svn uploads any files that have changed and your updates are saved.</p>

<h2>Adding files</h2>

<h3>Straight add</h3>

<p>If you add a file to the working directory, then run commit, you&#8217;ll find that svn doesn&#8217;t find any changes to update with. Whenever you add files to your working directory that you wish to add to the project, you need to tell svn.</p>

<pre class="code scroll">
svn add newfile.ext</pre>

<p>If the file to be added is in a folder, you&#8217;ll also need to specify that:</p>

<pre class="code scroll">
svn add sources/newfile.h</pre>

<p>Or if the resource you&#8217;re adding is a folder, you can just specify the path:</p>

<pre class="code scroll">
svn add headers/extension/</pre>

<h3>Import</h3>

<p>The import command doesn&#8217;t require you to have a checked out copy of the project, and it allows you to import a file to the server from any location on your hard drive (whereas add is usually restricted to the working directory). For the import command, you need to know the path to the resource, and the path on the server where it should reside. For a folder, you need to specify the path on the server that the folder will take, rather than the path where it should reside as svn will upload the contents of the folder rather than the folder itself. This can be confusing at first if you&#8217;re not aware of it.</p>

<p>The <code>import</code> command will commit the changes you make, so you need to provide a message as well. The overall syntax is:</p>

<pre class="code scroll">
svn import -m "message about update" /Path/To/Resource/ http://svn.location.on/server/trunk/</pre>

<p>Let&#8217;s add a file to our project:</p>

<pre class="code scroll">
svn import -m "Adding about xcode pdf" /Developer/AboutXcode.pdf http://svn.example.corg/turfapp/trunk/resources/</pre>

<p>Will result in the file being uploaded to the server at <code>http://svn.example.corg/turfapp/trunk/resources/AboutXcode.pdf</code>.</p>

<h2>Deleting files</h2>

<p>Now that you can import files, deleting them should be easy. The analog to <code>import</code> is (surprisingly) <code>delete</code>. You can just pass the URL of the file on the server to delete, or you can pass a path to a file in the working directory. If you pass a URL, the change is committed and a message is required. Let&#8217;s get rid of that pdf we imported:</p>

<pre class="code scroll">
svn delete -m "message about deletion" http://svn.example.corg/turfapp/trunk/resources/AboutXcode.pdf</pre>

<p>If you specify a path in the working directory and don&#8217;t send a message, the change is recorded and snchronized with the server the next time you run <code>commit</code>. For example:</p>

<pre class="code scroll">
svn delete trunk/resources/AboutXcode.pdf</pre>

<p>In which case the change is not reflected on the server until you run:</p>

<pre class="code scroll">
svn commit -m "summary of changes"</pre>

<h2>Summary</h2>

<p>SVN can be used to coordinate the development of a project. A project needs to be checked out using the <code>svn checkout</code> into a working directory before it can be edited. Updates are saved using the <code>svn commit</code> command, and files can be added using <code>svn add</code> or <code>svn import</code>, while files are removed using <code>svn delete</code></p>

<p>Some svn commands are analogous to the standard UNIX commands; you can use <code>ls</code>, <code>mkdir</code>, <code>cp</code> etc. to navigate and manage your repository.</p>

<h3>That&#8217;s it!</h3>

<p>You can find out more about subversion at <a href="http://subversion.tigris.org/">http://subversion.tigris.org</a>. Run <code>svn help</code> or <code>svn help subcommand</code> to learn more about the svn commands.</p>

<p>Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/apple/subversion-basics/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CSS Style guide generator</title>
		<link>http://lipidity.com/web/css-style-guide-generator/</link>
		<comments>http://lipidity.com/web/css-style-guide-generator/#comments</comments>
		<pubDate>Thu, 15 Mar 2007 08:37:18 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Design]]></category>

		<category><![CDATA[Web]]></category>

		<category><![CDATA[CSS]]></category>

		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/dev/css-style-guide-generator</guid>
		<description><![CDATA[For a web designer, remembering the properties of all the CSS classes, IDs and elements that have been written, often over multiple stylesheets, can be a real task. Often developers need to keep referring back to their CSS to check the definitions, look at the properties and classes and find the right element. This is time wasted. Time that could be spent on more constructive endeavours.]]></description>
			<content:encoded><![CDATA[<p><a href="http://dev.lipidity.com/wp-content/uploads/2007/03/cssedit.png" style="border: 1px solid #cccccc; margin: 5px; padding: 5px; float: left" title="CSSEdit shot" rel="lightbox"><img src="http://dev.lipidity.com/wp-content/uploads/2007/03/cssedit.thumbnail.png" alt="CSSEdit shot" /></a>MacRabbit&#8217;s CSSEdit eases the burden slightly by displaying a graphical representation of each CSS definition in the sidebar. This however, is still missing information on positioning, padding, margins, borders background images, background properties, font styles and various other vital pieces of data. Of course, it would be unreasonable to stipulate that kind of display in the application as it&#8217;s meant to be a CSS editor. Click on a definition on the left to bring up the full CSS.</p>

<p>But the web designer is not doomed to be eternally editing CSS. The HTML needs to be written as much as the styles, and it&#8217;s really very obtrusive and awkward to have to search through your CSS to see what a particular class or ID looks like. Which where style guides come into play.</p>

<p>A style guide is critical for any designer undertaking a project of a decent size. Not only does it help you remember your classes if you&#8217;re working on multiple projects or if it&#8217;s been a while, it&#8217;s also a great way to  get instantaneous updates, and easy cross-browser rendering to see what your styles look like in different browsers. A style guide will also benefit any other person working on the same website who may not be familiar with the styles you have created.</p>

<p>The benefits of having a style guide are numerous, and fairly obvious (Refer to <a href="http://72.14.253.104/search?q=cache:http://www.willjessup.com/?p=25">this article</a>), but often the time and effort taken to write up a style guide can be a deterrent. Not any more.</p>

<h1 style="text-align: center"><a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 3px">style</span><span style="color: #0080ff">say</span></a></h1>

<p><a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 2px">style</span><span style="color: #0080ff">say</span></a> is, to my knowledge, the first ever style guide generator, and it couldn&#8217;t be easier to use. It&#8217;s been written with a single, clear goal in mind - to provide designers with a resource from which CSS style guides can be created quickly, and with minimal effort.</p>

<p>Currently, <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="margin-right: 2px">style</span><span>say</span></a> is still being developed, but the feature-set is now near enough to completion that it does its job. There is no syntax to learn; <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="margin-right: 2px">style</span><span>say</span></a> recognizes CSS elements, classes and IDs, so you can copy and paste portions straight from your stylesheet. For the moment, the default text includes some basic documentation in the comments, but that will eventually be moved when the project goes final.</p>

<p>Would you find <a href="http://dev.lipidity.com/styled/" title="CSS Style guide generator"><span style="color: #8000ff; margin-right: 2px">style</span><span style="color: #0080ff">say</span></a> to be useful? Or are there any features that you would like to request?</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/web/css-style-guide-generator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Function - call thyself</title>
		<link>http://lipidity.com/development/function-call-thyself/</link>
		<comments>http://lipidity.com/development/function-call-thyself/#comments</comments>
		<pubDate>Wed, 07 Mar 2007 12:16:36 +0000</pubDate>
		<dc:creator>Ankur</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Tutorial]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://dev.lipidity.com/feature/tutorial/function-call-thyself</guid>
		<description><![CDATA[A function that calls itself. What sorts of pictures does that conjure in your mind? Errors, warnings or infinite loops? Crashes? Bugs? Believe it or not, using a function that calls itself can be used for more than hanging up IE. It can cut down on the amount of code you have to write, often by hundreds of lines.]]></description>
			<content:encoded><![CDATA[<p>I see that grimace. You don&#8217;t believe me do you? That&#8217;s all right, I didn&#8217;t believe myself at first either. The sort of thing you probably associate with this sort of thing would be something along the lines of:</p>

<pre class="code">
function writeNumber(number){
    print( number );
    print( " and " );
    writeNumber(number + 1);
}
writeNumber(1);</pre>

<p>If your first language is a programming languauge rather than, say, English, you would realise immediately that the preceding code will, in theory, execute for eternity - kind of like counting to infinite. The output would be <samp>1 and 2 and 3 and 4 &#8230;</samp> and it would keep increasing forever: <samp>75374524 and 75374525 and 75374526 and 75374527 and &#8230;</samp>. It&#8217;s not as bad as:</p>

<pre class="code">
for( i = 0; i &gt;= 0; i++ ){
    print( i );
}</pre>

<p>but in both cases the script would either time out or have to be terminated. Another common mistake while we&#8217;re on the topic of inifinite loops is the forever while.</p>

<pre class="code">
i = 1;
while ( i &lt; 10 ){
    echo i;
}</pre>

<p>Again, the output is not pretty. (As I said, it may be hard for beginners to spot the mistake in this one. The problem here is that <var>i</var> is always less than ten as we&#8217;re not changing it, so the loop continues forever as <var>i</var> is always 1. Adding a simple <code>i++;</code> line before closing the loop will solve the problem.)</p>

<p>There are a lot of ugly connotations related with topics such as this, especially if you&#8217;ve encountered (or written) some of the above code. So if you panicked when I said a function that called itself could be useful, I completely understand your apprehension.</p>

<p>But have no fear; I am not completely crazy (yet) and taking over the world through blatant misinformation is still a long way down on my todo list. So, cast aside your doubt for the time being, and allow me to demonstrate to you how this sort of recursive programming that I&#8217;m talking about can make a serious impact in your code.</p>

<p>The most beautiful way of using this technique (yes, inspiring code is beautiful) is to run through files and folders, arrays or collections of any sort that contain children collections (such as XML markup).</p>

<p>Here&#8217;s an example in PHP:</p>

<pre class="code">
function loop($array, $parent=''){

    foreach( $array as $option =&gt; $value ){
        if( $parent != '' ){
            $option = $parent . '[' . $option . ']';
        }
        if( is_array($value) ){
            loop($value, $option);
        } else {
            ?&gt;
        &lt;div&gt;&lt;?php echo $option; ?&gt; = &lt;?php echo $value; ?&gt;&lt;/div&gt;
            &lt;?php
        }
    }

}

loop ( $names );</pre>

<p>Ingenius, isn&#8217;t it?</p>

<p>If the above code is not clear to you, let&#8217;s take a look at some example usage. I&#8217;ll be working in PHP, but the language doesn&#8217;t really matter; the principle is the important thing.</p>

<p>Let&#8217;s say I have an array, with usernames in it, like so:</p>

<pre class="code">
var $names = array ();

$names[0] = "Bobster";
$names[1] = "Billy";
$names[2] = "Matty";
$names[3] = "Joey";
$names[4] = "Jacko";</pre>

<p>To output these values just requires an easy peasy:</p>

<pre class="code">
foreach ( $names as $name ){
    echo $name;
}</pre>

<p>So why in the world did you just write that <code>loop()</code> function, I hear you exclaim. In this case, it&#8217;s summarised in one word: extensibility.</p>

<p>We&#8217;ve decided that the usernames aren&#8217;t enough. We need to store the the first and last names in the array as well.</p>

<pre class="code">
var $names = array ();

$names[0] = array (
    'username' =&gt; "Bobster",
    'firstname' =&gt; 'Bob',
    'lastname' =&gt; 'Johnson');
$names[1] = array (
    'username' =&gt; "Billy",
    'firstname' =&gt; 'William',
    'lastname' =&gt; 'Gates');
$names[2] = array (
    'username' =&gt; "Matty",
    'firstname' =&gt; 'Matthew',
    'lastname' =&gt; 'Jefferson');
$names[3] = array (
    'username' =&gt; "Joey",
    'firstname' =&gt; 'Joseph',
    'lastname' =&gt; 'Carlton');
$names[4] = array (
    'username' =&gt; "Jacko",
    'firstname' =&gt; 'Jack',
    'lastname' =&gt; 'Richardson');</pre>

<p>Our array is now <em>multi-dimensional</em>. So, to get Bob&#8217;s username, we&#8217;d call <code>$names[0]['username'];</code>. Now, outputting all the values isn&#8217;t so easy:</p>

<pre class="code">
foreach ( $names as $userarray ){
    foreach ( $userarray as $field =&gt; $key ){
        echo $field . ' = ' . $key . '';
    }
}</pre>

<p>Do you see where I&#8217;m heading? What happens when instead of having firstname and lastname keys, we make is another array containing the first and last names like <code>$names[0]['name']['first']</code>? The array is now three-dimensional and we start to run into some problems in outputting our values:</p>

<pre class="code">
foreach ( $names as $userarray ){
    foreach ( $userarray as $field =&gt; $key ){
        if( is_array($field) ){
            foreach ($field as $sub_key =&gt; $value ){
                echo $key . ' ' . $sub_key . ' = ' . $value;
            }
        } else {
            echo $field . ' = ' . $key . '';
        }
    }
}</pre>

<p>Boy! Did that double in size or what! Becoming clearer now? If we decide to make another field that has another array in it, so we get four dimensions, the code will again need to be changed. But, what if we have an array where we <em>don&#8217;t know how many dimensions it has</em>? This is exactly the situation developers are faced with when trying to traverse files and folders. We don&#8217;t know how many levels of nested folders exists inside a particular loction. Trying to write a single function that traverses a filesystem is like trying to write a single function to crawl the internet. And guess what? I already showed you how its done.</p>

<p>Rather than nesting an arbitary number of foreach statements, we finally get back to our <code>loop</code> function.</p>

<pre class="code">
function loop($array, $parent=''){

    foreach( $array as $option =&gt; $value ){
        if( $parent != '' ){
            $option = $parent . '[' . $option . ']';
        }
        if( is_array($value) ){
            loop($value, $option);
        } else {
            ?&gt;
    &lt;div&gt;&lt;?php echo $option; ?&gt; = &lt;?php echo $value; ?&gt;&lt;/div&gt;
            &lt;?php
        }
    }

}

loop ( $names );</pre>

<p>In the <code>loop</code> function, we go through the array, and if the array contains another array, we run <code>loop</code> on it. The beauty of this function is that we pass the key as well as the child array, so we don&#8217;t lose the level that we&#8217;re on. An entry located at <code>$names[0]['admins'][2]['superadmins']['users'] = 'Bob'</code> would be correctly displayed by the <code>loop</code> function as <code>names[0][admins][2][superadmins][users] = Bob</code> The quotes aren&#8217;t printed by this example, but you easily add them in.</p>

<p>Similarly, archiving files could use a function that looks at the contents of the current folder, archives any files, then runs itself on any subfolders.</p>

<p>Find this code inspiring? Or do you know of any other techniques that save time and effort?</p>
]]></content:encoded>
			<wfw:commentRss>http://lipidity.com/development/function-call-thyself/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
