Dojo contentpane/tab parsing issue - parsing

I am having issues parsing HTML markup into Dojo widgets. Here is what I am doing:
var tab = new dijit.layout.ContentPane({
title: "xyz",
parseOnLoad: false, //I am doing this intentionally
href: "some-relative-url"
});
tabPane.addChild(tab);
now, if I test this with parseOnLoad = true, I get my widgets loaded nicely. However, I am trying to process the HTML before it is turned into widgets. So I delayed the parsing by adding the parseOnLoad: false option. I binded a function to be called when my tab is loaded (i.e. the Ajax call is complete), like such:
dojo.connect (tab, "onDownloadEnd", myFunction);
function myFunction() {
//manipulate the HTML code via this.content
dojo.parser.parse(this); //this doesn't do anything. I tried many variations!
}
So what happens when I do that is that I end up with the tab loaded but no widgets, just standard HTML controls. So why isn't the parser being triggered in this scenario and what can I do to make it work on my manipulated HTML?
Thanks

this in that context is probably the window object, since you're not specifically setting the scope in your connect (from the code you posted I assume myFunction() is a free function, not a method.
You need to pass dojo.parser.parse a DOM node. Assuming tab is a widget, you can use dojo.parser.parse(tab.domNode) if the function is defined in the context of availability of tab. If this is scoped to the tab widget, then you can use dojo.parser.parse(this.domNode) as you say in your comment.
You can force the scope with the almighty powerful dojo.hitch :) Read the documentation here and I recommend the How this works section from the Javascript garden.

Related

jQuery Mobile navigate or changePage?

With the arrival of jQuery Mobile 1.3, the .navigate() function has been added. I've heard that is the recommended way to change pages, and it seems they addressed the issues of transferring data between pages.
The problem is, since it has been simplified, how do I access the other options that changePage offered? I would really like to use the {data} portion of the .navigate() but I would also like to set a few options that I do normally with changePage (such as transition, direction, etc).
I currently have a "router" that listens for all navigate events, then passes along any data that it receives on to the next page (doing some other simple logic as well, like setting up the views controller).
Is there some hidden properties in the [,options] that I would be able to set up simple things like direction and transition?
$.mobile.navigate is still a new function, according to code comments it is also a work in progress.
Transition is active among hidden options;
$.mobile.navigate( "#bar", { transition : "slide", info: "info about the #bar hash" });
Working example: http://jsfiddle.net/Gajotres/g5vAN/
On the other hand, change to direction reverse is still not implemented, default false value is applied.
The other way would be to use:
$.mobile.pageContainer.pagecontainer("change", "target",
{transition: "flow", changeHash: false, reload: true})
Link
Use the Pagecontainer widget added in v1.4.
$(":mobile-pagecontainer").pagecontainer("change", "jquerypageIdentifier",{ options in key value format } );
e.g
$(":mobile-pagecontainer").pagecontainer("change", "#nextpage",{ transition: "slide",role: "dialog" } );

Custom changePage on jquery mobile causes c.data("page") is undefined on second call

