Keep getting "cannot read property style of null" error - javascript

I am working on my own website and not good with codes yet. When I am scrolling down I want to appear another content of the navbar and when I am on the top, original navbar is appearing. I want this to be done in pure JavaScript with no libraries or framewokrs. Please see codes below and I know that codes are not organised. I will do that later on.
var nav = document.querySelector("nav");
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
window.onscroll = function(){
if(document.body.scrollTop > 70){
hide.style.display = "block";
appear.style.display = "none"
} else {
hide.style.display = "none";
appear.style.display = "block"
}
}
nav{
list-style-type: none;
text-align: center;
background-color: #3FA9A5;
position: sticky;
top: 0;
}
.hide{
font-size: 70px;
font-family: 'Long Cang', cursive;
display: block;
}
.appear{
height: 70px;
display: none;
}
.appear img{
width: 210px;
}
ul{
margin: 0 auto;
padding: 0;
}
body{
margin: 0;
}
.container{
max-width: 1080px;
width: 95%;
margin: 10px auto;
display: grid;
grid-template-columns: 25% 50% 25%;
}
.text{
text-align: center;
}
.profile {
border: 1px solid black;
padding: 0 10px 20px 10px;
}
#main{
width: 100%;
}
.post{
margin-left: 4.165%;
}
#image{
width: 100%;
}
#post-divide{
margin-left: 10px;
margin-right: 10px;
}
.comments{
width: 100%;
margin-top: 68.5px;
padding-bottom: 293.5px;
border: 1px solid black;
}
h2{
text-align: center;
}
.center{
grid-column: 2;
}
<link rel="stylesheet" type="text/css" href="test.css">
<link href="https://fonts.googleapis.com/css?family=Indie+Flower|Long+Cang&display=swap" rel="stylesheet">
<title>test</title>
</head>
<body>
<nav>
<ul>
<li class="hide">Unknown</li>
<li class="appear"><img src="cat.png"></li>
</ul>
</nav>
<div class="container">
<div class="col-1">
<div class="profile text">
<img id="main" src="https://data.whicdn.com/images/86629641/superthumb.jpg?t=1384568664">
<hr>
<p>12 posts</p>
<p>instagram</p>
<button>Subscribe!</button>
</div>
</div>
<div class="col-1">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
<div class="col-1 center">
<div class="post">
<h2>TITLE</h2>
<div>
<img id="image" src="https://i.pinimg.com/originals/76/d4/8c/76d48cb2928845dfcfab697ac7cbcf1c.jpg">
</div>
<hr id="post-divide">
</div>
</div>
<div class="col-1">
<div class="comments text"></div>
</div>
</div>
I think I should add something to the JS code but don't know why
Would be thankful if you would advise me how could I write HTML/CSS code so I do not have to create 2 navbars if it is possible

The following instruction:
document.querySelector("hide");
Will query for elements like:
<hide></hide>
Since plain selectors without prefix (div, header, span) will query for the whole element tags, not for classes or attrbitues.
Maybe you meant to query for the class, using the .:
document.querySelector(".hide");

var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear")
So you should use class selector

You are using "hide" and "appear" as selectors but they do not exist in your HTML.
Use ".hide" and ".appear" in your querySelector instead.
var hide = document.querySelector(".hide");
var appear = document.querySelector(".appear");

