Quicksand jquery plugin enlarging elements as they ease. Why? - javascript

I'm currently trying to use Quicksand, a jquery plugin that allows you to animate elements on the page by hiding and showing certain elements based on tags. I have that working just fine. My problem is that as the elements are easing, they enlarge while they're moving. Once they settle in their places, they shrink to the proper size, but it looks awfully strange and I'd like to work out why this is happening in the first place.
Here is the main.js file that has my preferences for quicksand:
$(document).ready(function() {
// get the action filter option item on page load
var $filterType = $('#filterOptions li.active a').attr('class');
// get and assign the ourHolder element to the
// $holder varible for use later
var $holder = $('ul.ourHolder');
// clone all items within the pre-assigned $holder element
var $data = $holder.clone();
// attempt to call Quicksand when a filter option
// item is clicked
$('#filterOptions li a').click(function(e) {
// reset the active class on all the buttons
$('#filterOptions li').removeClass('active');
// assign the class of the clicked filter option
// element to our $filterType variable
var $filterType = $(this).attr('class');
$(this).parent().addClass('active');
if ($filterType == 'all') {
// assign all li items to the $filteredData var when
// the 'All' filter option is clicked
var $filteredData = $data.find('li');
}
else {
// find all li elements that have our required $filterType
// values for the data-type element
var $filteredData = $data.find('li[data-type~=' + $filterType + ']');
}
// call quicksand and assign transition parameters
$holder.quicksand($filteredData, {
duration: 800,
easing: 'easeInOutQuad'
});
return false;
});
});
The Quicksand file itself has remained the same, with the except that I changed all 'height's within the document to 'width', as I don't have heights specified for any of the divs.
Thank you for your help! Please let me know if you need to see the HTML or CSS to solve the problem.

This is happening because of the easing function you've used: easeInOutQuad.
It gives the animation an invese bounce aspect.
See here for reference: http://gsgd.co.uk/sandbox/jquery/easing/
Edit:
You have found your problem since start. I've debuged your page and found that the percentage measures are the problem.
From the site: http://razorjack.net/quicksand/docs-and-demos.html
CSS recommendations
1.When styling your items and their container, please use CSS class. Using ID may lead to strange results. Quicksand clones the container to simulate destination frame of the animation. Since it's impossible for two elements of the same ID to exist, styling your items/container via container ID should be avoided.
2.Quicksand needs to know the margin of body, container and collection items. If these elements have their margins, please use px (pixels), not ems. The plugin doesn't understand ems for now.
I think percentages are included in this same case.

Related

How to get index of current element taking into account only visible elements?

I'm using jQuery to create simple portfolio and show view light box with next before options.
When the user clicked some project I need get the index of the project but taking into account only visible elements.
After click I take
$(this).parents("li").filter(":visible").index();
But count hidden elements.
How can I get the index only count visible elements?
You can use like this,
var parents = $(this).closest(".portfolio-items").find("li:visible");
var parent = $(this).closest("li");
alert(parents.index(parent));
This will returns the index of the passes item based on the set of elements.
Fiddle
I found similar question
Using jQuery to select items that have style "visibility:visible" or "visibility:hidden" NOT "display: none"
var projectIndex = $("#grid li").filter(function() {
return !($(this).css('visibility') == 'hidden' || $(this).css('display') == 'none');
}).index(item) + 1;
item is variable that hold clicked element.
I hope that be useful for someone.

JQuery Draggable Object, set containment with dynamic div tags

