"Top" style not calculating correctly from Javascript - javascript

Okay, starting over as I'm new at all of this and, as Sebastian points out, the problem is likely elsewhere.
This is a combination lock which was created by Derek Hill. I've reformatted it by cutting its size in half. In doing so, the size of the dial after spinning doesn't work out right -- when you spin the numbers, you can see that the height of the numbers begins dropping and is no longer vertically centered. It creeps down by about 0.5px each time.
I first notice the problem at the variable "temporTopEarlier". I cannot understand why the "top" for the dial is 0.5px more than it should be (-157 instead of -157.5). I think this is causing my problems. I expected a truncation of decimals, but I don't see where that would happen.
I'm new at this, so apologies for the many poor elements to the code, format, and question. Thanks!
<html lang="en">
<head>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<style>
#lock-plate{
padding: 15px 0;
border: 0.5px solid #cfd3d6;
background: #ccc;
text-align: center;
width: 243px;
background: -webkit-linear-gradient(top, #eee 0%,#949ba0 100%);
background: linear-gradient(to bottom, #eee 0%,#949ba0 100%);
border-radius: 2px;
margin: 10px auto;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.6);
position: absolute;
top: 6%;
left: 43%;
transform: translate(-50%, -50%);
}
#lock-wrapper{
width: 220px;
padding: 0 10px 0 4px;
border-radius: 3.5px;
height: 60px;
border: .5px solid rgba(255, 255, 255, 0.6);
box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.9);
background: -webkit-linear-gradient(top, #c4c4c4 0%,#676767 100%);
background: linear-gradient(to bottom, #c4c4c4 0%,#676767 100%);
overflow: hidden;
margin: 0 auto;
}
.lock-dial{
height: 60px;
width: 34px;
margin-left: 5.5px;
background: -webkit-linear-gradient(top, #8c9093 0%,#b6babd 9%,#ccd2d6 18%,#ffffff 55%,#ccd2d6 82%,#b6babd 91%,#8c9093 100%);
background: linear-gradient(to bottom, #8c9093 0%,#b6babd 9%,#ccd2d6 18%,#ffffff 55%,#ccd2d6 82%,#b6babd 91%,#8c9093 100%);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
float: left;
position: relative;
cursor: move;
}
#lock-wrapper .lock-dial ul{
margin: 0;
padding: 0;
text-align: center;
list-style: none;
font-size: 26.5px;
line-height: 35px;
color: #414f6b;
text-shadow: 0 -1px 0 #212c42;
transition: box-shadow .45s linear, color .25s linear;
-webkit-transition: box-shadow .45s linear, color .25s linear;
}
</style>
</head>
<body style="background-color: #012443">
<div id="lock-plate">
<span></span><span></span><span></span><span></span>
<div id="lock-wrapper">
<!-- <div class="welcome-message">WELCOME!</div> -->
<div class="lock-dial" id="dial-one"><ul data-combo-num="0"><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>0</li><li>1</li><li>2</li><li>3</li><li>4</li></ul></div>
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js" integrity="sha256-hlKLmzaRlE8SCJC1Kw8zoUbU8BxA+8kR3gseuKfMjxA=" crossorigin="anonymous"></script>
<script>
$(function(){
var comboArray = [0, 0, 0, 0, 0];
var combination = [4, 3, 9, 2, 0];
var gridIncrement = $( ".lock-dial ul" ).css('line-height').replace('px', '')/2; // this is correct, 17.5
var numNums = $( ".lock-dial:eq(0) ul li" ).length; // 10 numbers
var halfHeight = gridIncrement*numNums; // this is correct, 175
var initTop = -(halfHeight-gridIncrement); //this is correct, -157.5
$( ".lock-dial ul" ).css('top', initTop); // this is correct -157.5
$( ".lock-dial ul" ).draggable({
grid: [ 0, gridIncrement ],
axis: 'y',
drag: function(){
var dragDir = $(this).css('top').replace('px', '') < initTop ? "up" : "down";
if(dragDir == "up"){
var curNum = parseFloat($(this).find('li:last-child').text()) + 1;
if(curNum < 10){
$(this).append('<li>'+curNum+'</li>');
}else{
$(this).append('<li>0</li>');
};
}else{
var curNum = parseFloat($(this).find('li:first-child').text()) - 1;
var thisTop = parseFloat($(this).css('margin-top')); //seems right, starts at 0 and goes down by 35s
$(this).css({
marginTop: thisTop-(gridIncrement*2)
});
if(curNum > -1){
$(this).prepend('<li>'+curNum+'</li>');
}else{
$(this).prepend('<li>9</li>');
};
};
var temporTopEarlier = parseFloat($(this).css('top')); // this is wrong -157, should be -157.5
console.log("tempor top earlier " + temporTopEarlier);
},
stop: function(){
//MATHS
var halfHeight = 175;
var initTop = -157.5;
var negOrPos = $(this).css('margin-top').replace('px', '') > 0 ? 1 : -1;
var tempor_top = parseFloat($(this).css('top')); // this is wrong -174.5, should be -175
console.log("tempor_top " + tempor_top);
console.log(this);
var thisTopTotal = parseFloat($(this).css('top')) + Math.abs(initTop); // this first part is wrong, -17 instead of -17.5
var marginMinified = parseFloat(Math.abs($(this).css('margin-top').replace('px', ''))) - thisTopTotal;
var numIncs = Math.floor(marginMinified/(halfHeight*2));
var totalDif = numIncs*(halfHeight*2);
var topTen = (marginMinified - totalDif)*negOrPos;
var activeIndex = Math.abs(topTen/(gridIncrement*2)) + (halfHeight/(gridIncrement*2));
console.log("halfHeight " + halfHeight);
console.log("initTop " + initTop);
console.log("thisTopTotal " + thisTopTotal);
console.log("marginMinified " + marginMinified);
console.log("numIncs " + numIncs);
console.log("topTen " + topTen);
console.log("totalDif " + totalDif);
console.log("activeIndex " + activeIndex); // this should be a number in 0.5 increments and it's not
$(this).attr("data-combo-num", $(this).find('li').eq(activeIndex).text()).css({
top: -157.5,
marginTop: topTen
}).find('li').slice(20).remove();
for(var i=0; i<$( ".lock-dial ul" ).length; i++){
comboArray[i] = $( ".lock-dial ul:eq("+i+")" ).attr("data-combo-num");
}
}
});
})
</script>

Related

Put a button in certain spot of page?

i am fairly new to coding and i got this typing script online and then created a button, the button links to a different page that I haven't created yet. The issue i am facing is that i cant get the button to stay in one place while the typing script is running, it moves around, is there a way i can put it in a fixed position maybe by the bottom left of the screen. my code is bellow, Thanks!
var TxtType = function(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtType.prototype.tick = function() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';
var that = this;
var delta = 200 - Math.random() * 100;
if (this.isDeleting) {
delta /= 3;
}
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 5000;
}
setTimeout(function() {
that.tick();
}, delta);
};
window.onload = function() {
var elements = document.getElementsByClassName('typewrite');
for (var i = 0; i < elements.length; i++) {
var toRotate = elements[i].getAttribute('data-type');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtType(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".typewrite > .wrap { border-right: 0.08em solid #fff}";
document.body.appendChild(css);
};
.button {
position: relative;
left: 20%;
right: 20%;
bottom: 5%;
top: 60%;
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 24px 80px;
border: 1px solid #a12727;
border-radius: 98px;
background: #bd4aff;
background: -webkit-gradient(linear, left top, left bottom, from(#bd4aff), to(#992727));
background: -moz-linear-gradient(top, #bd4aff, #992727);
background: linear-gradient(to bottom, #bd4aff, #992727);
-webkit-box-shadow: #ff5959 0px 0px 40px 0px;
-moz-box-shadow: #ff5959 0px 0px 40px 0px;
box-shadow: #ff5959 0px 0px 40px 0px;
text-shadow: #591717 1px 1px 0px;
font: normal normal bold 37px arial;
color: #ffffff;
text-decoration: none;
}
.button:hover,
.button:focus {
background: #e359ff;
background: -webkit-gradient(linear, left top, left bottom, from(#e359ff), to(#b62f2f));
background: -moz-linear-gradient(top, #e359ff, #b62f2f);
background: linear-gradient(to bottom, #e359ff, #b62f2f);
color: #ffffff;
text-decoration: none;
}
.button:active {
background: #712c99;
background: -webkit-gradient(linear, left top, left bottom, from(#712c99), to(#982727));
background: -moz-linear-gradient(top, #712c99, #982727);
background: linear-gradient(to bottom, #712c99, #982727);
}
.button:after {
content: "\0000a0";
display: inline-block;
height: 24px;
width: 24px;
line-height: 24px;
margin: 0 -4px -6px 4px;
position: relative;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABBUlEQVRIibXVMUrEQBQG4I9FrMXKUjyBhVjZeAULD7F2VoLHELEQKzsvINZWgldwFQutLCwWRFhisQ6Mw2Yzk4mvfC+8L/OTIfytMd6x65/qDA0+sDPEwlFLfx13QyBtQIxUxbUMCMitipN0AQHpHVcOECPFceUCASmOqwQISFFcpUCMZMXVBwhIVlx9gYB0xlUDxEhrXLVAQFrjGgIIyMWiwUqPZd84xVfSfxwKWMUrbnIezonoBW9J7yj3bbqACfZxnvT3sJ2LxBX+aA2esPXb38A0mjW4rAGesZnMrhNgirVS4BD3C5Yzv0yzBDkuBZbVCA/R8hlOhgTgAJ+4Mr+5nV/hD3mmNbSMQ+JfAAAAAElFTkSuQmCC") no-repeat left center transparent;
background-size: 100% 100%;
}
<!doctype html>
<html>
<head>
<style>
body {
background-color: #ce3635;
text-align: center;
color: #fff;
padding-top: 10em;
}
* {
color: #fff;
text-decoration: none;
}
</style>
<script src="js/script.js">
</script>
</head>
<body>
<h1>
<a href="" class="typewrite" data-period="1000" data-type='[ "Hi, Welcome to DShroff.com", "A Website created entirely from scratch by me.", "Click the button below to go to games or wait here to be redirected to home."]'>
<span class="wrap"></span>
</a>
<a class="button" style="vertical-align:middle;margin:50px 0px" href="https://games.dshroff.com">Click to go to Games</a>
</a>
</a>
</h1>
You can just change the position: relative; to position: absolute; of button . Button will get out of flow from document and will appear below the text
Did you try using position:fixed?
https://www.w3schools.com/css/css_positioning.asp
And then manipulate top and left.
Ah, maybe more important, put the button inside div, and style the div.

Adding Custom Number Scales to the range slider

Requirement:
Needed to add custom scale numbers to the range slider from the Rangeslider.js plugin, so that whenever it slides over the horizontal line it needs to display the selected number range from the console
Actual Results:
Whenever I tried to add custom numbers the whole design including marker gets ruined. Here is the below codes of the snippet which needs to add custom number scales
Code I:
init(1, 10);
function init(min, max) {
$("#io").append($("<div style='text-align:center;'><div><input type='range' id='slider' min='" + min + "' max='" + max + "' step='1' value='3' data-rangeslider><output id='val'></output></div></div>"));
$('head').append('<link href="https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.2/rangeslider.css" rel="stylesheet" type="text/css">');
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.2/rangeslider.js")
.done(function(script, textStatus) {
console.log(textStatus);
//Preform here
initRangeSlider($("#slider"));
});
}
function initRangeSlider(ele) {
ele.rangeslider({
// Deactivate the feature detection
polyfill: false,
// Callback function
onInit: function() {
//valueOutput(this.$element[0]);
},
// Callback function
onSlide: function(position, value) {
console.log('onSlide');
console.log('position: ' + position, 'value: ' + value);
},
// Callback function
onSlideEnd: function(position, value) {
console.log('onSlideEnd');
console.log('position: ' + position, 'value: ' + value);
}
});
}
.rangeslider--horizontal {
height: 6px !important;
width: 66% !important;
}
.rangeslider__handle {
background: white;
background-image: none;
background-size: auto;
border: 1px solid #ccc;
cursor: pointer;
display: inline-block;
width: 24px !important;
height: 25px !important;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<b>Range Slider</b><br/>
<div id='io'></div><br/><br/>
Code II:
Here the below code of snippets doesn't seem to fit for my project. This was my actual result when I tried to integrate. So I need to modify the above code I with the below code II snippets
var $r = $('input[type="range"]');
var $ruler = $('<div class="rangeslider__ruler" />');
// Initialize
$r.rangeslider({
polyfill: false,
onInit: function() {
$ruler[0].innerHTML = getRulerRange(this.min, this.max, this.step);
this.$range.prepend($ruler);
}
});
function getRulerRange(min, max, step) {
var range = '';
var i = 0;
while (i <= max) {
range += i + ' ';
i = i + step;
}
return range;
}
.rangeslider,
input[type='range'] {
max-width: 400px;
height: 6px !important;
width: 66% !important;
float: center !important;
}
.rangeslider__ruler {
cursor: pointer;
font-size: .7em;
margin: 20px 3px 0 3px;
position: relative;
top: 100%;
text-align: justify;
}
// Workaround to justify only one-line.
// Extra element to force a new line.
.rangeslider__ruler:after {
content: "";
display: inline-block;
width: 100%;
}
.rangeslider__handle {
background: white;
background-image: none;
background-size: auto;
border: 1px solid #ccc;
cursor: pointer;
display: inline-block;
width: 24px !important;
height: 25px !important;
position: absolute;
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4xIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(0, 0, 0, 0.1)));
background-image: -moz-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
background-image: linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));
-moz-box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.2/rangeslider.min.css" integrity="sha256-F8gzbY2A1VTf49iOrc8Lst/UvcUtoFr3myix0WMiNqA=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/rangeslider.js/2.3.2/rangeslider.min.js" integrity="sha256-vFhEtGnaQ2xB+yjBTSXxssthNcfdbzu+lmLYhCdp2Cc=" crossorigin="anonymous"></script>
<!--
rangeslider.js example
https://github.com/andreruffert/rangeslider.js
by André Ruffert - #andreruffert
-->
<br/>
<input type="range" min="0" max="4" step="0.5">
Here is a resulting snapshot showed after integrating the code II to my project
Expected Result:
Code I needs to be integrated/modified taking the code from the Code II snippets
OR
Apart from rangeslider.js plugin if in case, if there are any other procedures needs to be followed.

Images showing outside of div with overflow:hidden

I am trying to create a side scrolling roulette-type animation. My roll() function randomly generates a list of images beforehand, and then will scroll through them.
So that the images outside of my div aren't visible, I tried setting overflow:hidden, however, all images are still visible, even outside the div.
My code:
function roll() {
var tile_src = ["http://i.imgur.com/XUp8Y4r.jpg", "http://i.imgur.com/Q3suBFZ.jpg"]
var roulette = document.getElementById("roulette");
var tiles = []
for (var i = 0; i < 64; i++) {
tile = document.createElement("IMG");
tile.id = "tile"
tile.style.position = "fixed"
tile.style.zIndex = "-1";
tile.src = tile_src[Math.floor((Math.random() * 2))]
tile.style.left = $(window).innerWidth() / 2 - 64 + i * 136 + 'px';
tile.style.top = '16px'
tiles.push(tile)
}
for (var i = 0; i < tiles.length; i++) {
roulette.appendChild(tiles[i])
}
}
function place_objects() {
var ticker = document.getElementById("ticker")
ticker.style.position = "fixed"
ticker.style.left = $(window).innerWidth() / 2 - 16 + 'px'
ticker.style.top = '8px'
var roll = document.getElementById("roll")
roll.style.position = "fixed"
roll.style.left = $(window).innerWidth() / 2 - $("#roll").outerWidth() / 2 + 'px'
roll.style.top = $("#ticker").height() + 16 + 'px'
var roulette = document.getElementById("roulette")
roulette.style.position = "fixed"
roulette.style.left = $(window).innerWidth() / 2 - $("#roulette").outerWidth() / 2 + 'px'
roulette.style.top = '6px'
roulette.style.overflow = "hidden"
}
function init() {
$(window).resize(function() {
place_objects();
});
place_objects();
}
$(init)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<title>Random Pomodoro</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>
<style>
#font-face {
font-family: "Stratum";
src: url(Stratum2-Regular.woff) format("woff");
}
.btn {
background: #507224;
background-image: -webkit-linear-gradient(top, #507224, #3a551b);
background-image: -moz-linear-gradient(top, #507224, #3a551b);
background-image: -ms-linear-gradient(top, #507224, #3a551b);
background-image: -o-linear-gradient(top, #507224, #3a551b);
background-image: linear-gradient(to bottom, #507224, #3a551b);
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0px;
font-family: Stratum;
color: #ffffff;
font-size: 20px;
padding: 10px 20px 10px 20px;
border: solid #2a3b16 2px;
text-decoration: none;
}
.btn:hover {
background: #728f4e;
border: solid #64754f 2px;
text-decoration: none;
}
.btn:active {
background: #3a551b;
background-image: -webkit-linear-gradient(top, #3a551b, #507224);
background-image: -moz-linear-gradient(top, #3a551b, #507224);
background-image: -ms-linear-gradient(top, #3a551b, #507224);
background-image: -o-linear-gradient(top, #3a551b, #507224);
background-image: linear-gradient(to bottom, #3a551b, #507224);
border: solid #64754f 2px;
text-decoration: none;
}
</style>
</head>
<body>
<div id="roulette" style="width:600px; height:144px; border:solid 2px #0f0f0f;">
<img src="http://i.imgur.com/VMfKDyq.png" id="ticker">
</div>
<button class="button btn" onclick="roll()" id="roll">Roll</button>
</body>
For some reason my div is tiny on here. When I run it on my PC, I get this:
What I want is for only the portions of images inside the div to be visible.
Demo: https://jsfiddle.net/nu5jbc50/1/
When you apply a position: fixed or position: absolute, it is likely that such element(s) is not following the DOM tree which means those img are not display as children of the div#roulette. To get rid of that, I would add a new container <div class="showcase" style="width: 200%; height: 100%; "></div> after img#ticker
HTML:
<div id="roulette" style="width:600px; height:144px; border:solid 2px #0f0f0f;">
<img src="http://i.imgur.com/VMfKDyq.png" id="ticker">
<div class="showcase" style="width: 200%; height: 100%; "></div>
</div>
<button class="button btn" onclick="roll()" id="roll">Roll</button>
Instead of using position: fixed for the tiles, I would apply position: relative; to it and not assigning value to their left CSS property anymore, we may use the margin-left CSS property.
JavaScript (only the roll() is modified):
function roll() {
var tile_src = ["http://i.imgur.com/XUp8Y4r.jpg", "http://i.imgur.com/Q3suBFZ.jpg"]
var roulette = document.getElementById("roulette");
var $showcase = $(".showcase");
var tiles = []
for (var i = 0; i < 64; i++) {
tile = document.createElement("IMG");
tile.id = "tile"
tile.style.position = "relative";
tile.style.zIndex = "-1";
tile.src = tile_src[Math.floor((Math.random() * 2))];
//tile.style.left = $(window).innerWidth() / 2 - 64 + i * 136 + 'px';
tile.style.top = '16px';
if (i > 0) tile.style.margin = '0 0 0 32px';
else tile.style.margin = '0 0 0 ' + ($(roulette).innerWidth() / 2 - 64).toString() + 'px';
tiles.push(tile);
}
for (var i = 0; i < tiles.length; i++) {
$showcase.append($(tiles[i]));
}
}
also applied the following to CSS that demo the animation:
div.showcase > *:first-child {
-webkit-transition: 64s linear;
transition: 64s linear;
}
Call the animation via:
setTimeout(function(){
$showcase.find(">*").first().css("margin-left", ((128 * tiles.length) * -1).toString() + 'px');
}, 1);

Dragging inline SVG with JqueryUI

I'm trying to get inline SVG elements to be draggable using JQuery UI, so that I can make custom video controls.
Unfortunately I've had little luck. I've tried this SO answer in my code but haven't gotten anywhere. I've also managed to get an SVG image dragging but not inline. Is it just that JQuery UI doesn't play well with inline SVG?
Any suggested alternatives?
$(document).ready(function() {
var v = document.querySelector("#vid");
var b = document.querySelector("#progress");
var x = document.querySelector("#draw_here");
var vidTimer;
var s;
//wait for video and tracks to load
var myVideoPlayer = document.getElementById('vid');
myVideoPlayer.addEventListener('loadedmetadata', function() {
$("#play_ball").draggable()
.bind('mousedown', function(event, ui) {
$(event.target.parentElement).append(event.target);
})
.bind('drag', function(event, ui) {
event.target.setAttribute('x', ui.position.left);
});
//$("#play_ball").draggable({
// axis: "x",
// containment: 'parent'
//});
var videoControls = document.getElementById('videoControls'),
play = document.getElementById('play'),
playProgressInterval = false,
progressContainer = document.getElementById("progress"),
playProgressBar = document.getElementById("play_ball");
// Get rid of the default controls
v.removeAttribute('controls');
handleButtonPresses();
function handleButtonPresses() {
// When the play button is clicked, playor pause the video.
play.addEventListener('click', playPause, false);
// When the play button is pressed, witch to the "Pause" symbol.
v.addEventListener('play', function() {
play.title = 'Pause';
play.innerHTML = '<span id="pauseButton">▐▐</span>';
// Begin tracking video's progress.
trackPlayProgress();
}, false);
// When the pause button is pressed, switch to the "Play" symbol.
v.addEventListener('pause', function() {
play.title = 'Play';
play.innerHTML = '►';
// Video was paused, stop tracking progress.
stopTrackingPlayProgress();
}, false);
// When the video has concluded, pause it.
v.addEventListener('ended', function() {
this.currentTime = 0;
this.pause();
}, false);
v.addEventListener('touchstart', function(e) {
var sDate = new Date();
sTime = sDate.getTime();;
var touchobj = e.changedTouches[0]
console.log(touchobj.target) // returns element touch point landed on
// var xPos =
// var yPos =
// console.log("position is"+e.PageX + ", " + e.PageY);
// console.log("position is" + xPos + ", " + yPos);
}, false);
v.addEventListener('touchend', function() {
var eDate = new Date();
eTime = eDate.getTime();;
if (eTime - sTime >= 99) {
alert("you held it!");
}
}, false);
}
function playPause() {
if (v.paused || v.ended) {
if (v.ended) {
v.currentTime = 0;
}
v.play();
} else {
v.pause();
}
}
function vidUpdate() {
$scope.sliderV.value = parseInt(v.currentTime, 10);
$scope.$broadcast('rzSliderForceRender');
}
// Every 50 milliseconds, update the play progress.
function trackPlayProgress() {
(function progressTrack() {
updatePlayProgress();
vidUpdate();
// pause at chapter breaks
//ignore first cue
for (var i = 1; i < cueS.length; i++) {
if (v.currentTime >= cueS[i].startTime - .10 && v.currentTime <= cueS[i].startTime + .10) {
v.currentTime += .3;
v.pause();
}
}
playProgressInterval = setTimeout(progressTrack, 50);
})();
}
function updatePlayProgress() {
playProgressBar.style.width = ((v.currentTime / v.duration) * (progressContainer.offsetWidth)) + "px";
playProgressBar.setAttribute("cx", (4 + ((v.currentTime / v.duration) * 94) + "%"));
}
// Video was stopped, so stop updating progress.
function stopTrackingPlayProgress() {
clearTimeout(playProgressInterval);
}
}); //ends wait for vid
}); //ends doc ready
/* PROGRESS BAR */
#progress {
position: absolute !important;
left: 7%;
height: 70%;
width: 90%;
cursor: pointer;
z-index: 4;
}
#progress_box {
height: 95%;
width: 100%;
border: 1px solid #292929;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
background: #303030;
/* Old browsers */
background: -moz-linear-gradient(top, #303030 0%, #545454 49%, #545454 51%, #7e7e7e 100%);
/* FF3.6-15 */
background: -webkit-linear-gradient(top, #303030 0%, #545454 49%, #545454 51%, #7e7e7e 100%);
/* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to bottom, #303030 0%, #545454 49%, #545454 51%, #7e7e7e 100%);
/* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#303030', endColorstr='#7e7e7e', GradientType=0);
/* IE6-9 */
-webkit-box-shadow: 0 1px 0 #292929, 0 -1px 0 #292929;
-moz-box-shadow: 0 1px 0 #292929, 0 -1px 0 #292929;
box-shadow: 0 1px 0 #292929, 0 -1px 0 #292929;
margin: 2px 0 0 5px;
padding: 2px;
overflow: hidden;
z-index: 4;
}
#play_progress {
display: block;
height: 40%;
width: 100%;
background-color: #fff;
background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), color-stop(.5, white), to(#e3e3e3));
background: -moz-linear-gradient(top, #e3e3e3, white 50%, #e3e3e3);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
z-index: 4;
}
#play_time {
float: right;
margin: 7px 0 0 5px;
font-size: 10px;
font-weight: normal;
font-family: Helvetica, Arial, sans-serif;
line-height: 1;
z-index: 4;
}
#spacer {
display: block;
width: 100%;
height: 30%;
}
#sliderVideo {
position: absolute;
top: 50px;
bottom: 50px;
right: 1%;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
</head>
<body>
<div id="player">
<video id="vid" controls>
<source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">
</video>
<div id="videoControls">
<button id="play" title="Play">►</button>
<div id="progress">
<svg xmlns="http://www.w3.org/2000/svg" id="draw_here" height="100" width="100%">
<line id="play_bar" x1="5%" y1="15" x2="100%" y2="15" style="stroke:#7E7F81;stroke-width:2" />
<circle id="play_ball" cx="4%" cy="15" r="13" fill="#B0C4DE" />
</svg>
<span id="spacer"></span>
</div>
<button id="instructorBtn" title="Instructor">!</button>
</div>
</div>
</body>
I'll debug it and see if I can solve the problem.
First thing I noticed is that you didn't close your html tag ;)
Also why "document.querySelector" when you use jquery...
Edit:
You seem to use a lot non jquery code, cleaning up your code currently and I'll fix the slider.
Edit2:
You have forgotten that you also need to update the video progress after sliding with the slider, I'm adding code for that too.
Edit3:
Here's some working code: https://jsfiddle.net/seahorsepip/gLudkdd9/5/
It's still messy and working buggy, the things you did with 4% and 94% don't make any sense either.
You actually don't even need jquery ui just to make it draggable, it's pretty easy to write it with mousedown mousemove and mouseup instead.
.

Slider FileReader JS Multiple Image Upload (Incrementing Index)

I am trying to make a JavaScript multiple image uploader that uploads image previews to a slider, but I am having some issues. So far it looks like I was able to get the images to upload into the slider, but the problem seems to happen with my i variable - when I try to increment it, it stays the same, not allowing my next and previous slider arrows from working. If anyone knows how to get this slider working properly, I would appreciate the help.
JS Code:
$('#_uploadImages').click(function() {
$('#_imagesInput').click()
})
$('#_imagesInput').on('change', function() {
handleFileSelect();
});
function handleFileSelect() {
//Check File API support
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files; //FileList object
var output = document.getElementById("frames");
for (var i = 0; i < files.length; i++) {
var file = files[i];
//Only pics
if (!file.type.match('image')) continue;
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
console.log(event);
current_i = i;
prev_i = current_i - 1;
next_i = current_i + 1;
//var div = document.createElement("div");
//div.innerHTML = div.innerHTML + "<img class='thumbnail' src='" + picFile.result + "'" + "title='" + picFile.name + "'/>";
//output.insertBefore(div, null);
////output.innerHTML = output.innerHTML + "<img class='thumbnail' style='max-width:500px' src='" + picFile.result + "'" + "title=''/>"; // TODO: Enter Title
output.innerHTML = output.innerHTML + '<li id="slide-' + current_i + '" class="slide">' + "<img src='" + picFile.result + "'" + "title=''/>" + '<nav>' + '<a class="prev" href="#slide-' + prev_i + '">←</a>' + '<a class="next" href="#slide-' + next_i + '">→</a>' + '</nav>' + '<li>'; // TODO: Enter Title
});
//Read the image
picReader.readAsDataURL(file);
}
//output.innerHTML = output.innerHTML + '<li class="quicknav">' + '<ul>' + '<li></li>' + '<li></li>' + '<li></li>' + '</ul>' + '</li>'
} else {
console.log("Your browser does not support File API");
}
}
JSFiddle: http://jsfiddle.net/Hybridx24/yfr57u6w/
The problem with the code is that by the time the load event executes - the for loop has already incremented. So if two images are added - the value of i when the load event is executing is already 2.
One way to solve this is to add the value of i to an array and retrieve it in the event listener one by one:
var arrFilesCount = [];
for (var i = 0; i < files.length; i++) {
arrFilesCount.push(i); //push to array
var file = files[i];
//Only pics
if (!file.type.match('image')) continue;
var picReader = new FileReader();
picReader.addEventListener("load", function (event) {
var picFile = event.target;
current_i = arrFilesCount.shift(); // get from array instead of using i
prev_i = current_i - 1;
next_i = current_i + 1;
...
...
Corresponding jsFiddle here
Now, this array can also be used for determining the first/last element and thereby using this to go from last to first element. Because we cannot be sure when the event listener will execute (say if there are 100 images the first event listener may execute when the count of loop has reached 5 or 10), so I've used two loops instead of one. The first loop just to populate the array.
var arrFilesCount = [];
for (var i = 0; i < files.length; i++) {
arrFilesCount.push(i);
}
Lets use this to find the first and last elements
current_i = arrFilesCount.shift();
if(current_i === 0){
prev_i = files.length - 1; //This is for the first element. The previous slide will be the last image. (i=length-1)
}
else{
prev_i = current_i - 1;
}
if(arrFilesCount.length === 0){
next_i = 0; //This is for the last element. The next slide will be the first image (i=0)
}
else{
next_i = current_i + 1;
}
See this jsFiddle.
Finally, there can be scenarios where the user first adds a couple of images then clicks on upload button again and adds a couple of more images. In this case we need to correct the existing href. The elements which we need to correct are the next of last and prev of first. This can be done using:
var start = $(output).find('li').length;
var end = start+ files.length;
if(start !== 0){
$(output).find('li > nav > a.prev').first().attr('href','#slide-' + (end-1));
$(output).find('li > nav > a.next').last().attr('href','#slide-'+start);
}
So the final jsFiddle will be something like this.
Substituted .append() for .innerHTML ; created variable idx to increment .slide li elements ids ; added delegated click event to nav a elements ; added .bind() with this set to picReader , i passed as parameter to picReader onload event ; added file.name to title attribute of img element ; added "dot" navigation with thumbanail of images beneath #frames ; title to arrow navigation
var idx = -1, re = /(.*)(?=\.)/;
$('#_uploadImages').click(function() {
$('#_imagesInput').click();
});
$('#_imagesInput').on('change', function(event) {
handleFileSelect(event);
});
$(document).on("click", ".slider .slide nav a, .nav a", function(e) {
e.preventDefault();
$(".slide").hide()
.filter(":has(img[title^="+e.target.title.match(re)[0]+"])").show();
});
function handleFileSelect(event) {
//Check File API support
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files; //FileList object
var output = document.getElementById("frames");
for (var i = 0; i < files.length; i++) {
var file = files[i];
var picReader = new FileReader();
picReader.onload = function(index, event) {
++idx;
var picFile = event.target;
var slides = $(".slider li[id^=slide]");
// TODO: Enter Title
$(output)
.append('<li id="slide-'
+ idx
+ '" class="slide">'
+ "<img src='"
+ picFile.result
// set `title`
+ "'title="
//`index` : `i`
+ files[index].name
+ "/>"
+ '<nav>'
+ '<a class="prev">←</a>'
+ '<a class="next">→</a>'
+ '</nav>'
+ '</li>');
// add title to `nav a` elements
if (file.name === files[files.length - 1].name) {
$(".nav").empty();
$("nav a").each(function(i, el) {
if ($(el).closest("[id^=slide]").prev("[id^=slide]").length
&& $(el).is("nav a:nth-of-type(1)")) {
$(el).attr("title",
$(el).closest("[id^=slide]")
.prev("[id^=slide]").find("img").attr("title")
)
}
if ($(el).closest("[id^=slide]").next("[id^=slide]").length
&& $(el).is("nav a:nth-of-type(2)")) {
$(el).attr("title",
$(el).closest("[id^=slide]")
.next("[id^=slide]").find("img").attr("title")
)
}
if ($(el).is(".slider [id^=slide]:first a:first")) {
$(el).attr("title",
$("[id^=slide]:last").find("img").attr("title")
)
}
if ($(el).is(".slider [id^=slide]:last a:last")) {
$(el).attr("title",
$("[id^=slide]:first").find("img").attr("title")
)
};
});
$(".slider img").each(function(i, el) {
$(".nav").append(
$("nav a[title^="
+$(el).attr("title").match(re)[0]
+"]:first")
.clone().html(el.outerHTML)
)
})
}
}.bind(picReader, i);
//Read the image
picReader.readAsDataURL(file);
};
} else {
console.log("Your browser does not support File API");
}
}
* {
margin: 0;
padding: 0;
/*transition*/
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
}
body {
padding: 30px;
}
/* Slider */
.slider {
height: 250px;
left: 50%;
margin: -125px -225px;
position: absolute;
top: 48%;
width: 450px;
/*box-shadow*/
-webkit-box-shadow: 0 0 5px #000;
-moz-box-shadow: 0 0 5px #000;
box-shadow: 0 0 5px #000;
}
.slider .frames {
height: 250px;
position: relative;
list-style-type: none;
}
.slider .frames .slide {
height: 250px;
list-style: none;
position: absolute;
width: 450px;
}
.slider .slide:target {
z-index: 100
}
.slider .frames .slide img {
height: 250px;
width: 450px;
}
.slider .frames .slide nav a {
background: hsla(0, 0%, 0%, .75);
color: #fff;
font-size: 16px;
line-height: 50px;
margin-top: -25px;
opacity: 0;
position: absolute;
text-align: center;
text-decoration: none;
top: 50%;
width: 50px;
visibility: hidden;
z-index: 10;
}
.slider:hover .frames .slide nav a {
opacity: 1;
visibility: visible;
}
.slider .slide nav a:hover {
cursor: pointer;
}
.slider .frames .slide nav .prev {
/*border-radius*/
-webkit-border-radius: 0 25px 25px 0;
-moz-border-radius: 0 25px 25px 0;
border-radius: 0 25px 25px 0;
left: 0;
}
.slider .frames .slide nav .next {
/*border-radius*/
-webkit-border-radius: 25px 0 0 25px;
-moz-border-radius: 25px 0 0 25px;
border-radius: 25px 0 0 25px;
right: 0;
}
.slider .frames .slide nav a:hover {
background: #000
}
.slider .quicknav {
bottom: 0;
font-size: 0;
opacity: 0;
position: absolute;
text-align: center;
width: 100%;
z-index: 100;
}
.slider:hover .quicknav {
opacity: .9
}
.slider .quicknav li {
display: inline-block
}
.slider .quicknav a {
background: hsla(0, 0%, 100%, .9);
border: 1px solid hsla(0, 0%, 0%, .9);
/*border-radius*/
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
border-radius: 100%;
display: block;
height: 10px;
margin: 10px 5px;
text-decoration: none;
width: 10px;
}
.slider .quicknav a:hover {
background: hsla(0, 0%, 50%, .9)
}
.nav {
width:100%;
text-align:center;
}
.nav a {
display:inline-block;
background:transparent;
border-radius:50%;
border:4px solid transparent;
width:24px;
height:24px;
margin:4px;
}
.nav a img {
width:22px;
height:22px;
border-radius:50%;
}
.slider #one:target ~ .quicknav a[href="#one"],
.slider #two:target ~ .quicknav a[href="#two"],
.slider #three:target ~ .quicknav a[href="#three"],
.slider #four:target ~ .quicknav a[href="#four"],
.slider #five:target ~ .quicknav a[href="#five"] {
background: hsla(0, 0%, 0%, .9);
border-color: hsla(0, 0%, 100%, .9);
background: rgb(244, 246, 245);
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(244, 246, 245, 1), 0.01), color-stop(rgba(203, 219, 219, 1), 1), color-stop(rgba(216, 216, 216, 1), 1));
background: -webkit-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -moz-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -o-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(1%, rgba(244, 246, 245, 1)), color-stop(100%, rgba(203, 219, 219, 1)), color-stop(100%, rgba(216, 216, 216, 1)));
background: -webkit-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -moz-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: -o-linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
background: linear-gradient(top, rgba(244, 246, 245, 1) 1%, rgba(203, 219, 219, 1) 100%, rgba(216, 216, 216, 1) 100%);
filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#f4f6f5', endColorstr='#d8d8d8', GradientType=0);
/*box-shadow*/
-webkit-box-shadow: inset 0 0 3px #000, 0 0 2px rgba(0, 0, 0, .5), 0 2px 3px #666;
-moz-box-shadow: inset 0 0 3px #000, 0 0 2px rgba(0, 0, 0, .5), 0 2px 3px #666;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<button id="_uploadImages" class="btn btn-primary">Upload Images</button>
<form id="_imagesForm" action="" method="post">
<input id="_imagesInput" accept="image/*" type="file" style="display:none" multiple>
</form>
<div id="_displayImages">
<div class="slider">
<ul id="frames" class="frames">
</ul>
<div class="nav"></div>
</div>
</div>
jsfiddle http://jsfiddle.net/yfr57u6w/24/

Categories