I created a simple website as follows:
When I enter any text in the prompt and click okay, then a ball will be dropped into 1st box, i.e., into Past Thoughts box. Here is the code:
HTML
<h1>
Welcome to zen module
</h1>
<p id="demo">
</p>
<div id="divn">
<canvas id="myCanvas" width="100" height="300" style="transform: inherit; margin: 30px;">
</canvas>
</div>
<div class="fixed-size-square" onclick="popup();">
<span>
Past Thoughts
</span>
</div>
<div class="size-square" onclick="popup();">
<span>
Present Thoughts
</span>
</div>
<div class="square" onclick="popup();">
<span>
Future Thoughts
</span>
</div>
<button>
I've no thoughts
</button>
JavaScript
var context;
var dx = 4;
var dy = 4;
var y = 25;
var x = 10;
var counter = 0;
function draw() {
context = myCanvas.getContext('2d');
context.clearRect(0, 0, 400, 400);
context.beginPath();
context.fillStyle = "red";
context.arc(x, y, 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
if (x < 0 || x > 100) dx = -dx;
if (y < 0 || y > 200) dy = 0;
//x+=dx;
y += dy;
}
function popup() {
var thought = prompt("Please enter your thought");
if (thought !== null) {
setInterval(draw, 10);
} else window.alert("You should enter a thought");
}
CSS
.fixed-size-square {
display: table;
background: green;
}
.fixed-size-square span {
display: table-cell;
text-align: center;
vertical-align: middle;
color: white
}
.size-square {
display: table;
background: green;
}
.size-square span {
display: table-cell;
text-align: center;
vertical-align: middle;
color: white
}
.square {
display: table;
background: green;
}
.square span {
display: table-cell;
text-align: center;
vertical-align: middle;
color: white
}
.fixed-size-square, .size-square, .square {
float: left;
margin: 20px;
zoom: 1;
position: relative;
top: -291px;
width: 150px;
height: 150px;
/*box-shadow: 10px 10px 5px #888888;*/
/*position: absolute;*/
/*margin: auto;*/
}
button {
position: relative;
margin: 0px auto;
}
/*.myCanvas {
z-index: 0px;
}*/
#divn {
margin: 0px auto;
}
The problem is: The ball stays behind the box when it falls. It isn't visible in the box. How can it be fixed?
Fiddle
You could use opacity: 0.5; on .fixed-size-square, .size-square, .square
DEMO
Edit: here's a DEMO with optimized CSS.
position:relative;z-index:10000px; would do the trick but would mess with the layout you have now. I'd suggest something like this:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function popup (n) {
var context;
var dx= 4;
var dy=4;
var y=25;
var elWidth=150;
var ballWidth=10;
var x=(elWidth+ballWidth)/2;
var counter = 0;
var myCanvas=document.getElementById('myCanvas'+n);
function draw(){
context= myCanvas.getContext('2d');
context.clearRect(0,0,200,235);
context.beginPath();
context.fillStyle="red";
context.arc(x,y,10,0,Math.PI*2,true);
context.closePath();
context.fill();
if(y>200){clearInterval(interval);}
if( y<0 || y>200)dy=0;
y+=dy;
myCanvas.className='active';
}
var interval=setInterval(draw,10);
}
</script>
<style>
html,body{margin:0;}
div.time {
display: table;
background: green;
float: left;
margin: 20px;
zoom: 1;
position: relative;
top: 75px;
left:35px;
width: 150px;
height: 150px;
}
span {
display: table-cell;
text-align: center;
vertical-align: middle;
color: white
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
canvas{
z-index:10000;
transform: inherit;
float: left;
margin: 20px;
zoom: 1;
position: relative;
top: -200px;
left:35px;
margin:20px;
}
#myCanvas1{clear:left;}
</style>
</head>
<body>
<div class="time"><span>Past Thoughts</span></div>
<div class="time"><span>Present Thoughts</span></div>
<div class="time"><span>Future Thoughts</span></div>
<canvas id="myCanvas1" width="150" height="235" onclick="popup(1)"></canvas>
<canvas id="myCanvas2" width="150" height="235" onclick="popup(2)"></canvas>
<canvas id="myCanvas3" width="150" height="235" onclick="popup(3)"></canvas>
</body>
</html>
http://fiddle.jshell.net/uvrkgrqs/show/
there's an z-index property on html to set which layer things are.
Related
Is it possible to make a HTML5 slider with two input values, for example to select a price range? If so, how can it be done?
I've been looking for a lightweight, dependency free dual slider for some time (it seemed crazy to import jQuery just for this) and there don't seem to be many out there. I ended up modifying #Wildhoney's code a bit and really like it.
function getVals(){
// Get slider values
var parent = this.parentNode;
var slides = parent.getElementsByTagName("input");
var slide1 = parseFloat( slides[0].value );
var slide2 = parseFloat( slides[1].value );
// Neither slider will clip the other, so make sure we determine which is larger
if( slide1 > slide2 ){ var tmp = slide2; slide2 = slide1; slide1 = tmp; }
var displayElement = parent.getElementsByClassName("rangeValues")[0];
displayElement.innerHTML = slide1 + " - " + slide2;
}
window.onload = function(){
// Initialize Sliders
var sliderSections = document.getElementsByClassName("range-slider");
for( var x = 0; x < sliderSections.length; x++ ){
var sliders = sliderSections[x].getElementsByTagName("input");
for( var y = 0; y < sliders.length; y++ ){
if( sliders[y].type ==="range" ){
sliders[y].oninput = getVals;
// Manually trigger event first time to display values
sliders[y].oninput();
}
}
}
}
section.range-slider {
position: relative;
width: 200px;
height: 35px;
text-align: center;
}
section.range-slider input {
pointer-events: none;
position: absolute;
overflow: hidden;
left: 0;
top: 15px;
width: 200px;
outline: none;
height: 18px;
margin: 0;
padding: 0;
}
section.range-slider input::-webkit-slider-thumb {
pointer-events: all;
position: relative;
z-index: 1;
outline: 0;
}
section.range-slider input::-moz-range-thumb {
pointer-events: all;
position: relative;
z-index: 10;
-moz-appearance: none;
width: 9px;
}
section.range-slider input::-moz-range-track {
position: relative;
z-index: -1;
background-color: rgba(0, 0, 0, 1);
border: 0;
}
section.range-slider input:last-of-type::-moz-range-track {
-moz-appearance: none;
background: none transparent;
border: 0;
}
section.range-slider input[type=range]::-moz-focus-outer {
border: 0;
}
<!-- This block can be reused as many times as needed -->
<section class="range-slider">
<span class="rangeValues"></span>
<input value="5" min="0" max="15" step="0.5" type="range">
<input value="10" min="0" max="15" step="0.5" type="range">
</section>
No, the HTML5 range input only accepts one input. I would recommend you to use something like the jQuery UI range slider for that task.
Coming late, but noUiSlider avoids having a jQuery-ui dependency, which the accepted answer does not. Its only "caveat" is IE support is for IE9 and newer, if legacy IE is a deal breaker for you.
It's also free, open source and can be used in commercial projects without restrictions.
Installation: Download noUiSlider, extract the CSS and JS file somewhere in your site file system, and then link to the CSS from head and to JS from body:
<!-- In <head> -->
<link href="nouislider.min.css" rel="stylesheet">
<!-- In <body> -->
<script src="nouislider.min.js"></script>
Example usage: Creates a slider which goes from 0 to 100, and starts set to 20-80.
HTML:
<div id="slider">
</div>
JS:
var slider = document.getElementById('slider');
noUiSlider.create(slider, {
start: [20, 80],
connect: true,
range: {
'min': 0,
'max': 100
}
});
Sure you can simply use two sliders overlaying each other and add a bit of javascript (actually not more than 5 lines) that the selectors are not exceeding the min/max values (like in #Garys) solution.
Attached you'll find a short snippet adapted from a current project including some CSS3 styling to show what you can do (webkit only). I also added some labels to display the selected values.
It uses JQuery but a vanillajs version is no magic though.
#Update: The code below was just a proof of concept. Due to many requests I've added a possible solution for Mozilla Firefox (without changing the original code). You may want to refractor the code below before using it.
(function() {
function addSeparator(nStr) {
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + '.' + '$2');
}
return x1 + x2;
}
function rangeInputChangeEventHandler(e){
var rangeGroup = $(this).attr('name'),
minBtn = $(this).parent().children('.min'),
maxBtn = $(this).parent().children('.max'),
range_min = $(this).parent().children('.range_min'),
range_max = $(this).parent().children('.range_max'),
minVal = parseInt($(minBtn).val()),
maxVal = parseInt($(maxBtn).val()),
origin = $(this).context.className;
if(origin === 'min' && minVal > maxVal-5){
$(minBtn).val(maxVal-5);
}
var minVal = parseInt($(minBtn).val());
$(range_min).html(addSeparator(minVal*1000) + ' €');
if(origin === 'max' && maxVal-5 < minVal){
$(maxBtn).val(5+ minVal);
}
var maxVal = parseInt($(maxBtn).val());
$(range_max).html(addSeparator(maxVal*1000) + ' €');
}
$('input[type="range"]').on( 'input', rangeInputChangeEventHandler);
})();
body{
font-family: sans-serif;
font-size:14px;
}
input[type='range'] {
width: 210px;
height: 30px;
overflow: hidden;
cursor: pointer;
outline: none;
}
input[type='range'],
input[type='range']::-webkit-slider-runnable-track,
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
background: none;
}
input[type='range']::-webkit-slider-runnable-track {
width: 200px;
height: 1px;
background: #003D7C;
}
input[type='range']:nth-child(2)::-webkit-slider-runnable-track{
background: none;
}
input[type='range']::-webkit-slider-thumb {
position: relative;
height: 15px;
width: 15px;
margin-top: -7px;
background: #fff;
border: 1px solid #003D7C;
border-radius: 25px;
z-index: 1;
}
input[type='range']:nth-child(1)::-webkit-slider-thumb{
z-index: 2;
}
.rangeslider{
position: relative;
height: 60px;
width: 210px;
display: inline-block;
margin-top: -5px;
margin-left: 20px;
}
.rangeslider input{
position: absolute;
}
.rangeslider{
position: absolute;
}
.rangeslider span{
position: absolute;
margin-top: 30px;
left: 0;
}
.rangeslider .right{
position: relative;
float: right;
margin-right: -5px;
}
/* Proof of concept for Firefox */
#-moz-document url-prefix() {
.rangeslider::before{
content:'';
width:100%;
height:2px;
background: #003D7C;
display:block;
position: relative;
top:16px;
}
input[type='range']:nth-child(1){
position:absolute;
top:35px !important;
overflow:visible !important;
height:0;
}
input[type='range']:nth-child(2){
position:absolute;
top:35px !important;
overflow:visible !important;
height:0;
}
input[type='range']::-moz-range-thumb {
position: relative;
height: 15px;
width: 15px;
margin-top: -7px;
background: #fff;
border: 1px solid #003D7C;
border-radius: 25px;
z-index: 1;
}
input[type='range']:nth-child(1)::-moz-range-thumb {
transform: translateY(-20px);
}
input[type='range']:nth-child(2)::-moz-range-thumb {
transform: translateY(-20px);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="rangeslider">
<input class="min" name="range_1" type="range" min="1" max="100" value="10" />
<input class="max" name="range_1" type="range" min="1" max="100" value="90" />
<span class="range_min light left">10.000 €</span>
<span class="range_max light right">90.000 €</span>
</div>
Actually I used my script in html directly. But in javascript when you add oninput event listener for this event it gives the data automatically.You just need to assign the value as per your requirement.
[slider] {
width: 300px;
position: relative;
height: 5px;
margin: 45px 0 10px 0;
}
[slider] > div {
position: absolute;
left: 13px;
right: 15px;
height: 5px;
}
[slider] > div > [inverse-left] {
position: absolute;
left: 0;
height: 5px;
border-radius: 10px;
background-color: #CCC;
margin: 0 7px;
}
[slider] > div > [inverse-right] {
position: absolute;
right: 0;
height: 5px;
border-radius: 10px;
background-color: #CCC;
margin: 0 7px;
}
[slider] > div > [range] {
position: absolute;
left: 0;
height: 5px;
border-radius: 14px;
background-color: #d02128;
}
[slider] > div > [thumb] {
position: absolute;
top: -7px;
z-index: 2;
height: 20px;
width: 20px;
text-align: left;
margin-left: -11px;
cursor: pointer;
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
background-color: #FFF;
border-radius: 50%;
outline: none;
}
[slider] > input[type=range] {
position: absolute;
pointer-events: none;
-webkit-appearance: none;
z-index: 3;
height: 14px;
top: -2px;
width: 100%;
opacity: 0;
}
div[slider] > input[type=range]:focus::-webkit-slider-runnable-track {
background: transparent;
border: transparent;
}
div[slider] > input[type=range]:focus {
outline: none;
}
div[slider] > input[type=range]::-webkit-slider-thumb {
pointer-events: all;
width: 28px;
height: 28px;
border-radius: 0px;
border: 0 none;
background: red;
-webkit-appearance: none;
}
div[slider] > input[type=range]::-ms-fill-lower {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-fill-upper {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-tooltip {
display: none;
}
[slider] > div > [sign] {
opacity: 0;
position: absolute;
margin-left: -11px;
top: -39px;
z-index:3;
background-color: #d02128;
color: #fff;
width: 28px;
height: 28px;
border-radius: 28px;
-webkit-border-radius: 28px;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
text-align: center;
}
[slider] > div > [sign]:after {
position: absolute;
content: '';
left: 0;
border-radius: 16px;
top: 19px;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-top-width: 16px;
border-top-style: solid;
border-top-color: #d02128;
}
[slider] > div > [sign] > span {
font-size: 12px;
font-weight: 700;
line-height: 28px;
}
[slider]:hover > div > [sign] {
opacity: 1;
}
<div slider id="slider-distance">
<div>
<div inverse-left style="width:70%;"></div>
<div inverse-right style="width:70%;"></div>
<div range style="left:0%;right:0%;"></div>
<span thumb style="left:0%;"></span>
<span thumb style="left:100%;"></span>
<div sign style="left:0%;">
<span id="value">0</span>
</div>
<div sign style="left:100%;">
<span id="value">100</span>
</div>
</div>
<input type="range" value="0" max="100" min="0" step="1" oninput="
this.value=Math.min(this.value,this.parentNode.childNodes[5].value-1);
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[1].style.width=value+'%';
children[5].style.left=value+'%';
children[7].style.left=value+'%';children[11].style.left=value+'%';
children[11].childNodes[1].innerHTML=this.value;" />
<input type="range" value="100" max="100" min="0" step="1" oninput="
this.value=Math.max(this.value,this.parentNode.childNodes[3].value-(-1));
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[3].style.width=(100-value)+'%';
children[5].style.right=(100-value)+'%';
children[9].style.left=value+'%';children[13].style.left=value+'%';
children[13].childNodes[1].innerHTML=this.value;" />
</div>
The question was: "Is it possible to make a HTML5 slider with two input values, for example to select a price range? If so, how can it be done?"
In 2020 it is possible to create a fully accessible, native, non-jquery HTML5 slider with two thumbs for price ranges. If found this posted after I already created this solution and I thought that it would be nice to share my implementation here.
This implementation has been tested on mobile Chrome and Firefox (Android) and Chrome and Firefox (Linux). I am not sure about other platforms, but it should be quite good. I would love to get your feedback and improve this solution.
This solution allows multiple instances on one page and it consists of just two inputs (each) with descriptive labels for screen readers. You can set the thumb size in the amount of grid labels. Also, you can use touch, keyboard and mouse to interact with the slider. The value is updated during adjustment, due to the 'on input' event listener.
My first approach was to overlay the sliders and clip them. However, that resulted in complex code with a lot of browser dependencies. Then I recreated the solution with two sliders that were 'inline'. This is the solution you will find below.
var thumbsize = 14;
function draw(slider,splitvalue) {
/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var lower = slider.querySelector('.lower');
var upper = slider.querySelector('.upper');
var legend = slider.querySelector('.legend');
var thumbsize = parseInt(slider.getAttribute('data-thumbsize'));
var rangewidth = parseInt(slider.getAttribute('data-rangewidth'));
var rangemin = parseInt(slider.getAttribute('data-rangemin'));
var rangemax = parseInt(slider.getAttribute('data-rangemax'));
/* set min and max attributes */
min.setAttribute('max',splitvalue);
max.setAttribute('min',splitvalue);
/* set css */
min.style.width = parseInt(thumbsize + ((splitvalue - rangemin)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
max.style.width = parseInt(thumbsize + ((rangemax - splitvalue)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
min.style.left = '0px';
max.style.left = parseInt(min.style.width)+'px';
min.style.top = lower.offsetHeight+'px';
max.style.top = lower.offsetHeight+'px';
legend.style.marginTop = min.offsetHeight+'px';
slider.style.height = (lower.offsetHeight + min.offsetHeight + legend.offsetHeight)+'px';
/* correct for 1 off at the end */
if(max.value>(rangemax - 1)) max.setAttribute('data-value',rangemax);
/* write value and labels */
max.value = max.getAttribute('data-value');
min.value = min.getAttribute('data-value');
lower.innerHTML = min.getAttribute('data-value');
upper.innerHTML = max.getAttribute('data-value');
}
function init(slider) {
/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var rangemin = parseInt(min.getAttribute('min'));
var rangemax = parseInt(max.getAttribute('max'));
var avgvalue = (rangemin + rangemax)/2;
var legendnum = slider.getAttribute('data-legendnum');
/* set data-values */
min.setAttribute('data-value',rangemin);
max.setAttribute('data-value',rangemax);
/* set data vars */
slider.setAttribute('data-rangemin',rangemin);
slider.setAttribute('data-rangemax',rangemax);
slider.setAttribute('data-thumbsize',thumbsize);
slider.setAttribute('data-rangewidth',slider.offsetWidth);
/* write labels */
var lower = document.createElement('span');
var upper = document.createElement('span');
lower.classList.add('lower','value');
upper.classList.add('upper','value');
lower.appendChild(document.createTextNode(rangemin));
upper.appendChild(document.createTextNode(rangemax));
slider.insertBefore(lower,min.previousElementSibling);
slider.insertBefore(upper,min.previousElementSibling);
/* write legend */
var legend = document.createElement('div');
legend.classList.add('legend');
var legendvalues = [];
for (var i = 0; i < legendnum; i++) {
legendvalues[i] = document.createElement('div');
var val = Math.round(rangemin+(i/(legendnum-1))*(rangemax - rangemin));
legendvalues[i].appendChild(document.createTextNode(val));
legend.appendChild(legendvalues[i]);
}
slider.appendChild(legend);
/* draw */
draw(slider,avgvalue);
/* events */
min.addEventListener("input", function() {update(min);});
max.addEventListener("input", function() {update(max);});
}
function update(el){
/* set function vars */
var slider = el.parentElement;
var min = slider.querySelector('#min');
var max = slider.querySelector('#max');
var minvalue = Math.floor(min.value);
var maxvalue = Math.floor(max.value);
/* set inactive values before draw */
min.setAttribute('data-value',minvalue);
max.setAttribute('data-value',maxvalue);
var avgvalue = (minvalue + maxvalue)/2;
/* draw */
draw(slider,avgvalue);
}
var sliders = document.querySelectorAll('.min-max-slider');
sliders.forEach( function(slider) {
init(slider);
});
* {padding: 0; margin: 0;}
body {padding: 40px;}
.min-max-slider {position: relative; width: 200px; text-align: center; margin-bottom: 50px;}
.min-max-slider > label {display: none;}
span.value {height: 1.7em; font-weight: bold; display: inline-block;}
span.value.lower::before {content: "€"; display: inline-block;}
span.value.upper::before {content: "- €"; display: inline-block; margin-left: 0.4em;}
.min-max-slider > .legend {display: flex; justify-content: space-between;}
.min-max-slider > .legend > * {font-size: small; opacity: 0.25;}
.min-max-slider > input {cursor: pointer; position: absolute;}
/* webkit specific styling */
.min-max-slider > input {
-webkit-appearance: none;
outline: none!important;
background: transparent;
background-image: linear-gradient(to bottom, transparent 0%, transparent 30%, silver 30%, silver 60%, transparent 60%, transparent 100%);
}
.min-max-slider > input::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 14px; /* Set a specific slider handle width */
height: 14px; /* Slider handle height */
background: #eee; /* Green background */
cursor: pointer; /* Cursor on hover */
border: 1px solid gray;
border-radius: 100%;
}
.min-max-slider > input::-webkit-slider-runnable-track {cursor: pointer;}
<div class="min-max-slider" data-legendnum="2">
<label for="min">Minimum price</label>
<input id="min" class="min" name="min" type="range" step="1" min="0" max="3000" />
<label for="max">Maximum price</label>
<input id="max" class="max" name="max" type="range" step="1" min="0" max="3000" />
</div>
Note that you should keep the step size to 1 to prevent the values to change due to redraws/redraw bugs.
View online at: https://codepen.io/joosts/pen/rNLdxvK
2022 - Accessible solution - 30 second solution to implement
This solution builds off of this answer by #JoostS. Accessibility is something none of the answers have focused on and that is a problem, so I built off of the above answer by making it more accessible & extensible since it had some flaws.
Usage is very simple:
Use the CDN or host the script locally: https://cdn.jsdelivr.net/gh/maxshuty/accessible-web-components/dist/simpleRange.min.js
Add this element to your template or HTML: <range-selector min-range="0" max-range="1000" />
Hook into it by listening for the range-changed event (or whatever event-name-to-emit-on-change you pass in)
That's it. View the full demo here. You can easily customize it by simply applying attributes like inputs-for-labels to use inputs instead of labels, slider-color to adjust the color, and so much more!
Here is a fiddle:
window.addEventListener('range-changed', (e) => {console.log(`Range changed for: ${e.detail.sliderId}. Min/Max range values are available in this object too`)})
<script src="https://cdn.jsdelivr.net/gh/maxshuty/accessible-web-components#latest/dist/simpleRange.min.js"></script>
<div>
<range-selector
id="rangeSelector1"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
number-of-legend-items-to-show="6"
/>
</div>
<div>
<range-selector
id="rangeSelector1"
min-label="Minimum"
max-label="Maximum"
min-range="1"
max-range="500"
number-of-legend-items-to-show="3"
inputs-for-labels
/>
</div>
<div>
<range-selector
id="rangeSelector2"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
number-of-legend-items-to-show="3"
slider-color="#6b5b95"
/>
</div>
<div>
<range-selector
id="rangeSelector3"
min-label="Minimum"
max-label="Maximum"
min-range="1000"
max-range="2022"
hide-label
hide-legend
/>
</div>
I decided to address the issues of the linked answer like the labels using display: none (bad for a11y), no visual focus on the slider, etc., and improve the code by cleaning up event listeners and making it much more dynamic and extensible.
I created this tiny library with many options to customize colors, event names, easily hook into it, make the accessible labels i18n capable and much more. Here it is in a fiddle if you want to play around.
You can easily customize the number of legend items it shows, hide or show the labels and legend, and customize the colors of everything, including the focus color like this.
Example using several of the props:
<range-selector
min-label="i18n Minimum Range"
max-label="i18n Maximum Range"
min-range="5"
max-range="555"
number-of-legend-items-to-show="6"
event-name-to-emit-on-change="my-custom-range-changed-event"
slider-color="orange"
circle-color="#f7cac9"
circle-border-color="#083535"
circle-focus-border-color="#3ec400"
/>
Then in your script:
window.addEventListener('my-custom-range-changed-event', (e) => { const data = e.detail; });
Finally if you see that this is missing something that you need I made it very easy to customize this library.
Simply copy this file and at the top you can see cssHelpers and constants objects that contain most of the variables you would likely want to further customize.
Since I built this with a Native Web Component I have taken advantage of disconnectedCallback and other hooks to clean up event listeners and set things up.
Here is a reusable double range slider implementation, base on tutorial Double Range Slider by Coding Artist
near native UI, Chrome/Firefox/Safari compatible
API EventTarget based, with change/input events, minGap/maxGap properties
let $ = (s, c = document) => c.querySelector(s);
let $$ = (s, c = document) => Array.prototype.slice.call(c.querySelectorAll(s));
class DoubleRangeSlider extends EventTarget {
#minGap = 0;
#maxGap = Number.MAX_SAFE_INTEGER;
#inputs;
style = {
trackColor: '#dadae5',
rangeColor: '#3264fe',
};
constructor(container){
super();
let inputs = $$('input[type="range"]', container);
if(inputs.length !== 2){
throw new RangeError('2 range inputs expected');
}
let [input1, input2] = inputs;
if(input1.min >= input1.max || input2.min >= input2.max){
throw new RangeError('range min should be less than max');
}
if(input1.max > input2.max || input1.min > input2.min){
throw new RangeError('input1\'s max/min should not be greater than input2\'s max/min');
}
this.#inputs = inputs;
let sliderTrack = $('.slider-track', container);
let lastValue1 = input1.value;
input1.addEventListener('input', (e) => {
let value1 = +input1.value;
let value2 = +input2.value;
let minGap = this.#minGap;
let maxGap = this.#maxGap;
let gap = value2 - value1;
let newValue1 = value1;
if(gap < minGap){
newValue1 = value2 - minGap;
}else if(gap > maxGap){
newValue1 = value2 - maxGap;
}
input1.value = newValue1;
if(input1.value !== lastValue1){
lastValue1 = input1.value;
passEvent(e);
fillColor();
}
});
let lastValue2 = input2.value;
input2.addEventListener('input', (e) => {
let value1 = +input1.value;
let value2 = +input2.value;
let minGap = this.#minGap;
let maxGap = this.#maxGap;
let gap = value2 - value1;
let newValue2 = value2;
if(gap < minGap){
newValue2 = value1 + minGap;
}else if(gap > maxGap){
newValue2 = value1 + maxGap;
}
input2.value = newValue2;
if(input2.value !== lastValue2){
lastValue2 = input2.value;
passEvent(e);
fillColor();
}
});
let passEvent = (e) => {
this.dispatchEvent(new e.constructor(e.type, e));
};
input1.addEventListener('change', passEvent);
input2.addEventListener('change', passEvent);
let fillColor = () => {
let overallMax = +input2.max;
let overallMin = +input1.min;
let overallRange = overallMax - overallMin;
let left1 = ((input1.value - overallMin) / overallRange * 100) + '%';
let left2 = ((input2.value - overallMin) / overallRange * 100) + '%';
let {trackColor, rangeColor} = this.style;
sliderTrack.style.background = `linear-gradient(to right, ${trackColor} ${left1}, ${rangeColor} ${left1}, ${rangeColor} ${left2}, ${trackColor} ${left2})`;
};
let init = () => {
let overallMax = +input2.max;
let overallMin = +input1.min;
let overallRange = overallMax - overallMin;
let range1 = input1.max - overallMin;
let range2 = overallMax - input2.min;
input1.style.left = '0px';
input1.style.width = (range1 / overallRange * 100) + '%';
input2.style.right = '0px';
input2.style.width = (range2 / overallRange * 100) + '%';
fillColor();
};
init();
}
get minGap(){
return this.#minGap;
}
set minGap(v){
this.#minGap = v;
}
get maxGap(){
return this.#maxGap;
}
set maxGap(v){
this.#maxGap = v;
}
get values(){
return this.#inputs.map((el) => el.value);
}
set values(values){
if(values.length !== 2 || !values.every(isFinite))
throw new RangeError();
let [input1, input2] = this.#inputs;
let [value1, value2] = values;
if(value1 > input1.max || value1 < input1.min)
throw new RangeError('invalid value for input1');
if(value2 > input2.max || value2 < input2.min)
throw new RangeError('invalid value for input2');
input1.value = value1;
input2.value = value2;
}
get inputs(){
return this.#inputs;
}
get overallMin(){
return this.#inputs[0].min;
}
get overallMax(){
return this.#inputs[1].max;
}
}
function main(){
let container = $('.slider-container');
let slider = new DoubleRangeSlider(container);
slider.minGap = 30;
slider.maxGap = 70;
let inputs = $$('input[name="a"]');
let outputs = $$('output[name="a"]');
outputs[0].value = inputs[0].value;
outputs[1].value = inputs[1].value;
slider.addEventListener('input', (e) => {
let values = slider.values;
outputs[0].value = values[0];
outputs[1].value = values[1];
});
slider.addEventListener('change', (e) => {
let values = slider.values;
console.log('change', values);
outputs[0].value = values[0];
outputs[1].value = values[1];
});
}
document.addEventListener('DOMContentLoaded', main);
.slider-container {
display: inline-block;
position: relative;
width: 360px;
height: 28px;
}
.slider-track {
width: 100%;
height: 5px;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
border-radius: 5px;
}
.slider-container>input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: absolute;
margin: auto;
top: 0;
bottom: 0;
width: 100%;
outline: none;
background-color: transparent;
pointer-events: none;
}
.slider-container>input[type="range"]::-webkit-slider-runnable-track {
-webkit-appearance: none;
height: 5px;
}
.slider-container>input[type="range"]::-moz-range-track {
-moz-appearance: none;
height: 5px;
}
.slider-container>input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
margin-top: -9px;
height: 1.7em;
width: 1.7em;
background-color: #3264fe;
cursor: pointer;
pointer-events: auto;
border-radius: 50%;
}
.slider-container>input[type="range"]::-moz-range-thumb {
-moz-appearance: none;
height: 1.7em;
width: 1.7em;
cursor: pointer;
border: none;
border-radius: 50%;
background-color: #3264fe;
pointer-events: auto;
}
.slider-container>input[type="range"]:active::-webkit-slider-thumb {
background-color: #ffffff;
border: 3px solid #3264fe;
}
<h3>Double Range Slider, Reusable Edition</h3>
<div class="slider-container">
<div class="slider-track"></div>
<input type="range" name="a" min="-130" max="-30" step="1" value="-100" autocomplete="off" />
<input type="range" name="a" min="-60" max="0" step="2" value="-30" autocomplete="off" />
</div>
<div>
<output name="a"></output> ~ <output name="a"></output>
</div>
<pre>
Changes:
1. allow different min/max/step for two inputs
2. new property 'maxGap'
3. added events 'input'/'change'
4. dropped IE/OldEdge support
</pre>
For those working with Vue, there is now Veeno available, based on noUiSlider. But it does not seem to be maintained anymore. :-(
This code covers following points
Dual slider using HTML, CSS, JS
I have modified this slider using embedded ruby so we can save previously applied values using params in rails.
<% left_width = params[:min].nil? ? 0 : ((params[:min].to_f/100000) * 100).to_i %>
<% left_value = params[:min].nil? ? '0' : params[:min] %>
<% right_width = params[:max].nil? ? 100 : ((params[:max].to_f/100000) * 100).to_i %>
<% right_value = params[:max].nil? ? '100000' : params[:max] %>
<div class="range-slider-outer">
<div slider id="slider-distance">
<div class="slider-inner">
<div inverse-left style="width:<%= left_width %>%;"></div>
<div inverse-right style="width:<%= 100 - right_width %>%;"></div>
<div range style="left:<%= left_width %>%;right:<%= 100 - right_width %>%;"></div>
<span thumb style="left:<%= left_width %>%;"></span>
<span thumb style="left:<%= right_width %>%;"></span>
<div sign style="">
Rs.<span id="value"><%= left_value.to_i %></span> to
</div>
<div sign style="">
Rs.<span id="value"><%= right_value.to_i %></span>
</div>
</div>
<input type="range" name="min" value=<%= left_value %> max="100000" min="0" step="100" oninput="
this.value=Math.min(this.value,this.parentNode.childNodes[5].value-1);
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[1].style.width=value+'%';
children[5].style.left=value+'%';
children[7].style.left=value+'%';children[11].style.left=value+'%';
children[11].childNodes[1].innerHTML=this.value;" />
<input type="range" name="max" value=<%= right_value %> max="100000" min="0" step="100" oninput="
this.value=Math.max(this.value,this.parentNode.childNodes[3].value-(-1));
let value = (this.value/parseInt(this.max))*100
var children = this.parentNode.childNodes[1].childNodes;
children[3].style.width=(100-value)+'%';
children[5].style.right=(100-value)+'%';
children[9].style.left=value+'%';children[13].style.left=value+'%';
children[13].childNodes[1].innerHTML=this.value;" />
</div>
<div class="range-label">
<div>0</div>
<div>100000</div>
</div>
</div>
[slider] {
/*width: 300px;*/
position: relative;
height: 5px;
/*margin: 20px auto;*/
/* height: 100%; */
}
[slider] > div {
position: absolute;
left: 13px;
right: 15px;
height: 14px;
top: 5px;
}
[slider] > div > [inverse-left] {
position: absolute;
left: 0;
height: 14px;
border-radius: 3px;
background-color: #CCC;
/*margin: 0 7px;*/
margin: 0 -7px;
}
[slider] > div > [inverse-right] {
position: absolute;
right: 0;
height: 14px;
border-radius: 3px;
background-color: #CCC;
/*margin: 0 7px;*/
margin: 0 -7px;
}
[slider] > div > [range] {
position: absolute;
left: 0;
height: 14px;
border-radius: 14px;
background-color:#8950fc;
}
[slider] > div > [thumb] {
position: absolute;
top: -3px;
z-index: 2;
height: 20px;
width: 20px;
text-align: left;
margin-left: -11px;
cursor: pointer;
/* box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4); */
background-color: #FFF;
/*border-radius: 50%;*/
border-radius:2px;
outline: none;
}
[slider] > input[type=range] {
position: absolute;
pointer-events: none;
-webkit-appearance: none;
z-index: 3;
height: 14px;
top: -2px;
width: 100%;
opacity: 0;
}
div[slider] > input[type=range]:focus::-webkit-slider-runnable-track {
background: transparent;
border: transparent;
}
div[slider] > input[type=range]:focus {
outline: none;
}
div[slider] > input[type=range]::-webkit-slider-thumb {
pointer-events: all;
width: 28px;
height: 28px;
border-radius: 0px;
border: 0 none;
background: red;
-webkit-appearance: none;
}
div[slider] > input[type=range]::-ms-fill-lower {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-fill-upper {
background: transparent;
border: 0 none;
}
div[slider] > input[type=range]::-ms-tooltip {
display: none;
}
[slider] > div > [sign] {
/* opacity: 0;
position: absolute;
margin-left: -11px;
top: -39px;
z-index:3;
background-color:#1a243a;
color: #fff;
width: 28px;
height: 28px;
border-radius: 28px;
-webkit-border-radius: 28px;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
text-align: center;*/
color: #A5B2CB;
border-radius: 28px;
justify-content: center;
text-align: center;
display: inline-block;
margin-top: 12px;
font-size: 14px;
font-weight: bold;
}
.slider-inner{
text-align:center;
}
/*[slider] > div > [sign]:after {
position: absolute;
content: '';
left: 0;
border-radius: 16px;
top: 19px;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-top-width: 16px;
border-top-style: solid;
border-top-color:#1a243a;
}*/
[slider] > div > [sign] > span {
font-size: 12px;
font-weight: 700;
line-height: 28px;
}
[slider]:hover > div > [sign] {
opacity: 1;
}
.range-label{
display: flex;
justify-content: space-between;
margin-top: 28px;
padding: 0px 5px;
}
.range-slider-outer{
width:calc(100% - 20px);
margin:auto;
margin-bottom: 10px;
margin-top: 10px;
}
I want to drag and drop those 3 shapes into mxgraph canvas (which is the black area).
Note: I want to fully preserve the drag element on the canvas, including shape, size, color, text, etc.
I don't know whether insertVertex does it work. Dragging the orange,red or other box in to the dark area currently does not work.
var graph;
function initCanvas() {
//This function is called onload of body itself and it will make the mxgraph canvas
graph = new mxGraph(document.getElementById('graph-wrapper'));
}
function handleDrag(event) {
event.dataTransfer.setData("draggedId", event.target.id);
}
function allowDrop(event) {
event.preventDefault();
}
function handleDrop(event) {
console.log('dropped');
event.preventDefault();
var parent = graph.getDefaultParent();
graph.getModel().beginUpdate();
var element = document.getElementById(event.dataTransfer.getData('draggedId'))
var gridRect = document.getElementById('graph-wrapper').getBoundingClientRect();
var targetX = event.x - gridRect.x;
var targetY = event.y - gridRect.y;
try {
graph.insertVertex(parent, null, element, targetX, targetY);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
}
#graph-wrapper {
background: #333;
width: 100%;
height: 528px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--
Copyright (c) 2006-2013, JGraph Ltd
Dynamic toolbar example for mxGraph. This example demonstrates changing the
state of the toolbar at runtime.
-->
<html>
<head>
<title>Toolbar example for mxGraph</title>
<script type="text/javascript">
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
</script>
<script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
</head>
<body onload="initCanvas()">
<h4>Drag Boxes onto the black canvas and see what happens</h4>
<div>
<div draggable="true" id="shape_1" ondragstart="handleDrag(event)" style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">Pipe</div>
<div draggable="true" id="shape_2" ondragstart="handleDrag(event)" style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">Team</div>
<div draggable="true" id="shape_3" ondragstart="handleDrag(event)" style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
<div> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg></div>
<div>Info</div>
</div>
</div>
<div id="graph-wrapper" ondrop='handleDrop(event)' ondragover="allowDrop(event)">
</div>
</body>
</html>
In mxgraph, normally you do that using so-called "stencil". You can define your own custom shapes using XML, and then use mxgraph to take care of the rest. RTFM :)
If you don't want to follow this baseline path, then things will become increasingly harder. Anyway, back to the point - you can use this example (it's an adopted version of the "sidebar" code you can find in the mxgraph) - for the details on functions see the Sidebar.js:
var graph;
function initCanvas() {
//This function is called onload of body itself and it will make the mxgraph canvas
graph = new mxGraph(document.getElementById('graph-wrapper'));
graph.htmlLabels = true;
graph.cellsEditable = false;
// render as HTML node always. You probably won't want that in real world though
graph.convertValueToString = function(cell) {
return cell.value;
}
const createDropHandler = function (cells, allowSplit) {
return function (graph, evt, target, x, y) {
const select = graph.importCells(cells, x, y, target);
graph.setSelectionCells(select);
};
};
const createDragPreview = function (width, height) {
var elt = document.createElement('div');
elt.style.border = '1px dashed black';
elt.style.width = width + 'px';
elt.style.height = height + 'px';
return elt;
};
const createDragSource = function (elt, dropHandler, preview) {
return mxUtils.makeDraggable(elt, graph, dropHandler, preview, 0, 0, graph.autoscroll, true, true);
};
const createItem = (id) => {
const elt = document.getElementById(id);
const width = elt.clientWidth;
const height = elt.clientHeight;
const cell = new mxCell('', new mxGeometry(0, 0, width, height), 'fillColor=none;strokeColor=none');
cell.vertex = true;
graph.model.setValue(cell, elt);
const cells = [cell];
const bounds = new mxRectangle(0, 0, width, height);
createDragSource(elt, createDropHandler(cells, true, false, bounds), createDragPreview(width, height), cells, bounds);
};
createItem("shape_1");
createItem("shape_2");
createItem("shape_3");
}
<html>
<head>
<title>Toolbar example for mxGraph</title>
<style>
#graph-wrapper {
background: #333;
width: 100%;
height: 528px;
}
</style>
<script type="text/javascript">
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
</script>
<script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
<script src="./app.js"></script>
</head>
<body onload="initCanvas()">
<h4>Drag Boxes onto the black canvas and see what happens</h4>
<div>
<div id="shape_1"
style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
Pipe
</div>
<div draggable="true" id="shape_2"
style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
Team
</div>
<div draggable="true" id="shape_3"
style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
<div> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
</svg></div>
<div>Info</div>
</div>
</div>
<div id="graph-wrapper">
</div>
</body>
</html>
Note that your code, and the other answer focuses on generic drag-n-drop, which is not applicable to mxgraph. You need to use library-specific code.
This works:
function onDragOver(event) {
event.preventDefault();
}
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
event
.currentTarget
.style
.backgroundColor = 'yellow';
}
function onDrop(event) {
const id = event
.dataTransfer
.getData('text');
const draggableElement = document.getElementById(id);
const dropzone = event.target;
dropzone.appendChild(draggableElement);
event
.dataTransfer
.clearData();
}
var canvas = document.getElementById("myCanvas-1");
var ctx = canvas.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Team", 60, 60);
var canvas = document.getElementById("myCanvas-2");
var ctx = canvas.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Pipe", 70, 60);
.example-parent {
border: 2px solid #DFA612;
color: black;
display: flex;
font-family: sans-serif;
font-weight: bold;
}
.example-origin {
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
.example-draggable {
background-color: white;
font-weight: normal;
margin-bottom: 10px;
margin-top: 10px;
padding: 10px;
}
.example-dropzone {
background-color: darkgrey;
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
<div class="example-parent">
<div class="example-origin">
<div id="draggable-1" class="example-draggable" draggable="true" ondragstart="onDragStart(event);">
<canvas id="myCanvas-1" width="200" height="100" style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
</canvas>
</div>
<div id="draggable-2" class="example-draggable" draggable="true" ondragstart="onDragStart(event);">
<canvas id="myCanvas-2" width="200" height="100" style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
</canvas>
</div>
<div class="example-dropzone" ondragover="onDragOver(event);" ondrop="onDrop(event);">Drop
</div>
</div>
</div>
See this tutorial: https://www.digitalocean.com/community/tutorials/js-drag-and-drop-vanilla-js-de
its an image slider when I click the next I needs to change the image in the thumbnails also but its not working. also not showing main picture when I click in the the first picture and the second is working but third also not working...
thumbnail's are not change through next and previous...
in slider images are change through next and previous but the thumbnails are not change with image...
Code.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<style>
.newsslider {
width: 100%;
height: 800px;
background-color:#766582;
}
.text {
text-align: center;
font-size: 40px;
color: white;
margin-bottom: -101px;
}
.btn1,
.btn2 {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -30px;
padding: 16px;
color: #52492f;
font-weight: bold;
font-size: 20px;
border-radius: 0 3px 3px 0;
user-select: none;
}
.btn2 {
position: absolute;
right: 0;
border-radius: 3px 0 0 3px;
}
.btn1:hover,
.btn2:hover {
background-color: rgba(0, 0, 0, 0.8);
color: white;
}
.onebtn {}
.twobtn {}
.thumbs {
display: flex;
padding-top: 6%;
align-items: center;
justify-content: center;
list-style: none;
}
.thumbs li {
width: 12%;
padding: 10px;
margin: 1%;
}
.thumbs li img {
width: 100%;
}
.img12:hover {
box-shadow: 0 0 2px 1px rgba(0, 140, 186, 0.5);
}
</style>
</head>
<body>
<div class="newsslider">
<p class="text" id="demo"><img id="demo1" src="img5.png" width=30%; height=400px;> </p>
<div class="onebtn">
<button id="btn1" class="btn1" type="button" class="prev" onclick="prev()">PREV</button>
</div>
<div class="twobtn">
<button id="btn2" class="btn2" type="button" class="next" onclick="next()">NEXT</button>
</div>
<p id="newsArr1" class="text" style="font-size:40px; font-weight:bolder; color: #521d2c;">Hi,</p>
<ul class="thumbs">
<li class="img12" onclick="thumbchange(1)"><img src="img5.png" width=500%;></li>
<li class="img12" onclick="thumbchange(2)"><img src="img2.png"></li>
<li class="img12" onclick="thumbchange(3)"><img src="img4.png"></li>
</ul>
</div>
<script>
var newsArr = ['<img src="img5.png"width = 30%; height=400px;>',
'<img src="img2.png"width = 30%; height=400px; >',
'<img src="img4.png" width = 30%; height=400px;>'];
var newsArr1 = ["Hi",
"This is Urraan",
"Urraan is a digital gateway"];
var i = 0;
var x = document.getElementById("demo");
var y = document.getElementById("newsArr1");
// var timeoutId;
function next() {
// if (timeoutId) {
// clearTimeout(timeoutId);
// }
i++;
if (i < newsArr.length) {
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
} else {
i = 0;
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
}
// timeoutId = setTimeout(next, 2000);
}
function prev() {
i--;
if (i >= 0) {
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
} else {
i = newsArr.length - 1;
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
}
}
function thumbchange(num) {
var thumb = 'img' + num + '.png';
document.getElementById("demo1").src = thumb;
}
</script>
</body>
</html>
you problem solved ... please try it.
var newsArr = ['<img src="https://www.w3schools.com/bootstrap4/la.jpg"width = 100%; height=400px;>',
'<img src="https://www.w3schools.com/bootstrap4/chicago.jpg"width = 100%; height=400px; >',
'<img src="https://www.w3schools.com/bootstrap4/ny.jpg" width = 100%; height=400px;>'];
var newsArr1 = ["Hi",
"This is Urraan",
"Urraan is a digital gateway"];
var i = 0;
var x = document.getElementById("demo");
var y = document.getElementById("newsArr1");
// var timeoutId;
function next() {
// if (timeoutId) {
// clearTimeout(timeoutId);
// }
i++;
if (i < newsArr.length) {
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
} else {
i = 0;
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
}
// timeoutId = setTimeout(next, 2000);
setThumbnailFocus(i)
}
function prev() {
i--;
if (i >= 0) {
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
} else {
i = newsArr.length - 1;
x.innerHTML = newsArr[i];
y.innerHTML = newsArr1[i];
}
setThumbnailFocus(i)
}
function thumbchange(num) {
x.innerHTML = newsArr[num-1];
y.innerHTML = newsArr1[num-1];
setThumbnailFocus(num-1)
}
function setThumbnailFocus(num){
var elems = document.querySelectorAll(".thumbs .selected");
[].forEach.call(elems, function(el) {
el.classList.remove("selected");
});
document.getElementsByClassName("img12")[num].classList.add("selected");
}
.newsslider {
width: 100%;
height: 800px;
background-color:#766582;
}
.text {
text-align: center;
font-size: 40px;
color: white;
margin-bottom: -101px;
}
.btn1,
.btn2 {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -30px;
padding: 16px;
color: #52492f;
font-weight: bold;
font-size: 20px;
border-radius: 0 3px 3px 0;
user-select: none;
}
.btn2 {
position: absolute;
right: 0;
border-radius: 3px 0 0 3px;
}
.btn1:hover,
.btn2:hover {
background-color: rgba(0, 0, 0, 0.8);
color: white;
}
.onebtn {}
.twobtn {}
.thumbs {
display: flex;
padding-top: 6%;
align-items: center;
justify-content: center;
list-style: none;
}
.thumbs li {
width: 12%;
padding: 10px;
margin: 1%;
}
.thumbs li img {
width: 100%;
}
.img12:hover {
box-shadow: 0 0 2px 1px rgba(0, 140, 186, 0.5);
}
.selected{
border:solid 2px red
}
<div class="newsslider">
<p class="text" id="demo"><img id="demo1" src="https://www.w3schools.com/bootstrap4/la.jpg" width=100%; height=400px;> </p>
<div class="onebtn">
<button id="btn1" class="btn1" type="button" class="prev" onclick="prev()">PREV</button>
</div>
<div class="twobtn">
<button id="btn2" class="btn2" type="button" class="next" onclick="next()">NEXT</button>
</div>
<p id="newsArr1" class="text" style="font-size:40px; font-weight:bolder; color: #521d2c;">Hi,</p>
<ul class="thumbs">
<li class="img12 selected" onclick="thumbchange(1)"><img src="https://www.w3schools.com/bootstrap4/la.jpg" width=500%;></li>
<li class="img12" onclick="thumbchange(2)"><img src="https://www.w3schools.com/bootstrap4/chicago.jpg"></li>
<li class="img12" onclick="thumbchange(3)"><img src="https://www.w3schools.com/bootstrap4/ny.jpg"></li>
</ul>
</div>
The first issue I found is that you have this code:
<p class="text" id="demo"><img id="demo1" src="img5.png" width=30%; height=400px;> </p>
And here you didn't use part with setting id:
var newsArr = ['<img //here is no id// src="img5.png"width = 30%; height=400px;>',
'<img //here is no id// src="img2.png"width = 30%; height=400px; >',
'<img //here is no id// src="img4.png" width = 30%; height=400px;>'];
And when you are clicking on next and prev button, you are removing your id unconsciously, so your thumbchange() function stop working, because it is based on id.
I was looking to trigger different sections with a variable font based on my mouse movement.
For the first section, everything looks great, but when I tried to trigger the second section, it does not work as I expected since is connected to the first one I guess.
I would need to make the section working independently and in the correct way (to have an idea see section one how react in debug mode)
I was wondering what I have to modify in my Javascript code to make my snippet work with all the sections I want, working independently with their respective variable font interaction. Any ideas?
$('.square').on('mousemove', function(e) {
var x = e.pageX - $(this).offset().left;
var y = e.pageY;
var $tlSquare = $('.division--top.division--left');
var $trSquare = $('.division--top.division--right');
var $blSquare = $('.division--bottom.division--left');
var $brSquare = $('.division--bottom.division--right');
var squareWidth = $(this).width(),
squareHeight = $(this).height();
$tlSquare.width(x).height(y);
$trSquare.width(squareWidth - x).height(y);
$blSquare.width(x).height(squareHeight - y);
$brSquare.width(squareWidth - x).height(squareHeight - y);
stretchLetter(false);
});
stretchLetter(false);
$('.square').on('mouseleave', function() {
$('.division').width('50%').height('50%');
$('.letter').css('transform', '');
stretchLetter(false);
});
function stretchLetter(animation) {
$('.letter').each(function() {
var parentWidth = $(this).parent().width();
var parentHeight = $(this).parent().height();
var thisWidth = $(this).width();
var thisHeight = $(this).height();
var widthPercent = parentWidth / thisWidth;
var heightPercent = parentHeight / thisHeight;
var timing = animation == true ? .5 : 0;
TweenMax.to($(this), timing, {
scaleX: widthPercent,
scaleY: heightPercent
})
//$(this).css('transform', 'scalex('+ widthPercent +') scaley('+ heightPercent +')');
});
}
body,
html {
margin: 0;
padding: 0;
font-weight: bold;
font-family: helvetica;
}
section {
height: 200px;
background: blue;
color: white;
font-size: 28px;
}
.wrapper {
display: flex;
justify-content: center;
/*justify-content: flex-end;*/
width: 100%;
height: 100vh;
//background-color: blue;
overflow: hidden;
}
.square {
display: flex;
flex-wrap: wrap;
width: 100vh;
height: 100vh;
background-color: black;
}
.square-2 {
display: flex;
flex-wrap: wrap;
width: 100vh;
height: 100vh;
background-color: yellow;
}
.division {
//display: flex;
//align-items: center;
//justify-content: center;
width: 50%;
height: 50%;
//background-color: red;
//border: 1px solid white;
box-sizing: border-box;
}
.letter {
cursor: -webkit-grab;
cursor: grab;
}
.letter {
display: inline-block;
font-size: 50vh;
margin: 0;
padding: 0;
line-height: .8;
transform-origin: top left;
color: white;
}
/* .division:nth-child(1){
background-color: blue;
}
.division:nth-child(2){
background-color: red;
}
.division:nth-child(3){
background-color: green;
}
.division:nth-child(4){
background-color: orange;
} */
.circle {
width: 100%;
height: 100%;
border-radius: 50%;
border: 1px solid white;
background-color: blue;
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>SECTION-01</section>
<main>
<div class="wrapper">
<div class="square">
<div class="division division--top division--left">
<div class="letter">L</div>
</div>
<div class="division division--top division--right">
<div class="letter">A</div>
</div>
<div class="division division--bottom division--left">
<div class="letter">S</div>
</div>
<div class="division division--bottom division--right">
<div class="letter">T</div>
</div>
</div>
</main>
<section>SECTION-02</section>
<div class="wrapper">
<div class="square">
<div class="division division--top division--left">
<div class="letter">F</div>
</div>
<div class="division division--top division--right">
<div class="letter">A</div>
</div>
<div class="division division--bottom division--left">
<div class="letter">S</div>
</div>
<div class="division division--bottom division--right">
<div class="letter">T</div>
</div>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
https://jsfiddle.net/CAT999/ohaf61qp/5/
See working FIDDLE
You had to change the y variable because you were calculating with the offset top of the mouse position inn the document. This is always bigger than the element, so you have to extract the offset top of the element you were scrolling on, to get the right value.
var y = e.pageY - $(this).offset().top;
I've been chasing around this problem for hours, here's the code:
<!DOCTYPE html>
<html>
<head>
<style>
html, body{
height: 100%;
max-height: 100%;
overflow:hidden;
}
.controls{
display: table;
height: 10%;
margin-top: 1%;
width: 100%;
}
#w1 {
width:25%;
}
#can
float: left;
padding: 0;
margin: 0;
top: 0;
}
#canTwo{
float: left;
padding: 0;
margin: 0;
top: 0;
}
textarea {
outline: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-size: 1.25vw;
height: 100%;
width: 100%;
}
#w2{
width:50%;
}
#w3{
width:25%;
}
.controlbuttons {
display: table-cell;
height: 100%;
}
</style>
</head>
<body>
<div class="controls">
<div class="controlbuttons" id="w1"><canvas id = "can" width = "0" height = "0"></div>
<div class="controlbuttons" id="w2"><textarea rows="3" cols="50"></textarea></div>
<div class="controlbuttons" id="w3"><canvas id = "canTwo" width = "0" height = "0"></div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
fitToContainer();
});
var canvas = document.getElementById("can"),
ctx = canvas.getContext('2d'),
canvasTwo = document.getElementById("canTwo"),
ctxTwo = canvasTwo.getContext('2d');
function fitToContainer(){
var control = document.getElementsByClassName("controlbuttons")[0];
var h = control.clientHeight;
var w = control.clientWidth;
canvas.height = h;
canvas.width = w;
canvasTwo.height = h;
canvasTwo.width = w;
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 5000, 5000);
ctxTwo.fillStyle = "green";
ctxTwo.fillRect(0, 0, 5000, 5000);
}
</script>
</body>
</html>
jsfiddle:
https://jsfiddle.net/ca3uw837/
Basically I have one textarea and it's width takes 50% of the page and it is exactly in the middle, there are two
canvases to it's side which take 25% width.
I am trying to get them to align perfectly(same height, exactly one next to the other) but here is how it looks on my pc:
What am I supposed to do? use flexbox? I am not sure I know how to achieve it as canvases are very tricky with their sizing technique. Thank you so much for your time.
Apply flexbox to .controls to align the child elements. Also apply box-sizing: border-box to textbox as the default padding adds with the 100% height of the textbox. border-box will make the padding inclusive of height.
document.addEventListener("DOMContentLoaded", function(event) {
fitToContainer();
});
var canvas = document.getElementById("can"),
ctx = canvas.getContext('2d'),
canvasTwo = document.getElementById("canTwo"),
ctxTwo = canvasTwo.getContext('2d');
function fitToContainer() {
var control = document.getElementsByClassName("controlbuttons")[0];
var h = control.clientHeight;
var w = control.clientWidth;
canvas.height = h;
canvas.width = w;
canvasTwo.height = h;
canvasTwo.width = w;
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 5000, 5000);
ctxTwo.fillStyle = "green";
ctxTwo.fillRect(0, 0, 5000, 5000);
}
html,
body {
height: 100%;
max-height: 100%;
overflow: hidden;
}
.controls {
display: flex;
height: 10%;
margin-top: 1%;
width: 100%;
}
#w1 {
width: 25%;
}
#can float: left;
padding: 0;
margin: 0;
top: 0;
}
#canTwo {
float: left;
padding: 0;
margin: 0;
top: 0;
}
textarea {
outline: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-size: 1.25vw;
height: 100%;
width: 100%;
box-sizing: border-box;
}
#w2 {
width: 50%;
}
#w3 {
width: 25%;
}
.controlbuttons {
height: 100%;
}
<div class="controls">
<div class="controlbuttons" id="w1"><canvas id="can" width="0" height="0"></div>
<div class="controlbuttons" id="w2"><textarea rows="3" cols="50"></textarea></div>
<div class="controlbuttons" id="w3"><canvas id = "canTwo" width = "0" height = "0"></div>
</div>
To align table-cell items to the top you should use: vertical-align: top. Both canvas are missing height and width property, set them to 100%. Add box-sizing: border-box to the textarea:
box-sizing: border-box
The width and height properties (and min/max properties) includes
content, padding and border, but not the margin
So:
textarea {
/** ... rest of styles ...*/
margin: 0;
box-sizing: border-box;
float: left;
}
.controlbuttons { vertical-align: top; } /* Align items to the top */
.controlbuttons canvas { height: 100%; width: 100%; }
Demo: (Tested in firefox 53.0.2 & Chrome 56.0.2924.87)
document.addEventListener("DOMContentLoaded", function(event) {
fitToContainer();
});
var canvas = document.getElementById("can"),
ctx = canvas.getContext('2d'),
canvasTwo = document.getElementById("canTwo"),
ctxTwo = canvasTwo.getContext('2d');
function fitToContainer() {
var control = document.getElementsByClassName("controlbuttons")[0];
var h = control.clientHeight;
var w = control.clientWidth;
canvas.height = h;
canvas.width = w;
canvasTwo.height = h;
canvasTwo.width = w;
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 5000, 5000);
ctxTwo.fillStyle = "green";
ctxTwo.fillRect(0, 0, 5000, 5000);
}
html,
body {
height: 100%;
max-height: 100%;
overflow: hidden;
}
.controls {
display: table;
height: 10%;
margin-top: 1%;
width: 100%;
}
#w1 {
width: 25%;
}
textarea {
outline: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
font-size: 1.25vw;
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
float: left;
}
#w2 {
width: 50%;
}
#w3 {
width: 25%;
}
.controlbuttons {
display: table-cell;
height: 100%;
vertical-align: top;
}
.controlbuttons canvas {
float: left;
padding: 0;
margin: 0;
top: 0;
height: 100%;
width: 100%;
}
<!DOCTYPE html>
<html>
<body>
<div class="controls">
<div class="controlbuttons" id="w1">
<canvas id="can" width="0" height="0"></canvas>
</div>
<div class="controlbuttons" id="w2">
<textarea rows="3" cols="50"></textarea>
</div>
<div class="controlbuttons" id="w3">
<canvas id = "canTwo" width = "0" height = "0"></canvas>
</div>
</div>
</body>
</html>