I'm trying to use this image skimming script on my website, which I want to be iPhone and iPad compatible. The problem is it is based on mouse-over so it doesn't work on touch. Any way anyone could help me change the script so instead of hovering over the images you click and drag to skim through them? So it could work on touch devices? Thanks. (Example of the script: http://www.fourcornersbooks.co.uk )
(function($) {
$.fn.skim = function() {
return this.each(function() {
var container = $(this);
var numImgs = container.find("img").size();
var zoneWidth = container.width() / numImgs;
container.find("img").css("display", "none");
container.find("img:first").css("display", "block");
container.mousemove(function(e) {
var offset = container.offset();
x = e.pageX - offset.left;
var currentZone = Math.floor(x / zoneWidth);
$(this).find("img").css("display", "none");
$(this).find("img:eq(" + currentZone + ")").css("display", "block");
});
container.mouseout(function(){
$(this).find("img").css("display", "none");
$(this).find("img:first").css("display", "block");
});
});
}
})(jQuery);
Related
I'm trying to replicate Zara's product functionality: (click on product image)
https://www.zara.com/es/en/woman/outerwear/view-all/tweed-coat-with-metal-buttons-c733882p5205048.html
I have it almost working from a jsfiddle I found:
https://jsfiddle.net/y6p9pLpb/1/
$(function() {
$('.product-wrapper a').click(function() {
$('.image-zoom img').attr('src', $(this).find('img').attr('src'));
$('.image-zoom').show();
$('.product-wrapper').css('display', 'none');
return false;
});
$('.image-zoom').mousemove(function(e) {
var h = $(this).find('img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * e.pageY;
$('div img').css('top', y + "px");
});
$('.image-zoom').click(function() {
$('.image-zoom').hide();
$('.product-wrapper').css('display', 'block');
});
});
There's only one thing I can't solve.
When I click on the image and expands, this one jumps to match its respective position relative to the cursor.
Is there any way I can solve that? Like Zara does...
Thanks in advance!
The issue is that the image jumps to your cursor once you move it, right? This should do what you're looking for!
https://jsfiddle.net/8z67g96b/
I just broke out the position change as a function, and also call it when you click the thumbnail - that way, the image already has the cursor's position influencing it when it first appears.
function zoomTracking(event){
var h = $('.image-zoom img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * event.pageY;
$('.image-zoom img').css('top', y + "px");
}
$('.product-wrapper a').click(function(e) {
$('.image-zoom img').attr('src', $(this).find('img').attr('src'));
$('.image-zoom').show()
zoomTracking(e);
$('.product-wrapper').css('display', 'none');
return false;
});
$('.image-zoom').mousemove(function(e) {
zoomTracking(e);
});
In the fiddle, it has a section relating to the position of the mouse and the width/height of the image:
$('.image-zoom').mousemove(function(e) {
var h = $(this).find('img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * e.pageY;
$('div img').css('top', y + "px");
});
Simply remove this portion and it won't do any moving with the mouse, just expand onClick.
I have a div and inside that there's an image. Now when I click the image I can get the image by $(this) and a border is displayed to let the user know that it can be resized.
html:
<div id="content">
<p>Something <img src="http://placehold.it/350x150"/> Lorem expetendis .</p>
</div>
js:
$("#content img").on("click", function () {
$(this).addClass("resize_handler");
});
Then I though of getting the initial x and y axis on mousedown and compare it to the mousemove. And then change the height/width of the image accordingly.
$(document).mousemove(function (event) {
if (clicking == true) {
x_axis = event.pageX;
y_axis = event.pageY;
delta_x_axis = x_axis - initial_x_axis;
delta_y_axis = initial_y_axis - y_axis;
}
});
Check out jsfiddle.
But it didn't help either, because as I try to drag, the image gets selected. How to make the image resizable when clicked with its aspect ratio? I would really appreciate your help and guidance. Thank you.
Here is the fiddle: http://jsfiddle.net/jmyem32r/4/.
You should do your enhance, now it looks really ugly, but main principle is shown. To make a draggable behaviour, you should use a boolean switcher that is toggled with image mousedown event, and document mouseup. Also you should cancel default mousedown behaviour by calling event.preventDefault method.
$(document).ready(function (event) {
var x_axis;
var y_axis;
var initial_x_axis;
var initial_y_axis;
var isDragging = false;
$('#content img').mousedown(function (event) {
event.preventDefault();
isDragging = true;
initial_x_axis = event.pageX;
initial_y_axis = event.pageY;
$("#initial").text("initial-x: " + initial_x_axis + ", initial-y: " + initial_y_axis);
$(this).addClass("resize_handler");
});
$(document).mouseup(function () {
isDragging = false;
});
$(document).mousemove(function (event) {
if(isDragging) {
x_axis = event.pageX;
y_axis = event.pageY;
var newWidth = $('#content img')[0].width / (initial_x_axis / x_axis);
$('#content img').css('width', newWidth + 'px');
}
});
});
I'm looking to make something exactly like Facebook's Android app's UX for swiping between News Feed, Friend Requests, Messages, and Notifications. You should be able to "peek" at the next view by panning to the right of left, and it should snap to the next page when released if some threshold has been passed or when swiped.
Every scroll snap solution I've seen only snaps after the scrolling stops, whereas I only ever want to scroll one page at a time.
EDIT: Here's what I have so far. It seems to work fine when emulating an Android device in Google Chrome, but doesn't work when I run it on my Galaxy S4 running 4.4.2. Looking into it a bit more, it looks like touchcancel is being fired right after the first touchmove event which seems like a bug. Is there any way to get around this?
var width = parseInt($(document.body).width());
var panThreshold = 0.15;
var currentViewPage = 0;
$('.listContent').on('touchstart', function(e) {
console.log("touchstart");
currentViewPage = Math.round(this.scrollLeft / width);
});
$('.listContent').on('touchend', function(e) {
console.log("touchend");
var delta = currentViewPage * width - this.scrollLeft;
if (Math.abs(delta) > width * panThreshold) {
if (delta < 0) {
currentViewPage++;
} else {
currentViewPage--;
}
}
$(this).animate({
scrollLeft: currentViewPage * width
}, 100);
});
In case anyone wants to do this in the future, the only way I found to actually do this was to manually control all touch events and then re-implement the normally-native vertical scrolling.
It might not be the prettiest, but here's a fiddle to what I ended up doing (edited to use mouse events instead of touch events): http://jsfiddle.net/xtwzcjhL/
$(function () {
var width = parseInt($(document.body).width());
var panThreshold = 0.15;
var currentViewPage = 0;
var start; // Screen position of touchstart event
var isHorizontalScroll = false; // Locks the scrolling as horizontal
var target; // Target of the first touch event
var isFirst; // Is the first touchmove event
var beginScrollTop; // Beginning scrollTop of ul
var atanFactor = 0.6; // atan(0.6) = ~31 degrees (or less) from horizontal to be considered a horizontal scroll
var isMove = false;
$('body').on('mousedown', '.listContent', function (e) {
isMove = true;
isFirst = true;
isHorizontalScroll = false;
target = $(this);
currentViewPage = Math.round(target.scrollLeft() / width);
beginScrollTop = target.closest('ul').scrollTop();
start = {
x: e.originalEvent.screenX,
y: e.originalEvent.screenY
}
}).on('mousemove', '.listContent', function (e) {
if (!isMove) {
return false;
}
e.preventDefault();
var delta = {
x: start.x - e.originalEvent.screenX,
y: start.y - e.originalEvent.screenY
}
// If already horizontally scrolling or the first touchmove is within the atanFactor, horizontally scroll, otherwise it's a vertical scroll of the ul
if (isHorizontalScroll || (isFirst && Math.abs(delta.x * atanFactor) > Math.abs(delta.y))) {
isHorizontalScroll = true;
target.scrollLeft(currentViewPage * width + delta.x);
} else {
target.closest('ul').scrollTop(beginScrollTop + delta.y);
}
isFirst = false;
}).on('mouseup mouseout', '.listContent', function (e) {
isMove = false;
isFirst = false;
if (isHorizontalScroll) {
var delta = currentViewPage * width - target.scrollLeft();
if (Math.abs(delta) > width * panThreshold) {
if (delta < 0) {
currentViewPage++;
} else {
currentViewPage--;
}
}
$(this).animate({
scrollLeft: currentViewPage * width
}, 100);
}
});
});
I'm trying to set the position of a menu beneath a slider that is dynamically generating the height, so I've used imagesloaded to load my jquery last and all is well in every browser except safari where it retrieves the height of the slider set in the back-end and not the height of the image which is dynamically generated depending on page size. this is only occurring in safari....
Here is the javascript to position the menu:
$.browser.safari = ($.browser.webkit && !(/chrome/.test(navigator.userAgent.toLowerCase())));
if ($.browser.safari) {
$(window).load(function () {
var $container = $('.ls-wp-fullwidth-container');
$container.imagesLoaded(function () {
var height = $(".ls-wp-fullwidth-container").height() - 50;
$(".menu_wrap").css('top', height);
});
});
} else {
$(window).load(function () {
var $container = $('.ls-wp-fullwidth-container');
$container.imagesLoaded(function () {
var height = $(".ls-wp-fullwidth-helper").height();
$(".menu_wrap").css('top', height);
});
});
}
$(window).resize(function () {
var height = $(".ls-wp-fullwidth-container").height() + 40;
$(".menu_wrap").css('top', height);
});
The slider that is being used is anything slider I'm using a themeforest theme named cleanspace and running wordpress 3.5.1.
I've tried using $(window).bind("load",function(){ to load the jquery last and $.browser.safari = ($.browser.webkit && !(/chrome/.test(navigator.userAgent.toLowerCase())));
if ($.browser.safari) {
to detect the browser which works fine on pc but fails on mac, so I'm left with the first code pasted here and await any help with baited breath.
NOTE: the if statement here is un-needed if safari would load my jQuery after the slider images...
I have found a work around I'm guessing it's not the best anwser and would be happy to hear better suggestions, basically I've placed a timer on the function to load like so:
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
$(window).load(function() {
setTimeout(function(){
var $container = $('.ls-wp-fullwidth-helper');
$container.imagesLoaded( function() {
var height = $(".ls-wp-fullwidth-helper").height() ;
$(".menu_wrap").css('top', height);
});
}, 2000);
});
}
else {
$(window).load(function() {
var $container = $('.ls-wp-fullwidth-helper');
$container.imagesLoaded( function() {
var height = $(".ls-wp-fullwidth-helper").height();
$(".menu_wrap").css('top', height);
});
});
}
$(window).resize(function(){
var height = $(".ls-wp-fullwidth-helper").height() + 40;
$(".menu_wrap").css('top', height);
});
In my client's website, (http://slnyaadev45.herokuapp.com/),I have used a JS slider on the top. It will contiguously move the images across the site. In Firefox, it works perfectly. But in Google Chrome, it doesn't. Sometimes it work but if I reload the page it stops working. Sometimes, it start to work. Then if I just click a link to another page, it will still work. But if I reload, it breaks again. The problem is also there in the Android's default browser. What is going wrong? How to fix it?
PS : The site is built with Rails 3.2.
The javascript :
$(function(){
var scroller = $('#scroller div.innerScrollArea');
var scrollerContent = scroller.children('ul');
scrollerContent.children().clone().appendTo(scrollerContent);
var curX = 0;
scrollerContent.children().each(function(){
var $this = $(this);
$this.css('left', curX);
curX += $this.width();
});
var fullW = curX / 2;
var viewportW = scroller.width();
// Scrolling speed management
var controller = {curSpeed:0, fullSpeed:1};
var $controller = $(controller);
var tweenToNewSpeed = function(newSpeed, duration)
{
if (duration === undefined)
duration = 600;
$controller.stop(true).animate({curSpeed:newSpeed}, duration);
};
// Pause on hover
scroller.hover(function(){
tweenToNewSpeed(0);
}, function(){
tweenToNewSpeed(controller.fullSpeed);
});
// Scrolling management; start the automatical scrolling
var doScroll = function()
{
var curX = scroller.scrollLeft();
var newX = curX + controller.curSpeed;
if (newX > fullW*2 - viewportW)
newX -= fullW;
scroller.scrollLeft(newX);
};
setInterval(doScroll, 20);
tweenToNewSpeed(controller.fullSpeed);
});
because the distance between the elements is 4px, set the ''left'' of each element is equal to previous elements widths sum
OR
you can remove position:absolute for style of li, and add float:left
Because all my images have the same size, I added the width in this line of the script :
curX += $this.width();
as :
curX += 224;