programmatic view transition in dojo mobile - dojo

I would like to perform a programmatic view transition.
Here is a code I've tried :
var v = registry.byId('myenergy-pane');
v.transitionTo("home-pane");
Here is another one
var v = registry.byId('myenergy-pane');
v.performTransition("home-pane",1,"slide",null);
None of them is working.
Thanks for your help.

The second code you provided should work, but that's considering the following facts:
The code is executed after the DOM is loaded and the views are parsed by the dojo/parser. The correct way to indicate that is by using dojo/ready, for example:
require(["dojo/ready"], function(ready) {
var v = registry.byId('myenergy-pane');
v.performTransition("home-pane", 1, "slide", null);
});
Both given IDs (myenergy-pane and home-pane) are related to a widget (not only a DOM node) and are both views (dojox/mobile/View or inheriting from).
Make sure you are loading dijit/registry and the registry module alias is actually mapped to the correct module.
I also made a JSFiddle to demonstrate that it should be working: http://jsfiddle.net/g00glen00b/3JMnC/

Related

Dojo Dgrid - Events in Configuration

I've been looking into dgrid and I'm trying to figure out if there's a way to attach an event to a grid that uses dojo/on without explicitly calling grid.on but, instead, passes it as a method (or set of methods) in the initial configuration of the grid. The reason for this is because the grid instance itself out of scope upon creation and I can't find any documentation on it.
So, instead of
var grid = new (declare[Grid])({}, element);
grid.on('.dgrid-row:click', function(){console.log('Hello World!')});
having something like
var grid = new (declare[Grid])({
'events' : {
'.dgrid-row:click' : function(){console.log('Hello World!')}
}
}, element);
Ideas? Alternatives?
You can use the the DijitRegistry extension, which will allow you to get a reference to your grid like you would with a normal dijit widget, through registry.byId... then you can use grid.on, as usual.
Example : https://github.com/SitePen/dgrid/wiki/DijitRegistry

DojoX Mobile ListItem load HTML via AJAX and then remove from DOM

Let's say in a view I have a DojoX Mobile ListItem that is pulling an HTML view fragment into the DOM via AJAX and then transitioning to that view. Assume this is all working fine.
Now, I go back to the initial view that had that ListItem on it and click some other button that destroys that view node from the DOM. If I now click on that ListItem that previously loaded that view node into the DOM (which has now been removed), it will try to transition to a view that doesn't exist. It doesn't know that it has been removed.
Is there some type of way to tell a ListItem that it needs to fetch the HTML again because what was previously fetched no longer exists? I am not seeing anything about doing this in any documentation anywhere. I don't think a code sample is really necessary here, but I can provide a minimal one if necessary.
I went a different route and left the view exist in the DOM, and simply made a function that clears all sensitive data out of the view.
Okay, in this case, i guess you could hook the onShow function of your ListItem container(or any other onchange event). Create a listener for said handle to evaluate if your item needs reloading. Following is under the assumtion that it is the item.onclick contents showing - and not the label of your item which contains these informations
Or better yet, do all this during initialization so that your ListItem container will be an extended with custom onClick code.
Seems simple but may introduce some quirks, where/when/if you programatically change to this item, however here goes:
function checkItem() {
// figure out if DOM is present and if it should be
if( isLoggedIn() ) {
this.getChildren().forEach(function(listitem) {
if( dojo.query("#ID_TO_LOOK_FOR", listitem.domNode).length == 0 ) {
// this references the listItem, refresh contents.
// Note: this expects the listitem to be stateful, have no testing environment at time being but it should be
listitem.set("url", listitem.url);
}
});
}
}
Preferably, set this in your construct of the container for your ListItems
var listItemParent = new dojox.mobile.RoundRectList({
onShow : checkItem,
...
});
Or create listener
var listItemParent = dijit.byId('itemRegistryId');
// override onClick - calling inheritance chain once done
dojo.connect(listItemParent, "onClick", listItemParent, checkItem);

Dojo query on specific ContentPane in TabContainer

I have a TabContainer with different tabs (ContentPanes). I am loading each type dynamically when the user selects something from a tree. I would like to be able to run a certain JS function on the newly loaded ContentPane/Tab. So something in this form:
dojo.forEach(
dojo.query("select"),
function(selectTag) {
selectTag.disabled = true;
}
);
However, I only want to process this on the newly loaded ContentPane/Tab... so let's say given a ContentPane/Tab Dojo Object, how do I do a forEach/query on its content only?
Thanks
You can give dojo.query a second argument telling it in which DOM node to start looking. So if you have a ContentPane with id "fooTab", you can do:
dojo.forEach(dojo.query("select", "fooTab"),
function(selectTag) {
....
}
);
Now, technically, "fooTab" is the "dijit ID", but the dijit's/ContentPane's outermost DOM node will also have an id "fooTab". Perhaps not the kosher way, but it works.

Problems with adding/removing ContentPanes in AccordionContainer

