Showing posts with label Dashcode. Show all posts
Showing posts with label Dashcode. Show all posts

Developer Library Search

Search the Apple Developer Library right from your Mac OS X Dashboard.
↓ Download

Dashcode Tips

Get Dashcode Developer Tips, News and Sample Codes right in to your Mac OS X Dashboard.
↓ Download

Dashcode 3.0.5 is out now !


Dashcode Update running on OS X Lion/Mountain Lion.
Download from the Apple Developer Site:
https://developer.apple.com/downloads

Build Web Apps with Dashcode

When you first launch Dashcode (the easiest way to launch it is through Spotlight), you will see that Dashcode has already created some templates for you to build your Web applications quickly (see Figure 1).

Figure 1: The various templates provided by Dashcode

The best way to learn is to select each template (other than the Custom template) and examine the content of each application. When you have selected a template, examine their contents and press Command-r to test the application on the iPhone Simulator. Go ahead and have fun with each template. When you have enough fun and get yourself acquainted with the environment, come back and we shall create an iPhone Web application from scratch and you will see how each part is built.

Building the UI
Alright, now that you are back, create a new Custom project In Dashcode. Notice that by default, Dashcode created a content and a footer parts for you (see Figure 2). Parts are the various views that you seen on your Web applications, such as buttons, text, etc. For this section, you will create a simple currency convertor Web application for the iPhone.

Figure 2: The parts in the Custom template

Select each of these parts and press the delete key. We shall delete these two parts and add our own parts manually.

