I am currently trying to create a Character Selection for Airconsole.
I thought I could create this using a Jquery method like a Gallery.
So I need a previous button, a next button and the character display.
It seems that I am making a mistake that I can't figure out, because I am not used to working with Javascript.
var speed = 100;
$(".prev").click(function() {
var now = $(this).parent().next("ul.char_display").children(":visible"),
last = $(this).parent().next("ul.char_display").children(":last"),
prev = now.prev();
prev = prev.index() == -1 ? last : prev;
now.fadeOut(speed, function() {
prev.fadeIn(speed);
});
});
$(".next").click(function() {
var now = $(this).parent().next("ul.char_display").children(':visible'),
first = $(this).parent().next("ul.char_display").children(':first'),
next = now.next();
next = next.index() == -1 ? first : next;
now.fadeOut(speed, function() {
next.fadeIn(speed);
});
});
$(".char_display li").click(function() {
var first = $(this).parent().children(':first'),
next = $(this).next();
next = next.index() == -1 ? first : next;
$(this).fadeOut(speed, function() {
next.fadeIn(speed);
});
});
.prev {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.next {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.char_display li {
display: none;
list-style: none;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char_display li:first-child {
display: block;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char_display {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#char1 {
background: blue;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#char2 {
background: red;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="characterScreen_characterBlock">
<div id="characterScreen_leftArrow" class="characterScreen_left" ontouchend="otherChar(true);" ontouchend="otherChar(true);">
<div class="prev"></div>
</div>
<div id="characterScreen_characterDisplay" class="characterScreen_center">
<ul class="char_display">
<li>
<div class="char" id="char1"></div>
</li>
<li>
<div class="char" id="char2"></div>
</li>
</ul>
</div>
<div id="characterScreen_rightArrow" class="characterScreen_right" ontouchend="otherChar(false);" ontouchend="otherChar(false);">
<div class="next"></div>
</div>
</div>
I haven't look through all of your code, but I am pretty sure
$(this).parent().next("ul.char_display").children("...")
doesn't do what you want it to. Especially since it always returns an error for pushing the next-button.
$.next() returns the next DOM-element. characterScreen_rightArrow however doesn't have a next element (in this snippet)
What you were searching for is probably $.siblings(). Personally I would however use the qualifier #characterScreen_characterDisplay ul instead of searching for it relatively.
Related
I'm having a hard time figuring out why the code below doesn't work as expected.
What I'm trying to achieve is same functionality with position:sticky whereas when the scrolled reaches the top of the #second-header then fixes its position below the #header which is also fixed, however, the height of the #header is unknown which is I believe can be calculated using the function outerHeight(true) on JQuery.
Then after reaching out to the bottom of the #second-header-container, remove the fixed position of #second-header turning it back to normal position.
Due to browser compatibility issues and other customization, I cannot simply use the position:sticky of css.
It looks like my logic is wrong, and I need help.
jQuery(document).ready(function(){
var $document = jQuery(document);
var header = jQuery('#header');
var second_header = jQuery('#second-header-container').find('#second-header');
var second_header_container = jQuery('#second-header-container');
var second_header_offset = second_header.offset().top;
var second_header_container_offset = second_header_container.offset().top;
jQuery(window).scroll(function(){
var top_margin = header.outerHeight(true);
var second_header_height = second_header.outerHeight(true);
var second_header_container_height = second_header_container.outerHeight(true);
if( jQuery(window).scrollTop() > (second_header_offset - second_header_height) && jQuery(window).scrollTop() < second_header_container_height) {
second_header.addClass('fixer');
second_header.css({position:'fixed', top:top_margin, 'z-index':'999999'});
} else {
second_header.removeClass('fixer');
second_header.css({position:'relative', top:'0px', 'z-index':'0'});
}
});
});
*{
color: #FFFFFF;
padding: 0;
margin: 0;
}
.fixer{
position: fixed;
width: 100%;
}
#header, .banner, #second-header, .contents{
padding: 5px;
}
#header{
position: fixed;
width: 100%;
height: 74px;
z-index: 99999;
background-color: #000000;
}
.banner{
padding-top: 84px;
height: 200px;
background-color: #583E5B;
}
#second-header-container{
min-height: 300px;
background-color: #775F5E;
}
#second-header{
padding-bottom: 10px;
padding-top: 10px;
background-color: #4C3D3C;
}
.contents{
min-height: 200px;
background-color: #97A36D;
}
.footer{
background-color: #80A379;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header id="header">HEADER</header>
<div class="banner">BANNER</div>
<div id="second-header-container">
<div id="second-header">SECOND-HEADER</div>
<!--Other contents and elements...-->
</div>
<div class="contents">OTHER...</div>
<footer class="contents footer">FOOTER</footer>
To achieve this you need first check if the scroll height is near the second div header and within the height of the second div. Then add a class that make it stick below the main header. I have created a sticky class and added it while scrolling conditions are met.
Please check below code
jQuery(document).ready(function() {
var headerHeight = $('#header').outerHeight(true);
var secondHeaderContainer = $('#second-header-container');
const secondHeaderTopPos = secondHeaderContainer.offset().top;
const secondHeaderContainerHeight = $(secondHeaderContainer).height();
$(window).scroll(function() {
const scrollTop = $(this).scrollTop();
const secondContainerHeightEnd = secondHeaderContainerHeight + secondHeaderTopPos - $('#second-header').height() - headerHeight;
if (((secondHeaderTopPos - headerHeight) <= scrollTop) && (secondContainerHeightEnd >= scrollTop)) {
$('#second-header').addClass('sticky').css('top', headerHeight);
} else {
$('#second-header').removeClass('sticky');
}
});
});
* {
color: #FFFFFF;
padding: 0;
margin: 0;
}
.sticky {
position: fixed;
width: 100%;
top: 0;
left: 0;
}
.fixer {
position: fixed;
width: 100%;
}
#header,
.banner,
#second-header,
.contents {
padding: 5px;
}
#header {
position: fixed;
width: 100%;
height: 74px;
z-index: 99999;
background-color: #000000;
}
.banner {
padding-top: 84px;
height: 200px;
background-color: #583E5B;
}
#second-header-container {
min-height: 300px;
background-color: #775F5E;
}
#second-header {
padding-bottom: 10px;
padding-top: 10px;
background-color: #4C3D3C;
}
.contents {
min-height: 200px;
background-color: #97A36D;
}
.footer {
background-color: #80A379;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header id="header">HEADER</header>
<div class="banner">BANNER</div>
<div id="second-header-container">
<div id="second-header">SECOND-HEADER</div>
<!--Other contents and elements...-->
</div>
<div class="contents">OTHER...</div>
<footer class="contents footer">FOOTER</footer>
I have this small code which changes div after every 20 seconds. it works if I saved that in a small HTML file. it works if I save the live HTML code and run but it does not fire in the live site.
you can see that every 20 seconds the bar is getting changed but in my live site, it is not changing. live site is here.
https://pushdaddy2.myshopify.com/products/uhjkjhkhk
but if I save the live site code in desktop and launch that code in chrome it works.
https://jsfiddle.net/anamika99/vhmo7ex4/
jQuery(document).ready(function($) {
var allBoxes = $("div#qab_container").children("div");
transitionBox(null, allBoxes.first());
// console.log(allBoxes);
$("#qab_background1, #qab_background2, #qab_background3, #qab_background4, #qab_background5, #qab_background6").css({
"height": $("#qab_background").innerHeight()
});
});
function transitionBox(from, to) {
function next() {
var nextTo;
if (to.is(":last-child")) {
nextTo = to.closest("#qab_container").children("div").first();
} else {
nextTo = to.next();
}
to.fadeIn(500, function() {
setTimeout(function() {
transitionBox(to, nextTo);
var karreff = 787786766;
console.log(karreff);
}, 3000); // 20000 on site
});
}
if (from) {
from.fadeOut(500, next);
} else {
next();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="shopify-section-header" class="shopify-section">
<div id="qab_container" style="display: block; color: inherit; height: 44px;">
<div id="qab_background" onclick="qab_button_on_click(event)" style="opacity: 1; margin: 0px; padding: 0px; left: 0px; height: auto; width: 100%; z-index: 99998; position: fixed; cursor: pointer; background-image: url("https://way2enjoy.com/shopify/1/announcementbar/js/img/bar_background/20170926_cart.png"); top: 0px;">
<div id="qab_bar" style="text-align: center; margin: 0px; padding: 12px 10px; left: 0px; height: auto; width: 100%; box-sizing: border-box; border: none; background-color: rgba(5, 175, 242, 0); color: rgb(242, 242, 242); font-size: 16px; line-height: 20px; font-family: Helvetica;">
<div id="qab_content" style="text-align:center; display: inline-block;"><span id="qab_message" style="color:inherit;">All t-shirts are 15% off </span> </div>
</div>
</div>
<div id="qab_background1" onclick="qab_button_on_click1(event)" style="opacity: 0; margin: 0; padding: 0; left: 0; height: auto; width: 100%; z-index: 1000000; position: relative; cursor: pointer;">
<div id="qab_bar1" style="text-align: center; margin: 0; padding: 10px; left: 0; height: auto; width: 100%; box-sizing: border-box; border: none;">
<div id="qab_content1" style="text-align:center; display: inline-block;">
<span id="qab_message1" style="color:inherit;">fghghghh hghghhfhhf fhfgf</span>
</div>
</div>
</div>
</div>
</div>
solved this by triggering the function only when all data are loaded.
we have set the settimeout for allBoxes
earlier what was happening that our javascript code was taking some time to insert in html and before that full code was executing and that time in real there was no data we needed so we set the settimeout of 10 second and then everything was working because in this 10 second everything was in loaded in DOM and we were ready with full data.
here is full code which is working flawlessly
jQuery(document).ready(function($) {
setTimeout(function () {
var allBoxes = $("div#qab_container").children("div");
transitionBox(null, allBoxes.first());
console.log(allBoxes);
}, 10000);
$("#qab_background1, #qab_background2, #qab_background3, #qab_background4, #qab_background5, #qab_background6").css({"height": $("#qab_background").innerHeight()});
});
function transitionBox(from, to) {
function next() {
var nextTo;
if (to.is(":last-child")) {
nextTo = to.closest("#qab_container").children("div").first();
} else {
nextTo = to.next();
}
to.fadeIn(500, function () {
setTimeout(function () {
transitionBox(to, nextTo);
var karreff=787786766;
console.log(karreff);
}, 20000);
});
}
if (from) {
from.fadeOut(500, next);
} else {
next();
}
}
After clicking elements (the red square), the func function gets called and it gets the first child node, then that node changes It's children display to block. Now, I'm trying to set them back to none after clicking background_dim (the dark background) by getting background_dim's parent node, then iterating throught the children and setting their display to none. But apparently this doesn't work. It only works If I set their position to relative, but I'd have to change the other function as well.
function func(element) {
var _first_child = element.children[0];
for (var i = 0; i < _first_child.children.length; ++i)
_first_child.children[i].style.display = "block";
}
function func_t(element) {
var _parent = element.parentNode;
for (var i = 0; i < _parent.children.length; ++i)
_parent.children[i].style.display = "none";
}
.elements {
width: 40px;
height: 40px;
background-color: red;
}
.background {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
background-color: rgb(0, 0, 0, 0.7);
}
.display-container
{
display: none;
position: fixed;
top: 50%;
bottom: 30%;
left: 50%;
right: 0;
height: 100%;
width: 100%;
background-color: green;
}
<html>
<body>
<ul>
<li class="elements" onclick="func(this);">
<div class="_display_job_dim_">
<div class="background" onclick="func_t(this);"></div>
<div class="display-container"></div>
</div>
</li>
</ul>
</body>
</html>
https://jsfiddle.net/waxebm81/285/
Your problem is that if a click happens on background_dim it will by default propagate up in the DOM, so after func_t was called, the event will propagate to .elements and func(this) is called which will show the elements again.
So you ned to stop the propagation of the event:
document.querySelector('.elements').addEventListener('click', func, false)
document.querySelector('.background_dim').addEventListener('click', func_t, false)
function func(evt) {
evt.stopPropagation();
var element = evt.target;
var _first_child = element.children[0];
for (var i = 0; i < _first_child.children.length; ++i) {
_first_child.children[i].style.display = "block";
}
}
function func_t(evt) {
evt.stopPropagation();
var element = evt.target;
var _parent = element.parentNode;
for (var i = 0; i < _parent.children.length; ++i) {
_parent.children[i].style.display = "none";
}
return false;
}
.elements {
width: 40px;
height: 40px;
background-color: red;
}
.background_dim {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
background-color: rgb(0, 0, 0, 0.7);
}
.display-container {
display: none;
position: fixed;
top: 50%;
bottom: 30%;
left: 50%;
right: 0;
height: 100%;
width: 100%;
background-color: green;
}
<html>
<body>
<ul>
<li class="elements">
<div class="_display_job_dim_">
<div class="background_dim"></div>
<div class="display-container"></div>
</div>
</li>
</ul>
</body>
</html>
My Code:
window.addEventListener('scroll', scrollWhere);
function scrollWhere(e) {
var windowScroll = $(window).scrollTop();
var idScroll = $('.me').offset().top;
var height = $("#half-who").height();
if (windowScroll > idScroll) {
$('.me').addClass('me-fixed');
} else {
$('.me').removeClass('me-fixed');
}
}
I want to add a class when the scroll is past a certain point and remove it when is smaller than that certain point.
Get your idScroll value outside scrollWhere function as because it re-initiate calculation again and again and returns different values each time as because it has a fixed position. check below snippet for reference.
window.addEventListener('scroll', scrollWhere);
var idScroll = $('.me').offset().top;
function scrollWhere(e) {
var windowScroll = $(window).scrollTop();
//var height = $("#half-who").height();
if (windowScroll > idScroll) {
$('.me').addClass('me-fixed');
} else {
$('.me').removeClass('me-fixed');
}
}
.container {
height: 300vh;
width: 100%;
background-color: grey;
padding: 0;
margin: 0;
}
.content {
height: 100px;
width: 100%;
background-color: cyan;
}
.me {
height: 50px;
width: 100%;
background-color: red;
}
.me-fixed {
position: fixed;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="content"></div>
<div class="me"></div>
</div>
Here's a simple example to add a class when scroll passing a certain point. Hope you can get an idea. >>> JSFiddle
$(window).scroll(function(){
var winH = $(window).scrollTop();
var ruler = $('.ruler').position().top;
if(ruler < winH){
$('.nav').addClass('me-fixed');
}
else{
$('.nav').removeClass('me-fixed');
}
});
body{
height: 1500px;
}
.nav{
height: 50px;
background: #a1bfbe;
color: #000;
width: 100%;
position: relative;
top: 250px;
text-align: center;
}
.nav.me-fixed{
background: #c2debf;
}
p{
font-size: 20px;
display: none;
}
.me-fixed p{
display: block;
}
.ruler{
position: fixed;
top: 150px;
border-bottom: 1px solid red;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav">
<p>
Fixed
</p>
</div>
<div class="ruler">
</div>
Also if you can provide the html and css structure, it will be easy to identify the issue.
I am learning javascript these days and I have a little problem with my code.
I have three elements on page wrapper1, wrapper2 and wrapper3 and every of these has its triggerand redbox element.
My goal is when the trigger is hit, it will show the redbox element corresponding to number.
Examples:
clicking trigger1 inside wrapper1 element shows up redbox1 element,
trigger2 inside wrapper2 element shows up redbox2 element etc.
The problem is, when I click on trigger3 for example it always shows redbox1 element. (as example shows).
What I am doing wrong? I am just a begginer.
function showTheRedBox() {
var theRedBox = document.getElementsByClassName('redbox');
theRedBox[0].style.display = 'block';
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
You can use a for loop and a closure to access the .wrapper information for each onclick event. This method will work whether there are the same amount of children or not, and will always show the correct child.
Also, it is best to not use inline JavaScript attributes (e.g. onclick="showTheRedBox();") you should always assign your event handlers in your script for readability and maintainability.
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
(function(wrapper){
wrapper.querySelector('.trigger').onclick = function() {
hideAll();
wrapper.querySelector('.redbox').style.display = 'block';
}
})(wrappers[i]);
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
(function(wrapper){
wrapper.querySelector('.trigger').onclick = function() {
hideAll();
wrapper.querySelector('.redbox').style.display = 'block';
}
})(wrappers[i]);
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
This method will also work, but it will use more memory as it queries the DOM once more than the above solution.
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
wrappers[i].querySelector('.trigger').onclick = function() {
hideAll();
this.parentNode.querySelector('.redbox').style.display = 'block';
}
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
wrappers[i].querySelector('.trigger').onclick = function() {
hideAll();
this.parentNode.querySelector('.redbox').style.display = 'block';
}
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
The problem you have was that the method "getElementsByClassName", returns you an Array that contains all the elements of that class. So, when you where doing this:
theRedBox[0].style.display = 'block'
You were changing the display style of the First element of the Array, in this case "wrapper1".
Here's a modify version that functions whit the others wrappers:
<!DOCTYPE html>
<html lang = 'es'>
<head>
<title> MY TEST </title>
<style>
body {
background: #222;
}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(0)">trigger1</div> <!-- When the onClick event is trigered the function "showTheRedBox receives a parameter , that parameter is the position of the element in the Array "theRedBox"-->
<div class="redbox">hurrah1</div>
wrapper1
</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(1)">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2
</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(2)">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
<script>
function showTheRedBox(wrapperNumber) {
var theRedBox = document.getElementsByClassName('redbox');
theRedBox[wrapperNumber].style.display = 'block';
}
</script>
</body>
</html>