function eventlisternOnclick(_class, ability, _src, _id){
var cell_onclick = document.querySelectorAll(_class);
for(var c = 0; c < cell_onclick.length; c++){
cell_onclick[c].addEventListener('click', function(){
//problem here , ability(_src) = fun1(mysrc);
//error
ability(_src);
}, false);
}
}
function fun1(mysrc){
console.log();
}
eventlisternOnclick("abc", "fun1", "this.src", null);
the fun1 is a function and i was trying to set as variable at eventlisterOnclick , and run the function there , but when i type ability(_src); it wont work. how do i set the function in my eventlisternOnclick.
if the parameter passed is always class then replace
document.querySelectorAll(_class);
with
document.querySelectorAll("." + _class);
Also, fun1 is a string, so if fun1 is available to this scope then try
eventlisternOnclick("abc", fun1, "this.src", null);
Complete function could be
function eventlisternOnclick(_class, ability, _id){
var cell_onclick = document.querySelectorAll(_class);
for(var c = 0; c < cell_onclick.length; c++){
cell_onclick[c].addEventListener('click', function(){
ability(this.getAttribute("src"));
}, false);
}
}
function fun1(mysrc){
console.log();
}
eventlisternOnclick("abc", fun1, null);
Related
i've a problem in js. I've a function for example:
function robePersos() {
var persos = {"player" : "data"};
return persos;
}
and then i've another function which call robePersos() like this:
function test() {
var d = robePersos();
for(var k in d) {
console.log(k)
}
}
But nothing happens. Why ?
function robePersos() {
var persos = {
"player": "data"
};
return persos;
}
function test() {
var d = robePersos();
for (var k in d) {
console.log(k)
}
}
test();
EDIT
The first snippet works. So, here is my real function:
function robePersos() {
var persos = {};
$.get({
url : 'url',
success : function(data) {
var text = $(data).find("div[menu='perso'] a"); //.clone().children().remove().end().text();
$(text).each(function(){
perso_name = $(this).text();
perso_link = $(this).attr('href');
persos[perso_name] = perso_link;
});
}
});
for(var k in persos) {
console.log(persos[k]);
}
}
robePersos();
If I replace the loop by only console.log(persos) it works but the loop return nothing. Why ?
If you want to print both Key and Value, use the following small change in your code. Your code is printing just the keys.
function robePersos() {
var persos = {
"player": "data",
"anotherPlayer": "anotherData"
};
return persos;
}
function test() {
var d = robePersos();
for (var k in d) {
console.log(k, "-" ,d[k]); // change made here. It prints both.
}
}
test();
Try whith Object.keys()
function test() {
var d = Object.keys(robePersos());
for (var k in d) {
console.log(k, "-" ,d[k]); // change made here. It prints both.
}
}
Object.keys returns an array whose elements are strings corresponding to the enumerable properties found directly in the object. The order of the properties is the same as that provided when manually iterating over the properties of the object.
https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys
How can I define, that a javascript function is to be called, whenever another specific javascript function has been called and executed?
var UploadStatusController= {
var uploadedcount,
UpdateStatus: function (numberOfUploadedFiles) {
UploadStatusController.uploadedcount += numberOfUploadedFiles;
});
},
var DisplayController{
UpdateInfoBox: function () {
$('#Infobox').InnerHtml = UploadStatusController.uploadedcount;
});
}
I do not want to call my DisplayController from the UploadStatusController,
and I also do not want to pass my DisplayController into the UploadStatusController as a variable.
Instead, I am looking for a way to bind my function to calls on the other function in a way similar to binding it to a document-event.
var uploadStatusController = {};
(function () {
var subscribers = [];
var uploadedCount = 0;
uploadStatusController.updateStatus = function (numberOfUploadedFiles) {
uploadedCount += numberOfUploadedFiles;
// call subscribers
callSubscribers();
};
uploadStatusController.subscribe = function (fn) {
subscribers.push(fn);
};
function callSubscribers() {
for (var i = 0, len = subscribers.length; i < len; i++) {
subscribers[i].apply(this, [uploadedCount]);
}
};
}());
// subscribe to event from anywhere you need
uploadStatusController.subscribe(function (uploadedCount) {
console.log(uploadedCount);
});
I'm facing for the first time OOP in JavaScript and all the troubles that comes with it...
I have this function/Object/class/whatever which has a method mainLoop() that should display some falling text - just like in the movie The Matrix. When I call it though I get undefined variables errors and using the debugger I see that inside mainLoop() this is pointing to Window instead of the object that called the method.
Here's the code:
function Matrix(config) {
return {
//[...lots of other vars...],
drops: [],
lines: [],
//final string to put in the container
str: "",
mainLoop: function(){
var tmp = "";
//randomly create a "character drop"
//(not if there's already a drop)
for(var i = 0; i < this.cols; i++){
if(this.drops[i] == 0 && Math.random() < this.freq){
this.drops[i] = irandom(this.rows) + 1;//new drop
tmp += randomChar();//output drop
}
else tmp += lines[0].charAt(i);
}
this.lines[0] = tmp; // <-------------- ERROR
//update already created drops
tmp = "";
for(var j = 0; j < this.cols; j++){
if(this.drops[j] > 0){
tmp += this.randomChar();
this.drops[j]--;
}
else tmp += " ";
}
this.lines[this.rowIndex] = tmp;
this.rowIndex = (this.rowIndex+1) % this.rows;
//render the entire text
this.str = "";
for(var l in this.lines)
this.str += l + "<br/>";
$(container).html = this.str;
},
start: function(){
for(var i = 0; i < this.cols; i++)
this.drops[i] = 0;
timer = setInterval(this.mainLoop ,this.delay);
},
stop: function(){
clearInterval(this.timer);
},
randomChar: function(){
return this.chars.charAt(irandom(this.chars.length));
},
irandom: function(x){
return Math.floor(Math.random()*x);
}
}
};
And then I call this function like this:
var config = {
container: "#container",
rows: 20,
cols: 20,
delay: 2000
};
var m = Matrix(config);
m.start();
The browser console says:
TypeError: this.lines is undefined
(code comment shows the exact point of the error). Furthermore, the debugger says that, at that point, this points to Window, not to m as I would expect... what's wrong with my reasoning? Thanks in advance for any help.
Alter your start function:
start: function(){
var self = this;
for(var i = 0; i < this.cols; i++)
this.drops[i] = 0;
timer = setInterval(function() {
self.mainLoop();
}, this.delay);
}
this was poiting at window because the scope has changed.
Since JavaScript is prototype-based, maybe (if you haven't already) try doing it following this model:
function Matrix(config) {
this.property = config.firstmember;
this.property2 = config.secondmember;
return function() { console.log('hello world') };
}
Matrix.prototype = {
someMethod: function() {
//do something
},
start: function() {
//console.log('hello world');
},
stop: function() {
//do something
}
}
var config = {
firstMember: 'foo',
secondMember: 'bar'
}
var m = new Matrix(config);
//console output: "hello world"
/*var m = {
property: 'foo',
property2: 'bar',
____proto___: Matrix: {
someMethod: function() {
//do something
},
start: function() {
//console.log('hello world');
},
stop: function() {
//do something
}
}
}*/
Also, see the answer to this question regarding setInterval.
setInterval callback functions are members of the Window object; therefore, 'this' refers to the window. You will need to pass in a parameter of the current object to the callback that is inside setInterval. See the link above for more details.
If you need a reference to the calling object, I'd suggest passing it down as a parameter to the function.
I've encountered this before and I have a fair understanding of scope though not enough. I'm trying to pass a string as a parameter to an anonymous function, inside of a for loop. From my understanding by default this is recursive so no matter how many times the variable's string changes it still sends the same string (1,2,3,4 is passed on (maybe like?) 1,1,1,1 when we want 1,2,3,4).
I want to make this non-recursive so in the example below the file names from the multiple-file-input-element are different (since none of them can be the same).
How can we make the event listener receive the non-recursive parameter?
function images_upload(e)
{
for (var i = 0; i < document.getElementById('post_files').files.length; i++)
{
var file = document.getElementById('post_files').files[i];
var n = images_name(file.name);
var xhr = new XMLHttpRequest();
if (typeof xhr.upload=='object')
{
var upload = xhr.upload;
upload.addEventListener('progress', function(e,n)
{
alert('n = '+n);
}, false);
xhr.open('POST','upload.php');
xhr.setRequestHeader('Cache-Control','no-cache');
xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
xhr.setRequestHeader('X-File-Name',file.name);
xhr.send(file);
}
else {var ns = true;}
}
if (ns) {alert('Error: your browser does not support AJAX file uploads.');}
}
Yes, I know the context of what I'm testing (testing in Firefox 10, Chrome 17(?) and Opera 12).
Consider the following two snippets:
var i;
for (i = 0; i < 5; i += 1) {
setTimeout(function () {
// here, i will be the loop variable, and thus you'll get
// an ouput of 5, 5 times, because by the time this function will be
// called, the loop will be long finished
console.log(i);
}, 250);
}
for (i = 0; i < 5; i += 1) {
setTimeout(function (i) {
return function () {
// here, i will be the function parameter of the outer function
// which has been called immediately passing in a 'copy' of
// the loop variable.
// output will be: 0, 1, 2, 3, 4
console.log(i);
};
}(i), 250);
}
demo: http://jsfiddle.net/Hpxqq/
Also, this has nothing to do with recursion.
Regarding your code, you should change:
upload.addEventListener('progress', function(e,n)
{
alert('n = '+n);
}, false);
to:
upload.addEventListener('progress', function (n) {
return function(e) {
alert('n = ' + n);
};
}(n), false);
Javascript doesn't have block scope...
Try this :
function images_upload(e) {
var ns = false;
for (var i = 0; i < document.getElementById('post_files').files.length; i++) {
(function(i) {
var file = document.getElementById('post_files').files[i];
var n = images_name(file.name);
var xhr = new XMLHttpRequest();
if (typeof xhr.upload == 'object') {
var upload = xhr.upload;
upload.addEventListener('progress', function(e, n) {
alert('n = ' + n);
}, false);
xhr.open('POST', 'upload.php');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('X-File-Name', file.name);
xhr.send(file);
}
else {
ns = true;
}
})(i);
}
if (ns) {
alert('Error: your browser does not support AJAX file uploads.');
}
}
I have several methods that I need to wrap in new methods in basically the same manner. My first solution doesn't work, and I understand why, but I don't know if there is a simple solution to this problem or if it can't be done the way that I want to do it.
Here's an example. I have objects a-c that have an onClick method. I need to execute some code before the onClick methods. I tried the following:
// objects a-c
a = {onClick : function () { console.log('a'); }};
b = {onClick : function () { console.log('b'); }};
c = {onClick : function () { console.log('c'); }};
// first try
var arr = [a, b, c]
for (var i = 0; i < arr.length; i++) {
var oldOnClick = arr[i].onClick;
arr[i].onClick = function () {
// new code here
oldOnClick();
}
}
// outputs 'c'
// what i want is to maintain a reference to the original method
// so in this case, execute my new code and output 'a'
a.onClick();
This doesn't work because when the new method is called, oldOnClick will point to the method from the last iteration and not the to method when it was assigned.
Is there a simple solution that I'm overlooking?
What you need is closure:
for(var i=0, l=arr.length; i<l; i++){
(function(i){
var oldOnclick = arr[i].onClick;
//etc.
})(i);
}
did you tried with some AOP framwork for Javascript?
for example using jQuery AOP plugin:
jQuery.aop.before( {target: String, method: 'replace'},
function(regex, newString) {
alert("About to replace string '" + this + "' with '" + newString +
"' using regEx '" + regex + "'");
}
);
check also here.
Javascript binding rules are pretty odd. Really, javascript is pretty odd.
I don't know that I'd call this the way to fix it, but by introducing a sub-function you can get introduce another bind and thereby fix this particular problem.
Your (modified for quick-y Chrome hacking) code becomes:
a = {onClick : function () { alert('a'); }};
b = {onClick : function () { alert('b'); }};
c = {onClick : function () { alert('c'); }};
var arr = [a, b, c]
for (var i = 0; i < arr.length; i++) {
var oldOnClick = arr[i].onClick;
arr[i].onClick = bind(oldOnClick);
}
a.onClick();
b.onClick();
c.onClick();
function bind(oldFunc)
{
return function () {
//New Code
oldFunc();
}
}
The above code throws up three alerts: a, b, c. Anything replacing '//New Code' will be run at the right time.
var a = {onClick : function () { console.log('a'); }};
var b = {onClick : function () { console.log('b'); }};
var c = {onClick : function () { console.log('c'); }};
var arr = [a, b, c];
for (var i = 0; i < arr.length; i++) {
var oldOnClick = arr[i].onClick;
arr[i].onClick = wrapHandler(oldOnClick);
}
function wrapHandler(handler) {
return function() {
console.log("New stuff");
handler();
}
}
a.onClick(); // outputs "New stuff" then "a"
b.onClick(); // outputs "New stuff" then "b"
b.onClick(); // outputs "New stuff" then "c"