Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Web and WebWorks Development

Reply
Developer
nathanpc
Posts: 134
Registered: ‎05-19-2012
My Device: Torch 9800, PlayBook 64GB, Dev Alpha

Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Originally posted at my blog: Tech Philosophy: Using bbUI’s onscreenready and ondomready to Dynamically Change Your HTML.

 

I started playing a bit with BlackBerry development these days and since I'm not the best at Java (also hate how it's difficult to do simple things with it) I choose their awesome framework for HTML5 native web development called WebWorks. I really loved it because it's like PhoneGap, but a lot easier to build plugins (extensions on WebWorks) for it to make your native WebApp feel a lot more native.

 

Another great thing that RIM did to make the life of WebWorks developers easier and create apps that are exactly like native ones is a Javascript framework called bbUI.js, which is like jQuery Mobile, but seriously, it's a lot more than just a UI framework. It makes it a lot easier to interact with the OS, override the back button for example, and makes your development cycle look a lot with native development by using screens. On this post I'll teach you how to dynamically manipulate the screen's HTML before it's processed by the bbUI library.

 

One of the first things that you'll notice after you start working with bbUI is that it's not just a collection Javascript functions and CSS stylings, it actually reformat and customize your screen's HTML before it's shown to the user. As an example, this simple image-list item declaration in your screen HTML source looks like this:

 

<div data-bb-type="item" data-bb-title="Title goes here" data-bb-img="images/test.png" onclick="alert('this was clicked')">A description is welcome.</div>  

After it's processed by the library and shown to the user it will look like this:

 

<div data-bb-type="item" onclick="alert('this was clicked')" class="bb-hires-image-list-item" onmouseover="this.setAttribute('class','bb-hires-image-list-item-hover')" onmouseout="this.setAttribute('class','bb-hires-image-list-item')" x-blackberry-focusable="true"><img src="images/test.png">
  <div class="details">
    <span class="title">Title goes here</span>
    <span class="accent-text"></span>
    <div class="description">A description is welcome.</div>
  </div>
</div>

Hopefully we can easily manipulate our screen elements and other things before and after it's processed by bbUI. This is done with the bb.init() function (you can always read more at their documentation). This will be called when the application starts and can be used to listen to events like when a screen is loaded. The main ones are onscreenready and ondomready.

 

onscreenready: This event will be fired before the sources get processed by the library, so here is where you should manipulate, add or remove things from your HTML source using Javascript, so after it's done the code will be passed to bbUI to be processed.

 

ondomready: This event will be fired when the screen finished loading and it has been already processed by bbUI and shown to the user. Here you can put things like alerts and other things that will be used to interact with the user, also some little editing to the screen's source like renaming a field grabbing some information from a field and etc.

Here is a example of a bb.init() call:

 

bb.init({
  onscreenready: function (element, id) {
    if (id == "main") {
      // code to be executed before the "main" screen is loaded.
    } else if (id == "add") {
      // code to be executed before the "add" screen is loaded.
    }
  },
  ondomready: function (element, id) {
    if (id == "main") {
      // code to be executed after the "main" screen is loaded.
    } else if (id == "add") {
      // code to be executed after the "add" screen is loaded.
    }
  }
});

The code is almost self-explanatory. The id is the name, second argument, you gave to a screen when you call it to be processed, for example bb.pushScreen("screen/main.html", "main"). element is the screen source code, which is used to be manipulated before the screen is loaded.

 

A little problem that some developers might come across while using bbUI for the first time is that when you want to append or change the HTML of the screen before it's processed by bbUI you might write your code like if the HTML was already loaded onto the screen, but it's not. Here is an example of a code that won't work, used to populate a image-list and then show a button that was hidden (using jQuery):

 

bb.init({
  onscreenready: function (element, id) {
    if (id == "main") {
      var item = document.createElement('div');
      item.setAttribute('data-bb-type','item');
      item.setAttribute('data-bb-title','my title');
      item.innerHTML = 'my description';
      item.setAttribute('data-bb-img','foo.png');

      document.getElementById('mylist').appendItem(item);

      $("#button").css("display", "block");
    }
  }
}); 

The main problem here is that it's using document as the source to be manipulated. Since bbUI still hasn't appended the screen into the document it will give you an error. In order to correct this you should replace document with element, that is passed by the onscreenready event. If you have any jQuery code, just add element as a context argument as shown below in the corrected code:

 