I'm a complete newbie at Dojo, and Adobe AIR, which is my target. I'm
trying to put some panes into an AccordionContainer like so:
var mainview = dijit.byId("mainview");
var rand = randomString();
var widg = gtd_create_entry_widget(rand)
air.trace(mainview);
air.trace(widg);
mainview.addChild(widg);
"mainview" is my AccordionContainer, and gtd_create_entry_widget() is:
function gtd_create_entry_widget(id) {
var entry = new dijit.layout.ContentPane();
entry.attr("id",id);
entry.attr("title","title "+id);
return entry;
}
The pane shows up in the container, with the correct id and title, and
no errors, however, if I try to add another pane, the next one shows
up too, but I get the error:
TypeError: Result of expression '_7' [undefined] is not an object.
I get the same error if I run
var mainview = dijit.byId("mainview");
mainview.destroyDescendants();
and also, only one pane is destroyed at a time, and I understand this
method should destroy all the children.
I can include full project code if required.
Thanks a lot
Garry
I'm not exactly sure if this is going to fix your problem, but you're supposed to use dijit.layout.AccordianPane (http://www.dojotoolkit.org/api/dijit/layout/AccordionPane.html) with the AccordianContainer.

drupal multiple node forms on one page

I have a view that displays several nodes. I want to place node form below each displayed node. Both node_add and drupal_get_form directly in template.php works fine, but I get forms with same form ID of NODETYPE_node_form and validation and submitting does not work as expected.
If you had to put several node forms on one page, what would be your general approach?
Progress so far...
in template.php while preprocessing node
$author_profile and $content is set before.
$unique = $vars['node']->nid;
$node = new StdClass();
$node->uid = $vars['user']->uid;
$node->name = $vars['user']->name;
$node->type = 'review';
$node->language = '';
$node->title = t('Review of ') . $vars['node']->realname . t(' by ') . $vars['user']->realname . t(' on ') . $content->title;
$node->field_review_to_A[0]['nid'] = $nodeA->nid;
$node->field_review_to_B[0]['nid'] = $vars['node']->nid;
$node->field_review_to_profile[0]['nid'] = $author_profile->nid;
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
//$vars['A_review_form'] = drupal_get_form('review_node_form', $node);
$vars['A_review_form'] = mymodule_view($node, $unique);
in mymodule module
function mymodule_view($node, $unique) {
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
$output = drupal_get_form('review_node_form_' . $unique, $node);
return $output;
}
function mymodule_forms($form_id, $args) {
$forms = array();
if (strpos($form_id, "review_node_form_") === 0) {
$forms[$form_id] = array('callback' => 'node_form');
}
return $forms;
}
function mymodule_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) && $form_id != $form['type']['#value'] .'_node_form' && $form['type']['#value'] == 'review') {
$type = content_types($form['#node']->type);
if (!empty($type['fields'])) {
module_load_include('inc', 'content', 'includes/content.node_form');
$form = array_merge($form, content_form($form, $form_state));
}
$form['#pre_render'][] = 'content_alter_extra_weights';
$form['#content_extra_fields'] = $type['extra'];
//$form['#id'] = $form_id;
//$form['#validate'][0] = $form_id . '_validate';
$form['title']['#type'] = 'value';
$form['field_review_to_A']['#type'] = 'value';
$form['field_review_to_B']['#type'] = 'value';
$form['field_review_to_profile']['#type'] = 'value';
}
}
Questions
My take on summarizing unclear questions...
Is this good general approach for displaying multiple node forms on same page?
Is it OK to copy/paste code from content modules content_form_alter function in function mymodule_form_alter? Will it not brake things if content module is updated?
Should i set $form['#id']? Without it all forms has same HTML form ID of node_form, with it ID is unique, like review_node_form_254. Thing is that there is no difference of how form is submitted. Setting $form['#validate'][0] does not seem to influence things too. Maybe I should set $form[button]['#submit'][0] to something else? Now its node_form_submit.
Why validation does not work even with unique form id and form validate function? If i submit last form without required field all previous forms gets particular fields red. should I make my own validation function? what level - form or field? Any tips on where to start?
You need to implement hook_forms() to map different ids to the same builder function.
The NODETYPE_node_form ids you mention are already an example of this mechanism, as they are all mapped to the same builder function (node_form()) within the node modules node_forms() implementation.
You can find links to more examples in the 'Parameters' explanation off the drupal_get_form() function.
This was exceptionally useful to me.
Documentation on all the drupal APIs is so lacking - I was tearing my hair out. The crucial bit for me, that I don't think is covered anywhere else on the net:
CCK adds its fields to your form through hook_form_alter() . But it does this based on the form_id. So if the form ID is different (cause you want multiple ones on the same page), you need to replicate a bit of the CCK code to add the fields to your form regardless.
That is what this does brilliantly.
I really did not dig to the bottom of it, but it seems to me that you pretty much did all the relevant digging by yourself.
From what I understand by inspecting the code only, you are right in thinking that content_form_alter() is the show-stopper.
Maybe this is a naïve suggestion, but what about writing your own implementation of hook_form_alter() starting from the content_form_alter() code but changing the conditions that make the alteration to occur? I am thinking to something along these lines:
function modulename_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) &&
stripos($form_id, $form['type']['#value'] .'_node_form')) {
...
}
}
I did not actually test the code above, but I hope it is self-explenatory: you actually trigger the changes for a give customised type of content if MYCCKTYPE_node_form is a substring of the actual form_id (es: MYCCKTYPE_node_form_234).
Hope this helps at least a bit... Good luck! :)
EDIT: TWO MORE THINGS
It just occurred to me that since your custom implementation of hook_form_alter() will live aside the CCK one, you would like to add a check to avoid the form to be modified twice something like:
&& $form_id != $form['type']['#value'] .'_node_form'
The other way you might try to implement this by not using CCK but implementing you custom type programmatically (this might even be an advantage if you plan to use your module on various different sites).