Can this snippet of Javascript be simplified more with jQuery? - javascript

I have the following snippet of Javascript, which is just attaching an onclick to a button and then updating the text of an em tag underneath it. I'm slowly trying to educate myself and work with jQuery more as I've found to like the syntax a lot more and for some tasks, it's more of a pleasure to work with.
Some of the best examples I've found have come from Stackoverflow, so I come once again, to see how this could refactored and improved with jQuery; any thoughts?
$$('em.green').each(function(em) {
em.up('button').onclick = function() {
em.update('Saving...')
};
});
Thanks!

Try this, little bit shorter:
$('button').click(function(i, button) {
$(button).closest('em.green').html('Saving...');
});
Saves you from having to loop through every EM and then bind the onclick. Might also help to add a class to the button so you're not binding to every button on the page, just in case there are others.

Here is a line by line translation from your prototype code. Not a lot different:
$('em.green').each(function(i, em) {
$(em).closest('button').click(function() {
$(em).html('Saving...')
})
});
IMO the prototype version looks just as nice if not nicer (without $ sprinkled everywhere).

This is a little shorter and might be easier to understand, but duplicates the "em.green" selector.
$('button:has(em.green)').click(function() {
$(this).find('em.green').html('Saving...');
});
crescentfresh's answer is also good, and doesn't need search for the em element each time. The performance impact shouldn't be noticeable though, since you probably don't have a huge tree of elements under the button.

Matthew Crumley's answer is good but why attach multiple handlers when one will do.
The added advantage is that this will also work if you create any em.green elements later in the lifespan of the document.
$('button:has(em.green)').live('click', function(){
$(this).find('em.green').html('Saving...')
});

(I can't edit, so I'll have to create a new answer but:)
Slightly shorter:
$('button').click(function() {
$(this).closest('em.green').html('Saving...');
});
Saves you from having to loop through every EM and then bind the onclick. Might also help to add a class to the button so you're not binding to every button on the page, just in case there are others.
It's unnecessary to include the function parameters, use the this variable to specify the context you want to find the closest parent of.

Related

Vanilla Javascript - How can I use mouseup and mousedown on the same button to change and revert a css class value?

