Guy's I'm a bit stick on this project. Trying to create a Google Calander page. Giving a function an array of objects each object having 2 properties, start and end, print the following to the screen.
I'm almost done.... this is what I have so far
I'm stock on the positioning. If I should make the inner div's absolute or relative. Because when I make them relative, they drop down to much, if I make the absolute, then having trouble aligning them correctly.
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Title</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="wrapper">
<div id="canv" class="canvas">
<!-- <div class="event">
<h1>Sample Item</h1>
<p>Sample location</p>
</div> -->
</div>
<div class="time">
<p>9:00 <span class="am">AM</span></p>
<p class="thirty">9:30</p>
<p>10:00 <span class="am">AM</span></p>
<p class="thirty">10:30</p>
<p>11:00 <span class="am">AM</span></p>
<p class="thirty">11:30</p>
<p>12:00 <span class="am">PM</span></p>
<p class="thirty">12:30</p>
<p>1:00 <span class="am">PM</span></p>
<p class="thirty">1:30</p>
<p>2:00 <span class="am">PM</span></p>
<p class="thirty">2:30</p>
<p>3:00 <span class="am">PM</span></p>
<p class="thirty">3:30</p>
<p>4:00 <span class="am">PM</span></p>
<p class="thirty">4:30</p>
<p>5:00 <span class="am">PM</span></p>
<p class="thirty">5:30</p>
<p>6:00 <span class="am">PM</span></p>
<p class="thirty">6:30</p>
<p>7:00 <span class="am">PM</span></p>
<p class="thirty">7:30</p>
<p>8:00 <span class="am">PM</span></p>
<p class="thirty">8:30</p>
<p>9:00 <span class="am">PM</span></p>
</div>
</div>
</div>
<script>
var events = [
{start: 30, end: 150},
{start: 540, end: 600},
{start: 560, end: 620},
{start: 610, end: 670}
];
var canvas = document.getElementById("canv");
var totalElem = 0;
var totalTop = 0;
var total = events.forEach(function(event, index){
var testArr = events;
var test = testArr.length - index;
if(index > 0 && test >=2 ){
totalElem++
}
})
function layOutDay(event){
var newArr = event;
event.forEach(function(event, index){
var env = document.createElement("div"),
h1 = document.createElement("h1"),
p = document.createElement("p"),
sampleItem = document.createTextNode("Sample Item"),
sampleLocation = document.createTextNode("Sample Location");
p.appendChild(sampleLocation);
h1.appendChild(sampleItem);
env.className = "event";
env.setAttribute('id', index)
env.appendChild(h1);
env.appendChild(p);
canvas.appendChild(env);
//conversion
//totalTop = keeping track of start of each event
var pixelsStart = (event.start * .86);
pixelsEnd = ((event.end - event.start) * .86);
totalTop += pixelsEnd;
console.log(totalTop, 'test');
env.style.top = pixelsStart + "px";
env.style.height = pixelsEnd + "px";
// check start collide with previous event
var test = newArr.length - index;
if(index > 0 && test >=2 ){
var start = event.start,
end = event.end,
check = newArr[index+1].start;
function between(check, start, end) {
return check >= start && check <= end;
}
if (between(check, start, end)) {
var newWidth = (96/totalElem)
env.style.width = newWidth + "%";
}
}
}) // end of loop
// correct placement
// 1. If 2 or more events - done
// 2. Grab values then check range
// 3. if within same range then run logic to divide with evently
// 4. else place elements as is
// var newArr = document.getElementsByClassName("event");
// if(newArr.length > 1){
// var start = obj.start;
// var end = obj.end;
// var check = checkObj.start
// var check = function between(check, start, end) {
// return check >= start && check <= end;
// }
// if (check(600, 560, 620)) {
// console.log('true')
// }
// }
}
layOutDay(events);
</script>
</body>
</html>
css
body {
font-size: 40px;
}
.wrapper {
position: relative;
}
.canvas {
background-color: #ECECEC;
border-left: 2px solid #ABABAB;
height: 620px;
width: 720px;
float: right;
margin-right: 300px;
margin-left: 10px;
position: relative;
}
p {
font-size: 12px;
font-family: Arial, Helvetica, sans-serif;
margin-bottom: 13px;
margin-bottom: 13px;
}
.am {
font-size: 10px;
color: #ADADAD;
}
.thirty {
font-size: 10px;
color: #ADADAD;
}
.wrapper {
width: 1100px;
}
.time {
text-align: right;
position: relative;
}
.event {
background-color: #ffffff;
border: 1px solid #D9D9D9;
border-left: 3px solid #63AF8F;
width: 96%;
margin-left: 10px;
margin-right: 0px;
position: relative;
float: right;
top: 28px;
height: 52px;
overflow: hidden;
}
.event h1 {
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #63AF8F;
padding: 0;
padding-top: 5px;
padding-left: 5px;
margin: 0px;
}
.event p {
padding: 0;
padding-left: 5px;
margin: 0px;
color: #ADADAD;
}
/*# sourceMappingURL=../maps/style.css.map */
I believe the position relative is fine, you need to check your 'top' and 'height' calculations based on start and end positions.
Also, adjust margin positions to align properly.
And can use wrapper div and give some padding there.
Related
Hello lately i've been working with APIs to get the hang of them through the usual weather app project BUT i'm pretty much still a beginner in javascript and i was wondering how to add a background image that matches the weather report of the city selected by the user.
I wanted to create many classes in css, each called like the weather (ex: .clear, .clouds,.rain etc...) and then use a classList.add() method to change it each time depending on the openWeatherMap data. I tried adding something like document.getElementsByTagName("body")[0].classList.add(weatherValue); inside the .then promise but it doesn't work. Can somebody help me? If there's a much simpler way i'd like to hear about it too :) Thank you so much
var button = document.querySelector(".button");
var inputValue = document.querySelector(".inputValue");
var cityName = document.querySelector(".name");
var weather = document.querySelector(".weather");
var desc = document.querySelector(".desc");
var temp = document.querySelector(".temp");
var humi = document.querySelector(".humi");
button.addEventListener("click", function() {
fetch("https://api.openweathermap.org/data/2.5/weather?q="+inputValue.value+"&appid={myapikey}")
.then(response => response.json())
.then(data => {
var nameValue = data['name'];
var weatherValue = data['weather'][0]['main'];
var tempValue = data['main']['temp'];
var descValue = data['weather'][0]['description'];
var humiValue = data['main']['humidity'];
cityName.innerHTML = nameValue;
weather.innerHTML = weatherValue; // this gives "clear" "clouds" etc to <p> element
desc.innerHTML = descValue;
temp.innerHTML = "Temperature: " + tempValue;
humi.innerHTML = "Humidity: " + humiValue;
})
.catch(err => alert("Wrong city name!"))
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Nunito", sans-serif;
background-repeat: no-repeat;
background-size: cover;
}
.input {
text-align: center;
margin: 100px 0;
}
input[type="text"] {
height: 50px;
width: 600px;
background: #e7e7e7;
font-family: "Nunito", sans-serif;
font-weight: bold;
font-size: 20px;
border: none;
border-radius: 2px;
padding: 10px 10px;
}
input[type="submit"] {
height: 50px;
width: 100px;
background: #e7e7e7;
font-family: "Nunito", sans-serif;
font-weight: bold;
font-size: 20px;
border: none;
border-radius: 2px;
}
.display {
text-align: center;
}
.clear {
/* background image here */
}
.clouds {
/* another background image here */
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="weather_app.css">
</head>
<body>
<div class="input">
<input type="text" class="inputValue" placeholder="Enter a city">
<input type="submit" value="Submit" class="button">
</div>
<div class="display">
<h1 class="name"></h1>
<p class="weather"></p>
<p class="desc"></p>
<p class="temp"></p>
<p class="humi"></p>
</div>
<script src= "weather_app.js"></script>
</body>
</html>
I did a project like this not long ago, https://github.com/Kroplewski-M/Weather-App , I used the openWeater API. I did this:
function setBackground(weather) {
if (weather == "Rain") {
background.src = "./resources/rainy-weather.jpg";
} else if (weather == "Snow") {
background.src = "./resources/snowy-weather.jpg";
} else if (weather == "Clear") {
background.src = "./resources/sunny-weather.jpg";
} else if (weather == "Clouds") {
background.src = "./resources/cloudy-weather.jpg";
}
}
The openWeather API returns what condition the weather is so you can just if statement on what the condition is and set the background accordingly
I am trying to build a page:
Like This
When a div gets into the view on the screen, then a class gets added to the right side of the "table of contents", then when it's scrolled off the screen and another div shows up the class gets moved to the next "title" of the content.
So far I have a list of divs stacked on the top of each other and some basic JS but it does not work. I am not even sure if this is a good approach to get this done?
$(window).scroll(function(){
if ( $('#field-wrap1').offset().top <= 100 ) {
$('#slide-li1').addClass("active");
}else{
$('#slide-li1').removeClass("active");
}
});
JSFiddle
<!---
With this code it doesn't require editing the JavaScript
at all, only the HTML/CSS, it will apply the class .qqq_menu_active
to the active menu item and .qqq_section_active to the active section.
--->
<style>
* {
font-family: Arial;
margin: 0;
padding: 0;
}
body {
font-size: 10pt;
}
.qqq_container {
padding: 50px;
}
.qqq_menu {
position: fixed;
width: 200px;
left: 750px;
top: 50px;
}
.qqq_menu_item {
color: #333;
}
.qqq_menu_active {
font-size: 14pt;
font-weight: bold;
color: #000;
}
.qqq_section {
width: 600px;
padding: 25px;
color: #676767;
background-color: #fff;
}
.qqq_section_active {
color: #281c96;
background-color: #bdb6ff;
}
h1 {
padding-bottom: 20px;
}
</style>
<div class="qqq_menu">
<div class='qqq_menu_item'>section_1</div>
<div class='qqq_menu_item'>section_2</div>
<div class='qqq_menu_item'>section_3</div>
<div class='qqq_menu_item'>section_4</div>
<div class='qqq_menu_item'>section_5</div>
</div>
<div class='qqq_container'>
<div class='qqq_section'>
<h1>section_1</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_2</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_3</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_4</h1>
<p class='text_fill'></p>
</div>
<div class='qqq_section'>
<h1>section_5</h1>
<p class='text_fill'></p>
</div>
</div>
<script>
// note: have tried editing .repeat to 3000 to make it a lot of text and 150 to make it a little text and still works right. also added a bunch of space with <br /> above and below the .qqq_container element and still works right.
asdf_text = "asdf ".repeat(750);
document.querySelectorAll(".text_fill").forEach(function (element) {
element.innerHTML = asdf_text;
});
container = document.querySelectorAll(".qqq_container")[0];
sections = document.querySelectorAll(".qqq_section");
menu = document.querySelectorAll(".qqq_menu_item");
percentage = 0;
function qqq_menu_highlight() {
active = 0;
ttt = window.innerHeight / 100;
lll = ttt * percentage;
zzz = window.scrollY + lll;
sections.forEach(function (v, k, l) {
if (zzz > v.offsetTop) {
active = k;
}
});
menu.forEach(function (v, k, l) {
if (active === k) {
v.classList.add('qqq_menu_active');
} else {
v.classList.remove('qqq_menu_active');
}
});
sections.forEach(function (v, k, l) {
if (active === k) {
v.classList.add('qqq_section_active');
} else {
v.classList.remove('qqq_section_active');
}
});
}
function element_scroll_percentage(element) {
//inc = (document.body.scrollHeight - window.innerHeight) / 100;
//console.log(active);
rect = element.getBoundingClientRect();
if (Math.sign(rect.top) == -1) {
value = Math.abs(rect.top);
inc = (rect.height - window.innerHeight) / 100;
percentage = value / inc;
if (percentage > 100) {
percentage = 100;
}
} else {
percentage = 0;
}
return percentage;
}
document.onscroll = function() {
percentage = element_scroll_percentage(container);
qqq_menu_highlight();
//console.log(percentage);
}
document.onscroll();
</script>
In the solution below, I divided the value of this.scrollY by 200, since the height of the containers is 200px. I added the result of this action to the end of the slide-li statement to use as the id of the targeted item.
function removeClass() {
for(let i = 0 ; i < 6 ; i++)
$(`#slide-li${i + 1}`).removeClass("active");
}
$(window).scroll(function(){
console.clear();
console.log(`Scroll: ${this.scrollY}`);
removeClass();
let visibleElement = Math.floor(this.scrollY / 200);
$(`#slide-li${visibleElement + 1}`).addClass("active");
});
#container {
width: 800px;
margin: auto;
text-align: left;
display: inline-flex;
margin: 0;
margin: 100px 0;
}
#field {
width: 500px;
float: left;
font-weight: 500;
color: #001737;
}
.field-wrap {
padding: 0;
border-bottom: 1px solid #8392A5;
height: 200px;
background-color: #FF000030;
}
#slidecart {
position: fixed;
top: 10px;
right: 0px;
width: 300px;
display: inline-block;
padding: 20px;
border-left: 1px solid #8392A5;
}
#slide-ul {
list-style-type: none;
margin: 0;
padding: 5px 0 0 5px;
}
.slide-li {
margin: 0;
padding: 0 0 0 10px;
cursor: pointer;
}
.active {
padding: 0 0 0 5px;
border-left: 5px solid #0168FA;
color: #0168FA;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="field">
<div id="field-wrap1" class="field-wrap">
1.) - Hello World!
</div>
<div id="field-wrap2" class="field-wrap">
2.) - Hello World!
</div>
<div id="field-wrap3" class="field-wrap">
3.) - Hello World!
</div>
<div id="field-wrap4" class="field-wrap">
4.) - Hello World!
</div>
<div id="field-wrap5" class="field-wrap">
5.) - Hello World!
</div>
<div id="field-wrap6" class="field-wrap">
6.) - Hello World!
</div>
</div>
<div id="slidecart">
TABLE OF CONTENTS
<ul id="slide-ul">LIST
<li id="slide-li1" class="slide-li">1.) - Hello World!</li>
<li id="slide-li2" class="slide-li">2.) - Hello World!</li>
<li id="slide-li3" class="slide-li">3.) - Hello World!</li>
<li id="slide-li4" class="slide-li">4.) - Hello World!</li>
<li id="slide-li5" class="slide-li">5.) - Hello World!</li>
<li id="slide-li6" class="slide-li">6.) - Hello World!</li>
</ul>
</div>
</div>
I am creating a collage app that has an dogAPI. When the breed is selected a dog image will appear. I want the image to appear in a random spot on the page but ideally not over the text and dropdown menu. This is what I have tried and here is my codepen. This is an app so it needs to also be responsive.
//Get a random number
let getRandomNum = (num) => {
return Math.floor(Math.random() * Math.floor(num));
}
//show image in a random location
let moveImg = () => {
let dogImgs = document.querySelector('.dogPic')
let w = window.innerWidth;
let h = window.innerHeight;
dogImgs.style.top = getRandomNum(w) + "px";
dogImgs.style.left = getRandomNum(h) + "px";
};
https://codepen.io/drxl/pen/VwbQZyK
Your moveImg function is flawed - it uses querySelector which will only select the first element. It should ideally accept an image as a parameter.
We can declare it like so:
let moveImg = (dogImgs) => {
let w = window.innerWidth;
let h = window.innerHeight;
dogImgs.style.top = getRandomNum(w) + "px";
dogImgs.style.left = getRandomNum(h) + "px";
};
Then, in your createImgs function, simply pass the constructed image as a parameter to moveImg.
// fetches dog breed list/shows error if applicable
async function start() {
try {
const response = await fetch("https://dog.ceo/api/breeds/list/all")
const data = await response.json()
breedList(data.message)
} catch (e) {
console.log("There was a problem fetching the breed list.")
alert("There was a problem fetching the breed list.")
}
}
//load breed list in dropdown menu
start()
function breedList(dogList) {
document.getElementById("breeds").innerHTML = `
<select onchange="loadByBreed(this.value)">
<option>Choose a dog breed</option>
${Object.keys(dogList).map(function (breed) {
return `<option>${breed}</option>`
}).join('')}
</select>
`
}
//load images
async function loadByBreed(breed) {
if (breed != "Choose a dog breed") {
const response = await fetch(`https://dog.ceo/api/breed/${breed}/images`)
const data = await response.json()
createImgs(data.message)
}
}
//show randomized images
function createImgs(images) {
let imageContainer = $(".slideshow");
let dogImgs = $('<img>');
dogImgs.attr("src", images[Math.floor(Math.random() * images.length)]);
dogImgs.addClass("dogPic")
imageContainer.append(dogImgs);
moveImg(dogImgs[0]);
}
//deletes pic if dbl tapped
$(document).on('dblclick', ".dogPic", function () {
$(this).remove();
})
//resets select menu when image has loaded
$("#breeds").on("change", "select", function () {
const value = this.value;
console.log(value);
let select = this
setTimeout(function () {
select.selectedIndex = 0;
}, 800)
});
//Get a random number
let getRandomNum = (num) => {
return Math.floor(Math.random() * Math.floor(num));
}
let moveImg = (dogImgs) => {
let w = window.innerWidth;
let h = window.innerHeight;
dogImgs.style.top = getRandomNum(w) + "px";
dogImgs.style.left = getRandomNum(h) + "px";
};
body {
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
background-color: rgb(26, 43, 38);
}
.header {
text-align: center;
color: white;
font-size: 1.75rem;
max-width: 80%;
margin-top: 3rem;
}
select {
font-size: 2rem;
margin-bottom: 4rem;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
text-transform: capitalize;
color: black;
background-color: rgb(255, 255, 255);
}
.main-container {
display: flex;
flex-direction: column;
align-items: center;
}
.slideshow {
overflow: hidden;
text-align: center;
}
img {
max-width: 40%;
margin-top: 25rem;
position: absolute;
left: 100px;
top: 100px;
}
.top_link_position {
display: block;
position: fixed;
bottom: 4%;
right: 3%;
z-index: 600;
}
.top_btn {
border: 1.5px solid white;
background: black;
padding: .5rem .5rem;
color: white;
font-weight: bolder;
text-transform: uppercase;
}
#media screen and (max-width: 425px) {
.header {
font-size: 1.25rem;
}
select {
font-size: 1.5rem;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.3/css/all.css" integrity="sha384-SZXxX4whJ79/gErwcOYf+zWLeJdY/qpuqC4cAa9rOGUstPomtqpuNWT9wdPEn2fk" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> -->
<link rel="stylesheet" href="styles.css">
<title>Dog Collage</title>
</head>
<body>
<!--Title and menu-->
<div class="main-container">
<div class="header">
<h1>Dog Collage!</h1>
<p>Select a dog and create your collage!</p>
<p>Double-tap to remove an image.</p>
<div id="breeds"></div>
</div>
</div>
<div class="slideshow" id="imgs">
</div>
<!-- Modal
<div id="my-modal" class="modal fade" tabindex="-1" role="dialog"
aria-labelledby="pokemonModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" aria-labelledby="pokemonModalLabel">Modal title</h5>
<button type="button" class="modal-close" id=".modal-close" data-dismiss="modal" aria-label="Close">X</button>
</div>
<div class="modal-body"></div>
</div>
</div>
</div> -->
<!--Top of Page Button-->
<div class="top_link_position">
<a class="back-to-top" href="#page_top" title="Top">
<button class="top_btn"><span class="icon"><i class="fas fa-chevron-up fa-2x"></i></span></button>
</a>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script src="src/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
By default, the rangeSlider plug in calculates default values of 33 min and 66 max. The code below is completely functional, around line 125 I have further comments on where I think my solution resides. Remove and add // to see what I am talking about. I hope this makes sence and thanks in advance for any help
<?php
$qty_min = isset($_REQUEST['qty_min']) ? $_REQUEST['qty_min'] : "33";
$qty_max = isset($_REQUEST['qty_max']) ? $_REQUEST['qty_max'] : "66";
$first_load = "false";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Dashboard - SB Admin</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css" />
<style>
/* RANGE SLIDER BAR REGULAR CSS */
.primaryText{
font-weight: 300;
font-size: 50px;
text-shadow: 2px 2px 1px rgba(0,0,0,0.3);
}
.secondaryText{
font-weight: 300;
font-size: 25px;
}
.createdBy {
font-weight: 300;
font-size: 17px;
margin-top: 10px;
}
.createdBy a{
color: #333;
font-weight: 500;
}
.message {
background: white;
padding: 10px;
display: inline-block;
text-align: center;
color: #000;
margin: 25px 0;
font-size: 13px;
box-shadow: 2px 2px 0px 1px rgba(0,0,0,0.2);
border-radius: 4px;
}
.projHeader{
text-align: center;
}
.footer{position: fixed; bottom: 0; right: auto; top: auto; left: 0; border-top: 1px solid rgba(0,0,0,0.5); width: 100%; transform: translate(0); border: none; padding: 0; text-align: center; border-top: 1px solid #bfc7e4;}
.footer div{display: inline-block;}
.footer a.social{display: inline-block; font-size: 17px; padding: 7px 0; color: #000; text-decoration: none; margin: 0px 20px;}
body{background: #333; font-family: poppins;}
.projHeader, .createdBy a, .message{color: #fff;}
.message{background: rgba(255, 255, 255, 0.1);}
.demoContainer{position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%); width: 400px;}
.sliderContainer{position: relative; border-radius: 20px;
background: #6a6a6a; width: 400px; height: 10px; margin-top: 40px;}
.sliderContainer:after{content:""; clear: both; display: block; }
.slider{height: 10px; float: left;}
.slider_a{background: transparent;}
.slider_b{background: #fd1874; border-radius: 20px;}
.slider_c{background: transparent;}
.slider_adj{position: absolute; padding: 3px 10px; background: #fff; top: 12px; cursor: move; user-select: none; z-index: 1; font-size: 13px; color: #333; border-radius: 20px; width: 20px; text-align: center;}
.slider_adj_1{top: -28px;}
.slider_adj_2{z-index: 3}
</style>
<div class="projHeader">
<div style="background:rgb(124, 124, 124);padding-bottom:40px;">
<div style="color:white;font-size:16px;font-weight: 100"> Slide the numbered ovals to select your desired range.</div>
<div align="center">
<div class="sliderContainer" id="sliderContainer">
<input type="hidden" name="qty_min" id="qty_min" value="<?php echo $qty_min ?>" placeholder="<?php echo $qty_min ?>" />
<input type="hidden" name="qty_max" id="qty_max" value="<?php echo $qty_max ?>" placeholder="<?php echo $qty_max ?>" />
<div class="slider slider_a" id="slider_a"></div>
<div class="slider slider_b" id="slider_b"></div>
<div class="slider slider_c" id="slider_c"></div>
<div style="width:70px" class="slider_adj slider_adj_1" id="slider_adj_1"></div>
<div style="width:70px" class="slider_adj slider_adj_2" id="slider_adj_2"></div>
</div>
</div>
</div>
<div style="color:white"> var-a_wt = <span id="var-a_wt"></span></div>
<div style="color:white"> var-b_wt = <span id="var-b_wt"></span></div>
<div style="color:white"> var-c_wt = <span id="var-c_wt"></span></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
var sliderContainer, sliderContainerWt;
var sliderHandleWt;
$(document).ready(function(){
sliderContainer = $("#sliderContainer");
sliderContainerWt = sliderContainer.outerWidth();
sliderHandleWt = $("#slider_adj_1").outerWidth();
setLeftPosition();
setDraggable();
bindMouseUp();
updateGraph();
});
function setLeftPosition(){
var wt = sliderContainerWt/3;
$(".slider").css({"width": wt+"px" })
The two lines below work great, but I need to change default values on the fly, then store them in a DB table to restore custom values on page reload. The two lines below calculate 33 and 66 only
//var sliderHandlePos_1 = wt-sliderHandleWt/2;
//var sliderHandlePos_2 = wt*2-sliderHandleWt/2;
The two lines below kind of work, but throws off the format of my slider bar and min and max values are still not right
var sliderHandlePos_1 = '<?php echo $qty_min ?>';
var sliderHandlePos_2 = '<?php echo $qty_max ?>';
$("#slider_adj_1").css({"left": sliderHandlePos_1+"px"});
$("#slider_adj_2").css({"left": sliderHandlePos_2+"px"});
}
</script>
<script>
function updateGraph(){
I think my solution is in the next 3 lines of code, but my limited skills in javascript inhibit me from wrapping my head around it.
var a_wt = parseInt(($("#slider_a").width()/sliderContainerWt*100).toFixed(0));
var b_wt = parseInt(($("#slider_b").width()/sliderContainerWt*100).toFixed(0));
var c_wt = parseInt(($("#slider_c").width()/sliderContainerWt*100).toFixed(0));
I have tried the following, but no luck. I need the initial values to load from the table via PHP just once, then java script takes back over and keeps track of slider values, as YES I understand PHP is server side script, so I understand why this does not work. Just and example> I need a JavaScript equivalent.
var a_wt = <?php echo $qty_min ?>;
var b_wt = <?php echo ($qty_max-$qty_min) ?>;
var c_wt = <?php echo (100-$qty_max) ?>;
I don't think my solution is beyond this point. But of course I could be wrong.
$("#slider_adj_1").html(a_wt+"%");
$("#slider_adj_2").html((b_wt+a_wt)+"%");
document.getElementById('qty_min').value = a_wt;
document.getElementById('qty_max').value = b_wt+a_wt;
document.getElementById('var-a_wt').innerHTML = a_wt;
document.getElementById('var-b_wt').innerHTML = b_wt;
document.getElementById('var-c_wt').innerHTML = c_wt;
return { a: a_wt,
b: b_wt,
c: c_wt
}
}
</script>
<script>
function bindMouseUp(){
$("#slider_adj_1, #slider_adj_2").on("mouseout", function(){
$("#slider_adj_1, #slider_adj_2").draggable( "destroy" );
});
$("#slider_adj_1, #slider_adj_2").on("mouseover", function(){
setDraggable();
});
}
function setDraggable(){
var maxLeft = $("#slider_a").offset().left-(sliderHandleWt/2);
var maxRight = $("#slider_b").offset().left+$("#slider_b").outerWidth()-(sliderHandleWt/2);
var startX, start_a_Wt, start_b_Wt, start_c_Wt;
$("#slider_adj_1").draggable({
axis: 'x',
containment: [ maxLeft, 0, maxRight, 0 ],
refreshPositions: true,
start: function(event, ui){
startX = $(this).position().left;
start_a_Wt = $("#slider_a").width();
start_b_Wt = $("#slider_b").width();
},
drag: function(event, ui){
var endX = $(this).position().left;
var finalX = endX - startX;
var slider_a = start_a_Wt + finalX;
var slider_b = start_b_Wt - finalX;
$("#slider_a").css("width", slider_a+"px");
$("#slider_b").css("width", slider_b+"px");
updateGraph();
},
stop: function(event, ui){
maxLeft = $("#slider_a").position().left;
maxRight = $("#slider_c").position().left;
}
});
var maxLeft_2 = $("#slider_a").offset().left+$("#slider_a").outerWidth()-(sliderHandleWt/2);
var maxRight_2 = $("#slider_a").offset().left+sliderContainerWt-(sliderHandleWt/2);
$("#slider_adj_2").draggable({
axis: 'x',
containment: [ maxLeft_2, 0, maxRight_2, 0 ],
start: function(event, ui){
startX = $(this).position().left;
start_b_Wt = $("#slider_b").width();
start_c_Wt = $("#slider_c").width();
},
drag: function(event, ui){
var endX = $(this).position().left;
var finalX = endX - startX;
var slider_b = start_b_Wt + finalX;
var slider_c = start_c_Wt - finalX;
$("#slider_b").css("width", slider_b+"px");
$("#slider_c").css("width", slider_c+"px");
updateGraph();
},
stop: function(event, ui){
maxLeft_2 = $("#slider_b").offset().left;
maxRight_2 = $("#slider_c").offset().left + $("#slider_c").width();
}
});
}
</script>
I was completely going down the wrong path. After reading further in the PROPER documentation, I came up with the following completely functioning code, just in case this helps someone else. I also show how to explode the my_range variable so now you can store these variable in a database table. Great documentation at http://ionden.com/a/plugins/ion.rangeSlider/start.html
<?php
$my_range = isset($_REQUEST['my_range']) ? $_REQUEST['my_range'] : "";
$split_range = (explode(";",$my_range));
$qty_min = $split_range[0];
$qty_max = $split_range[1];
?>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script>
<form action="slider_test2.php" method="post">
<input style="color:blue" type="text" class="js-range-slider" name="my_range" value="" />
<br>
<?php echo "my_range = " . $my_range; ?>
<?php echo "<br>qty_min = " . $qty_min; ?>
<?php echo "<br>qty_max = " . $qty_max; ?>
<br>
<button type="submit" >submit</button>
</form>
<script>
$(".js-range-slider").ionRangeSlider({
type: "double",
grid: true,
min: 1,
max: 100,
from: <?php echo $qty_min ?>,
to: <?php echo $qty_max ?>,
postfix: "%",
skin: "big"
});
</script>
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I want to make a simple slider using pure javascript that support at least ie8, but got stuck at the moment. The problem is I when I click one of the paging items it should grab current index and then target another div for the slider container item with the same index as the paging. Basically I want to add and remove active class on both div.sliderItems & div.pagingItems based on div.pagingItems index. Here's my code:
window.onload = function(){
var slider = document.getElementById('slider'),
sliderItems = slider.children,
totalItems = sliderItems.length,
activeSlider = document.querySelector('.activeSlider'),
pagingSlider = document.getElementById('pagingSlider'),
pagingItems = pagingSlider.children,
activePaging = document.querySelector('.activePaging');
function next(){
for (var i = 0; i < totalItems; i++) {
if (i < totalItems - 1) {
if (sliderItems[i].className.match( /(?:^|\s)activeSlider(?!\S)/ )) {
sliderItems[i].className = sliderItems[i].className.replace( /(?:^|\s)activeSlider(?!\S)/g , '' );
sliderItems[i + 1].className += ' activeSlider';
pagingItems[i].className = pagingItems[i].className.replace( /(?:^|\s)activePaging(?!\S)/g , '' );
pagingItems[i + 1].className += ' activePaging';
return;
}
} else {
sliderItems[i].className = sliderItems[i].className.replace( /(?:^|\s)activeSlider(?!\S)/g , '' );
sliderItems[i + 1 - totalItems].className += ' activeSlider';
pagingItems[i].className = pagingItems[i].className.replace( /(?:^|\s)activePaging(?!\S)/g , '' );
pagingItems[i + 1 - totalItems].className += ' activePaging';
return;
}
}
}
for (var i = 0; i < totalItems; i++) {
(function(index){
pagingItems[i].onclick = function(){
pagingItems[i].className = pagingItems[i].className.replace( /(?:^|\s)activePaging(?!\S)/g , '' );
this.className += ' activePaging';
console.log(index);
}
})(i);
}
if (activeSlider === null) {
sliderItems[0].className += ' activeSlider';
pagingItems[0].className += ' activePaging';
}
var start = setInterval(next, 3000);
pagingSlider.onmouseenter = function(){clearInterval(start);};
pagingSlider.onmouseleave = function(){start = setInterval(next, 3000);};
}
* {
box-sizing: border-box;
}
html, body {
padding: 0;
margin: 0;
font-family: sans-serif;
}
.wrapperSlider {
position: relative;
width: 100%;
padding-bottom: 35%;
}
#slider {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#slider > * {
display: table;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
color: #fff;
background: red;
opacity: 0;
transition: all ease-in-out .5s;
}
#slider > * > * {
display: table-cell;
vertical-align: middle;
}
#slider > *.activeSlider {
z-index: 1;
background: green;
opacity: 1;
}
.wrapperPaging {
text-align: center;
}
#pagingSlider {
display: inline-block;
font-size: 0;
}
#pagingSlider > * {
display: inline-block;
margin: 0 10px;
font-size: 14px;
color: black;
cursor: pointer;
transition: all ease-in-out .5s;
}
#pagingSlider > *.activePaging {
color: red;
cursor: default;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test File | Vanilla JS</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
</head>
<body>
<div class="wrapperSlider">
<div id="slider">
<div class="sliderItems">
<div>Item 1</div>
</div>
<div class="sliderItems">
<div>Item 2</div>
</div>
<div class="sliderItems">
<div>Item 3</div>
</div>
<div class="sliderItems">
<div>Item 4</div>
</div>
<div class="sliderItems">
<div>Item 5</div>
</div>
</div>
</div>
<div class="wrapperPaging">
<div id="pagingSlider">
<a class="pagingItems">1</a>
<a class="pagingItems">2</a>
<a class="pagingItems">3</a>
<a class="pagingItems">4</a>
<a class="pagingItems">5</a>
</div>
</div>
</body>
</html>
Your onclick function has a closure around the i loop counter, which is causing the "classic" closure bug of all of your event handlers sharing the same value for i and i persisting after its defining scope has ended. At that point, i has the last value set by the loop, which is one more than the number of actual items there are, so when the time comes to click on your slider, no matter which number you click on, you get the same i value that is one more than the highest index used. While your code was set up to avoid this problem by using an immediately invoked function expression that passes itself a copy of i, which it receives as index, your nested onclick functions ignored that and used i anyway. You could just change references to i with index. But, changing the pageSlider[i] reference to this solves the issue as well and doesn't rely on the IIFE.
A couple of other small pieces of advice...
An <a> is only valid when it has a name or href attribute and, in your case, you really aren't trying to navigate anywhere, so the <a> tag is inappropriate for what you are doing. In my example below, I've changed those to <span> elements, which is more appropriate.
Instead of working with the className property, it is simpler (and less error prone) to use classList, which provides .add(), remove() and toggle() and methods. When you use .add(), you don't have to worry about prepending a space in situations when there will be more than one class applied. And, most importantly, you can easily remove a class without regular expressions and String.replace().
window.onload = function(){
var slider = document.getElementById('slider'),
sliderItems = slider.children,
totalItems = sliderItems.length,
activeSlider = document.querySelector('.activeSlider'),
pagingSlider = document.getElementById('pagingSlider'),
pagingItems = pagingSlider.children,
activePaging = document.querySelector('.activePaging');
function next(){
for (var i = 0; i < totalItems; i++) {
if (i < totalItems - 1) {
if (sliderItems[i].className.indexOf('activeSlider') > -1) {
sliderItems[i].classList.remove('activeSlider');
sliderItems[i + 1].classList.add('activeSlider');
pagingItems[i].classList.remove('activePaging');
pagingItems[i + 1].classList.add('activePaging');
}
} else {
sliderItems[i].classList.remove('activeSlider');
sliderItems[i + 1 - totalItems].classList.add('activeSlider');
pagingItems[i].classList.remove('activePaging');
pagingItems[i + 1 - totalItems].classList.add('activePaging');
}
}
}
for (var i = 0; i < totalItems; i++) {
pagingItems[i].onclick = function(){
// You were forming a closure around i in this function. You can reference
// the element that triggered the event simply with "this"
this.previousElementSibling.classList.remove('activePaging');
this.classList.add('activePaging');
}
}
if (activeSlider === null) {
sliderItems[0].classList.add('activeSlider');
pagingItems[0].classList.add('activePaging');
}
var start = setInterval(next, 3000);
pagingSlider.onmouseenter = function(){clearInterval(start);};
pagingSlider.onmouseleave = function(){start = setInterval(next, 3000);};
}
* {
box-sizing: border-box;
}
html, body {
padding: 0;
margin: 0;
font-family: sans-serif;
}
.wrapperSlider {
position: relative;
width: 100%;
padding-bottom: 35%;
}
#slider {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#slider > * {
display: table;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
color: #fff;
background: red;
opacity: 0;
transition: all ease-in-out .5s;
}
#slider > * > * {
display: table-cell;
vertical-align: middle;
}
#slider > *.activeSlider {
z-index: 1;
background: green;
opacity: 1;
}
.wrapperPaging {
text-align: center;
}
#pagingSlider {
display: inline-block;
font-size: 0;
}
#pagingSlider > * {
display: inline-block;
margin: 0 10px;
font-size: 14px;
color: black;
cursor: pointer;
transition: all ease-in-out .5s;
}
#pagingSlider > *.activePaging {
color: red;
cursor: default;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test File | Vanilla JS</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
</head>
<body>
<div class="wrapperSlider">
<div id="slider">
<div class="sliderItems">
<div>Item 1</div>
</div>
<div class="sliderItems">
<div>Item 2</div>
</div>
<div class="sliderItems">
<div>Item 3</div>
</div>
<div class="sliderItems">
<div>Item 4</div>
</div>
<div class="sliderItems">
<div>Item 5</div>
</div>
</div>
</div>
<div class="wrapperPaging">
<div id="pagingSlider">
<span class="pagingItems">1</span>
<span class="pagingItems">2</span>
<span class="pagingItems">3</span>
<span class="pagingItems">4</span>
<span class="pagingItems">5</span>
</div>
</div>
</body>
</html>