Slider with teardrop label using MDL - javascript

I am currently building a form with Material Design Lite.
My form is similar to this one. A discrete slider, with a teardrop label, would then be the best solution for easily defining parts of an amount in my form.
But MDL doesn't include a slider with a teardrop label by default. Angular Material includes one, though.
How can I include a teardrop label similar to the one in the Material Design Guidelines ?

You can make a MDL continuous slider into a discrete slider by adding a step attribute. Ex. step="10".
As for the teardrop label, that's a bit harder. MDL doesn't have an built-in style for that so you'd need to add it yourself. The following should get you started.
Note: the calculation for the positioning (labelPosX) is a bit wonky and I'm sure a few minutes thinking about it would clean it up.
Demo
const demoInput = document.getElementById('demo');
const labelMaker = function (e) {
const input = e.target || e;
const label = input.parentElement.querySelectorAll('.label')[0] || document.createElement('div');
const labelInner = label.firstChild || document.createElement('div');
const parentWidth = input.parentElement.offsetWidth;
const inputWidth = input.offsetWidth ;
const labelOffset = (parentWidth - inputWidth) / 2;
const labelPosX = inputWidth * (input.value/100) + ((100 - input.value) * 14)/100;
label.classList.add('label');
if (input.value == 0) {
label.classList.add('zeroed');
} else {
label.classList.remove('zeroed');
}
labelInner.innerText = input.value;
label.appendChild(labelInner);
label.style.left = labelPosX + 'px';
input.parentElement.appendChild(label);
}
demoInput.addEventListener('input', labelMaker);
window.onload = function() {
labelMaker(demoInput)
};
body {
padding: 100px 0 0 0;
}
.label {
display: block;
position: absolute;
top: -55px;
width: 25px;
height: 25px;
border-radius: 0 50% 50% 50%;
background-color: rgb(63, 81, 181);
transform: rotate(-135deg);
margin-top: 20px;
}
.label div {
line-height: 25px;
color: #ffffff;
font-size: 10px;
font-weight: 300;
letter-spacing: 1px;
text-align: center;
transform: rotate(135deg);
}
.label.zeroed {
background-color: rgba(0, 0, 0, 0.3);
}
<script src="https://code.getmdl.io/1.3.0/material.min.js"></script>
<link href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css" rel="stylesheet" />
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="20" tabindex="0" step="10" id="demo">
</div>
</div>

Related

having trouble with multiple dragabblevanilla javascript modal boxes

