Jquery and CSS preforming strangely - javascript

I've this section of code (I'll point out where I'm confused, just added that huge wall to incase anyone wanted to really dig in).
anyway, the behaviour is to display these boxes, when you click on a box, the box expands, and displays more information. this works 70% of the time, however, it seems when an image is not chached, when you click the box again to minimize it, it starts to minimize, then pops back out. I'm wondering if this has something to do with the line: if($(this)[0].style.width == '70%'){
If this isn't enough, feel free to ask, and if you want to attempt to replicate the issue:
http://newgameplus.nikuai.net/
Try searching a few games, and clicking on the results. (That's only if what I"m saying isn't making sense though)
Thank you.
$container.on("click", ".box", function (event) {
var description;
var user_id;
var org_img = $(this).find("img").attr("src");
if ($(this)[0].style.width == '70%') {
$(this).find("img").attr("src", org_img);
$(this).css('width', '18%');
$(this).find(".resultData").fadeOut('slow');
$container.masonry('reload');
} else {
var me = this;
value['name'] = $(me).find("p").html();
oldImage = $(this).find("img").attr("src");
$.ajax({
url: 'scripts/php/fetchResultsData.php',
data: {
action: value
},
type: 'post',
dataType: 'json',
success: function (data) {
description = data[0][2];
for (var i = 0; i < $test.length; i++) {
if ($test[i][1][2]['name'] == value['name']) {
pos = i;
break;
}
}
$(me).find("img").attr("src", data[0][4]);
$(me).css('width', '70%');
$(me).append("\
<div class='resultData'>\
<div class='resultName'>" + value['name'] + "</div>\
<div class='resultDesc'>" + description + "</div>\
<div class='reasonDataTitle'> Similar tropes between this game and the searched games </div>\
<div class='reasonData'>" + $test[pos][4] + "</div>\
<div class='wikiLink'><a href='http://wikipedia.org/wiki/" + value['name'] + "'>Wikipedia</a></div>\
<div class='resultLike'></div>\
</div>");
value['clicked'] = 0;
$.ajax({
url: 'scripts/php/userProfile.php',
data: {
action: value
},
type: 'post',
dataType: 'json',
success: function (profileData) {
if (profileData == 'alreadyAdded') {
$(me).children('.resultData').children('.resultLike').html('un-Favourite');
} else if (profileData == 'notLoggedIn') {
$(me).children('.resultData').children('.resultLike').html('Login to add');
} else {
$(me).children('.resultData').children('.resultLike').html('Favourite?');
}
}
});
$(me).on("click", '.resultLike', function (event) {
event.stopPropagation()
value['clicked'] = 1;
$.ajax({
url: 'scripts/php/userProfile.php',
data: {
action: value
},
type: 'post',
dataType: 'json',
success: function (profileData) {
if (profileData == 'removed') {
$(me).children('.resultData').children('.resultLike').html('Favourite?');
} else if (profileData == 'notLoggedIn') {
$(me).children('.resultData').children('.resultLike').html('Login to add');
} else {
$(me).children('.resultData').children('.resultLike').html('un-Favourite');
}
}
});
});
$container.masonry('reload');
}
});
}
});

I would suspect there's a race condition in your effects code. jQuery effects run asynchronously, so $container.masonry('reload') will get called when fadeOut starts rather than after it's finished. If the jQuery Masonry plugin affects the display of any blocks you're fading out (and its documentation indicates that's highly possible), that race condition of both functions running at once will cancel the first one out.
To work around this, try running the Masonry reload in a callback function to fadeOut, like so:
$(this).find(".resultData").fadeOut('slow', function () {
$container.masonry('reload');
});
The reason it happens only sometimes is based on the speed of how things are loading, which would explain why it only happens when certain assets aren't cached.

Related

Animation effect before ajax call