I'm a beginner learning to work with vanilla javascript. I have been searching for 2 days, and posting questions in a couple of javascript facebook groups since last night, and I haven't found a solution yet. Maybe I'm not asking the question correctly in my search, but I'm just stuck. If, for some reason, I am bringing up a question that has been answered, I apologize. In my defense, being a beginner sometimes means we are not sure exactly how to search for the answers.
Moving on...
I am trying to figure out how to use 2 eventListeners for the same button to change a css property value. I want function1 to run on mousedown and function2 to run on mouseup. I think my problem is occurring with the (event) parameter. Is there a way to make sure the event parameter in function1 is targeting only the event for mousedown? Then point the event in function2 to use the event for mouseup?
This is what I have so far...
html
<button class="my-btn">My button</button>
<div class="my-class">
some content
</div>
Javascript
let myBtn = document.querySelector('.my-btn');
let myClass = document.querySelector('.my-class');
myBtn.addEventListener('mousedown', function1);
myBtn.addEventListener('mouseup', function2);
function function1(event){
myClass.style.bottom = "-16em";
}
function function2(event){
myClass.style.bottom = "0";
}
Good that you have started to work on Js.
I have created a playground which changes the background color on mouseup and mousedown event. Please visit the below link for the same.
https://jsfiddle.net/kqydbwhL/
Also, I feel like in your code.
myBtn.addEventListener('mousedown', function1);
myBtn.addEventListener('mouseup', function2);
myBtn should be replaced with myClass because you are storing the element into myClass but while listening to the events you are targeting myBtn which is undefined.
Thanks.
I think you updated your code snippet in the problem description.
Here is the new playground url having those changes.
https://jsfiddle.net/6pzhjvfL/17/
After looking at your pen, it seems that position property should be set differently in my-class. Bottom property does not work with static position, which is a default position of all elements.
Maybe you can learn more about bottom property here.
Take a look at this example. I added position:relative to my-class. Try it with position:absolute if that is the result you wanted.
After reviewing the responses here, it was pointed out to me that my code actually works the way I want it to. So I went back to my original project to review. I discovered that I had function2 nested inside `function1' which was not intended. A misplaced curly bracket way down at the bottom of my file, completely out of sight, was the problem. I wasted 2 days looking for an answer to a problem that ended up being a syntax error of my own doing.
Thank you all for your help. I will be careful in the future to keep this from happening again.

Jquery img added through append() triggers onload twice

The code that produces the headache for me is rather simple:
$(function(){
$("#test").append('<img onload="alert(\'hi\')" src="Image.jpg"/>');
})
I have the above code in my head and a div with id 'test' in the body. Now my problem is that the page produces two alerts when the image is loaded, but I expected it to produce only one as the 'onload' should be triggered only once- The way it happens when I add the image manually without any javascript..
See the fiddle I made at: http://jsfiddle.net/9985N/
Any help/explanation is greatly appreciated...
UPDATED (Because some people don't believe me, lol)
Because .append creates the node first and then moves it to its appropriate position. Try appending the element first then adding its attributes as follow:
$(function() {
$("#test").append(
$("<img />").attr({
src: "http://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Bachalpseeflowers.jpg/300px-Bachalpseeflowers.jpg",
onload: "alert(\'hi\')"
})
);
});
My answer does not "avoid" the problem, it answers it very directly. If you open the jQuery.js file in uncompressed format you can clearly see that .append creates the node on the document which is when the onload event is first called and then shifts it into position which is when it gets called again. Perhaps shift is the wrong word, forgive me as vocabulary is not my strong suit. However if you follow the code you see its creation and its movement, however the same is not said for using append again to move it, as the node is already created it simply moves from one element to another with no respark of onload. As I said, not sure best terminology, but it's very easy to follow along on the jQuery.js.
Don't believe me? Just tested the following fiddle in MSIE9, FF12, & GoogleChrome20 with 0 problems.
jsFiddle
just FYI, it's not really a horrible practice, but I see people write whole lines of HTML in jQuery all the time and that kind of defeats the purpose. It's a library with many books to read on purpose. Sometimes a complete line of HTML might seem easier, but it may not be faster as it doesn't follow all the great layout work that has been done for you. The idea is to "Write less, do more" and this includes HTML. After all, if you were gonna write the whole line of HTML, why use jQuery at all when you could just PHP it in!? :P Just a thought.
or this:
var img = $('<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Bachalpseeflowers.jpg/300px-Bachalpseeflowers.jpg"/>').on('load', function(){
$('#test').append(img);
alert('loaded');
});

Div with a jQuery click event bound to it is not firing when clicked?

It could be a rookie mistake, but I've gone over my code enough times doing things such as; pre-pending .select-delete with div, attempted to use document.write("Hello") to see if the event was firing or not.
Here's a link to my jsFiddle: http://jsfiddle.net/gPF8X/5/
I really have no idea what's going on :(.
Any help would be greatly appreciated!
Edit: Linked to the incorrect JSFiddle, relinked to the correct one.
There is no - in your div class name.
<div id="1" class="selectdelete"></div>
$('.select-delete').click( function() {
Got it - id needs to be wrapped in quotes.
var value = $(this).attr('id');
The trigger is firing, but your code is not running because of an error - you're not quoting the string 'id' so it's an undefined value. Use your browser's debugger tool - it will help for this sort of thing.
Beyond that though, I can't say anything further because it's not clear what the desired result is.
Edit There's another issue as well - the selector is not working. You can't use the [ and ] character unquoted inside a jQuery comparison like that. The simplest solution is just not to have those characters in your input names. But you can also use escaping like so: $('select[name=g_country\\['+value+'\\]]').
I know you already accepted my other answer, but I just want to add for the record that there is another way to do it. Specifically, this seems like one of those cases where jQuery is less helpful rather than more. What I would do is change your HTML so the element names were also given as IDs, and then write it like so:
document.getElementById('g_country['+value+']').disabled = true;
document.getElementById('g_url['+value+']').disabled = true;

How to prevent child from one element to be on top of another element

(Okay, I know the questions probably sounds rancid bad, so someone edit if they they know how to reformulate it).
So, basically I have this: jsFiddle
And as you can probably see, I'm trying to re-create a basic windows 7 aero effect (curiosity, fun, learning, etc nothing big), but I stumbled into a few problems.
(I will explain only vaguely, since you can see it on the fiddle and otherwise it would be a textathon)
The text is stuck on top of the parent's(div) parent(div) element.
The text somehow leaks out of the duplicate element(div), even thought it doesn't from the original.
I know this all sounds odd, but you'll probably best see it on the fiddle.
Thank you.
I think the problem you're having is stemming from this:
$(container).find('*').each(function() {
var e_clone = $(this).clone(false).appendTo(processor);
// etc etc
});
By using the * selector then running .each you are cloning more markup into #processor than I think you might have intended to. You get two copies of span.lol in there because first it clones #box (including all its children) and then on the next iteration through the each it copies over span.lol on it own.
As for the "leaking" of text out of the parent, it does happen in the original... at least that's what I see in Chrome if I comment out the call to glass('#container', '#processor').

What is the most common waste of computing power in Javascript?

We've all seen people who do this:
jQuery('a').each(function(){
jQuery(this)[0].innerHTML += ' proccessed';
});
function letsPoluteNS() {
polute = '';
for (morePolution = 0; morePolution < arguments.length; morePolution++)
polute.join(arguments[morePolution]);
return polute;
}
and so on. I was wondering what people have seen the most common JavaScript/jQuery technique that is slowing down the page and/or wasting time for the JavaScript engine.
I know that this question may not seem to fit into what's an accepted question, yet I'm asking "what is the most common accepted waste?"
I'm guilt of this. Basically using only the element's class in a jQuery selector. Instead of combining the class selector with the elements tag name.
<div></div>
<div class="hide"></div>
<div class="show"></div>
<div class="hide"></div>
<div class="hide again"></div>
$(".hide").hide();
Instead of the quicker
$("div.hide").hide()
Also this is inefficient, many people don't make use of the context parameter for selectors
$( selector, [ context ] )
$("#mydiv").click(function () {
$("#mydiv span").show();
}
Which can be handled better like this:
$("#mydiv").click(function () {
$("span", this).show();
}
You'll also see this:
$('#this').find('a').doSomeThing();
Know what's a lot more efficient? One selector that covers both will server you better...
$('#this a').doSomeThing();
It seems obvious, but you'll see it all the time.
Anything that has do to with tracking users and heavy publicity. Thats wasted space for sure.
I guess wrong use of stuff like using classes instead ids as selector in very complex html would slow thing down.
And ie of course.
Calling $.animate to animate elements should make the things slow down.
not declaring your vars from the getgo so they are cached, not using closures and repeating x number of the same function/call/etc but only changing id or class for each, using eval().

Categories

Resources