Changing content of a div with Prototype or JavaScript - javascript

I have this code :
<div class="box_container">
<div class="box_container_button" id="navigator_1">
Button 1
</div>
<div class="box_container_button" id="navigator_2">
Button 2
</div>
<div class="box_container_button" id="navigator_3">
Button 3
</div>
<div class="box_container_content" style="background-color:#d5d5d5;" id="navigator_content_1">
Content 1
</div>
<div class="box_container_content" style="background-color:#00aeef; display:none;" id="navigator_content_2">
Content 2
</div>
<div class="box_container_content" style="background-color:#4db848; display:none;" id="navigator_content_3">
Content 3
</div>
</div>
If I press on the button with navigator_2, navigator_content_1 must be hidden, and navigator_content_2 showed.
How can I do this with prototype? (Or javascript if it's too stronger). Unfortunatly I can't use jQuery.

Try this
function nav(obj)
{
document.getElementById("navigator_content_1").style.display = "hidden"
document.getElementById("navigator_content_2").style.display = "hidden"
document.getElementById("navigator_content_3").style.display = "hidden"
obj.style.display = "none";
}
Add onclick="nav(this)" to each button element.

Here is my suggestion:
Give the container holding the buttons in ID (for convenience).
Change the IDs of the content containers from navigator_content_1 to navigator_1_content (again, for convenience).
Then all you have to do is to keep a reference to the currently showed content pane and you have to attach a click handler to the container holding the buttons:
// by default, the first panel is shown
var current = document.getElementById('navigator_1_content');
document.getElementById('box_container').onclick = function(event) {
event = event || window.event; // for IE
var target = event.target || event.srcElement; // for IE
current.style.display = 'none';
current = document.getElementById(target.id + '_content');
current.style.display = 'block';
};
This makes use of event bubbling. event.target has a reference to the element that was actually clicked (I don't know if the Safari bug is still present, you might have to traverse the DOM up to find the correct element). This can certainly be improved but should give you a good start. You can easily add new buttons / content panels without having to modify the code.
Here is a DEMO.
To learn more about event handling, I suggest to have a look at the excellent articles at quirksmode.org

This would use prototype and get what you want
$$('.box_container_button').each(function(element) {
element.observe('click', function(event) {
$$('.box_container_content').each(function(element) {
element.setStyle({
'display': 'none'
});
});
$('navigator_content_' + this.id.replace("navigator_", "")).setStyle({
'display': 'block'
});
});
});
http://jsfiddle.net/VENLh/
THIS solution would work even if you add more buttons / contents without changing any line in the javascript (just add the html part!)

Related

Use XPath or onClick or onblur to select an element and use jQuery to blur this element

*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.

Click outside an element doesn't work

I have this code:
function showAll(el){
var id = el.parentNode.id;
var all= document.getElementById(id).getElementsByClassName('items')[0];
if(all.style.display === 'block'){
all.style.display = 'none';
} else{
all.style.display = 'block';
window.addEventListener('mouseup', function(e){
document.getElementById('test').innerHTML = e.target.className;
if(e.target != all){
all.style.display = 'none';
}
});
}
}
<div id="parent">
<div class="selected" onClick="showAll(this);">
</div>
<div class="items" style="display: none">
</div>
</div>
Basically what i want to achieve is: click on selected to display items which is now hidden after that if i click again on selected or if i click outside of items(a random spot on that page or even on selected) i want to be able to hide items.
The problem is that without the EventListener when i click on selected it works to display items and then if i click again on selected it works to hide items but if i click on a random spot it doesn't work to close items.
But when i add EventListener and i click on selected it works to click a random spot to close items but it doesn't work to click selected again to close items.
Can anybody help me with a full JavaScript explanation, please?
You're going to want to use highly reusable code. I use change() and id_() on my web platform all of the time and it's very direct and simple. In the below example the second parameter will make the class empty (you can also use id_('items').removeAttribute('class') for a cleaner DOM (Document Object Model)).
HTML
<input onclick="change(id_('items','');" type="button" value="Display Items" />
<div clas="hidden" id="items"><p>Items here.</p></div>
CSS
.hidden {display: none;}
JavaScript
function change(id,c)
{
if (id_(id)) {id_(id).className = c; if (id_(id).className=='') {id_(id).removeAttribute('class');}}
else if (id) {id.className = c; if (id.className=='') {id.removeAttribute('class');}}
else {alert('Error: the class id \''+id+'\' was not found or has not yet been imported to the DOM.\n\nNew class intended: '+c);}
}
function id_(id)
{
if (id == '' && window['console']) {console.log('Developer: empty id called from: '+id_.caller.toString().split('function ')[1].split('(')[0]);}
return (document.getElementById(id)) ? document.getElementById(id) : false;
}
This code exists from years of refining the same platform instead of industry standard drama of pointlessly changing things. You are two clicks from finding more highly reusable functions on my platform's JavaScript documentation from the link in my profile.

Efficient jQuery/JS - avoiding copy-paste the same code again & again

I need to write an efficient code in order to keep it simple & code file small, also I want to use the knowledge I hopefully get from here in future codes.
UPDATE: Just to be clear - my example is fixed "buttons" on browser window side & if you click on one of them, it takes you to div with same ID (look at code below).
IMAGE:
MY CODE EXAMPLE:
//Smooth Scroll Menu Links
jQuery('.div1').on('click', function(e) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:jQuery(this.hash).offset().top-100}, 800);
});
//I have to copy-paste it 1000 times & only change the ".div1" to something else
//Note that I need a solution with different class names, not "div1", "div2" etc but e.g "location", "potato", "car" etc.
How to make this code working without writing same lines for every single div?
There got to be a way to get class from item you click & then scroll to item with same name ID, right? Or any other way to keep codes shorter in that kind of situations - otherwise it's just copy-paste-huge-file fest.
You can give each button a class so you can catch them all, than go to the element you want to scroll to by looking at the attribute of the clicked button :)
HTML
<div class="buttons" data-scroll="div1">div1</div>
<div class="buttons" data-scroll="div2">div2</div>
<div class="buttons" data-scroll="div3">div3</div>
<div class="content" id="div1">some content</div>
<div class="content" id="div2">some content</div>
<div class="content" id="div3">some content</div>
JS
$('.buttons').on('click', function(e) {
e.preventDefault();
var scrollTarget = $(this).data("scroll");
scrollme(scrollTarget);
function scrollme(target) {
$('html,body').animate({scrollTop:$("#"+target).offset().top}, 800);
}
});
example: http://jsfiddle.net/7gd66kr1/1/
try this i hope will work with you :
jQuery('div').on('click', function(e) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:jQuery(this.hash).offset().top-100}, 800);
});
note that : this function will aplay on all divs in page
I think there are more than an unique solution. If you don't want to modify your HTML, then you need a condition to determine if the clicked element is an "active" one:
jQuery('div').on('click', function(e) {
var id = $(this).attr('class');
var scrollto = $('#' + id);
if(scrollto.length > 0) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:scrollto.offset().top-100}, 800);
}
});
If you "can" modify your HTML, it's wise to add some attribute to the "active" elements (the ones that are buttons), so you know they scroll the page, or put them inside a container. The attribute you add may be a class or any other valid attribute (I recommend "rel", but might be "data" as spotted by #Iliya Reyzis , who selects by class and scrolls to "data") and select them by it:
<div class="div1" rel="mybutton">div1</div>
jQuery("[rel='mybutton']").on('click', function(e) {
var id = $(this).attr('class');
var scrollto = $('#' + id);
e.preventDefault();
jQuery('html,body').animate({scrollTop:scrollto.offset().top-100}, 800);
});
Hope it helps!!

