I am attempting to create my very first jQuery post slider.
The slider has previous and next buttons which offset the top position of the div containing all the post items. ie. increments or decrements the top position value by the '.post-item' height.
I am facing difficulty with a conditional statement to disable the previous and next buttons based on the value of the CSS top property of the div. For example, disable previous button if top position <= 0
I am new to programming and I was hoping to learn by others examples pertaining to my situation, to better grasp the concepts. Any help and guidance on how to best achieve this would be a huge help for me. At the bottom of the post I have included my rather embarrassing progress on one of my attempts.
JavaScript Source
(function ($) {
$(document).ready(function () {
$('.prev-btn').click(function () {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
});
$('.next-btn').click(function () {
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
});
});
})(jQuery);
HTML Markup
<div class="buttons">
<span class="prev-btn ">Up</span>
<span class="next-btn ">Down</span>
</div>
<div class="post-slider">
<div class="posts-body">
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
<div class="post-item">
<h1>Placeholder Text</h1>
</div>
</div>
</div>
Failed Attempt
(function ($) {
$(document).ready(function () {
$('.prev-btn').click(function () {
var selector = document.querySelector(".posts-body");
var offset = selector.offsetTop;
if (selector.css("top") > 0) {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
console.log(offset);
});
$('.next-btn').click(function () {
var selector = document.querySelector(".posts-body");
var offset = selector.offsetTop;
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
console.log(offset);
});
});
})(jQuery);
Thanking you very much for your time and help.
I have managed to find a solution, I am sure the example posted below is full of bad programming techniques(learning something new everyday), however my original question to use an if statement on clicking a button to check div position has been solved.
Note:
The jQuery css() Method returns a string, which was being compared to an integer in the previous example.
JavaScript Source (Solved)
(function ($) {
$(document).ready(function () {
$('.up-btn').click(function () {
var a = parseInt($(".posts-body").css("top"));
if (a === 0) {
$(".posts-body").css("top", "0");
} else {
$(".posts-body").animate({
top: "+=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
});
$('.down-btn').click(function () {
var a = parseInt($(".posts-body").css("top"));
var b = Math.abs(a);
var c = parseInt($(".posts-body").css("height"));
var d = c - (3 * 142);
if (b >= d) {
$(".posts-body").css("top", "d");
} else {
$(".posts-body").animate({
top: "-=142"
}, {"duration": 400, "easing": "easeOutBack"});
}
});
});
})(jQuery);
Sources
CSS-Tricks Link: Check div position with jQuery if/else
Related
One of my ng-views has a next structure
<div class="container-fluid wrapper">
<aside ng-if="asideMenu">
<div ng-include src="'html/partials/stats/aside.html'"></div>
</aside>
<section>
<div ng-include src="'html/partials/stats/grid.html'"></div>
<div ng-include src="'html/partials/stats/tabs.html'"></div>
</section>
where I have a grid and tabs as a major content and if user wants he can open aside bar. The function to open aside bar is
$scope.asideMenu = false;
$scope.aside = function () {
getTree();
var section = document.getElementsByTagName("section");
var aside = document.getElementsByTagName("aside");
$scope.asideMenu = !$scope.asideMenu;
if ($scope.asideMenu == true) {
$(section).animate({
'width': '84%'
}, 500, function () {
$(aside).animate({
'width': '15%'
});
});
}
else {
$(aside).animate({
'width': '0%'
}, 1000, function () {
$(section).animate({
'width': '100%'
});
});
}
};
So currently I'm using jQuery animation to open aside menu and shrink major content.
The question is simple, what is the best way to replace jQuery animation to Angular & CSS animation (without any additional dependencies and libs)??
This is simple example of my page
I'm creating a one page website that acts as a form of book. when the "down" div is clicked, i want the current content div to fadeOut & for the next content div to be shown. I've got it working.. but to a certain extent. Also, I need to use a if statement with length to determine when the user has reached the last div, so that i can remove the down div.
Right now, it isn't working exactly how I want it too. Also I think I need to use next, length etc. Here's a quick example of what I'm working with
HTML
<div class="content>
<h1> page one </h1>
</div>
<div class="content hidden-content>
<h1> page two </h1>
<div>
<div class="content hidden-content>
<h1> last page </h1>
</div>
<div class="hover-wrap>
<div class="down"></div>
</div>
jQuery
$(".hover-wrap").hover(function(){
if (!$(".down").hasClass('animated')) {
$(".down").dequeue().stop().animate({ bottom: "0px" }, 500);
}
}, function() {
$(".down").addClass('animated').animate({ bottom: "-75px" }, 500, "linear", function() {
$(".down").removeClass('animated').dequeue();
});
});
var btnNode = $(".down"),
btnWrap = $(".hover-wrap"),
contentNode = $(".content"),
nextContentNode = contentNode.next(".content"),
endNode = $(".credit"),
fadeInSpeed = 500;
btnNode.on("click", function(){
contentNode.hide();
if (nextContentNode.length){
nextContentNode.fadeIn(fadeInSpeed);
} else {
contentNode.hide();
endNode.fadeIn();
btnWrap.fadeOut();
}
});
Heres a codepen which makes things a little clearer! thanks!
http://codepen.io/Mctowlie/pen/qxdyE
Is it what you want : http://codepen.io/OxyDesign/pen/rykLI ?
JS
$(document).ready(function(){
var btnNode = $(".down"),
btnWrap = $(".hover-wrap"),
pages = $('[data-page]'),
pagesLgth = pages.length,
fadeInSpeed = 500;
btnWrap.hover(function() {
if (!btnNode.hasClass('animated')) {
btnNode.dequeue().stop().animate({
bottom: "0px"
}, 500);
}
}, function() {
btnNode.addClass('animated').animate({
bottom: "-75px"
}, 500, "linear", function() {
btnNode.removeClass('animated').dequeue();
});
});
btnNode.on("click", function(e) {
e.preventDefault();
var currentPage = pages.filter('.active');
currentPage.hide().removeClass('active');
if(currentPage.data('page') < pagesLgth){
currentPage.next('[data-page]').fadeIn(fadeInSpeed).addClass('active');
}else{
$('[data-page="1"]').fadeIn(fadeInSpeed).addClass('active');
}
});
});
Ive been attempting to create my own Javascript slider plugin, (I realise there are many out there, but i wanted to treat it as a learning exercise),
an example can be seen here: http://jsfiddle.net/6GTGU/
the problem I'm having is that the animation goes round once, and then stops, Ive tried to examine this to see what i have done wrong but i can't find any reason for it, if anyone can help me i would be very grateful.
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed"></div>
<div style="background-color: #62ed43"></div>
<div style="background-color: #ed5943"></div>
</div>
JAVASCRIPT
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
sliderItems.each(function( index ) {
$(this).css('z-index', index);
});
window.setInterval(function(){
var maxValue = findMaxZIndex();
var currentItem = sliderItems.filter(function() {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function() {
sliderItems.each(function( index ) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
});
}, 4000);
});
function findMaxZIndex() {
var maxValue = undefined;
$(sliderItems).each(function() {
var val = $(this).css('z-index');
val = parseInt(val, 10);
if (maxValue === undefined || maxValue < val) {
maxValue = val;
}
});
return maxValue;
}
PLUGIN DEMO IN ACTION
You said you want a plugin so here you go.
It even stops on mouseenter. (I personally hate when I cannot stop a gallery by just hovering it.)
I don't understand the need of z-index at all, so you can calmly remove it all from your HTML and don't bother at all.
<div class="cjwFader" id="el1">
<div style="background: red;"> 1 </div>
<div style="background: green;"> 2 </div>
<div style="background: gold;"> 3 </div>
</div>
CSS:
(the only needed, but you can also make jQ apply the children position)
.cjwFader > div {
position: absolute;
}
And finally the plugin:
(function($){
$.fn.cjwFader = function(opts){
// Default Settings
var S = $.extend({
fade: 400,
wait: 2000,
startAt: 0
//, need more? add more.
},opts);
return $(this).each(function(){
var that = $(this),
child = $('>*',that),
nOfChildren = child.length,
sI;
function animate(){
child.eq( S.startAt = ++S.startAt % nOfChildren )
.fadeTo( S.fade,1 )
.siblings().stop().fadeTo(S.fade,0);
}
function loop(){
sI=setInterval( animate, S.wait+S.fade );
}loop();
child.hover(function(e){
return e.type==='mouseenter'? clearInterval(sI) : loop();
}).eq(S.startAt).show().siblings().hide();
});
};
})(jQuery);
Plugin usage:
$(function(){ // DOM ready
// $('#el1').cjwFader(); // Use default plugin settings
$('#el1').cjwFader({ // Let's apply some custom stuff
startAt : 1,
fade : 1000,
wait: 700
});
});
Here is the working slideshow: http://jsfiddle.net/6GTGU/7/
I've updated the HTML slightly to remove the initialization code from your JS. You may decide to revert that back
HTML
<div id="cjwSlider">
<div style="background-color: #6495ed; z-index: 0;"></div>
<div style="background-color: #62ed43; z-index: 1;"></div>
<div style="background-color: #ed5943; z-index: 2;"></div>
</div>
I had to remove a lot of JS code to nail down the problem. I think the current JS is all you may need and don't need to go back to your original one:
var cjwSlider = $('#cjwSlider');
var sliderItems = cjwSlider.children('div');
$(document).ready(function () {
window.setInterval(function () {
var maxValue = $('#cjwSlider').find('div').length - 1;
var currentItem = sliderItems.filter(function () {
return $(this).css('z-index') == maxValue;
});
currentItem.addClass("hiddenDiv").delay(1000).queue(function () {
sliderItems.each(function (index) {
$(this).css('z-index', parseInt($(this).css('z-index')) + 1);
});
currentItem.css('z-index', 0);
currentItem.removeAttr('class');
$(this).dequeue();
});
}, 4000);
});
The crux of the problem was the missing call to dequeue() at the end of the function that was queued up. The function executed fine for the first time but then stayed at the head of the queue and prevented execution of functions queued later on. This is why your animation played for one cycle but not after that.
I'm putting together a quick little status board that shows active and upcoming github issues.
I have them all pulled in and formatted as a simple list and found a nice jQuery plugin that cycles through each item as a sort of slideshow. However, it was requested that it show multiple issues at once to fill up the screen more.
So on each slide swap it would display, say 5 LI items at once versus just 1. And then swap to show the next 5 and so on.
HTML
...
<ul id="issue-list">
<li class="issue"></li>
...
<li class="issue"></li>
</ul>
...
<script type="text/javascript">
$(function() {
$('#issue-list').swapmyli({
swapTime: 900, // Speed of effect in animation
transitionTime: 700, // Speed of Transition of ul (height transformation)
time: 4000, // How long each slide will show
timer: 1, // Show (1) /Hide (0) the timer.
css: 0 // Apply plugin css on the list elements.
});
});
</script>
JS
(function(e) {
e.fn.swapmyli = function(t) {
function s() {
var e = i.parent().find(".timer span");
e.animate({
width: "100%"
}, r);
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
i.animate({
height: n
}, t.transitionTime);
i.find("li").hide();
e.animate({
width: "0%"
}, 60);
i.find("li:first").remove().appendTo(i).fadeIn(t.swapTime)
}
var n = {
swapTime: 300,
transitionTime: 900,
time: 2e3,
timer: 1,
css: 1
};
var t = e.extend(n, t);
var r = t.time - t.swapTime;
var i = this;
i.wrap('<div class="swapmyli clearfix"></div>');
i.after('<div class="timer"><span></span></div><br class="clear" />');
e(window).load(function() {
var e = i.find("li:first").outerHeight(true);
i.height(e);
i.find("li").hide();
s()
});
if (t.timer == 0) {
i.parent().find(".timer").hide()
}
if (t.css == 0) {
i.parent().addClass("nocss")
}
setInterval(s, t.time)
}
})(jQuery)
I'm not sure if outerHeight() will function correctly with slice, but you may try changing these lines:
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
To the following:
var n = i.find("li").slice(0, 4).outerHeight(true);
i.find("li").slice(0, 4).fadeOut(120);
That's sort of a quick answer, but hopefully you're catching my drift. Probably need to play around with it a little bit :)
How can I implement custom-looking scrollbars in YUI containers?
Using YUI3, you can change the scroll bars of an internal frame. If you ment the external scroll bars of the actual browser -- just drop the idea. It is not worth any headache. Too many browsers simply won't let you.
Here is example of an internal setup skinned in YUI 3.4
CSS:
<style type="text/css" media="screen">
#video-playlist-scroll-bar-container{text-align:right}
#video-playlist-scroll-bar{position:relative;width:14px;border:1px solid #e0e0e0;height:379px;margin:0 auto}
#drag-handle-container-wrap{position:relative;top:17px;bottom:17px;left:0;width:14px;height:345px}
#drag-handle-container-wrap .yui3-slider-content{position:absolute;top:0;left:0}
#drag-handle-draggable{position:absolute;left:0;background-color:#eaeaea;text-align:center;cursor:move;width:14px}
#drag-handle-up,#drag-handle-down{position:absolute;display:block;width:14px;height:16px;cursor:pointer}
#drag-handle-up{top:0;left:0}
#drag-handle-down{bottom:0;left:0}
</style>
HTML:
<div class="yui3-u-1-12" id="video-playlist-scroll-bar-container">
<div id="video-playlist-scroll-bar">
<div id="drag-handle-up"><img src="/assets/images/rebrand/drag-arrow-top.gif"></div>
<div id="drag-handle-container-wrap">
<span class="yui3-widget yui3-sliderbase yui3-slider" style=""><span class="yui3-slider-content yui3-slider-y"><div id="drag-handle-container" style="height: 345px; ">
<div id="drag-handle-draggable" class="yui3-dd-draggable" style="top: 0px; left: 0px; ">
<img src="/assets/images/rebrand/drag-handle.gif" width="9" height="100">
</div></div></span></span></div>
<div id="drag-handle-down"><img src="/assets/images/rebrand/drag-arrow-bottom.gif"></div>
</div>
</div>
YUI:
YUI().use("base","node",'slider',function(Y){
var CLICK = "click",
ID = "#",
_scrollingBuffer = 75,
_maxScrollRegion = 0;
// Slider
var _tmp = Y.one(ID+'playlist-container'+" .video-playlist-item"),
_nodeBuffer = Y.one(ID+'playlist-container').get('children').slice(-5),
_bufferFunction = function() {
var _height = 0;
_nodeBuffer.each(function(i) {
_height = _height + i.get('region').height;
});
return _height;
},
_buffer = _bufferFunction(),
_maxScrollRegion = Y.one(ID+'playlist-container').get("region").height - _buffer;
var listScroll = new Y.Slider({
axis : 'y',
min : 0, // reverse min and max to make the top
max : _maxScrollRegion,
value : 0,
length: '345px'
});
listScroll.renderRail = function () {
return Y.one( "#drag-handle-container" );
};
listScroll.renderThumb = function () {
return this.rail.one( "#drag-handle-draggable" );
};
listScroll.render( "#drag-handle-container-wrap" );
listScroll.on('valueChange', Y.bind(function (e) {
//scroll something?
}));
Y.one("#drag-handle-up").on(CLICK, Y.bind(function (e) {
e.preventDefault();
if (listScroll.get('value') >= _scrollingBuffer) {
listScroll.setValue(listScroll.get('value') - _scrollingBuffer);
} else {
listScroll.setValue(0);
}
}));
Y.one("#drag-handle-down").on(CLICK, Y.bind(function (e) {
e.preventDefault();
if (listScroll.get('value') <= Math.round(_maxScrollRegion - _scrollingBuffer)) {
listScroll.setValue(listScroll.get('value') + _scrollingBuffer);
} else {
listScroll.setValue(_maxScrollRegion);
}
}));
});
Note, this is pretty much a copy/paste from a project of mine -- with a quick removal of any identifiers. It may not work as a copy/paste .. but you'll get the jist.
Final product:
You could go even further by not using a "overflow: auto;" CSS and use the YUI 3 ScrollView along with it. I use the Paged version on YUI myself. It is easy enough to do a up & down by page & percentages.
Hopefully this is what you were looking for, not the browser's scroll bar.