michelle hedstrom may 17, 2005

38
Michelle Hedstrom May 17, 2005

Upload: manju

Post on 19-Jan-2016

30 views

Category:

Documents


0 download

DESCRIPTION

Introduction to Dashboard Widgets. Michelle Hedstrom May 17, 2005. Agenda. Introduction to Dashboard/Widgets Building your first widget Adding on - web searching! Scrollbars and saved searches What’s Next Debugging. What is Dashboard?. Part of Mac OS 10.4 (Tiger). - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Michelle Hedstrom May 17, 2005

Michelle Hedstrom

May 17, 2005

Page 2: Michelle Hedstrom May 17, 2005

Agenda

• Introduction to Dashboard/Widgets

• Building your first widget

• Adding on - web searching!

• Scrollbars and saved searches

• What’s Next

• Debugging

Page 3: Michelle Hedstrom May 17, 2005

What is Dashboard?

• Part of Mac OS 10.4 (Tiger).

• Lets You Run Mini-Applications (Widgets).

• Pretty wrapper around Apple’s WebKit.

• Virtual Layer - only comes when called.

Page 4: Michelle Hedstrom May 17, 2005

What is a Widget?

• Mini application - can run in Safari.• Stored as a bundle.• HTML, JavaScript, & CSS.• Information, application, or accessory.

New widget object

Page 5: Michelle Hedstrom May 17, 2005

Components of a Widget

• HTML Files, Info.plist, Default.png, Icon.png

• Optional: JavaScript & CSS Files

Picture from http://developer.apple.com/macosx/dashboard.html

Page 6: Michelle Hedstrom May 17, 2005

Making a Widget

• Put all required files in a folder.

• Add on to folder name .wdgt extension - turns into bundle.

• Double-click .wdgt file to launch in Dashboard.

• Optionally, move to ~/Library/Widgets.

Page 7: Michelle Hedstrom May 17, 2005

We’re Not Talking About…

• Error checking

• Preferences

• Most design conventions

Aqua bad

Custom good

Page 8: Michelle Hedstrom May 17, 2005

Tools Needed

• A Mac with Tiger (OS 10.4) installed

• Text editor

• Graphics editor (optional)

• Xcode Tools (optional)

Page 9: Michelle Hedstrom May 17, 2005

Build Stage 1

• Create the widget itself.

• Put in the background graphic.

• Add in the search form field with results area.

Page 10: Michelle Hedstrom May 17, 2005

Stage 1 HTML

<html>

<head> <link rel="stylesheet" href="YahooClass.css" type="text/css" /> <title>Yahoo Class Widget</title></head>

<body> <div class="front"> <input type="search" id="searchYahoo" size="30" /> <div id="resultsArea"> </div> </body>

</html>

resultsArea

searchYahoo

front

Page 11: Michelle Hedstrom May 17, 2005

Stage 1 CSS

.front { width: 290px; height: 314px; background-image: url(Default.png);}

.searchYahoo { position: absolute; top: 60px; left: 40px; text-align:left;}

#resultsArea { background-color: white; position: absolute; font-size: small; top: 90px; left: 30px; width: 240px; height: 190px;}

Page 12: Michelle Hedstrom May 17, 2005

Stage 1 Info.plist

•CFBundleDisplayName - actual widget name displayed in Finder and widget bar.

•CFBundleIdentifier - Uniquely identifying string in reverse domain format.

•CFBundleName - Name of widget, must match name of bundle on disk minus the .wdgt extension.

•CFBundleVersion - version number.

•MainHTML - name of the main HTML file implementing widget.

Page 13: Michelle Hedstrom May 17, 2005

Build Stage 2

• Run search when user types in search terms.

• Display results in results box.

• Clicking on URL opens in widget window.

Page 14: Michelle Hedstrom May 17, 2005

Stage 2 Info.plist

•AllowNetworkAccess - if widget requires any network resources.

Page 15: Michelle Hedstrom May 17, 2005

Stage 2 HTML

<html><head> <link rel="stylesheet" href="YahooClass.css" type="text/css" /> <script language="JavaScript" src="Main.js"></script> <title>Yahoo Class Widget</title></head><body> <div class="front"> <input type="search" id=“searchYahoo” size="30" onSearch="doSearch(this.value)" /> <div id="resultsArea"> </div> </div></body></html>

Page 16: Michelle Hedstrom May 17, 2005

Stage 2 JS - Vars

var baseSearchURL = "http://api.search.yahoo.com/WebSearchService/V1/";var searchMethod = "webSearch";var appID = "DashboardSearch";var numResultsReturned = "5";var req;

•Requirements of Yahoo Search API.

•Num results returned optional - defaults to 10 if not provided.

Page 17: Michelle Hedstrom May 17, 2005

Stage 2 JS - doSearch()

function doSearch(searchValue) { var searchURL= baseSearchURL+searchMethod+"?"+"appid="+appID+"&query="+searchValue+"&results="+numResultsReturned;

req = new XMLHttpRequest(); req.open("GET",searchURL,false); req.send(null); document.getElementById('resultsArea').innerHTML = (parseXML(req.responseXML));}

