Toggle Text between multiple buttons - html

I would like to have two buttons which are basically categories. Let's name them category A and category B. The are displayed left and right. Below i would like to display some text which is dependent of the chosen category (i.e the clicked button) so that category A shows text A and category B shows text B.
This if for html. I'm working on a wordpress homepage.
I was able to install one button which toggles text (basically button 1 = Category A). But i couldn't manage to insert a second button (basically button 2 = Category B). Any ideas? Highly appreciated!
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Click the button to swap the text of the DIV element:</p>
<p><button onclick="myFunction()">Click Me</button></p>
<div id="myDIV">Hello</div>
<script>
function myFunction() {
var x = document.getElementById("myDIV");
if (x.innerHTML === "Hello") {
x.innerHTML = "Swapped text!";
} else {
x.innerHTML = "Hello";
}
}
</script>
</body>
</html>
I expect to have 2 buttons which display 2 categories, the text should toggle according to which button has been clicked.

Could put the description in an attribute, then get the attributes value on click and change the html of the description. Here is a jsFiddle
<div>
<button class="js-button default-button" data-description="Category A's Description" onclick="myFunction(this)">
Category A
</button>
<button class="js-button default-button" data-description="Category B's Description" onclick="myFunction(this)">
Category B
</button>
</div>
<div id="js-description" class="description">
</div>
<script>
function myFunction(elem) {
var x = document.getElementById("js-description");
var description = elem.getAttribute('data-description');
x.innerHTML = description;
var button = document.getElementsByClassName('js-button');
for (var i = 0; i < button.length; i++) {
button[i].classList.remove('active-button');
}
elem.classList.add('active-button');
}
</script>
<style>
.default-button{
font-size:16px;
border-radius: 4px;
padding:7px 12px;
}
.active-button{
background:blue;
color:#fff;
}
.description{
margin-top:20px;
}
</style>

I don't really like all these solutions because everything is written from JS but contents probably come from database. So here is my solution :
// Native JS version
// Working Fiddle : https://jsfiddle.net/d34cbtw7/
var togglers = document.querySelectorAll('[data-toggle="tab"]');
for (var i = 0; i < togglers.length; i++) {
togglers[i].addEventListener('click', function() {
var tabs = document.querySelectorAll('.tab');
for(var j = 0; j < tabs.length; j++) {
tabs[j].classList.remove('active');
}
var $target = document.querySelector(this.getAttribute('data-target'));
$target.classList.add('active');
});
}
// jQuery version
$('body').on('click', '[data-toggle="tab"]', function(e) {
e.preventDefault();
// Select our target
var $target = $($(this).data('target'));
// Hide all tabs
$('.tab-contents .tab').removeClass('active');
// Show only $target tab
$target.addClass('active');
});
.tab-contents .tab {
display: none;
}
.tab-contents .tab.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button data-toggle="tab" data-target="#cat-A-content">
Cat A
</button>
<button data-toggle="tab" data-target="#cat-B-content">
Cat B
</button>
<div class="tab-contents">
<div class="tab active" id="cat-A-content">
My category A contents
</div>
<div class="tab" id="cat-B-content">
My category B contents
</div>
</div>
I also don't really like "onclick" attribute in HTML...

I've made a quick codepen as example.
You can achieve this by passing a parameter to the onClick function. In this example I keep track of the last button clicked, and the text it should render. If the last button clicked was the same button, the switched back to default. I hope this helps.
https://codepen.io/maffekill/pen/rbpjzw
HTML
<p>Click the button to swap the text of the DIV element:</p>
<p><button onclick="myFunction(1, 'TEXT A')">TEXT A</button></p>
<p><button onclick="myFunction(2, 'TEXT B')">TEXT B</button></p>
<div id="myDIV">Default Text</div>
JS
// Keep track of the button currently clicked
var activeBtn = null;
function myFunction(btnId, text) {
var x = document.getElementById("myDIV");
// If the last button is the same as the new one, show default text
if (activeBtn === btnId) {
x.innerHTML = "Default Text";
activeBtn = null
} else {
// Else show the text given to the text param
x.innerHTML = text;
activeBtn = btnId;
}
}

