Undefined JavaScript - javascript

Why do I get undefined in alert() in the following code:
var header = document.getElementById("header");
var navigationBar = document.getElementById("navigationBar");
var buttons = document.getElementsByClassName("button");
alert(header.innerWidth);
alert(navigationBar.innerWidth);
.header {
background-color: #263238;
border-bottom: solid 0.25em #37474F;
border-radius: 0;
padding: 0.5em;
display: block;
}
.navigationBar {
display: inline-block;
}
<div class="header" id="header" align="right">
<div class="navigationBar" id="navigationBar">
</div>
</div>

It's because DOM elements don't have an innerWidth and innerHeight. That's a window property.

Elements don't have innerWidth/innerHeight. You might have wanted offsetWidth/offsetHeight, or getComputedStyle(x).width/height (which will give you a string, almost certainly ending in px, for the outer width of the element).
Also note Kuldeep Singh's answer about clientWidth/clientHeight.
Example (without clientWidth/clientHeight):
var header = document.getElementById("header");
var navigationBar = document.getElementById("navigationBar");
var buttons = document.getElementsByClassName("button");
console.log(header.offsetWidth);
console.log(navigationBar.offsetWidth);
console.log(getComputedStyle(header).width);
console.log(getComputedStyle(navigationBar).width);
.header {
background-color: #263238;
border-bottom: solid 0.25em #37474F;
border-radius: 0;
padding: 0.5em;
display: block;
}
.navigationBar {
display: inline-block;
}
<div class="header" id="header" align="right">
<div class="navigationBar" id="navigationBar">
</div>
</div>
(On old IE, instead of getComputedStyle(x), you'd use x.currentStyle.)

try clientWidth instead of innerWidth .

There is no innerWidth on elements, that's a jQuery function. Instead, look for clientWidth:
document.addEventListener('DOMContentLoaded', function() {
var header = document.getElementById("header");
var navigationBar = document.getElementById("navigationBar");
var buttons = document.getElementsByClassName("button");
console.log(
header.clientWidth,
navigationBar.clientWidth
);
});
.header {
background-color: #263238;
border-bottom: solid 0.25em #37474F;
border-radius: 0;
padding: 0.5em;
display: block;
}
.navigationBar {
display: inline-block;
}
<div class="header" id="header" align="right">
<div class="navigationBar" id="navigationBar" ></div>
</div>

Related

Some issues with chat box design

I am working on a chat application and I have two major issues in chatbox design.
I want some part of the screen scrollable just like other chatting applications when we have more messages we scroll up to see previous messages and other things are fixed on the screen like: sendbar,top-menu-bar, etc. but I unable to do so, I tried overflow-y = scroll but it didn't work.
As I mentioned in the first point some things have to be fixed on the screen but after setting position = fixed it also doesn't work.
I tried everything please help.
function fxn(){
var text = document.getElementById("inp").value
var ele = document.getElementById("parent")
var foo = document.createElement("div")
foo.innerHTML = "<div class = box1>" + text + "</div><br><br><br>";
ele.appendChild(foo)
}
#box {
margin-bottom: 10px;
background-color: aqua;
width: 300px;
border: solid 2px black;
}
.box1 {
display: inline;
padding: 10px;
border-radius: 15px;
width: 300px;
border: solid 2px black;
}
.out{
position: fixed;
width: 100%;
background-color: aquamarine;
}
<body id="bd">
<div id ="box">
Testing chat box
</div>
<div id="parent"></div>
<div class="out">
<input type="text" id="inp">
<button onclick="fxn()">Send</button>
</div>
</body>
Output
I see that the post has been accepted and it works nicely for the OP. But I would still like to present one more option. I just made CSS changes to make the footer fixed and header sticky so as to mimic your requirement.
function fxn(){
var text = document.getElementById("inp").value
var ele = document.getElementById("parent")
var foo = document.createElement("div")
foo.innerHTML = "<div class = box1>" + text + "</div><br><br><br>";
ele.appendChild(foo)
}
#box {
margin-bottom: 10px;
background-color: aqua;
width: 300px;
border: solid 2px black;
position: sticky;
top:0;
}
.box1 {
display: inline;
padding: 10px;
border-radius: 15px;
width: 300px;
border: solid 2px black;
}
.out{
position: fixed;
width: 100%;
background-color: aquamarine;
left: 0;
bottom: 0;
}
<body id="bd">
<div id ="box">
Testing chat box
</div>
<div id="parent"></div>
<div class="out">
<input type="text" id="inp">
<button onclick="fxn()">Send</button>
</div>
</body>
function fxn(){
var text = document.getElementById("inp").value
var ele = document.getElementById("parent")
var foo = document.createElement("div")
foo.innerHTML = "<div class = box1>" + text + "</div><br><br><br>";
ele.appendChild(foo)
ele.scrollTop = ele.scrollHeight;
}
#parent{
height:100px;
overflow-y:scroll;
}
#box {
margin-bottom: 10px;
background-color: aqua;
width: 300px;
border: solid 2px black;
}
.box1 {
display: inline;
padding: 10px;
border-radius: 15px;
width: 300px;
border: solid 2px black;
}
.out{
position: fixed;
width: 100%;
background-color: aquamarine;
}
<body id="bd">
<div id ="box">
Testing chat box
</div>
<div id="parent"></div>
<div class="out">
<input type="text" id="inp">
<button onclick="fxn()">Send</button>
</div>
</body>
please note here i had added height to the parent div and overflow-y to be scroll, and also added ele.scrollTop = ele.scrollHeight; in the js part.
here you can read more about ScrollTop
Try this
function fxn(){
var text = document.getElementById("inp").value
var ele = document.getElementById("parent")
var foo = document.createElement("div")
foo.innerHTML = "<div class = box1>" + text + "</div><br><br><br>";
ele.appendChild(foo)
window.scrollTo(0,document.body.scrollHeight);
}
.out{
width: 100%;
background-color: aquamarine;
}

