I have a group of list items that I control through "Next" and "Prev" buttons. The code shows five list items at a time, if there are more you can click "Next" and you'll see another five - if you click "Prev" you'll see the previous five...pretty simple operation and it works. You can see a live example at: http://joshrodg.com/hallmark/events/.
The javascript I am using is:
$(document).ready(function () {
var $li = $('.eo-events li');
$li.hide().filter(':lt(5)').show()
var x = 5;
$('#next, #prev').click(function () {
var m = this.id === 'prev' ? 'first' : 'last';
var $m = $li.filter(':visible')[m]()[this.id + 'All'](":lt(" + x + ")");
if ( $m.length == 0 ) return;
$li.hide();
$m.show();
});
});
http://jsfiddle.net/479Fr/
What I'd like to do is have the items fade-in instead of just appearing...kind of like: https://codepo8.github.io/simple-carousel/carousel-pointer-events.html (or something similar)
I know there are some carousels out there that can do this, but I don't need something that bulky, especially since the functionality already works with such a small amount of code.
Is there a simple modification I can make to what I'm already using to accomplish something like this?
Thanks,
Josh
Use the JQuery .fadein/out to have fading animations
http://api.jquery.com/fadein/
Like that :
$(document).ready(function () {
var $li = $('#myList li');
$li.hide().filter(':lt(5)').show()
var x = 5;
$('#next, #prev').click(function () {
var m = this.id === 'prev' ? 'first' : 'last';
var $m = $li.filter(':visible')[m]()[this.id + 'All'](":lt(" + x + ")");
if ( $m.length == 0 ) return;
var time = 250;
$li.fadeOut(time);
setTimeout( function(){
$m.fadeIn(time);
}, time);
});
});
Related
I am trying to accomplish an infinite loop of items inside 1 main div.
The idea is to show part of the items, then slide the left one outside of the screen, whilst another is added from the right side of the screen.
The following function is working, but the animate method doesn't work, it just changing the css without animating it.
Am I doing it wrong?
Also any better approach would be welcome. I tried to search jQuery solutions but they didn't work well for me so i wanted to create another one.
jQuery(document).ready(function() {
var items = jQuery('.companies-logos div');
var temp;
var item_width = 0;
if(items.length > 9) {
items.slice(9).remove();
setInterval(function(){
jQuery('.companies-logos').append(items[9]);
items[9].style.marginLeft = '0';
item_width = items[0].offsetWidth + 12.5;
jQuery(items[0]).animate({marginLeft: '-' + item_width + 'px'}, 2000);
// items[0].style.marginLeft = '-' + item_width + 'px';
temp = items[0];
jQuery(items[0]).remove();
items.splice(0, 1);
items.push(temp);
// jQuery(items[items.length-1]).css('transition', 'all 2500ms');
}, 2500);
}
});
For those interested in achieving the wanted result from above:
$(function(){
setInterval(function(){
var item_width = $('.companies-logos ul li:first-child').width() + 25;
$(".companies-logos ul li:first-child").animate({"margin-left": -item_width}, 1500, function(){
$(this).css("margin-left",25).appendTo(".companies-logos ul");
});
}, 2000);
});
I'm currently working on a project where a custom slider was needed and i quickly grabbed a neat looking tutorial of the web and went away and staticly it all works great.
Now i want to be able to put several sliders on my page and therefore need to add the controls dynamicly rather than just selecting a certain slider with jquery like I've done below.
This is my code with comments added to explain what im trying to achieve:
var Slider = function() { this.initialize.apply(this, arguments) };
Slider.prototype = {
initialize: function(slider) {
this.ul = slider.children[2];
this.li = this.ul.children;
this.nav = slider.children[3]; //Why cant i use .append on this element?
// make <ul> as large as all <li>’s
this.ul.style.width = (100 * this.li.length) + '%';
// set width of the li's
for(i = 0; i < this.li.length; i++) {
this.li[i].style.width = (100 / this.li.length) + '%';
$(".slider-nav").append( '<div class="slider-dot"></div>'); //Want to make it a this.nav or something similar instead of an external selector
//console.log(this.nav);
}
this.currentIndex = 0;
},
goTo: function(index) {
if (index < 0 || index > this.li.length - 1)
return;
// move <ul> left
this.ul.style.left = '-' + (100 * index) + '%';
this.currentIndex = index
},
goToPrev: function() {
this.goTo(this.currentIndex - 1)
},
goToNext: function() {
this.goTo(this.currentIndex + 1)
}}
var sliders = [];
$('.slider').each(function() {
sliders.push(new Slider(this));
});
//Find a way to implement theese 2 within the slider function, how to find out what position in the array a slider has?
$(".prev-btn").click(function() {
sliders[0].goToPrev();
});
$(".next-btn").click(function() {
sliders[0].goToNext();});
The marks up for the slider looks like this: http://puu.sh/hAUH1/a865792137.png
I managed to get it done by defining this as another var
var sliderEle = this;
I could then call it like this:
$(this.prev).click(function(e) {
e.preventDefault();
sliderEle.goToPrev();
});
with prev and next defined like this:
this.prev = slider.children[0];
this.next = slider.children[1];
I'm trying to create kind of runway of lights and here's what it looks like now
http://jsfiddle.net/7NQvq/
var divs = document.querySelectorAll('div');
var index = 0;
setInterval(function(){
if(index > divs.length+20){
index = 0;
}
if(divs[index-1]){
divs[index-1].className = '';
}
if(divs[index]){
divs[index].className = 'active';
}
index++;
}, 50);
What I don't like about it is that it's completely inflexible and hard to adjust. Furthermore it also runs additional 20 empty cycles which is wrong. Is there a better way to achieve it (preferrably pure JS)?
It seemes that there must be some combination of setInterval and setTimeout but I just can't make it work.
I've made some adjustments to use a CSS animation rather than messing around with transitions and class toggling.
Updated Fiddle
All the JavaScript does now is define the animation delay for each dot.
You can adjust:
The animation delay - I just have i/10, but you could make it i/5, i/20... experiment!
The animation duration - it's set to 1s in my Fiddle, but try shorter and longer to see what happens
The 50% that indicates when the light has faded out
How about
function cycle(selector, cssClass, interval) {
var elems = document.querySelectorAll(selector),
prev = elems[0],
index = 0,
cssClassRe = new RegExp("\\s*\\b" + cssClass + "\\b");
if (elems.length === 0) return;
return setInterval(function () {
if (prev) prev.className = prev.className.replace(cssClassRe, "");
index %= elems.length;
elems[index].className += " " + cssClass;
prev = elems[index++];
}, interval);
}
and
var runwayIntval = cycle("div", "active", 100);
and at some point
clearInterval(runwayIntval);
See: http://jsfiddle.net/arNY8/1/
Of course you could argue that toggling a CSS class is a little limited. You could work with two callback functions instead: one to switch on a freely definable effect, one to switch it off:
function cycle(elems, enable, disable, interval) {
var prev = elems[0], index = 0;
if (elems.length === 0) return;
return setInterval(function () {
index %= elems.length;
if (prev) disable.call(prev);
enable.call(elems[index]);
prev = elems[index++];
}, interval);
}
and
var cycleIntval = cycle(
document.querySelectorAll("div"),
function () {
this.className += " active";
},
function () {
this.className = this.className.replace(/\s*\bactive\b/, "");
},
100
);
I have a word counter running on a DIV and after typing in a few words, the page crashes. The browser continues to work (par scrolling) and no errors are showing in Chrome's console. Not sure where I'm going wrong...
It all started when I passed "wordCount(q);" in "keyup". I only passed it there as it would split-out "NaN" instead of a number to countdown from.
JS:
wordCount();
$('#group_3_1').click(function(){
var spliced = 200;
wordCount(spliced);
}) ;
$('#group_3_2').click(function(){
var spliced = 600;
wordCount(spliced);
}) ;
function wordCount(q) {
var content_text = $('.message1').text(),
char_count = content_text.length;
if (char_count != 0)
var word_count = q - content_text.replace(/[^\w ]/g, "").split(/\s+/).length;
$('.word_count').html(word_count + " words remaining...");
$('.message1').keyup(function() {
wordCount(q);
});
try
{
if (new Number( word_count ) < 0) {
$(".word_count").attr("id","bad");
}
else {
$(".word_count").attr("id","good");
}
} catch (error)
{
//
}
};
HTML:
<input type="checkbox" name="entry.3.group" value="1/6" class="size1" id="group_3_1">
<input type="checkbox" name="entry.3.group" value="1/4" class="size1" id="group_3_2">
<div id="entry.8.single" class="message1" style="height: 400px; overflow-y:scroll; overflow-x:hidden;" contenteditable="true"> </div>
<span class="word_count" id="good"></span>
Thanks in advanced!
This is causing an infinite loop if (new Number(word_count) < 0) {.
Your code is a mess altogether. Just study and start with more basic concepts and start over. If you want to describe your project to me in a comment, I would be glad to show you a good, clean, readable approach.
Update:
Part of having a good architecture in your code is to keep different parts of your logic separate. No part of your code should know about or use anything that isn't directly relevant to it. Notice in my word counter that anything it does it immediately relevant to its word-counter-ness. Does a word counter care about what happens with the count? Nope. It just counts and sends the result away (wherever you tell it to, via the callback function). This isn't the only approach, but I just wanted to give you an idea of how to approach things more sensefully.
Live demo here (click).
/* what am I creating? A word counter.
* How do I want to use it?
* -Call a function, passing in an element and a callback function
* -Bind the word counter to that element
* -When the word count changes, pass the new count to the callback function
*/
window.onload = function() {
var countDiv = document.getElementById('count');
wordCounter.bind(countDiv, displayCount);
//you can pass in whatever function you want. I made one called displayCount, for example
};
var wordCounter = {
current : 0,
bind : function(elem, callback) {
this.ensureEditable(elem);
this.handleIfChanged(elem, callback);
var that = this;
elem.addEventListener('keyup', function(e) {
that.handleIfChanged(elem, callback);
});
},
handleIfChanged : function(elem, callback) {
var count = this.countWords(elem);
if (count !== this.current) {
this.current = count;
callback(count);
}
},
countWords : function(elem) {
var text = elem.textContent;
var words = text.match(/(\w+\b)/g);
return (words) ? words.length : 0;
},
ensureEditable : function(elem) {
if (
elem.getAttribute('contenteditable') !== 'true' &&
elem.nodeName !== 'TEXTAREA' &&
elem.nodeName !== 'INPUT'
) {
elem.setAttribute('contenteditable', true);
}
}
};
var display = document.getElementById('display');
function displayCount(count) {
//this function is called every time the word count changes
//do whatever you want...the word counter doesn't care.
display.textContent = 'Word count is: '+count;
}
I would do probably something like this
http://jsfiddle.net/6WW7Z/2/
var wordsLimit = 50;
$('#group_3_1').click(function () {
wordsLimit = 200;
wordCount();
});
$('#group_3_2').click(function () {
wordsLimit = 600;
wordCount();
});
$('.message1').keydown(function () {
wordCount();
});
function wordCount() {
var text = $('.message1').text(),
textLength = text.length,
wordsCount = 0,
wordsRemaining = wordsLimit;
if(textLength > 0) {
wordsCount = text.replace(/[^\w ]/g, '').split(/\s+/).length;
wordsRemaining = wordsRemaining - wordsCount;
}
$('.word_count')
.html(wordsRemaining + " words remaining...")
.attr('id', (parseInt(wordsRemaining) < 0 ? 'bad' : 'good'));
};
wordCount();
It's not perfect and complete but it may show you direction how to do this. You should use change event on checkboxes to change wordsLimit if checked/unchecked. For styling valid/invalid words remaining message use classes rather than ids.
I think you should use radio in place of checkboxes because you can limit 200 or 600 only at a time.
Try this like,
wordCount();
$('input[name="entry.3.group"]').click(function () {
wordCount();
$('.word_count').html($(this).data('val') + " words remaining...");
});
$('.message1').keyup(function () {
wordCount();
});
function wordCount() {
var q = $('input[name="entry.3.group"]:checked').data('val');
var content_text = $('.message1').text(),
char_count = content_text.length;
if (char_count != 0) var word_count = q - content_text.replace(/[^\w ]/g, "").split(/\s+/).length;
$('.word_count').html(word_count + " words remaining...");
try {
if (Number(word_count) < 0) {
$(".word_count").attr("id", "bad");
} else {
$(".word_count").attr("id", "good");
}
} catch (error) {
//
}
};
Also you can add if your span has bad id then key up should return false;
See Demo
This is the code I have, now what it needs to do is increase the integer after the class name 'icon-' so that on each click the 'icon-' class gets a higher integer value ex. click -> 'icon-2', click -> 'icon-3' and so forth.
Bare in mind that the current icon shown to the user is 'icon-1'.
Also, is there a way for me to alert if it hits 'icon-10' or prevent it from trying to go further than 'icon-10' or below 'icon-1'.
$(function () {
a = 2,
b = '',
$('.icon-step-backward').click(function(){
$('#slider').removeClass();
$('#slider').addClass('icon-' - a);
});
$('.icon-step-forward').click(function(){
$('#slider').removeClass('icon-');
$('#slider').addClass('icon-' + a);
});
});
$('.icon-step-backward, .icon-step-forward').click(function () {
var s = $(this).hasClass('icon-step-backward') ? -1 : 1;
$('#slider').prop('className', function (_, p) {
return p.replace(/\d+/g, function (n) {
var j = +n + s;
return j <= 10 && j >= 1 ? j : n;
});
});
});
http://jsfiddle.net/Mwcbp/
$(function () {
var classes=["icon-1","icon-2","icon-3","icon-4","icon-5","icon-6"
,"icon-7","icon-8","icon-9","icon-10"];
var classCounter=0;
$('.icon-step-backward, .icon-step-forward').click(function () {
//caching slider object
var $slider = $('#slider'),
s = $(this).hasClass('icon-step-backward') ? -1 : 1,
tmp=counter+s,
disableButton=(s==-1)?'.icon-step-backward':'.icon-step-forward',
enableButton=(s==-1)?'.icon-step-forward':'.icon-step-backward';
$(enableButton).show();
if(tmp<classes.length && tmp>0){
$slider.removeClass(classes[counter]);
counter=counter+s;
$slider.addClass(classes[counter]);
}else{
$(disableButton).hide();
}
});
});
If you have multiple .icon-step buttons having to manipulate multiple slider (#slider suggest otherwise) than you can add the classCounter as $("#slider").data to be used specifically for this slider.