Simple Way to Switch a CSS Class in Javascript

I appreciate all the suggestions I've gotten so far-thank you!
I'll try to describe a bit better what I'm trying to do:
I want to switch a CSS class on the active (clicked on) tab item on a item (to make a highlight effect while its related content is showing).
The JS Fiddle http://jsfiddle.net/4YX5R/9/ from Vlad Nicula comes close to what I'm trying to achieve, however I can't get it to work in my code.
The tabs are linked to content which is shown on the page when the tab is clicked. This part is working fine. I just want to change the CSS style on the ContentLink items when its content is being shown.
I'd also like to keep the content for ContentLink1 visible when the page loads, as it is now in the code, and for ContentLink1 to have the CSS .infoTabActive class when the page loads. When the ContentLink tab is not clicked, it should have the .infoTab class.
This is what I have so far:
HTML:
<article class="grid-70 infoContainer">
<a class="infoTab" id="aTab" href="javascript:show('a')">ContentLink1</a>
<a class="infoTab" id="bTab" href="javascript:show('b')">ContentLink2</a>
<a class="infoTab" id="cTab" href="javascript:show('c')">ContentLink3</a>
<div id="a">
<p> Inhalt 1111111.</p></div>
<div id="b">
<p>Inhalt 222222222
</p></div>
<div id="c">
<p>Inhalt 33333333
<7p></div>
</article>
Javascript:
window.onload = function () {
document.getElementById("a").style.display = "block";
}
function show(i) {
document.getElementById('a').style.display ="none";
document.getElementById('b').style.display ="none";
document.getElementById('c').style.display ="none";
document.getElementById(i).style.display ="block";
}
basic CSS for tab styles I want to apply:
.infoTab {
text-decoration:none;
color:red;
}
.infoTabActive {
text-decoration:none;
color:yellow;
}
Any pointers would be appreciated!
You can switch the classes simply bu using class property on DOM element.
To replace the existing class use
document.getElementById("Element").className = "ClassName";
Similarly to add a new class to exisiting classes use
document.getElementById("Element").className += "ClassName";
Change show function to be like this:
function show(i) {
document.getElementById('a').style.display ="none";
document.getElementById('a').className ="";
document.getElementById('b').style.display ="none";
document.getElementById('b').className ="";
document.getElementById('c').style.display ="none";
document.getElementById('c').className ="";
document.getElementById(i).style.display ="block";
document.getElementById(i).className ="selected";
}
I changed a little bit your code to make it suits your needs.
First, change the onload part in the Fiddle, by no wrap.
Then, you need to hide each elements at start like this :
window.onload = function () {
var list = document.getElementsByClassName("hide");
for (var i = 0; i < list.length; i++) {
list[i].style.display = "none";
}
}
I added an hide class to achieve it. Your show function works well then.
I would do it like this:
add a class called .show which sets the element to display block.
then toggle the classname.
Here's a JSFiddle
And here's an example:
HTML
<article class="grid-70 infoContainer">
<a class="infoTab" id="aTab" href="javascript:show('a')">Werbetexte</a>
<a class="infoTab" id="bTab" href="javascript:show('b')">Lektorate</a>
<a class="infoTab" id="cTab" href="javascript:show('c')">Übersetzung</a>
<div class="box" id="a">
<div class="col1"> <p>Inhalt 1111111.</p></div>
</div>
<div class="box" id="b">
Inhalt 222222222
</div>
<div class="box" id="c">
Inhalt 33333333
</div>
</article>
JavaScript
window.onload = function () {
show('a');
}
function show(elm) {
// get a list of all the boxes with class name box
var shown = document.getElementsByClassName('box');
// loop through the boxes
for( var i=0; i<shown.length; i++ )
{
// set the classname to box (removing the 'show')
shown[i].className = 'box';
}
// change the classname to box show for the element that was clicked
document.getElementById( elm ).className = 'box show';
}
CSS
.box {
display:none;
}
.box.show {
display:block;
}
Simplest way I could think of is this : http://jsfiddle.net/4YX5R/9/
Basically you don't want to listen to each element. If you do that you will have issues with new tabs. If you listen to the parent element like in my example you can add new tabs without having to write any more javascript code.
<a class="infoTab" data-target='a' id="aTab">Werbetexte</a>
Each tab button has a data-target attribute that will describe the div to show as the tab content. Hiding and showing content will be done via css, not style - which is a recommended best practice -.
tabs.addEventListener("click", function ( ev ) {
var childTarget = ev.originalTarget || ev.toElement;
...
}
When a tab is clicked, we check to see which element was clicked from the event listener on the parent, and then get the data-target from it. We use this as a id selector to show the new tab. We also need a reference to the old tab that was active, so we can hide it.
The logic is not that complicated, and with this you can have any number of tabs. I would recommend jQuery for this, since the event delegation might not work in all browsers with the current code.
I hope this helps :)

