<li><a href="#ui_design">UI Design</a></li>
<li><a href="#event">Event Handling</a></li>
<li><a href="#communication">Communication Between Web Widgets and Other Applications</a></li>
+ <li><a href="#cookbook">Locale Information Formatting</a></li>
<li><a href="#debug">Debugging</a></li>
<li><a href="#performance">Performance Considerations</a></li>
<li><a href="#faq">FAQ</a></li>
</ul>
+ <p class="toc-title">Related Info</p>
+ <ul class="toc">
+ <li><a href="https://developer.tizen.org/dev-guide/2.3.2/org.tizen.web.apireference/html/widget_spec/web_widget.html">Tizen Wearable Web Widget Specification</a></li>
+ </ul>
</div></div>
</div>
<pre class="prettyprint">
<head>
<style>
- body
- {
+ body {
margin: 0px;
text-align: center;
}
- #content
- {
+ #content {
margin-top: 10px;
padding-left: 33px;
padding-right: 33px;
<pre class="prettyprint">
<head>
<style>
- body
- {
+ body {
text-align: center;
}
- #secondDiv
- {
+ #secondDiv {
padding-top: 10px; padding-bottom: 10px;
}
</style>
<pre class="prettyprint">
<style>
- body
- {
+ body {
text-align: center;
}
</style>
<pre class="prettyprint">
<head>
<style>
- body
- {
+ body {
text-align: center;
}
- #largeImage
- {
+ #largeImage {
width: 150px; height: 150px;
}
</style>
<strong>Note</strong>
The widget engine only supports the <code>block</code>, <code>inline</code>, <code>inline-block</code>, and <code>none</code> values for the <code>display</code> property.
<pre class="prettyprint">
-#more
-{
+#more {
.display: inline-block;
}
</pre>
<pre class="prettyprint">
<head>
<style>
- #leftDiv
- {
+ #leftDiv {
text-align: right;
}
- #rightDiv
- {
+ #rightDiv {
text-align: left;
}
- .split
- {
+ .split {
display: inline-block;
width: 45%; height: 100%;
}
- .imgArea
- {
+ .imgArea {
width: 50px; height: 100px;
}
</style>
<pre class="prettyprint">
<head>
<style>
- body
- {
+ body {
width: 360px; height: 360px; margin: 0;
}
- .box
- {
+ .box {
position: absolute;
width: 100px; height: 100px;
}
- #topDiv
- {
+ #topDiv {
left: 130px; /* (360/2)-(100/2) */
}
- #leftDiv
- {
+ #leftDiv {
top: 100px;
}
- #rightDiv
- {
+ #rightDiv {
top: 100px;
left: 260px; /* 360-100 */
}
- #bottomDiv
- {
+ #bottomDiv {
top: 200px;
left: 130px; /* (360/2)-(100/2) */
}
<pre class="prettyprint">
<head>
<style>
- body
- {
+ body {
width: 360px; height: 360px; margin: 0;
}
- .box
- {
+ .box {
width: 100px; height: 100px;
display: inline-block;
}
- #topDiv, #midDiv, #bottomDiv
- {
+ #topDiv, #midDiv, #bottomDiv {
text-align: center;
}
- #leftDiv
- {
+ #leftDiv {
margin-right: 50px;
}
- #rightDiv
- {
+ #rightDiv {
margin-left: 50px;
}
</style>
<p>You can set the widget content styles, such as font and border, by changing the CSS properties. For example, you can set the font and border properties as follows:</p>
<pre class="prettyprint">
-#text
-{
+#text {
font-size: 20pt;
font-weight: bold; /* Available values: normal, bold, bolder, lighter, number */
text-align: center;
}
-
-#more
-{
+#more {
border-style: solid;
border-left-color: lightgray;
border-top-color: lightgray;
</html>
<!--CSS-->
-#viewport
-{
+#viewport {
font-size: 20pt;
text-align: center;
}
-#day
-{
+#day {
color: green;
font-size: 30pt;
}
-#scheduleTitle
-{
+#scheduleTitle {
margin-top: 5%;
height: 13%;
font-weight: bold;
font-size: 30pt;
}
-#more
-{
+#more {
font-size: 16pt;
width: 50px;
display: inline-block;
border-left-color: lightgray;
border-top-color: lightgray;
}
-#scheduleTime, #more
-{
+#scheduleTime, #more {
margin-top: 2%;
color: gray;
}
</html>
<!--CSS-->
-body
-{
+body {
position: absolute;
width: 360px; height: 360px;
font-size: 20px;
text-align: center;
}
-*
-{
+* {
display: block;
margin: 0px; padding: 0px;
}
-.category
-{
+.category {
margin-top: 40px;
margin-left: 137.5px;
}
-.content
-{
+.content {
margin-top: 10px;
padding-left: 33px;
padding-right: 33px;
height: 66px;
font-size: 26px;
}
-.more
-{
+.more {
margin-top: 28px;
height: 20.2px;
}
</pre>
<pre class="prettyprint">
/* JavaScript */
-function onload()
-{
+function onload() {
/* Load news data here */
/* Content update */
<pre class="prettyprint">
var cntImage = 0;
-function step()
-{
+function step() {
document.getElementById("imgWeather").src = "images/sun_" + (cntImage++) + ".png";
- if (cntImage < 4)
- {
+ if (cntImage < 4) {
window.requestAnimationFrame(step);
}
}
-function goAni()
-{
+function goAni() {
window.requestAnimationFrame(step);
}
</pre>
<pre class="prettyprint">
var scrollLength = 0;
-function step()
-{
+function step() {
+
document.getElementById('scheduleTitle').style.transform =
"translateX(" + (scrollLength--) + "px)"
- if (scrollLength > -300) /* Max length */
- {
+ if (scrollLength > -300) { /* Max length */
window.requestAnimationFrame(step);
}
}
-function goAni()
-{
+function goAni() {
window.requestAnimationFrame(step);
}
</pre>
object.addEventListener('load', load);
/* Define the event handler in the main.js file */
-function load()
-{
+function load() {
/* Load water data from shared file */
loadWaterData();
document.getElementById('currentWaterNum').textContent = currentWaterNum;
/* Change the color of the water cups */
- for (var i = 1; i <= currentWaterNum; ++i)
- {
+ for (var i = 1; i <= currentWaterNum; ++i) {
document.getElementById('watercup' + i)).style.backgroundColor = 'blue';
}
}
/* Define the event handler in the main.js file */
/* When the user clicks the button, update the status and change the style */
-function click()
-{
+function click() {
/* Increase the water amount */
currentWaterNum++;
document.addEventListener('visibilitychange', visibilitychange);
/* Define the event handler in the main.js file */
-function visibilitychange()
-{
- if (document.visibilityState === 'hidden')
- {
+function visibilitychange() {
+ if (document.visibilityState === 'hidden') {
/* Store shared data */
- }
- else
- {
+ } else {
/* Load stored data and update the page */
}
}
<p>The following example shows how to set a key-value pair in the <code>Widget_main.js</code> file:</p>
<pre class="prettyprint">
-function checkPreference()
-{
- if (!tizen.preference.exists("KEY"))
- {
+function checkPreference() {
+ if (!tizen.preference.exists("KEY")) {
tizen.preference.setValue("KEY", "Widget_HELLOWORLD1");
}
- if (tizen.preference.exists("KEY"))
- {
+ if (tizen.preference.exists("KEY")) {
tizen.preference.remove("KEY");
tizen.preference.setValue("KEY", "Widget_HELLOWORLD2");
}
console.log('value for KEY: ' + tizen.preference.getValue('KEY'));
/* Callback function */
- var listener = function(data)
- {
+ var listener = function(data) {
/* [Log] Preference with the key: KEY has a new value: APP_HELLOWORLD */
console.log('Preference with the key: ' + data.key
+ ' has a new value: ' + data.value);
</pre>
<p>To set the value in the <code>WebApp_main.js</code> file:</p>
<pre class="prettyprint">
-window.onload = function()
-{
- var timer = setInterval(function()
- {
- clearInterval(timer);
- try
- {
+window.onload = function() {
+ var timer = setInterval(function() {
+ clearInterval(timer);
+ try {
tizen.preference.setValue("KEY", "APP_HELLOWORLD");
tizen.application.getCurrentApplication().exit();
- }
- catch (ignore)
- {
- }
- }, 2000);
+ } catch (ignore) {}
+ }, 2000);
};
</pre>
var CHANNELID = 2000;
var providerAppName = 'WeatherProvider';
-function onerror(err)
-{
+function onerror(err) {
/* Error handling */
}
-var agentCallback =
-{
- onconnect: function(socket)
- {
+var agentCallback = {
+ onconnect: function(socket) {
SASocket = socket;
- SASocket.setSocketStatusListener(function(reason)
- {
+ SASocket.setSocketStatusListener(function(reason) {
disconnect();
- });
+ });
SASocket.setDataReceiveListener(onreceive);
/* Request the provider to get weather info */
SASocket.sendData(CHANNELID, 'request');
onerror: onerror
};
-var peerAgentFindCallback =
-{
- onpeeragentfound: function(peerAgent)
- {
- try
- {
- if (peerAgent.appName == providerAppName)
- {
+var peerAgentFindCallback = {
+ onpeeragentfound: function(peerAgent) {
+ try {
+ if (peerAgent.appName == providerAppName) {
SAAgent.setServiceConnectionListener(agentCallback);
SAAgent.requestServiceConnection(peerAgent);
}
- }
- catch (err)
- {
+ } catch (err) {
/* Error handling */
}
},
onerror: onerror
};
-function onsuccess(agents)
-{
- try
- {
- if (agents.length > 0)
- {
+function onsuccess(agents) {
+ try {
+ if (agents.length > 0) {
SAAgent = agents[0];
SAAgent.setPeerAgentFindListener(peerAgentFindCallback);
SAAgent.findPeerAgents();
}
- }
- catch (err)
- {
+ } catch (err) {
/* Error handling */
}
}
-function onreceive(channelId, data)
-{
+function onreceive(channelId, data) {
document.getElementById('result').textContent = data;
}
-function getDataFromHostApp()
-{
- if (SASocket)
- {
+function getDataFromHostApp() {
+ if (SASocket) {
return false; /* Already connected */
}
- try
- {
- webapis.sa.requestSAAgent(onsuccess, function(err)
- {
- /* Error handling */
- });
- }
- catch (err)
- {
+ try {
+ webapis.sa.requestSAAgent(onsuccess, function(err) {
+ /* Error handling */
+ });
+ } catch (err) {
/* Error handling */
}
}
.send(WeatherProviderForWidget.WIDGET_CHANNEL_ID, jsonData.toString().getBytes());
} catch (JSONException e) {
e.printStackTrace();
-}
-catch (IOException e_io) {
+} catch (IOException e_io) {
e_io.printStackTrace();
}
e.printStackTrace();
}
} else if (req_message.equals(new String("delete_widget"))) {
- Log.e(TAG, "The widget was deleted from the viewer");
+ Log.e(TAG, "The widget was deleted from the viewer");
} else if (req_message.equals(new String("Add city"))) {
- Context context = getApplicationContext();
- Intent intent = new Intent(context, ProviderActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ Context context = getApplicationContext();
+ Intent intent = new Intent(context, ProviderActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
}
}
<h3 id="comm_server">Communicating with a Web Server</h3>
- <p>To get data from a Web server through the Internet, use the XMLHttpRequest API. The Web widget engine, however, does not support the full XMLHttpRequest specification. It supports only the <code>GET</code> method, and the <code>TEXT</code> and <code>JSON</code> data types.</p>
+ <p>To get data from a Web server through the Internet, use the XMLHttpRequest API. The Web widget engine, however, does not support the full XMLHttpRequest specification. It only supports the <code>GET</code> and <code>POST</code> methods, and the <code>TEXT</code> and <code>JSON</code> data types. This design decision emphasizes the read-only behavior of the Web widgets and meets the runtime memory requirements. Use Web widgets to display information in a compact manner, and do not create new resources using the <code>PUT</code> method: as user interaction is not intended and can exceed the widget's maximum allowed memory, it can lead to security risks.</p>
<p>The following example shows Web widget communication with a Web server:</p>
<pre class="prettyprint">
<pre class="prettyprint">
/* JavaScript */
-function errorHandling(e)
-{
- if (e.target.readyState == 3)
- {
+function errorHandling(e) {
+ if (e.target.readyState == 3) {
/* Error handling */
e.target.abort();
}
}
-function getDataFromNetwork(file, handler)
-{
+function getDataFromNetwork(file, handler) {
var xhr = new XMLHttpRequest();
xhr.open('GET', file, true);
xhr.onreadystatechange = handler;
- xhr.onload = function()
- {
- if (this.status == 200)
- {
+ xhr.onload = function() {
+ if (this.status == 200) {
/* Handle the response */
}
};
xhr.send();
}
-/* In case of getting Text data */
-function handleResponseTEXT(e)
-{
- if (e.target.readyState == 4)
- {
- if (e.target.status == 200)
- {
+/* If getting Text data */
+function handleResponseTEXT(e) {
+ if (e.target.readyState == 4) {
+ if (e.target.status == 200) {
document.getElementById('result').textContent = e.target.responseText;
- }
- else
- {
+ } else {
/* Error handling */
}
}
}
-/* In case of getting JSON data */
-function handleResponseJSON(e)
-{
- if (e.target.readyState == 4)
- {
- if (e.target.status == 200)
- {
+/* If getting JSON data */
+function handleResponseJSON(e) {
+ if (e.target.readyState == 4) {
+ if (e.target.status == 200) {
var data = JSON.parse(e.target.responseText);
var val = data.employees;
var result = val[0].firstName + ' ' + val[0].lastName;
document.getElementById('result').textContent = result;
- }
- else
- {
+ } else {
/* Error handling */
}
}
}
</pre>
+<h2 id="cookbook">Locale Information Formatting</h2>
+
+<p>You can use a <code>Date</code> object to format locale information in a widget.</p>
+
+<p>The following example provides the date information in different formats:</p>
+
+<pre class="prettyprint">
+var d = new Date();
+d.toLocaleString(); /* "2/1/2013 7:37:08 AM" */
+d.toLocaleDateString(); /* "2/1/2013" */
+d.toLocaleTimeString(); /* "7:38:05 AM" */
+</pre>
<h2 id="debug">Debugging</h2>
<link rel="stylesheet" type="text/css" href="http://spec.example.com/theme.css">
<!--CSS-->
-#myImage
-{
+#myImage {
content: url('http://spec.example.com/image.png');
}
</pre>
<pre class="prettyprint">
<!--CSS style-->
<style>
- body
- {
+ body {
position: absolute;
margin: 0px;
padding: 0px;
color: Black;
background-color: White;
}
-
- #leftDiv
- {
+ #leftDiv {
text-align: center;
border: 1px solid red;
}
-
- #rightDiv
- {
+ #rightDiv {
text-align: center;
border: 1px solid red;
margin-left: -5px;
}
-
- .split
- {
+ .split {
display: inline-block;
width: 45%; height: 100%;
}
var c = parent.children;
var i;
-for (i = 0; i < c.length; i++)
-{
- if (c[i].id === 'leftDiv')
- {
+for (i = 0; i < c.length; i++) {
+ if (c[i].id === 'leftDiv') {
/* Do something */
}
}
var c = document.body.children;
var i;
-for (i = 0; i < c.length; i++)
-{
+for (i = 0; i < c.length; i++) {
c[i].style.backgroundColor = "red";
}
</pre>