I'm am pretty new to DOJO 1.8 and would like to know how I can call a function from outside a require-method? I try to implement a message-box which fades in and out.
I created the method:
require(["dojo/dom", "dojo/on", "dojo/domReady!" ], function(dom, on, ready) {
/*function which shows a msg-box on top of the page */
var showMsg = function(text) {
dom.byId("msgbox").innerHTML = text;
}
});
OK! IT works....but I no I would like to call it from somewhere else in my application:
showMsg("Item saved");
But that doesn't work: Uncaught ReferenceError: showMsg is not defined
How do I get that reference?
Thank you for your help!
AFX
As things stand you're declaring a local variable and so it's not visible elsewhere in the program.
You could make the variable global, for example
window.showMsg = function(text) {
dom.byId("msgbox").innerHTML = text;
}
The downside of this approach is that as you application gets bigger you end up with more and more global variables and that makes maintenance harder.
So Dojo offers ways to package chunks of reusable code and refer to them. You are already exploiting some of those capabilities when you use "require" - you're getting access to chunks of dojo. You can make your own code visible as reusable chunks in the same way.
This is quite a big topic, but you could start by reading this
Another thing you can do is to move the require inside the function.
Even if you have many such functions, while it's annoying to repeat, there is essentially no runtime penalty for requiring over and over. The only thing to watch for is that code inside the function becomes asynchronous, so instead of returning a value you have to use a callback or promise.
Alternatively, if you're only using this function from within some event handlers (I see dojo/on), you can set them up within the scope of this same require block.
Related
I'm developing a canvas game that happens to have several scenes. Each scene might end up being a static final frame after having finished. The circumstances are that the ticker and the listener for the "tick" event are still running and keep on rendering full speed - which is asking for cpu usage.
I have tried to remove the listeners at the end of scene and add them back wenn the user interacts and starts the next scene.
I wonder what would be the "createJS" way of doing this.
I see some other options but am a bit lost how to proceed:
Caching the "whole" last frame. Will it make the ticker do "absolutely nothing" performance-wise?
Pause the ticker and check for the paused attribute in the handleTick method: Seems to not take the CPU usage completely down.
Can somebody recommend a way?
On a side note: I need my real "this" object inside the tick function that is bound to the ticker. How can I achieve this? Right now I use this code:
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
// Actions carried out each tick (aka frame)
if (!event.paused) {
// Actions carried out when the Ticker is not paused.
}
}
Inside handleTick "this" is not my object that added the listener.
A simple createjs.Ticker.removeEventListener("tick", handleTick); should do just fine as long as handleTick exists in your current scope. See this example.
There are a couple ways to access the scope of the object that assigned the tick listener. For example, you could simply assign this to a local variable like so:
var _this = this;
function handleTick(){
//"_this" now refers to the scope that defined handleTick.
}
Or you can use a delegate. In this example I'm using jQuery's proxy function to scope handleTick to this.
var handleTick = $.proxy(function(){
//"this" refers to the scope that defined handleTick.
}, this);
createjs.Ticker.addEventListener("tick", tickHandler);
I'm facing an issue (or probably two) that is frustrating the swearwords out of me; keep in mind, I'm a fairly beginner coder, so there's a good chance I'm missing something obvious.
One: I've got a page that has a sidebar that is hidden via a class containing margin-left: -90%. When the class is removed, the bar slides in to fill the whole screen. I can handle this really easily with jQuery, but I'd rather stick as much as possible in Angular - to this end, I've given it the following code:
<div id="detail_box" ng-class="{d_hide: dVis}">
<div tw-detail></div>
</div>
Which, as you can see, has a class that refers to a variable in a controller, and a link that has an ng-click connected to a function. The controller in question is stupidly simple, and relies on $rootScope variables. I'm only using rootScope because in total, over my whole page, I have two variables that will need to change dynamically, but be the same, for every controller and directive I've made. The connecting scope and controller are here:
app.run(function($rootScope) {
$rootScope.currentUrl = 'visual/design/1/';
$rootScope.detail_hide = true;
});
app.controller('navController', ['$scope', '$rootScope',
function ($scope, $rootScope) {
$scope.dVis = $rootScope.detail_hide;
$scope.hide = function(){
$rootScope.detail_hide = false;
}
}]);
Now, I've used console.log from my ng-click to see that it is picking up clicks, and I've used console.log to make sure that the detail_hide part of rootScope is changing. If I change true to false by hand in my app.js, the detail page hides itself just fine... but that ng-click doesn't actually do what I'm trying when I test it on the page. It's painful and I can't understand why changing the variable via a function (which I know changes the actual variable in rootScope, thanks to extensive testing) isn't telling my detail box to just go away.
Secondly, and it's connected to the first; dynamically changing the currentUrl in rootScope similarly doesn't change the actual AJAX content I've got stuck inside my twDetail directive, even though, again, the ng-click functions I've written do change the variable. Changing it manually works fine (although images in the second URL aren't loading but that's probably an entirely different problem) but just... what the heck am I doing wrong here?
The following code is only being run once, when the controller is being setup
$scope.dVis = $rootScope.detail_hide
Make sure you change the $scope.dVis in the hide function, like this
$scope.hide = function(){
$rootScope.detail_hide = false;
$scope.dVis = $rootScope.detail_hide;
}
I need more info on the twDetail directive to be able to solve that problem
I'm creating a GUI, but only if things go ok, so can i
addEventListener(Event.Complete, go) to something and in the go function create my GUI (grafical elements such as labels, lists, squares)?
Is it ok to do that?
Technically it's fine. crooksy88 gives a good example of supplying a default value for the event parameter to make the function more versatile.
However, for the sake of semantics, clarity, and maintenance I would usually prefer to separate things more. So mine might be set up more like this:
protected function onLoadComplete(e:Event):void {
initAppSettings();
createUI();
startApp();
}
It makes it much easier to understand the flow of the app and what each part does just by reading the function names. When I come back to this later, I'll know that my UI is created in the function named createUI and not have to figure out that it gets created in an event handler with a cryptic name like go or handleEvent.
Also, if I want to change the flow of my app, say to pop up a dialog once the load is complete before the UI is created, I just have to move around some function calls, instead of moving around large chunks of code.
Yes that is perfectly fine. The go function isn't part of the event listener.
function go(e:Event):void {
// do something
}
The sample above requires the event parameter from the listener (e:Event).
But you can modify the function so that the parameter is optional so you can call the go function any time you want
function go(e:Event = null):void {
// do something
}
The example above will be triggered by the listener and also by typing
go();
Is it possible to extend the addEvent function in mootools to do something and also calls the normal addEvent method? Or if someone has a better way to do what I need I'm all years.
I have different 'click' handlers depending on which page I'm on the site. Also, there might be more than one on each page. I want to have every click on the page execute a piece of code, besides doing whatever that click listener will do. Adding that two lines on each of the handlers, would be a PITA to say the least, so I thought about overriding the addEvent that every time I add a 'click' listener it will create a new function executing the code and then calling the function.
Any idea how I could do it?
Whereas this is not impossible, it's a questionable practice--changing mootools internal apis. Unless you are well versed with mootools and follow dev direction on github and know your change won't break future compatibility, I would recommend against it.
The way I see it, you have two routes:
make a new Element method via implement that does your logic. eg: Element.addMyEvent that does your thing, then calls the normal element.addEvent after. this is preferable and has no real adverse effects (see above)
change the prototype directly. means you don't get to refactor any code and it will just work. this can mean others that get to work with your code will have difficulties following it as well as difficulties tracing/troubleshooting- think, somebody who knows mootools and the standard addEvent behaviour won't even think to check the prototypes if they get problems.
mootools 2.0 coming will likely INVALIDATE method 2 above if mootools moves away from Element.prototype modification in favour of a wrapper (for compatibility with other frameworks). Go back to method 1 :)
I think solution 1 is better and obvious.
as for 2: http://jsfiddle.net/dimitar/aTukP/
(function() {
// setup a proxy via the Element prototype.
var oldProto = Element.prototype.addEvent;
// you really need [Element, Document, Window] but this is fine.
Element.prototype.addEvent = function(type, fn, internal){
console.log("added " + type, this); // add new logic here. 'this' == element.
oldProto.apply(this, arguments);
};
})();
document.id("foo").addEvent("click", function(e) {
e.stop();
console.log("clicked");
console.log(e);
});
it is that simple. keep in mind Element.events also should go to document and window. also, this won't change the Events class mixin, for that you need to refactor Events.addEvent instead.
Explanation:
i have few objects and im declaring them inside $(document).ready(). WHY? because in thous objects i have many jquery methods $(..), obviously they can work outside too, but when i include mootool, then it stop working. i tried noConflict and some other things, nothing works, only if i change the $() to jQuery() or to $j().. and i dont want to change for my 20 files and more then 2000 lines for each file. anyway declaring my objects inside $(document).ready(). made them work just fine.
Now My Question is:
if i declare all these objects inside the $(document).ready() method, would it make my site slow? or would it make things slow from client side? thats the only concern in my mind.
I don't see how doing that would make your site slow. By declaring them within the $().ready you're simply restricting the scope of your declarations to that particular $().ready function, thus they won't be available from within the scopes of other ready functions on the same page - which should not really be a bother if your application is well-designed and you've stuck to one per page.
Oh, and your declarations certainly won't have been been parsed until the DOM is fully loaded, (as you know, $().ready only executes once the DOM has loaded), but that too should not be a problem as you're only utilizing them from within a ready function (at least I hope).
Do you really need two libraries? If it's just one or two little tidbits of functionality you are using from one of those libraries chances are you can mimic that behaviour using the one you're making the greatest use of. If you can possibly/feasibly do that it will make your life so much simpler.
Doing everything in jQuery.ready will not slow down your site.
As an alternative solution, you could replace $ with jQuery in all of your jQuery code, or you could wrap it in a function like this:
(function($) {
$('whatever').something();
})(jQuery);
This code makes a function that takes a paremeter called $, and calls that function with the jQuery object. The $ parameter will hide mootools' global $ object within the scope of the function, allowing you to write normal jQuery code inside the function.
Just declare
jQuery.noConflict before the document.ready request, then alias the jQuery method to $ within in the document.ready...
jQuery.noConflict();
jQuery(document).ready(function($){
});