so im making some vanilla js draggable modal boxes but i keep having trouble when it comes to the dragging.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
<title>Me website mate</title>
</head>
<body>
<!--------------------------------------------------------------------------------------->
<button id="buttonone" class="button">click me</button>
<div id="boxone" class="box">
<div id="headerone" class="header">header
<div class="box-buttons">
<div id="box-close-one" class="operation-button" style="background-color: rgb(207, 9, 33);">&times</div>
<div id="box-maximize" class="operation-button" style="background-color: rgb(248, 201, 27);">max</div>
<div id="box-minimize" class="operation-button" style="background-color: rgb(0, 104, 69);">min</div>
</div>
</div>
<div class="content">
content
</div>
<div class="resize"></div>
</div>
<!---------------------------------------------------------------------------------------->
<button id="buttontwo" class="button">click me</button>
<div id="boxtwo" class="box" style="left: 500px;">
<div id="headertwo" class="header">header
<div class="box-buttons">
<div id="box-close-two" class="operation-button" style="background-color: rgb(207, 9, 33);">&times</div>
<div id="box-maximize" class="operation-button" style="background-color: rgb(248, 201, 27);">max</div>
<div id="box-minimize" class="operation-button" style="background-color: rgb(0, 104, 69);">min</div>
</div>
</div>
<div class="content">
content
</div>
<div class="resize"></div>
</div>
<script src="javaScript/main.js"></script>
</body>
</html>
the html has 2 buttons and 2 modal boxes each button opening the assigned box, each box had a close button that hides said modal box
.box{
/*display: none;*/
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 12px;
background-color: #666;
border: 1px solid #000;
position: absolute;
height: 280px;
width: 400px;
margin: 2px;
position: absolute;
left: 0px;
z-index: 9;
}
.header{
position: relative;
height: 32px;
line-height: 32px;
font-size: 1.2em;
vertical-align: middle;
padding: 0 8px 0 8px;
white-space: normal;
overflow: hidden;
background: rgb(69, 161, 211);/*69, 161(golden ratio), 211(prime)*/
cursor: grab;
position: initial;
}
.box-buttons{
position: absolute;
display: flex;
flex-direction: row-reverse;
right: 0em;
top: 0em;
}
.operation-button{
height: 31px;
width: 31px;
border: 1px solid black;
text-align: center;
cursor: pointer;
}
.content{
position: absolute;
width: 400px;
height: 248px;
}
some styling
const boxOne = document.querySelector("#boxone");
boxOne.style.display = "none";
const boxTwo = document.querySelector("#boxtwo");
boxTwo.style.display = "none";
/////
const buttonOne = document.querySelector("#buttonone");
const closeOne = document.querySelector("#box-close-one");
const headOne = document.querySelector("#headerone");
buttonOne.addEventListener("click", function open(e){
openBox(boxOne);
});
closeOne.addEventListener("click", function close(e){
closeBox(boxOne);
});
headOne.addEventListener("mousedown",function grab(e){
mouseDown(boxOne, headOne,e);
});
/////
const buttonTwo = document.querySelector("#buttontwo");
const closeTwo = document.querySelector("#box-close-two");
const headTwo = document.querySelector("#headertwo");
buttonTwo.addEventListener("click",function open(e){
openBox(boxTwo);
});
closeTwo.addEventListener("click",function close(e){
closeBox(boxTwo);
});
function mouseDown(B,H,i){
var box = B;
var head = H;
head.style.cursor = "grabbing";
window.addEventListener("mousemove",drag);
window.addEventListener("mouseup",drop);
var windowHeight = window.innerHeight;
var windowWidth =window.innerWidth;
let previousX = i.clientX;
let previousY = i.clientY;
function drag(i){
let currentX = previousX - i.clientX;
let currentY = previousY - i.clientY;
const bounds = box.getBoundingClientRect();
console.log(bounds);
box.style.left = bounds.left - currentX + "px";
box.style.top = bounds.top - currentY + "px";
previousX = i.clientX;
previousY = i.clientY;
}
function drop(){
head.style.cursor = "grab";
window.removeEventListener("mousemove",drag);
window.removeEventListener("mouseup",drop);
}
}
function openBox(rect){
if (rect.style.display === "none") {
rect.style.display = "block";
}
console.log("open");
}
function closeBox(rectClose){
if(rectClose.style.display !== "none"){
rectClose.style.display = "none";
}
console.log("close");
}
it opens and closes well but it seems to be having a lot of trouble when i try to drag it. it always seems to go to the bottom right of the screen for some reason. Ive tried this project before but only with a single box, the code for the single box worked great and dragged perfectly fine but when ive tried to copy the same instructions , it fails. ik that it my code rn is inefficient but rn its just a prototype. Ive tried console.log to trouble shoot it but when i do the same to the previous project which worked fine, the output of the console looks pretty much the same. i dont know if im missing something bc i am a beginner, ive never taken a class on JS, so i dont really know what to look for or how to properly debug this. I would really appreciate the help and if possible, i would like to keep it in vanilla JS for the practice.
so after some experimenting, i boiled the answer down to the fact that the box moved 2 pixels to the right and 2 pixels down plus the movement of my mouse. I know this because I printed out the bounds variable to the console and moving my mouse only up (with a straightedge) and to the side. im still not sure what causes this however i just added a "-2" to the box.style.left and box.style.top to mitigate this problem so now the code is
box.style.left = (bounds.left - currentX) - 2 + "px";
box.style.top = (bounds.top - currentY) -2 + "px";
thank you to anybody that actually tired to figure it out and help me

Move text insertion point (caret) on click

