Positioning java script element with embedded external value in the text - javascript

I am working on simple looking one-page-site hosted on Google Drive using "Editey" tools. What I need is to embed a number statistic values from a list of single cells of the correspondent Google Spreadsheet into various lines of my site text. It's almost done, but the final value can not be fixed in exact place. The cell value "3" must be displayed in one line of my text, just after the word "Alex", but paragraph tags that follow with id element "Alex" did not let fix it all together in a single row. How can I set my text "Alex" and embedded result "3" in one row, to let it looking as Alex3 ("3" styled as red superscript)?
// https://google,developers.appspot.com/chart/interactive/docs/spreadsheets#gid
google.load('visualization', '1', {packages: ['corechart', 'line']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var spreadsheetUrl = "https://docs.google.com/spreadsheets/d/1iVtRu6vQHmyNyXQdqGmoODhz3Vi9LJQSbEyAiw4t1Ww/edit?usp=sharing";
var query = new google.visualization.Query(spreadsheetUrl);
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
var dataTable = response.getDataTable();
// https://developers.google.com/chart/interactive/docs/reference?hl=en#methods
// getValue(rowIndex, columnIndex)
document.getElementById("Alex").innerHTML = dataTable.getValue(2, 1);
}
#Alex {
vertical-align: super;
font-size: 10px;
color: red;
}
<html>
<head>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="code.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<body>
<p>Alex
<p id="Alex"> </p>
</body>
</html>
Thank in advance for your attention : )

Assuming the incorrect HTML with missing </head> & </p> tags are typos, If you want to bring the two values on the same line, you can use 1 of the following 2 methods:
Reason: - In HTML <p> tags are by default block elements(display: block;), each block elements extend to 100% of the width and hence they stack one below the other instead of one within/next to the other(this is what you want). If you want to place them next to another you have to explicitly change the display property from block to inline-block.
Method 1 :
Make both the <p> tags you want display: inline-block.
p {
display: inline-block;
}
Method 2(I prefer this) :
Instead of using <p> tag for #Alex, use <span> inside the outer <p> element instead, Like so -
<body>
<p>Alex
<span id="Alex"> </span>
</p>
</body>
Because <span> by default has display: inline-block; property.
Hope this helped.

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.

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>

Unable to completely change jquery class

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");

Getting blank page sent to printer using a hidden div method

I am using a code snippet that I found to display a multipage form using visibility hidden.
There is a very good possibility that all of my problem stems from this method. That resource was from here:
http://www.devx.com/webdev/Article/10483/0/page/2
It is a fairly straightforward way to display multiple pages of a form...it probably was never intended to be able to allow printing.
<html>
<head>
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script language="JavaScript">
$.getScript("printThis.js", function(){
});
var currentLayer = 'page1';
function showLayer(lyr){
hideLayer(currentLayer);
document.getElementById(lyr).style.visibility = 'visible';
currentLayer = lyr;
}
function hideLayer(lyr){
document.getElementById(lyr).style.visibility = 'hidden';
}
function showValues(form){
var values = '';
var len = form.length - 1; //Leave off Submit Button
for(i=0; i<len; i++){
if(form[i].id.indexOf("C")!=-1||form[i].id.indexOf("B")!=-1)
continue;
values += form[i].id;
values += ': ';
values += form[i].value;
values += '\n';
}
alert(values);
}
</script>
<style>
body{
font: 10pt sans-serif;
}
.page{
position: absolute;
top: 10;
left: 100;
visibility: hidden;
}
</style>
</head>
<body>
<form id="multiForm" action="App1.php" method="POST" action="javascript:void(0)" onSubmit="showValues(this)" id="app">
<div id="page1" class="page" style="visibility:visible;">
Applicant Name: <input type="text" size="50" name="name1" >
</form>
<p><input type="button" id="C1" value="Continue" onClick="showLayer('page2')"></p>
</div>
<div id="page2" class="page">
This is Page 2
<br>
<input type="button" id="B1" value="Go Back" onClick="showLayer('page1')">
<input type="button" id="B2" value="Print App" onClick="$('#page1').printThis({})">
<br><br>
</div>
</form>
</body>
</html>
The "Print App" button is properly calling the printThis plugin. However, I get no content from the page1 DIV section. All that is printed is the normal header portion (Page 1 of 1) in the upper right and about:blank in lower left and date in lower right of pageā€¦no content, which with my sample file should be Applicant Name input box.
I assume that this is because the DIV for page1 is set to "hidden" while the content of page2 is being displayed. If I substitute "page2" in the button call then I get the content from page2 as expected.
So...I guess what I am after is a way to temporarily change the DIV being referenced in the printThis button call to be visible just long enough to perform the page print.
Any ideas?
I'm the plugin author - you need to incorporate the print media query into your css.
This would also help users that select file > print or control + P, as it will show all form elements.
The print media query allows you to make styling changes specifically for the printed page.
Example:
#media print {
#page1, #page2 {
display: block;
visibility: visible;
position: relative;
}
}
You include this in your css.
Additionally, based on your above code - you have css and javascript inline in your page. You should consider moving both to an external files, for maintenance and improved code standards.
printThis won't work with your current setup, because the plugin looks for the container (selector) you have specified and any linked css in the head of the document.
So for the above, you can do the following:
<!-- move all of this to the bottom of the page for performance -->
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="printThis.js"></script>
<script type="text/javascript" src="myJavascript.js"></script>
<!-- the above file is your javascript externalized, remove $.getScript, wrap in $(document).ready() -->
Then put this in your head:
<link type='text/css' rel='stylesheet' href='style.css'>
<!-- contains your css from the page, including the print media query -->

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