Individually Animate Each Character on a Page - javascript

Currently I have a mostly working script I've hobbled together. I'm doing this in multiple phases to make it as modular as possible.
//This grabs every element on page.
$('body').find('*').each(function(){
//This filters for text nodes only
$(this).contents().filter(function() { return this.nodeType == Node.TEXT_NODE; }).each(function(){
//Wraps each text node in a span.
$(this).wrap("<span class='text'></span>")
});
})
//
$('.text').each(function(){
//Splits each text node into a character array and wraps each char in a span.
var test = $(this).text().split('');
var curStr = '';
for(var i = 0; i < test.length; i++){
if(test[i] != " " || test[i] != ''){
curStr = curStr + "<span class='char'>" +test[i] + "</span>";
} else {
curStr = curStr + test[i];
}
}
$(this).html(curStr);
})
My issue come from trying to style the elements at random. I'm using the following code to do so:
setInterval(function(){
$($('.char')[Math.floor((Math.random()*$('.char').length)+1)]).each(function(){
$(this).css('color', 'green');
$(this).css('position', 'absolute');
$(this).css('background-color', 'red');
$(this).animate({
top: $(window).height + 'px'
}, 1000, 'swing', function(){$(this).remove()});
})
}, 100)
The issue with this is, it manages to apply the color styling, but my position and animate don't seem to be working.

The jQuery height() method requires parentheses:
Change this:
top: $(window).height + 'px'
To this:
top: $(window).height() + 'px'
Working Example

Related

Dynamically shortened text with “Read More” link using javascript

I have a text and I want to dynamically shortened the text with “Read More” link using JavaScript. I use the following JavaScript code:
var limitDesc = -1;
function ResponsiveDesc() {
//var limitDesc = 100;
//var isHTML = RegExp.prototype.test.bind(/(<([^>]+)>)/i);
var chars = $("#ResponsiveDescription").html();
if (chars.length > limitDesc) {
var visiblePart = $("<span> " + chars.substr(0, limitDesc - 1) + " </span>");
var dots = $("<span class='dots'>... </span>");
var hiddenPart = $("<span class='more'>" + chars.substr(limitDesc - 1) + "</span>");
var readMore = $("<span class='read-more'>More</span>");
readMore.click(function () {
$(this).prev().remove(); // remove dots
$(this).next().show(); //show hiddenPart
$(this).remove(); // remove readMore
});
$("#ResponsiveDescription").empty()
.append(visiblePart)
.append(dots)
.append(readMore)
.append(hiddenPart);
}
}
$(document).ready(function () {
if (limitDesc > 0 && $(window).width() < 500) {
ResponsiveDesc();
}
});
The main problem is that I don't what this code to cut my text in the middle of a word or a link. What is the best way to solve this problem ?
I can manually change the "limitDesc" variable on each page but when the content of the page is dynamic, it's impossible.
Thanks you in advance.
You can split the string at the last whitespace before your length limit.
You can determine it using lastIndexOf():
limitDesc = chars.lastIndexOf(" ", limitDesc);
http://www.w3schools.com/jsref/jsref_lastindexof.asp

Setting up an array to handle size conditions

