Hover in/out makes my div flicker - javascript

I am trying to make a flowing-down div. I have the following jQuery code for them:
$(".centered-wrapper>main>.event").hoverIntent({
over: function() {
var pos = $(this).position();
$presentationEvent = $(this);
$fullEvent = $(this).clone();
$fullEvent.addClass("full");
$(this).css("visibility", "hidden");
$fullEvent.css({
position: "absolute",
top: pos.top,
left: pos.left
});
$(".centered-wrapper>main").append($fullEvent);
$fullEvent.find("main").slideDown(50, function() {
$fullEvent.find("footer").slideDown(50);
});
$fullEvent.animate({boxShadow: "0px 5px 5px 0px rgba(0,0,0,0.5);"}, 100);
console.log( $(".centered-wrapper>main>.event.full"));
$(".centered-wrapper>main>.event.full").on("mouseout", function() {
$(this).find("main, footer").slideUp(100);
$(this).remove();
$presentationEvent.css("visibility", "visible");
});
},
out: function() {}
});
Everything works well until I move my cursor up and down on that element, because, then it flickers and appears and disappears...
<div class="event">
<header>
<img class="photo" src="/res/users/events-photos/bal.jpg" alt=""/>
<div class="event-card">
<div class="date">
<!-- content -->
</div>
</header>
<main>
<!-- content -->
</main>
<footer>
<!-- content -->
</footer>
</div>
How can I solve this problem and where am I wrong?

You need to disable multiple queued animations. The best way to achieve this is to stop() it.
http://api.jquery.com/stop/
According to documentation:
$( "#hoverme-stop-2" ).hover(function() {
$( this ).find( "img" ).stop( true, true ).fadeOut();
}, function() {
$( this ).find( "img" ).stop( true, true ).fadeIn();
});
In your case:
$fullEvent.find("main").stop(true,true).slideDown(50, function() {
$fullEvent.find("footer").stop(true,true).slideDown(50);
});
and:
$(this).find("main, footer").stop(true,true).slideUp(100);

The visibility hidden code interferes with element hover and causes the flicker. Use another way to hide it. Like
.event:hover
{
opacity: 0;
}
To avoid events from firing use 'pointer-events: none;'
.event:hover
{
opacity: 0;
pointer-events: none;
}

Related

Is there a more efficent way to do this?

