Remove function creation in loop - closure - javascript

I want to remove the function creation in my code, but I don't know how? Can anyone here help me?
for (var eventName in this.events) {
var eventFunc = this.events[eventName],
splitEventName = eventName.split(" "),
eventType = splitEventName[0],
eventUI = splitEventName[1];
Utilities.addEventListener(this.ui[eventUI], eventType, (function(view, eventFunc) {
return function(e) {
eventFunc.call(view, e);
};
}(this, eventFunc)));
}

You could move your immediately-invoked function expression out of the loop and turn it into a normal function declaration. Then you can simply call it on each iteration:
function makeEventListener(view, eventFunc) {
return function (e) {
eventFunc.call(view, e);
};
}
for (var eventName in this.events) {
var eventFunc = this.events[eventName],
splitEventName = eventName.split(" "),
eventType = splitEventName[0],
eventUI = splitEventName[1];
Utilities.addEventListener(this.ui[eventUI], eventType, makeEventListener(this, eventFunc));
}

Related

javascript add Single Event Lister for multiple events like ajax function callbacks succss, fail etc

I want to crate javascript object that accepts setting and provide multiple events with single addListener function. for example addListener({success: callback,fail:callback}) etc. I hope my requirement is clear.
var myCustomObject=new MyCustomeObject({name:'anu', age:'30'});
myCustomObject.addListener({
success: function(e){ console.log(e)},
fail: function(ef){ console.log(ef)}
});
You can implement your own EventEmitter like this:
const EventEmitter = function () {
this.events = {};
};
Then you need to create function for subscribe:
EventEmitter.prototype.on = function (event, listener) {
if (typeof this.events[event] !== 'object') {
this.events[event] = [];
}
this.events[event].push(listener);
};
and of course function for emit:
EventEmitter.prototype.emit = function (event) {
let i, listeners, length, args = [].slice.call(arguments, 1);
if (typeof this.events[event] === 'object') {
listeners = this.events[event].slice();
length = listeners.length;
for (i = 0; i < length; i++) {
listeners[i].apply(this, args);
}
}
};

A prototype-less, new-less, one-instance-only javascript object?

This doesn't work.
var genericClickHandler = function () {
this.handlers = [];
if (console && console.log) {
console.log("this:", this);
console.log("event:", event);
}
};
genericClickHandler.addHandler = function (handlerSpec) {
this.handlers.push(handlerSpec);
return this;
};
genericClickHandler.executeHandler = function (handlerName) {
for (var i = 0; i < this.handlers.length; i++) {
if (handlerName === this.handlers[i][0]) {
this.handlers[i][1]();
}
}
return this;
};
It doesn't work because the addHandler can't see the this.handlers in genericClickHandler.
Anyway what I'm after is function that gets defined once, but has methods and properties. I want to be able to use the function with Google Maps like this:
heatmap.addListener("click", genericClickHandler)
circle.addListener("click", genericClickHandler)
polygons.addListener("click", genericClickHandler)
So in the first instance, it only reports the this and event object. However, I then want to write code which extends the genericClickHandler dynamically so that it can implement map-object-specific behaviour.
Here's an example of what I meant using an object rather than a function.
var genericClickHandler = {
handlers: []
};
genericClickHandler.addHandler = function (name, fn) {
this.handlers.push([name, fn]);
return this;
};
genericClickHandler.executeHandler = function (name) {
for (var i = 0, l = this.handlers.length; i < l; i++) {
if (this.handlers[i][0] === name) this.handlers[i][1]();
}
};
genericClickHandler.addHandler('click', function () {
console.log('hi');
});
genericClickHandler.addHandler('click', function () {
console.log('hallo again');
});
genericClickHandler.executeHandler('click'); // hi... hallo again
DEMO
if you want to create an object, here you can see 2 ways to do the same thing, javascript got multiple way to write the same things.
var genericClickHandler = function()
{
this.handlers = [];
this.addHandler = function (handlerSpec)
{
this.handlers.push(handlerSpec);
return this;
},
this.executeHandler = function (handlerName)
{
this.handlers[handlerName]();
return this;
}
};
//sample:
var tmp = new genericClickHandler();
console.log(tmp.handlers);
console.log(tmp.addHandler("TEST"));
Another way to write the same object, but more optimised : prototype will be stored once for each object
var genericClickHandler = function(){}
genericClickHandler.prototype =
{
handlers:[],
addHandler : function (handlerSpec)
{
this.handlers.push(handlerSpec);
return this;
},
executeHandler : function (handlerName)
{
this.handlers[handlerName]();
return this;
}
}
//sample:
var tmp = new genericClickHandler();
console.log(tmp.handlers);
console.log(tmp.addHandler("TEST"));