I've got the following code. I am working on an array. I found a javascript array instructions..if this is wrong, I'd love help to find out if there is a jQuery version of this.
My issue comes into play when I am trying to implement an if() and else if() conditions to the array. I am using i (variable) to count items in array.
It is saying that there is an issue on the line that reads else if(width <= Sizes[i]) { $(element).attr('src', 'images/' + Sizes[i] + '/' + name[name.length - 1]) }
Also, it appears that the array isn't working at all. Its pulling the default image.
I am probably doing this wrong. I am doing this trying to figure out how arrays work and implementing them into a code I already have. Can someone please help solve this? It isn't working. The code works perfectly without the array, so it is something in the array.
$(document).ready(function() {
window.onresize = resize;
function resize() {
var img = $('img.resizable');
var width = $(window).innerWidth();
var Sizes, sLength, i;
img.each(function(index, element) {
var name = element.src.split('/') // Split is a native javascript function, which 'splits' the string into an array with the components
Sizes = [2880, 1920, 1000, 600];
sLength = Sizes.length;
for (i = 0; i < sLength; i++) {
if (i == 0) {
if (width <= Sizes[i]) {
$(element).attr('src', 'images/' + Sizes[i] + '/' + name[name.length - 1])
}
}
if (i > 0) {
else if (width <= Sizes[i]) {
$(element).attr('src', 'images/' + Sizes[i] + '/' + name[name.length - 1])
}
}
} else {
$(element).attr('src', 'images/2880/' + name[name.length - 1])
}
})
}
resize();
});
The actual script I am trying to convert
$(document).ready(function() {
window.onresize = resize;
function resize() {
var img = $('img.resizable');
var width = $(window).innerWidth();
img.each(function(index, element) {
var name = element.src.split('/') // Split is a native javascript function, which 'splits' the string into an array with the components
if(width <= 600) {
$(element).attr('src', 'images/600/' + name[name.length - 1]) // This name[name.length -1] trick is being used to select the 'last value in the string' based on the length of the string.
}
else if(width <= 1000) {
$(element).attr('src', 'images/1000/' + name[name.length - 1])
}
else if(width <= 1920) {
$(element).attr('src', 'images/1920/' + name[name.length - 1])
}
else {
$(element).attr('src', 'images/2880/' + name[name.length - 1])
}
})
}
resize();
});
Here's a solution that simplifies matters by using Array#filter to select the appropriate width; the appropriate size will sit in the first position of the sizes array:
$(document).ready(function() {
window.onresize = resize;
resize();
});
function resize() {
// use $.each to iterate over each element
$('img.resizable').each(function(index, element) {
// get the image name directly
var name = element.src.substring(element.src.lastIndexOf('/'));
// let's whittle down sizes to *only* those that fit our screen width
var sizes = [600, 1000, 1920, 2880].filter(function(s){
return window.innerWidth < s || s == 2880;
});
// update the image with whatever size is in the first position
$(element).attr('src', 'images/' + sizes[0] + name);
});
}
We can move the resize function definition outside of your on ready handler, to make it globally accessible. We can dispense with use of split to just find whatever is after the last / (the image name). And we can avoid using loops and if statements with breaks, which tend to be difficult to read and maintain.
This is a bit verbose and follows your array starting with the largest value which I used instead of hard coding that for the "largest" (last) conditional. Remove the console logs prior to deployment.
$(document).ready(function() {
window.onresize = resize;
var sizes = [2880, 1920, 1000, 600];
function resize() {
console.log('si');
var img = $('img.resizable');
var width = $(window).innerWidth();
img.each(function(index, element) {
var name = element.src.split('/');
name = name[name.length - 1];
var setto = 0;
for (var i = sizes.length; i >= 0; i--) {
console.log(i,width,setto, sizes[i]);
if (width <= sizes[i]) {
setto = sizes[i];
break;
}
}
setto = width >= sizes[0] ? sizes[0] : setto;
$(element).attr('src', 'images/' + setto + '/' + name);
});
}
resize();
});
You are referencing Sizes array using lowercase s at sizes[i], where sizes is not defined
I hope this could solve your problem:
$(window).on('resize', function (e) {
var img = $('img.resizable');
var width = $(window).innerWidth();
var Sizes, sLength, i;
img.each(function (index, element) {
var name = element.getAttribute('src').split('/') // Split is a native javascript function, which 'splits' the string into an array with the components
Sizes = [2880, 1920, 1000, 600].sort((a, b) => {return a - b;});
sLength = Sizes.length;
for (i = 0; i < sLength; i++) {
if (width <= Sizes[i]) {
$(element).attr('src', 'images/' + Sizes[i] + '/' + name.pop())
console.log('New src for image N. ' + index + ' is: ' + $(element).attr('src'));
break;
}
}
});
});
$(function () {
// simulate a resize on dom ready: for testing
$(window).trigger('resize');
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<img class="resizable" src="images/100/nameofimage1.png">
<img class="resizable" src="images/100/nameofimage2.png">
You want something like this probably:
sort_array_small_to_large(Sizes)
for (i = 0; i < Sizes.length; i++)
{
if (width <= Sizes[i])
{
size = Sizes[i]
break
}
}
$(element).attr('src', 'images/' + size + '/' + name[name.length - 1])

Need Jquery chaning My Background image in a DIV

I`m starting level in jquery , but i have the concept of my idea , i have a #SlidShow div , all i need to change the css property ( background-image ) every 3 second , i have i think 4 image , so my concept is (( Make New Array with images link )) and change the .css( background-image ) of this div with this array every 3s ..
i hope that my concept be right :) , can any one help me with that
#('SlideShow').css('background-image', (Array /* Cant handle it */));
var array = ['url(a.png)', 'url(b.png)', 'url(c.png)', 'url(d.png)'];
var i = 0;
function setBackgroundImage() {
$('#SlideShow').css('background-image', array[i]);
i = i % array.length;
}
setBackgroundImage();
setInterval(setBackgroundImage, 3000);
You already got your answer. Just wanted to add that jQuery is a bit overkill if this is all you want to do, but it's probably not.
Here is a pure javascript solution:
http://jsfiddle.net/2BQV5/2/
var arr = ['http://placekitten.com/200/300','http://placekitten.com/200/301','http://placekitten.com/200/302'];
window.onload = function ()
{
index = 0;
var c = document.getElementById('cat');
setInterval(function() {
if(index > arr.length-1) {index = 0}
c.style.backgroundImage='url(' + arr[index++] + ')';
}, 3000);
}
Have fun!
Edit
However for the second request in the comments, to have to pictures fade, jQuery is probably more suited.
Here is one way to achieve the fading effect:
http://jsfiddle.net/8jWT5/
var arr = ['http://placekitten.com/200/300','http://placekitten.com/200/301','http://placekitten.com/200/302'];
$(document).ready(function() {
var c = $('#cat');
fade = document.createElement('div');
$(fade).attr('style','position: absolute; width:' + c.width() + 'px; height:' + c.height() + 'px;').attr('id','fade').hide();
c.append(fade);
var index = 0;
setInterval(function () {
$('#fade').css('background-image', 'url(' + arr[index] + ')').fadeIn(500,function() {
c.css('background-image', 'url(' + arr[index++] + ')');
if(index > arr.length-1) {index = 0}
$(this).hide();
});
}, 3000);
});

JavaScript: How do I stack rectangle elements tetris style, without using plugins?

I'm making a scheduling calendar. The events are horizontal blocks (Google Cal has vertical ones). And because I have loads of events in one date I want the events to stack onto eachother without wasting any space, like this:
I did find plugins:
http://masonry.desandro.com/
http://isotope.metafizzy.co/
http://packery.metafizzy.co/
But I'm not keen on using a 30kb plugin just to do this simple thing.
To clarify: because this is a timeline, the div-events cannot move left/right, but must fit itself vertically amongst other div-events.
My own solution is a 2.6kb (commented) jQuery script, that uses absolute positioning for events and a div as a container for each row.
This script generates randomly size bars. Each new bar checks for space in each row from top-down. I'm using percentages, because that way calculating bar position against time will be easy (100% / 24h).
http://jsfiddle.net/cj23H/5/
Though works and is efficient enough, it feels bulky. You're welcome to improve.
jQuery code from my jsfiddle:
function rand() {
return Math.floor(Math.random() * 101);
}
function get_target_row(width, left) {
var i = 0;
var target_found = false;
// Loop through all the rows to see if there's space anywhere
while (target_found === false) {
// Define current row selector
var target_i = '.personnel#row' + i;
// Add row if none
if ($(target_i).length === 0) {
$('body').append('<div class="personnel" id="row' + i + '"></div>');
}
// See if there's space
if ($(target_i).children().length === 0) {
target_found = $(target_i);
} else {
var spaceFree = false;
// Check collision for each child
$(target_i).children().each(function () {
// Get left and right coordinates
var thisWidthPx = parseFloat($(this).css('width'), 10);
var thisWidthParentPx = parseFloat($(this).parent().css('width'), 10);
var thisWidth = (thisWidthPx / thisWidthParentPx * 100);
var thisLeftPx = parseFloat($(this).css('left'), 10);
var thisLeftParentPx = parseFloat($(this).parent().css('left'), 10);
var thisLeft = (thisLeftPx / thisWidthParentPx * 100);
var thisRight = thisLeft + thisWidth;
var right = left + width;
// Sexy way for checking collision
if ((right > thisLeft && right < thisRight) || (left < thisRight && left > thisLeft) || (thisLeft > left && thisLeft < right) || (thisRight < right && thisRight > left)) {
spaceFree = false;
return false;
} else {
spaceFree = true;
}
});
// If no children have collided break the loop
if (spaceFree === true) {
target_found = $(target_i);
}
}
i++;
}
// If after all the while loops target is still not found...
if (target_found === false) {
return false;
}
// Else, if target is found, return it.
return target_found;
}
// Generate random bars
for (var i = 0; i < 10; i++) {
var width = rand()/2;
var left = rand()/2;
var right = left + width;
var target = get_target_row(width, left);
target.append('<div class="block" style="width:' + width + '%;position:absolute;left:' + left + '%;background-color:rgba(' + rand() + ',' + rand() + ',' + rand() + ',0.4)" id="bar'+i+'">' + 'b' + i + '</div>');
}
CSS:
.block {
position: absolute;
background-color: rgba(200, 100, 100, 0.4);
height: 32px;
}
.personnel {
position: relative;
float: left;
width: 100%;
height: 33px;
}

Turning Javascript into jQuery

Hi there Stack Overflow,
I'm new at learning jQuery and just trying to condense some sample code down, how would I go about the following.
On mouseover of #navweb, select all elements with a class of .web and then change the background of each of these elements to url(back/"+ i +".png) where i is the JS loop, and then fadeIn these new backgrounds.
Here's the JS i have at current which works (except for the fadeIn)
function showweb() {
for(var i=1; i < 45; i++){
var el = document.getElementById("im"+(i));
if(el && /web/.test( (el ||{}).className)){
el.style.backgroundImage = "url(back/"+ i +"col.png)";}
}
}
function hideweb() {
for(var i=1; i < 45; i++){
var el = document.getElementById("im"+(i));
if(el && /web/.test( (el ||{}).className)){
el.style.backgroundImage = "url(back/"+ i +".png)";}
}
}
I started and got to something like this but it doesn't work, becasue i know its not complete, can you use counters in jQuery?
$('#navweb').mouseover(function(){
var i = 1;
$(".web").each(function(){
$(this).css('background-image', 'url(back/" + i + ".col.png)');
i += 1;
});
});
Many thanks to all replies.
EDIT:
Thanks to all replies, Guffa's proved the most ideal and condensed for my use; I have also added the fadeIn() method but doesn't seem to be triggering on the mouseover?
$('#navweb').mouseover(function(){
$(".web").each(function(){
var i = parseInt(this.id.substr(2));
$(this).css('background-image', 'url(back/' + i + 'col.png)').fadeIn(1000);
});
});
You can get the number from the id of the element:
$('#navweb').mouseover(function(){
$(".web").each(function(){
var i = parseInt(this.id.substr(2));
$(this).css('background-image', 'url(back/' + i + '.col.png)');
});
});
You had a small mistake here: 'url(back/" + i + ".col.png)', it should be like I wrote bellow with single quotes.
$('#navweb').mouseover(function(){
var i = 1;
$('.web').each(function(){
$(this).css('background-image', 'url(back/' + i + '.col.png)');
i += 1;
});
});

Categories

Resources