Clone and Remove Method efficiently if possible - javascript

I hope that someone can help me please.
I need for the hidden text to be cloned and have the clone be removed regardless of the the status of the hidden text. Right now the Hidden text will show and when cloned, it produces the clone but the remove function does not work on the clone. Instead the remove function of the text that the duplicate was cloned from affects the clone. I would like for the Clone copy to hold the same events as the hidden text but independent of the status it was copied from.
I am trying to figure out how to use the cloning and remove methods with a table I am building. I have searched online with .data(array[1]) and .hide and .show. but in order for my idea to work I NEED to use the remove and clone if possible!
I APPRECIATE IT!
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script>
var count = 1;
var $clone = $(".t1").clone(true)
$(document).ready(function(){
$(".hide0").click(function(){
$(".t0").hide();
});
$(".show0").click(function(){
$(".t1 , .t0").show();
});
$(".hide1").click(function(){
$(".t1").remove();
});
$(".show1").click(function(){
if(count < 2) {
$(".t1").clone(false).appendTo("body");
count++;
}
});
});
</script>
</head>
<body>
<div class="t0">Original Text. <br /></div>
<button class="show0">Add Project</button>
<br />
<div class="t1" style="color:red; display:none;">
Hidden Text when removed, clone copy is removed and cannot be regenerated. Clone copy should hold the same events as the original but independent of the status it was copied from. <br>
<button class="show1">Add Project</button>
<button class="hide1">Remove Project</button><br /></div>
<div class="t2" style="color:blue; display:none;">
If you click on the "Hide" button, I will disappear.<br>
<button class="hide2">Remove Project</button><br /></div>
</body>
</html>