javascript replace div on each click

The following works to replace a div with a new div...
<div id = "div1" style="display:block" onclick = "replace()"><img src="1.jpg" /></div>
<div id = "div2" style="display:none"><img src="2.jpg" /></div>
<script type = "text/javascript">
function replace() {
document.getElementById("div1").style.display="none";
document.getElementById("div2").style.display="block";
}
</script>
What I can't figure out is how to make this work so when you click div2 it is replaced by div3 and so on.
In other words, I want to replace the div on each click more than just once. What's the best way to go about this? I'm a novice, so not sure if the above is a good start or not.
Thanks!
You could make a more generic function:
function replace( hide, show ) {
document.getElementById(hide).style.display="none";
document.getElementById(show).style.display="block";
}
Then you can create many divs and use the same function:
<div id = "div1" style="display:block" onclick = "replace('div1','div2')">...</div>
<div id = "div2" style="display:none" onclick = "replace('div2','div3')">..</div>
<div id = "div3" style="display:none" onclick = "replace('div3','div4')">..</div>
...
I will suggest you some best practices in this answer:
Use classes instead of the style property, it's way nicer for the browser.
Don't use inline event handler. See the example below.
It's not "replace" you're looking for, it's "toggling".
I suggest you use event bubbling. This way, you add a single event on the container of all your div, and you can work on this.
Alright, now for the example:
HTML:
<div id="container">
<div id="div1">..</div>
<div id="div2" class="hidden">..</div>
<div id="div3" class="hidden">..</div>
</div>
JS:
// Notice how I declare an onclick event in the javascript code
document.getElementById( 'container' ).onclick = function( e ) {
// First, get the clicked element
// We have to add these lines because IE is bad.
// If you don't work with legacy browsers, the following is enough:
// var target = e.target;
var evt = e || window.event,
target = evt.target || evt.srcElement;
// Then, check if the target is what we want clicked
// For example, we don't want to bother about inner tags
// of the "div1, div2" etc.
if ( target.id.substr( 0, 3 ) === 'div' ) {
// Hide the clicked element
target.className = 'hidden';
// Now you have two ways to do what you want:
// - Either you don't care about browser compatibility and you use
// nextElementSibling to show the next element
// - Or you care, so to work around this, you can "guess" the next
// element's id, since it remains consistent
// Here are the two ways:
// First way
target.nextElementSibling.className = '';
// Second way
// Strip off the number of the id (starting at index 3)
var nextElementId = 'div' + target.id.substr( 3 );
document.getElementById( nextElementId ).className = '';
}
};
And of course, the CSS:
.hidden {
display: none;
}
I highly suggest you read the comments in the javascript code.
If you read carefully, you'll see that in modern browsers, the JS code is a matter of 5 lines. No more. To support legacy browsers, it requires 7 lines.

Categories

Resources