•Building the search URL:•http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=DashboardSearch&query=Michelle&results=5

Page 18: Michelle Hedstrom May 17, 2005

…Stage 2 JS - doSearch()…

function doSearch(searchValue) { var searchURL= baseSearchURL+searchMethod+"?"+"appid="+appID+"&query="+searchValue+"&results="+numResultsReturned; req = new XMLHttpRequest(); req.open("GET",searchURL,false); req.send(null); document.getElementById('resultsArea').innerHTML = (parseXML(req.responseXML));}

•HTTP request that returns XML DOM object.

•req.open with false boolean - synchronous mode just for demo. Asynchronous better - check for onreadystatechange event.

•req.send arg. used to transmit content for a POST request, null otherwise.

Page 19: Michelle Hedstrom May 17, 2005

…Stage 2 JS - doSearch()…

function doSearch(searchValue) { var searchURL= baseSearchURL+searchMethod+"?"+"appid="+appID+"&query="+searchValue+"&results="+numResultsReturned; req = new XMLHttpRequest(); req.open("GET",searchURL,false); req.send(null); document.getElementById('resultsArea').innerHTML = (parseXML(req.responseXML));}

•Looks for a div called resultsArea.

•Gets the area where the content is stored for that div.

Page 20: Michelle Hedstrom May 17, 2005

…Stage 2 JS - doSearch()

function doSearch(searchValue) { var searchURL= baseSearchURL+searchMethod+"?"+"appid="+appID+"&query="+searchValue+"&results="+numResultsReturned; req = new XMLHttpRequest(); req.open("GET",searchURL,false); req.send(null); document.getElementById('resultsArea').innerHTML = (parseXML(req.responseXML));}

•Gets results back of search as a document object.

•Passes off to parseXML function.

Page 21: Michelle Hedstrom May 17, 2005

Stage 2 JS - parseXML()function parseXML(xmlResults) { var resultsStrings = ""; var indResponse = xmlResults.getElementsByTagName("Result");

for (i=0; i<indResponse.length; i++) { var title = indResponse[i].getElementsByTagName("Title")[0].firstChild.nodeValue; var URL = indResponse[i].getElementsByTagName("ClickUrl")[0].firstChild.nodeValue; var summary = indResponse[i].getElementsByTagName("Summary")[0].firstChild.nodeValue;

resultsStrings += "<A HREF=\""+URL+"\">"+title+"</a><br>"+summary+"<p>"; } return resultsStrings;}

•Find all nodes named Result.

•Each individual search result is one such XML node.

Page 22: Michelle Hedstrom May 17, 2005

…Stage 2 - parseXML()function parseXML(xmlResults) { var resultsStrings = ""; var indResponse = xmlResults.getElementsByTagName("Result");

for (i=0; i<indResponse.length; i++) { var title = indResponse[i].getElementsByTagName("Title")[0].firstChild.nodeValue; var URL = indResponse[i].getElementsByTagName("ClickUrl")[0].firstChild.nodeValue; var summary = indResponse[i].getElementsByTagName("Summary")[0].firstChild.nodeValue;

resultsStrings += "<A HREF=\""+URL+"\">"+title+"</a><br>"+summary+"<p>"; } return resultsStrings;}

•Iterate through all results, from high level object to value of each individual field we want.

•Format all results in way we want with clickable title.

Page 23: Michelle Hedstrom May 17, 2005

Stage 2 - CSS

Without overflow:hidden

With overflow:hidden

#resultsArea { background-color: white; position: absolute; font-size: small; top: 90px; left: 30px; width: 240px; height: 190px; overflow: hidden;}

Page 24: Michelle Hedstrom May 17, 2005

Build Stage 3

• Scroll bars for results.

• Clicking on URL opens in default browser.

• Saved keyword search.

Page 25: Michelle Hedstrom May 17, 2005

Scrollbar

• Custom built scrollbar - Apple code

• “Define a parent DIV with overflow CSS property set to hidden”

resultsArea

searchYahoo

front

#resultsArea { background-color: white; background-image: none; position: absolute; font-size: small; top: 90px; left: 30px; width: 240px; height: 190px; overflow:hidden;}

Page 26: Michelle Hedstrom May 17, 2005

Scrollbar Step 2

• “Place all scrollable content in a div within the parent div: this ‘child’ div should have an undefined overflow, or a value of visible.”

<div id=“resultsArea”> <div id=“mainContent”> </div</div>

•Changed resultsArea to mainContent in Main.js

Page 27: Michelle Hedstrom May 17, 2005

Scrollbar Step 3

• “Declare the Scroller divs and place them inside the parent div.”

<div id="resultsArea"> <div id="mainContent"> </div> <div id='myScrollBar'>

<div id='myScrollTrack' onmousedown='mouseDownTrack(event);' onmouseup='mouseUpTrack(event);'>

<div class='scrollTrackTop' id='myScrollTrackTop'></div> <div class='scrollTrackMid' id='myScrollTrackMid'></div> <div class='scrollTrackBot' id='myScrollTrackBot'></div></div><div id='myScrollThumb' onmousedown='mouseDownScrollThumb(event);'> <div class='scrollThumbTop' id='myScrollThumbTop'></div> <div class='scrollThumbMid' id='myScrollThumbMid'></div> <div class='scrollThumbBot' id='myScrollThumbBot'></div>

