Related
I am playing around and practice my JS (beginner). I have created stacking panels and i hit a wall. I just can not target and add class of shadow to the moving element (only when one panel is above other, class should add).
For now i have this:
const boxes = Array.from(document.querySelectorAll(".box"));
const wrapper = document.querySelector(".wrapper");
const leftMargin = 60; //px
function scrollWrap(e) {
let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
boxes.forEach((box, index) => {
let leftMarginStop = index * leftMargin;
const boxCoord = box.getBoundingClientRect();
let leftCoordPanel = boxCoord.left;
let flag = false;
//console.log({scrollCoord, leftMarginStop, leftCoordPanel, box});
if (boxCoord.left <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,...
//console.log("STAHP!!");
box.style.position = "sticky";
box.style.left = `${leftMarginStop}px`; // sets the left to 60, 120, 180,...
flag = true;
if (flag) {
box.classList.add("shadow");
console.log(this) //how to target each panel rather than wrapper?
} else {
box.classList.remove("shadow");
}
} else {
box.style.position = "static";
box.style.left = 0;
flag = false;
}
});
}
wrapper.addEventListener("scroll", scrollWrap);
body {
margin: 0;
padding: 0;
}
.wrapper, .box1, .box2, .box3, .box4, .box5, .box6, .box7, .box8 {
position: sticky;
height: 750px;
z-index: 1;
}
.wrapper {
width: 1442px;
border-right: 1px solid #f2f2f2;
border-bottom: 1px solid #f2f2f2;
display: flex;
overflow: scroll;
}
.wrapper .box1 {
min-width: 357px;
height: 750px;
background-color: #1a1a1a;
}
.wrapper .box2 {
min-width: 357px;
height: 750px;
background-color: #333;
}
.wrapper .box3 {
min-width: 702px;
height: 750px;
background-color: #4d4d4d;
}
.wrapper .box4 {
min-width: 630px;
height: 750px;
background-color: #666;
}
.wrapper .box5 {
min-width: 630px;
height: 750px;
background-color: #808080;
}
.wrapper .box6 {
min-width: 357px;
height: 750px;
background-color: #999;
}
.wrapper .box7 {
min-width: 630px;
height: 750px;
background-color: #b3b3b3;
}
.wrapper .box8 {
min-width: 630px;
height: 750px;
background-color: #ccc;
}
.shadow {
box-shadow: -4px 0px 40px rgba(0, 0, 0, 0.2);
}
<div class="wrapper">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
<div class="box box5"></div>
<div class="box box6"></div>
<div class="box box7"></div>
<div class="box box8"></div>
</div>
If anyone can help me out, please show me code with explanation, so i can see and know what and how.
I try to do it with some flag or without, but every time the class is added when element reaches the end (left padding). I want to add class when element is on top of other element. If it is not, remove class. Also, how to make this so it works on mouse scroll wheel? I was testing this with apple magic mouse, but on scroll wheel it does not work.
Oh and please, if you see something very wrong please let me know, i am beginner and would like to learn something from this post.
For now i have managed to update my code. It works when i scroll and shadow is also applying to the panel. There is still something i wonder.
When i add shadow class i created transition. It works perfect, but when i remove shadow class it just disappears, no transition back. Why is that? I want shadow to appear and disappear in same way
How to track every single panel if it has reached the left margin, and than apply eventListener with mouse enter and mouse leave on it? So when i hover to "closed" panel, i get that item and if i hover on NOT "closed" panel i will not get item. I was trying with console.log "this" but it returned every panel i mouse entered it
How to target every panel, so i can later say, when 4th panel reaches left margin, the margin of stacked elements change?
My updated code:
const boxes = Array.from(document.querySelectorAll(".box"));
const wrapper = document.querySelector(".wrapper");
const leftMargin = 60; //px
function scrollWrap(e) {
let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
boxes.forEach((box, index) => {
let leftMarginStop = (index) * leftMargin; // calculation for left margin stop (60, 120, 180,...)
const boxCoord = box.getBoundingClientRect();
const leftSideOfCurrent = boxCoord.left; // coordinarion of left side of panel
const rightSideOfCurrent = boxCoord.right; // coordinarion of right side of panel
const leftSideOfNextItem = box.nextElementSibling.getBoundingClientRect().left; // coordinarion of left side of NEXT panel
box.style.position = "sticky";
box.style.left = `${leftMarginStop}px`;
// controll shadow of first element
scrollCoord > 0 ? boxes[1].classList.add("shadow") : boxes[1].classList.remove("shadow");
// controll shadow of all 0+ elements
if (leftSideOfCurrent <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,...
box.nextElementSibling.classList.add("shadow");
}
// controll removal of shadow of all 0+ elements
if (leftSideOfNextItem === rightSideOfCurrent) {
box.nextElementSibling.classList.remove("shadow");
}
// when panel 5 reach left margin, left margin change from 60 to 30 to all panels
if (boxes[4] && leftSideOfCurrent < leftMarginStop) {
console.log("helo");
}
});
}
wrapper.addEventListener("scroll", scrollWrap);
body {
margin: 0;
padding: 0;
}
.wrapper, .box1, .box2, .box3, .box4, .box5, .box6, .box7, .box8 {
position: sticky;
height: 750px;
z-index: 1;
}
.wrapper {
width: 1442px;
border-right: 1px solid #f2f2f2;
border-bottom: 1px solid #f2f2f2;
display: flex;
overflow: scroll;
}
.wrapper .box0 {
min-width: 357px;
background-color: #1a1a1a;
}
.wrapper .box1 {
min-width: 357px;
background-color: #333;
}
.wrapper .box2 {
min-width: 702px;
background-color: #4d4d4d;
}
.wrapper .box3 {
min-width: 630px;
background-color: #666;
}
.wrapper .box4 {
min-width: 630px;
background-color: #808080;
}
.wrapper .box5 {
min-width: 357px;
background-color: #999;
}
.wrapper .box6 {
min-width: 630px;
background-color: #b3b3b3;
}
.wrapper .box7 {
min-width: 630px;
background-color: #ccc;
}
.shadow {
box-shadow: -4px 0px 40px rgba(0, 0, 0, 1.2);
-webkit-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
-moz-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
-o-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
}
<div class="wrapper">
<div class="box box0"></div>
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
<div class="box box5"></div>
<div class="box box6"></div>
<div class="box box7"></div>
</div>
Tips for your code:
In your CSS code, the wrapper element has a width property. This
causes the page and the wrapper element to have a scrollbars. So,
remove it.
You do not need to use javascript to add stickiness to the
boxes. The only CSS will do this for you. You need JavaScript only
for add the left property and shadow to the boxes.
Don’t try to use overflow: auto|scroll|hidden on the parent element
of a position:sticky element. It completely breaks the stickiness.
overflow: visible is fine. See the code snippet below.
In your JavaScript code, the flag variant value, always is true, So
the shadow class can't remove from elements.
Other notes:
If you’re wanting to use position:absolute on an element inside of
a sticky element you have to be careful. If your app is running in
an older browser that doesn’t support position:sticky, then that
sticky element won’t act like a relative positioned element. So
the absolute positioned element will skip it and look up the DOM
tree until it finds the next non-static element (absolute / relative / fixed position), defaulting to the html element if none
found. In other words, your absolute positioned element is going
to be in a way different place on the screen than you expected it to
be.
position: sticky; is supported in a lot of browsers, but not yet
in Edge. IE doesn’t matter at this point. There are many
polyfills out there if you absolutely have to have this behavior,
but they all use JavaScript. A better option is to design your app
so that sticky position is a slick addition, but the app still
functions without it.
Example:
const boxes = Array.from( document.querySelectorAll( '.box' ) ),
scroller = document.querySelector( '.scroller' ),
leftMargin = 30,
length = boxes.length - 1;
function scrollWrap() {
boxes.forEach( function( box, index ) {
let leftMarginStop = index * leftMargin;
const boxCoord = box.getBoundingClientRect();
let leftCoordPanel = boxCoord.left;
if ( leftCoordPanel <= leftMarginStop ) {
box.style.left = leftMarginStop + 'px';
if ( index < length ) boxes[ index + 1 ].classList.add( 'shadow' )
if ( index == 0 && boxes[ 1 ].getBoundingClientRect().left == box.offsetWidth ) boxes[ 1 ].classList.remove( 'shadow' )
} else {
box.style.left = 0;
if ( index < length ) boxes[ index + 1 ].classList.remove( 'shadow' )
}
} );
}
scroller.addEventListener( 'scroll', scrollWrap )
html,
body {
margin: 0;
height: 100%
}
.scroller {
height: 100%;
display: flex;
align-items: center;
overflow-x: auto;
overflow-y: hidden
}
.wrapper {
height: 100%;
display: flex
}
.box {
min-width: 630px;
height: 100%;
position: -webkit-sticky;
position: sticky;
left: 0 /* <-- become sticky once touching left edge */
}
.box1 {
min-width: 357px;
background: #1a1a1a url(https://cdn.pixabay.com/photo/2015/12/10/16/09/seamless-pattern-1086662__340.jpg)
}
.box2 {
min-width: 357px;
background: #333 url(https://cdn.pixabay.com/photo/2015/12/18/23/46/template-1099298__340.png)
}
.box3 {
min-width: 702px;
background: #4d4d4d url(https://cdn.pixabay.com/photo/2014/07/28/16/00/pattern-403769__340.png)
}
.box4 {
background: #666 url(https://cdn.pixabay.com/photo/2017/06/10/03/14/damask-2388884__340.png)
}
.box5 {
background: #808080 url(https://cdn.pixabay.com/photo/2015/12/12/17/34/seamless-pattern-1089797__340.png)
}
.box6 {
min-width: 357px;
background: #999 url(https://cdn.pixabay.com/photo/2016/03/06/16/23/background-1240686__340.png)
}
.box7 {
background: #b3b3b3 url(https://cdn.pixabay.com/photo/2018/04/24/05/00/backdrop-3346304__340.png)
}
.box8 {
background: #ccc url(https://cdn.pixabay.com/photo/2016/04/01/09/03/floral-1299131__340.png)
}
.shadow {
box-shadow: -10px 0px 40px rgba(0, 0, 0, 1);
}
<div class="scroller">
<div class="wrapper">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
<div class="box box5"></div>
<div class="box box6"></div>
<div class="box box7"></div>
<div class="box box8"></div>
</div>
</div>
About your updated code:
the following line in your jS code:
const leftSideOfNextItem = box.nextElementSibling.getBoundingClientRect().left;
causes an error. Because, when index become 8, box.nextElementSibling can't retrieve any element. So you can change it to this:
const leftSideOfNextItem = ( index < boxes.length - 1 ) ? box.nextElementSibling.getBoundingClientRect().left : 0;
Also at the end of your JS code, the following code snippet:
if (index[4] && leftSideOfCurrent < leftMarginStop) {
console.log("helo");
}
must change to:
// when panel 5 reach left margin, left margin change from 60 to 30 to all panels
if (index == 4 && leftSideOfCurrent <= leftMarginStop) {
console.log("helo");
leftMargin = 30
}
Also you must change const leftMargin = 60; to var leftMargin = 60;
Updated code:
const boxes = Array.from(document.querySelectorAll(".box"));
const wrapper = document.querySelector(".wrapper");
var leftMargin = 60; //px
function scrollWrap(e) {
let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
boxes.forEach((box, index) => {
let leftMarginStop = (index) * leftMargin; // calculation for left margin stop (60, 120, 180,...)
const boxCoord = box.getBoundingClientRect();
const leftSideOfCurrent = boxCoord.left; // coordinarion of left side of panel
const rightSideOfCurrent = boxCoord.right; // coordinarion of right side of panel
const leftSideOfNextItem = ( index < boxes.length - 1 ) ? box.nextElementSibling.getBoundingClientRect().left: 0; // coordinarion of left side of NEXT panel
box.style.position = "sticky";
box.style.left = `${leftMarginStop}px`;
// controll shadow of first element
scrollCoord > 0 ? boxes[1].classList.add("shadow") : boxes[1].classList.remove("shadow");
// controll shadow of all 0+ elements
if (leftSideOfCurrent <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,...
box.nextElementSibling.classList.add("shadow");
}
// controll removal of shadow of all 0+ elements
if (leftSideOfNextItem === rightSideOfCurrent) {
box.nextElementSibling.classList.remove("shadow");
}
// when panel 5 reach left margin, left margin change from 60 to 30 to all panels
if (index == 4 && leftSideOfCurrent <= leftMarginStop) {
console.log("helo");
leftMargin = 30
}
});
}
wrapper.addEventListener("scroll", scrollWrap);
body {
margin: 0;
padding: 0;
}
.wrapper, .box0, .box1, .box2, .box3, .box4, .box5, .box6, .box7 {
position: sticky;
height: 750px;
z-index: 1;
}
.wrapper {
width: 1442px;
border-right: 1px solid #f2f2f2;
border-bottom: 1px solid #f2f2f2;
display: flex;
overflow: scroll;
}
.wrapper .box0 {
min-width: 357px;
background-color: #1a1a1a;
}
.wrapper .box1 {
min-width: 357px;
background-color: #333;
}
.wrapper .box2 {
min-width: 702px;
background-color: #4d4d4d;
}
.wrapper .box3 {
min-width: 630px;
background-color: #666;
}
.wrapper .box4 {
min-width: 630px;
background-color: #808080;
}
.wrapper .box5 {
min-width: 357px;
background-color: #999;
}
.wrapper .box6 {
min-width: 630px;
background-color: #b3b3b3;
}
.wrapper .box7 {
min-width: 630px;
background-color: #ccc;
}
.shadow {
box-shadow: -4px 0px 40px rgba(0, 0, 0, 1.2);
-webkit-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
-moz-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
-o-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
}
/* To make the console visible. */
.box0 {
height: 700px;
)
<div class="wrapper">
<div class="box box0"></div>
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
<div class="box box5"></div>
<div class="box box6"></div>
<div class="box box7"></div>
</div>
This was helpful. I know for error but could not fix it. I have set let leftMargin = 60; i use let instead var.
I am working on the margins, if the 5th panel reaches the left margin the margin of all panels get 30px. I did it also for reverse:
if (index > 4 && leftSideOfCurrent <= leftMarginStop) {
leftMargin = 30;
} else if (index < 5 && leftSideOfCurrent > leftMarginStop) {
leftMargin = 60;
}
But now when 5th panel reaches left margin, the panels less than 5 get EACH transitioned seperately instead of all, but when the 5th element is no longer in left margin, all gets transitioned at same time. Why is it like that? I do not understand. Can you explain please?
Is there any way to show the data i.e, when user starts accessing our website, after changing the two or three links of same website a data should be showed from the bottom.Is there any way to display the div when user changes the two or three links of my website.Below is my code
$(document).scroll(function(e) {
e.preventDefault();
var y = $(this).scrollTop();
if (y > 800) {
$('.fadein-data').fadeIn();
} else {
$('#close-data').click(function() {
$('.fadein-data').fadeOut();
$(document).unbind('scroll');
})
}
});
.fadein-data {
display: none;
position: fixed;
width: 350px;
left: 20px;
bottom: 0;
border: 1px solid #e5e5e5;
border-bottom: 0;
padding: 30px;
background-color: #ffffff;
z-index: 1050;
-webkit-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
box-shadow: 0 0.085em 0.5em 0 rgba(0, 0, 0, 0.165);
}
#close-data {
float: right;
font-size: 21px;
font-weight: 700;
line-height: 1;
color: #000;
text-shadow: 0 1px 0 #fff;
opacity: .2;
top: 5px;
position: absolute;
right: 9px;
cursor: pointer;
}
<div class="fadein-data">
<a type="button " id="close-data "><span aria-hidden="true ">×</span></a>
<h4 class="mt-0 mb-10 ">Heading</h4>
<p><b>The all in one software and some content</b></h4>
<img src="images/brochure.png ">
<br>
<a type="button " href="Brochure.pdf " class="btn btn-success">Download Brouchure</a>
</div>
:
So you want to start displaying your data once the user has already navigated through a few links? Here's one solution.
You can bind a callback to the
`$(window).on('hashchange', function(e){
// do something...
});`
event or the
(document).location().change
event.
In the callback push the current url into a globally defined array and then check on the array length. If it's greater than 2 or 3 as per your need fire the callback to display your data. Here's a close example!
$(document).ready(function() {
var navigatedUrls = [];
$(window).bind( 'hashchange', function(e) {
var anchor = document.location.hash;
navigatedUrls.push(anchor);
if(navigateUrls.length >2) {
//call the method that displays data
}
});
});
You can replace the hash and location part based on how your Url is.
Here is a list of browsers that support hashchange event.
http://caniuse.com/#feat=hashchange
I stumbple upon this Javascript flip effect page.
When I inspect its obfuscated source code, I can not find css property transform or rotate .
I want to know how the flip effect is achieved. What CSS properties are involved?
$(document).ready(function() {
/* The following code is executed once the DOM is loaded */
$('.sponsorFlip').click(function() {
// $(this) point to the clicked .sponsorFlip element (caching it in elem for speed):
var elem = $(this);
// data('flipped') is a flag we set when we flip the element:
if (elem.data('flipped')) {
// If the element has already been flipped, use the revertFlip method
// defined by the plug-in to revert to the default state automatically:
elem.revertFlip();
// Unsetting the flag:
elem.data('flipped', false)
} else {
// Using the flip method defined by the plugin:
elem.flip({
direction: 'lr',
speed: 350,
onBefore: function() {
// Insert the contents of the .sponsorData div (hidden
// from view with display:none) into the clicked
// .sponsorFlip div before the flipping animation starts:
elem.html(elem.siblings('.sponsorData').html());
}
});
// Setting the flag:
elem.data('flipped', true);
}
});
});
body {
/* Setting default text color, background and a font stack */
font-size: 0.825em;
color: #666;
background-color: #fff;
font-family: Arial, Helvetica, sans-serif;
}
.sponsorListHolder {
margin-bottom: 30px;
}
.sponsor {
width: 180px;
height: 180px;
float: left;
margin: 4px;
/* Giving the sponsor div a relative positioning: */
position: relative;
cursor: pointer;
}
.sponsorFlip {
/* The sponsor div will be positioned absolutely with respect
to its parent .sponsor div and fill it in entirely */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: 1px solid #ddd;
background: url("img/background.jpg") no-repeat center center #f9f9f9;
}
.sponsorFlip:hover {
border: 1px solid #999;
/* CSS3 inset shadow: */
-moz-box-shadow: 0 0 30px #999 inset;
-webkit-box-shadow: 0 0 30px #999 inset;
box-shadow: 0 0 30px #999 inset;
}
.sponsorFlip img {
/* Centering the logo image in the middle of the .sponsorFlip div */
position: absolute;
top: 50%;
left: 50%;
margin: -70px 0 0 -70px;
}
.sponsorData {
/* Hiding the .sponsorData div */
display: none;
}
.sponsorDescription {
font-size: 11px;
padding: 50px 10px 20px 20px;
font-style: italic;
}
.sponsorURL {
font-size: 10px;
font-weight: bold;
padding-left: 20px;
}
.clear {
/* This class clears the floats */
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://demo.tutorialzine.com/2010/03/sponsor-wall-flip-jquery-css/jquery.flip.min.js"></script>
<div title="Click to flip" class="sponsor">
<div class="sponsorFlip">
<img alt="More about google" src="data:image/png;base64,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">
</div>
<div class="sponsorData">
<div class="sponsorDescription">
The company that redefined web search.
</div>
<div class="sponsorURL">
http://www.google.com/
</div>
</div>
</div>
It's a jQuery plugin they use to achieve this result. It's called jquery.flip.min.js 😉
• Here is a more legible version of their JavaScript code:
eval(function(p, a, c, k, e, r) {
e = function(c) {
return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
};
if (!''.replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [
function(e) {
return r[e]
}
];
e = function() {
return '\\w+'
};
c = 1
};
while (c--)
if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
}('(5($){5 H(a){a.1D.1f[a.1E]=1F(a.1G,10)+a.1H}6 j=5(a){1I({1J:"1g.Z.1K 1L 1M",1N:a})};6 k=5(){7(/*#1O!#*/11&&(1P 1Q.1h.1f.1R==="1S"))};6 l={1T:[0,4,4],1U:[1i,4,4],1V:[1j,1j,1W],1X:[0,0,0],1Y:[0,0,4],1Z:[1k,1l,1l],20:[0,4,4],21:[0,0,A],22:[0,A,A],23:[12,12,12],24:[0,13,0],26:[27,28,1m],29:[A,0,A],2a:[2b,1m,2c],2d:[4,1n,0],2e:[2f,2g,2h],2i:[A,0,0],2j:[2k,2l,2m],2n:[2o,0,R],2p:[4,0,4],2q:[4,2r,0],2s:[0,t,0],2t:[2u,0,2v],2w:[1i,1o,1n],2x:[2y,2z,1o],2A:[1p,4,4],2B:[1q,2C,1q],2D:[R,R,R],2E:[4,2F,2G],2H:[4,4,1p],2I:[0,4,0],2J:[4,0,4],2K:[t,0,0],2L:[0,0,t],2M:[t,t,0],2N:[4,1k,0],2O:[4,S,2P],2Q:[t,0,t],2R:[t,0,t],2S:[4,0,0],2T:[S,S,S],2U:[4,4,4],2V:[4,4,0],9:[4,4,4]};6 m=5(a){T(a&&a.1r("#")==-1&&a.1r("(")==-1){7"2W("+l[a].2X()+")"}2Y{7 a}};$.2Z($.30.31,{u:H,v:H,w:H,x:H});$.1s.32=5(){7 U.1t(5(){6 a=$(U);a.Z(a.B(\'1u\'))})};$.1s.Z=5(i){7 U.1t(5(){6 c=$(U),3,$8,C,14,15,16=k();T(c.B(\'V\')){7 11}6 e={I:(5(a){33(a){W"X":7"Y";W"Y":7"X";W"17":7"18";W"18":7"17";34:7"Y"}})(i.I),y:m(i.D)||"#E",D:m(i.y)||c.z("19-D"),1v:c.J(),F:i.F||1w,K:i.K||5(){},L:i.L||5(){},M:i.M||5(){}};c.B(\'1u\',e).B(\'V\',1).B(\'35\',e);3={s:c.s(),n:c.n(),y:m(i.y)||c.z("19-D"),1x:c.z("36-37")||"38",I:i.I||"X",G:m(i.D)||"#E",F:i.F||1w,o:c.1y().o,p:c.1y().p,1z:i.1v||39,9:"9",1a:i.1a||11,K:i.K||5(){},L:i.L||5(){},M:i.M||5(){}};16&&(3.9="#3a");$8=c.z("1b","3b").8(3c).B(\'V\',1).3d("1h").J("").z({1b:"1A",3e:"3f",p:3.p,o:3.o,3g:0,3h:3i});6 f=5(){7{1B:3.9,1x:0,3j:0,u:0,w:0,x:0,v:0,N:3.9,O:3.9,P:3.9,Q:3.9,19:"3k",3l:\'3m\',n:0,s:0}};6 g=5(){6 a=(3.n/13)*25;6 b=f();b.s=3.s;7{"q":b,"1c":{u:0,w:a,x:a,v:0,N:\'#E\',O:\'#E\',o:(3.o+(3.n/2)),p:(3.p-a)},"r":{v:0,u:0,w:0,x:0,N:3.9,O:3.9,o:3.o,p:3.p}}};6 h=5(){6 a=(3.n/13)*25;6 b=f();b.n=3.n;7{"q":b,"1c":{u:a,w:0,x:0,v:a,P:\'#E\',Q:\'#E\',o:3.o-a,p:3.p+(3.s/2)},"r":{u:0,w:0,x:0,v:0,P:3.9,Q:3.9,o:3.o,p:3.p}}};14={"X":5(){6 d=g();d.q.u=3.n;d.q.N=3.y;d.r.v=3.n;d.r.O=3.G;7 d},"Y":5(){6 d=g();d.q.v=3.n;d.q.O=3.y;d.r.u=3.n;d.r.N=3.G;7 d},"17":5(){6 d=h();d.q.w=3.s;d.q.P=3.y;d.r.x=3.s;d.r.Q=3.G;7 d},"18":5(){6 d=h();d.q.x=3.s;d.q.Q=3.y;d.r.w=3.s;d.r.P=3.G;7 d}};C=14[3.I]();16&&(C.q.3n="3o(D="+3.9+")");15=5(){6 a=3.1z;7 a&&a.1g?a.J():a};$8.1d(5(){3.K($8,c);$8.J(\'\').z(C.q);$8.1e()});$8.1C(C.1c,3.F);$8.1d(5(){3.M($8,c);$8.1e()});$8.1C(C.r,3.F);$8.1d(5(){T(!3.1a){c.z({1B:3.G})}c.z({1b:"1A"});6 a=15();T(a){c.J(a)}$8.3p();3.L($8,c);c.3q(\'V\');$8.1e()})})}})(3r);', 62, 214, '|||flipObj|255|function|var|return|clone|transparent||||||||||||||height|top|left|start|second|width|128|borderTopWidth|borderBottomWidth|borderLeftWidth|borderRightWidth|bgColor|css|139|data|dirOption|color|999|speed|toColor|int_prop|direction|html|onBefore|onEnd|onAnimation|borderTopColor|borderBottomColor|borderLeftColor|borderRightColor|211|192|if|this|flipLock|case|tb|bt|flip||false|169|100|dirOptions|newContent|ie6|lr|rl|background|dontChangeColor|visibility|first|queue|dequeue|style|jquery|body|240|245|165|42|107|140|230|224|144|indexOf|fn|each|flipRevertedSettings|content|500|fontSize|offset|target|visible|backgroundColor|animate|elem|prop|parseInt|now|unit|throw|name|js|plugin|error|message|cc_on|typeof|document|maxHeight|undefined|aqua|azure|beige|220|black|blue|brown|cyan|darkblue|darkcyan|darkgrey|darkgreen||darkkhaki|189|183|darkmagenta|darkolivegreen|85|47|darkorange|darkorchid|153|50|204|darkred|darksalmon|233|150|122|darkviolet|148|fuchsia|gold|215|green|indigo|75|130|khaki|lightblue|173|216|lightcyan|lightgreen|238|lightgrey|lightpink|182|193|lightyellow|lime|magenta|maroon|navy|olive|orange|pink|203|purple|violet|red|silver|white|yellow|rgb|toString|else|extend|fx|step|revertFlip|switch|default|flipSettings|font|size|12px|null|123456|hidden|true|appendTo|position|absolute|margin|zIndex|9999|lineHeight|none|borderStyle|solid|filter|chroma|remove|removeData|jQuery'.split('|'), 0, {}))
I make autocomplete
Max-height set from JavaScript:
if (data.length < 10)
element.css({'max-height': (30 * newVal.length) + 'px'})
If max-height decreases(e.g. 300px to 150px), transition does not work.
If max-height increases(e.g. 150px to 300px), transition works.
.autocomplete-ion {
background-color: gray;
position: absolute;
width: 90%;
left: 5%;
top:45px;
overflow-y: auto;
z-index: 10000000;
background-color: #FAFAFA;
transition: 0.8s;
max-height: 300px;
box-shadow: 0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084);
ul li {
padding:5px;
}
}
It is because you have max-height value as 300px in your css. So you should remove that to work properly
.autocomplete-ion {
background-color: gray;
position: absolute;
width: 90%;
left: 5%;
top:45px;
overflow-y: auto;
z-index: 10000000;
background-color: #FAFAFA;
transition: 0.8s;
box-shadow: 0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084);
ul li {
padding:5px;
}
Because the height change from element add/remove will not cause a animation.
When elements increasing, the new height is likely to always larger than previous max-height, so when you set a higher max-height, the animation appears from old max-height to new one.
When elements decreasing, if you remove the elements first, then the height will decrease first, without animation, then, when you set the new max-height, it'll only animate part only if new max-height is smaller than decreased height. And if the new max-height is still larger than decreased height, the animation not appears at all.
So you have to first set to the new max-height when new elements is less then old ones, to trigger animation, and set the list to new one(either by removing or create a new list) when animation ends.
var list = $(".autocomplete-ion ul");
var tryAppend = function(newList) {
var curList = $(".autocomplete-ion ul li");
var curLength = curList.length;
var newLength = newList.length;
if (newLength <= 10) {
// If its adding, no need to listen to animation, as the new height will be definetly larger.
// Otherwise,
if (newLength < curLength) {
$(".autocomplete-ion").on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function() {
list.empty().append(newList);
$(this).off();
});
$(".autocomplete-ion").css({'max-height': (30 * newLength) + 'px'});
} else {
$(".autocomplete-ion").css({'max-height': (30 * newLength) + 'px'});
list.empty().append(newList);
}
}
};
var create = function(num) {
var list =[];
var i, li;
for (i = 0; i < num; ++i ) {
li = $("<li>").text("Test li " + (i + 1));
list.push(li);
}
tryAppend(list);
};
$(".cl").click(function() {
var counts = parseInt($(this).data("len"), 10);
create(counts);
});
$(".clear").click(function() {
list.empty();
});
.autocomplete-ion {
background-color: gray;
position: absolute;
width: 90%;
left: 5%;
top:45px;
overflow-y: auto;
z-index: 10000000;
background-color: #FAFAFA;
transition: 0.8s;
max-height: 0px;
box-shadow: 0 3px 1px -2px rgba(0,0,0,.14),0 2px 2px 0 rgba(0,0,0,.098),0 1px 5px 0 rgba(0,0,0,.084);
ul li {
height: 40px;
padding:5px;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="autocomplete-ion">
<ul>
</ul>
</div>
<button class="cl" data-len="1">1</button>
<button class="cl" data-len="5">5</button>
<button class="cl" data-len="10">10</button>
I am writing a slider from scratch, no plugins.
I have my slider working, based on adding the slides together and plus or minus the length of the slider window.
It has become complicated when pagination needs to be added. I can't seem to wrap my head around the logic of the function needed to be written that states.
if button 1 is clicked run the function 1 time and go to slide one.
if button 2 is clicked run the function 2 times and go to slide two. .... and so on..
The issue I see coming from this is if on slide 3 and the button 4 is clicked the function only needs to move once not 4 times!! This is where my head breaks and all logic spills out of my ears.
How do I go about writing something like this?
here is the jsfiddle I have so far. http://jsfiddle.net/r5DY8/2/
Any help would be appreciated.
:: all the code on one page if you don't want to use jsfiddle ::
<!DOCTYPE html>
<html>
<head>
<script src='http://code.jquery.com/jquery-1.9.0.min.js'type="text/javascript"></script>
<link href='http://fonts.googleapis.com/css?family=Marmelad' rel='stylesheet' type='text/css'>
<style type="text/css">
body {
font-family: 'Marmelad', sans-serif;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#slideContainer {
position: relative;
width: 990px;
height: 275px;
float: left;
overflow: hidden;
margin-top:5%;
margin-left:15%;
}
#slideWrap {
width: 3960px;
height: 275px;
position: absolute;
top: 0;
left: 0;
}
.slide {
width: 990px;
height: 275px;
float: left;
}
.slide:first-child { background-color: #009999; }
.slide:nth-child(2) { background-color: #CC0033; }
.slide:nth-child(3) { background-color: #FFFF66; }
.slide:nth-child(4) { background-color: #006699; }
#clickLeft{
color: black;
float: left;
margin: 12% 0% 0 15%;
/*background: url("prev.png") no-repeat;*/
width: 60px;
height: 60px;
cursor: pointer;
list-style: none;
position: absolute;
z-index: 9;
border:1px solid black;/**/
}
#clickRight{
color: black;
float: right;
margin: 12% 0 0 79.5%;
/*background: url("next.png") no-repeat;*/
width: 60px;
height: 60px;
cursor: pointer;
list-style: none;
position: absolute;
border:1px solid black;/**/
}
.dots{
width: 9%;
position: absolute;
top: 310px;
text-align: center;
height: 45px;
padding-top: 5px;
background: white;
left: 43.5%;
border-radius: 8px;
list-style:none;
}
.dots li {
display: inline-block;
list-style:none;
}
.dots li:first-child {
margin-left:-40px;
}
.dots li a{
width: 16px;
height: 16px;
display: block;
background: #ededed;
cursor: pointer;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
-o-border-radius: 20px;
border-radius: 20px;
margin: 5px;
}
.dots li a:hover { background: rgba(0, 0, 0, 0.7); }
.styleDots { background: #a4acb2; }
.active { background: #a4acb2;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
-o-border-radius: 20px;
border-radius: 20px;}
li.pagerItem{
}
</style>
<script type="text/javascript">
$(function(){
var currentSlidePosition = 0;
var slideW = 990;
var allSlides = $('.slide');
var numberOfSlides = allSlides.length;
var marker;
$('.slide').each(function(i) {
listNumber=i+1;
marker = $("<li>");
marker.addClass('pagerItem '+listNumber);
$("<a href='#' ></a>").appendTo(marker);
if (i===0){
marker.addClass('active');
}
marker.appendTo($(".dots"));
});
allSlides.wrapAll('<div id="moveSlide"></div>').css({'float' : 'left','width' : slideW});
$('#moveSlide').css('width', slideW * numberOfSlides);
$('body').prepend('<li class="controls" id="clickLeft"></li>')
.append('<li class="controls" id="clickRight"></li>');
$('.controls').click(function(){
moveSlide(this);
moveSlide(this); // running twice because the function is being called twice
//create a function that says if button 1 is clicked run the function 1 time if button 3 is clicked run the function 3 times..
});
var moveSlide = function(thisobject){
console.log('function run');
if(($(thisobject).attr('id')=='clickRight')) {
if(currentSlidePosition == numberOfSlides-1)currentSlidePosition=0;
else currentSlidePosition++;
var active = $(".active").removeClass('active');
if(active.next() && active.next().length){
active.next().addClass('active');
} else {
active.siblings(":first").addClass('active');
}
} else if($(thisobject).attr('id')=='clickLeft'){
if(currentSlidePosition == 0)currentSlidePosition=numberOfSlides-1;
else currentSlidePosition--;
var active = $(".active").removeClass('active');
if(active.prev() && active.prev().length){
active.prev().addClass('active');
} else {
active.siblings(":last").addClass('active');
}
}
$('#moveSlide').animate({'margin-left' : slideW*(-currentSlidePosition)});
}
});
</script>
</head>
<body>
<div id="slideContainer">
<div id="slideWrap">
<div class="slide">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
</div>
</div>
<ul class="dots"></ul>
</body>
</html>
It's more complicated than just calling the function a number of times. As the animation is asynchronous, you need to call the function again when the animation has finished, not right away.
Add a callback parameter to the function so that it can use that do do something when the animation finishes:
var moveSlide = function (thisobject, callback) {
Add the callback to the animation:
$('#moveSlide').animate({
'margin-left': slideW * (-currentSlidePosition)
}, callback);
Make a function moveTo that will call moveSlide in the right direction, and use itself as callback:
function moveTo(target){
if (target < currentSlidePosition) {
moveSlide($('#clickLeft'), function(){ moveTo(target); });
} else if (target > currentSlidePosition) {
moveSlide($('#clickRight'), function(){ moveTo(target); });
}
}
Bind the click event to the links in the dots. Use the index method to find out which slide you want to go to, and call moveTo to do it:
$('.dots a').click(function(e){
e.preventDefault();
var target = $(this).parent().index();
moveTo(target);
});
Fiddle: http://jsfiddle.net/Guffa/r5DY8/3/
From a purely logical point of view (assumes the existence of two variables - curr_slide_num and butt_num):
for (var i=0; i < Math.abs(curr_slide_num - butt_num); i++) my_func();
Be careful of zero indexing; either treat the first button and first slide as number 0, or neither, else the maths will break down.
This takes no account of the direction the slider should move. I haven't looked at your Fiddle but I guess you would pass direction as an argument to the function. Let's say the function expects direction as its first argument - the string 'left' or 'right'
for (var i=0; i < Math.abs(curr_slide_num - butt_num); i++)
my_func(curr_slide_num < butt_num ? 'left' : 'right');