To enhance UX by catching miss-clicks in my form, I'm using the following code on a bounding box around each text field:
focusMethod = function getFocus() {
document.getElementById("myTextField").focus();
}
This works well in setting focus on the closest text field to where the user has clicked, even if not directly on the text field itself. However, the text insertion point (caret) is always automatically placed at the left side of the input, rather than the closest x point of the input.
Using vanilla JS, how can I take this one step further and find and move the text insertion point (caret) to the closest possible placement to where the user has clicked (assuming the field has text in it)?
Images:
what I have now | what I want to happen
You can overlay a sort of hacky text input that's larger, then use text positioning from it for the true input.
Otherwise, it's really, really difficult to figure out character positions... fonts are weird, and there's no way I know of in js to figure out exactly where they'll be.
const byId = (id) => document.getElementById(id);
const on = (el, event, cb) => el.addEventListener(event, cb);
const textEl = byId("Text");
const hackEl = byId("Hack");
on(textEl, "input", () => hackEl.value = textEl.value);
on(hackEl, "click", () => {
const charFocusPos = hackEl.selectionStart;
textEl.focus();
textEl.selectionStart = textEl.selectionEnd = charFocusPos;
});
#Container {
position: relative;
display: inline-block;
}
#Hack {
transform: translate(-50%, -50%) scaleY(5);
position: absolute;
top: 50%;
left: 50%;
width: 100%;
opacity: 0;
padding-top: 0px;
padding-bottom: 0px;
height: 16px;
border: none;
outline: none;
}
#Hack.showOnHover:hover {
opacity: 0.1;
}
#Hack, #Text {
font-size: 16px;
font-family: arial;
}
<div id="Container">
<input type="textbox" id="Text">
<input type="textbox" id="Hack"></div>
</div>
<button onClick="byId('Hack').classList.toggle('showOnHover')">Toggle Hack Layer</div>
You can achieve this. I have cooked up something that can be used as a starting point:
<div id="container">
<input type="text" id="input">
<br>
<br>
</div>
<script type="text/javascript">
var testInput = document.getElementById("input");
var testContainer = document.getElementById("container");
document.getElementById("container").addEventListener("click", function(event) {
testInput.focus();
var padding = 0;
console.log(event.clientX);
console.log(testInput.getBoundingClientRect().left);
console.log(testInput.getBoundingClientRect().right);
if (event.clientX > testInput.getBoundingClientRect().right) padding = (testInput.getBoundingClientRect().right * 0.8);
else if (event.clientX > testInput.getBoundingClientRect().left) padding = (event.clientX - testInput.getBoundingClientRect().left);
testInput.style["padding-left"] = padding + "px";
});
</script>
and
#container {
width: 90%;
margin: auto;
background-color: gray;
}
#input {
width: 80%;
margin-top: 100px;
margin-left: 10%;
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
}
See: https://jsfiddle.net/mLqj17xe/1/
The idea is to find out where should the cursor be and use that as padding-left.

dynamically update css content using javascript

