The case:
I use dojo to request a page and load it into a div ( view ).
The problem:
The content that gets loaded into a form contains a dojo form and relevant objects, textbox, etc... how can I controller these widgets? I believe the current way I am working around the issue is sloppy and could be more refined.
Comments are in the code to help explain the issue I have. Please let me know your thoughts.
function (parser, domAttr, util, ready, dom, on, request, domStyle, registry, TextBox) {
//This prepares the doc main html page We are looking for a click of a menu option to load in thats pages pages content
ready(function () {
//Look for click of menu option
on(dom.byId('steps'), "a:click", function(e) {
event.preventDefault();
//Get the div we are going to load the page into
var view = domAttr.get(this, "data-view");
// function that loads the page contents
load_page(view);
});
});
function load_page(view) {
//First I see if this page already has widgets and destroy them
//We do this so users can toggle between menu items
// If we do not we get id already registered
var widgets = dojo.query("[widgetId]", dom.byId('apply-view')).map(dijit.byNode);
dojo.forEach(widgets, function(w){
w.destroyRecursive();
});
//get the html page we are going to user for the menu item
request.post("/apply_steps/"+view, {
data: {
id: 2
}
}).then(
function(response){
//Add the content and parse the page
var parentNode = dom.byId('apply-view');
parentNode.innerHTML = response;
parser.parse(parentNode);
//This is where it is sloppy
//What I would prefer is to load a new js file the controlls the content that was just loaded
//What happens now is I create a traffic director to tell the code what main function to use
controller_director(view);
},
function(error){
util.myAlert(0, 'Page not found', 'system-alert');
});
}
function controller_director(view) {
//based on the view switch the function
switch(view) {
case 'screening_questions':
screening_questions();
break;
}
}
function screening_questions() {
//Now we are controlling the page and its widgets
// How would I get this info into a seperate js file that i would load along with the ajax call??
ready(function () {
on(dom.byId('loginForm'), "submit", function(e) {
event.preventDefault();
var formLogin = registry.byId('loginForm');
authenticate();
});
});
this.authenticate = function() {
var formLogin = registry.byId('loginForm');
if (formLogin.validate()) return;
}
}
});
Related
I am using ajaxComplete to run some functions after dynamic content is loaded to the DOM. I have two separate functions inside ajaxComplete which uses getJSON.
Running any of the functions once works fine
Running any of them a second time causes a loop cause they are using getJSON.
How do I get around this?
I'm attaching a small part of the code. If the user has voted, clicking the comments button will cause the comments box to open and close immediately.
$(document).ajaxComplete(function() {
// Lets user votes on a match
$('.btn-vote').click(function() {
......
$.getJSON(path + 'includes/ajax/update_votes.php', { id: gameID, vote: btnID }, function(data) {
......
});
});
// Connects a match with a disqus thread
$('.btn-comment').click(function() {
var parent = $(this).parents('.main-table-drop'), comments = parent.next(".main-table-comment");
if (comments.is(':hidden')) {
comments.fadeIn();
} else {
comments.fadeOut();
}
});
});
Solved the problem by checking the DOM loading ajax request URL
$(document).ajaxComplete(event,xhr,settings) {
var url = settings.url, checkAjax = 'list_matches';
if (url.indexOf(checkAjax) >= 0) { ... }
}
Ok, so I need some insight into working with History.js and jQuery.
I have it set up and working (just not quite as you'd expect).
What I have is as follows:
$(function() {
var History = window.History;
if ( !History.enabled ) {
return false;
}
// Capture all the links to push their url to the history stack and trigger the StateChange Event
$('.ajax-link').click(function(e) {
e.preventDefault();
var url = this.href; //Tells us which page to load
var id = $(this).data('passid'); //Pass ID -- the ID in which to save in our state object
e.preventDefault();
console.log('url: '+url+' id:'+id);
History.pushState({ 'passid' : id }, $(this).text(), url);
});
History.Adapter.bind(window, 'statechange', function() {
console.log('state changed');
var State = History.getState(),
id = State.data.editid; //the ID passed, if available
$.get(State.url,
{ id: State.data.passid },
function(response) {
$('#subContent').fadeOut(200, function(){
var newContent = $(response).find('#subContent').html();
$('#subContent').html(newContent);
var scripts = $('script');
scripts.each(function(i) {
jQuery.globalEval($(this).text());
});
$('#subContent').fadeIn(200);
});
});
});
}); //end dom ready
It works as you'd expect as far as changing the url, passing the ID, changing the content. My question is this:
If I press back/forward on my browser a couple times the subContent section will basically fadeIn/fadeOut multiple times.
Any insight is appreciated. Thanks
===================================================
Edit: The problem was in my calling all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.
The problem was in my calling of all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.
I have a dijit tree that when a node is clicked it loads an html page in the center content page. One of the html pages is a login page and I'd like to check a cookie to see if they have already logged on, so I can set the page appropriately if the page gets re-loaded. Is there a way to check for a cookie on page load, or perhaps a better method than this? Thanks
my code for the tree is:
TOCSet: function (TOCStore) {
var myModel = new ObjectStoreModel({
store: TOCStore,
query: { root: true }
});
// Create the Tree.
var tree = new Tree({
model: myModel,
onClick: function (item, node, evt) {
// Get the URL from the item, and navigate to it
evt.preventDefault();
var href = item.url;
registry.byId('Content').set('href', href); //set the page on node clicks
}
});
tree.placeAt("TOC");
tree.startup();
ready(function () {
registry.byId("Content").set("href", "Login.htm");//set the login page at start
});
}
I set the cookie using "dojo/cookie" after successful login
function SetLoginCookie(lia) {
cookie("LoggedInAs", lia);
}
and then used "dojo/ready" to check for the cookie when the page reloads
ready(function () {
var lia = cookie("LoggedInAs");
alert(lia + " is logged in");
});
I have list of item IDs on page load:
var itemIds = [1, 5, 10, 11];
IDs are rendered into list and shown to user. I have function which loads detailed information about item, it returns Promise/A.
function loadInfo(id) { ... }
Loading of info for all items is initiated on page load:
val infos = {};
$.each(itemIds, function(i, id) { infos[id] = loadInfo(id); }
Now the problem itself.
When user clicks on item ID:
if item info is loaded, info must be shown
if item info is not yet loaded, it must be shown when it is loaded
Looks easy:
$('li').click(function() {
var id = $(this).data('item-id');
infos[id].then(function(info) { $('#info').text(info); });
});
But if user cliked on another item before current one is loaded, then I have to cancel handler on current item promise and schedule on new one.
How to properly do it?
I have several working solutions (like maintaining currentItemId variable and checking it in promise handler), but they are ugly. Should I look to reactive programming libraries instead?
Kriomant,
I guess there's a number of ways you could code this. Here's one :
var INFOS = (function(){
var infoCache = {},
promises = {},
fetching = null;
var load = function(id) {
if(!promises[id]) {
promises[id] = $ajax({
//ajax options here
}).done(function(info){
infoCache[id] = info;
delete promises[id];
});
}
return promises[id];
}
var display = function(id, $container) {
if(fetching) {
//cancel display (but not loading) of anything latent.
fetching.reject();
}
if(infoCache[id]) {
//info is already cached, so simply display it.
$container.text(infoCache[id]);
}
else {
fetching = $.Deferred().done(function() {
$container.text(infoCache[id]);
});
load(id).done(fetching.resolve);
}
}
return {
load: load,
display: display
};
})();
As you will see, all the complexity is bundled in the namespace INFOS, which exposes two methods; load and display.
Here's how to call the methods :
$(function() {
itemIds = ["p7", "p8", "p9"];
//preload
$.each(itemIds, function(i, id) { INFOS.load(id); });
//load into cache on first click, then display from cache.
$('li').on('click', function() {
var id = $(this).data('item-id');
INFOS.display(id, $('#info'));
});
});
DEMO (with simulated ajax)
The tricks here are :
to cache the infos, indexed by id
to cache active jqXHR promises, indexed by id
to display info from cache if previously loaded ...
... otherwise, each time info is requested, create a Deferred associated with display of the info, that can be resolved/rejected independently of the corresponding jqXHR.
There are menu button ("clients"), tree panel with clients list (sorted by name) and viewer with selected client details. There is also selectionchange action..
My task - on button click switch to client view and select and load details for first client every time button has been clicked. My problem - store is not loaded, how waiting until ext js will autoload data to the store?
my controller code:
me.control({
'#nav-client': {
click: me.onNavClientClick
},
...
'clientlist': {
// load: me.selectClient,
selectionchange: me.showClient
}
});
onNavClientClick: function(view, records) {
var me = this,
content = Ext.getCmp("app-content");
content.removeAll();
content.insert(0, [{xtype: 'clientcomplex'}]);
var first = me.getClientsStore().first();
if (first) {
Ext.getCmp("clientList").getSelectionModel().select(me.getClientsListStore().getNodeById(first.get('clientId')));
}
},
...
Two main questions:
is it good solution in my case? (to select first client in tree panel)
var first = me.getClientsStore().first();
// i use another store to get first record because of i dont know how to get first record (on root level) in TreeStore
...
Ext.getCmp("clientList").getSelectionModel().select(me.getClientsListStore().getNodeById(first.get('clientId')));
i know this code works ok in case of "load: me.selectClient," (but only once),
if i place this code on button click - i see error
Uncaught TypeError: Cannot read property 'id' of undefined
because of me.getClientsListStore() is not loaded.. so how to check loading status of this store and wait some until this store will be completely autoloaded?..
Thank you!
You can listen the store 'load' event. Like this:
...
onNavClientClick: function(view, records) {
var me = this;
// if the store isn't loaded, call load method and defer the 'client view' creation
if (me.getClientsStore.getCount() <= 0) {
me.getClientsStore.on('load', me.onClientsStoreLoad, me, { single : true});
me.getClientsStore.load();
}
else {
me.onClientsStoreLoad();
}
},
onClientsStoreLoad : function () {
var me = this,
content = Ext.getCmp("app-content");
content.removeAll();
content.insert(0, [{xtype: 'clientcomplex'}]);
var first = me.getClientsStore().first();
if (first) {
Ext.getCmp("clientList").getSelectionModel().select(me.getClientsListStore().getNodeById(first.get('clientId')));
}
},
...