Using the Library (Window'Show Library), drag-and-drop a Stack Layout part to the design surface (see Figure 3).

Figure 3: Using the Library to drag and drop parts onto your application

Expand the stackLayout part and you should see that it contains two subviews - view1 and view2. Select view1 and change its size to 320px by 356px (see Figure 4) via the Inspector window (Window'Show Inspector). Do the same for view2.

Figure 4: Changing the size for view1 and view2 via the Inspector window

Double-click on view1 and rename it as mainScreen. Do the same for view2 and rename it as settings (see Figure 5).


Figure 5: Renaming the two subviews

In the Library, drag-and-drop the Rounded Rectangle Shape part onto the mainScreen view (see Figure 6).

Figure 6: Adding the Rounded Rectangle Shape part to the subview

It its Inspector window, select the Fill & Stroke tab and in the Style tab select Gradient fill (see Figure 7) and select two colors.

Figure 7: Using the gradient fill to fill the part

Select the Effects tab and check the Glass and Recess checkboxes (see Figure 8).

Figure 8: Adding glass effect to the part

Select the Metrics tab and select the Absolute layout (see Figure 9).

Figure 9: Using absolute layout for parts positioning



Add the following parts to the Rounded Rectangle Shape part (see Figure 10) and name them as:

Text
TextField
Pop-up Menu
Push Button


    Figure 10: Adding additional parts to the subview

    Select the settings subview and repeat the same steps you have performed above. Figure 11 shows the parts added to the settings subview.

    Figure 11: Populating the settings subview

    You are now ready to view the application on the iPhone Simulator. Press Command-r to view the application on the iPhone Simulator (see Figure 12). Notice that the application is hosted by mobile Safari on the iPhone.

    Figure 12: Click 'Run' toView the application on the iPhone Simulator

    Notice that you can only see the mainScreen subview. To see the settings subview, you need to write some code to navigate to it from the mainScreen subview.


    Coding the Application
    So you are now ready to write some code. With the mainScreen subview selected, right-click on the Settings button and select Events'onclick (see Figure 13).

    Figure 13: Creating an event handler for the onclick event

    You will be asked to name the event handler for this event. Name it as shown in Figure 14.


    Figure 14: Naming the handler for the event

    Notice that the code editor now appears at the bottom of the designer (see Figure 15).


    Figure 15: The code editor where you can add your code


    Enter the following code:

        function btnSettings_ClickHandler(event)
        {
            var views = document.getElementById('stackLayout');
            var settings = document.getElementById('settings');
            if (views && views.object && settings) {
                views.object.setCurrentView(settings);
            }
        }

    Select the settings subview and right-click on the Save Settings button and select Events'onclick. Name the handler as btnSave_ClickHandler. Enter the following code:

        function btnSave_ClickHandler(event)
        {
            var views = document.getElementById('stackLayout');
            var front = document.getElementById('mainScreen');
            if (views && views.object && front) {
                views.object.setCurrentView(front, true);
            }
        }

    Test the application again by pressing Command-r. This time, you will be able to navigate to the settings view by tapping on the Settings button in the mainScreen subview (see Figure 16).

    Figure 16: Tapping on the Settings button navigates to the settings subview


    Database Access
    So far, your application displays two screens where you can perform some currency conversion as well as set the exchange rates for the different currencies. For simplicity, I am going to assume that you are converting the currencies into Singapore Dollars (SGD). All the exchange rates would be based on the SGD as the base currency.

    To allow the users to store their own exchange rates, you will make use of the local database feature as defined in HTML 5 (which is supported by Mobile Safari). Doing so allows users of your application to store the exchange rate locally on their iPhones.

    In the main.js file, add the following lines of code for performing database operations:

        var database = null;                           // The client-side database
        var DB_tableName = "CurrencyKeyValueTable";    // database name

        // Function: initDB() - Init and create the local database, if possible
        function initDB()
        {
            try {
                if (window.openDatabase) {
                    database = openDatabase("ExchangeRatesDB", "1.0",
                                            "Exchange Rates Database", 1000);
                    if (database) {
                        database.transaction(function(tx) {
                            tx.executeSql("SELECT COUNT(*) FROM " + DB_tableName, [],
                            function(tx, result) {
                                loadRates();
                            },
                            function(tx, error) {
                                // Database doesn't exist. Let's create one.
                                tx.executeSql("CREATE TABLE " + DB_tableName +
                                " (id INTEGER PRIMARY KEY," +
                                "  key TEXT," +
                                "  value TEXT)", [], function(tx, result) {
                                    initRates();
                                    loadRates ();
                                });
                            });
                        });
                    }
                }
            } catch(e) {
                database = null;
            }
        }

        // Function: initRates() - Initialize the default exchange rates
        function initRates()
        {
            if (database) {
                database.transaction(function (tx) {
                    tx.executeSql("INSERT INTO " + DB_tableName +
                        " (id, key, value) VALUES (?, ?, ?)", [0, 'USD', 1.44]);
                    tx.executeSql("INSERT INTO " + DB_tableName +
                        " (id, key, value) VALUES (?, ?, ?)", [1, 'EUR', 2.05]);
                    tx.executeSql("INSERT INTO " + DB_tableName +
                        " (id, key, value) VALUES (?, ?, ?)", [2, 'AUS', 1.19]);
                });
            }
        }

        // Function: loadRates() - Load the currency exchange rates from DB
        function loadRates()
        {
            var element;  
            var popUpElement = document.getElementById('popupConvertTo');

            if (database) {
                database.transaction(function(tx) {
                    tx.executeSql("SELECT key, value FROM " + DB_tableName, [],
                    function(tx, result) {
                        for (var i = 0; i < result.rows.length; ++i) {
                            var row = result.rows.item(i);
                            var key = row['key'];
                            var value = row['value'];

                            //---populate the pop-up menu part---
                            popUpElement.options[i].text = key;
                            popUpElement.options[i].value = value;

                            if (key == 'USD') {
                                element = document.getElementById('txtUSD');
                            }
                            else {
                                if (key == 'EUR') {
                                    element = document.getElementById('txtEUR');
                                }
                                else if (key == 'AUS') {
                                    element = document.getElementById('txtAUS');
                                }
                            }
                            element.value = value;
                        }
                    },
                    function(tx, error) {
                        showError('Failed to retrieve stored information from database - ' +
                            error.message);
                    });
                });
            }
            else {
                loadDefaultRates();
            }
        }

        // Function: saveRates() - Save the currency exchange rates into DB
        function saveRates()
        {
            if (database) {
                var elementUSD = document.getElementById('txtUSD');
                var elementEUR = document.getElementById('txtEUR');
                var elementAUS = document.getElementById('txtAUS');

                database.transaction(function (tx) {
                    tx.executeSql("UPDATE " + DB_tableName + " SET key = 'USD',
                        value = ? WHERE id = 0", [elementUSD.value]);
                    tx.executeSql("UPDATE " + DB_tableName + " SET key = 'EUR',
                        value = ? WHERE id = 1", [elementEUR.value]);
                    tx.executeSql("UPDATE " + DB_tableName + " SET key = 'AUS',
                        value = ? WHERE id = 2", [elementAUS.value]);
                });
            }
            loadRates();
        }

        // Function: deleteTable() - Delete currency exchange table from DB
        function deleteTable()
        {
            try {
                if (window.openDatabase) {
                    database = openDatabase("ExchangeRatesDB", "1.0",
                                            "Exchange Rates Database");
                    if (database) {
                        database.transaction(function(tx) {
                            tx.executeSql("DROP TABLE " + DB_tableName, []);
                        });
                    }
                }
            } catch(e) {
            }
        }

        // Function: loadDefaultRates() - Load the default exchange rates
        function loadDefaultRates()
        {
            var popUpElement = document.getElementById('popupConvertTo');
            var element = document.getElementById('txtUSD');
            element.value = "1.44";
            popUpElement.options[0].text = "USD";
            popUpElement.options[0].value = element.value;

            element = document.getElementById('txtEUR');
            element.value = "2.05";
            popUpElement.options[1].text = "EUR";
            popUpElement.options[1].value = element.value;

            element = document.getElementById('txtAUS');
            element.value = "1.19";
            popUpElement.options[2].text = "AUS";
            popUpElement.options[2].value = element.value;
        }


    The database code above is pretty straightforward - store the exchange rates inside the database and populate the pop-up menu part when the rates are retrieved.

    Modify the load() function as follows:

        //
        // Function: load()
        // Called by HTML body element's onload event when the Web application is ready to
        // start
        //
        function load()
        {
            dashcode.setupParts();

            initDB();   
            if (!database) {
                loadDefaultRates();
            }
        }

    Press Command-r to test the application. When the application is loaded, the pop-up menu will now display the three different currencies (see Figure 17).

    Figure 17: The pop-up menu part displaying the different currencies

    When you tap on the Settings button, the exchange rates would also be displayed in the settings subview (see Figure 18).

    Figure 18: The exchange rates displayed in the settings subview


    Performing the Conversion
    You are now ready to perform the actual conversion of the currencies. In Dashcode, select the mainScreen subview and right-click on the Convert! Button and select Events'onclick (see Figure 19).

    Figure 19: Handling the onclick event for the Convert! button



    Name the event handler as btnConvert_ClickHandler and code it as follows:

        function btnConvert_ClickHandler(event)
        {
            var amount = document.getElementById("txtAmount").value;   
            var rates = document.getElementById("popupConvertTo").value;
            var result = amount * rates;
            alert(result);
        }

    Press Command-r to test the application. Enter an amount and select the currency to convert. Tapping on the Convert! button will now display the amount converted (see Figure 20).

    Figure 20: Try converting some currencies!


    Converting your Web Application into an iPhone Native Application
    Now that your application is completed, you may deploy your application onto a Web server so that users can access your application through the Safari browser on their iPhones. However, since this is a Web application, the user must have access to the Internet, or else there is no way to access your application. And since our application does not make use of any server-based data, it is a good candidate to convert into a native iPhone application. The easiest way would be to host the Web application within the Safari browser, which is represented by the WebView view in the iPhone SDK.

    In this section, I will show you how you can convert an iPhone Web application into a native iPhone application.

    First, deploy your Web application by clicking the Share item in Dashcode (see Figure 21). Click the Deploy button so that all the files of the application will be saved to a Web publishing directory. Take note of the Web publishing directory shown in Dashcode. It is saved in /Users//Sites/CurrencyConvertor/. You will make use of the files contained within this folder shortly.

    Figure 21: Deploying a Web application in Dashcode
    • Launch Xcode and create a new View-based Application project. Name the project as CurrencyConvertor.
    • In Finder, navigate to the /Users//Sites/CurrencyConvertor/ folder and select the files shown in Figure 22.
    Figure 22: All the project files created by Dashcode

    Drag-and-drop all the selected files onto the Resources folder in Xcode. Xcode will prompt you with a dialog (see Figure 23). Check the Copy items into destination group's folder (if needed) checkbox and click Add.


    Figure 23: Adding all the Dashcode files into the Resource folder in Xcode

    Perform a global Find-and-Replace (by pressing Shift-Command-F). Search and replace the following strings with an empty string (see Figure 24):

    Parts/
    Images/



    Figure 24: Replacing all instances of "Parts/" and "Images/" with an empty string

    This will update the various HTML and JavaScript files that reference other files using the Parts/ and Images/ folder. Files stored in the Resources folder of your Xcode application have no directory structure when they are deployed; hence all the files are in a flat directory.

    Select the files shown in Figure 25 and drag-and-drop them onto the Copy Bundle Resources (16) folder. This will ensure that all the HTML, JavaScript, CSS, and images files will be deployed together with your application.

    Figure 25: Copying all the Web files into the targets folder so that they are deployed together with your application


    In the CurrencyConvertorViewController.h file, add the following statements to define an outlet:

        #import

        @interface CurrencyConvertorViewController : UIViewController {
            IBOutlet UIWebView *webView;
        }

        @property (nonatomic, retain) UIWebView *webView;

        @end


    Double-click on the CurrencyConvertorViewController.xib file to open it in Interface Builder.
    Add a WebView view to the View window and control-click and drag the File's Owner item to the WebView view (see Figure 26). Select webView.


    Figure 26: Connecting an outlet to a view

    In the CurrencyConvertorViewController.m file, add the following statements:

        #import "CurrencyConvertorViewController.h"

        @implementation CurrencyConvertorViewController

        @synthesize webView;

        - (void)viewDidLoad {
            NSString *path = [[NSBundle mainBundle] pathForResource:@"index"
                                ofType:@"html"];
            [webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath: path
                                    isDirectory:NO] ]];
            [super viewDidLoad];
        }



    That's it! Press Command-r to test the application on the iPhone Simulator. The Web application is now hosted within the WebView view (see Figure 27). What you have just done is convert a Web application into a native application!

    Figure 27: Running the Web application as a native iPhone application

    Sample Codes for Dashcode


    Dashboard is a display and management system for Mac OS X desktop utilities, called widgets. Developers can create widgets, such as a clock or a calculator,
    to provide functionality that doesn't require the complexity of a large application.

    Dashcode Sample Codes:

    Hello World
    Introductory Dashboard widget example
    (HTML)
    (DMG)
    (ZIP)

    Fortune
    Deprecated - Demonstrates use of a widget plug-in
    (HTML)
    (DMG)
    (ZIP)

    Scroller
    Dashboard widget with a DHTML scrollbar implementation
    (HTML)
    (DMG)
    (ZIP)

    Birthdays
    Dashboard widget with a plug-in that queries AddressBook.framework for contacts with upcoming birthdays
    (HTML)
    (DMG)
    (ZIP)

    Fader
    Demonstrates fading of elements inside a Dashboard widget
    (HTML)
    (DMG)
    (ZIP)

    Goodbye World
    Demonstrates display and use of widget preferences to save a widget's state
    (HTML)
    (DMG)
    (ZIP)

    Hello Welt
    Demonstrates localization techniques for Dashboard widgets
    (HTML)
    (DMG)
    (ZIP)

    Voices
    Demonstrates use of the widget.system command from Dashboard
    (HTML)
    (DMG)
    (ZIP)

    Resizer
    A widget that demonstrates how to use the Apple Animation and Animator classes.
    (HTML)
    (DMG)
    (ZIP)

    Syncer
    A widget that demonstrates how to use handle a Dashboard Sync event.
    (HTML)
    (DMG)
    (ZIP)

    Dashcode



    Ever wish you could make your very own Dashboard widget? A handy RSS feed of your favorite blog, maybe. Or a miniature photocast of your iPhoto library. Something uniquely useful, uniquely you. Say hello to Dashcode. Now you can get a widget up and running in minutes, even if you’ve never written a line of code in your life.


    Choose your widget.
    Your Dashcode project starts life as a template designed specifically for the kind of information you want to display. Choose from a handful of Dashcode widget templates — including a countdown timer, map, RSS feed, photocast, podcast, and gauge — or create a widget from scratch with a blank template. Every template includes detailed workflow steps to guide you through the process of creating your widget.

    Stop, drop, and roll.
    After you choose the perfect template, you can drag and drop components onto the Dashcode canvas. Drag in an RSS link and your widget populates with a full feed. Drag in a photocast URL and your widget transforms into a self-contained slideshow. Drag in a podcast link and you can start playing the feed right from your widget.

    Widgets by design.
    Once your widget’s working, you can use the Dashcode library to add design and functionality finesse. The library comes with a collection of buttons, lists, containers, and text fields. Resize the components of your entire widget or alter fonts, colors, gradients, images — practically every visual element — without writing a single line of code.

    Deploy and conquer.
    Dashcode organizes all the files that make up your widget, including images, JavaScript code, style sheets, generated files, and localizations. Add new files and the Dashcode project manager takes care of updates automatically. And when your widget is ready for prime time, Dashcode packages up all your files and the Apple-provided resources required to deploy your widget to Dashboard or submit it to Apple.com.

    Dashcode for the power user.
    Instant-on debugging. Total integration of project management, design, and code in Dashcode makes your widget ready to test. Just click Run and your widget instantly starts up. Click Pause to inspect the running widget or set breakpoints to debug specific sections of code. The built-in debugger provides all the features you’d expect from a professional developer tool.

    Professional source code editor.
    Dashcode offers all the text-editing features of a professional integrated development environment (IDE) — including color syntax highlighting, line numbering, and Code Sense code completion — optimized for the JavaScript programming language. The editor also integrates with the debugger, so you can easily set and view breakpoints and track your widget’s execution through the source code.

    Code snippets.
    The Dashcode library includes more than just GUI controls. It also provides a rich collection of JavaScript code snippets for many common programming tasks. Simply drag the snippet from the library and drop it into your JavaScript source file. Each snippet includes instructions for changing the behavior to meet your needs. The snippets complete many common tasks you would otherwise have to hand-code, including:

    RSS parsing.
    Download and understand RSS feeds to provide up-to-date information to your widget.

    Animate elements.
    Fade, move, or resize elements in your widget.

    String and data processing.
    Format and localize text.

    Preferences.
    Manage user preferences for your widget: Perfect for the back panel.

    Parts APIs.
    Manipulate the include GUI parts using JavaScript.


    Generic Ajax Widget

    As part of this article, I've included a generic Ajax widget that simply grabs a URL and parses out a small section of the DOM that I'm interested in.
    It’s a good jumping off point to get going with an Ajaxified widget.



    Getting Dashcode
    If you've got a recent version of Leopard or Tiger, the system Disks will contain Dashcode in the developer kit (it may be installed already in your /Developer/Applications directory).
    Apple did have Dashcode available for download, but since it expired in July (when Leopard was to come out) it’s no longer there.
    You can hunt around the Internet for a old mirror if you don't have the CDs.
    Once installed, it'll say it’s expired: just get Dashcode working again.


    Stability
    Broken Dashcode RenderDashcode is particularly ropy with Safari 3.
    With Safari 2 it’s much more stable. Since there is the occasional crash from Dashcode,
    I would recommend constantly saving your project as you're coding.
    I found more than 10% of the time, Dashcode would crash and result in a total loss of my code from the last save point.

    Also, I've noticed that dumping a lot to the run log, when viewing the log, can cause Dashcode to slow right down to almost hanging.
    Best to avoid dumping large amounts of HTML to the log.
    However - and this is a big one - the upside of programming with Dashcode is worth the risk of the crash, because it’s takes most work out of the design process.
    Since you're using it’s GUI to drag and drop your design and how the user will interact with it, rather than having to code the look and feel by hand.

    Designing Widgets
    The interface and the library component of Dashcode makes it possibly the strongest app for developing widgets. It’s 2 minutes work to create a glass effect on your widget, or to place the elements on the window and get going.
    I would strongly recommend studying other widgets, and reading through the Dashcode design recommendations as it’s easy to design a widget that works, but twice the work to design a widget that’s usable and works well.
    You'll find you can place widget-type objects on your widget, like scroll areas or gauges - but to handle them in the code isn't entirely intuitive, which is why the best source of understand how these interface elements work, is by opening up other widgets that already make use of the element.

    Controls
    Dashcode offers the easy integration of bespoke elements such as the scrollarea, gauges and other such sexy components.
    They're pretty easy to drop on to the widget from Dashcode, but until you're coding, they're not immediately obvious how they work.
    The help is limited, so I would recommend to develop by tutorial, in particular, look for the 'refresh()' methods - as this seems to be a fairly standard way to redraw objects.
    Full documentation for the Apple classes API is available, but it’s pretty clinical.




    Effects
    Although effects are available within the Apple classes, you'll need to implement them yourself.

    This is fairly limited to dynamic resizing of the widget, which is achieved using:

    window.resizeTo(x, y);
     
    If you are going to resize the widget dynamically, check out the Apple resizing examples too.
    I used this technique in my HTML entities widget to keep the widget small when it’s dropped in to the Dashboard, but to allow it to grow dynamically when the user searched for a particular HTML entity.
    You should be able to find easing effects code and examples if the built in Apple animation class doesn't suite your needs.

    Running system commands
    This is one of the few areas that’s well documented in the provided API.

    You can run system commands using the following type of command:

    widget.system('ps -auxww | grep ' + myCommand, null);
     
    What you should keep in mind, is that you can run any command through the system method. This includes Perl, Ruby, AppleScript and anything else that suits your needs.
    Using these commands I've recently been able to create a widget that queries Mail’s SQLite’s database via Perl.
    It was a case of running the system method and capturing the output (and in my case, eval'ing it from a JSON output).



    Ajax in the widget
    You widget supports a variation of the Ajax object (or rather xmlhttprequest object).
    This version isn't bound by the usual security constraints of a browser - most importantly, it can request content from any domain.
    To execute any Ajax requests from your widget, ensure you have the Allow Network Access attribute turned on - otherwise the Ajax will fail without any given reason.
    For example, you could use Ajax to pull your film page from IMDb and then parse the XML for the elements of interest.
    However, if you do want to pull some data from a web page and process it using the DOM returned you have to fiddle the request - in particular the responseXML will be null because the page being returned isn't text/xml - it’s text/html. You can do it using the following (in jQuery syntax):

    $.ajax({
    url: 'http://remysharp.com/example_page', // doesn't really exist!
    dataType: 'html', // important
    success: function (xml) {
    // convert the HTML to an XML DOM object
    var dom = getDOMfromXML(xml);
    alert(dom.getElementsByTagName('h1').length);
    }
    });

    function getDOMfromXML(xml) {
    var d = document.createElement('div');
    xml = xml.substring(xml.indexOf('<body') + xml.substring(xml.indexOf('<body')).indexOf('>')+1);
    xml = xml.substring(0, xml.indexOf('</body>'));
    d.innerHTML = xml;
    return d;
    }
     
    This getDOM function is pretty horrible - but it works. I tried using DOMParser and tried using Ajax local data trick and I tried using an iframe to inject the XLM - but neither would load the XML properly (in fact it would be blank).
    The iframe would not load properly because it was still loading the entire frame while I was trying to access it.
    You can see this in use in the generic Ajax widget or download the source Dashcode project.




    Widget Attributes

    The widget attributes are fairly self explanatory, but it’s worth knowing:
    • Allow Network Access is required for Ajax requests
    • Allow Command Line Access is required for running external programs, i.e. if you have a Perl script executing some arbitrary task

    If you intend to make your widget available in different languages, then this is the place to enter the different strings.

    The Inspector

    • Hide items from the default image to present a better widget when it’s installing. It can to keep the preview of your app looking clean.

     

    Debugging
    Dashcode comes with a log that can be viewed during run time.

    You have following debugging tools:
    • Breakpoints
    • Live stack traces
    • Evaluate window - to test commands

    To write to the log, you need to use alert("My debug message");.