I've watched several tutorials on how to load content without having to refresh the browser. I'm also using history pushState and popstate to update the url dynamically depending on what site that is displaying. However even if this code works, I would like to be able to make som page transition animation effects > call the Ajax function > then make some fadeIn animation effects. So far i've had no luck in trying to do so. I tried to read up on Ajax (beforeSend: function(){}), but the success function seems to execute before the (beforeSend) function. Is there anyone that could point me in the right direction, or tell me what i possibly am doing wrong? I'd appriciate it!
$(document).ready(function() {
var content, fetchAndInsert;
content = $('div#content');
// Fetches and inserts content into the container
fetchAndInsert = function(href) {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
}
});
};
// User goes back/forward
$(window).on('popstate', function() {
fetchAndInsert(location.pathname);
});
$('.buttonlink').click(function(){
var href = $(this).attr('href');
// Manipulate history
history.pushState(null, null, href);
// Fetch and insert content
fetchAndInsert(href);
return false;
});
});
Questions? Just ask!
Thanks beforehand!
/// E !
You need to use callbacks. The provided solutions will work, but not necessarily sequentially. $.animate() and $.ajax both run asynchronously. If unfamiliar with this term, here's a good intro: http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027
Here's what I might do:
fetchAndInsert = function(href) {
$('#some-element').animate({'opacity':'0.0'}, 1000, function () {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
content.animate({'opacity':'1.0'}, 1000);
}
});
});
};
That will fade out whatever is currently in content, fetch the new data, replace what's currently in content, and then fade back in.
I tried to read up on Ajax (beforeSend: function(){}), but the success
function seems to execute before the (beforeSend) function
You can wait for animation to complete before appending new content to html using .queue(), .promise(), .finish()
beforeSend: function() {
element.queue(function() {
$(this).animate({/* do animation stuff */:500}, {duration:5000}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
container.append(content).fadeIn()
})
}
var element = $("#loading").hide();
var container = $("#content");
var button = $("button");
var ajax = {
// do asynchronous stuff
request: function() {
return new $.Deferred(function(d) {
setTimeout(function() {
d.resolve("complete")
}, Math.random() * 5000)
})
},
beforeSend: function() {
element.fadeIn().queue(function() {
$(this).animate({
fontSize: 100
}, {
duration: 2500
}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
element.fadeOut("slow", function() {
$(this).css("fontSize", "inherit");
container.append(content + "<br>").fadeIn("slow");
button.removeAttr("disabled")
})
})
}
}
button.click(function() {
$(this).attr("disabled", "disabled");
$.when(ajax.beforeSend()).then(ajax.request).then(ajax.success)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div id="loading">loading...</div>
<div id="content"></div>
<button>load content</button>
jsfiddle https://jsfiddle.net/ajmL5g1a/
Try this:
fetchAndInsert = function(href) {
// Before send ajax. Do some effects here
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
// After loading. Do some effects here
content.html(data);
}
});
};
My solution:
fetchAndInsert = function(href) {
var timeBeforeAnimation = Date.now(), animationDuration = 500;
/* Do some animation, I assume that with jQuery,
so you probably know how much time is takes - store that
time in variable `animationDuration`. */
/* Run your "before" animation here. */
$.ajax({ ...,
success: function(data) {
/* Check, if request processing was longer than
animation time... */
var timeoutDuration = animationDuration -
(Date.now() - timeBeforeAnimation);
/* ...and if so, delay refreshing the content,
and perform the final animation. */
setTimeout(function() {
content.html(data);
/* Perfom final animation. */
}, Math.max(0, timeoutDuration);
}
});
};
I would probably try using some css for this.
#content {
opacity: 0;
transition: all 1s;
}
#content.fade-in {
opacity: 1;
}
...
const content = $('#content');
const btn = $('.buttonlink');
const success = data =>
content.html(data).addClass('fade-in');
const fetchAndInsert = url =>
$.ajax({ url, cache: 'false' }).done(success);
const getData = function(e) {
e.preventDefault();
content.removeClass('fade-in');
fetchAndInsert($(this).attr('href'));
};
btn.on('click', getData)

jQuery show() method is not working on Chrome and IE browers