bb.init({
  onscreenready: function (element, id) {
    if (id == "main") {
      var item = element.createElement('div');
      item.setAttribute('data-bb-type','item');
      item.setAttribute('data-bb-title','my title');
      item.innerHTML = 'my description';
      item.setAttribute('data-bb-img','foo.png');

      element.getElementById('mylist').appendItem(item);

      $("#button", element).css("display", "block");
    }
  }
});

That's it! Now you know how to use the onscreenready and ondomready events to dynamically insert or modify your bbUI screen's. Any questions or suggestions just make a post and I'll reply as soon as possible. Also don't forget to click the Like button to support my work on this piece. :smileyhappy:

 

 

If I helped you please click the "Like" button to support my work.
My apps: CherryNotes - Bookmarked - Requests
Social Me: about.me - Twitter
Retired
astanley
Posts: 1,382
Registered: ‎07-02-2009
My Device: BlackBerry Bold 9900
My Carrier: Bell

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Very nice tutorial.

 

Thanks for sharing this!

Follow me on Twitter: @n_adam_stanley
-------------------------------------------------------------------------------------------------------------------------
Your app doesn't work? Use BlackBerry remote web inspector to find out why.
Retired
epelegrillopart
Posts: 99
Registered: ‎10-03-2009
My Device: Not Specified

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Nice.  I added a link to your post to the bbUI.js page at the community Wiki: http://blackberry.github.com/Community/bbUIjs.html

 

We are just getting started with the Wiki.  Goal is to help consolidate the relevant content, so if you see other info worth linking, let us know... or, even better, add it -- it's a wiki!

 

  - eduard/o

Developer
nathanpc
Posts: 134
Registered: ‎05-19-2012
My Device: Torch 9800, PlayBook 64GB, Dev Alpha

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Thanks very much for the support. I'll be writing more tutorials like this one and also sharing awesome content that I find too. :smileyhappy:
If I helped you please click the "Like" button to support my work.
My apps: CherryNotes - Bookmarked - Requests
Social Me: about.me - Twitter
Retired
epelegrillopart
Posts: 99
Registered: ‎10-03-2009
My Device: Not Specified

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Sure thing!

 

Note the wiki also has pages for different cities/geographies. The intention would be to provide links to local activites, User Groups, events, etc.  I did a quick pass and added all the cities in the BBJam Tour, including one for Sao Paolo.

 

Staged wiki at: 

http://blackberry-community.github.com/Community/Sao_Paulo.html

 

I'll push from staged to released Wiki later today.

 

It would be great if developers could add content to these pages.  And,if you see a missing page, either add it to your fork, or submit a request and I'll create the page for you.

Contributor
fotodng
Posts: 21
Registered: ‎05-04-2012
My Device: Dev Alpha B & C, Z10 and PlayBook

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Thanks for that fantastic tutorial!!! I bookmark it.

Regular Contributor
superfly_fr
Posts: 55
Registered: ‎12-23-2011
My Device: 9900 / PB 2.0641

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

[ Edited ]

EDIT : Please see Tim Neil's answer below. It is not a proper way to do.

 

Since it looks like a kitchen mixture (I mean self experimental with no real background about DOM), I'd like to have some returns about my last try.

 

Context :

A sensitive area (image) that react to touch events and fill a div accordingly (of course this is for testing, not the real goal).

WebWorks SDK : 1.0.1.6 - bbUI : 0.9.3 -  OS : BB10 - Device: Alpha - Simulator : Ripple BB10 (Chrome ext.)

 

Basic idea :

As described, it was not possible to script an innerHTML property of the div using the document as the source.

Thanks to Tim Neil (sorry for Twitter flooding), and nathanpc tutorial, I've been lead to the ondomready event perspective.

I'm more familiar with variable scoping (eh, web dev ... lol) so that I thought "well, the problem is the source 'identifier'; let's try to 'scope' this".

 

As a result here are the 3 files I set to make a try ... that actually works.
 

index.htm (nothing interesting before the "ondomready" line, so ... abstract first and full bellow)

abstract :