Since both navbars have a static data, I would suggest to keep both of them and follow with answers of guys, that suggested to update querySelector param. Or you can hide/show the data inside of navbar (in your case it's only ul element) and leave the whole navbar always visible. So you can put classes appear/hide on ul element instea of navbar and then in JS get them with document.querySelector('.navbar .hide') and document.querySelector('.navbar .appear').
Using framework/library will definitely simplify it.
However, if you still want to have only one navbar in pure js/html/css (or it's data just dynamic) I would probably do like this:
HTML:
<nav class="navbar">
<ul>
<li><img src="cat.png"></li>
</ul>
</nav>
somewhere in JS:
var navbarUl = document.querySelector('.navbar ul');
window.onscroll = function() {
if (document.body.scrollTop > 70) {
navbarUl.innerHtml = '';
navbarUl.appendChild(getTopNavbarHTML);
} else {
navbarUl.innerHtml = '';
navbarUl.appendChild(getNavbarHTML);
}
}
getNavbarHTML and getTopNavbarHTML - will return documentFragment with li elements, see for details https://www.w3schools.com/jsref/met_document_createdocumentfragment.asp
But changing DOM during a scroll event can drastically decrease performance of a web app

Related

If a Class Within a Div is Not Found, Insert a Div Before?

I am wanting to display a div .before() another if it does not contain a specific class within it. Though it seems simple enough, somehow I am not able to get it working...
Here's a snippet of the progress I've made so far:
$('.container > #content').not('.entry', function() {
$(this).before('<div class="noentry">No entries to display.</div>');
});
body {
font-size: 16px;
margin: 0;
padding: 0;
border: 0;
}
h1 {
font-size: 22px;
margin-top: 0;
}
.container {
margin: 0 auto;
max-width: 300px;
border: 1px solid lightgrey;
padding: 10px;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>Section With an Entry:</h1>
<div id="content">
<div class="entry">This is an entry.</div>
</div>
</div>
<div class="container">
<h1>Section Without an Entry:</h1>
<div id="content"></div>
</div>
The .not() method does not work as you are expecting. It only checks the immediate object for the .entry class. You need to search descendants. See the updated example below, you can use a .find().
Also, as noted in the comments above, you shouldn't duplicate ids, so I changed your content to a class.
$(function() {
$('.container > .content').each(function() {
if (!$(this).find(".entry").length) {
$(this).before('<div class="noentry">No entries to display.</div>');
}
});
});
body {
font-size: 16px;
margin: 0;
padding: 0;
border: 0;
}
h1 {
font-size: 22px;
margin-top: 0;
}
.container {
margin: 0 auto;
max-width: 300px;
border: 1px solid lightgrey;
padding: 10px;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>Section With an Entry:</h1>
<div class="content">
<div class="entry">This is an entry.</div>
</div>
</div>
<div class="container">
<h1>Section Without an Entry:</h1>
<div class="content"></div>
</div>

How to make different video answers in list of questions?

I need to make popup which have to contain questions and video answers.
The tricky part for me is how to make every question to display different video, but on the same place. Also when the user first sees the popup the first question and video should be predefined.
Here is the basic scheme of the popup:
Set every video to display:none, then use jQuery to display the needed item once some user action is taken. In my example I used .click()
Basic example:
$(".options>li").click(function() {
$(".view").css('display', 'none')
});
$("li.aaa").click(function() {
$(".view.aaa").css('display', 'block')
});
$("li.bbb").click(function() {
$(".view.bbb").css('display', 'block')
});
$("li.ccc").click(function() {
$(".view.ccc").css('display', 'block')
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
display: flex;
width: 90vw;
margin: 0 auto;
align-items: center;
}
.panel {
display: inline-block;
width: 50%;
}
.view {
max-width: 100%;
display: none;
border: 1px solid red;
}
.options>li {
width: 100%;
background: grey;
list-style: none;
margin: .25em auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="panel right">
<ul class="options">
<li class="aaa">aaa</li>
<li class="bbb">bbb</li>
<li class="ccc">ccc</li>
<li class="ddd"></li>
<li class="eee"></li>
</ul>
</div>
<div class="panel left">
<img src="http://fruitandvegetablesmelbourne.com.au/wp-content/uploads/2015/04/golden-delicious-apples.jpg" class="view aaa">
<img src="http://img.aws.livestrongcdn.com/ls-article-image-400/cpi.studiod.com/www_livestrong_com/photos.demandstudios.com/56/251/fotolia_5712687_XS.jpg" class="view bbb">
<img src="http://timesofindia.indiatimes.com/thumb/msid-49502853,width-400,resizemode-4/49502853.jpg" class="view ccc">
</div>
</div>

How to implement this layout

I found a web page which shows only 3 events in a grid and when the screen is re-sized less a certain width, it not only relocates the 3 events into a list but also changes the layout inside each event.
I have tried many ways to make it look like that web page, but have not got any luck.
this is the web page
And this is what I have done: CodePen
/* -- DEFAULTS -- */
div, ul, li {
margin: 0;
padding: 0;
list-style-type: none;
}
/* -- FLUID GRID STYLES -- */
#Grid {
margin-bottom: 40px;
text-align: justify;
font-size: 0.1px;
}
#Grid li {
display: inline-block;
background: #eee;
width: 23%;
padding-top: 23%;
/* Used instead of height to give elements fluid, width-based height */
margin-bottom: 2.5%;
}
#Grid:after {
content: 'haha';
display: inline-block;
width: 100%;
border-top: 10px dashed #922d8d;
/* Border added to make element visible for demonstration purposes */
}
ul li .icon {
width: 100%;
display: table;
min-height: 300px;
height: 300px;
padding: 0;
background: #545454 url(https://www.nike.com/events-registration/client-dist/assets/images/multi-card-bg.png) no-repeat center center;
}
#Grid .placeholder {
padding: 0;
border-top: 10px solid #922d8d;
/* Border added to make element visible for demonstration purposes */
}
/* -- MEDIA QUERIES DEFINING RESPONSIVE LAYOUTS -- */
/* 3 COL */
#media (max-width: 800px) {
#Grid li {
width: 31%;
padding-top: 31%;
margin-bottom: 3%;
}
}
/* 2 COL */
#media (max-width: 600px) {
#Grid li {
width: 48%;
padding-top: 48%;
margin-bottom: 4%;
}
}
/* SINGLE COL */
#media (max-width: 400px) {
#Grid li {
width: 100%;
padding-top: 100%;
margin-bottom: 5%;
}
}
/* -- LEGEND STYLES (NOT PART OF GRID FRAMEWORK) -- */
h1 {
font: 600 20px"Helvetica Neue";
text-align: right;
text-transform: uppercase;
}
label {
padding: 8px 15px;
margin-bottom: 20px;
display: block;
font: 100 22px"Helvetica Neue";
border-left: 10px solid #922d8d;
}
label:last-of-type {
border-left: 10px dotted #922d8d;
}
p {
font: 200 15px/1.5em"Helvetica Neue";
max-width: 400px;
margin-bottom: 30px;
color: #333;
}
Update
Here is my updated code. The problem is I cannot place the "1 JAN" and "NEW YEAR" in the middle of the div.
Updat 2
<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap#*" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-4 col-xs-12">
<div class="row hidden-xs icon">
<div class="title">1 JAN</div>
<div class="event-time"><i>8:00PM</i></div>
<div class="sub-title">This Event is Full</div>
</div>
<div class="row hidden-xs sub-icon">
<div><span>LRC Thursday Night Run test long long</span></div>
<div>
<input type="button" class="btn btn-primary" value="Register" />
</div>
</div>
<div class="row hidden-sm event-sm">
<div class="col-xs-4 event-left">
<div class="event-day">01</div>
<div class="event-month">JAN</div>
<div class="event-time"><i>8:00PM</i></div>
</div>
<div class="col-xs-8 event-right">
<div class="event-notice">This event is full</div>
<div class="event-title">NIKE RUN 10 KM</div>
<div class="event-slogan">Come run with us</div>
</div>
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="well well-sm">
<h1 class="text-center hidden-xs">14 FEB</h1>
<p class="text-center hidden-xs">Valentine</p>
<div class="row hidden-sm">
<div class="col-xs-4"><i>February 14th</i>
</div>
<div class="col-xs-8">Ah! Lovey Dovey Day... Where is my chocolate?</div>
</div>
</div>
</div>
<div class="col-sm-4 col-xs-12">
<div class="well well-sm">
<h1 class="text-center hidden-xs">1 APR</h1>
<p class="text-center hidden-xs">April Fool</p>
<div class="row hidden-sm">
<div class="col-xs-4"><i>April 1st</i>
</div>
<div class="col-xs-8">Your car just got stolen.... JUST KIDDING!!!</div>
</div>
</div>
</div>
</div>
</div>
<script data-require="jquery#2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script data-require="bootstrap#*" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="script.js"></script>
</body>
</html>
If you are already using Bootstrap, you already have this capability. Use hidden-.. and the col-xx-... classes to make your page responsive.
See this example: http://embed.plnkr.co/IH4WeZ/
It's all done using bootstrap css. The trick is to hide stuffs at certain media query and show them whenever appropriate.
I only coded it be responsive at small and extra small size, so on medium and large it's a bit bonker... but you get the idea...
You could use the Bootstrap grid system to do something like this.
You could use a combination of the columns, and offset to achieve this.
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
That will span three columns across the full width of the page. You could experiment with smaller width columns, and adding an offset to the first one to push it away from the left edge.
http://getbootstrap.com/css/#grid-offsetting
If you want to achieve a similar effect, try and replicate it with minimal code and work from there.
Here is a simple example I have knocked up to get the layout working:
http://codepen.io/anon/pen/OPeXgj
HTML
<ul class="events">
<li>Event Name</li>
<li>Event Name</li>
<li>Event Name</li>
</ul>
CSS
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.events {
clear: both;
width: 100%;
max-width: 1000px;
margin: 0 auto;
padding: 0;
list-style: none;
}
.events li {
float: left;
clear: both;
width: 100%;
background: yellow;
margin: 0;
padding: 10px;
}
#media only screen and (min-width: 768px) {
.events li {
width: 33.3%;
clear: none;
}
}
Using a mobile first approach, child items are styled with a width: 100%; and clear: both; Then, with a simple media query, I float them left and set a width to around a 3rd (33.3%) (there could be a better way, but this was a quick fix).
If you're using a grid system, it may be even easier. I would look into Bootstrap or Foundation, as many of these problems have already been solved many times over.
Good luck!
Last resort solution is to code two versions. One for mobile and another one for desktop. Then use media queries to hide one on mobile resolution and the other on desktop.
This will add some extra load on the page, but it should do it.