I am showing a progress loader on my webpage when there are some processing going on in the background task. The problem I am facing is that the div which contains progress loader always stays "display : none " on Chrome and IE browser. However it works fine on FF and Safari.
Here is the HTML
<div id="progressIndicatorBackground">
<div id="progressIndicator">
<img src="/cms/images/icons/progressIndicator.gif" alt="Loading...">
</div>
</div>
CSS
#progressIndicatorBackground, #preLoaderBackground {
display: none;
height: auto;
width: auto;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 9000;
position: fixed;
background-color:rgba(0, 0, 0, 0.5);
}
JS function for showing and hiding progress loader
function progressIndicator(value) {
if(value) {
$("#progressIndicatorBackground").show();
}
else {
$("#progressIndicatorBackground").hide();
}
}
On several occasion I am calling the progressIndicator function. For e.g. In one of the page I am calling the function (This is just an example function I am using in my web app. There are other functions as well where I am calling progressIndicator function in the same way)
racingSubCategoryBindClick: function(id, parentId) {
if ($('#'+id).css('display') != 'none') {
$("#"+id).unbind();
$("#"+id).live('click', function() {
// Make all the rest of the group not active, not only this active
$('.' + $(this).attr('class') +'.active').removeClass('active');
$(this).addClass('active');
progressIndicator(true);
var menuId = $(this).parent().parent().attr('id'), day;
if (menuId.indexOf(days.today) != -1) day = days.today
else if (menuId.indexOf(days.tomorrow) != -1) day = days.tomorrow
else day = days.upcoming;
$.when(ajaxCalls.fetchEventsForCategory(id, parentId, day)).done(function (eventsMap) {
// There are no events
if (eventsMap.events.length == 0 || eventsMap.events[0].markets.length == 0) {
$('#mainError').show();
$('div.main').hide();
}
else {
$('#mainError').hide();
$('#'+id).addClass('active');
var events = eventsMap.events;
// If there are events
if (events.length > 0) {
var firstActive = racingNavigation.drawAllRaceNumbers(events);
racingNavigation.drawRaceView(events, firstActive);
// if 1st time and no next selections on the right
if ($('#tabaside').css('display') == 'none') racingNavigation.drawNextRaces(false, true, numberOfNextRaces);
$('.racing_nextraces').hide()
}
$('div.main').show();
}
});
$('.rightmain').show();
$('#racing_home').hide();
progressIndicator(false);
});
}
},
When the background task is in progress and I am fetching JSON data the progress indicator should be visible after calling progressIndicator(true) and as soon as the processing is completed the display attribute should be set to none as I am calling progressIndicator(false) after everything is done. But the status of progressIndicatorBackground is never set display : block on Chrome and IE.
P.S -> I am using latest version or Chrome and IE.
P.S.S -> I have tried modifying my function to but no luck. The problem still persist on Chrome and IE.
function progressIndicator(value) {
if(value) {
$("#progressIndicatorBackground").css("display", "block");
}
else {
$("#progressIndicatorBackground").css("display", "none");
}
}
The main problem was because of using synchronous AJAX calls. It does freezes Chrome and IE and stop any other events to fire up.
Progress loader wasn't working because it was waiting for the synchronous ajax calls to finish loading the event.
Original AJAX call
fetchEventsForCategory: function (categoryId, parentId, day) {
var to = (date.getTo(day) == null) ? '' : '&to=' + date.getTo(day);
return $.ajax({
url: "/billfold-api/betting/events",
type: "POST",
data: 'scid=' + categoryId + '&pcid=' + parentId + '&from=' + date.getFrom(day) + to,
dataType: "json",
async: false,
});
},
Modified AJAX call with success callback
fetchEventsForCategory: function (categoryId, parentId, day) {
var to = (date.getTo(day) == null) ? '' : '&to=' + date.getTo(day);
return $.ajax({
url: "/billfold-api/betting/events",
type: "POST",
data: 'scid=' + categoryId + '&pcid=' + parentId + '&from=' + date.getFrom(day) + to,
dataType: "json",
async: true,
success: function(data) {
progressIndicator(false);
}
});
},
In my JS function where I was calling the progress loader. I removed progressIndicator(false);and instead put it under success function in my ajax call itself.
In my experience display:none can make things buggy and should only be used as a last resort. Take a look at this article here for alternatives. Also I found sometimes adding :hidden helps in making jquery show a hidden or display:none element. So for instance $("#progressIndicatorBackground:hidden").show(); might get it to work.

