I have a mouse-down event listener on an object that starts a createjs.Ticker. I need to pass a reference to the object in the 'tick' function, or at least be able to access that object. This is the code block:
this.obj.on("mousedown", function(event) {
createjs.Ticker.addEventListener("tick",
this.flowControl);
});
I need to be able to get a reference to obj object from the flowControl function:
this.flowControl = function(e) {
api.onButtonPress(this.obj);
}
...the 'this' in the flowControl function is the Ticker event and I cannot find how to reference the obj object
The 3rd parameter of the on method is scope. If you don't pass one in, it uses the firing object as the scope.
Additionally, you are using both on and addEventListener. I recommend sticking with on().
this.obj.on("mousedown", function(event) {
createjs.Ticker.on("tick",
this.flowControl, this);
}, this);
Your mousedown and tick events will fire in the same scope, so you can reference this.obj from both functions.
Related
I have two Vue components that have a "save to disk" call on every change of data, it is loaded into these components via a mixin and each component save into a different file, so they must function independently (only trigger a debounce reset on its own change of data). To prevent too much writing to the disk. Here's my debound function:
function debounce(fn, delay) {
var timeoutID = null;
return function () {
console.log("clearing " + timeoutID)
clearTimeout(timeoutID);
var args = arguments;
var that = this;
timeoutID = setTimeout(() => fn.apply(that, args), delay);
};
}
Here's the methods on my mixin that the components inherit:
methods: {
saveData: debounce(function(){
console.log('saving widget: ' + this.$parent.widget.id);
this.saver.store = this.persisted;
}, 5000),
},
It works well when I'm changing data on one or the other component, but when I change data on one and before debounce ends I change on the other, it cancels my debounce function from the first one, and only saves the second component data.
What am I missing here?
I've encountered the same issue today. I've tried something else that is, in my opinion, a bit cleaner. Instead of defining the debounced function within the methods block like you did, try defining it as part of the data like so:
data() {
return {
saveData: debounce(function(){
console.log('saving widget: ' + this.$parent.widget.id);
this.saver.store = this.persisted;
}, 5000)
}
}
You can call the method the same way as you would normally. From the docs: "A component’s data option must be a function, so that each instance can maintain an independent copy of the returned data object." This way, each instance that uses the debounce function will have it's own unique instance of it.
More on how this works can be found here: https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function
That's because each component instance shares the same debounced function, only the context (this, that) is varying.
A simple workaround would be to change your debounce implementation to
function debounce(fn, delay) {
var thatUidToTimeoutID = {};
return function () {
var args = arguments;
var that = this;
clearTimeout(thatUidToTimeoutID[that._uid]);
thatUidToTimeoutID[that._uid] = setTimeout(() => fn.apply(that, args), delay);
};
}
_uid is holding an unique id of each component, it's more of an internal property (hence it's weird key) but it should be good enough.
I have checked similar question, but there is still one thing that is unclear to me:
Can I pass a parameter in emit on event hub, but I need parameter to be VALUE and not the VARIABLE which stores value. So for example: eventHub.$emit('test_emit', true) and the method which is called on test_emit should have it's parameter set on true.
From the similar question that you provided, you would just replace name with true when you are emitting event
methods: {
showModal(name) { this.bus.$emit('showModal', true); },
}
created() {
// `show` will have the value that you emitted
this.bus.$on('showModal', (show) => console.log(show);
}
Sure you can, what you cannot do is to pass more then one variable (like eventHub.$emit('test_emit', true, false) as $emit accepts only one additional parameter (that can be the value or an object containing the key: value associations, also know as payload.
I want to override dijit._CssStateMixin's domReady() method.
Is there any way to override that instead of changing the listener mechanism in Dojo.
I tried overriding _cssMouseEvent() method in simple javascript, but it still does invoke dijit's _cssMouseEvent() from domReady().
I have tried following approach:
dojoConfig = {
map: {
'dijit/_CssStateMixin': {
'dojo/domReady': 'app/noop'
}
}
};
I have added 'app' folder and then 'noop.js' inside that.
noop.js has nothing in it:
define([], function () {
return function () {};
});
Even after this I can see that dijit.js's _CssStateMaxin domReady() getting called from listener.apply (code snippet pasted below)
var addStopImmediate = function(listener){
return function(event){
if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately
event.stopImmediatePropagation = stopImmediatePropagation;
return listener.apply(this, arguments);
}
};
}
If your ultimate goal is to prevent the domReady callback in dijit/_CssStateMixin from running, your simplest bet is likely to re-map dojo/domReady to a different module that doesn't call the callback at all, when loaded via dijit/_CssStateMixin.
NOTE: Stripping out these handlers might have adverse visual effects on Dijit widgets which inherit _CssStateMixin, since it may hinder the application of Dijit CSS classes related to hover and focus. But if your concern is that _CssStateMixin is hampering performance, it may at least be worth a try to confirm or deny your suspicion.
First we have to create a simple module that returns a function that does nothing, which we will later substitute for dojo/domReady when loaded by dijit/_CssStateMixin, so that it can still call domReady but it won't execute the callback it passes.
For simplicity's sake I'll assume you already have a custom package that you can easily add a module to; for this example I'll assume it's called app. Let's create app/noop:
define([], function () {
return function () {};
});
Now let's configure the loader to map app/noop in place of dojo/domReady specifically when loaded by dijit/_CssStateMixin:
var dojoConfig = {
...,
map: {
'dijit/_CssStateMixin': {
'dojo/domReady': 'app/noop'
}
},
...
};
Now the offending domReady callback should no longer be run.
If you're curious about map, you can read more about it in this SitePen FAQ.
For some reason, my code is unable to retrieve the IAsyncOperation object that is returned upon calling captureFileAsync method of the Windows.Media.Capture.CameraCaptureUI() method. The IAsyncOperation object is returned according to this documentation. In that documentation link, it states:
Return value
Type: IAsyncOperation<StorageFile>
When this operationcompletes, a StorageFile object is returned.
So here is my code:
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 4, height: 3 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
appSession.InAsyncMode = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).done(function (file) {
if (file) {
self.addPage(URL.createObjectURL(file));
} else {
WinJS.log && WinJS.log("No photo captured.", "sample", "status");
}
}, function (err) {
// None taken
});
When I inspect the value of appSession.InAysncMode, I see that the function returns undefined. I suspect it returns undefined because the operation is not complete (i.e. the user has not yet created the photo, and it has not been saved to disc), but I need it in order to cancel out of the camera capture mode programmatically. Does anybody know why it would return undefined instead of the documented IAsyncOperation object?
Thanks!
For reference, here's the answer I posted on the MSDN forum.
To answer your ending question, you can cancel the capture UI by canceling the promise from dialog.captureFileAsync.
Your InAsyncMode flag is undefined because you're assigning to it the return value from captureFileAsync.done() which is, by definition, undefined. It has nothing to do with the API's success.
In the docs, when you see IAsyncOperation, what you get in JavaScript is a promise that will deliver as a result to the completed handler if it succeed. You never see IAsyncOperation or related interfaces in JavaScript directly. The documentation for WinRT is written to be language-neutral, so it's important to understand how those things show up in JS (as promises). In C# you don't see it either, as you just use the await keyword. It's mostly in C++ that you actually encounter the interface.
Anyway, you I believe you want is something along the lines of the code below, where you could eliminate IsAsyncMode in favor of just checking for a non-null promise:
appSession.capturePromise = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo);
appSession.IsAsyncMode = (appSession.capturePromise != null);
//This will close the capture UI after 5 seconds--replace with whatever logic you need
setTimeout(function () { appSession.capturePromise.cancel(); }, 5000);
appSession.capturePromise.done(function (file) {
if (file) {
} else {
}
}, function (err) {
appSession.IsAsyncMode = false;
appSession.capturePromise = null;
});
I have created Dojo widget like below using AMD loader in Dojo 1.7.2
var myCpane;
require([
"dijit/layout/ContentPane"
], function(ContentPane) {
myCpane = new ContentPane();
});
myCpane.startup(); // It gives 'myCpane' as undefined
In the above example, in the last statment, the variable 'myCpane' is coming as 'undefined', if I use the 'myCpane.startup()' inside the 'require()' callback function then, it will work fine.
But I want to use that 'myCpane' variable on outside of the 'require' function (for many reasons). I know the 'require()' callback function execution delayed due to the component loading process by Dojo.
My question is,
How to block the 'require()' function until it completes to execute it's callback function.
So the variable 'myCpane' will not be 'undefined' when the control come out from the 'require()' function
===========================================================
To overcome this issue, I have written a small function to load the modules and wait until the module load complete
LoadModule: function(modulePath) { // modulePath = "dijit/layout/ContentPane"
var moduleObject = undefined;
require({async: false}, [modulePath], function(getModuleObject) {
moduleObject = getModuleObject;
});
// Wait until the module loads completes
while(moduleObject === undefined);
// Return the loaded module.
return moduleObject;
}
The output of the function is always executing the while loop, the control never comes inside of 'require()'s callback function to set the value to the variable "moduleObject".
When the 'require()' function will call it's callback function? I have verified using the browser debugger window the file 'ContentPane.js' is loaded properly, but the callback function is not called, If I comment the while loop then, the callback is called properly.
When the control will come inside of the callback function in my case ?
I'm not sure what are you about to achieve, but it looks for me like a programming anti-pattern. Anyway you can achieve this via dojo/_base/Deferred:
require(["dojo/_base/Deferred"], function(Deferred) {
var deferred = new Deferred();
require(["dijit/layout/ContentPane"], function(ContentPane) {
var myCpane = new ContentPane();
deferred.resolve(myCpane); //resolve, i.e. call `then` callback
});
deferred.then(function(myCpane) {
console.log(myCpane);
myCpane.startup();
});
});​
Mess with it at jsFiddle: http://jsfiddle.net/phusick/HYQEd/
I would also suggest you consider one of these two strategies to achieve the same:
Give the ContentPane an id and obtain its reference via dijit's registry.byId().
Create ContentPane instance in a separate module and expose it as a return value of that module:
// file: myCpane.js
define(["dijit/layout/ContentPane"], function(ContentPane) {
var myCpane = new ContentPane();
return myCpane;
});
// file: main.js
require(["./myCpane"], function(myCpane) {
myCpane.startup();
});
I think this goes more to scope issue then amd loader question; consider
var x;
function foo() {
x = { bar : 1 };
}
// you wouldn't expect to have reference to x variable here
if(typeof x.bar == "undefined") console.log(x);
// foo() is called at a random time - or in dojo loader case, when modules are present
foo();
console.log(x.bar); // oohh now its there ^^
x in this case translates to your myCpane, which is declared as variable (var $$) inside a function, the function that is callback for when loader is done requireing modules.
The Deferred is a nice handler for this as stated below. A slight overhead though, if youre allready in a detached (async) function flow. For full control, look into require() you could do this as well:
var myCpane;
require({ async: false }, [
"dijit/layout/ContentPane"
], function(ContentPane) {
myCpane = new ContentPane();
});
// require does not return until module loading is done and callback executed
myCpane.startup();