I have multiple div tags that i can drag objects to.
I would like to contain the draggable objects to the div tags. These div tags are dynamically generated.
In order to do this, i realized that i would have to list all the div containers. These are only available when the program runs initially.
Then i can set the containment with the list of divs returned.
My issue is that the containment functionality only works for the first div and not the other ones.
I would like to have a solution in place where the dragged objects can be moved anywhere inside the dynamically generated div tags
Please see the code i used below to retrieve the dynamically generated div tags and set them to the containment option.
Can somebody please explain how i can set the containment with dynamically generated divs and restrict objects dragged to these divs?.
//Handle object drop in div area
function handleContainmentDIVs() {
var id;
var i = 0;
$("div[id$='pnlPdfPage']").each(function () {
if (i == 0)
id = $(this);
else
id = id.add($(this));
i++;
}
);
return id;
}
//Make element droppable
$(".droppablePage").droppable({
accept: '.existingFieldItem, .existingPageObject',
containment: handleContainmentDIVs()
};
//Make element draggable
$(".draggableItem").draggable({
// use a helper-clone that is append to 'body' so is not 'contained' by a pane
helper: function () {
return $(this).clone().appendTo('body').css({
'zIndex': 5
});
},
revert: "invalid",
cursor: 'move',
containment: handleContainmentDIVs()
});
I found the solution to this issue. Basically I added the mouseover event handler to return the updated Draggable area.

Adding classes to filtered items and hidden items in Isotope. Buttons not checkbox

I know this question has been answered, and here is a fiddle which achieves exactly what I want to do, HOWEVER, in the example they use radio buttons, whereas I'm using a set of buttons (essentially just divs which gain a class of .active once clicked).
I've tried to adapt the code so 'filters' gives the same output as it does on the example, and as far as I can tell it does (An array with the name of the filter class inside), so I can't tell why it isn't working.
Here is my edited code...
$(document).ready(function(){
var $container = $('#content');
$container.isotope({
itemSelector: '.box',
});
$('.nav a').click(function(){
$('.nav a').removeClass('active');
$(this).addClass('active');
var selector = $(this).attr('data-filter');
$items = $('.box'); // to reference methods on all .item divs later
// alert($items.length);
// get checked checkboxes values
var filters = [];
filters.push(selector);
console.log(filters);
$container.isotope({
filter: filters
}, function($changedItems, instance) {
instance.$allAtoms.filter('.isotope-hidden').removeClass('is-filtered');
alert((instance.$allAtoms.filter('.isotope-hidden')).length); // here it is
instance.$filteredAtoms.addClass('is-filtered');
});
return false;
});
});
Any ideas as to why my version doesn't work would be appreciated.
Here is a link to my NOT WORKING EXAMPLE
Your variable filters is an array. I think it should be a string to work.
So just do that:
var filters = [];
filters.push(selector);
filters = filters.join(', ');
In fact, if you'll only use one filter at a time (as it appears), you can use your variable selector directly, as it already contains your filter class name.
Hope it helps!

Target current menu item in a single page site with fixed menu

I'm working a single-page website for my friend's photo studio: http://dev.manifold.ws/yorckstudio/
The site is divided in six sections, each the size of the viewport. When you click on one of the menu item, it takes you to the corresponding section. What I can't figure out is how to get a menu item to be underline when viewing the corresponding section. So if I'm viewing the "Photos" section, the item "Photos" in my fixed menu would be underlined.
My guess is that there must be a relatively simple way to achieve that with a bit of javascript / jQuery magic. But my js skills being quite poor, I'm not sure where to start.
Does anyone have a idea of how this could be achieved?
Cheers,
Thom
Using jQuery, add this is your JS:
$('#menu a').click(function(){
$(this).css('text-decoration','underline');
$(this).parent().siblings().find('a').css('text-decoration','none');
})
This will add an underline to the clicked anchor tags and remove the attribute on all the other ones.
jsFiddle: http://jsfiddle.net/z97RX/
Try this:
$('#menu ul li a').click(function(){
var that = $(this);
that.addClass('underline');
that.parent().siblings().find('a').removeClass('underline');
});
And add to css
.underline{
text-decoration: underline;
}
If you could, please take a look here http://jsfiddle.net/xv8tf/3/
It could be cleaned up a bit, but here is the jist of it.
All you require to do on your end is update you menu and your scrollto elements and just add a rel tag with matching values
Example:
<div id="menu">
<ul>
<li><a rel="photos" href="javascript:void(0)">Photos</a></li>
</ul>
</div>
<div rel="photos" id="photos"></div>
//create a list of all elements to be tested against
var scrollMatches = [
$('#photos'),
$('#studio'),
$('#rates'),
$('#features'),
$('#plan'),
$('#contact')
];
$(window)
.on('scroll', function(){
//save scrolltop to var to prevent multiple callings
var scroll = $(this).scrollTop();
//iterate through each of the elements to be testing against
$.each(scrollMatches, function(k, v){
var offset = v.offset()
// if the element is in the viewport
if(offset.top <= scroll && (offset.top + v.outerHeight()) > scroll){
// get associated element
var element = $('#menu li > a[rel='+v.attr('rel')+']');
// do whatever you want to the current tested element
element.css('text-decoration','underline');
// dp whatever you want to the associated menu item
element.parent().siblings().find('a').css('text-decoration','none');
return false;
}
});
});

JQuery Event Listeners in a For Loop

I am trying to create some basic button rollover functionality using Jquery and toggleClass. I am building a list of elements by cloning a DIV from my HTML and duplicating it multiple times (its populating a list of data from a database). To do this I am using a for loop. Here is the currently working code.
var displayNode = document.getElementById('phoneDisplayContainer');
for(var i=0; i<length; i++) {
//Clone the original container display.
var clonedDisplay = displayNode.cloneNode(true);
clonedDisplay.setAttribute('id', 'phoneDisplayContainer' + i);
//Remove hidden class from cloned Element. NOT CROSS BROWSER!
clonedDisplay.classList.remove('hidden');
var children = clonedDisplay.getElementsByTagName('div');
//Fill new nodes children containers with data.
children[1].innerHTML = contact.phone[i].type;
children[2].innerHTML = contact.phone[i].number;
children[3].setAttribute('onclick', 'PhoneUtility.edit(' + i + ');');
children[3].setAttribute('id', 'phoneEditDisplay' + i);
children[4].setAttribute('onclick', 'PhoneUtility.remove(' + i + ');');
//Hidden elements
var hidden = new Array(children[3], children[4]);
//Set rollover events.
clonedDisplay.setAttribute('onmouseover', '$("#' + children[3].id + '").toggleClass("hidden");');
clonedDisplay.setAttribute('onmouseout', '$("#' + children[3].id + '").toggleClass("hidden");');
//Append the new node to the display container
phoneContainer.appendChild(clonedDisplay);
}
}
Is there a way to use Jquery event listeners instead of having to set onmouseover and onmouseout directly on the element?
I tried this:
$(clonedDisplay).mouseover(function() {
$(children[3]).toggleClass('hidden');
});
With no luck. It just displays performs the rollover effect on the last element in the list. This is actually my first attempt at using jQuery so any other suggestions to ways I could jQuery inside the code would be helpful too.
EDIT: I'd also like to toggle multiple children from the arraylist mentioned in the for loop. How would I set this up? I can't seem to pass an array to the jquery command without getting errors.
The following code after your for loop should let you assign all the mouseover and mouseout handlers in one go to apply to all the clones:
$('div[id^="phoneDisplayContainer"]').mouseover(function() {
$(this).find("div").eq(3).toggleClass("hidden");
}).mouseout(function() {
$(this).find("div").eq(3).toggleClass("hidden");
});
// or, given that both handlers do the same thing:
$('div[id^="phoneDisplayContainer"]').on("mouseover mouseout", function() {
$(this).find("div").eq(3).toggleClass("hidden");
})
(If you're using jQuery older than 1.7 use .bind() instead of .on().)
The above says to find all the divs with an id beginning with "phoneDisplayContainer" and assign event handlers. Within the handler, find the fourth descendant div and toggle the class.
You don't show your HTML or CSS, but you could do this all in your CSS if you like. Assuming you can assign a common class ("parentDiv") to the divs that you want to trap the hover event on, and a common class ("childDiv") to their child div (the one to be hidden), you can do this:
.parentDiv .childDiv { visibility: hidden; }
.parentDiv:hover .childDiv { visibility: visible; }
(Obviously you can give more meaningful class names to fit your structure.)
Otherwise, again if you can assign those classes to the appropriate divs then after your loop you can do this with jQuery:
$(".parentDiv").on("mouseover mouseout", function() {
$(this).find(".childDiv").toggleClass('hidden');
});
Basically the same as what I said initially, but using classes for selectors. If you feel like I'm pushing a class-based solution on you that's because I am: it tends to make this sort of thing much easier.

Categories