There are multiple ways to achieve this, but the easiest way I could come up with to explain this to you would be as following:
function myFunction(myEle) {
var x = document.getElementById("myDIV");
x.innerHTML = "This is category " + myEle.value;
}
<p>Click the button to swap the text of the DIV element:</p>
<p>
<button onclick="myFunction(this)" value="a">
Category A
</button>
<button onclick="myFunction(this)" value="b">
Category B
</button>
</p>
<div id="myDIV">Hello</div>
JSFiddle
No need to overcomplicate things.
Firstly you would like to send the clicked element from the caller (which in this case would be the clicked element as well, the <button> element). You could use JavaScript's thisfor this purpose.
Within your function you can name a parameter between parenthesis, so in my example above: function myFunction() contains a parameter called myEle so it will look like: function myFunction(myEle). Once the function will be triggered, the parameter called myEle will be set to the clicked element (or
JavaScript's this). You can simply access any of its attributes like value by using a dot: myEle.value.
Knowing the above, you could apply it to whatever you require your function to do (refer to my example code above).

Related

icon not clickable with onclick event

The onclick event only works with the button. If I click on the icon in the button the function does not work.
enter code here
<div class="dropdown">
<button onclick="myFunction()" class="elementor-button-link elementor-button elementor-size-md elementor-animation-grow" id="dropbtn">
<i onclick="myFunction() "class="far fa-arrow-alt-circle-down">
<script>/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('#dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
enter code here
Short answer: Try using element.closest() instead of element.matches().
I suspect it's the condition in your if statement. By the looks of it, element.matches() will match exactly the ID provided - I.e., it'll match if the element clicked on has that ID, but not if you click on a child element that does not explicitly have the ID, even if the parent does.
According to Mozilla web docs, element.closest() should also match any elements whose parents match the condition provided, even if the element itself doesn't.
Bear in mind this will change the type of the returned value - matches() returns a boolean, while closest() returns the 'closest' element matching the condition.

HTML multiple pages on same file

i managed to do 2 pages on same file but when i try 3 with this same technique it doesn't work.
<script>
function show(shown, hidden, hidden) {
document.getElementById(shown).style.display='block';
document.getElementById(hidden).style.display='none';
document.getElementById(hidden).style.display='none';
}
</script>
BMI-laskuri
Now this button shows content of Page 1 and 2 on same page but not the 3rd. I would like it to show only Page 2.
The pages are divs like this: (except page1 doest have display:none)
<div id="Page2" style="display:none">
I think the issue is that you have two parameters with the same name in your function which means when you refer to them it will only use the first instance of it.
If you change the names slightly, like I have below, I think you should be sorted.
function show(shown, hidden1, hidden2) {
document.getElementById(shown).style.display='block';
document.getElementById(hidden1).style.display='none';
document.getElementById(hidden2).style.display='none';
}
I actually just created a site like this yesterday, and I've created many in the past (the most simple of them being this one: http://oops-studio.com/twinsremasteredobstaclecreator/helppage/)
How I usually do it is to just make every page a div which is a massive container for everything on the page, and then give it a class like page or something.
Then you can create a function like changePageTo(index) and have that loop through every page and set its style.display = "none"; then taking the target page and style.display = "block";
An example would be like so:
let pages = document.getElementsByClassName("page");
function changePageTo(index){
for(let i = 0;i < pages.length;i++){
pages[i].style.display = "none";
}
pages[index].style.display = "block";
}
You could also display pages using assigned names if you'd like, rather than indexes. How I would usually do that is just like so:
let pages = document.getElementsByClassName("page");
let pageNames = ["Cookies","Another page","The last page"];// One name per page element
function changePageTo(name){
let index = pageNames.indexOf(name);
if(index === -1){// If the page doesn't exist
// Do whatever you want in here
return;
}
for(let i = 0;i < pages.length;i++){
pages[i].style.display = "none";
}
pages[index].style.display = "block";
}
Hope this answers your question!
Here's a working example:
let pages = document.getElementsByClassName("page");
function changePageTo(index){
for(let i = 0;i < pages.length;i++){
pages[i].style.display = "none";
}
pages[index].style.display = "block";
}
changePageTo(0);
<div class = "page">
<h1>This is page one. It's titled "Cookies"</h1>
</div>
<div class = "page">
<h1>This is page two. It's titled "Another page"</h1>
</div>
<div class = "page">
<h1>This is page three. It's titled "The last page"</h1>
</div>
<button onclick = "changePageTo(0)">Show page 1</button>
<button onclick = "changePageTo(1)">Show page 2</button>
<button onclick = "changePageTo(2)">Show page 3</button>

How to make a button pattern?

I'm trying to make a little puzzle game in HTML5 and I'm having trouble figuring out how to make a puzzle. In the puzzle you have to click the squares in a certain order to beat it. I don't know how to make it to where you have to click the buttons in order and if you don't you'll lose.
<!DOCTYPE html>
<html>
<head>
<title>Room Two</title>
<link rel="stylesheet" type="text/css" href="youtubeGame.css">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Tangerine|Inconsolata|Droid+Sans|Oxygen|Ubuntu|Coming+Soon">
</head>
<body>
<div id="content">
<h1 id="roomNum">Room 2</h1>
<p id="roomInfo">Once again the door seems to magically close behind
you.<br /> Unlike the stone floor from the previous room, this one is divided up
into wooden slabs.<br /> You press your foot onto a slab. It slides down, and an
arrrow shoots from the roof.<br /> You barely get out of the way but somehow you
dodge it. You tell yourself to watch your step...</p>
<p id="step"></p>
<p id="step2"></p>
<div class="menu-container" id="puzzle">
<div class="button-container">
1
2
3
4
5
6
7
8
9
</div>
</div>
</div>
<br><br>
<div id="death">
Try Again?
</div>
Next Room
<script type="text/javascript">
document.getElementById("death").style.display = "none";
document.getElementById("nextRoom").style.display = "none";
function correctStep1() {
return true;
}
function correctStep2() {
return true;
}
function correctStep3() {
return true;
}
function correctStep4() {
return true;
}
function correctStep5() {
return true;
}
function correctStep6() {
return true;
}
function correctStep7() {
return true;
}
function wrongStep() {
document.getElementById("content").style.display = "none;"
document.getElementById("puzzle").style.display = "none";
document.getElementById("death").style.display = "block";
document.getElementById("roomNum").innerHTML = "You Have
Died";
document.getElementById("roomInfo").style.display = "none";
}
</script>
</body>
</html>
Please help me fix this
A very simple way would be to save the correct order in an array and if the user clicks, increment a clickcounter and check if the clicked button is at this position in the array:
var state = {
clickedButtons:[]
};
var correctClickSettings = {
order:[7,8,9,6,5,2,3],
resetOn:7 // order has 7 elements, so the user have to click 7 buttons, after that it will be checked and the clicked buttons will be resolved or rejected
};
// called from every button that can be clicked to solve the game
function onClick(evt) {
evt = evt || window.event;
var sourceButtonText = this.innerText;
state.clickedButtons.push(sourceButtonText);
if(state.clickedButtons.length >= correctClickSettings.resetOn) {
var distanceBetweenArrays = state.clickedButtons.reduce((cur,val,idx)=>cur+Math.abs(val-correctClickSettings.order[idx]),0);
if(distanceBetweenArrays > 0) {
wrongStep();
state.clickedButtons = [];
} else {
alert('This was right!');
}
}
}
This solution has one problem: Everybody with a little bit of understanding for javascript can open the webpage and read out the solution. So if you want to do it a little better (not so easaly cheatable) you have to use another solution:
You can use a hash instead of an array of button clicks as correct order:
function simpleHash(currentHash, idx, sourceButtonText) {
currentHash = currentHash*137+parseInt(sourceButtonText,10);
}
Now simply calculate the correct solution value: 46672273550408 (in your case)
Now with every button click calculate the next hash and compare it after 7 steps with the solution.
This is a very similar approach to your current implementation, however uses attributes to declare the order of the options. It also does the binding of the events directly through javascript.
var options = [];
var expected = 0;
document.querySelectorAll('.button').forEach((button, index)=>{
options.push({
button: button,
order: button.getAttribute('order'),
index: index,
clicked: false
});
button.addEventListener('click',onClick);
//console.log(options[options.length-1]);
});
function onClick(event){
let order = parseInt(event.currentTarget.getAttribute('order'));
if(order == expected){
expected++;
options[order].clicked = true;
console.log(options[order]);
}
}
<div id="content">
<h1 id="roomNum">Room 2</h1>
<p id="roomInfo">Once again the door seems to magically close behind you.
<br /> Unlike the stone floor from the previous room, this one is divided up into wooden slabs.<br /> You press your foot onto a slab. It slides down, and an arrrow shoots from the roof.<br /> You barely get out of the way but somehow you dodge it.
You tell yourself to watch your step...</p>
<p id="step"></p>
<p id="step2"></p>
<div class="menu-container" id="puzzle">
<div class="button-container">
1
2
3
4
5
6
7
8
9
</div>
</div>
</div>
<br><br>
<div id="death">
Try Again?
</div>
Next Room

multistep form - toggle between styled radio buttons

i have built a multi step form that works , but it is not very "elegant" coded,
so i am asking
for your advice to make it more efficient ,
i have placed here only 2 steps out of 3 because the first step - email name etc', is not relevant for my question:
in each step 2 and 3 there are 2 styled radio button yes and no for the user to select,
in each step i need to toggle between check and uncheck styled images and of course prevnt that both
yes and no check images will show at the same time.
i know that the default/not styled radio buttons behavior prevents two checked buttons at the same time- can i use it here to save some lines of code?
the html(index.php)
<form method="post" id="userForm" action="process_form.php">
<fieldset class="formFieldset">
<div id="second_step" class="vanish">
<div class="form slide_two check_wrap">
<div class="quizyes quizbtn">
<img class="uncheck_pic pic one" src="images/check_not.png">
<img class="check_pic pic agree" src="images/check_bgfull.png" style="display: none;">
<h1 class="quizText">yes</h1>
</div>
<div class="quizno quizbtn">
<img class="uncheck_pic pic two" src="images/check_not.png">
<img class="check_pic not not_agree pic first_not" src="images/check_bgfull.png" style="display: none;">
<h1 class="quizText">no</h1>
</div>
<div id="feedback_wrap"><div class="feedback"></div></div>
<div id="submit_wrap" >
<input type="radio" class="yep decideOne" val ="1" name="yep" style="display: none;"/>
<input type="radio" class="nope decideOne" val ="2" name="nope" style="display: none;"/>
</div>
</div></div>
<!-- end of second step -->
<!-- third step -->
<div id="third_step" class="vanish">
<div class="form check_wrap">
<div class="quizyes quizbtn">
<img class="uncheck_pic pic one" src="images/check_not.png">
<img class="check_pic pic agree" src="images/check_bgfull.png" style="display: none;">
<h1 class="quizText">yes</h1>
</div>
<div class="quizno quizbtn">
<img class="uncheck_pic pic two" src="images/check_not.png">
<img class="check_pic not not_agree pic second_not" src="images/check_bgfull.png" style="display: none;">
<h1 class="quizText">no</h1>
</div>
<div id="feedback_wrap"><div class="feedback"></div></div>
<div id="submit_wrap">
<input type="radio" class="yep decideTwo" val ="1" name="yep" style="display: none;"/>
<input type="radio" class="nope decideTwo" val ="2" name="nope" style="display: none;"/>
</div>
</div></div>
<!-- end of third step -->
</fieldset>
<div id="submit_wrap">
<input class="submit btn" type="button" name="submit_all" id="submit_all" value="" />
</div>
</form>
the script
$(document).ready(function(){
$(function() {
$('.check_pic').hide();
//original field values
var isDecide= false;
//toggle images and set values
$('.pic').on('click', function(event) {
if ($(this).hasClass('uncheck_pic') && $(this).hasClass('one') ){
$(".yep").val('agree');
$(this).hide();
$(this).siblings('.check_pic').show();
$(".not").hide();
$(".two").show();
}
else if ($(this).hasClass('uncheck_pic') && $(this).hasClass('two') ){
var isDecide = $(".nope").val('notagree');
$(this).hide();
$(this).siblings('.check_pic').show();
$('.agree').hide();
$(".one").show();
}
else if ($(this).hasClass('check_pic') && $(this).hasClass('agree') ){
$(this).hide();
$(this).siblings('.uncheck_pic').show();
}
else if ($(this).hasClass('check_pic') && $(this).hasClass('not_agree') ){
$(this).hide();
$(this).siblings('.uncheck_pic').show();
}
});
// start the submit thing
$('#submit_all').click(function() {
if($('#second_step').is(":visible")) {
$('.decideOne').removeClass('error valid');
// prevent empty boxes and display a message
if($('.one').is(":visible") && $('.two').is(":visible")) {
$('.feedback').text('please select one').show();
return false;
}
// case the user selects yes
if($('.agree').is(":visible")) {
$('.feedback').text('thank you for selecting yes').show();
var isDecide = $(".yep").val();
var name = $("#firstname").val();
var phone = $("#phone").val();
var email = $("#email").val();
var dataString = 'user-details:name=' + name + ' phone=' + phone + ' email=' + email + ' decide=' + isDecide ;
$.ajax({
type : "POST",
url : "/",
data: dataString,
success : function(data) {
console.log('data');
$('#second_step').delay(1000).fadeOut(600, function() {
$('#first_step').fadeIn(400);
$('.feedback').hide();
});
}
});
}
// case the user selects no
if($('.first_not').is(":visible")) {
$(".yep").val();
$(".nope").val();
$('#second_step').fadeOut(600, function() {
$('#third_step').fadeIn(600);
$('.feedback').hide();
});
}
return false;
// end second step
} else if($('#third_step').is(":visible")) {
$('.third_input').removeClass('error').removeClass('valid');
// prevent empty boxes and display a message
if($('.quizyes .one').is(":visible") && $('.quizno .two').is(":visible")) {
$('.feedback').text('please select one').show();
return false;
}
// if decide yes then submit
if($('.agree').is(":visible")) {
$('.feedback').text('thank you for selecting yes').show();
var isDecide = $(".yep").val();
var name = $("#firstname").val();
var phone = $("#phone").val();
var email = $("#email").val();
var dataString = 'user-details:name=' + name + ' phone=' + phone + ' email=' + email + ' decide=' + isDecide ;
$.ajax({
type : "POST",
url : "/",
data: dataString,
success : function(data) {
console.log('data');
$('#second_step').delay(1000).fadeOut(600, function() {
$('#first_step').fadeIn(400);
$('.feedback').hide();
});
}
});//end ajax
return true;
}//end if agree is visible
// if decide no then send message and quit
if($(".second_not").is(":visible")) {
$(".nope").val("no");
$('.feedback').text('too bad bye bye').show();
$('#third_step').fadeOut(3000, function() {
$('#first_step').fadeIn(600);
$('.feedback').hide();
});
}
}
// end third step
});
//end submit_all
}) // general function
}); // document ready
Dude my wish to you take a look on good js library - knockout to represants all that kind show, hide functunality and forms inputs, checkbox, radiobutton modifications.
If you're using images to style your radiobuttons I would suggest combining the images into a Sprite and just using css to move the background-position of the image using the input[type=radio]:checked selector. No javascript necessary.
For Example - you combine your two images into a single image that is 100px wide, each individual image being 50px wide. And then style the checkbox...
input[type=radio].myCustomRadioButton {
background: url(myRadioButtonSprite.png) 0 0;
}
input[type=radio].myCustomRadioButton:checked {
background-position: -50px 0;
}
Assuming your images are lined up horizontally in your sprite, this would move the background image of the radiobutton left 50px to display the checked-image, when the radiobutton is checked.
As a side note, doing this is going to require unsetting some of the browser styling that is going to occur automatically. A good reset for form elements is to start with these styles.
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
Keep in mind if you need to support Internet Explorer versions less than 9, the :checked pseudo-selector isn't available in pure CSS and you may need to resort to some scripting.
Listen for the change event on your custom radio buttons and update a parent element based on that.
Here's an example.
The <input> has position: absolute so the clip property can be applied to hide it and it does not affect the content box of its parent, which has relative position to contain it.
I used background-color but you could swap this in for your image urls or change the background-position of a sprite as suggested in rob-gordon's answer.
You can still add visible label text inside the label as you see in the second set of radio inputs.

highlight word in div using javascript

hi i have to implement find and replace functionality in my project. in this functionality there is one find and replace button on the top of contenteditable div. when user click on this button, popup window will open and ask for the search word when specify word and press find it will find word in that div only. and if match found it will highlight that word. so anybody tell me how can i highlight word in div. its urgent so please . thank you.
<div id="test" contenteditable="true">
this is test <font class='classname'> some text test</font>
</div>
i want to high light only test word not else
You will need to search through the div to find the word and then put that word into a span, and change the background color of the span.
Edit: I just noticed that you are not using CSS, so you will need to insert a font tag to change the color.
I just stole this from Sphix, the documentation tool:
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node) {
if (node.nodeType == 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) {
var span = document.createElement("span");
span.className = className;
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this)
});
}
}
return this.each(function() {
highlight(this);
});
}
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('.sidebar .this-page-menu li.highlight-link').fadeOut(300);
$('span.highlight').removeClass('highlight');
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlight');
});
}, 10);
$('<li class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></li>')
.appendTo($('.sidebar .this-page-menu'));
}
},
So, adding this to a js file in your site, any page with it that receives a highlight GET parameter will search and highlight the word in the page.
You can find a demo of the working code in:
http://sphinx.pocoo.org/intro.html?highlight=python
Note: This code needs jQuery, off course...
Its actually pretty easy using the prototype library:
<html>
<head>
<style type="text/css">
#content span {
background-color: yellow;
}
</style>
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
Event.observe(window,'load',function(){
var htm = $('content').innerHTML;
$('content').innerHTML = htm.sub('my','<span>my</span>');
});
</script>
</head>
<body>
<div id="content">
This is the div containing my content.
</div>
</body>
</html>
This should get you started so you can implement the rest.
To highlight a word you have to select it somehow. One option is to surround the word with a span tag.
this is <span class="highlight">test</span> some text test
then specify CSS for the highlight class.