I'm trying to build some custom navigation in a dynamic application, all screens are obtained from the server and thus I registered the pagebeforechange event and execute my own function.
Everything works as I expected except when I refresh the data I destroy the dynamic pages and try to call the page I was in again using the page Id, but this second time, although my code creates the HTML for the page, jQuery Mobile throws an "c.data("page") is undefined" error.
I bind the pagebeforechange event:
$(document).bind('pagebeforechange', function(e, data) {
if(typeof data.toPage === 'string') {
appobj.dynamicPage(data.toPage, data.options);
}
});
Then in the dynamicPage method I create the HTML for my page based on Underscore.js templates and let jQuery continue changing the page:
$.get('templates/page.tpl.html', function (data) {
html = _.template(data, { /* several template parameters */});
});
page = $(html);
page.appendTo('body').page();
The idea was to use as much of jQM as possible since I'm creating the destination page and injecting it into the DOM.
When I need to update the supporting data, that I store in localStorage, I just find all dynamic pages and destroy them:
var current = $.mobile.activePage.attr('id');
$('.dynamicpage').remove();
$.mobile.changePage('#' + current
When running the application I can easily navigate between various screens/pages, even for pages that don't exist when the application starts but if the data needs to be updated (because the user added elements in the application of data in the database changed) then the removal code is executed but the old page is not regenerated ending in a white page with all the DOM contents hidden, but the page I wanted to navigate too seems to be in the DOM (at least firebug tells me so).
If I were to restart development I would probably use Backbone.js to handle my model updates and view changes but for now I'll have to use only jQM. Any suggestions? I understand that jQM is not finding my page but I don't see why since my event should be called and the page regenerated, even with the allowSamePageTransition flag set.
Regards,
Sérgio Lopes

How to bind backbone.js events to JQuery UI dialogue windows?

I'm very new to backbone.js but we're starting to use more and more JS on the front end and I wanted to use some framework to give the code structure - backbone seems to suit our needs.
So started off with a very simple test app that launches a dialogue window using jquery-ui. The problem I have is that since jquery-ui adds a wrapper DIV round the original template used by backbone, the events no longer fire.
I don't want to use the jquery-ui event model as I'd rather just use the one - how can I bind backbone's to this new structure?
It looks as though the call to _.template() is actually doing the wrapping in an extra div. The parent div with the events bound to it is being left behind appended to #well. A simple workaround is to call .parent() on the result of getting the element with the model class ID. See here for example
There's more than likely some information in the _ documentation that might shed some more light on the problem too.
OK - at the end of this project, I finally realised that I hadn't answered this. What happens is when you create a .dialog with JQueryUI, it actually detatches your original DOM element and moves it to the bottom of the DOM wrapped in it's own JQueryUI markup to turn it into a dialog.
Since the Backbone view's element has now been moved, Backbone doesn't pick up any events that fire as it's happening outside it's own "view" as far as it is concerned.
So what you have to do is reassign the view's element:
var dlg = this.$("#dialogue-properties").dialog({ ..});
this.setElement(dlg);
Where this is the view. This is done within the initialize method
You can create div wrapper in your view and modal it's content, as described here (first part of the post)
cocovan does a good job explaining the problem in his answer. However, as for the solution, the JQuery UI team actually added a method at the end of 2012 (Allow dialog to be attached to a element other than body) that takes care of this issue.
It is the appendTo(selector) method (jQuery Dialog appendTo method). So simply specify to which element you want the dialog appended.

is it ok to pass variable through the url in phonegap?

When creating a jquery mobile / phonegap app, is it ok to pass variables through the url from one page to another
page.html?var1=foo&var2=bar
or is does it create a problem when compiling the code?
It should be just fine to pass variables to external pages. Just know that URL variables will only be passed to external pages. Meaning that if you already have an external page in the DOM, you will have to re-load the page to pass it variables again.
I believe that older versions of jQuery Mobile hamper this behavior but you should be good to go with anything 1.0 or later.
Also read the bottom of this page, "Known Limitations": http://jquerymobile.com/demos/1.1.0-rc.1/docs/pages/page-navmodel.html (specifically the second from the bottom bullet)
Update
To reload a page with jQuery Mobile you can use the $.mobile.changePage() function and set the reloadPage option to true:
$(document).delegate('#my-link-id', 'click', function () {
$.mobile.changePage({ reloadPage : true });
return false;
});
Docs: http://jquerymobile.com/demos/1.1.0-rc.1/docs/api/methods.html
it "works", however it's not the best way.
Apps should be all one page with dynamically retrieved and displayed content.

jQuery Mobile Page refresh mechanism

I'm having a lot of pain understanding how jQuery Mobile handles pages refresh after an ajax update.
I'm having a two pages - unique file site: a search engine.
First page is a search field. Submit triggers a JSON call and parser which updates the second page: results.
for now i'm using: $.mobile.changePage( $('#result') ); which does the job great from search field to result page.
However:
If I reuse it from result page for next/prev pages ( new json call, new parse, new added nodes in the DOM );
Jquery Mobile just don't "paint" the newly added nodes.
can anyone explain, please the use and distinction of
1- $.mobile.page()
2- $.mobile.changePage()
3- $.mobile.refresh()
or give me a hint on how I should handle page changes.
thanks!
function refreshPage()
{
jQuery.mobile.changePage(window.location.href, {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true
});
}
Taken from here http://scottwb.com/blog/2012/06/29/reload-the-same-page-without-blinking-on-jquery-mobile/ also tested on jQuery Mobile 1.2.0
Please take a good look here: http://jquerymobile.com/test/docs/api/methods.html
$.mobile.changePage() is to change from one page to another, and the parameter can be a url or a page object. ( only #result will also work )
$.mobile.page() isn't recommended anymore, please use .trigger( "create"), see also: JQuery Mobile .page() function causes infinite loop?
Important:
Create vs. refresh: An important distinction
Note that there is an important difference between the create event and refresh method that some widgets have. The create event is suited for enhancing raw markup that contains one or more widgets. The refresh method that some widgets have should be used on existing (already enhanced) widgets that have been manipulated programmatically and need the UI be updated to match.
For example, if you had a page where you dynamically appended a new unordered list with data-role=listview attribute after page creation, triggering create on a parent element of that list would transform it into a listview styled widget. If more list items were then programmatically added, calling the listview’s refresh method would update just those new list items to the enhanced state and leave the existing list items untouched.
$.mobile.refresh() doesn't exist i guess
So what are you using for your results? A listview? Then you can update it by doing:
$('ul').listview('refresh');
Example:
http://operationmobile.com/dont-forget-to-call-refresh-when-adding-items-to-your-jquery-mobile-list/
Otherwise you can do:
$('#result').live("pageinit", function(){ // or pageshow
// your dom manipulations here
});
I posted that in jQuery forums (I hope it can help):
Diving into the jQM code i've found this solution. I hope it can help other people:
To refresh a dynamically modified page:
function refreshPage(page){
// Page refresh
page.trigger('pagecreate');
page.listview('refresh');
}
It works even if you create new headers, navbars or footers. I've tested it with jQM 1.0.1.
I found this thread looking to create an ajax page refresh button with jQuery Mobile.
#sgissinger had the closest answer to what I was looking for, but it was outdated.
I updated for jQuery Mobile 1.4
function refreshPage() {
jQuery.mobile.pageContainer.pagecontainer('change', window.location.href, {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true
// 'reload' parameter not working yet: //github.com/jquery/jquery-mobile/issues/7406
});
}
// Run it with .on
$(document).on( "click", '#refresh', function() {
refreshPage();
});
I solved this problem by using the the data-cache="false" attribute in the page div on the pages I wanted refreshed.
<div data-role="page" data-cache="false">
/*content goes here*/
</div>
In my case it was my shopping cart. If a customer added an item to their cart and then continued shopping and then added another item to their cart the cart page would not show the new item. Unless they refreshed the page. Setting data-cache to false instructs JQM not to cache that page as far as I understand.
Hope this helps others in the future.
This answer did the trick for me http://view.jquerymobile.com/master/demos/faq/injected-content-is-not-enhanced.php.
In the context of a multi-pages template, I modify the content of a <div id="foo">...</div> in a Javascript 'pagebeforeshow' handler and trigger a refresh at the end of the script:
$(document).bind("pagebeforeshow", function(event,pdata) {
var parsedUrl = $.mobile.path.parseUrl( location.href );
switch ( parsedUrl.hash ) {
case "#p_02":
... some modifications of the content of the <div> here ...
$("#foo").trigger("create");
break;
}
});

Resources