HTML/JavaScript: Sidebar expand/collapse button

So I'm using this "Color Admin Responsive Admin Template" (http://wrapbootstrap.com/preview/WB0N89JMK) and I have a sidebar menu, and I have the expand/collapse button displaying, but the actual function is not working. I'm not sure exactly why it isn't working, I got the function from the template. I'm pretty new to JavaScript but I think everything that I needed to change on my specific HTML matches the function.
HTML
<!--sidebar left start-->
<!-- begin #sidebar -->
<div id="sidebar" class="sidebar">
<!-- begin sidebar scrollbar -->
<div data-scrollbar="true" data-height="100%">
<!-- begin sidebar user -->
<ul class="nav">
<li class="nav-profile">
<div class="info">
Matt Smith
<small>Manager</small>
</div>
</li>
</ul>
<!-- end sidebar user -->
<ul class="nav">
<!-- begin sidebar minify button -->
<li><i class="fa fa-angle-double-left"></i></li>
<!-- end sidebar minify button -->
</ul>
</div>
<!-- end sidebar scrollbar -->
</div>
<!--sidebar left end-->
JavaScript
var handleSidebarMinify = function() {
$('[data-click=sidebar-minify]').click(function(e) {
e.preventDefault();
var sidebarClass = 'page-sidebar-minified';
var targetContainer = '#page-container';
if ($(targetContainer).hasClass(sidebarClass)) {
$(targetContainer).removeClass(sidebarClass);
if ($(targetContainer).hasClass('page-sidebar-fixed')) {
generateSlimScroll($('#sidebar [data-scrollbar="true"]'));
}
} else {
$(targetContainer).addClass(sidebarClass);
if ($(targetContainer).hasClass('page-sidebar-fixed')) {
$('#sidebar [data-scrollbar="true"]').slimScroll({destroy: true});
$('#sidebar [data-scrollbar="true"]').removeAttr('style');
}
// firefox bugfix
$('#sidebar [data-scrollbar=true]').trigger('mouseover');
}
$(window).trigger('resize');
});
};
http://jsfiddle.net/BootstrapOrBust/71og00ev/1/
You do not include jQuery library in your html. I've added check for JQuery at the top of your code:
alert(typeof jQuery !== "undefined")
it returns false that means you don't add JQuery. You can see the Uncaught ReferenceError: $ is not defined error on browser console. Updated JSFiddle
You can do this (without an animation) without any javascript at all, using the css's :hover.
EDIT: I just realised you wanted to control the expansion and collapse with buttons. This answer doesn't address that, but I'll leave it here anyway as an alternative.
JSFiddle: http://jsfiddle.net/2byg62z4/
<style>
body { margin: 0; }
#sidepanel
{
position: absolute;
min-width: 30px;
height: 60%;
top: 20%;
left: 0;
}
#bar
{
display: table;
background-color: #999999;
color: white;
width: 30px;
height: 100%;
text-align: center;
}
#bar div
{
display: table-cell;
vertical-align: middle;
}
#panel
{
display: none;
background-color: #999999;
color: white;
width: 300px;
height: 100%;
text-align: center;
}
#panel div
{
display: table-cell;
vertical-align: middle;
}
#sidepanel:hover #bar { display: none; }
#sidepanel:hover #panel { display: table; }
</style>
<div id='sidepanel'>
<div id='bar'>
<div>
><br>><br>>
</div>
</div>
<div id='panel'>
<div>
stuff
</div>
</div>
</div>