I believe your problem is how to handle events for dynamically created elements (in this case button add and remove in t1 class).
Code
$(document).on("click", ".show1", function(e) {
if ($(".t1").length < MaxRows) {
addRows();
}
});
$(document).on("click", ".hide1", function(e) {
$(this).parent(".t1").remove();
});
And the second problem is cloning elements. It will be easier if you do the following:
create a div named original
clone this original
change original class name to t1
append it to a row or container class to hold your clones
Code
function addRows() {
$(".t1-original")
.clone(false)
.removeClass("t1-original")
.addClass("t1")
.appendTo(".data-rows")
.show()
.find(".name").html(new Date().toISOString() + " <br/>");
}
var MaxRows = 3;
function addRows() {
$(".t1-original")
.clone(false)
.removeClass("t1-original")
.addClass("t1")
.appendTo(".data-rows")
.show()
.find(".name").html(new Date().toISOString() + " <br/>");
}
$(document).ready(function() {
$(".show0").click(function() {
// $(".t1 , .t0").show();
if ($(".t1").length < MaxRows) {
addRows();
}
});
// .hide0 class does not exist?
$(".hide0").click(function() {
$(".t0").hide();
});
$(document).on("click", ".show1", function(e) {
if ($(".t1").length < MaxRows) {
addRows();
}
});
$(document).on("click", ".hide1", function(e) {
$(this).parent(".t1").remove();
});
// $(".hide1").click(function() {
// $(".t1").remove();
// });
//$(".show1").click(function() {
// if (count < 3) {
// $(".t1").clone(false).appendTo("body");
//
// count++;
// }
//});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="t0">
Original Text.
<br />
</div>
<button class="show0">Add Project</button>
<br />
<div class="t1-original" style="color:red; display:none;">
<span class="name"></span> Hidden Text when removed, clone copy is removed and cannot be regenerated. Clone copy should hold the same events as the original but independent of the status it was copied from.
<br>
<button class="show1">Add Project</button>
<button class="hide1">Remove Project</button>
<br />
</div>
<div class="data-rows">
</div>
<div class="t2" style="color:blue; display:none;">
If you click on the "Hide" button, I will disappear.
<br>
<button class="hide2">Remove Project</button>
<br />
</div>

Related

Button styling bug

I want to receive information from my users using buttons, so i created two sections for that. When the user clicks a button i need it to change its style so the user will see a difference in what they clicked even when they click another button in the other section. The problem is that when another button is clicked the other section looses its style (so the user wouldn't know what he previously clicked). I pasted the html code of the part with the problem(below)
<div>
<p><strong>Network</strong></p>
<button class="btn25" onclick = "gfg_Run()">
MTN
</button>
<button class="btn25">
Glo
</button>
<button class="btn25">
9 Mobile
</button>
<button class="btn25">
Airtel
</button>
</div>
<div>
<p><strong>Data</strong></p>
<button class="btn25">
1Gb
</button>
<button class="btn25">
2Gb
</button>
<button class="btn25">
3Gb
</button>
<button class="btn25">
5Gb
</button>
<button class="btn25">
10Gb
</button>
</div>
i need it to change its style so the user will see a difference
Create a class called active and then set the buttons to use that class when the user selects them.
The problem is that when another button is clicked the other section looses its style
The issue is that you need to separate out each group. I added a class on the parent div that distinguishes the two groups: "data" or "speed". The button background will change to blue for each of the groups because it is limited to that class in the query as ".data" does here:
document.querySelectorAll('.data .btn25');
Here is an example snippet showing the basic technique.
const dataChoices = document.querySelectorAll('.data .btn25');
dataChoices.forEach(function(choice) {
choice.addEventListener('click', function() {
removeClass(dataChoices);
this.classList.add('active');
});
});
const speedChoices = document.querySelectorAll('.speed .btn25');
speedChoices.forEach(function(choice) {
choice.addEventListener('click', function() {
removeClass(speedChoices);
this.classList.add('active');
});
});
function removeClass(dataGroup) {
dataGroup.forEach(function(choice) {
choice.classList.remove('active');
});
}
.active {
background-color: lightblue;
}
div {
float: left;
margin-right: 10px;
}
<div class="data">
<p><strong>Data</strong></p>
<button id="1" class="btn25">1Gb</button>
<button id="2" class="btn25">2Gb</button>
<button id="3" class="btn25">3Gb</button>
<button id="4" class="btn25">5Gb</button>
<button id="5" class="btn25">10Gb</button>
</div>
<div class="speed">
<p><strong>Speed</strong></p>
<button id="1" class="btn25">1Mbps</button>
<button id="2" class="btn25">2Mbps</button>
<button id="3" class="btn25">3Mbps</button>
<button id="4" class="btn25">5Mbps</button>
<button id="5" class="btn25">10Mbps</button>
</div>
I have an alternate way to do this, but honestly Christopher Taleck's answer is perfectly fine as well, I just had a different conception of how to solve the problem and figured that would be informative for others facing a similar situation.
Here is a link to a JSFiddle with a working example: JSFiddle
Here is the complete code, an explanation of everything is provided below:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Button Practice</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="network-container">
<h2>Network</h2>
<button type="button" class="btn25">MTN</button>
<button type="button" class="btn25">Glo</button>
<button type="button" class="btn25">9 Mobile</button>
<button type="button" class="btn25">Airtel</button>
</div>
<div class="speed-container">
<h2>Speed</h2>
<button type="button" class="btn25">1Mbps</button>
<button type="button" class="btn25">2Mbps</button>
<button type="button" class="btn25">3Mbps</button>
<button type="button" class="btn25">5Mbps</button>
<button type="button" class="btn25">10Mbps</button>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
script.js
function ButtonContainer(element) {
this.element = element;
this.selectedButton = null;
this.element.addEventListener('click', function(e) {
if (e.target.type !== 'button') return;
if (this.selectedButton) this.selectedButton.classList.remove('active');
e.target.classList.add('active');
this.selectedButton = e.target;
});
}
const networkContainer = new ButtonContainer(document.querySelector('.network-container'));
const speedContainer = new ButtonContainer(document.querySelector('.speed-container'))
style.css
.active {
background-color: #9AD58E;
}
GENERAL CODE EXPLANATION
First, I would suggest removing this call to gfg_Run() from the .html file:
// index.html
<button class="btn25" onclick = "gfg_Run()">
And creating a separate file to hold your JS. Then, you can just link that file like so, right before the closing <body> tag (I created a file called script.js for this purpose):
// index.html
<script type="text/javascript" src="script.js"></script>
Also, I would suggest adding a descriptive class based on the type of buttons that each <div> holds, like so:
// index.html
<div class="network-container">
------ rest of the container ------
<div class="speed-container">
------ rest of the container ------
To handle the change of style on the button click, you can create a class that is added to the clicked button. I will use .active as that is a pretty common convention. This can be in a style.css file that you link from the head of the HTML document:
// style.css
.active {
background-color: #9AD58E;
}
In that script.js file, my approach would be to create a constructor function that represents the container that holds the buttons:
// script.js
function ButtonContainer(element) {
this.element = element;
this.selectedButton = null;
this.element.addEventListener('click', function(e) {
if (e.target.type !== 'button') return;
if (this.selectedButton) this.selectedButton.classList.remove('active');
e.target.classList.add('active');
this.selectedButton = e.target;
});
}
ButtonContainer CONSTRUCTOR FUNCTION EXPLANATION
We set the ButtonContainer up with two properties, element and selectedButton. element represents the DOM element which contains the buttons (in our case, a <div>), and the selectedButton represents the last <button> in this <div> that was clicked.
The eventListener will fire whenever the <div> is clicked anywhere inside it's borders. We only want to handle clicks on a <button> element within this <div>, so we exit the listener if the target of the event was not a button with the line below:
if (e.target.type !== 'button') return;
Next, we want to see of there is already a selectedButton in this <div>, and if so, we need to remove the .active class from it so we don't have two buttons in the same <div> that have colored backgrounds:
if (this.selectedButton) this.selectedButton.classList.remove('active')
Finally, we set the .active class on the <button> that triggered the event, and set the selectedButton property of this ButtonContainer object to that button, so that we can keep track of the currently selected button in this <div>:
e.target.classList.add('active');
this.selectedButton = e.target;
Then simply create two instances of the ButtonContainer that represent the <div> elements containing each group of buttons (each <div> should have a class representing the type of buttons it holds):
const networkContainer = new ButtonContainer(document.querySelector('.network-container'));
const speedContainer = new ButtonContainer(document.querySelector('.speed-container'));
In this way, you don't have to loop through the buttons and add event listeners to each, you simply allow each container to handle it's own button events. I like this approach because we seem to be treating the buttons like two separate groups, and this logically mirrors that.

Track all elements on page

I'm attempting to track events for all UI elements on a page. The page contains dynamically generated content and various frameworks / libraries. Initially I tracked elements through creating a css class "track" , then adding style "track" to tracked elements. elements are then tracked using :
$('.track').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
As content can be dynamically generated I wanted a method to track these elements also. So tried this using wildcard jQuery operator.
In this fiddle : https://jsfiddle.net/xx68trhg/37/ I'm attempting to track all elements using the jquery '*' selector.
Using jQuery '*' selector appears to fire the event for all elements of given type.
So for this case if is clicked all the click event is fired for all divs. But id is just available for div being clicked.
For the th element the click event is fired twice , what is reason for this ?
Can the source be modified that event is fired for just currently selected event ?
fiddle src :
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<th id="th">tester</th>
You can try with:
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<tr>
<td>Cols 1</td>
<td id="td">Cols 2</td>
</tr>
</table>
<p id="th">tester</p>
You may want to use event delegation to target the elements you need. Advantage is that this also works for dynamically generated elements. See code for an example of this.
// method to add/set data-attribute and value
const nClicksInit = (element, n = "0") => element.setAttribute("data-nclicked", n);
// add data-attribute to all current divs (see css for usage)
// btw: we can't use the method directly (forEach(nClicksInit))
// because that would send the forEach iterator as the value of parameter n
document.querySelectorAll("div").forEach(elem => nClicksInit(elem));
// add a click handler to the document body. You only need one handler method
// (clickHandling) to handle all click events
document.querySelector('body').addEventListener('click', clickHandling);
function clickHandling(evt) {
// evt.target is the element the event is generated
// from. Now, let's detect what was clicked. If none of the
// conditions hereafter are met, this method does nothing.
const from = evt.target;
if (/^div$/i.test(from.nodeName)) {
// aha, it's a div, let's increment the number of detected
// clicks in data-attribute
nClicksInit(from, +from.getAttribute("data-nclicked") + 1);
}
if (from.id === "addDiv") {
// allright, it's button#addDiv, so add a div element
let newElement = document.createElement("div");
newElement.innerHTML = "My clicks are also tracked ;)";
const otherDivs = document.querySelectorAll("div");
otherDivs[otherDivs.length-1].after(newElement);
nClicksInit(newElement);
}
}
body {
font: 12px/15px normal verdana, arial;
margin: 2em;
}
div {
cursor:pointer;
}
div:hover {
color: red;
}
div:hover:before {
content: '['attr(data-nclicked)' click(s) detected] ';
color: green;
}
#addDiv:hover:after {
content: " and see what happens";
}
<div id="1">
Click me and see if clicks are tracked
</div>
<div id="2">
Click me and see if clicks are tracked
</div>
<div id="3">
Click me and see if clicks are tracked
</div>
<p>
<button id="addDiv">Add a div</button>
</p>
<h3 id="th">No events are tracked here, so clicking doesn't do anything</h3>
You can invoke the stopPropagation and the condition this === e.currentTarget to ensure invoke the handler function of the event source DOM.
And you must know the <th> tag must wrapped by <table>, otherwise it will not be rendered.
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function(e) {
if (this === e.currentTarget) {
e.stopPropagation();
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<th id="th">tester</th>
</table>

Hide/show child element onClick

I am building a "edit profile" page.
Here is what I want to do:
In each section, the employer will be shown and the edit form will be hidden.
When I click the "edit employer" button, the edit form will be shown and the employer will be hidden.
Here is what I did using jQuery. It does not work when I click on the "edit employer" button. I do not know why this does not work.
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<div class="edit">
<form class="editForm">
employer: <input type="text" value="Citigroup" />
</form>
<div class="contents">Employer: Citigroup</div>
<button class="editButton">Edit Employer</button>
</div>
<script>
$('div.edit').each(function(i) {
$(this).children('.editForm').hide();
})
$('div.edit').each(function() {
$(this).children('.editButton').click(function() {
$(this).children('.editForm').show();
$(this).children('.contents').hide();
});
})
</script>
</body>
</html>
The $(this) inside the click function contains the local instance of the $(this).children('.editButton'). For that reason your code is not finding any .editForm elements.
For this to work you could do something like this:
<script>
$('div.edit').each(function(i) {
$(this).children('.editForm').hide();
})
$('div.edit').each(function() {
var $this = $(this);
$(this).children('.editButton').click(function() {
$this.children('.editForm').show();
$this.children('.contents').hide();
});
})
</script>
If I may I would improve the code with some more changes:
<script>
$('.edit .editForm').hide(); // this will hide all instances of .editForm
$('.edit .editButton').click(function() { //assign 1 handler for all cases
$(this).siblings('.editForm').show(); // show the sibling edit form
$(this).siblings('.contents').hide(); // hide the sibling contents element
});
</script>
Reference:
Sibling Selector: https://api.jquery.com/siblings/#siblings-selector
The problem is the this inside the click handler referring to the button, not the div.edit. Here's one way to fix this:
$('div.edit').each(function(i) {
$(this).children('.editForm').hide();
});
$('div.edit').each(function() {
var $self = $(this);
$(this).children('.editButton').click(function() {
$self.children('.editForm').show();
$self.children('.contents').hide();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="edit">
<form class="editForm">
employer:
<input type="text" value="Citigroup" />
</form>
<div class="contents">Employer: Citigroup</div>
<button class="editButton">Edit Employer</button>
</div>
You don't need to use .each() at all. Just do an .click() event on the class of .editButton and use this to find its parent. If you want to make a toggle, you're going to have to make use of a new class or something of that nature to make a conditional statement off of.
//This will hide *ANY* .editForm elements
$('.editForm').hide();
//This will fire off of *ANY* editButton clicks.
$('.editButton').click(function() {
var form = $(this).closest('.edit'); //Get the wrapper
if(form.hasClass('open')) { //Check to see if it is open or not
form.removeClass('open').addClass('close'); //Toggle Classes
form.find('.editForm').show();
form.find('.contents').hide();
} else {
form.removeClass('close').addClass('open');
form.find('.editForm').hide();
form.find('.contents').show();
}
});
I like to use closest and find more than parent and children (respectively). They can go 1-many layers up or down and search the hierarchy for whatever you're looking for, rather than parent and children going up or down a single layer.
If you are inserting your .edit form after the DOM loads, you're going to need to bind your click event to the document
$(document).on('click', '.editButton', function() {
var form = $(this).closest('.edit');
form.find('.editForm').hide();
form.find('.contents').show();
});

If HTML text equals value, onclick change

Okay, I have tried a few ways of doing this but nothing has worked. I am hoping someone here can tell me what I am doing wrong. Below is a step-by-step of what I am trying to achieve.
#info-NUMBER-btn displays Click to display more information.
#info-NUMBER CSS is set to display: none.
When #info-NUMBER-btn is clicked:
- Corresponding #info-NUMBER-btn displays Click to display less information.
- Corresponding #info-NUMBER CSS is set to display: inline-block.
/* Jquery */
$(document).ready(function() {
$("#info-1-btn").text("Click to display more information");
$("#info-2-btn").text("Click to display more information");
$("#info-3-btn").text("Click to display more information");
$("#info-4-btn").text("Click to display more information");
$("#info-5-btn").text("Click to display more information");
if($("#info-1-btn").text("Click to display more information")) {
$("#info-1-btn").click(function () {
$(this).text("Click to display less information");
$("#info-1").css("display", "inline-block");
});
} else if($("#info-1").text("Click to display less information")) {
$("#info-1-btn").click(function() {
$(this).text("Click to display more information");
$("#info-1").css("display", "none");
});
}
if($("#info-2-btn").text("Click to display more information")) {
$("#info-2-btn").click(function () {
$(this).text("Click to display less information");
$("#info-2").css("display", "inline-block");
});
} else {
$("#info-2-btn").click(function() {
$(this).text("Click to display more information");
$("#info-2").css("display", "none");
});
}
if($("#info-5-btn").text("Click to display more information")) {
$("#info-5-btn").click(function () {
$(this).text("Click to display less information");
$("#info-5").css("display", "inline-block");
});
} else {
$("#info-5-btn").click(function() {
$(this).text("Click to display more information");
$("#info-5").css("display", "none");
});
}
});
<!-- HTML -->
<div id="info-5" class="hire-equipment-more-information">
<table class="hire-equipment-more-information-table" cellpadding="15px">
<tr>
<th>Length:</th>
<th>Material:</th>
<th>HP:</th>
</tr>
<tr>
<td>7.5m</td>
<td>Aluminium</td>
<td>225</td>
</tr>
</table>
</div>
<br />
<a id="info-5-btn" class="hire-equipment-item-link"></a>
You could make it a lot more easy for yourself, by binding not to the element id's, but to use your class hire-equipment.
This way you don't have to bind to 5 different buttons that in essence do the same thing.
Once you hit the eventHandler, you can use the first argument of the function, to check from which button you are coming and take the appropriate action.
As an example, I just created the 5 elements, and 1 event handler.
The $(selector).click() will bind to all elements sharing the selector ( in my case hire-equipment), and then, it will check from which button it's coming, select the parent node (the div surrounding the button, title and description), search the description element, and toggle it's hidden class. The buttons text will then change depending on it's text.
It's not fully how your example is built, but it's an example of making your event handlers a bit more generic.
$('.hire-equipment').click(function(event) {
var sourceElement = $(event.target);
$(sourceElement).parent().find('.description').toggleClass('hidden');
if ($(sourceElement).text() === 'Show more information') {
$(sourceElement).text('Show less information');
} else {
$(sourceElement).text('Show more information');
}
});
.hidden {
display: none;
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<p class="title">Title of item</p>
<div class="description hidden">This is a description</div>
<button type="button" class="hire-equipment">Show more information</button>
</div>
<div>
<p class="title">Title of item</p>
<div class="description hidden">This is a description</div>
<button type="button" class="hire-equipment">Show more information</button>
</div>
<div>
<p class="title">Title of item</p>
<div class="description hidden">This is a description</div>
<button type="button" class="hire-equipment">Show more information</button>
</div>
<div>
<p class="title">Title of item</p>
<div class="description hidden">This is a description</div>
<button type="button" class="hire-equipment">Show more information</button>
</div>
Lets examine this line of code
if($("#info-1-btn").text("Click to display more information")) {
This should be:
if($("#info-1-btn").text() === "Click to display more information")) {
The text function is an overloaded function. If you pass in no value, it will return you the text inside the element.
If you pass in a value, it will modify the text, and return the jQuery object again (which will be a truthy value).
Now lets look at your overall logic.
Your code is testing the state of the buttons once, when the document loads. It should be testing the state of the button as part of the click handler.
See this complete code example: http://plnkr.co/edit/HLsLcKrRY3OqK6w44bXp?p=preview
It might not match your requirements exactly, but it demonstrates how you test the state of the button inside a click handler.
It also demonstrates how you can use a custom attribute (in this case, data-target) to link a button to a div block.
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
</head>
<body>
<button class="toggleButton" data-target="buttonOneInfo"></button>
<br />
<div class="toggleTarget" id="buttonOneInfo">
Here's some information about the first item
</div>
<button class="toggleButton" data-target="buttonTwoInfo"></button>
<br />
<div class="toggleTarget" id="buttonTwoInfo">
Here's some information about the second item
</div>
<button class="toggleButton" data-target="buttonThreeInfo"></button>
<br />
<div class="toggleTarget" id="buttonThreeInfo">
Here's some information about the third item
</div>
</body>
<script type="text/javascript">
$(function() {
$('.toggleTarget').hide();
$(".toggleButton")
.text("Click to display more information")
.click(function() {
var toggleTargetId = $(this).attr('data-target');
var toggleTarget = $(document.getElementById(toggleTargetId));
if ($(this).text() === 'Click to display more information') {
$(this).text('Click to display less information');
toggleTarget.show();
} else {
$(this).text('Click to display more information');
toggleTarget.hide();
}
});
});
</script>
</html>
Trimmed the fat off of OP's jQuery. The following procedure is roughly outlined here:
Primary method used is toggleClass()
At least 2 classes are required to indicate a state of .info-btn
The big advantage of using classes is that you can add more styles to each class that would enhance .info-btn's state. ex. color, background-color
Further details are commented in the source of the Snippet below:
SNIPPET
/* jQuery */
// Alternate styntax for $(document).ready(
$(function() {
// Click on ANYTHING with the class .info-btn
$(".info-btn").on("click", function(e) {
// Prevent .info-btn from jumping when clicked
e.preventDefault();
/* `this` or .info-btn will toggle between the
| classes of .more and .less
| See CSS for details of expected behavior of
| .info-btn in both states
*/
$(this).toggleClass('more less');
});
});
.info-btn {
cursor: pointer;
}
/* Both classes use the :after pseudo-selector
| The value of content will complete the
| string: "Click to display"...
*/
a.more:after {
content: ' more information';
}
a.less:after {
content: ' less information';
}
button.less:before {
content: 'less ';
}
button.less:after {
content: ' more';
}
button.more:before {
content: 'more ';
}
button.more:after {
content: ' less';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- HTML -->
<div id="info-5" class="rental-info">
<table class="rental-info-table" cellpadding="15px">
<tr>
<th>Length:</th>
<th>Material:</th>
<th>HP:</th>
</tr>
<tr>
<td>7.5m</td>
<td>Aluminium</td>
<td>225</td>
</tr>
</table>
</div>
<br />
<a class="info-btn rental-link more">Click to display</a>
<br/>
<button class='info-btn less'>is</button>
<br/>

How to add/append and toggle items to the div on every click of an link in jquery?

I am having the div like below..
<div id="div1">Edit your content
<a id="link1" href="#">click to Edit</a>
<textarea id="text1" cols="3"/>
<input type="button" id="button1" value="Save" />
</div>
What i want is..
I want to show and hide the textarea and save button every time the link is clicked.
And when an save button clicked the textarea content has to be added before the textarea as listitem, every time the save button clicked the edited text has been updated into that list.
Please anyone guide me to do this..
The simples approach would be if the Edit your content part could be wrapped in a container of its own, so that the content of that container could be replaced entirely upon save:
<div id="div1">
<span class="content">Edit your content</span>
<a id="link1" href="#">click to Edit</a>
<textarea id="text1" cols="3"></textarea>
<input type="button" id="button1" value="Save" />
</div>
$('#div1 > a').click(function() {
var parent = $(this).closest('div');
parent.find('textarea').val(parent.find('.content').html());
parent.find(':input, .content, a').toggle();
});
$('#div1 > input[type=button]').click(function() {
var parent = $(this).closest('div');
parent.find('.content').html(parent.find('textarea').val());
parent.find(':input, .content, a').toggle();
});
Demo
You'll note that the declaration of parent could easily be replaced with #div1 in this particular example, but with this code, you could easily change the #div1 > a selector to one that matches several elements (i.e. .editable > a; demo)
Edit
It appears I misread your question the first time around, but the changes aren't all that big.
Rather than setting the textbox to the value of your .content, you would clear it each time you're showing it. Also, you might not want to hide the .content each time the edit link is clicked. At the click of the save button, you create a new element, and append that after the last .content, rather than updating the existing one.
$('#div1 > a').click(function() {
var parent = $(this).closest('div');
parent.find('textarea').val('');
parent.find(':input, a').toggle();
});
$('#div1 > input[type=button]').click(function() {
var parent = $(this).closest('div');
$('<div/>', { 'class': 'content' })
.html(parent.find('textarea').val())
.insertAfter(parent.find('.content:last'));
parent.find(':input, a').toggle();
});​
Note that I've changed .content to a div, because of its block-level behavior. This should of course be reflected in the initial markup as well.
Demo
Edit (2)
To account for your question in comments, about adding the textarea and save button upon link click, you'd have to make a few changes. First of all, the link click listener would have to be updated with code to add the elements, and presumably with a first check to see whether or not they exist already (i.e. second click of link button):
$('#div1 > a').click(function() {
var parent = $(this).closest('div');
var txt = parent.find('textarea');
if(txt.length == 0) {
txt = $('<textarea/>', { id: 'text1', cols: 3 });
txt.appendTo('#div1');
$('<input />', { type: 'button', id: 'button1' }).val('Save').appendTo('#div1');
}
txt.val('');
parent.find(':input, a').toggle();
});
Second, your listener $('#div1 > input[type=button]') will no longer work exactly as written, because there is no such button in the document at the time when the selector is evaluated. To fix this, you could either use a live delegate, such as:
$('#div1').on('click', 'input[type=button]', function() { ... });
Demo. (for earlier jQuery versions, use .delegate(selector, event, handler) rather than .on(event, selector, handler).)
... Or, you could add the listener immediately to the button as you're creating it:
$('<input />', { type: 'button', id: 'button1' })
.val('Save')
.appendTo('#div1')
.click(saveEdit);
Demo
As a bonus, I'm adding focus to the textbox after showing it in these demos. You may want that as well.
you can do it like this
HTML
<div id="div1">Edit your content
<a id="link1" href="#">click to Edit</a>
<ul id="NewElement"></ul>
<textarea id="text1" cols="3" style="display:none;"></textarea>
<input type="button" id="button1" value="Save" />
</div>​
Jscript
$('#link1')​.click(function(){
$('#text1').toggle();
});
$('#button1').click(function(){
$('#NewElement').append('<li>' + $('#text1').val() +'</li>');
});
Live Demo
​
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#link1').click(function(){
$('#some').toggle();
});
$('#button1').click(function(){
$('ul').append('<li>'+$('#text1').val()+'</li>');
})
})
</script>
</head>
<div id="div1">Edit your content
<a id="link1" href="#">click to Edit</a>
<ul></ul>
<div id="some">
<textarea id="text1" cols="3"/></textarea>
<input type="button" id="button1" value="Save" />
</div>
</div>

Categories