Ask for confirmation in the same div by swapping its contents?

I have the following html:
<div class="modify">
Change<br>
Delete
</div>
And an according jQuery:
$(".delete").click(function(){
var parent_element = $(this).closest('li');
var url_string = $(this).attr('id') + '/delete/';
$.ajax({
type: 'POST',
url: url_string,
success: function(response) {
parent_element.fadeOut(600, function() {
parent_element.remove();
});
}
});
});
Now I want to ask the user for confirmation within .modify. The current contents .change and .delete should disappear and be swapped for something like:
Are you sure?
Yes
No
This is how it would look in general:
If the user presses Delete the contents should change like this:
As you might have figured, if the user chooses
Yes, the parent_element should be deleted
No, .modify should return back its original state
What would be the idiomatic way to do this?
I modified my answer after your additional note.
codepen live example
What about..
HTML
<div class="modify askState">
<div class="ask">
Change<br>
Delete
</div>
<div class="confirm">
<span class="confirmDeleteText">Are you sure?</span><br/>
Yes
No
</div>
</div>
JS
var askState = true, modifyElement = $(".modify");
$(".delete").click(function(){
askConfirmation();
});
function askConfirmation() {
toggleState();
}
$(".confirmYes").click(function() {
var parent_element = $(this).closest('li');
var url_string = $(this).attr('id') + '/delete/';
$.ajax({
type: 'POST',
url: url_string,
success: function(response) {
parent_element.fadeOut(600, function() {
parent_element.remove();
});
}
});
});
$(".confirmNo").click(function() {
toggleState();
});
function toggleState() {
if( askState ) {
modifyElement. addClass("confirmState").removeClass("askState");
} else {
modifyElement.removeClass("confirmState"). addClass("askState");
}
askState = !askState;
}
CSS
.confirmState .ask {
display: none;
}
.askState .confirm {
display: none;
}
I added HTML so that the original text wont get lost (if you do innerHTML=newText then you cannot restore its innerHTML properly without backing up).
Please also note that its fairly readable:
IF I click "delete", then ASK confirmation (semantic code).
IF I ask confirmation, then CHANGE State (functional code, could have been nice to make toConfirmState() in stead of toggleState()).
(then in new state)
IF I click "confirmYes", then DO perform code (functional code, could have been nice to make a delete function (semantic code))
$(".delete").click(function(){
var ans = confirm("Are You Sure To Delete This Record...");
if(ans)
{return true;}
else
{return false;}
... ur code so on
}

jQuery / Ajax Add Class to an LI not working

jQuery / Ajax Add Class to an LI not working. Trying to add the 'open' class to a LI, that opens my 'floating cart' area when an item has been added to the cart. However, the 'open' class just. won't. apply. Not sure why.
I'm also using the Bootstrap framework, and jQuery.
My Code is:
function ShoppingCartAddAJAX(formElement, productNumber) {
formElement = $(formElement);
$.ajax({
type: "POST",
url: "dmiajax.aspx?request=ShoppingCartAddAJAX",
data: formElement.serialize(),
dataType: "json",
success: function (response) {
if (response.Status == "WishListSuccess") {
var url = "productslist.aspx?listName=" + response.listName + "&listType=" + response.listType;
$(location).attr('href', url)
} else if (response.Status == "Success") {
if (response.Status == "Success") {
$.ajax({
type: "GET",
url: "dmiajax.aspx?request=FloatingCart&extra=" + rnd(),
dataType: "html",
success: function (response) {
$('#floating').addClass('open');
var floatingCart = $("ul.dropdown-menu.topcartopen");
if (floatingCart.length == 0) {
floatingCart = $('<ul class="dropdown-menu topcart open"></ul>').insertBefore("#floating-cart");
floatingCart.hoverIntent({
over: function () {},
timeout: 200,
out: function () {
$(this).stop(true, true).filter(":visible").hide("drop", {
direction: "down"
})
}
})
}
floatingCart.html(response);
$("html, body").scrollTop(0);
var floatingCartTbody = floatingCart.find("tbody");
floatingCartTbody.find("tr").filter(":last").effect("highlight", {
color: "#B3B3B3"
}, 3500);
floatingCart.fadeIn()
}
});
if (response.CartItemCount) {
if (response.CartItemCount == "0") {
$("a.cart-tools-total").html("Shopping Cart<span class=\"label label-orange font14\">0</span> - $0.00")
} else {
$("a.cart-tools-total").html("Shopping Cart <span class=\"label label-orange font14\"> " + response.CartItemCount + " Item(s) </span> - " + response.CartItemTotal + " <b class=\"caret\"></b>")
}
}
formElement.find("select option").attr("selected", false);
formElement.find("input:radio").attr("checked", false);
formElement.find("input:checkbox").attr("checked", false);
formElement.find("input:text").val("");
if (formElement.find(".personalization-toggle").length > 0) {
formElement.find(".person-options").hide()
}
if (formElement.find(".attribute-wrap.trait").length > 0) {
formElement.find(".stock-wrap").remove()
}
} else if (response.Error) {
alert(response.Error)
}
}
}
})
}
The line where I'm tring to add it to the LI is:
$('#floating').addClass('open');
The LI is:
<li id="floating" class="dropdown hover carticon cart">
The LI's ID is floating, I figured that'd add the class of 'open' to it. NOPE. For some reason, just not happening.
And, just for the sake of including it, the live environment is here: http://rsatestamls.kaliocommerce.com/
Try changing it to:
$('#floating').attr("class", "open");
Try adding this to your ajax request. It maybe is getting an error:
$.ajax({
type: "GET",
url: "dmiajax.aspx?request=FloatingCart&extra=" + rnd(),
dataType: "html",
success: function (response) {
$('#floating').addClass('open');
var floatingCart = $("ul.dropdown-menu.topcartopen");
if (floatingCart.length == 0) {
floatingCart = $('<ul class="dropdown-menu topcart open"></ul>').insertBefore("#floating-cart");
floatingCart.hoverIntent({
over: function () {},
timeout: 200,
out: function () {
$(this).stop(true, true).filter(":visible").hide("drop", {
direction: "down"
})
}
})
}
floatingCart.html(response);
$("html, body").scrollTop(0);
var floatingCartTbody = floatingCart.find("tbody");
floatingCartTbody.find("tr").filter(":last").effect("highlight", {
color: "#B3B3B3"
}, 3500);
floatingCart.fadeIn()
}
error: function(objAjax,state,exception){
console.log('exception: '+exception+'. State: '+state);
},
});
Then, you will be able to check (at Firebug or other app) if your request is working right.
I suspect you are not correctly selecting the #floating element. Sometimes the element is not visible with only the ID and you must be a little more specific with the selectors.
We would need to see exactly the source for the rendered page to be sure what to put, but try doing this:
Add a button onto the page that you can use to test if you found the correct selector:
<input id="mybutt" type="button" value="Tester Click">
Next, add this javascript/jquery code and -- one at a time -- comment the test selector that failed, and uncomment the next attempt:
$('#mybutt').click(function() {
var test = $("#floating");
//var test = $("li #floating");
//var test = $("ul li #floating");
//var test = $("ul > li #floating");
if ( test.length > 0 ) {
alert('Found this: ' + test.attr('id') );
}
});
Once you are certain that you have the correct selector, then your original code -- using the correct selector -- should work:
$('#the > correctSelector').addClass('open');
Note: the above code uses jQuery, so ensure you are including the jQuery library on the page (usually between the <head> tags, like this:
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</head>

jquery .on() is not triggering

I have the following code:
console.log($(".resultLike"));
$(".resultLike").on("click", function (event) {
alert('test');
event.stopPropagation();
alert('test1');
value['clicked'] = 1;
$.ajax({
url: 'scripts/php/userProfile.php',
data: {
action: value
},
type: 'post',
dataType: 'json',
success: function (profileData) {
if (profileData == 'removed') {
$(me).children('.resultInside')
.children('.resultData')
.children('.resultLike').html('Favourite?');
} else if (profileData == 'notLoggedIn') {
$(me).children('.resultInside')
.children('.resultData')
.children('.resultLike').html('Login to add');
} else {
$(me).children('.resultInside')
.children('.resultData')
.children('.resultLike').html('un-Favourite');
}
}
});
});
My expectations is that when you click on the div resultLike, then it will preform the function(). However, it does nothing. I have two alert() calls in there, and neither is being called. The output of console.log() is as follows:
[
<div class=​"resultLike searchBarGameLike">​</div>​
]
That proves it's being put on the page. Any help would be appreciated, thanks.
EDIT:
I think it should be mentioned that I'm actually using two .on() events.
This is actually all my code. The issue is around the
$("body").on("click", ".resultLike", function(){
Line, it's not working.
$searchedGamesContainer.on(
"click",
".box",
function(event){
if(!$displayLock){
$displayLock = true;
var description;
var user_id;
if($(this)[0].style.width == '75%'){
var org_img = $(this).children(".resultInside").find("img").attr("src");
$(this).children(".resultInside").append("<img src='"+org_img+"' id='imgId'/>");
$(this).children(".resultInside").css('height','auto');
$(this).css('width', '18%');
$(this).css('height', 'auto');
$(this).find(".resultData").fadeOut('fast');
setTimeout(function(){$searchedGamesContainer.masonry('reload');},300);
setTimeout(function(){$displayLock = false;},1000);
}else{
var me = this;
var pos;
largeImage= new Image();
value['name']=$(me).find("p").html();
oldImage = $(this).find("img").attr("src");
for(var i = 0; i<$searchBarGames.length; i++){
if($searchBarGames[i][5] == value['name']){
pos = i;
break
}
}
description = $searchBarGames[pos][2];
$(me).find("img").hide();
largeImage.src = $searchBarGames[pos][4];
$(me).find("img").attr("src",largeImage.src);
$(me).children(".resultInside").css('height','400px');
$(me).css('width', '75%');
$(me).children(".resultInside").html("\
<div class='resultData'>\
<div class='resultImg'><img src='"+ largeImage.src +"'></div>\
<div class='resultName'>" + value['name'] + "</div>\
<div class='resultDesc'>" + description +"</div>\
<div class='wikiLink searchBarGameWiki'><a href='http://wikipedia.org/wiki/" + value['name'] + "'>Wikipedia</a></div>\
<div class='resultLike searchBarGameLike'></div>\
</div>");
value['clicked']=0;
$.ajax({
url:'scripts/php/userProfile.php',
data:{action:value},
type: 'post',
dataType: 'json',
success:function(profileData){
//logic
}
});
console.log($(".resultLike"));
$("body").on("click", ".resultLike", function(){
alert('test');
event.stopPropagation();
alert('test1');
value['clicked']=1;
$.ajax({
url:'scripts/php/userProfile.php',
data:{action:value},
type: 'post',
dataType: 'json',
success:function(profileData){
//logic
}
});
}
);
}
}
}
);
try
$("body").on("click", ".resultLike", function(){
// your code goes here.
});
Your implementation will likely not be bound if the div.resultLike is added dynamically
This problem actually ended up being completely because of CSS.
For the div element I wanted the alerts on, I had markup to look like a button.
However, I noticed this:
.resultLike:active {
position:relative;
top:1px;
z-index:1235;
}
I'm not 100% why, but I think this was actually changing where the button was when clicking it. Meaning as soon as it was active, it wasn't where your mouse was. I could be wrong, but this fixed it.

Categories