Create grid in HTML - javascript

I'm looking to create a grid like this: Grid
I'm using this:
$(document).ready(function() {
for (var i = 0; i < 366; i++) {
$('#div-padre').append('<div class="dia" id="div'+ i +'" /> ');
}
});
to generate 365 divs, then, with CSS, create the 'grid' style.
.dia {
width: 45px;
height: 45px;
background: white;
outline: 2px solid;
float: left;
}
.div-padre {
width: 800px;
}
I tried to clearfix but the last div goes wrong, I don't care if they are divs, tr or whatever, but in the future i would like to select one square and change color, so div or tr or something, I need you to be able to do that later

This is a border/outline management issue, take a look at this:
$(document).ready(function() {
for (var i = 0; i < 366; i++) {
$('#div-padre').append('<div class="dia" id="div'+ i +'" /> ');
}
});
.dia {
width: 45px;
height: 45px;
background: white;
border: 2px solid;
float: left;
margin-top:-2px;
margin-left:-2px;
}
.div-padre {
width: 800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div-padre"></div>

Use border: 2px solid; margin: -1px; instead of outline: 2px solid;
$(document).ready(function() {
for (var i = 0; i < 365; i++) {
$('#div-padre')
.append(
$('<div>', {
id: 'div-' + (i+1),
class: 'dia'
}));
}
});
.dia {
width: 45px;
height: 45px;
background: white;
border: 2px solid;
margin: -1px;
float: left;
}
.div-padre {
width: 800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div-padre"></div>

Related

Jquery Hover function not changing class

I've created a grid of pixels and want it to change to black when hovered.
The problem is that the event is not working.
$(document).ready(function() {
function makeGrid(k) {
var size = 320 / k;
for (var i = 0; i < k; i++) {
$(".container").append("<div class=row></div>");
}
for (var j = 0; j < k; j++) {
$(".row").append("<div class=square></div>");
}
$('.square').css({
'height': size,
'width': size
});
}
$('.square').hover(function() {
$(this).addClass(".hover");
})
$('.reset').on('click', function() {
$(".container").empty();
makeGrid(16);
})
$('.start').on('click', function() {
var n = prompt("Set the size");
$(".container").empty();
makeGrid(n);
})
})
.square {
border-collapse: collapse;
display: inline-block;
}
.container {
text-align: -webkit-center;
position: relative;
top: 50px;
margin: 0 auto;
border: 1px solid #000000;
width: 320px;
height: 320px;
border-collapse: collapse;
}
.row {
clear: both;
content: "";
height: 20px;
}
.hover {
background-color: black;
}
button {
text-align: center;
background-color: white;
display: inline-block;
font-size: 20px;
border-radius: 2px;
top: 50%;
}
.wrap {
text-align: -webkit-center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="wrap">
<button class="clear">New Grid</button>
<button class="start">Start</button>
<button class="reset">Reset</button>
</div>
<div class="container"></div>
Since you dynamically add your divs, you can't use .hover() and have to use .on() with mouseenter instead. Also when using .addClass() you just use the class' name with no period being prefixed.
$(document).ready(function() {
function makeGrid(k) {
var size = 320 / k;
for (var i = 0; i < k; i++) {
$(".container").append("<div class=row></div>");
}
for (var j = 0; j < k; j++) {
$(".row").append("<div class=square></div>");
}
$('.square').css({
'height': size,
'width': size
});
}
$(document).on("mouseenter", ".square", function(e) {
$(this).addClass("hover");
});
$('.reset').on('click', function() {
$(".container").empty();
makeGrid(16);
})
$('.start').on('click', function() {
var n = prompt("Set the size");
$(".container").empty();
makeGrid(n);
})
})
.square {
border-collapse: collapse;
display: inline-block;
}
.container {
text-align: -webkit-center;
position: relative;
top: 50px;
margin: 0 auto;
border: 1px solid #000000;
width: 320px;
height: 320px;
border-collapse: collapse;
}
.row {
clear: both;
content: "";
height: 20px;
}
.hover {
background-color: black;
}
button {
text-align: center;
background-color: white;
display: inline-block;
font-size: 20px;
border-radius: 2px;
top: 50%;
}
.wrap {
text-align: -webkit-center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="wrap">
<button class="clear">New Grid</button>
<button class="start">Start</button>
<button class="reset">Reset</button>
</div>
<div class="container"></div>

For loop runs length of array but displays one element array.length times

I'm working on a project for freeCodeCamp and I'm running a for loop through an array of twitch.tv users. I've created a table and for each username in my array, it's supposed to add the new row, fill it with the data, and move onto the next element. The problem is that every time I run the code it seems to be choosing a random index in the array and running the loop through to equal the number of elements in the array. I think it's a display issue because it's connecting to the server for each individual call.
Hopefully someone can help me out.
var twitch = ['ESL_SC2', 'OgamingSC2', 'cretetion', 'freecodecamp', 'storbeck', 'habathcx', 'RobotCaleb', 'noobs2ninjas', 'ESL_LOL', 'wow_2', 'brunofin', 'comster404']
var streams = 'https://wind-bow.gomix.me/twitch-api/streams/';
var channels = 'https://wind-bow.gomix.me/twitch-api/channels/';
var users = 'https://wind-bow.gomix.me/twitch-api/users/';
var getStream = function(data) {
if (data.stream === null) {
$('.status').append('Offline');
} else {
var streamStatus = data.stream.channel.status;
var html = '<td class="stream">' + streamStatus + '</td>';
$('.stream').html(html);
}
}
var getChannels = function(data) {
var game = data.display_name;
var logoHtml = data.logo;
var channelUrl = data.url;
var gameHtml = '' + game + '';
var logoHtml = '<img class="image" src="' + logoHtml + '">';
$('.game').html(gameHtml);
$('.logo').html(logoHtml);
}
$(document).ready(function() {
$('.choice').on('click', function() {
$('.choice').removeClass('selected');
$(this).toggleClass('selected');
});
var table = $('<table id="twitch-table"></table>').appendTo('#content');
for (var i = 0; i < twitch.length; i++) {
var row = $('<tr></tr>').appendTo(table);
$('<td class="logo"></td>').appendTo(row);
$('<td class="game"></td>').appendTo(row);
$('<td class="stream"></td>').appendTo(row);
$.getJSON(streams + twitch[i], getStream, 'jsonp');
$.getJSON(channels + twitch[i], getChannels, 'jsonp');
}
});
body {
padding: 0;
margin: 0;
font-family: 'Oswald', sans-serif;
font-size: 100%;
}
a {
text-decoration: none;
}
#main {
width: 600px;
margin: 2% auto 0;
}
#header {
padding: 0;
margin: 0;
background: #116466;
color: #d1e8e2;
line-height: 100px;
width: 100%;
}
h1 {
margin: 0 0 0 5%;
font-size: 300%;
}
#row {
background: #285277;
width: 100%;
}
ul {
margin: 0;
padding: 0;
list-style: none;
display: flex;
justify-content: space-between;
}
.choice {
position: relative;
text-align: center;
width: 33%;
background: #285277;
padding: 5px 10px;
display: inline-block;
color: #d1e8e2;
font-size: 150%;
}
.choice a {
/*padding: 5px 20px;*/
color: #d1e8e2;
}
#content {
width: 100%;
background: #efefef;
}
/*
.choice a:active {
background: #1E3D59;
}
*/
.selected {
background: #1E3D59;
}
.selected:after {
content: '';
position: absolute;
top: 100%;
right: 45%;
width: 0;
height: 0;
border-top: solid 10px #1E3D59;
border-left: solid 10px transparent;
border-right: solid 10px transparent;
}
table {
width: 600px;
}
tr {
margin: 5px 0;
display: flex;
width: 100%;
justify-content: space-between;
}
td {
border-collapse: collapse;
box-sizing: border-box;
margin: 0;
padding: 0;
display: inline-block;
white-space: nowrap;
overflow: hidden;
}
.game {
padding-left: 10px;
width: 100px;
font-size: 120%;
line-height: 75px;
text-overflow: ellipsis;
}
.game a {
color: #111;
}
.image {
height: 75px;
width: 75px;
}
.logo {
padding: 3px 5px;
box-sizing: border-box;
}
.stream {
padding-right: 10px;
width: 350px;
display: inline-block;
text-overflow: ellipsis;
line-height: 75px;
}
<!DOCTYPE html>
<html>
<head>
<title>Twitch.tv JSON API</title>
<link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet">
<script src="https://use.fontawesome.com/57c9bf8971.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<div id='main'>
<header id='header'>
<h1>Twitch Streamers</h1>
</header>
<div id='row'>
<ul>
<li class='choice selected'><a href='#'>All</a></li>
<li class='choice'><a href='#'>Online</a></li>
<li class='choice'><a href='#'>Offline</a></li>
</ul>
</div>
<div id='content'>
</div>
</div>
</body>
</html>
The problem is in these lines:
$('.game').html(gameHtml);
$('.logo').html(logoHtml);
$('.stream').html(html);
They select all lines with game class (or logo or stream) And change them all.
See here a fixed JSfiddle.
You need to use the callback function properly. Your getStreams and getChannels functions are applying data to all rows, instead of its own individual row.
Below are the modified callback functions declarations:
var getStream = function(url, idx) {
$.getJSON(url, function(data){
if (data.stream === null) {
$('.status').append('Offline');
} else {
var streamStatus = data.stream.channel.status;
var html = '<td class="stream">' + streamStatus + '</td>';
$('tr').eq(idx).find('.stream').html(html);
}
});
}
var getChannels = function(url, idx) {
$.getJSON(url, function(data){
var game = data.display_name;
var logoHtml = data.logo;
var channelUrl = data.url;
var gameHtml = '' + game + '';
var logoHtml = '<img class="image" src="' + logoHtml + '">';
$('tr').eq(idx).find('.game').html(gameHtml);
$('tr').eq(idx).find('.logo').html(logoHtml);
});
}
And, call them within your for loop as:
getStream(streams + twitch[i], i);
getChannels(channels + twitch[i], i);
JSFiddle for your reference: https://jsfiddle.net/yogesh214/yxLu9mwg/4/
I understand your problem now:
As #Shalom Peles said, you're using $('.stream') to select all the elements in the document with the class .stream instead of just the element within your row.
Instead use .find to select within an element. For example:
let row = $('<div class="my-row"></div>'); // creates a row
row.append(/* ... */);
let elementInsideRow = row.find('.my-column'); // this selects an element *inside* the row element.
Also: use let instead of var for all declarations
I edited your code to work for streams. Do the same for channels. Read the comments.
var twitch = ['ESL_SC2', 'OgamingSC2', 'cretetion', 'freecodecamp', 'storbeck', 'habathcx', 'RobotCaleb', 'noobs2ninjas', 'ESL_LOL', 'wow_2', 'brunofin', 'comster404']
var streams = 'https://wind-bow.gomix.me/twitch-api/streams/';
var channels = 'https://wind-bow.gomix.me/twitch-api/channels/';
var users = 'https://wind-bow.gomix.me/twitch-api/users/';
// refactor this like I did below
var getChannels = function(data) {
var game = data.display_name;
var logoHtml = data.logo;
var channelUrl = data.url;
var gameHtml = '' + game + '';
var logoHtml = '<img class="image" src="' + logoHtml + '">';
$('.game').html(gameHtml);
$('.logo').html(logoHtml);
}
$(document).ready(function() {
$('.choice').on('click', function() {
$('.choice').removeClass('selected');
$(this).toggleClass('selected');
});
var table = $('<table id="twitch-table"></table>').appendTo('#content');
// you need to use `let` here because you need block scope
// in general, use `let` instead of `var` everywhere.
// https://stackoverflow.com/questions/21906133/when-should-i-use-let-and-var
for (let i = 0; i < twitch.length; i++) {
let row = $('<tr></tr>');
$.getJSON(streams + twitch[i], function(data) {
$('<td class="logo"></td>').appendTo(row);
$('<td class="game"></td>').appendTo(row);
$('<td class="stream"></td>').appendTo(row);
if (data.stream === null) {
// instead of selecting all the elements with `.status`, use `find` to select *within* the `row` element
// $('.status').append('Offline');
row.find('.status').append('Offline');
} else {
var streamStatus = data.stream.channel.status;
var html = '<td class="stream">' + streamStatus + '</td>';
row.find('.stream').html(html);
}
// apend it when you're done
row.appendTo(table);
}, 'jsonp');
// make the same changes for channel
//$.getJSON(channels + twitch[i], getChannels, 'jsonp');
}
});
body {
padding: 0;
margin: 0;
font-family: 'Oswald', sans-serif;
font-size: 100%;
}
a {
text-decoration: none;
}
#main {
width: 600px;
margin: 2% auto 0;
}
#header {
padding: 0;
margin: 0;
background: #116466;
color: #d1e8e2;
line-height: 100px;
width: 100%;
}
h1 {
margin: 0 0 0 5%;
font-size: 300%;
}
#row {
background: #285277;
width: 100%;
}
ul {
margin: 0;
padding: 0;
list-style: none;
display: flex;
justify-content: space-between;
}
.choice {
position: relative;
text-align: center;
width: 33%;
background: #285277;
padding: 5px 10px;
display: inline-block;
color: #d1e8e2;
font-size: 150%;
}
.choice a {
/*padding: 5px 20px;*/
color: #d1e8e2;
}
#content {
width: 100%;
background: #efefef;
}
/*
.choice a:active {
background: #1E3D59;
}
*/
.selected {
background: #1E3D59;
}
.selected:after {
content: '';
position: absolute;
top: 100%;
right: 45%;
width: 0;
height: 0;
border-top: solid 10px #1E3D59;
border-left: solid 10px transparent;
border-right: solid 10px transparent;
}
table {
width: 600px;
}
tr {
margin: 5px 0;
display: flex;
width: 100%;
justify-content: space-between;
}
td {
border-collapse: collapse;
box-sizing: border-box;
margin: 0;
padding: 0;
display: inline-block;
white-space: nowrap;
overflow: hidden;
}
.game {
padding-left: 10px;
width: 100px;
font-size: 120%;
line-height: 75px;
text-overflow: ellipsis;
}
.game a {
color: #111;
}
.image {
height: 75px;
width: 75px;
}
.logo {
padding: 3px 5px;
box-sizing: border-box;
}
.stream {
padding-right: 10px;
width: 350px;
display: inline-block;
text-overflow: ellipsis;
line-height: 75px;
}
<!DOCTYPE html>
<html>
<head>
<title>Twitch.tv JSON API</title>
<link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet">
<script src="https://use.fontawesome.com/57c9bf8971.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<div id='main'>
<header id='header'>
<h1>Twitch Streamers</h1>
</header>
<div id='row'>
<ul>
<li class='choice selected'><a href='#'>All</a></li>
<li class='choice'><a href='#'>Online</a></li>
<li class='choice'><a href='#'>Offline</a></li>
</ul>
</div>
<div id='content'>
</div>
</div>
</body>
</html>

