I need short messages disappearing after preset time. Please see the fiddle here: http://jsfiddle.net/X88F9/1/.
It works well, what I am not sure about is the reference for each created object:
function addObject() {
new SomeObj(Math.random() * 1000 + 300);
}
it is not stored in any variable, can I just leave it as it is ? Or do I need to push them in some array ?
I also found this recommendation to put all in closures: https://stackoverflow.com/a/10246262/2969375, but not sure if necessary in my case and if yes, then how.
My answer to the question is: Javascript does not need a reference to the object to work, as proofed by your fiddle. So the question is more about if you need a reference to the object, to do other stuff with it later on. If you, for instance, would like to give the user the ability to click the temporarily display message and stop it from disappearing, than you can put all that code in a closure and do not need a reference, too. But if you would like to display the very same object again after it was removed from the DOM, than you need to store it in an array, other object, or variable, depending on your needs and ways to find it in a list.
Related
I have made a simple proof-of-concept Polymer 1.0 app that demonstrates my problem: JSBin.
In my problem, I am using array mutation methods to alter the array, which contains the list of shopping items.
However, this doesn't seem to work as intended. I do get a change in dom-repeat and when printing the length of the array. But I do not get the change event when I am printing the array itself nor when I wrap it in a function.
In short, why does this work?
<p>Number of items: [[list.length]]</p>
And why does this not work?
<p>Items inline: [[list]]</p>
<p>Observe function : [[_observe(list)]]</p>
Also, when I uncomment the following line (in the JSBin), things seem to work as indened. But I don't like it since it's a bit hackish.
app.notifyPath('list', app.list.slice());
I have stumbled upon the slice() fix by reading this issue: https://github.com/Polymer/polymer/issues/2068
EDIT
So, after reviewing the comments, the answer to the question "Is this by design" is YES. The array itself doesn't change (since it's only a reference), but it's property do change. That's why the slice() forces the reload since it creates a shallow copy.
However, one could argue whether this is OK. Yes, the variable list does not change per se. But putting [[list]] in the HTML code actually triggers toString(). And result of that function has changed.
I guess I'm stuck with piggybacking the length property for now...
As alluded to in the comments the notifyPath and slice calls are creating a shallow copy of the array and assigning a different reference back to the list variable - triggering an update of the binding. Without maintaining a separate (watchable) variable or messing around with object references, the only other workaround I can think of would be to piggy back on the list.length property instead of the list itself and pass that through some kind of "formatting" function. e.g.
<p>Items inline: [[format(list.length)]]</p>
app.format = function(){
return app.list.toString();
};
» Fiddle
As pointed out by #zb you could expand on this and make the function reusable with any array by passing the relevant variable as an argument too:
<p>Items inline: [[format(list, list.length)]]</p>
app.format = function(list){
return list.toString();
};
» Fiddle
I am using code lines like the following in order to fetch data from an intranet website:
util.setProp(obj, "firstNameOld", $(msg).find('#fname_a').text());
Now I have another function in the same file where I want to use the above again, resp. the value of that object - currently I am hard-coding this ('Test') for test purposes:
util.setProp(obj, "firstNameNew", 'Test');
How can I pass the value from the firstNameOld object in one function to the firstNameNew object in another function ? If a solution with global variables is better here than this would work as well.
Many thanks for any help with this, Tim.
I've never used the framework that includes util But I imagine that if there is a setProp() then there has to be a getProp() or something similar.
If so, you could do something like
util.setProp(obj, "firstNameNew", util.getProp(obj, "firstNameOld"));
This also relies on the assumption that you want to copy from two properties in the same object.
If not, then pass the desired source object in the getProp() call.
My guess is that functions (or properties) are called "firstNameOld" and "firstNameNew", so the first time you get it from selector, second time you want to do the same.
Try to use the local variable like that:
var text = $(msg).find('#fname_a').text();
//
util.setProp(obj, "firstNameOld", text);
//
util.setProp(obj, "firstNameNew", text);
This is my first question, probably very silly indeed :)
I have a selection of values in an array, returned from GM_listValues().
As I loop over the collection, I want to dynamically create buttons that call a function to delete the stored value, and reload the page.
deleteB.addEventListener("click", function() {deleteTrip(names[i]);pageSelect();}, false);
Above is the line I am using to attach the event to the button (deleteB). However, when I press the button, javascript tries to access the array of listValues (names) with the count variable (i). Naturally, this will not exist, as the loop is now done, and names is not global anyway.
What I want to know is if there is a way to copy the string value of names[i] while I am creating the function in the button, so as to not need a reference to names[i] in the code.
I know this is probably a really simple answer, but its got me stumped, this is some of my first work with javascript.
Thanks in advance.
Use a closure to remember the value;
function createDeleteFunc(name) {
return function(){deleteTrip(name);pageSelect();}
}
for() {
...
deleteB.addEventListener("click", createDeleteFunc(names[i]), false);
...
}
The problem is that all functions you create reference the same i variable. When they are called, they try to delete names[i], but i is now equal to names.length so it doesn't work.
The solution is to make a separate reference to names[i] for each function. This is usually done with a closure (à-la Paul's answer)
I'd really like to track variables without switching between Firebug console windows or clicking around so much, so I want to draw a runtime viewer of variable names and their corresponding values that will display on the page of the app I am building.
I'd like to two functions, show(variableName) and freeze(variableName). They will output both the variable's value and the name of the variable or object as a literal string which will serve as the text label in the viewer. freeze(variableName) is the same as show(variableName) except with a setTimeOut timer for tracking loops.
I'm sure I'm missing something basic, but I haven't found out a way to get the string that comprises the name of a value programmatically so I can use it as a label. I guess I could create the table with hardcoded labels prior to runtime and just populate it with values at runtime, but I really want to generate the table dynamically so it only has those variables I specifically want to show or freeze. Simple functions:
foo1 = "Rock";
show(foo1);
foo2 = "Paper";
show(foo2);
foo3 = "Scissors";
show(foo3);
should output this via getElementById('viewer-table'):
<table>\<tr><td>foo1</td><td>Rock</td></tr><tr><td>foo2</td><td>Paper</td></tr><tr><td>foo3</td><td>Scissors</td></tr></table>
I've tried this solution:
How to convert variable name to string in JavaScript?
and eval() but it's not working for me...I dunno, shouldn't this be easy? Getting frustrated...
Thanks,
motorhobo
I am not sure you can actually get the "name" of the variable that is being passed into a function for two reasons:
1) The variable is just an identifier. In fact, you could have multiple identifiers reference the exact same object. You are (generally) passing that reference, not any actual object.
2) The show/freeze function is going to stomp on the identifier name, either through named arguments in the function declaration or by referencing them through the arguments array.
I was trying to think if there was some clever way to use the arguments.callee or the stack property on an exception in Firefox... but I can't see anything that would expose the arguments as you desire.
What I would recommend is to simply add the name of the variable and its value to a simple object, and call one of the various jsDump methods (I prefer the one in QUnit):
function show(o) {
document.getElementById("viewer-table").innerHTML = QUnit.jsDump(o);
}
// actually use the method
show({"foo1":foo1});
There's no easy way to solve this as the called function simply doesn't know the original name of the variable. You couldn't solve this with reflection even (esp. in javascript) so you'll have to pass the name of the variable to the function too. To follow the link you posted:
function show(varObject)
{
for(name in varObject)
{
alert(name + ": " + varObject[name]);
// save both name and reference to the variable to a local "to observe array"
}
}
And call it with
var test = "xxx";
show({'test' : test});
Within the for loop you could add easy variable to a monitor array and update your gui in fixed time intervalls (you can't be notifed when a signle variable changes it's value. You need some kind of global monitor/observer which exactly you're trying to create).
In this link: http://css-tricks.com/snippets/jquery/jquery-plugin-template/ it has a line of code that says
// Add a reverse reference to the DOM object
base.$el.data("yourPluginName", base);
what does the "reverse reference to the DOM object" mean?
Assuming that you know the jQuery data function:
It's storing a reference to the instance of the class in the data cache of jQuery, meaning that the stored instance can be used to access the initial base object if it in the current context is not available.
This way, the class instance can be used later. However, the use of the prototype keyword upon the initial class that the instance were created from will modify the instance.
EDIT:
Ooops, it seems that Anurag is right, and I was giving wrong information.
Sorry, the information I gave in initial answer was not completely correct. I've updated the answer, so it now tells the truth.
In the comments you're asking:
so you mean its storing the current state of "base" in the data cache but if we make changes to "base" later on then the one in the data wont be affected? so if for some reason we needed to get the original one again we can do data('yourPluginName') to retrieve it? can you give me an example of when this would be helpful?
It seems that none of the statements are correct.
As I did obviously not remember adequately, the thing stored in data is only a reference to the object:
var obj = {};
obj.hello = "Hello";
$("#someElement").data("object", obj);
obj.world = " world.";
alert(
obj.hello +
$("#someElement").data("object").world
); // alerts "Hello world."
BTW, JavaScript variables with names like this base-thing (but, more often seen as that or similar) are typically used to represent the current context, accessed through the this keyword, which on many occasions is more easy to store in another variable due to scoping/context changes, that will make the current context and therefore this, change.
Also due to issues with context, the stored value in data could be used to access the specific object instance from another context (that is, when this represents something else), instead of the version of the base object that was continually used after a copy of it was stored.
I hope this answered you questions :D
The technique and the problem it solves is general and not specific to jQuery plugins. There may be cases where a Javascript object corresponds to a DOM element, and wraps logic specific to that DOM element. This object might be interested in listening to events such as clicks that happen within that DOM element. The information we get in those callbacks is the element that triggered it, and not the associated object. You could use jQuery's data API or any type of map in general to retrieve the corresponding object, and do something with it.