I have a
<div id="content">
</div>
and three js variables that store different html: content1, content2 and content3.
By user interactions, the content of mentioned above div changes to one of that that stored in js variables.
What is preferable either to directly set div content to what I need by user interaction:
$("#content").html(content2);
or to change div structure to:
<div id="content">
<div id="c1">
// value of content1 variable here
</div>
<div id="c2">
// value of content2 variable here
</div>
<div id="c3">
// value of content3 variable here
</div>
</div>
And doing hide() and show() to that inner blocks, i.e when I want content2 to be shown:
$("#c1").hide();
$("#c2").show();
$("#c3").hide();
?
I'd say hiding & showing divs.
It's less intensive, and if the content inside the javascript variables happens to contain elements that you'll bind to, you won't have to rebind everytime you refresh the content, and if you wanted to have some sort of animation between the different content, multiple divs also allows that.
As a side note, using jQuery it's less code to do something like
$("#c2").show().siblings().hide();
The two aren't really all-that comparable since they do different things. They may well give a similar perception but what's happening isn't the same in terms of markup. In fact, it's not uncommon to see .html('Something').show() chained together.
Passing a string to .html() replaces the content of the selected element, it does nothing to affect the element itself.
Calling .show() or .hide() only affects the element itself - all the descendants remain exactly the same, they just can't be seen because their parent is not being displayed.
By using .html() you are replacing everything inside your element. All references to these descending elements will become undefined and direct (non-delegated) event listeners will also be lost.
.hide() and .show() do exactly what they say. The data inside your element is still preserved, the event handlers still in place, it's all just 'hidden' by way of display: none.
If the content dynamically changes, without page-load, use .html(), if not, .show() and .hide() are more appropriate.
For the ease of use and shorter more cleaner looking code, setting the content through HTML is the right option!
Think of it as what you're trying to do, 1 DIV => Can contain 3 different contents, you can manipulate it through JS.
So, in your first solution, you actually have one div and manipulating it through JS:
$("#content").html(content1);
$("#content").html(content2);
$("#content").html(content3);
Whereas, in the second solution, you are actually using 4 divs for the same functionality! So definitely, if you can do something with 1 div. That's the preferred way.
They both are taking equal lines for JS, but with the second approach, your HTML will contain a lot more code considering your contents are large.
I think that the best solution is to store the different contents into three variables and then assign to the div the choosen one with
$("#content").html(content2);
In this way you have three less nodes on your DOM tree
There isn't that much difference between the two options. One factor that might affect this is the actual size of the content you are changing. If the content is relatively small then it really doesn't matter which way you choose.
Another thing to consider is how available the three versions of the content variable is. If you have to fetch this HTML content each time you load it then it might make sense to pre-populate the content before you display it to your users so as to save the time it takes to load it. Then just show/hide the appropriate content.
Related
I want to toggle(hide/show) an element when a button is being pressed. I have two ways as to implement this:
Find the element according to its class name, e.g $('.my-content')
Find the element according to its relevant DOM position towards the button, e.g. $('#my-button').parent().next().next().next()
However, none of the above seems to me very reliable since in case someone changes the HTML code, the above approaches should not work. Is there something more reliable I am missing?
If it's a specific element, supply it with an Id value and use that
to find it.
If it's a TYPE of element, use a class name.
Other than that, there's no real conventions. Just try and make sure that somebody reading your code understands what is going on.
A very good practice is to decouple HTML, CSS and JS.
When binding javascript to DOM elements you should use javascript selectors.
Basically classes with some custom prefix (like js-) which will be used only for javascript purposes (not css style).
So whenever the DOM tree structure or the CSS class names are changed, you can still have your working JS selector
HTML
<div class="my-content js-toggle-element"></div>
JS
$('.js-toggle-element')
CSS
.my-content{ ... }
Plus, using Javascript Selectors:
makes HTML highly readable: you can easily find out what will happen to that element with that js class
allows you to easily apply/disapply that behaviour also to other elements in the future, simply by adding/removing that class in your HTML and without affecting CSS at all
<div class="my-content js-toggle-element"></div>
...
<div class="another-content-to-toggle js-toggle-element"></div>
Using jQuery will be much easiest way. Like this -
$( ".target" ).toggle();
The matched elements will be revealed or hidden immediately, with no animation, by changing the CSS display property. If the element is initially displayed, it will be hidden; if hidden, it will be shown.
Reference - jQuery Toggle
If the class or the position of the element in DOM is changing then you can try
selecting it with the inner text
$("button:contains('buttontextgoeshere')")
I want to do the following:
<div id="theDiv" style="width: aJavascriptVariableOrFunctionCallToGetValue">TESING</div>
I don't want to use, elsewhere in the code,
document.getElementById('theDiv').style.width = someValue;
I actually want that div, when it first appears, to have a width set, inline, by either a JavaScript variable or by way of a call to a JavaScript function.
How can I do this?
This is impossible to do the way you see this.
Every time the variable changes, you need to update the style of that particular object:
var theDiv = document.getElementById("theDiv");
document.getElementById('theDiv').style.width = someValue;
I really don't understand what you mean that when it first appears you want it's width to be set to certain width - why do you want to do that inline? Why can't you just set the width in your Javascript? What's preventing you from doing that? Especially if you want to do it just once and don't want to change it dynamically.
If you want to link the width of the div to a variable, look at frameworks like Backbone or EmberJS. You can then define a renderer that changes the width when the variable changes.
The only way to get JavaScript to run when an element first appears is with an onload event handler. And onload events only work on a few specific elements, like body, script or img.
Here is how you could make it work in your case, with a img tag:
<div id="theDiv">
TESING
<img style="display:none;" src="tinyImage.jpg" onload="this.parentNode.style.width='100px';"/>
</div>
Honestly, I don't see this as a good practice, and I would recommend to just be patient, and set the width later in a script.
Live demo: http://jsfiddle.net/HKW6b/
You cannot do it like that. There are other ways to achieve what you want, though.
Server side processing, specially if the technology you use supports templating. You can manipulate the html value before sending it to the client;
jQuery may be something to consider. Simply fetch the element and use its API. Example:
$("#theDiv").width(aJavascriptVariableOrFunctionCallToGetValue);
This small piece of code does exactly what you want. It is not written inside the element itself, and it is about equivalent to the sample you provided, but again, it's something to consider should you have to do more complex operations on the DOM later on.
If you want to execute that piece of code only once, and after the page is ready, you can do it like this:
var div = $("#theDiv");
div.ready(function () {
div.width(aJavascriptVariableOrFunctionCallToGetValue);
});
The solution for this issue allowed me to set the proper width of the div immediately, asymptotically approaching inlined-javascript as possible, as per one of the comments above suggested:
"If you need the style applied immediately, you can embed a script immediately following your HTML markup and then you won't have the flash of unstyled content I'm guessing you want to avoid. – Harvey A. Ramer"
This solved the 'slow server' => FOUC problem. I added a 'script' tag immediately after the div tag to set the div to the window.innerWidth, problem solved.
From what I've seen, this approach is the earliest/soonest/fastest way to use javascript to set a CSS style attribute -- and it avoids having to code up an 'onload' handler.
The problem with 'onload' handlers being used to set UI style attributes on the page is -- the onload Javascript handler function can grow...and grow...and grow over time over the project's lifespan and you eventually are forced to clean out the onload handler. Best approach is to never use an onload handler that sets styles in the first place.
I'm using React, and this syntax worked for me:
<div id="theDiv" style={`width: ${aJavascriptVariable} %`}>TESING'</div>
I am trying to toggle a div by clicking on a different div. The only relation that two divs share is that they are inside the same div. I have a DIV class comment which holds DIV class button that is supposed to toggle DIV class box when clicked. The box DIV is also inside the comment DIV. I am trying to use jQuery(this).find(".box").toggle();, but it is not working. I am triggering it with $( ".button" ).click(function(). The script is currently at the bottom of my body.
Could anyone please tell me what am I doing wrong here? I've been playing around with the function for a while now, but with no luck at all. Thank you in advance for your replies.
JSFIDDLE here
HTML
<div class="comment">
<div class="button">
show/hide .box with text1
</div>
<div class="box">
text 1
</div>
</div>
<div class="comment">
<div class="button">
show/hide .box with text2
</div>
<div class="box">
text 2
</div>
<div>
jQuery
$( ".button" ).click(function() {
jQuery(this).find(".box").toggle();
});
You can use the jQuery selector .siblings() to re-write your function like this:
$( ".button" ).click(function() {
$(this).siblings().toggle();
});
Here's a working fiddle to demonstrate.
All you really need to do is this:
$(this).parent().find(".box").toggle();
In short, change:
jQuery(this).find(".box").toggle();
To ONE of the following lines:
$(this).parent('.comment').find(".box").toggle();
$(this).closest('.comment').find(".box").toggle();
$(this).siblings(".box").toggle();
Full Explanation:
The reason it's not working is due to the call. Let's break down your call and see what exactly it's doing.
First we see a simple jQuery selector. This tells jQuery to look for a div containing the class button. Keep in mind, jQuery makes use of any CSS selector. So selecting an item in jQuery is as simple as using it's CSS selector!
$( ".button" )
Next you are assigning an event. In this case, that event is click, meaning you're telling a div having the class button to do something every time it is clicked. Keep in mind, however, not including a callback function is an easy way to trigger this event as well.
$( ".button" ).click(function() {
Now this next line is where your mistake takes place.
jQuery(this).find(".box").toggle();
The first mistake is the use of jQuery. after you're already making use of it's short sign, $. You only need use the elongated name if you are using jQuery's noconflict because another JS library you include might use $. In other words, if $('.button') works and is a jQuery object when used, then you don't need to use jQuery.. See more about this here.
Now, that aside, we can look at jQuery(this) as $(this). Whenever you use $(this) in an Event's callback method, you're referring to the element that the event was tied too. That means that $(this) in your function refers to $('.button'). The problem here is that you then want it to find an inner element containing the class box. Well according to your HTML, that can't happen since .box is a sibling, it is not within the inner HTML of .button. Thus you need to make a different call before you can find .box.
There are actually several solutions here. No solution is more "correct" than another, just simply different and possibly causes a different amount of "time" to run. Now I went with what I saw as being the most simple in that it gives you control over the parent element which contains ALL relevant elements to this function. I'll talk about possible alternatives in a minute.
$(this).closest('.comment')
The above line simply tells .button:clicked to look for the first parent element that contains the class .comment. In other words, this won't find any children or siblings, it will only go up from the current element. This allows us to grab the block that contains all relevant elements and information and thus make maneuvers as needed. So, in the future, you might even use this as a variable in the function, such as:
$('.button').click(function(e) {
var container = $(this).closest('.comment');
Now you can find anything within this element block. In this case you want to find box and toggle it. Thus:
$(this).closest('.comment').find(".box").toggle();
// Or with our variable I showed you
container.find(".box").toggle();
Now, there are plenty of alternatives based on your HTML layout. This example I've given would be good even if .box was buried inside more elements inside .comment, however, given your exact HTML, we see that .button and .box are siblings. This means that you could make this call different entirely and get the same result using something like:
$(this).siblings(".box").toggle();
This will allow our currently clicked and selected button element to look for ANY and ALL siblings having class box. This is a great solution and simple if your HTML is that simple.
However, many times, for "comment" type setups, our HTML is not so simple, nor is it static. It's usually something loaded after the page load. This means our general assignment of .click will not work. Given your exact HTML and not knowing a static Parent ID, I would probably write your code as:
$(document).on('click', '.button', function(e) {
$(this).siblings('.box').toggle();
});
What this does is allow for this click event to be assigned to ANY element containing .button for a class, whether loaded with page or even ten minutes after the page is up. However, the caveat often seen here is the assignment is placed on document. Should we assign a lot of events to document it could become quite convoluted and possibly slow down the client's browser. Not to mention the arguments held over all the other headaches this could cause. So here's my recommendation, make a static (loads with page, is a part of page's main HTML) loading area and do our dynamic assignment to that. For instance:
<div id"Comments"><!-- load comments --></div>
Then you can do the assignment as such:
$('#Comments').on('click', '.button', function(e) {
$(this).siblings('.box').toggle();
});
If you have any more questions, just comment!
Side Note .on is for jQuery versions 1.7+. If using older jQuery, use .live or .bind
I'm trying to think of the most elegant solution to handle multiple Fx.Slides within mootools. I'm developing a dictionary page with a very long list of words where there's a pair word -- translation and all the translations must be hidden by default showing just a word list. I'm looking for a solution that won't require creating a separate slide for each word on the page, so that they're created on-the-fly when a visitor clicks on a word because the size of the script and performance hit concern me. There's another problem in that their initial states must be set to 'hidden' beforehand and I don't want to do it in CSS (that would hide everything from people whose browsers don't support javascript).
Is anything of this sort possible or will I have to rely on creating slides in a loop (my element ids go like w01, w02, ...)? If so, how would I put that block inside a loop?
Check out this question regarding if the user does not have Javascript Embedding extra styles with noscript.
After that is taken care of we can concentrate in mootools. You want the elements to have visability: hidden when you load the page with Javascript. Give your elements a class so we can select them all at once. Example to initialize the elements.
$$('.sliders').each(function(el) {
el.slide('hide').setStyle('visibility', 'visible');
});
Now we need to handle the click event. The same goes here.
Example html:
<h3 class="slideIn" >Some title</h3>
<div class="sliders>Some lengthy text<div>
Example html:
$$('.slideIn').addEvent('click', function() {
this.getNext().getChildren('.sliders').slide();
});
Example fiddle: http://jsfiddle.net/b4Zjs/
Edit: If there are a lot of elements that should have click events it's better to use event delegation. Then you are only adding one event listener to the page, and it can make a huge difference some times.
$('parent').addEvent('click:relay(h3.slideIn)', function(event, target) {
target.getNext().getChildren('.sliders').slide();
});
jsFiddle example: http://jsfiddle.net/b4Zjs/2/
I have a number of divs, each of which contain an instance of a number of different items, each with their own unique classes and/or ids.
A lot of .js code applies to the elements within each of these parent divs, and my .js is getting bloated by the constant need to do things like:
// Stuff like this occurs 15-20 times for similar but different actions
$(this).parent().nextAll('.target').eq(0).find('.toggle').slideToggle();
$(this).next('.alert').html('Success');
In the context of the document, I see why this code is necessary. However, I feel that if I were only able to redefine the reference point as being the parent div instead of the whole document, I could replace the convoluted code above with the MUCH easier:
function keepingCodeWithinParentDiv(){
$('.toggle').slideToggle();
$('.alert').html('Success');
}
So, is there a way to say in Javascript: for this part nothing exists outside this div?
If you have a parent element (let's name it element) that you want to confine your jQuery selector operations to, you can just pass it as a context to any jQuery select:
$(".toggle", element).slideToggle();
See jQuery doc for more info.
If you show us your actual HTML and describe what you're trying to get, we could give more specific advice.