Event handler function out of scope in for

The handler inside of my for loop might be out of scope and only prints "Last Event added" in console but doesn't loop through each element in the array. No sure where I'm going wrong here, but I need help attaching the event listener to each.
(function () {
if (document.addEventListener) {
this.addEvent = function (elem, type, fn) {
elem.addEventListener(type, fn, false);
};
} else if (document.attachEvent) {
this.addEvent = function (elem, type, fn) {
var bound = function () {
return fn.apply(elem, arguments);
};
elem.attachEvent("on" + type, bound);
return bound;
};
}
if (document.getElementsByClassName) {
this.getClass = function (className) {
return document.getElementsByClassName(className);
};
} else if (document.querySelectorAll) {
this.getClass = function (className) {
return document.querySelectorAll("." + className);
};
}
var elem = getClass("images"),
display = getClass("display_box"),
rolloverImage = function (e) {
console.log("Event 'rolloverImage' triggered");
};
console.log(display);
console.log(elem);
console.log(elem.length);
for (var i = 0; i < elem.length; i++) {
document.addEvent(elem[i], "mouseover", rolloverImage);
if (i = elem.length) {
console.log("Last event added");
} else {
console.log("Event added to " + elem[i]);
}
};
})();
A fiddle is available here: http://jsfiddle.net/bNL5C/
if you are wanting your addEvent function to be on the document object use document.addEvent = not this.addEvent = as that is putting it on the global object window
Also it doesnt loop through all of them because you are assigning i to the elem array length instead of comparing.
if (i = elem.length) {
should be
if (i == elem.length) {
Because of this on the first iteration through the loop causes i to be the value of elem.length and since i is now not < elem.length your loop exits.
One problem is that in your for loop, the if (i = elem.length) will always be true, as you are using a single assignment =, and changing the value of i. This needs to be changed to if (i == elem.length) or perhaps you'd prefer to use ===.

JavaScript - reactivity

I have this code. It does that always when there is function, that is interested on some key in Session, it will be called whenever the key changed its value.
The problem is that to track what keys the function is interested, i need to run that function once and it can have some sideffects (if that function will manipulate DOM for instance). How can i run that function without affecting the current environment, if it is possible....?
var checkRunning = false;
var keys = [];
var checks = {};
var Session = {
get: function (key) {
if (checkRunning) {
keys.push(key);
}
},
set: function (key, value) {
if (checks[key]) {
var l = checks[key].lenght;
for (var i = 0; i < l; i++) {
checks[key][i]();
}
}
}
};
function check(f) {
checkRunning = true;
f();
checkRunning = false;
var l = keys.lenght;
for (var i = 0; i < l; i++) {
if (checks[keys[i]]) {
checks[keys[i]].push(f);
}
else {
checks[keys[i]] = [f];
}
}
keys = [];
}
//how to use
var a = "something";
check(function () {
// this function should be run always when Session key "a_dep" will change
a = Session.get("a_dep");
});
Session.set("a_dep", 10);
Session.set("a_dep", 20);
So I refactored your code to achieve what I understood you wanted.
I first redefined Session and its getter/setter. I store the values in a literal object with the key to access it :
function Session () {
this.myDictionnary = {};
this.myCallbacks = {};
}
Session.prototype.set = function (key, value) {
this.myDictionnary[key] = value;
}
Session.prototype.get = function (key) {
return this.myDictionnary[key];
}
Here we have our core code. Now you want to call a function every time you set a value to a key, so we have to
Set a function (or function set) - key couple
Call this function (or these functions) when a value is set to key
Note the myCallbacks literal object which will handle these couples. So first, create the key - function couple :
Session.prototype.callbackWhenSet = function (key, callback) {
if(!this.myCallbacks[key]) {
this.myCallbacks[key] = [];
}
this.myCallbacks[key].push(callback);
}
Then call it when set is called (here I rewrite the set function )
Session.prototype.set = function (key, value) {
this.myDictionnary[key] = value;
if(this.myCallbacks[key]) {
for(var i = 0; i < this.myCallbacks[key].length; i++) {
this.myCallbacks[key][i]();
}
}
}
Finally we can test it !
var test = new Session();
test.callbackWhenSet("a_dep", function () {
alert("a_dep is set to " + test.get("a_dep"));
});
test.set("a_dep", 10);
test.set("something", 250);
test.set("a_dep", 20);
As you can see here, we have an alert showed each time "a_dep" is set.
Or you can use ProAct.js and do stuff like this:
var obj = ProAct.prob({
a: 4
});
obj.p('a').on(function () {
console.log('obj.a has changed!');
});

How to make event listener to change a variable inside javascript code?

I set up some event listeners in a traditional way like this:
<script>
window.onload = setup;
function(setup) {
var myButton = document.getElementById("myButton");
myButton.onclick = someFunction;
}
What I want someFunction to do is to change a certain variable inside my code (when the button is pushed of course). Let's say for example, that I have a function something() in my code containing variable x and the event listener is active.
function something() {
var x;
for (;;) {
if (x === value set by someFunction) {
break;
}
}
}
How can I do that?
When an event is fired you can do stuff so:
CODE CODE CODE
....
var x = INITIAL_VALUE;
function someFunc(){
x = what ever you wish;
}
The simple way is to make x a global variable.
If you don't want to pollute the global namespace, you use an immediately executing function:
(function() {
var x;
function someFunc() {
// May assign x
}
function setup() {
var myButton = document.getElementById("myButton");
myButton.onclick = someFunction;
}
window.onload = setup;
function something() {
// Use x
}
})();
This function creates a local namespace for the x variable.
If I understand your question, the simplest way would be to define a global variable var value, such that it would be accessible by both someFunction() and by something().
Another approach, without any listener, could be:
function something() {
var x;
for (;;) {
if (x === someFunction()) {
break;
}
}
}
function someFunction() {
...
return value;
}
//
// try a 'notifier' decorator
//
function notifier( handler_fn, callback_fn ) {
// #helpers
function slc( args, i1, i2 ) {
return Array.prototype.slice.call( args, i1, i2 );
}
function prepend( targetArr, arr ) {
Array.prototype.unshift.apply( targetArr, arr );
return targetArr;
}
function thepush( targetArr, arr ) {
Array.prototype.push.apply( targetArr, arr );
return targetArr;
}
return ( function( cb, args1 ) {
var origfn = this;
return function() {
var
args = prepend( slc( arguments ), args1 ),
out = origfn.apply( this, args );
cb.apply( this, thepush( args, [out] ) );
return out;
};
} ).call( handler_fn, callback_fn, slc( arguments, 2 ) );
}
var
handlerfn = function ( e ) {
var
T = e.type.toUpperCase();
( this instanceof Node ) && ( this.innerHTML = T );
return T;
},
F = notifier(
handlerfn,
function ( f1_in, f1_out ) {
var
v1 = f1_in;
v1.target.innerHTML += ', coords:[' + v1.clientX + ', ' + v1.clientY +']';
console.log( f1_in, ', ', f1_out );
}
);
document.getElementById('btn_01').onclick = F;
//
//

Categories