Create the list with limited elements inside

I need to create ul with a limit of 5 li's inside. If it goes more then 5 elements - create new ul with the same limitations. And so on and on. Here is the start point I made:
$(function(){
var $container = $('.container'),
el = 5,
i;
newUl = $('<ul />')
for(i=0; i < el; i++){
$container.append(newUl)
$('<li />', { html : i }).appendTo(newUl)
}
})
* {
box-sizing: border-box;
}
body {
background: #f2f2f2;
}
.wrapper {
display: table;
margin: 0 auto;
padding: 10px;
max-width: 600px;
width: 100%;
height: 100vh;
border: 2px solid rgba(0, 0, 0, 0.2);
}
.wrapper .container {
display: table-cell;
vertical-align: bottom;
}
.wrapper ul {
background: #c0c0c0;
border: 1px solid #333;
font-size: 0;
}
.wrapper ul:nth-of-type(odd) {
direction: rtl;
}
.wrapper ul li {
display: inline-block;
font-size: 16px;
width: 20%;
padding: 10px;
border: 1px solid #333;
text-align: center;
direction: rtl;
}
.status {
position: fixed;
left: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="container">
</div>
</div>
<div class="status"></div>
Any advices how to do this?
You can use the modulus operator % to determine when you have reached the max, and then you need to create a new jQuery for your new ul, and append it.
$(function(){
var $container = $('.container'),
el = 10,
max = 5,
i;
var newUl;
for(i=0; i < el; i++){
if(i%max==0) {
newUl = $('<ul/>');
$container.append(newUl);
}
$('<li />', { html : i }).appendTo(newUl)
}
});
* {
box-sizing: border-box;
}
body {
background: #f2f2f2;
}
.wrapper {
display: table;
margin: 0 auto;
padding: 10px;
max-width: 600px;
width: 100%;
height: 100vh;
border: 2px solid rgba(0, 0, 0, 0.2);
}
.wrapper .container {
display: table-cell;
vertical-align: bottom;
}
.wrapper ul {
background: #c0c0c0;
border: 1px solid #333;
font-size: 0;
}
.wrapper ul:nth-of-type(odd) {
direction: rtl;
}
.wrapper ul li {
display: inline-block;
font-size: 16px;
width: 20%;
padding: 10px;
border: 1px solid #333;
text-align: center;
direction: rtl;
}
.status {
position: fixed;
left: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="container">
</div>
</div>
<div class="status"></div>
I'm not quite following your example, so forgive me that I've just started fresh here. The first loop and the 12 on line 2 is just to generate a list of fake data to work with. Test it with 0, less than 5, multiples of 5, and 1+ a multiple of 5 just to make sure it works.
var items = [];
for(var i=0; i<12; i++) {
items.push("item " + i.toString());
}
var subItems = items.splice(0, 5);
var div = $("<div>").get(0);
while(subItems.length > 0) {
var ul = $("<ul>").get(0);
div.appendChild(ul);
for(var i=0; i<subItems.length; i++) {
ul.appendChild( $("<li>").text(subItems[i]).get(0) );
}
subItems = items.splice(0, 5);
}
You can paste this into the console to see the results. Just add console.log(div) at the end.
This will create a div with n number of ul tags, each having 5 li's (or less depending on the data)
Change line 6 to point to your div tag. And I'm not sure we can tell from your example where the data is supposed to come from so you'll need to change items and line 11 accordingly.

Changing all the cursors?

When I hover each span, the cursors are changed follow its title !
var cursors = [ "auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize", "s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize" ,"col-resize","row-resize","all-scroll","zoom-in","zoom-out","grab","grabbing" ];
var newHTML = [];
for (var i = 0; i < cursors.length; i++) {
newHTML.push('<span>' + cursors[i] + '</span>');
}
$("body").html(newHTML.join(""));
$("span").on( "mouseover", function() {
$(this).css( "cursor", cursors[4] );
});
html, body{
margin: 30px auto;
width: 90%;
text-align: center;
background: linear-gradient(top, green, lightblue);
}
h1{
color: #f49ba2;
}
span{
background-color: #ddd;
margin: 5px;
padding: 5px;
border: #abc 1px solid;
display: inline-block;
}
span:odd{
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="element"></p>
Do you mean this?
See https://api.jquery.com/index/
var cursors = [ "auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize", "s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize" ,"col-resize","row-resize","all-scroll","zoom-in","zoom-out","-webkit-grab", "-webkit-grabbing" ];
var newHTML = [];
for (var i = 0; i < cursors.length; i++) {
newHTML.push('<span>' + cursors[i] + '</span>');
}
$("body").html(newHTML.join(""));
$("span").on( "mouseover", function() {
$(this).css( "cursor", cursors[$(this).index()] );
});
html, body{
margin: 30px auto;
width: 90%;
text-align: center;
background: linear-gradient(top, green, lightblue);
}
h1{
color: #f49ba2;
}
span{
background-color: #ddd;
margin: 5px;
padding: 5px;
border: #abc 1px solid;
display: inline-block;
}
span:odd{
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
</body>

Html Range slider with Javascript

So I have recently been playing around with styling the html range slider.
I came across a pen on CodePen that has some really great designs.
This is the source code from one.
HTML:
<input type="range" data-idx="1">
CSS:
html {
background: #393939;
}
input[type='range'] {
display: block;
margin: 2.5em auto;
border: solid .5em transparent;
padding: 0;
width: 15.5em;
height: 1em;
border-radius: .25em;
background: transparent;
font-size: 1em;
cursor: pointer;
}
input[type='range'], input[type='range']::-webkit-slider-runnable-track, input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
}
.js input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-moz-range-track {
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
}
.js input[type='range']::-moz-range-track {
background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-ms-track {
border: none;
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
color: transparent;
}
input[type='range']::-ms-fill-lower {
border-radius: 0.25em;
background: #e44e4f;
}
input[type='range']:nth-of-type(1)::-webkit-slider-runnable-track {
background-size: 50% 100%;
}
input[type='range']:nth-of-type(1)::-moz-range-track {
background-size: 50% 100%;
}
input[type='range']:nth-of-type(1)::-webkit-slider-thumb {
margin-top: -0.125em;
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']:nth-of-type(1)::-moz-range-thumb {
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']:nth-of-type(1)::-ms-thumb {
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']:nth-of-type(1)::-ms-tooltip {
display: none;
}
input[type='range']:focus {
outline: none;
box-shadow: 0 0 0.25em #e44e4f;
}
Javascript:
var s = document.createElement('style'),
r = document.querySelectorAll('input[type=range]'),
prefs = ['webkit-slider-runnable', 'moz-range'],
styles = [],
l = prefs.length
n = r.length;
document.body.appendChild(s);
var getTrackStyleStr = function(el) {
var str = '',
j = el.dataset.idx,
min = el.min || 0,
perc = (el.max) ? ~~(100*(el.value - min)/(el.max - min)) : el.value,
val = perc + '% 100%';
for(var i = 0; i < l; i++) {
str += '.js input[type=range]:nth-of-type(' + j + ')::-' + prefs[i] + '-track{background-size:' + val + '}';
}
return str;
};
var getTipStyleStr = function(el) {
var str = '.js input[type=range]:nth-of-type(' + el.dataset.idx + ') /deep/ #thumb:after{content:"' + el.value + '%"}';
return str;
};
for(var i = 0; i < n; i++) {
styles.push('');
r[i].addEventListener('input', function() {
styles[this.dataset.idx] = getTrackStyleStr(this);
if(this.classList.contains('tip')) {
styles[this.dataset.idx] += getTipStyleStr(this);
}
s.textContent = styles.join('');
}, false);
}
This works great for one range element but if I try adding more range elements on the same page, and change the data attribute to data-idx="2" it will not work, the first range will control them all.
How can I adjust the code to make each range work independently?
Here is a JSFiddle of the code I'm using, for some reason the javascript isn't working on there at all, but it's works fine on codepen? Hmm...
Here is the original Codepen
SOLUTION
var r = document.querySelectorAll('input[type=range]'),
prefs = ['webkit-slider-runnable', 'moz-range'],
styles = [],
l = prefs.length,
n = r.length;
var getTrackStyleStr = function(el, j) {
var str = '',
min = el.min || 0,
perc = (el.max) ? ~~(100*(el.value - min)/(el.max - min)) : el.value,
val = perc + '% 100%';
el.previousElementSibling.textContent = el.value;
for(var i = 0; i < l; i++) {
str += "input[type=range][data-rangeId='" + j + "']::-" + prefs[i] + '-track{background-size:' + val + '} ';
}
return str;
};
var setDragStyleStr = function(evt) {
var trackStyle = getTrackStyleStr(evt.target, this);
styles[this].textContent = trackStyle;
};
for(var i = 0; i < n; i++) {
var s = document.createElement('style');
document.body.appendChild(s);
styles.push(s);
r[i].setAttribute('data-rangeId', i);
r[i].addEventListener('input', setDragStyleStr.bind(i));
}
html {
background: #393939;
}
div {
margin: 2.5em auto;
}
input[type='range'] {
display: block;
margin: 0.2em auto;
border: solid .5em transparent;
padding: 0;
width: 15.5em;
height: 1em;
border-radius: .25em;
background: transparent;
font-size: 1em;
cursor: pointer;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
}
input[type='range']::-webkit-slider-runnable-track {
background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-moz-range-track {
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
}
input[type='range']::-moz-range-track {
background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-ms-track {
border: none;
width: 15.5em;
height: 0.5em;
border-radius: 0.25em;
background: #fff;
color: transparent;
}
input[type='range']::-ms-fill-lower {
border-radius: 0.25em;
background: #e44e4f;
}
input[type='range']::-webkit-slider-runnable-track {
background-size: 0% 100%;
}
input[type='range']::-moz-range-track {
background-size: 0% 100%;
}
input[type='range']::-webkit-slider-thumb {
margin-top: -0.125em;
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']::-moz-range-thumb {
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']::-ms-thumb {
border: none;
width: 0.75em;
height: 0.75em;
border-radius: 50%;
box-shadow: 0 0 0.125em #333;
background: #fff;
}
input[type='range']::-ms-tooltip {
display: none;
}
input[type='range']:focus {
outline: none;
box-shadow: 0 0 0.25em #e44e4f;
}
output[for='range'] {
font-family: "Lucida Grande","Lucida Sans Unicode", Tahoma, Sans-Serif;
font-size: 13px;
color: white;
display: block;
text-align: center;
}
<div>
<output for="range">0</output>
<input type="range" value="0">
</div>
<div>
<output for="range">0</output>
<input type="range" value="0">
</div>
<div>
<output for="range">0</output>
<input type="range" value="0">
</div>
Jquery UI offers some functional sliders that can be used in multiple instances on a page. You don't have to write or modify as much code to use them as above. Unless you are trying to avoid jquery, this may be a better option for you.
Here is a link to the multiple sliders demo.
The approach used for multiple sliders relies of course on jquery, but given markup such as:
<div id="eq">
<span>88</span>
<span>77</span>
<span>55</span>
<span>33</span>
<span>40</span>
<span>45</span>
<span>70</span>
</div>
A simple .each statement handles setting them all up.
$( "#eq > span" ).each(function() {
// read initial values from markup and remove that
var value = parseInt( $( this ).text(), 10 );
$( this ).empty().slider({
value: value,
range: "min",
animate: true,
orientation: "vertical"
});
});
Edit: As per comments below, if you want to add tool-tips / hints, you have to roll your own. Here's a brief example from some code I wrote last year. It has some specific behaviors that fit the needs of my users, but this should give you an idea. The id "hintrow" refers to a table row on a grid that contained my slider. Through experimentation, you can probably find the best place relative to your various sliders to append this. It will get positioned so you only want a dom node to append it to.
function drawExtCues(){
z = 200;
$('#hintrow').append('<div id="hintContainer" style="position:relative"></div>');
for(h in rowobjects){
z++;
$('#hintContainer').append('<div title="' + rowobject[h].property1 + '" class="' + rowobject[h].property2+ ' ui-slider-range hint" style="z-index:' + z +';">' + rowobject[h].property1+ '</div>');
}
$('.hint').mouseover(function(){
hintMouseOver();
});
}
function hintMouseOver(){
$('.hint').addClass('hintInspect',500);
$('.hint').unbind('mouseover');
$('.hint').click(function(){
$J('.hint').removeClass('hintInspect',500);
$J('.hint').mouseover(function(){hintMouseOver();})
});
}
Note the z++. This was used to ensure my tool-tips would stack. Since we made them click to dismiss in our case, this worked well. You don't have to do this, but if you don't use a click to dismiss, you might want to bind a timeout to clear the tool tip for you.
The hintMouseOver function does some house cleaning, like unbinding itself to prevent repeat calls. It is rebound after the click event to dismiss the tool tip is fired. This is just the behavior my client wanted. You could do a lot of things here. The class hintInspect is basically the style rules for how your tool-tip will appear. You can make it look any way you like. I think I just used a simple black outline with grey background.

Categories

Resources