Unable to completely change jquery class - javascript

I am trying to make an emoji system whereby a file called emoji.css willm store the emojis.The names of all the emoji's are stored in a really javascript array although slightly altered.When users input a emoji text
(something like :emoji: ,:another-emoji:)Javascript should check if it that text is in the emoji array,if it is,it will be automatically turned into an emoji.
Atleast that is what I'm trying to do
This is the steps of what is supposed to happen
Page loads
User inputs in input with class 'input'
If the text is in the array called
emoji,javascript
i.Alerts the name of the input
ii.Says 'it is in array'
iii.Copy the text into a div with class
`see`
iv.Text in div automatically becomes an array`
And I think that is where the problem is.
In the emoji.css file all emoji have classes with names like em em-abc,em em-woman but when users want to call an emoji, they must input a text with a : in the front and back like :abc:,:woman: so jquery should automatically change that input string(:abc:) to emoji.css class(em em-abc) and I used this line of code to do that
$(".see").addClass("em em-"+$(".see").html().split(":").pop()).removeClass(".see");
here is my full code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Rad emojis</title>
<style>
div {
color: blue;
}
span {
color: red;
}
</style>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<link href="emoji.css" rel="stylesheet">
</head>
<body>
<div class ="see em-abc"></div>
<input class="input">
<div class ="see"></div>
<div class ="see2"></div>
<div class ="see3"></div>
<div class="add"></div>
<script>
var emoji = [ ":abc:", ":woman",":eye:", <!--it was much longer than this--> ];
var input=$(".input");
var input2=$(".input").val();
$(input).change(function(){
$(".see").html( $(".input").val());
if(jQuery.inArray($(".input").val(), emoji) != -1) {
var see="."+$(".see").html();
$(".see2").html(see);
var classs =see+"";
alert($(".see").html());
var real=$(".see").html().split(":").pop();
$(".see3").html(real);
$(".see").toggleClass("em em-"+$(".see").html().split(":").pop());
$(".see").addClass("em em-"+$(".see").html().split(":").pop()).removeClass(".see");
alert("is in array");
alert($(".see").html());
} else {
alert("is NOT in array");
}
});
</script>
</body>
</html>

When you remove a class using the removeClass method, you have to omit the dot.
Simply use
$(".see").addClass("em em"+$(".see").html().split(":").pop()).removeClass("see");

Related

JS onClick event ignores first click, works for every subsequent click

Having a very weird issue with a simple div visibility toggle script.
I'm just using javascript to switch a div between 'display: block' and 'display: none' to toggle its visibility. Very routine stuff.
And in general it works, but it always fails on the first click after a fresh page load. Then it works consistently from the second click onward.
No error output on console.
Relevant HTML:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="res/classes.js"></script>
<script type="text/javascript" src="res/util_c.js"></script>
<script type="text/javascript">
// load client prefs
var clientPrefs = new ClientPrefs();
</script>
</head>
<body>
<a id="join_show_publist" class="a_btn" onClick="javascript:joinPublistToggle()">View Public Matches</a><br />
<!-- list of public games -->
<div id="join_publist_container" class="ovr">
<table id="join_publist_listbox">
<tr id="join_publist_listbox_header">
<td>Table Name</td>
<td>Open</td> <!-- open seats remaining at table -->
</tr>
</table>
<div class="spacer"></div>
<div id="join_savePref_container">
<input id="join_savePref" type=checkbox onclick="javascript:clientPrefs.joinAlwaysShowPubToggle()" />
<span id="join_savePref_label" onclick="javascript:clientPrefs.joinAlwaysShowPubToggle()">Always show public tables list</span>
</div>
</div>
Relevant CSS:
div.ovr {
display: none;
}
...and finally in util_c.js:
// toggle visibility of public tables list
function joinPublistToggle() {
var listContainer = document.getElementById('join_publist_container');
if (listContainer.style.display == 'none') {
listContainer.style.display = 'block';
} else {
listContainer.style.display = 'none';
}
}
First click: nothing happens.
Second click: the DIV is shown
Third click: the DIV is re-hidden
etc..
If I put an alert(listContainer.style.display) into the joinPublistToggle function, the alert comes up empty with the first click, then shows 'none' with the second click.
But the CSS specifically sets the display style for that div as 'none' on load. And if I look at that div in the page inspector after a fresh page load the inspector specifically says the div's display property is set to none.
So the issue seems to be that javascript is reading that property as empty even though that property is set as 'none'.
Why would it do that?
style returns the inline style of the element, and your element doesn't have any, which is why listContainer.style.display returns an empty string and the condition fails.
It would work if you compared against 'block' instead but it's not really more reliable.
function joinPublistToggle() {
var listContainer = document.getElementById('join_publist_container');
if (listContainer.style.display == 'block') {
listContainer.style.display = 'none';
} else {
listContainer.style.display = 'block';
}
}
https://stackoverflow.com/questions/69213611/js-onclick-event-ignores-first-click-works-for-every-subsequent-click/69224191#
The other answers provide valid solutions, here is another using classes:
CSS:
div.hidden {
display: none;
}
HTML:
<div id="join_publist_container" class="ovr hidden">
(of course you can also just keep using ovr but I wasn't sure what that's for)
JS:
function joinPublistToggle() {
document.getElementById('join_publist_container').classList.toggle('hidden');
}
And in general it works, but it always fails on the first click after a fresh page load. Then it works consistently from the second click onward.
I am going to asume when you clicked the link, the checkbox and the table should go away. And when it is clicked again, the table and the checkbox should show. I modified your code and it works for me.
for your HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" src="classes.js"></script>
<script type="text/javascript" src="util_c.js"></script>
<script type="text/javascript">
// load client prefs
var clientPrefs = new ClientPrefs();
</script>
</head>
<body>
<a id="join_show_publist" class="a_btn" onClick="javascript:joinPublistToggle()">View Public Matches</a><br />
<!-- list of public games -->
<div id="join_publist_container" class="ovr">
<table id="join_publist_listbox">
<tr id="join_publist_listbox_header">
<td>Table Name</td>
<td>Open</td> <!-- open seats remaining at table -->
<td>Starts</td> <!-- time left until game starts (or "started" if underway) -->
<td>Timer</td> <!-- time limit for turns (or "none") -->
<td>Min</td> <!-- min players to start the round (or '--' if already underway) -->
<td>Late</td> <!-- whether late joiners are allowed at the table -->
<td>AI</td> <!-- whether there are any AI players at the table (and if so, how many)
also colour denotes difficulty: green-easy / yellow-med / red-hard -->
</tr>
<!-- Generate list via js. Clicking any list entry joins -->
</table>
<div class="spacer"></div>
<div id="join_savePref_container">
<input id="join_savePref" type=checkbox onclick="javascript:clientPrefs.joinAlwaysShowPubToggle()" />
<span id="join_savePref_label" onclick="javascript:clientPrefs.joinAlwaysShowPubToggle()">Always show public tables list</span>
</div>
</div>
Classes.js:
// ClientPrefs - client-side preferences
class ClientPrefs {
constructor() {
// JOIN GAME page settings
this.joinAlwaysShowPub = false;
}
joinAlwaysShowPub() { return joinAlwaysShowPub; }
joinAlwaysShowPubToggle() {
// toggle setting in memory
this.joinAlwaysShowPub = !this.joinAlwaysShowPub;
// update checkbox & label
document.getElementById('join_savePref').checked = this.joinAlwaysShowPub;
}
}
And finally your other script:
function joinPublistToggle() {
var listContainer = document.getElementById('join_publist_container');
if (listContainer.style.display == 'none') {
listContainer.style.display = 'block';
} else {
listContainer.style.display = 'none';
}
}
Here are few reasons why your code might not work:
I think the problem is that you mistyped joinPublistToggle() to joinShowPubList.
Your div has a value of nothing for the display property. So, when JS looks at your div, well, the div is not set to none or block, I don't know how to handle it. After you clicked the link a second time, it sets the display in your JS code. So, it knows how to handle it.
Maybe add an display property to your a tag and set it to block so JS know what the property of the style is.
<a id="join_show_publist" class="a_btn" onClick="javascript:joinPublistToggle()" style="display:block;">View Public Matches</a><br />
This doesn't really answer my question, but I've implemented a simple workaround by adding an OR statement into the JS function:
function joinPublistToggle() {
var listContainer = document.getElementById('join_publist_container');
if ( (listContainer.style.display == 'none') ||
(listContainer.style.display == '' ) ) {
listContainer.style.display = 'block';
} else {
listContainer.style.display = 'none';
}
}
This doesn't explain why it was behaving so odd, and it isn't a proper solution (as a proper solution would address the cause, not the symptom).
But it works.
I won't mark the post as solved just yet in case any wizards end up reading this and are able to explain why the problem occurred in the first place.

Create highlight effect on hover an element

I tried to make highlight effect on each <a> element while I hover on each div element but it doesn't work and console shows this error
"Uncaught TypeError: Cannot set property 'background' of undefined
at highlight_function"
enter image description here
function highlight_function () {document.getElementsByTagName("a").style.background="#80ff00"};
document.getElementsByTagName("div").addEventListener("mouseover",highlight_function())
I think it's because document.getElementsByTagName("a") is an array, and you are trying to set style on the array and not in each element.
You should either make a for loop to change background style of each element or add a style tag like a {background: "#80ff00"}.
But you can't define style to an array like this
index.html
<html lang="en">
<head>
</head>
<body>
<div>
something
</div>
</body>
<script>
function highlight_function() {
const a = document.querySelector('a');
a.style.background = "#80ff00"
}
const div = document.querySelector('div');
div.addEventListener('mouseover', highlight_function);
</script>
</html>
I don't think background property will work on an <a> tag. Try doing this in your function:
document.getElementsByTagName("a").style.color="#80ff00"
Here is you can try this
function highlight_function() {
document.getElementById("a").style.backgroundColor = "#80ff00";
};
<div id="div">
<a id="a" onmouseover="highlight_function()">Hell</a>
</div>
when you make this call
document.getElementsByTagName("a")
it will return to you collection of html elements so there is no style property
you can use for loop through it
for(var a of document.getElementsByTagName("a")) {
a.style.background="#80ff00";
}
you can simply add highlight effect or change the background color by adding the CSS as follows:
<!DOCTYPE html>
<html>
<head>
<style>
p:hover {
background-color: green;
}
</style>
</head>
<body>
<p id="hometown">I live in Pakistan</p>
</body>
</html>

Element.innerHTML breaks connection between element and Document in DOM(isConnected = false)?

So basically I was trying to make an error message that is hidden by default be displayed when the user inputs incorrect information. However, the message wasn't appearing. So I used the debugger and found out that the error node element at the top of the js. code was successfully finding the element in the HTML and also successfully changing it's properties. And yet nothing was happening. So after a bit of research I found out that there is a property called isConnected which shows if the Node is connected to the Document. Turns out mine was connected(true) immediately after finding the element, but it was disconnected(false) by the time it entered the errorHandler() func. So again after a bit of debugging I found out that the bottom line of the onPageLoad func was causing the problem. It used to be rootUl.innerHTML += template(countriesObj); but that was breaking it. However, when I moved my error element in the HTML from the ul to outside the id="root" div, it was working fine. It was only breaking when the element was inside the ul. At the end of the day I fixed it by using Element.insertAdjacentHTML() instead, which wouldnt sever the connection between the error element and Document. So after about an hour of struggle, I am curious why that happens and what the difference is between rootUl.innerHTML += template(countriesObj); and rootUl.insertAdjacentHTML('beforeend', template(countriesObj));
Just to add, rootUl.innerHTML+=template(countriesObj) breaks the connection even when used by other function which are not shown here.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List Towns</title>
<script src="../handlebars.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<p style="text-align: center; font-size: 18px; font-weight: 700; font-family: Arial, Helvetica, sans-serif;">
Input in the following format: "{Country}: {town}, {town} {Country}: {town}, {town}" and so on. Matching is case-insensitive. Non-english characters are not supported. Numbers are not supported. Check regex for more info. Reset button deletes entire database and refreshes page.
</p>
<form action="#" class="content">
<label for="towns">Towns</label>
<input id="towns" type="text" placeholder="ex. Bulgaria: Burgas, Varna Turkey: Ankara"/>
<button id="btnLoadTowns">Load</button>
</form>
<div id="root">
<ul>
<!--When the element was here, innerHTML wasn't working correctly-->
<h4 id="error" style="color: rgb(136, 9, 0); display: none;" >Error. Input string not in correct format. Look at instructions above.</h4>
</ul>
</div>
<!--When the element was here, innerHTML was working fine-->
<!-- <h4 id="error" style="color: rgb(136, 9, 0); display: none;" >Error. Input string not in correct format. Look at instructions above.</h4> -->
<button id="reset">Reset</button>
<h4 id="empty-database" style="color: rgb(136, 9, 0); display: none;" >Database is currently empty.</h4>
</body>
<script src="./app.js"></script>
</html>
async function pageApp(){
//Misc
let error = document.querySelector('#error');
let emptyDatabase = document.getElementById('empty-database');
// Grab the unordered list of countries
let rootUl = document.querySelector('#root ul');
// Extract(GET request) data from database
let database = await getRequestForCountries();
// Get the two templates: One is for both country and town, another is just for town when country already exists
let template = await getTemplate();
let templateTown = await getTemplateTown();
// Load countries on page load
onPageLoad();
//Attach load event to button
attachLoadEvent();
//Reset button for deleting the database
resetButton()
function errorHandler(){
error.style.display = 'block';
setTimeout(function(){
error.style.color = 'rgb(136, 9, 0)';
error.style.background = 'none';
}, 150)
error.style.color = 'red';
error.style.background = 'rgb(136, 9, 0)';
}
function onPageLoad(){
database.forEach(entry => {
let townsArr = entry.towns;
let countryName = entry.countryName;
let townsArrObj = townsArr.reduce((acc, cur) =>{
let townObj = {
name: cur
}
acc.push(townObj);
return acc;
},[]);
let countriesObj = {
countries:[
{
name: countryName,
towns: townsArrObj
}
]
}
//Was rootUl.innerHTML += template(countriesObj); But that breaks the DOM of error and makes error.isConnected = false;
// rootUl.innerHTML += template(countriesObj);
rootUl.insertAdjacentHTML('beforeend', template(countriesObj));
})
}
Element.innerHTML +=, gets HTML code within the element and append it with something.
document.querySelector('p').innerHTML += `<span>Appended span</span>`;
<p>
Lorem Ipsum
<span style="color: red">Something</span>
<p>
Whereas, Element.insertAdjacentHTML('beforeend', 'To be inserted node'), will add new node, before the specified element.
document.querySelector('p').insertAdjacentHTML('beforeend', '<div>I am div</div>');
<p>Lorem ipsum</p>

How to change the colour of a div element when clicked?

I have a this html page, Whenever the element with class name FreeSeat is clicked I want to change the colour of that div element.Below is my html page
<html>
<head>
<title>
QuickBus
</title>
<link type="text/css" rel="stylesheet" href="Seat.css">
</head>
<body>
<div id="Bus">
<div class="Row">
<div class="FreeSeat" ></div>
<div class="FreeSeat" ></div>
<div class="ResSeat" ></div>
<div class="ResSeat" ></div>
<div class="ResSeat" ></div>
</div>
</div>
<body>
</html>
It will be very helpful if anyone can help me out with this .
Considering that you want to use pure JS and not any library, you'd have to manually add event listeners to your classes.
And it has been solved for a similar problem here
var freeclass = document.getElementsByClassName("FreeSeat");
var myFunction_Free = function() {
this.style.color = "blue";
}
for(var i=0;i<freeclass.length;i++){
freeclass[i].addEventListener('click', myFunction_Free, false);
}
But for your case, here's a working fiddle
JQuery is amazing for these sorts of things.
Say you have a div with id 'box1'
<div id='box1'></div>
Style it with css
#box1 {
width:100px;
height:100px;
background-color:white;
border:1px solid black;
}
Using JQuery, you can make this call:
$( "#box1" ).click(function() {
$('#box1').css('background-color', 'red');
});
And now whenever your div is clicked, the colour will change, you can customise this however much you like.
Here is a JSFiddle demo.
Also, since you didn't specify exactly what you want to change the colour of, in my example jquery, it is telling the browser that when a div with an id of box1is clicked, change the background-color of the div with an id of box1, you can change anything though.
If you have a <p> tag you can change that too when the div is clicked, hope this helped!
You can use the following method to change the background color of an element by class:
const free_seat = document.getElementsByClassName('FreeSeat');
free_seat[0].style.backgroundColor = '#ff0';
Each element can be referenced by its index:
free_seat[0] // first div
free_seat[1] // second div
Therefore, we can create a function that will be called whenever the click event is delivered to the target:
const change_color = () => {
this.style.backgroundColor = '#ff0';
};
for (let i = 0; i < free_seat.length; i++) {
free_seat[i].addEventListener('click', change_color);
}
Note: You can also use document.querySelectorAll('.FreeSeat') to obtain a NodeList of elements of a certain class.
You can use simply the css focus pseudo-class for this:
#foo:focus {
background-color:red;
}
<div id="foo" tabindex="1">hello world!</div>
Dont forget to set the tabindex.

Javascript creating <div> on the fly

I have a a link that looks similar to this
Blog
As you can the link has an ID of 'blog' what I want to do is to create an div on the fly with the ID from the link that was clicked so if the 'blog' is clicked, then the markup would be
<div id="blog">
<!--some content here-->
</div>
Like wise if for instance the news link is clicked then I would like,
<div id="news">
<!--some content here-->
</div>
to be created in the markup if this possible? and how Im pretty new to jQuery.
Try this:
$("a").click(function(){
$("#wrapper").append("<div id=" + this.id + "></div>");
});
Not tested, should work ;)
where: #wrapper is parent element, work on all a as you see.
You will need to give the div a different ID. Perhaps you could give it a class instead:
$("#blog").click(function() {
$(this).after("<div class='blog'>...</div>");
return false;
});
That's just one of many ways to create a div. You probably also want to avoid duplicates however in which case, use something like this:
$("#blog").click(function() {
var content = $("#blog_content");
if (content.length == 0) {
content = $("<div></div>").attr("id", "blog_content");
$(this).after(content);
}
content.html("...");
return false;
});
As for how to handle multiple such links I would do something like this:
Blog
News
Weather
<div id="content"></div>
with:
$("a.content").click(function() {
$("#content").load('/content/' + this.id, function() {
$(this).fadeIn();
});
return false;
});
The point is this one event handler handles all the links. It's done cleanly with classes for the selector and IDs to identify them and it avoids too much DOOM manipulation. If you want each of these things in a separate <div> I would statically create each of them rather than creating them dynamically. Hide them if you don't need to see them.
Try This :
<a id="blog">Blog</a>
<a id="news">news</a>
<a id="test1">test1</a>
<a id="test2">test2</a>
$('a').click(function()
{
$('<div/>',{
id : this.id,
text : "you have clicked on : " + this.id
}).appendTo("#" + this.id);
});
First of all you should not make 2 elements with same ID. At your example a and div will both have id="blog". Not XHTML compliant, plus might mess up you JS code if u refernce them.
Here comes non-jquery solution (add this within script tags):
function addDiv (linkElement) {
var div = document.createElement('div');
div.id = linkElement.id;
div.innerHTML = '<!--some content here-->';
document.body.appendChild(div); // adds element to body
}
Then add to HTML element an "event handler":
Blog
This question describes how to create a div. However, you shouldn't have two elements with same IDs. Is there any reason why you can't give it an id like content_blog, or content_news?
Unfortunately if you click on a link the page you go to has no idea what the idea of the link you clicked was. The only information it knows is what's contained in the URL. A better way to do this would be to use the querystring:
Blog
Then using the jQuery querystring plugin you could create the div like:
$("wrapper").add("div").attr("id", $.query.get("id"));
You shouldn't have elements in your page with the same ID. Use a prefix if you like, or perhaps a class.
However, the answer is as follows. I am imagining that your clickable links are within a div with the ID "menu", and your on-the-fly divs are to be created within a div with the ID "content".
$('div#menu a').click(function(){
$('div#content').append('<div id="content_'+this.id+'"><!-- some content here --></div>');
});
Any problems, ask in the comments!
Also the following statement is available to create a div dynamically.
$("<div>Hello</div>").appendTo('.appendTo');
Working fiddle: https://jsfiddle.net/andreitodorut/xbym0bsu/
you can try this code
$('body').on('click', '#btn', function() {
$($('<div>').text('NewDive').appendTo("#old")).fadeOut(0).fadeIn(1000);
})
#old > div{
width: 100px;
background: gray;
color: white;
height: 20px;
font: 12px;
padding-left: 4px;
line-height: 20px;
margin: 3px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div>
<!-- Button trigger modal -->
<button type="button" id="btn">Create Div</button>
<div id="old">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>

Categories