I have a function that is outside of the require portion of the dojo functions.
This function needs to call a function that resides within the dojo require block.
How do i call a function that is within the require code block from a function that resides outside the dojo require block?
Perhaps a little more application flow will demonstrate the need
Main window application spawns a child window
Main window sends a message to the child window that has a global function that will receive the message
Child window receives the message
The external function parses the message and determines that the map
needs to be updated (The child window that is spawned is the mapping window and loads a lot of ESRI modules in the require section)
the child window function needs to call a function that is
within the require code block of dojo to do the actual ESRI related tasks
It's a hacky solution and you should really think of a way to rearrange your modules if possible, but this should at least work:
var inside = null;
function outside () {
try { inside(); }
catch (err) { /* log error or throw away, whatever */ }
}
require(['dojo/_base/declare', ..., 'your/module/function'], function (declare, ..., myModuleFunction) {
inside = myModuleFunction;
outside();
});
Just require the module which contains the function (named "your/module/function" and myModuleFunction in the example), store it in a variable outside of the require and call it in a function which has been defined outside already. I added a try-catch block because it is good measure and prevents your code from blowing up if you call outside too early.
In case the function inside the dojo require block isn't a module, it's almost the same:
var inside = null;
function outside () {
try { inside(); }
catch (err) { /* log error or throw away, whatever */ }
}
require(['dojo/_base/declare'], function (declare) {
inside = function () { console.log('Inside the require block'); };
outside();
});
Except that you don't have to require it.
Talk about a hack... here is what i did to get the results i needed.
I created a hidden button on the form, bound the click event to fire off the function.
When the message was received and processed, I fired off the button click event - and viola!!
thanks everyone for the help.
Related
I have a main page that loads a child page via ajax, then when the child page is closed a globally scoped callback function is run to do whatever action is necessary, for example to refresh the main page content in some way.
I came across a situation where the child page itself needs to define the callback function since it is the only place that knows what needs to be done when it closes.
In this instance the callback function is a closure of another function that accepts parameters, and the parameters are derived from a jquery expression using elements on the child page.
The problem is by the time the callback function is run the child page has been unloaded so when the enclosed function's parameter list is evaluated jquery cannot locate the target elements.
I was able to work around this one case by using a globally scoped temporary variable to hold the parameter but I would rather 'force' evaluation of the jquery expression while the page is still in memory.
A pseudo-code example of the setup that does not work:
main-page:
callback = null;
newcallback = some_function;
function open-child(newcallback) {
callback = newcallback;
//load child page
};
function close-child(){
//unload child page
callback();
}
child-page:
child-page-element
callback = function () {
some_action( $("#child-page-element").data("id") );
};
close-child();
by adding a global variable I can make this work:
child-page:
child-page-element
global_var = $("#child-page-element").data("id");
callback = function () {
some_action(global_var);
};
close-child();
Questions:
Can the jquery param be 'forced' to evaluate as I have it written?
Is there a better way altogether?
Well, you could make a function on the child page that creates the callback (and gathers its data) like:
main-page:
function open-child(createCallback) {
callback = createCallback();
}
child-page:
createCallback = function() {
var id = $("#child-page-element").data("id");
return function () {
some_action(id);
};
};
I am rewriting a project of mine and this time I decided to use self invoking functions to save a bit of code, but I became very uncertain if this would even work since I don't want the self invoking functions to be run before page has loaded + the init function has been run.
The expected execution order I want is this:
init: function() {
//some code gets executed here
createCalendar(2015);
}
addEventListnrs: (function() {
//event listeners gets added here on elements that gets created
//in the createCalendar function
})()
createCalendar: function(year) {
//creates elements that the addEventListnrs uses
}
window.onload = init;
Question is, is this what I'm going to get or will the addEventListnrs function invoke itself before init gets run?
Assuming your labels are valid code (i.e. you've left some code out)
The IIFE labelled addEventListnrs invokes itself as soon as the interpreter reaches it
...some time passes as the page loads... ...and it finishes loading
The load event is sent to window
init is invoked by the listener
createCalendar is invoked by init
In the rails.js that came with my rails (3.0.x, still with prototype), I see the following structure:
(function() {
// ...
document.on("click", ...
})();
What exactly is accomplished with the wrapping of the whole code in the anonymous function? Is this a valid way to delay the code until the dom has loaded or only the document object?
In my project, I currently have a lot of setup code inside a Event.observe(document, 'dom:loaded', function() { ... } block. I was wondering, if I should adopt the pattern above when I refactor my code.
You have stumbled across the module pattern. It is useful because variables inside the immediately invoked function are local and don't pollute the global namespace.
(function(){
var something = 17;
//can use something inside here
}());
//but not here anymore
Not ethat there is no difference in timeing since the function is immediately invoked (in the final () bit)
The self-invoking anonymous function will trigger what is inside immediately, which has nothing to do with delaying the code.
To make the code block inside be executed after the DOM is ready, you have to have DOMready listener. I guess the code you mentioned Event.observe(document, 'dom:loaded', function() { ... } is the one.
I want to log all errors in my browser side JavaScript code. I saw a lot of discussions here and on the net about window.onerror and it is clear it does not work cross browser. So, I plan to wrap top level entry functions with try - catch. Trouble is, a lot of my code is event handlers. I have not tested it yet, but I am pretty sure that no matter where the event handler function is defined, a thrown error will fire out directly to the browser implementation that calls it, not to event function declaring code. My only choice is to declare throw, catch and error log calls in every error handler even the tiniest anonymous one. I don't like that one bit.
A possible solution:
I use one method to cross browser register events. I can modify it to do something like this:
function registerEventHandler(object, handlerRef) {
var wrapperFunction = function(evt) {
try {
handlerRef(evt);
} catch {
logError(error);
}
registerEvent(object, wrapperFunction);
}
There is one major problem with that implementation. I often keep references to event handler function in order to deregister them later. This will not work as the function registered as the handler will be the wrapper, not the original one. The answer to this is to implement a wrapper -> wrapped mapping object and use it on unregister.
The question:
I dare you JavaScript magicians to come up with more clever solution than that. Maybe it could be done by somehow augmenting the event handler function before registration? This is a far as my JavaScript knowledge goes. What about yours?
I often keep references to event
handler function in order to
deregister them later. This will not
work as the function registered as the
handler will be the wrapper, not the
original one.
Why is this a problem? once the function is wrapped in the error handling, you dont really care about the original function anymore. The wrapper keeps a reference to your original function, and the wrapper is what is registered, and the wrapper is what needs to be unregistered.
Just keep a reference to your wrapper function you generate because its the only one that matters.
Also making it it's own function will make this pattern far more reusable
var protectErrors = function(fn) {
var that = this;
return function() {
try {
fn.apply(that, arguments);
} catch(error) {
logError(error);
}
};
};
var registerEventHandler = function(object, handlerRef) {
var wrapperFunction = protectErrors(handlerRef);
registerEvent(object, wrapperFunction);
};
protectErrors(fn) will return a function that runs the original in whatever context it was called in, and forwarding any number of arguments.
using drupal with lightbox2 to open a form. this form is from a custom module.
the module has a setting: 'onsubmit' => 'return form_submission(this);' and that appears to be working correctly.
I've included the functions.js in the theme.info file and it's showing up, i can open that file and see the function.
for some reason, i keep getting "form_submission not a function" when i do submit the form.
if(Drupal.jsEnabled)
{
$(document).ready(function() {
// Call back function for AJAX call
var form_submission = function(responseText) {
alert (responseText);
}
// preventing entire page from reloading
return false;
});
}
Your form_submission function is local to the anonymous function it's inside (ie the document ready function).
You need to declare the function in a global scope, outside of the document ready. You at least need to declare the variable form_submission. You will then be able to attach the function on to it wherever you wish.
form_submission has to be a defined function.
function form_submission(data) {
// action code
}
or also try
var form_submission = new function(data) {
// action code
}
Not that this is the perfect answer, but I removed the function from within the document.ready jquery wrapper and it picked up on it.