ondomready : function(element, id) {
if (id == 'dataOnTheFly') { dataOnTheFly_initialLoad(element); }else if (id== 'home') { // my screen ID domElement = element; // assign the element value to my "scoping" variable } }

 full

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="initial-scale=1.0,width=device-width,user-scalable=no,target-densitydpi=device-dpi" />
        <title>LLRL</title>
        <script src="JS/webworks-1.0.1.6.js"></script>
        <script src="JS/bbui-0.9.3.js"></script>
        <link  rel="stylesheet" type="text/css" href="css/bbui-0.9.3.css" />
        <link  rel="stylesheet" type="text/css" href="css/llrl.css" />
        <script type="text/javascript">
           var domElement; // HERE is my "scoping" variable

			// BBui.js init
			bb.init({
				bb10HighlightColor : '#ffcc22',
				bb10ActionBarDark : true,
				bb10ControlsDark : true,
				bb10ListsDark : true,
				bb10ForPlayBook : true,
				// Fires "before" styling is applied and "before" the screen is inserted in the DOM
				onscreenready : function(element, id) {
					if (id == 'dataOnLoad') {
						dataOnLoad_initialLoad(element);
					} else if (id == 'masterDetail') {
						masterDetail_initialLoad(element);
					} 

					// Remove all titles "except" input and pill buttons screen if running on BB10
					if (bb.device.isBB10 && (id != 'input') && (id != 'pillButtons')) {
						var titles = element.querySelectorAll('[data-bb-type=title]');
						if (titles.length > 0) {
							titles[0].parentNode.removeChild(titles[0]);
						}
					}

				},
				// Fires "after" styling is applied and "after" the screen is inserted in the DOM
				ondomready : function(element, id) {
					if (id == 'dataOnTheFly') {					
                                            dataOnTheFly_initialLoad(element);
					} else if (id== 'home') { // my screen ID
                                            domElement = element; // assign the element value to my "scoping" variable
                                        }
				}
			});
  
        </script>
    </head>
    <body onload="bb.pushScreen('home.htm', 'home');">

    </body>
</html>

 The llrl.js external script I will use in my "home" screen

 

var msg = ''; // displayed variable

// touch states : 1 = start / 0 = end or leave lSensor = function(state) {
if (state == 1) { msg = 'Left pressed'; } else { msg = 'Left released'; } domElement.getElementById('topFiller').innerHTML = msg; // wooot ! domElement ! };

 And finally my home.htm HTML fragment (screen)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">
<div data-bb-type="screen" data-bb-effect="none">
 

<div id="topFiller" style="color:red;"></div>
    <div id="lThumb">
        <img id="lPrint" src="images/pouceG.png" width="175" height="265" ontouchstart="lSensor(1)" ontouchend="lSensor(0)" ontouchleave="lSensor(0)" />
    </div>

    <div id="bottomFiller"></div>

<!-- my external script is loaded after the DIV is defined. Yet not sure it's mandatory --> <script id="jsHome" src="JS/llrl.js"></script> </div><!-- screen -->

 

Must say I'm pretty sure I could have done this easier and moreover cleaner ... :smileyembarrassed:
Don't shoot ! :smileyhappy:

Retired
tneil
Posts: 3,708
Registered: ‎10-16-2008
My Device: Z10
My Carrier: Rogers

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

I can see what your issue was before.... 

 

You have in-line javascript as part of your llrl.js.  The problem with this is that it will run as soon as it is inserted.  bbUI will find any script tags and insert them into the live page.  So it is a race condition of the dom being updated with your new content and when your code in llrl.js is running.

 

What is recommended is that you place the contents of your llrl.js file into a function.  Then call that function from the ondomready event.  This is the intent of the ondomready event... fires once your page is ready for manipulation inside the DOM.

 

The ondomready event fires once everything is placed in the page.  It even waits for any of the CSS animation from the screen transition effects to finish before it is fired.  This is so that any DOM manipulation in the ondomready doesn't stall/lag the animations.

 

You can also use the onscreenready event to manipulate your screen before the content is inserted into the DOM.  However, you cannot use document.getElementById() in the onscreenready. This is because the screen is not yet inserted into the DOM, thus cannot be found by the document.

 

In the onscreenready, you can find and manipulate elements by their id by using getElementById() function added to the element passed into the onscreenready event.

 

onscreenready : function(element, id) {

  // Get an element by it's id
  var fooElement = element.getElementById('foo');

}

 

Tim Neil
Director, Application Platform & Tools Product Management
Follow me on Twitter
Regular Contributor
superfly_fr
Posts: 55
Registered: ‎12-23-2011
My Device: 9900 / PB 2.0641

Re: Tutorial: Using bbUI's onscreenready and ondomready to Dynamically Change Your HTML

Thanks again for making this clear, Tim.
I believe my holidays will be filled with some DOM reference ...