How can I achieve this code easier or with less lines of code?
I'm curious if it can be done easier and/or more efficently. Because I feel like there is too much repetition in this, so there must be an easy way.
And I'm not only planning to make 4 of this but like 20-30, so performance is a key aspect.
Jquery:
$( document ).ready(function() {
$( "#q1" ).click(function() {
$( "#a1" ).slideToggle( "slow", function() {});
if ($(this).hasClass('on')){
$(this).removeClass('on');
}else{
$(this).addClass('on');
}
});
$( "#q2" ).click(function() {
$( "#a2" ).slideToggle( "slow", function() {});
if ($(this).hasClass('on')){
$(this).removeClass('on');
}else{
$(this).addClass('on');
}
});
$( "#q3" ).click(function() {
$( "#a3" ).slideToggle( "slow", function() {});
if ($(this).hasClass('on')){
$(this).removeClass('on');
}else{
$(this).addClass('on');
}
});
$( "#q4" ).click(function() {
$( "#a4" ).slideToggle( "slow", function() {});
if ($(this).hasClass('on')){
$(this).removeClass('on');
}else{
$(this).addClass('on');
}
});
});
HTML:
<div id="faq_content">
<div class="faq_box">
<div class="questions" id="q1">
<span>xyz</span>
</div>
<div class="answers" id="a1">
<span>xyz</span>
</div>
</div>
<div class="faq_box">
<div class="questions" id="q2">
<span>xyz</span>
</div>
<div class="answers" id="a2">
<span>xyz</span>
</div>
</div>
</div>
The easiest way that I can think of, given your HTML structure, is the following:
$(document).ready(function() {
// selecting all the elements you need to work with,
// and binding the anonymous function of the click()
// method as the event-handler:
$("#q1, #q2").click(function() {
// here $(this) will refer to the element that fired the
// click event, from that element:
$(this)
// we navigate to the next-sibling element matching the
// supplied selector:
.next('.answers')
// we use the slideToggle() method to show/hide the element,
// using an Arrow function to compose the anonymous
// function so that we can use the same this (and therefore
// $(this)) as the outer function:
.slideToggle('slow', () => {
// here $(this) still refers to the clicked element, as
// Arrow functions don't establish their own 'this'; and
// we use the toggleClass() method to add, or remove, the
// supplied class based on whether it already exists on
// the element:
$(this).toggleClass('on');
});
// here we again call the click() method, without arguments, in
// order to fire the click event on page-load (which, in this
// context will cause the answers to be hidden on page-load):
}).click();
});
$(document).ready(function() {
$("#q1, #q2").click(function() {
$(this).next('.answers').slideToggle('slow', () => {
$(this).toggleClass('on');
});
}).click();
});
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.faq_box {
border: 1px solid #000;
margin: 0.2em auto;
width: 80vw;
}
.questions {
background-color: #ffff;
border: 1px solid transparent;
border-bottom-color: #000;
cursor: pointer;
font-size: 1.2em;
font-weight: bold;
transition: background-color 0.3s linear;
}
.questions::before {
content: attr(id) ': ';
text-transform: capitalize;
}
.answers::before {
content: attr(id) ': ';
}
.on {
background-color: #0f06;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="faq_content">
<div class="faq_box">
<div class="questions" id="q1">
<span>xyz</span>
</div>
<div class="answers" id="a1">
<span>xyz</span>
</div>
</div>
<div class="faq_box">
<div class="questions" id="q2">
<span>xyz</span>
</div>
<div class="answers" id="a2">
<span>xyz</span>
</div>
</div>
</div>
References:
click().
next().
slideToggle().
$(document).ready(function(){
var qClasses = $('.q');
qClasses.on('click', function(){
var $this = $(this);
var aIds = $this.data('id');
$(aIds).slideToggle("slow");
$this.toggleClass("on");
});
});
Since all the #q1,#q2... are doing the same thing on click you can utilize the classes for this and with <div id="#q1" class="q" data-id="#a1" ></div> you can refer to the id on click of the q classes. Also, you can define the initial state of #q1 or q classes as there are only two states with class "on" or without it so the default state can be defined directly in HTML instead of checking in the JS. like: <div id="#q1" class="q on" data-id="#a1"></div>
Because all your handlers look the same, you can create a function which returns a function:
function createHandler(selector) {
return function() {
$( selector ).slideToggle( "slow", function() {});
if ($(this).hasClass('on')){
$(this).removeClass('on');
}else{
$(this).addClass('on');
}
}
}
and use it like this:
$( "#q1" ).click(createHandler("#a1"))
To find out more about this principle search for "Higher-Order Functions" and "Closures"

How to show a indicator when clicked on a Button in this case

On Click Of the Try Again Button , is it possible to show some processing happening on the device
My jsfiddle
My code as below
$(document).on("click", ".getStarted", function(event) {
// Simulating Net Connection here
var a = 10;
if (a == 10) {
$('#mainlabel').delay(100).fadeIn(300);
$('#nonetconnmain').popup({
history : false
}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain", function(event, ui) {
$('#mainlabel').hide();
});
With my code , the functionality is working , but it seems that the application is not doing any action
So my question is it possible to show any indication (For example , delay , progressbar , anything )
Here ya go
$(document).on("click", ".getStarted", function(event) {
$.mobile.loading("show", {
text: "",
textVisible: true,
theme: "z",
html: ""
});
// Simulating Net Connection here
var a = 10;
if (a == 10) {
setTimeout(function() {
$.mobile.loading("hide");
$('#mainlabel').fadeIn(300);
}, 1000);
$('#nonetconnmain').popup({
history: false
}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain", function(event, ui) {
$('#mainlabel').hide();
});
.popup {
height: 200px;
width: 150px;
}
.popup h6 {
font-size: 1.5em !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<link href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
<div data-role="page">
<div data-role="popup" id="nonetconnmain" data-dismissible="false" class="ui-content" data-theme="a">
<div class="popup_inner popup_sm">
<div class="popup_content" style="text-align:center;">
<p class="">Please check net connectivcty</p>
<label id="mainlabel" style="margin:100px auto 60px auto;color:Red; line-height:40px;font-size:medium;display:none">Please check</label>
</div>
<div class="popup_footer nonetconnmainclose">
<a class="">Try Again</a>
</div>
</div>
</div>
<button class="getStarted btn btn-a get_btn">Click Here</button>
</div>
You can use a small function (with time as parameter) and use jQuery animate() to create the process effect like below.
var updateProgress = function(t) {
$( "#p" ).css("width",0);
$( "#p" ).show();
$( "#p" ).animate({ "width": "100%" }, t , "linear", function() {
$(this).hide();
});
}
Do notice that the time that is chosen when calling updateProgress() is relevant with the delay and the fade in effect of the text message
updateProgress(3500);
$('#mainlabel').delay(3400).fadeIn(600);
Check it on the snippet below
var updateProgress = function(t) {
$( "#p" ).css("width",0);
$( "#p" ).show();
$( "#p" ).animate({ "width": "100%" }, t , "linear", function() {
$(this).hide();
});
}
$(document).on("click", ".getStarted", function(event) {
var a = 10;
if(a==10)
{
updateProgress(3500);
$('#mainlabel').delay(3400).fadeIn(600);
$('#nonetconnmain').popup({history: false}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain",function( event, ui ) {
$('#mainlabel').hide();
});
.popup {
height: 200px;
width: 400px;
}
.popup h6 {
font-size: 1.5em !important;
}
#p {
border:none;
height:1em;
background: #0063a6;
width:0%;
float:left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<link href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet"/>
<div data-role="page">
<div data-role="popup" id="nonetconnmain" data-dismissible="false" class="ui-content" data-theme="a">
<div class="popup_inner popup_sm">
<div class="popup_content" style="text-align:center;">
<p class="">Please check net connectivcty</p>
<div id="p"></div><br>
<label id="mainlabel" style="margin:100px auto 60px auto;color:Red; line-height:40px;font-size:medium;display:none">Please check </label>
</div>
<div class="popup_footer nonetconnmainclose">
<a class="">Try Again</a>
</div>
</div>
</div>
<button class="getStarted btn btn-a get_btn">Click Here</button>
</div>
Fiddle
Probably when you click on try again , you can have a setinterval triggered which can check for online connectivity and when found can close the popup and get started again, also when we do retries in the interval the progress can be shown as progressing dots..
Below is the code, i haven't tried to run the code, but it shows the idea
$(document).on('click', '.nonetconnmainclose', function(event) {
var msgUI = $("#mainlabel");
msgUI.data("previoustext",msgUI.html()).html("retrying...");
var progress = [];
var counter = 0 ,timeout = 5;
var clearIt = setInterval(function(){
var online = navigator.onLine;
progress.push(".");
if(counter > timeout && !online){
msgUI.html(msgUI.data("previoustext"));
counter=0;
}
if(online){
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
counter=0;
clearInterval(clearIt);
}
else{
msgUI.html("retrying" + progress.join(""));
counter++;
}
},1000);
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
Sure,
try appending a loader GIF to one of the div and remember to remove the same when your process is finished.
Kindly refer to StackOverflow
And try appending this
$('#nonetconnmain').append('<center><img style="height: 50px; position:relative; top:100px;" src="cdnjs.cloudflare.com/ajax/libs/semantic-ui/0.16.1/images/…; alt="loading..."></center>');
This will append a loader to your HTML to show some kind of processing.

$('#div').bind('scroll' function({})) not working

I have added 2 codes here the window.scroll works on my example but not the second one binding the div to the scroll.
Any one knows what am I doing wrong!?
Just so you know I'm working in MeteorJS <- I dont think that this is the problem bc. the window scrolling works.
This 2 codes are in the same js file.
$(window).scroll(function() {
lastSession = Session.get('c_info')[Session.get('c_info').current]
if(lastSession.list == 0 && $(window).height() + $(window).scrollTop() >= $(document).height()){
lastItem = $( ".list-item div:last" ).html();
if (lastSession.page == 1){
currentSession().more();
lastItem2 = $( ".list-item div:last" ).html();
} else if( lastItem2 != lastItem) {
currentSession().more();
lastItem2 = $( ".list-item div:last" ).html()
}
}
});
$('#playlist').bind('scroll',function() {
console.log("div is scrolling");
});
I tried this too:
$('#playlist').scroll(function() {
console.log("div is scrolling");
});
MeteorJS Template:
<template name="playList">
<div id="playlist" class="playlist show-for-large-up">
{{#each list}}
<a href="/video/{{_id}}" class="large-12 columns" id="pl{{v_id}}">
<div>
<div class="large-7 columns plRight">
<span>{{vTitle}}</span>
</div>
</div>
</a>
{{/each}}
</div>
</template>
Also Tried:
$('#playlist').on('scroll',function() {console.log('test')});// not working
Tried to Change the id name and putting on the document ready:
$( document ).ready(function (){
$('#pl_list').bind('scroll',function() {
console.log("div is scrolling");
});
})//failed
The div has a scrollbar and the list is long and i have a css like this:
.playlist {
padding: 0;
overflow-y: scroll;
height: 458px;
}
Also tried:
Template.playList.rendered = function () {
console.log("playlist rendered");// i can see this on logs this tells that template is in doom
Meteor.setTimeout(function(){
$('#playlist').on('scroll',function(){
console.log('Scrolling...');
});
}, 2000);// with settimeout i have giveng it 2 more seconds
}
Try this out -
$(document).ready(function(){
$('#playlist').on('scroll',function(){
console.log('Scrolling...');
});
});
Use
$('#playlist').scroll(function() {
console.log("div is scrolling");
});
instead (like you did for window).
Thats the purpose of scroll(). See jquery documentation.
Scrolling event is fired on the element, if it has scrolled. So if you only scrolling the "body" element of the DOM it will not be triggered for #playlist.
So you have put a scrollbar to the container element of #playlist. Shot answer, cut the height and add a scrollbar, then the event will fire on it.
I did a Jsfiddle http://jsfiddle.net/34j0qnpg/4/
html
<div id="playlist-wrapper">
<div id="playlist" class="playlist show-for-large-up">
<a href="/video/1" class="large-12 columns" id="pl1">
<div>
<div class="large-7 columns plRight">
<span>Titel</span>
</div>
</div>
</a>
css part
body, html {
padding: 0;
margin: 0;
background-color: lightgrey;
color: #fff;
font-family: Arial;
height: 5000px;
overflow-y:scroll;
}
#stats {
position: relative;
}
#playlist-wrapper {
border: 1px solid #000;
padding: 10px;
height: 300px;
overflow-y: scroll;
}
#playlist {
height: 1000px;
background-color: darkgrey;
}
var $stats = $('#stats');
$('#playlist-wrapper').on('scroll', function() {
$stats.html('playlist scrolling');
console.log('playlist scrolling');
});
$(window).on('scroll', function() {
$stats.html('window scrolling');
console.log('window scrolling');
});
Solved with this code:
Tried it earlyer no results, after meteorjs project reset it just automagicly workded:
Template.playList.rendered = function () {
console.log("playlist rendered");
$('#playlist').on('scroll',function(){
console.log('Scrolling...');
});
}
I answered my question just if anybody is searching for the same answer.
Thanks to anybody who tried to help me.
I LOVE THIS COMMUNITY.

JQuery carousel shift by one element

I try to create my own JQuery carousel using this code as example http://coolcodez.net/create-infinite-carousel-in-jquery-using-a-few-lines-of-code/
$(document).ready(function () {
$.fn.carousel = function () {
var carousel = $(this);
var width = carousel.find('li').width();
setInterval(function() {
carousel.delay(1000).animate({
right: '+=' + width
}, 1000, function () {
var first = carousel.find('>:first-child');
first.remove();
$(this).append(first);
$(this).css({
right: '-=' + width
});
});
}, 2000);
return $(this);
};
$('#carousel-1').carousel();
});
http://jsfiddle.net/n8b65qbb/33/
I need to shift one image to the left every time, but my script doesn't work properly.
How can I fix it and make it work the right way ?
There are some errors in your code. First, I think the carousel variable should point to the ul, not to the div. The selector for the first variable is weird. Also, you should use detach instead of remove. By the way, there was a "jump" because you're not taking into account the margin between the list items in the animation.
Here's a working version (still needing big improvement):
$(document).ready(function () {
$.fn.carousel = function () {
var carousel = $(this);
var width = carousel.find('li').width() + 15; // Hardcoded margin
setInterval(function () {
carousel.animate({
right: '+=' + width
}, 1000, function () {
var first = carousel.find("li:first-child").detach();
$(this).find("ul").append(first); // The "ul" should be cached
$(this).css({
right: '-=' + width
});
});
}, 2000);
return $(this);
};
$('#carousel-1').carousel();
});
Some thoughts and changes:
I would suggest to constrain your HTML and CSS to the really needed elements to achieve the desired, and that's UL. keep it minimalistic and simple:
<ul id="carousel-1" class="carousel clearfix">
<li>
<img src="http://i.imgur.com/eTxMX2T.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/VegKfUt.jpg" alt="" width="646" height="350">
</li>
</ul>
therefore that's the only needed CSS you need:
ul.carousel {
list-style: none;
padding:0;
height: 350px;
white-space:nowrap;
overflow:hidden;
font-size:0;
}
ul.carousel li {
display:inline-block;
margin-left:15px;
}
Regarding your plugin, this is a simple way to achieve the desired, looping a function instead of using a setInterval:
(function($) {
$.fn.carousel = function( options ) {
return this.each(function() {
var ul = this,
w = $("li", ul).outerWidth(true);
(function loop(){
$(ul).delay(2000).animate({scrollLeft : w}, 700, function(){
$(this).append( $('li:first', ul) ).scrollLeft(0);
loop();
});
}());
});
};
}(jQuery));
You can see from the code above that there's no hardcoded width values (beside the delay and animation, but on that later) cause of the use of outerWidth(true);which will account paddings, margins , borders of your LI element.
Now you're building a plugin, right? You might want to allow the user to easily modify default Plugin values like:
$('#carousel-1').carousel({
pause : 3400,
animate : 700
});
simply extend your plugin to accept editable options:
(function($) {
$.fn.carousel = function( options ) {
var S = $.extend({ // Default Settings
pause : 2000,
speed : 700
}, options );
return this.each(function() {
var ul = this,
w = $("li", ul).outerWidth(true);
(function loop(){
$(ul).delay(S.pause).animate({scrollLeft : w}, S.speed, function(){
$(this).append( $('li:first', ul) ).scrollLeft(0);
loop();
});
}());
});
};
}(jQuery));
(function($) {
$.fn.carousel = function( options ) {
var S = $.extend({
pause : 2000,
speed : 700
}, options );
return this.each(function() {
var ul = this,
w = $("li", ul).outerWidth(true);
(function loop(){
$(ul).delay(S.pause).animate({scrollLeft : w}, S.speed, function(){
$(this).append( $('li:first', ul) ).scrollLeft(0);
loop();
});
}());
});
};
}(jQuery));
$(function () { // DOM ready
$('#carousel-1').carousel();
});
ul.carousel {
list-style: none;
padding:0;
height: 350px;
white-space:nowrap;
overflow:hidden;
font-size:0;
}
ul.carousel li {
display:inline-block;
margin-left:15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="carousel-1" class="carousel clearfix">
<li>
<img src="http://i.imgur.com/eTxMX2T.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/VegKfUt.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/YrU0rrW.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/eTxMX2T.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/VegKfUt.jpg" alt="" width="646" height="350">
</li>
<li>
<img src="http://i.imgur.com/YrU0rrW.jpg" alt="" width="646" height="350">
</li>
</ul>
Regarding a better UX, I would also sugget to pause completely your gallery on mouseenter, and restart your animations on mouseleave (though a setInterval might be best suited in that case.)

jquery draggable for multiple divisions

The Drag works properly in the first division but is not working properly in the next one. I need to get it working without changing the div Id/Class name.
Fiddle here: JS Fiddle
HTML:
<div class="track">
<div id="rocket">
</div>
</div>
<br><br><div style="clear:both">
<div class="track">
<div id="rocket">
</div>
</div>
​
CSS:
.track {
height: 400px;
width: 48px;
overflow: hidden;
margin: 10px 0 0 10px;
float:left;
background: #ccc;
}
#rocket{
height:48px;
width:48px;
background: url('http://cdn1.iconfinder.com/data/icons/Symbolicons_Transportation/48/Rocket.png');
position:relative;
top:352px;
}
​
Jquery :
$(document).ready(function() {
$('.track').each(function(){
//rocket drag
$(this).children("#rocket").draggable({
containment: ".track",
axis: "y",
scroll: false,
start: function(event, ui) {
draggingRocket = true;
},
drag: function(event, ui) {
// Show the current dragged position of image
},
stop: function(event, ui) {
draggingRocket = false;
}
});
});
});​
here is the fiddle...
http://jsfiddle.net/zHyA9/30/
1) id should always be unique... so chnaged ur ids to class..
2) added containment: $(this), in ur draggable class
You need to change some thing in html code.
<div class="track">
<div id="rocket">
</div>
</div>
<div style="clear:both">
<div class="track">
<div id="rocket">
</div>
</div>
Here the fiddle: fiddle
You need several changes in your html as well as js code.
Refer this fiddle.
JS:
$(document).ready(function() {
$('.track').live("hover",function(){
//rocket drag
$(this).children(".rocket").draggable({
containment: this,
axis: "y",
scroll: false,
start: function(event, ui) {
draggingRocket = true;
},
drag: function(event, ui) {
// Show the current dragged position of image
},
stop: function(event, ui) {
draggingRocket = false;
}
});
});
});​

Categories

Resources