There is a need to update css to dynamic value and I am not sure what's the best approach to it.
<div id="app" style="zoom: 0.XX;">
...
</div>
The zoom level will trigger based on window resize and the app will zoom according. I loaded this app into cordova and have it run within iPAD, then I realize the font-size needs to be adjusted to the same as zoom level using "-webkit-text-size-adjust" in order for it to not break the design layout.
My challenge is to set the css dynamically like this:
#app * {
-webkit-text-size-adjust : nn%
}
Where nn is the zoom X 100 + '%'
I have tried:
1) Set the style on the app div, but this doesn't help to apply to inner elements
<div id="app" style="zoom: 0.XX; -webkit-text-size-adjust: XX%">
2) Use javascript to set to all inner nodes, but not only I think this is less efficient, but it won't get trigger if my window doesn't resize, that means if I navigate to other pages, this logic won't get called.
REF: https://stackoverflow.com/questions/25305719/change-css-for-all-elements-from-js
let textSizeAdjust = function(zoom) {
let i,
tags = document.getElementById("app").getElementsByTagName("*"),
total = tags.length;
for ( i = 0; i < total; i++ ) {
tags[i].style.webkitTextSizeAdjust = (zoom * 100) + '%';
}
}
3) I tried using javascript, and most likely they are technically incorrect because querySelector return null.
document.querySelector('#app *').style.webkitTextSizeAdjust = zoom *100 + '%';
document.querySelector('#app').querySelector('*').style.webkitTextSizeAdjust = zoom * 100 + "%";
Ultimate, I believe I need to dynamically create the css, for the browser to apply this setting to the DOM:
#app * {
-webkit-text-size-adjust: nn
}
Please let me know if this is the right, or how to use javascript to create the above css and change the value dynamically?
CSS Variables
Requirements
HTML
Each form control that has numerical data should have:
value={a default, don't leave it blank}
class='num'
data-unit={unit of measurement or a single space}
The select/option tag should have the selected attribute
CSS
CSS Variable Signature: propertyName: var(--propertyValue)
// Declare CSS Variables at the top of a stylesheet
:root {
--mx0: 50px;
--my0: 50px;
--rz0: 1.0;
--zm0: 1.0;
--sp0: 360deg;
}
JavaScript
There's step by step details commented in the JavaScript Demo. Here's the most important statement in the code:
CSSStyleDeclaration CSS Variable
🢃 🢃
`ele.style.setProperty(`--${node.id}`,
${node.valueAsNumber}${node.dataset.unit})
🢁 🢁
HTMLInputElement DataSet API
Demo 1
// Reference form#UI
var ui = document.forms.UI;
// Register form#UI to change event
ui.addEventListener('change', setCSS);
// Callback passes Event Object
function setCSS(e) {
// Collect all form controls of form#UI into a NodeList
var fx = ui.elements;
// Reference select#pk0
var pk0 = fx.pk0;
// Get select#pk0 value
var pick = pk0.options[pk0.selectedIndex].value
// if the changed element has class .num...
if (e.target.className === 'num') {
// Reference Event Target
var tgt = e.target;
// Then reference is by its #id
var node = document.getElementById(tgt.id);
// DOM Object to reference either html, square, or circle
var ele;
/* Determine which tag to test on: html (affects everything),
|| #sQ<uare> and #ciR<cle> shapes.
*/
switch (pick) {
case "rT":
ele = document.documentElement;
break;
case "sQ":
ele = document.getElementById('sQ');
break;
case "cR":
ele = document.getElementById('cR');
break;
default:
break;
}
/* Sets a target element's Transform:
|| translateXY, scale, and rotate
*/
ele.style.setProperty(`--${node.id}`, `${node.valueAsNumber}${node.dataset.unit}`);
}
}
/* Declare CSS Variables on the :root selector at the top of sheet
All CSSVar must be prefixed with 2 dashes: --
*/
:root {
--mx0: 50px;
--my0: 50px;
--rz0: 1.0;
--sp0: 360deg;
}
.set {
border: 3px ridge grey;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
padding: 5px;
}
/* The var() function's signature is:
propertyName: var(--propertyValue)
*/
#sQ {
position: relative;
background: rgba(0, 100, 200, 0.3);
width: 50px;
height: 50px;
transform: translateX(var(--mx0)) translateY(var(--my0)) scale(var(--rz0)) rotate(var(--sp0));
border: 3px ridge grey;
z-index: 1;
transition: all 1s ease;
}
#cR {
position: relative;
background: rgba(200, 100, 0, 0.3);
width: 50px;
height: 50px;
transform: translateX(var(--mx0)) translateY(var(--my0)) scale(var(--rz0)) rotate(var(--sp0));
border: 3px ridge grey;
border-radius: 50%;
transition: all 1s ease;
}
#sQ::before {
content: '\1f504';
text-align: center;
font-size: 2.25rem;
transform: translate(1px, -8px)
}
#cR::after {
content: '\1f3b1';
text-align: center;
font-size: 2.25rem;
}
input,
select {
display: inline-block;
width: 6ch;
font: inherit;
text-align: right;
line-height: 1.1;
padding: 1px 2px;
}
select {
width: 9ch
}
.extension {
overflow-y: scroll;
overflow-x: auto;
min-height: 90vh;
}
/* For debugging on Stack Snippets */
/*.as-console-wrapper {
width: 25%;
margin-left: 75%;
min-height: 85vh;
}*/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style></style>
</head>
<body>
<!--
HTML Requirements
Each form control that has numerical data should have:
1. value={a default, don't leave it blank}
2. class='num'
3. data-unit={unit of measurement or a single space}
4. The select/option tag should have the selected attribute
-->
<form id='UI'>
<section class='set'>
<label>X: </label>
<input id='mx0' class='num' type='number' min='-350' max='350' value='50' step='10' data-unit='px'>
<label>Y: </label>
<input id='my0' class='num' type='number' min='-350' max='350' value='50' step='10' data-unit='px'>
<label>Size: </label>
<input id='rz0' class='num' type='number' min='0' max='5' value='1' step='0.1' data-unit=' '>
<label>Spin: </label>
<input id='sp0' class='num' type='number' min='0' max='1440' value='360' step='180' data-unit='deg'>
<label>Pick: </label>
<select id='pk0' class='num'>
<option value='rT' selected>Root</option>
<option value='sQ'>Square</option>
<option value='cR'>Circle</option>
</select>
</section>
</form>
<section class='set extension'>
<div id='sQ' class='test shape' width="50" height="50"></div>
<div id='cR' class='test shape' width="50" height="50"></div>
</section>
</body>
</html>
Update
This update is specifically for OP, so this may be of help or not for other users.
Deno 2
:root {
--opc: 0;
--zoom: 1;
}
.fc {
display: inline-block;
width: 18ch;
margin:0 0 10px 0
}
#app * {
opacity: var(--opc);
transform: scale(var(--zoom));
}
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
</head>
<body>
<form id='app' action='https://httpbin.org/post' method='post' target='view'>
<fieldset class='sec'>
<legend>App of Mystery</legend>
<input id='A0' name='A0' class='fc' type='text' placeholder='User Name'>
<input id='A1' name='A1' class='fc' type='password' placeholder='Password'>
<input type='submit'>
<input type='reset'>
<input id='zBtn' type='button' value='Zoom'>
<iframe name='view' frameborder='1' width='100%'></iframe>
</fieldset>
</form>
<script>
var node = document.querySelector('#app *');
var zBtn = document.getElementById('zBtn');
var flag = false;
document.addEventListener('DOMContentLoaded', function(e) {
node.style.setProperty("--opc", "0.5");
});
document.addEventListener('click', function(e) {
node.style.setProperty("--opc", "1");
});
zBtn.addEventListener('click', function(e) {
if (flag) {
flag = false;
node.style.setProperty("--zoom", "1");
} else {
flag = true;
node.style.setProperty("--zoom", "1.25");
}
});
</script>
</body>
</html>
I don't have much knowledge about -webkit-text-size-adjust
However, this should work for creating a dynamic stylesheet and inserting it:
I have added code to dynamically update it as well
const form = document.getElementById('colorChooser');
form.addEventListener('submit', (e) => {
e.preventDefault();
color = document.getElementById('colorInput').value;
const style = document.getElementById('colorStyle');
style.innerHTML = `#app * {
background-color: ${color};
}`;
});
const style = document.createElement('style');
style.id = 'colorStyle';
style.type = 'text/css';
style.innerHTML = `#app * {
background-color: red;
}`;
document.head.appendChild(style);
#app {
margin-bottom: 10px;
}
#inner {
width: 50px;
height: 50px;
background-color: black;
}
<div id="app">
<div id="inner"></div>
</div>
<form id="colorChooser">
<input id="colorInput" type="text" placeholder="red" />
<input type="submit" value="Update color"/>
</form>

How to build inline rating using JavaScript or jQuery?

I need to build inline rating for tv shows for example. Max rating I put in jQuery code, current rating in html document. This is how I found the way to do this.
$(document).ready(function() {
var maxRating = $('.rate-line').width();
var maxRating = 6; //max-rating
var currentRatingFirst = $('.first-rd').text();
var calc = (currentRatingFirst / maxRating) * 100 + "%";
$('.first-rl span.fill').width(calc);
});
.rate-line {
border: 1px solid #bababa;
background: #fff;
position: relative;
vertical-align: middle;
margin-right: 1.25em;
overflow: hidden;
width: 50%;
height: 20px;
}
.rate-line, .rate-data, .fill {
display:inline-block;
}
.fill {
background: #ff6292;
height: 22px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">4.56</span>
</div>
But, I need to create 6 rating lines for this month, then 6 for next and so on. And every time I must give new unique classes to make it work. And code becomes huge. And one more, all this rating nested to bootstrap carousel items and when I duplicate it nothing works .I'm not good in JavaScript at all and I'm asking your help. Would you please tell me how to make it work correctly and make it easier?
In this case it makes sense to create basin custom plugin, so you can easily reuse it without duplicating code.
Here is a very basic example of how you can extend jQuery prototype with a new method:
$.fn.rating = function(options) {
return this.each(function() {
var maxRating = $(this).find('.rate-line').width();
var maxRating = 6;
var currentRatingFirst = $(this).find('.first-rd').text();
var calc = (currentRatingFirst / maxRating) * 100 + "%";
$(this).find('.first-rl span.fill').width(calc);
});
};
$(document).ready(function () {
$('.rating').rating();
});
.rate-line {
border: 1px solid #bababa;
background: #fff;
position: relative;
vertical-align: middle;
margin-right: 1.25em;
overflow: hidden;
width: 50%;
height: 20px;
}
.rate-line, .rate-data, .fill {
display:inline-block;
}
.fill {
background: #ff6292;
height: 22px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rating">
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">4.56</span>
</div>
<div class="rating">
<span class="rate-line first-rl">
<span class="fill"></span>
</span>
<span class="rate-data first-rd">3.21</span>
</div>

Progress bar with slide ability

I am new to JavaScript/CSS (basically the whole world of web dev) and I am really struggling to create the following widget. I created a picture of what I want to make to make it more clear.
The Play/Pause and Stop button are ready. Loop checkbox is no problem. But the progress bar is painful. The two markers are supposed to mark the point from where the file would start playing and where it would stop. The progress bar is also supposed to be click-able, so if I want to access a certain point in time, then its possible.
What I tried so far
jQuery UI slider: For a sliding progress bar and use that draggable slider to access a certain point in audio file. Works fine. But no markers and looks really ugly. Don't how to change it.
<progress> tag: not very flexible. Marker? Clicking?
<div> tag: there seems to be no way to get the point where I clicked.
So, what do you guys recommend? How should I proceed?
Canvas Alternative
You might want to use a canvas and draw your own progress bar element within it.
Here are some canvas progress bar tutorials:
How to create a progress bar with HTML5
A progress bar using HTML5 canvas
Doing it with <progress>
To access the clicked position within a DOMElement, you can proceed with the click event's properties: clientX and clientY (MDN Source), like so:
HTML
<div class="marker" id="StartMarker">^</div>
<div class="marker" id="StopMarker">^</div>
<progress id="progress" value="0" min="0" max="100">0%</progress>
<form id="choice">
<button id="marker1">Beginning marker</button>
<button id="marker2">Ending marker</button>
<input type="hidden" id="markerValue" value="0" />
</form>
JavaScript (not optimized)
document.getElementById('progress').onclick = function (event, element) {
/* Math.floor((event.offsetX / this.offsetWidth) * 100) */
var newProgress = event.offsetX;
document.getElementById('choice').style.display = "block";
document.getElementById('markerValue').setAttribute('value', newProgress);
document.getElementById('marker1').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
var marker = startMarker;
marker.style.display = "block";
startMarker.style.display = "block";
startMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
startMarker.style.left = newProgress + "px";
};
document.getElementById('marker2').onclick = function (event) {
event.preventDefault();
var newProgress = document.getElementById('markerValue').value;
var progressBar = document.getElementById('progress');
var startMarker = document.getElementById('StartMarker');
var stopMarker = document.getElementById('StopMarker');
stopMarker.style.display = "block";
stopMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
stopMarker.style.left = newProgress + "px";
};
};
CSS
.marker {
position:absolute;
top:24px;
left:9px;
display:none;
z-index:8;
font-weight:bold;
text-align:center;
}
#StartMarker {
color: #CF0;
}
#StopMarker {
color:#F00;
}
#choice {
display:none;
}
progress {
display: inline-block;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 300px;
height: 20px;
padding: 3px 3px 2px 3px;
background: #333;
background: -webkit-linear-gradient(#2d2d2d, #444);
background: -moz-linear-gradient(#2d2d2d, #444);
background: -o-linear-gradient(#2d2d2d, #444);
background: linear-gradient(#2d2d2d, #444);
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 15px;
box-shadow: 0 1px 0 rgba(255, 255, 255, .2);
}
Live Demo
Using simple blocks for that is possible. Your layout would look like this (simplified):
HTML
<div class="progressbar">
<div class="bar">
<div class="progress" style="width: 30%;">
</div>
</div>
<div class="markers">
<div class="right" style="width: 70%;">
<div class="marker">
</div>
<div class="left" style="width: 20%;">
<div class="marker">
</div>
</div>
</div>
</div>
</div>
SCSS
.progressbar {
width: 20em;
background: grey;
.bar {
height: 2em;
.progress {
background: blue;
height: 100%;
}
}
.markers {
height: 1em;
background: white;
.right {
height: 100%;
background: red;
.marker {
width: 1em;
height: 100%;
background: green;
position: relative;
float: right;
}
.left {
background: white;
height: 100%;
}
}
}
}
The operations can be quite difficult
jQuery
$('.bar').click(function(e){
$(this).find('.progress').css('width', (e.offsetX / this.offsetWidth)*100+'%');
});
will set the Progressbar properly on clicks.
For the markers though you will need mousedown, mousemove, mouseleave events, since you got 2 of them.
Example
http://jsfiddle.net/JXauW/

Categories

Resources