Jquery to Prototype - javascript

How do I convert the jquery code below to prototype?
<script>
$(document).ready (function() {
$("#valor").keyup(function(){
var resultVal = 0.0;
var objRegExp = '\s+';
$("#valor").each ( function() {
resultVal += parseFloat ( $j(this).val().replace(/\s/g,'').replace(',','.'));
});
$("#total").val(resultVal);
});
});
</script>
Thanks.

I don't know, but pure JavaScript is always nice:
function doLoad() {
var valor = document.getElementById("valor");
valor.onkeyup = function() {
var resultVal = 0.0;
var objRegExp = '\s+';
for(var i = 0; i < valor.childNodes.length; i++) {
var n = valor.childNodes[i];
if(n.nodeType === 1) resultVal += parseFloat(n.value.replace(/\s/g, '').replace(',', '.'));
}
document.getElementById("total").value = resultVal.toString();
};
}
if(window.addEventListener)
window.addEventListener("load", doLoad, false);
else
window.attachEvent("onload", doLoad);

Here's a working example with the migration:
http://jsfiddle.net/MaQA5/
Code:
eventObserver = function() {
var resultVal = 0.0;
var objRegExp = '\s+';
$$(".valor").each(function(el) {
resultVal += parseFloat($(el).getValue().replace(/\s/g, '').replace(',', '.'));
});
$("total").setValue(resultVal);
};
$$('.valor').each(function(el) {
el.observe('keyup', eventObserver);
});
Some comments:
From your code, I supposed you have several inputs with the same id (valor). If this is the case, that's wrong, as ids must be unique in the whole DOM.
That's why I changed that for a class named valor.
Prototype has a special $$ function to get elements by css-selector. But uses $ for id search or to turn a DOM element into a Prototype-empowered element.
When calling to each method, instead of using this as every element in the original collection (like you do in jQuery), you must use the first argument in the function: el.
Instead of calling the keyup jQuery method, you must use observe('keyup', ....
In my opinion, jQuery is more elegant, or at least, the Prototype that I know is not that fancy :)

Related

Why can't I remove my event listener?