</div> </div> </div>

Page 28: Michelle Hedstrom May 17, 2005

Scrollbar Step 4

• “It is important that the child div start with a CSS top property set to 0;”

#mainContent { position:absolute; left:0; top: 0; right:35px;}

Page 29: Michelle Hedstrom May 17, 2005

Scrollbar Step 5

• Scrollbar CSS from Apple#myScrollBar {/* border-style:solid; border-color:yellow; */

position:absolute;top:6px;bottom:14px;right:0px;width:19px;display:block;-apple-dashboard-region:dashboard-region(control rectangle);

}

/* Scroller track */.scrollTrackTop {/* border-style:solid; border-color:red; */

position:absolute;top:0px;width:19px;height:18px;background:url(Images/top_scroll_track.png) no-repeat top left;

}…

Page 30: Michelle Hedstrom May 17, 2005

apple-dashboard-region

#myScrollBar {/* border-style:solid; border-color:yellow; */

position:absolute;top:6px;bottom:14px;right:0px;width:19px;display:block;-apple-dashboard-region:dashboard-region(control rectangle);

}

•Region used for specific purpose.

•1st param - type of region defined.

•2nd param - shape of region

Page 31: Michelle Hedstrom May 17, 2005

Stage 3 HTML

…<head> <link rel="stylesheet" href="YahooClass.css" type="text/css" /> <script language="JavaScript" src="Main.js"></script> <script language="JavaScript" src="Scroller.js"></script> <title>Yahoo Class Widget</title></head><body onload='setup();'>…

•Use the JavaScript file provided by Apple.

•Call a setup function after load.

Page 32: Michelle Hedstrom May 17, 2005

Stage 3 JS - setup()

function setup() { scrollerInit(document.getElementById("myScrollBar"), document.getElementById("myScrollTrack"), document.getElementById("myScrollThumb")); document.getElementById('mainContent').innerHTML = ""; calculateAndShowThumb(document.getElementById('mainContent')); }

•Call Apple defined init function.

•Set our content area to empty.

•Figure out the height of the view, and make the thumb proportional (Apple defined func.).

Page 33: Michelle Hedstrom May 17, 2005

Stage 3 JS - doSearch()function doSearch(searchValue) { var searchURL= baseSearchURL+searchMethod+"?"+"appid="+appID+” &query="+searchValue+"&results="+numResultsReturned; req = new XMLHttpRequest(); req.open("GET",searchURL,false); req.send(null);

document.getElementById('mainContent').innerHTML = (parseXML(req.responseXML)); calculateAndShowThumb(document.getElementById('mainContent'));}

•Resize the scrollbar for the current amount of text in the area.

Page 34: Michelle Hedstrom May 17, 2005

Saved Keyword Search

<input type="search" id="searchYahoo” size="30" onSearch="doSearch(this.value)" />

Change:

To: <input type="search" id="searchYahoo" size="30" results="5" onSearch="doSearch(this.value)" />

•Results is number of past searches saved.

Page 35: Michelle Hedstrom May 17, 2005

Open URL in Default Browserfunction parseXML(xmlResults) { var resultsStrings = ""; indResponse = xmlResults.getElementsByTagName("Result");

for (var i=0; i<numResultsReturned; i++) { var title = indResponse[i].getElementsByTagName("Title")[0].firstChild.nodeValue; var URL = indResponse[i].getElementsByTagName("ClickUrl")[0].firstChild.nodeValue; var summary = indResponse[i].getElementsByTagName("Summary")[0].firstChild.nodeValue;

if (window.widget) { resultsStrings += "<A HREF=\"javascript:widget.openURL('"+URL+"')\">"; } else { resultsStrings += "<A HREF=\""+URL+"\">"; } resultsStrings += title+"</a><br>"+summary+"<p>"; } return resultsStrings;}

Page 36: Michelle Hedstrom May 17, 2005

What’s Next?

• Truncate summary or build summary box at bottom of screen.

• Preferences to support language, type of search, num results returned.

Page 37: Michelle Hedstrom May 17, 2005

Debugging

• Safari JavaScript Console Open Terminal window, type:

• defaults write com.apple.Safari IncludeDebugMenu 1 Relaunch Safari, check “Log JavaScript Exceptions” in Debug Menu Choose “Show JavaScript Console” in Debug menu.

• Write directly to JS Console window.console.log(“Problem if you get here") Shows up in dark green

• Create Debug div

• Good ‘ol alerts

Page 38: Michelle Hedstrom May 17, 2005

Resources

• Developing Dashboard Widgets - http://developer.apple.com/macosx/dashboard.html

• Apple Dashboard Documentation - http://developer.apple.com/documentation/AppleApplications/Dashboard-date.html

• Yahoo Search API - http://developer.yahoo.net/

• /Library/WidgetResources for premade graphics/buttons

• /Developer/Examples/Dashboard

• /Developer/Applications/Utilities/Property List Editor

• Me! - [email protected]