With jQuery how can you make all of the parent divs and body expand in height to accommodate content?

Objective
To have the page the page on my website to expand in height according to the dynamic data pushed into the container.
Background
The page has a set of images and text that is populated via a JSON feed. The text is overflowing into the footer because it is not expanding its containing div which would subsequently expand its containing div which would subsequently expand the body. So I need for a specific child div to push its multiple parent divs.
I have searched similar problems on Stackoverflow and attempted various CSS solutions such as giving all of the parent divs a CSS rule of clear:both or even in the HTML inserting a <div style="clear:both"></div> but none of those solutions worked.
So now I am experimenting with jQuery to see if I could find a solution to this problem.
I know I need to create a variable of some sort like
var newHeight = $("#carousel").height();
And that it needs to have push out the height with something like
$(".case").height(newHeight);
This is my current HTML
<body>
<div class="container">
<div class="block push">
<div id="mainContent" class="row">
<div class="large-12 columns">
<h1>Before & After Case Gallery</h1>
<div id="casesContainer">
<div id="carousel"></div>
</div>
<script id="casestpl" type="text/template">
{{#cases}}
<div class="case">
<div class="gallery_images_container">
<div class="item_container">
<div class="gallery_heading">BEFORE</div>
<img src="/assets/img/content/images-bruxzir-zirconia-dental-crown/cases/{{image}}_b_300.jpg" alt="Photo of {{alt}}" />
</div>
<div class="item_container">
<div class="gallery_heading">AFTER</div>
<img src="/assets/img/content/images-bruxzir-zirconia-dental-crown/cases/{{image}}_a_300.jpg" alt="Photo of {{alt}}" />
</div>
</div>
<div class="description_container">
<p>
<span><strong>Case Number {{{number}}} {{version}}:</strong></span>
{{{description}}}
</p>
</div>
</div>
{{/cases}}
</script>
The {{{description}}} in the <p> is overflowing into its parent divs <div class="description_container"> then <div class="case"> then <div id="carousel"> then <div class="casesContainer"> then <div class="large-12"> (which is a container in Foundation) then <div class="mainContent"> and so on.
Here is my CSS
html, body { height: 100%; }
.container { display: table; height: 100%; width: 100%; margin: 0 auto; }
.block { display: table-row; height: 1px; }
.push { height: auto; }
#mainContent {}
#casesContainer {
min-width:310px;
}
.image-navigation {
background: rgb(6,6,6);
color: #fff;
width:100%;
max-width: 640px;
height: 24px;
}
.image-navigation a {
color: #fff;
padding: 6px;
}
.image-navigation-previous, .image-navigation-next{
float:left;
width: 50%;
}
.image-navigation-previous {
text-align: right;
}
.image-navigation-next {
text-align: left;
}
#carousel {
height:auto;
min-height:600px;
overflow-y: auto;
}
.case {
max-width: 640px;
height:auto;
}
.gallery_images_container {
clear: both !important;
}
.item_container{
max-width: 320px;
float: left;
}
.gallery_heading {
background: black;
color: white;
width: 100%;
text-align: center;
}
.description_container {
background: none repeat scroll 0% 0% white;
min-width: 308px;
max-width: 640px;
padding: 6px 6px 12px 6px;
clear: both !important;
}
I realize that #carousel { height:auto; min-height:600px; overflow-y: auto; } is an ugly hack. It was just an experiment.
I hope that I am just completely missing something and this is an easy jQuery fix. Or maybe my HTML and CSS could use a different structure?
Not a complete fix but maybe helpful.
I've used this function but Internet Explore increases the heights on resize.
$(document).on('ready', function() {
// $(window).on('resize', function() {
var height1 = $("#r1c1").height();
if (height1 < $("#r1c2").height()) { height1 = $("#r1c2").height() }
if (height1 < $("#r1c3").height()) { height1 = $("#r1c3").height() }
$("#r1c1").height(height1);
$("#r1c2").height(height1);
$("#r1c3").height(height1);
// }).trigger('resize'); // Trigger resize handlers not working correctly with IE8.
});//ready

Categories

Resources