I have an issue with removeEventListener, it doesn't seem to work at all, I've seen some other questions on this site but I don't get it, can you help me?
displayImg() {
console.log('img')
for (var i = 1; i <= 4; i++) {
var line = "l"+i;
var position = 0;
var addDivLine = document.createElement('div');
addDivLine.className = 'line';
addDivLine.id = line;
document.getElementById('container').appendChild(addDivLine);
for (var j = 1; j <= 7; j++) {
var block = "b"+j;
var element = line+"-"+block;
var addDivBlock = document.createElement('div');
addDivBlock.className = 'block';
addDivBlock.id = element;
document.getElementById(line).appendChild(addDivBlock);
memory.addEvent(element);
};
};
showImage(event) {
event.preventDefault();
memory.clickedBlock++;
var block = event.target.id;
memory.removeEvent(block);
}
addEvent(id){
document.getElementById(id).addEventListener('click', function(){memory.showImage(event)});
},
removeEvent(id){
console.log("remove");
document.getElementById(id).removeEventListener('click', function(){memory.showImage(event)});
},
I am creating div elements then put an eventListener on them, I call the same function to remove the event, I use the same id, is there something that I forgot? I probably don't fully understand how it really works.
Thanks a lot!
In this two lines:
.addEventListener('click', function() { memory.showImage(event) });
and
.removeEventListener('click', function() { memory.showImage(event) });
function() { memory.showImage(event) } are two different functions. You need to provide reference to the same function in both cases in order to bind/unbind listener. Save it so some variable and use in both places:
.addEventListener('click', memory.showImage);
.removeEventListener('click', memory.showImage);
For example using directly memory.showImage will work properly as it's the same function in both cases.
The function looks like the same but its reference would be different. So, define the function in a scope where it's available for both function and use the reference in both case.
var callback = function(){memory.showImage(event)};
addEvent(id){
document.getElementById(id).addEventListener('click', callback);
}
removeEvent(id){
console.log("remove");
document.getElementById(id).removeEventListener('click', callback);
}

addEvenListener doesn't work on dynamic button - javascript

So I'm currently busy with learning JavaScript. I created some dynamic buttons and I tried to add an addEvenListener to it. But it doesn't work and I can't figure it out why it doesn't work. I'm just testing some stuff and I try to create buttons with values from the localstorage. It is almost working, only the addEvenListener isn't working. I just want a simple alert with the key from the localstorage.
for (var i = 0; i <= localStorage.length-1; i++) {
var categoryButton = document.createElement('input');
categoryButton.setAttribute('class', 'forumMenu');
categoryButton.setAttribute('type', 'button');
categoryButton.setAttribute('name', localStorage.key(i));
categoryButton.setAttribute('value', localStorage.key(i));
categoryButton.setAttribute('id', localStorage.key(i));
categoryButton.addEventListener('click', function(col){
alert(col);
}(localStorage.key(i)),true);
forumMenu.appendChild(categoryButton);
}
Does anyone know why it doesn't work?
You're not passing a function to EventTarget.addEventListener(). You're immediately executing and passing the result of this:
function (col) {
console.log(col);
}(localStorage.key(i))
... which is undefined. You can ammend that by using the following syntax:
categoryButton.addEventListener('click', (function(col) {
// return a function to addEventListener
return function(){
console.log(col);
}
})(localStorage.key(i)),true);
Here's a demo:
var input;
for (var i = 0; i <= 5; i++) {
input = document.createElement('input');
input.type = "button"
input.value = i;
input.addEventListener('click', function(i) {
// return a function to addEventListener
return function() {
console.log(i);
}
}(i), true);
document.body.appendChild(input);
}
You stored the value in the id attribute, so just use it:
for (var i = 0; i <= localStorage.length-1; i++) {
var categoryButton = document.createElement('input');
categoryButton.setAttribute('class', 'forumMenu');
categoryButton.setAttribute('type', 'button');
categoryButton.setAttribute('name', localStorage.key(i));
categoryButton.setAttribute('value', localStorage.key(i));
categoryButton.setAttribute('id', localStorage.key(i));
categoryButton.addEventListener('click', function () {alert(this.getAttribute('id'));});
document.body.appendChild(categoryButton);
}
In the event handler, this references the <input> element itself, so you can just retrieve the attribute value.
Thats because you are assigning that eventlistener to an object that is not still in the DOM (thats because you created this element after the DOM was loaded)
Try this:
categoryButton.onclick = function(col){
alert(col);
}
You can either declare a function to a var and then reasign this function to the event handler:
var myFunction = function(){
alert("I'm a function");
}
myElement.onclick = myFunction;

jQuery each() doesn't work using OOP approach

This is my situation in javascript:
EA = {
DOMElement: $('#example img'),
photos: '',
...
countSelected: function(){
var len = 0;
var id = '';
EA.DOMElement.each(function(index){
id = $(this).attr('data-id');
EA.photos += id + ",";
});
len = EA.photos.length;
return len;
},
}
The function countSelected return 0 but if I use this solution all works fine:
countSelected: function(){
var len = 0;
var id = '';
$('#example img').each(function(index){
id = $(this).attr('data-id');
EA.photos += id + ",";
});
len = EA.photos.length;
return len;
},
In my opinion the problem is in selector: $(this).
Do you know any solution?
Thanks!
The question is, when did you initialize the namespace? If you did so before the DOM was fully ready, and/or if images were added later under that #example element, then the jQuery reference is stale.
You have a couple of options. One is to initialize it later; another is to use the jQuery call every time (like in your second code snippet); another is to create a function in the namespace that will invoke the jQuery constructor whenever you need it (which at least allows you to reduce selector duplication).

How do I build up my Javascript/Jquery for many elements using a loop?

instead of repeating the same code over and over again in my js file with the only difference being the element names, I was hoping to build a loop that would build out my js.
I'm tryign to add toggle functions to some buttons on my page that change their colors and sets a value elsewhere on my page. Here is my code:
var className;
var idName;
var i;
for (i = 0; i < 11; i++) {
className = ".feedbackq";
idName = "#feedbackq";
className = className + i.ToString();
idName = idName + i.ToString();
$(className).toggle(
function () {
$(className).each(function () {
$(className).css("background-color", "");
});
$(this).css("background-color", "red");
var value = $(this).val();
$(idName).val(value);
},
function () {
$(this).css("background-color", "");
$(idName).val("");
});
}
This is unfortunately not doing anything. When not in a loop, with hardcoded variable names, the code works, but I need this to be dynamic and constructed through a loop. The 11 count that is shown will eventually be a dynamic variable so I can't do hard coding....
Thanks for the help!
UPDATE: As requested, here is the not in the loop code:
$(".feedbackq0").toggle(
function () {
$(".feedbackq0").each(function () {
$(".feedbackq0").css("background-color", "");
});
$(this).css("background-color", "red");
var value = $(this).val();
$("#feedbackq0").val(value);
},
function () {
$(this).css("background-color", "");
$("#feedbackq0").val("");
});
$(".feedbackq1").toggle(
function () {
$(".feedbackq1").each(function () {
$(".feedbackq1").css("background-color", "");
});
$(this).css("background-color", "red");
var value = $(this).val();
$("#feedbackq1").val(value);
},
function () {
$(this).css("background-color", "");
$("#feedbackq1").val("");
});
$(".feedbackq2").toggle(
function () {
$(".feedbackq2").each(function () {
$(".feedbackq2").css("background-color", "");
});
$(this).css("background-color", "red");
var value = $(this).val();
$("#feedbackq2").val(value);
},
function () {
$(this).css("background-color", "");
$("#feedbackq2").val("");
});
One way to do this (without seeing your HTML for further simplifications) is to put the index number on the object before your event handlers using .data() so it can be retrieved later upon demand independent of the for loop index which will have run its course by then:
var className, idName, i;
for (i = 0; i < 11; i++) {
className = ".feedbackq" + i;
$(className).data("idval", i).toggle(
function () {
var idVal = $(this).data("idval");
$(".feedbckq" + idVal).css("background-color", "");
$(this).css("background-color", "red");
var value = $(this).val();
$("#feedbackq" + idVal).val(value);
},
function () {
var idVal = $(this).data("idval");
$(this).css("background-color", "");
$("#feedbackq" + idVal).val("");
});
}
Note: I've made a bunch of other simplifications too:
I declare multiple variables with one var statement.
toString(i) is not needed to add a number onto the end of a string and you had it mispelled too (with the wrong capitalization)
.each() is not needed to apply .css() to every item in a jQuery collection
I suspect that if we could see your HTML, we could significantly simplify this further as there are probably relationships between items that could be exploited to reduce code, but without the HTML we can't offer any advice on that.
You probably fell victim to the closures-inside-for-loops bug. You need the code inside the loop to be in a separate function, so each iteration gets its own className variables instead of them sharing the variables.
You could do this by crating a named function or by using a jQuery iterator function with a callback instead of a for loop
var toggle_stuff = function(i){
var className = ".feedbackq" + i; //The variables are local to just this iteration now
var idName = "#feedbackq" + i; //No need to call toString explicitly.
//And so on...
}
for(var i=0; i<11; i++){
toggle_stuff(i)
}
I kinda suspect that you are calling the wrong function, should be .toString() instead of .ToString().
Note that JavaScript is case-sensitive.
But if I write the code anyway I will ignore the .toString() part and use the numeric value directly...

making getelementbyid plural

In the context of the code below (or anywhere), is it possible for a getelementbyid function to work plurally? Or do I need a different function, or possibly Jquery?
<script type="text/javascript">
window.onload = function()
{
var test = document.getElementById('test');
if (test)
{
test.className = 'unactive';
test.firstChild.onclick = function()
{
if(this.parentNode.className == 'unactive') {
this.parentNode.className = 'active';
}
else
{
this.parentNode.className = 'unactive';
}
}
}
};
</script>
You can use this;
document.getAllById = function(id){
if(document.all)
return document.all[id];
var elements = [],
all = document.getElementsByTagName('*');
for(var i=0;i<all.length;i++)
if(all[i].getAttribute('id')===id)
elements.push(all);
return elements;
}
Anyway, as #Pointy said, the id attribute is supposed to be unique, while class is used to define one or more elements that has some common properties
I assume you want to act on multiple elements using a list of IDs. (If I am wrong, and you actually want to select multiple elements with the same ID, you have done a Bad Thing, since IDs should be unique. In that case, you should use classes instead.)
In jQuery, you can accomplish this with a comma-separated list of id selectors (like $("#foo, #bar, #baz")) and implement your function like:
$("#foo, #bar, #baz").addClass("unactive")
.children(":first-child").click(function() {
var $this = $(this);
var $parent = $this.parent();
$parent.toggleClass("active unactive");
});
Without jQuery, this small function takes a list of IDs and results an array of nodes:
document.getElementsByIdList() {
var results = [];
for(var i=0; i<arguments.length; ++i) {
results.push(document.getElementById(arguments[i]));
}
return results;
}
Use it with you current code with:
var myNodeArray = document.getElementsByIdList("foo", "bar", "baz");
for(var i=0; i<myNodeArray.length; ++i) {
var test = myNodeArray[i];
if(test) {
// your code goes in here...
}
}

Categories

Resources