onClick JS not go to top of the page

I have a page with an initial description, followed by 2 buttons, where the user can choose typeA or typeB. They work by "target": when the user clicks typeA comes the content relative to typeA, bellow the buttons; same to typeB.
typeA is the most common selection, then, when the page loads, a javascript emulates the click to typeA and opens respective content. To avoid hidden the initial description, there is another javascript to put the page at the top. Worked on Chrome and Edge, not on Firefox.
I would like to repeat the same process when the user clicks: opens the respective content, but positioning the page at the top, or, at least, showing the buttons. I thought event onClick calling the same js backToTop would worked - but not.
I put an alert on js and enters there but not execute: always keeps the content of the button selected in its better visibility.
I tried:
window.location.href = '#top';
window.scrollBy(0, -500);
document.html.scrollTop = document.documentElement.scrollTop = 0;
without success.
What am I doing wrong?
<head>
<meta charset="UTF-8">
<title>TOP PAGE TEST</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body,html {margin-left:auto; margin-right:auto;width:70%; font-family:verdana; font-size:1.2em;}
.menuFAQ {background:#aaa; font-size:2em; width:100%;}
.menuFAQ ul {list-style-type:none; position:relative; margin-left:-40px; /* to avoid user agent chrome */}
.menuFAQ li {display:inline-block; margin-top:10px; margin-bottom:10px; width:49%; background:#fff; text-align:center; box-shadow:2px 3px 4px 0px rgba(170,170,170,1); font-weight:400; line-height:80px;}
.menuFAQ li a {display:block; color:#020062; background:#fff; font-weight:400; text-decoration:none;}
.menuFAQ li .active,.menuFAQ li:hover a {color:#fff; font-weight:400; background-image:linear-gradient(#165686, #0f3a5a); }
:target {color:#fff;font-size:1em;}
div.items>div:not(:target) {display:none}
div.items>div:target {display:block; margin-left:auto; margin-right:auto; color:#000; border:1px solid #aaa;}
</style>
</head>
<body>
<div id="top">Top Page</div>
<br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5
<div class="menuFAQ">
<ul>
<li><a id="preferedFAQ" onclick="backToTop()" class="target" href="#typeA">TypeA</a></li>
<li><a onclick="backToTop()" class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p><p>text2B</p><p>text3B</p>
<br>[...]
</nav>
</div>
</div>
<script>
const allTargetLinks = document.querySelectorAll('.target')
allTargetLinks.forEach(targetLink => {
targetLink.addEventListener('click', () => {
allTargetLinks.forEach(targetLink => {
targetLink.classList.remove('active')
})
targetLink.classList.add('active')
})
})
window.onload = function() {assignPreferedFAQ()};
function assignPreferedFAQ() {
document.getElementById("preferedFAQ").click();
backToTop();
};
function backToTop() {
//document.html.scrollTop = document.documentElement.scrollTop = 0;
//document.body.scrollTop = document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};
</script>
You had a real mess there regarding how you process click events and href attribute, i.e:
You had onclick attribute on your links, and you were adding yet another listener to them in JS
You didn't event.preventDefault() in your function, and default browser behavior when you click on a link is to get you to its href path
I've cleaned up a bit and changed some things. Since we need to prevent default behavior :target selector will no longer work, so instead I did what you've already been doing with links, and added an active class to your content. clickHandler() will now remove and add class active as necessary. At the end just scroll to the top. Here's the snippet:
document.querySelectorAll('.target').forEach(targetLink => targetLink.addEventListener('click', clickHandler, false));
function clickHandler(ev) {
ev.preventDefault(); // prevent browser from automatically scrolling to href pos
if (!ev.currentTarget.classList.contains('active')) {
// disable active elements
document.querySelector('.target.active').classList.remove('active');
document.querySelector('.items div.active').classList.remove('active');
// add class to the clicked on button and its corresponding content tab
ev.currentTarget.classList.add('active');
// to prevent pointless string slicing below, you'd have to store ids somewhere else i.e in the data-id attribute
const id = ev.currentTarget.href.slice(ev.currentTarget.href.lastIndexOf('#') + 1);
document.getElementById(id).classList.add('active');
}
window.scrollTo(0,0);
}
* {
font-family: verdana;
font-size: 1em;
}
.menuFAQ {
background: #aaa;
font-size: 2em;
width: 100%;
}
.menuFAQ ul {
list-style-type: none;
text-align: center;
padding: 0;
/* to avoid user agent chrome */
}
.menuFAQ li {
display: inline-block;
width: 48%;
margin-top: 10px;
margin-bottom: 10px;
background: #fff;
text-align: center;
box-shadow: 2px 3px 4px 0px rgba(170, 170, 170, 1);
font-weight: 400;
line-height: 80px;
}
.menuFAQ li a {
display: block;
color: #020062;
background: #fff;
font-weight: 400;
text-decoration: none;
}
.menuFAQ li .active,
.menuFAQ li:hover a {
color: #fff;
font-weight: 400;
background-image: linear-gradient(#165686, #0f3a5a);
}
div.items>div {
display: none;
}
div.items>div.active {
display: block;
margin-left: auto;
margin-right: auto;
color: #000;
border: 1px solid #aaa;
}
<div id="top">Top Page</div>
<br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5
<div class="menuFAQ">
<ul>
<li><a class="target active" href="#typeA">TypeA</a></li>
<li><a class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div class="active" id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p>
<p>text2B</p>
<p>text3B</p>
<br>[...]
</nav>
</div>
</div>
Note that instead of artificially clicking at the page load, now your content just loads with class active.
Hope this help you.
< script >
window.onload = function() {
document.getElementById("preferedFAQ").click();
backToTop();
};
function backToTop() {
document.documentElement.scrollTop = document.body.scrollTop = 0;
//alert("enter backToTop");
var elmnt = document.getElementById("top");
var x = elmnt.scrollLeft;
var y = elmnt.scrollTop;
}; <
/script>
body,
html {
margin-left: auto;
margin-right: auto;
width: 70%;
font-family: verdana;
font-size: 1.2em;
}
.menuFAQ {
background: #aaa;
font-size: 2em;
width: 100%;
}
.menuFAQ ul {
list-style-type: none;
position: relative;
margin-left: -40px;
/* to avoid user agent chrome */
}
.menuFAQ li {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
width: 49%;
background: #fff;
text-align: center;
box-shadow: 2px 3px 4px 0px rgba(170, 170, 170, 1);
font-weight: 400;
line-height: 80px;
}
.menuFAQ li a {
display: block;
color: #020062;
background: #fff;
font-weight: 400;
text-decoration: none;
}
.menuFAQ li .active,
.menuFAQ li:hover a {
color: #fff;
font-weight: 400;
background-image: linear-gradient(#165686, #0f3a5a);
}
:target {
color: #fff;
font-size: 1em;
}
div.items>div:not(:target) {
display: none
}
div.items>div:target {
display: block;
margin-left: auto;
margin-right: auto;
color: #000;
border: 1px solid #aaa;
}
<div id="top">Top Page</div> <br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5<br>textExp6<br>textExp7<br>textExp8<br>textExp9<br>textExpA<br>textExpB<br>textExpC<br>textExpD
<br>textExpE
<div class="menuFAQ">
<ul>
<li><a id="preferedFAQ" onclick="backToTop()" class="target" href="#typeA">TypeA</a></li>
<li><a onclick="backToTop()" class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p>
<p>text2B</p>
<p>text3B</p>
<br>[...]
</nav>
</div>
</di

Make tabs responsive on smaller screens

I have the following tabs and I would like to make them responsive when in smaller screens. Currently the last tabs just disappear when I make the screen smaller. The best scenario would be... when in smaller screens the tabs will start stacking below the first ones. Any ideas on how to implement this?
(function() {
$(function() {
var toggle;
return toggle = new Toggle('.toggle');
});
this.Toggle = (function() {
Toggle.prototype.el = null;
Toggle.prototype.tabs = null;
Toggle.prototype.panels = null;
function Toggle(toggleClass) {
this.el = $(toggleClass);
this.tabs = this.el.find(".tab");
this.panels = this.el.find(".panel");
this.bind();
}
Toggle.prototype.show = function(index) {
var activePanel, activeTab;
this.tabs.removeClass('active');
activeTab = this.tabs.get(index);
$(activeTab).addClass('active');
this.panels.hide();
activePanel = this.panels.get(index);
return $(activePanel).show();
};
Toggle.prototype.bind = function() {
var _this = this;
return this.tabs.unbind('click').bind('click', function(e) {
return _this.show($(e.currentTarget).index());
});
};
return Toggle;
})();
}).call(this);
.toggle {
font-family: arial, sans-serif;
}
.toggle .tabs {
border-bottom: 1px solid grey;
width: 100%;
overflow: hidden;
height: 36px;
line-height: 36px;
}
.toggle .tabs .tab {
float: left;
background: white;
color: #777777;
height: 31px;
margin: 2px 8px 0;
padding: 0 8px;
cursor: pointer;
}
.toggle .tabs .tab.active {
color: #dd4b39;
border-bottom: 3px solid #dd4b39;
}
.toggle .panels .panel {
padding: 20px 10px;
display: none;
}
.toggle .panels .panel:first-child {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='toggle'>
<div class='tabs'>
<div class='tab active'>Tab 1</div>
<div class='tab'>Tab 2</div>
<div class='tab'>Tab 3</div>
<div class='tab'>Tab 4</div>
</div>
<div class='panels'>
<div class='panel'>Panel 1</div>
<div class='panel'>Panel 2</div>
<div class='panel'>Panel 3</div>
<div class='panel'>Panel 4</div>
</div>
</div>
There are various ways to handle web-page responsiveness:
1.) Use flex view to make it scale based on the size of your page. But this doesn't sustain much because beyond a point the text starts to overflow the container.
2.) Use media queries to change the page layout at different sizes of the page. Reference
It turns out that it was very simple... I just had to delete the height from the following:
.toggle .tabs {
border-bottom: 1px solid grey;
width: 100%;
overflow: hidden;
height: 36px; ////////delete this here
line-height: 36px;
}

Looking for ways to refactor my jQuery code for a div toggle I created

I wrote some code with three things in mind:
Highlighting a selection's border using 'on click'.
Selecting one item will remove the highlight from the other item.
The ability to deselect each item on click.
I've managed to get everything working for the most part, but I don't particularly like how complex the code is for the radial dot that appears when one item is selected.
Below is an example of what I'm talking about, particularly I'm looking for ways to refactor the code below into something a little more legible (shorter).
$(this).children('.radial').children().toggleClass('checked').parents('.itembox')
.siblings().children('.radial').children().removeClass('checked');
Here's a working example for more context (line 10):
var raceInternet = false;
var racePhone = false;
var raceTv = false;
$(function() {
var $targetDiv = $('#race-internet > .itembox');
var $radialDot = $('.radial > .center-dot');
$targetDiv.on('click', function() {
$(this).toggleClass('user-selected').siblings().removeClass('user-selected');
//Is it possible to refactor Line 10?
$(this).children('.radial').children().toggleClass('checked').parents('.itembox').siblings().children('.radial').children().removeClass('checked');
if ($targetDiv.is('.user-selected')) {
raceInternet = true;
} else {
raceInternet = false;
}
})
})
.itembox-container {
display: flex;
}
.boxes-2 {
width: calc((100% - 25px)/2);
margin: 10px;
padding: 10px;
}
.itembox {
position: relative;
display: inline-block;
border: 5px solid #e8e8e8;
border-radius: 10px;
cursor: pointer;
}
.user-selected {
border: 5px solid #E16E5B;
}
.itembox h4 {
color: #22ddc0;
font-weight: 700;
}
span.price {
display: inline-block;
font-weight: 400;
float: right;
color: #22ddc0;
}
.itembox > ul {
list-style: none;
}
.itembox > ul > li {
line-height: 3;
}
.radial {
position: absolute;
float: right;
height: 35px;
width: 35px;
padding: 2px;
border: 5px solid #e8e8e8;
border-radius: 50%;
top: 43%;
right: 10px;
}
.center-dot {
display: none;
position: relative;
height: 21px;
width: 21px;
background-color: #E16E5B;
border-radius: 50%;
}
.checked {
display: block;
}
.prime-aux:first-of-type {
top: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container">
<!-- Primary Content Container -->
<div class="prime-aux">
<div id="race-internet" class="itembox-container">
<div class="itembox boxes-2">
<h4>Gigabit Internet <span class="price">$60/mo</span></h4>
<ul>
<li>1,000 Mbps</li>
<li>No data caps</li>
</ul>
<div class="radial">
<div class="center-dot"></div>
</div>
</div>
<div class="itembox boxes-2">
<h4>Basic Internet <span class="price">$25/mo</span></h4>
<ul>
<li>25 Mbps</li>
<li>No data caps</li>
</ul>
<div class="radial">
<div class="center-dot"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Primary Content Container End -->
View on JS Fiddle
You can eliminate a lot of your jQuery by just leveraging CSS. Typically, if I want to toggle a feature, I have it either display: block; or display: none; based upon a CSS selector. Then, I just use jQuery to toggle the parent element's class name. So for example:
.item.selected .checkmark {
display: block;
}
.item .checkmark {
display: none;
}
$('.item').click(function(){ $(this).toggleClass('selected') });
JSFiddle

Size of HTML Box in Google site

I am trying to insert a collapsible table with HTML Box in a Google site. The code of the collapsible table is from http://tutorials.seowebpower.com/google-sites-advanced/collapsible-table. The code is
<html>
<head>
<style>
.container {
background-color:deepskyblue;
width: 600px;
height:50px;
position: relative;
}
.title {
font-size: 16pt;
font-weight: bold;
color: aliceblue;
position: absolute;
left: 20px;
top:25%;
}
#opened {
display: none;
}
.arrow-up {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid white;
}
.arrow-down {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid white;
}
.arrow-up, .arrow-down {
position: absolute;
top: 40%;
right:15px;
}
.hidden-content {
margin:0 0 20px 0;
padding: 10px 20px 10px 20px;
border: 1px solid deepskyblue;
border-top: none;
background-color: aliceblue;
}
</style>
<script>
var collapse;
var uncollapse;
var turnOn = true;
// Chrome Sites Fix
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
function tempChromefix() {
// To turn off set true to false
if (turnOn == false && is_chrome) {
document.getElementById("opened").style.display = "block";
document.getElementById("closed").style.display = "none";
} else {
return false;
}
}
function uncollapse() {
document.getElementById("closed").style.display = "block";
document.getElementById("opened").style.display = "none";
}
function collapse() {
document.getElementById("opened").style.display = "block";
document.getElementById("closed").style.display = "none";
}
</script>
</head>
<body onLoad="tempChromefix()">
<table id="closed">
<tr>
<td>
<div class="container" onclick="collapse()">
<div class="title">Click to open drop-down</div>
<div class="arrow-down"></div>
</div>
</td>
</tr>
</table>
<table id="opened">
<tr>
<td>
<div class="container" onclick="uncollapse();">
<div class="title">Click to close drop-down</div>
<div class="arrow-up"></div>
</div>
<div class="hidden-content">
<h3>It works!</h3>
<p>This content is to be hidden from the user until clicked. </p>
</div>
</td>
</tr>
</table>
</body>
</html>
The problem I am facing is with width of the table. I would like it to have maximum possible width depending on the screen size. For example, I would like to have the table expand to the screen size in my MacBook as well as in iMac.
The logical way is to use the width: 100% so that the table inherits its parent's screen size. However it seems that inside an HTML Box the different categories does not inherit parent's attribute.
For example in the .container section, if I use width: 100%, it collapses to zero width instead of full size of the screen.
Would appreciate any help!
--- Madhur
I had this issue also, and eventually figured out (the very un-intuitive) way is to hover over the HTML box, and then click on the "Align center" icon. When you save, elements will be the full width (my div's were at least).

Categories