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/>
Related
I would like to make sure which method is the best and if my code is valid and good.
I did not succeed in renaming the text "hide contact" / "'show contact" to see the result.
.style.display = 'none'; seems a bit too brutal to me without an exit animation.
I opted for the "hide button" version
but if you know how to rename the button it will be a bonus.
I also have jerks on mobile (chrome), I can't understand why .slideToggle is not smooth everywhere.
Method 1 : not working
/* Show/hide rename button text */
jQuery(document).on('click', '#TEST_BTN', function(event) {
event.preventDefault();
$(document).ready(function(){
$("TEST_BTN").click(function(){
if ($(this).text() == 'show contact'){
$(this).html('hide contact;')
}else{
$(this).html('show contact');
}
jQuery('#hidden-content').slideToggle('250','swing','hide');
});
Method 2 : working
/* Hide show contact button */
document.addEventListener("DOMContentLoaded", function(event) {
jQuery('#TEST_BTN').click(function(){
event.preventDefault();
document.getElementById("TEST_BTN").style.display = 'none';
jQuery( '#hidden-content' ).slideToggle('250','swing','hide');
});
});
mmm click inside click for the same element?! it'll not work like this it will add another click event each time you click the element and this is what you'll get after some clicks
var i = 0;
$('button').on('click' , function(){
$('button').click(function(){
console.log(i++);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Click Inside Click</button>
Your code should looks like
/* Show/hide rename button text */
$(document).ready(function(){
$("#TEST_BTN").click(function(){
$(this).text($(this).text() == 'show contact' ? 'hide contact': 'show contact')
$('#hidden-content').slideToggle('250','swing','hide');
});
});
I prefer to use classes instead of ids in this case .. It'll much easier especially if you've more than one card .. see the next simple example
/* Show/hide rename button text */
$(document).ready(function(){
$(".TEST_BTN").click(function(){
$(this).text($(this).text().toLowerCase().trim() == 'show contact' ? 'hide contact': 'show contact')
$(this).closest('.card').find('.hidden_content').slideToggle('250','swing','hide');
});
});
.hidden_content{
display : none;
height : 100px;
background : #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
<button class="TEST_BTN">Show Contact</button>
<div class="hidden_content">Contact Info</div>
</div>
<div class="card">
<button class="TEST_BTN">Show Contact</button>
<div class="hidden_content">Contact Info</div>
</div>
<div class="card">
<button class="TEST_BTN">Show Contact</button>
<div class="hidden_content">Contact Info</div>
</div>
Note: For event.preventDefault() you need to use function(event){ event.preventDefault();
I am making an html change to a CMS that will affect all pages when the changes are live. I would like this html alert to only affect 1 specific page. I am attempting to do an if statement for the page title.
The logic is that if the page title is Test Article Two then show the html that I have put in place, if not then display=none. With this logic in place, I am viewing the html on all pages not just the one I want it to show.
<div class="container">
<div class="title-wrapper">
<span id="article-banner-country">#countryFullText</span> /
<span id="article-banner-category">#subCatText</span>
<div id="article-banner-title">#pageTitle</div>
<!--page alert -->
<div class="feedback-container content-desktop" id="alert-dialog">
<div class="feedback-left">
<p>Have any feedback? Reach out to us!</p>
</div>
<div class="feedback-right">
<button class="feedback-button">Give Feedback</button>
<button class="feedback-button">Dismiss</button>
</div>
</div>
</div>
</div>
<script>
function showAlert() {
if(#pageTitle === "Test Article Two") {
document.getElementById('alert-dialog').style.display = 'block';
}else {
document.getElementById('alert-dialog').style.display = 'none';
}
}
</script>
I'd recommend changing a class on the body element so that you can use CSS for the styling.
HTML: nothing really changed here
<body>
<div class="container">
<div class="title-wrapper">
<span id="article-banner-country">#countryFullText</span> /
<span id="article-banner-category">#subCatText</span>
<div id="article-banner-title">#pageTitle</div>
<div class="feedback-container content-desktop" id="alert-dialog">
<div class="feedback-left">
<p>Have any feedback? Reach out to us!</p>
</div>
<div class="feedback-right">
<button class="feedback-button">Give Feedback</button>
<button class="feedback-button">Dismiss</button>
</div>
</div>
</div>
</div>
</div>
</body>
javascript: just check the document.title and add the class the the body element
<script>
if(document.title === "Test Article Two") {
document.body.classList.add("show-alert");
}
</script>
Use CSS for the styling. Always hide #alert-dialog and only show it when we add the class to the body.
<style>
#alert-dialog {
display: none;
}
.show-alert #alert-dialog {
display: block;
}
</style>
If you are making static pages or using server side rendering, you could add logic to add a class to show or hide the alert element without adding more javascript to the page. It will have the relevant class(es) when the html is generated and delivered. This way you won't have to create a function, call it and manipulate the DOM after everything is rendered.
I may have missed this in the code above, are you calling the showAlert function anywhere? If not, your alert won't be shown (or will be shown depending on the default styles).
One thing I'd caution against is the imperative nature of the code here. If you wanted to reuse this alert functionality on another page, you'd have to add another more logic to detect another page title every time you wanted to use the alert. Since you are using a CMS, you might consider adding a flag to show the alert, and on this specific page, turn that flag on.
If you wanted to use the function strategy, I'd set your default alert styles:
#alert-dialog {
display: none;
}
.show {
display: block;
}
and try something like this:
<script>
function showAlert() {
if(document.title === "Test Article Two") {
document.getElementById('alert-dialog').classList.add('show');
}
}
document.addEventListener("DOMContentLoaded", showAlert);
</script>
Another alternative is to take a look at the path of the page this is supposed to be on (window.location.pathname) and using regex to see if it matches what you want. I'd recommend that over looking at the title since it's more likely the title of the page will change rather than the url.
In JavaScript, you can access the page title with document.title. You should change the script like this:
function showAlert() {
if(document.title === "Test Article Two") {
document.getElementById('alert-dialog').style.display = 'block';
} else {
document.getElementById('alert-dialog').style.display = 'none';
}
}
I am facing an issue about this.
<div id="1">
<div id="2">
</div>
<div id="3">
<div id="4">
</div>
</div>
</div>
<div id="others_div">
</div>
I want to add the class "hidden" to "1" when I click on something which is not "1" nor one of its children.
Now I am using this but I have a lack of imagination for solving this issue...
document.onclick = function(e)
{
if(e.target.id!="1")
{
$("#1").addClass("hidden");
}
}
Well, to avoid e.stopPropagation() (maybe you want that event to bubble up to some other ancestor) You can check if it is not clicked on #1 nor on it's children like this:
$('body').on('click', function(e) {
if (!((e.target.id== "1") || $(e.target).closest('#1').length)) {
$("#1").addClass("hidden");
}
});
You could use a jQuery check like the following one to check if the current element is your 1 element or traverse the DOM to see if the current target is contained within an element with an ID of 1 :
<script>
$(function(){
// Trigger this when something is clicked
$(document).click(function(e){
// Toggle the hidden class based on if the current element is 1
// or if it is contained in an element with ID of 1
$("#1").toggleClass('hidden',!((e.target.id== "1") || $(e.target).closest('#1').length))
});
});
</script>
Generally, you should avoid using ID attributes that only consists of numbers as they are not valid (ID attributes must begin with a letter). Ignoring this could result in some issues with regards to CSS or jQuery selection.
JQuery
$('body').on( "click", function(e) {
if(e.target.id !== "1")
{
$("#1").addClass("hidden");
}
});
I think you want this
// taken from http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element
$('html').click(function() {
//Hide the menus if visible
alert('hide');
});
$('#one').click(function(event){
event.stopPropagation();
});
div#one {
background: yellow;
}
div#others_div {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="one">
div one
<div id="2">
div two
</div>
<div id="3">
div three
<div id="4">
div four
</div>
</div>
</div>
<div id="others_div">
other div
</div>
i have a data table with a column like this
This is my HTML
<td class="orders-options column-invoice">
<strong>
<a class="row-title" href title="View detail">78060</a>
</strong>
<div class="locked-info"></div>
<div class="row-actions">
<span class="edit">Edit</span>
<span class="view">View</span>
</div>
</td>
I would like to show certain options like, "Edit" or "View" when user mouse over . My plan is to addclass on to so that it's visibility: changes hidden; to visible; according to CSS file.
This is my JS
$("td.orders-options").focusin(function() {
$(this).find(".row-actions").addClass('visible');
});
$("td.orders-options").focusout(function() {
$(this).find(".row-actions").removeClass('visible');
});
However this doesn't seem to have any effect on html.
Also I'm curious if this function will change class only in the that is focused or all on other that are not focused
You can use mouseover and mouseout or simple hover.
$("td.orders-options").mouseenter( function() {
$(this).find(".row-actions").addClass('visible');
}).mouseleave( function() {
$(this).find(".row-actions").removeClass('visible');
});
Also instead of visibility, toggle display property in css. Because visibility:hidden will take space though it's hidden.
In terms of hover, it will be like:
$("td.orders-options").hover( function() {
$(this).find(".row-actions").addClass('visible');
} ,function() {
$(this).find(".row-actions").removeClass('visible');
});
Update: Adding DEMO
$("td.orders-options").hover( function() {
console.log("Rias");
$(this).find(".row-actions").addClass('visible');
} ,function() {
$(this).find(".row-actions").removeClass('visible');
});
.row-actions.visible {
display: block;
}
.row-actions {
display: none;
}
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<table>
<td class="orders-options column-invoice">
<strong>
<a class="row-title" href title="View detail">78060</a>
</strong>
<div class="locked-info"></div>
<div class="row-actions">
<span class="edit">Edit</span>
<span class="view">View</span>
</div>
</td>
</table>
You should rather use .hover()..hover() method specifies two functions to run when the mouse pointer hovers over the selected elements:
$("td.orders-options").hover(function(){
$(this).find(".row-actions").addClass('visible');
},function(){
$(this).find(".row-actions").removeClass('visible');
});
Easily achieve your goal using toggelclass
$("td.orders-options").hover( function() {
$(this).find(".row-actions").toggleClass('visible');
});
I have a minimize button which sets the visibility of the selection to 'hidden'.
I also have a maximize button which sets the visibility of the selection to 'visible'.
Now I want to do this with only one button, but be able to pass through different selections to the function this button calls.
I can easily do this if I was only using the function on one object. For example, I would create a variable, say, hidden=false. Once I click the button it would check what hidden is equal to. If it is true then it would show the selection then change it to false. If it is false, it would hide the selection and change it to true.
Now I want to do this so I can pass objects through to one function and for that function to then check what the hidden value for that selection is.
I want to make a function as I want to be able to re-use this code, rather than having to do alot of if statements everytime I want to show/hide something.
What I have already.
//Pseudo code of buttons
MinimizeButton = onClick(hideThis(selection1));
MaximizeButton = onClick(ShowThis(selection1));
function hideThis(selection){
selection.classed("hidden", true);
}
function showThis(selection){
selection.classed("hidden", false);
}
.hidden{
visibility:hidden;
}
I want to be able to do this with one button rather than two as I have at the moment
I would use a class on the buttons (button.toggle) and a data attribute holding the selector of elements to modify.
function toggleBySelector() {
var target = $(this).data("selector");
$(target).toggle();
}
$("button.toggle").on("click", toggleBySelector);
.red {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div>
<button class="toggle" data-selector="#single">Toggle Single</button>
</div>
<div>
<button class="toggle" data-selector=".red">Toggle Red</button>
</div>
</div>
<div>
<div class="red">Red Div</div>
<div id="single">Single Div</div>
<div class="red">Additional Red Div</div>
</div>
This binds the template to itself (or potentially other templates), but allows you to keep your DOM and script largely separate. Each button knows what elements it should toggle, using a jQuery selector in the data-selector attribute.
Using jQuery's toggle method, you don't need to keep track of which elements are shown or hidden, it will handle that for you.
A general approach:
function generalHideOrShow(element)
{
if (element instanceof Element)
{
//single element passed
element = [element]; //mimic node list
}
if(element.length && element.length > 0 && element[0] instanceof Element)
{
//node list
for (var i = 0; i < element.length; ++i)
{
if (element[i].getAttribute("data-hidden") == "true" )
{
$(element[i]).removeClass("hidden");
element[i].setAttribute("data-hidden", false);
}
else
{
element[i].setAttribute("data-hidden", true);
$(element[i]).addClass("hidden");
}
}
}
else
{
return false;
}
}
$("#button1").click(function(){
generalHideOrShow($("div"));
});
$("#button2").click(function(){
generalHideOrShow($("span"));
});
$("#button3").click(function(){
generalHideOrShow(document.body.querySelectorAll("span:nth-child(odd)"));
});
.hidden{
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div>test div 1</div>
<div>test div 2</div>
<div>test div 3</div>
<div>test div 4</div>
<span>test span 1</span>
<span>test span 2</span>
<span>test span 3</span>
<span>test span 4</span>
<br />
<button id="button1">Click to toggle the divs</button>
<button id="button2">Click to toggle the spans</button>
<button id="button3">Click to toggle the even spans</button>
To use:
generalHideOrShow( $("divs") );
That will give an array of elements to the function.
This function will work with an element (passed with document.getElementById("element") for example), a Node list (passed with document.querySelectorAll("div") for example) and jQuery selectors.