jquery append not showing in safari - ajax

I have a working progress bar inside a Django app. Except in Safari the bar shows up only under weird circumstances.
First, I have the progress bar appended via jquery/ajax combination:
var $progress = $('<div id="upload-progress" class="upload-progress"></div>')
.appendTo($('#webfileuploadform'))
.append('
<div class="progress-container">
<div class="progress-info">uploading 0%</div>
<div class="progress-bar"></div>
</div>');
//This is all one string, I've just broken it up like this so it's readable.
//Called on form submit
$.ajax({
...yada yada...
success: function(data){
$progress.show(); <-- shows the div(s)
...more yada...
In Firefox and Chrome, this all works fine. In Safari, this is actually working as well, just not displaying. When I open up Safari developer tools and drill down to the <form> I can see that the DOM elements are being appended to the form as they should. The width of the progress bar and the text of the progress-info div are updating correctly as well (in developer tools). The problem is the #upload-progress div is not showing in the browser even though I see it exists in the developer tools!
What blows my mind is that if I click the grey 'x' in Safari to force stop the page, the progress bar then shows up!
Another weird thing is that once I click the form submit, if I highlight any dom element in my developer tools the entire page is blanked out with the same color I have on a wrapper div around the entire page! Also, if I highlight an element in the developer tools before I click the submit button, then click, the page just jumps straight to blanking out again. I don't even have to move around in the developer tools.
Very strange behavior. I have no idea what's going on...
I've read some things saying safari doesn't redraw the DOM when css is applied with jquery? I don't think that's true, but does this have something to do with it?
UPDATE
So this problem persists even outside the ajax function, but works outside the submit handler. That is:
problem persists when I click the submit button (no ajax code here)
$('#webfileuploadform').submit(function(){
$('#webfileuploadform').append('<div id="upload-progress" class="upload-progress">asdf</div>');
$('#upload-progress').append('<div class="progress-container"><div class="progress-info">uploading 0%</div><div class="progress-bar"></div></div>');
...
});
same code outside of the submit handler works
$('#webfileuploadform').append('<div id="upload-progress" class="upload-progress">asdf</div>');
$('#upload-progress').append('<div class="progress-container"><div class="progress-info">uploading 0%</div><div class="progress-bar"></div></div>');
$('#webfileuploadform').submit(function(){
...
});

This is a problem with webkit. The bug report is here. Webkit cannot handle XMLHttpRequests after a form submit. A workaround that I used was to submit the form to a target iframe. Turns out the bug only happens when the target is the same document that the form is in...
Changed target:
<form action="my_django_view" method="post" enctype="multipart/form-data" id="formID" target="theIframeName">
...
</form>
Hidden iframe on page:
<iframe name="theIFrameName" id="style-me-with-display-none"></iframe>
Although it should be noted I'm working with legacy code here, which is why I'm handling file objects with forms. If you are starting from scratch, there are better ways to handle file objects nowadays and this method should be avoided.

Related

JQuery Waypoints - infinite scroll "shortcut" makes unnecessary and erroneous AJAX requests?

Running into a problem while trying to implement Waypoints infinite scroll example from http://imakewebthings.com/waypoints/shortcuts/infinite-scroll/.
Here is a JSFiddle to demonstrate my issue: http://jsfiddle.net/jmankin/75g6cap2/5/
HTML
<div class="infinite-container">
<div class="infinite-item">Not much content</div>
</div>
<a class="infinite-more-link"
href="/gh/get/response.html/jermifer/jsfiddle/tree/master/waypoints-infinite/"
>Loading...</a>
JS
var waypoint = new Waypoint.Infinite({
element: $('div.infinite-container')[0]
});
In instances where the 1st "infinite-more-link" is "above the fold" of the viewport on page load (i.e. the "inifinite-item" content is too short to require scrolling), the script correctly makes an AJAX call to the link href and loads the requested content.
However, it then prematurely--and seemingly incorrectly--proceeds to make the AJAX call to the 2nd "infinite-more-link" even though that is "below the fold" when it loads.
Secondly, from then on, scrolling to the bottom of the page (what would technically now be the 2nd "infinite-item" content element) will cause an AJAX call to the originally requested URL (the one that the client explicitly addressed), which is completely baffling. Under normal circumstances, it does this over and over again. In jsFiddle, it just does it the once, but that still gives you an idea of what I mean.
(Note: I'm not able to know ahead of time the length of the content I'd be loading, which is why I can't guarantee that the user will have to scroll down to see the 1st "infinite-more-link.")
I tried to contribute to solve this issue in the library in this link, please check that: https://github.com/imakewebthings/waypoints/issues/384 - Best wishes!

Wiring up Ajax.BeginForm that didn't exist during doc.ready?

I have a MVC page that loads a Partial via a Ajax.ActionLink, which works, and then the loaded Partial contains a form that has Ajax.BeginForm. This form is not getting wired up to unobtrusive ajax, and instead is performing a page refresh(I verified this in the Network log of the browser that shows the initiator when I click submit is the browser instead of jquery).
What I believe is the issue is that since the form didn't exist when the page is loaded(but later is added via the Ajax.ActionLink), then unobtrusive ajax didn't see the data-ajax attributes on the newly added form and wire up the necessary events. I'm assuming that only happens at document.ready, and the ajax form didn't exist then.
Is there something I can do to say "hey Unobstrusive Ajax, please look at my page again now that I have some new elements that are marked with data-ajax and wire them up"?
Thanks.
Looking at the unobtrusive ajax source, it has this:
$("form[data-ajax=true]").live("submit", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
...
The form tag generated looks like this:
<form action="/Path/Create" class="form-horizontal" data-ajax="true" data-ajax-method="post" data-ajax-mode="replace" data-ajax-update="#ParentContainer" id="PathForm" method="post" novalidate="novalidate">
As far as I can tell the selector on the .live event should be picking up on the new form when it's loaded onto the page. The form is inside a bootstrap modal however, so I don't know if that would be preventing the event from bubbling up somehow.
I can even run this in Chrome console:
$("form[data-ajax=true]").live("submit", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault(); });
And it returns the form element successfully, but when I click submit it still does a full page refresh. I would expect it to at least do nothign since I wired it up to preventDefault.
To answer my own question regarding unobtrusive ajax and dynamically loaded content, it should work fine out of the box. The way it wires up to events with .live(deprecated, still works currently) should detect forms that are loaded dynamically onto the page. So apparently it doesn't suffer the same problem that unobtrusive validation does.
Our problem was unrelated to that. We were using bootstrap modal which spawned a modal div from inside a form. Since the modal then loaded another page containing a form, we realized we had a form within a form (even though it didn't really look that way since the other form was in a modal).
To solve this we moved the declaration of the modal div in the first form outside of the form. We could still have a link that referenced the modal to show it, but not the modal's inner form wouldn't be nested in the first form.
I believe the reason this caused both the .live and .on methods to not catch the event was because they depend on the event to bubble up to the document, and it bubbled up only as far as the outer form which was not an ajax form, thus did not match the selector.
Another solution would have been to write .on more like this so that the event would be caught when it bubbled up to the container of the inner form, instead of scoping it to the document where the event would reach the outer form first.
$('#innerModalId').on("submit", "form[data-ajax=true]", function (evt) {
evt.preventDefault();
...
return false
});
However since this was part of a library, that's not an ideal solution as I would have needed to repeat their code. We didn't get as far as updating unobtrusive ajax:
http://nuget.org/packages/jQuery.Ajax.Unobtrusive
But I think we would have still had the problem since even with .on it still didn't work due to our page structure problem.

How to create a Like button in a "display:none" context?

The Like button plugin doesn't appear, if one of its containers is display:none when the page loads, and made visible later with display:block.
Problem detected in Firefox (my version 15.0.1) only.
What can I do?
when you make the element visible, you should add your fb like plugin to dom
IE
<div id="showfb">mouseoverme</div>
<div style="display:none" id="facebutton"></div>
<script>
var fbbutton = document.getElementById("facebutton");
document.getElementById("showfb").onmouseover = function(){
// first visible
fbbutton.style.display='block';
// then add fb html5
fbbutton.innerHTML = '<div class="fb-like" ......... ></div>';
};
</script>
in alternative, try
width:0;height:0;overflow:hidden
instead of
display:none
and
width:auto;height:auto;overflow:visible
instead of
display:block
I don't know what is the reason of this bug (FB or FF), but I've solve that problem by show my element by default in FF only:
#-moz-document url-prefix() {#exe-article-social-tools { display: block; }}
https://developers.facebook.com/docs/reference/javascript/
The fb-root tag
The JavaScript SDK requires the fb-root element to be present in the page.
The fb-root element must not be hidden using display: none or visibility: hidden, or some parts of the SDK will not work properly in Internet Explorer.
It took me an entire day to figure it out, but being logged in on Facebook with a "test user" renders the like button invisible. In my case, I was always logged in with my test user on Firefox, while logged out / logged in with my regular Facebook user in Chrome (and I initially thought this was a browser issue).
However, the solution was as easy as loggin off the test user.
It is specified in the FB docs that not all features are enabled for test users (and the like button is one of those features), but I'd thought that it would at least get rendered.
Anyway, I hope this helps someone.
I had a number of different invisible divs on my page where fb-like buttons was hidden. When one of div shown, no fb-like button appears in it. Solution worked for me is to relaunch FB.init manually each time when invisible div reveals.
FB is a global function being added into your window object since you call for remote facebook api by url like http://connect.facebook.net/en_US/all.js. So since this remote script attached to your DOM you can run something like
FB.init({
appId : '346094915460000', // App ID
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
You can dynamically add like button html5 code to the DOM and then run the FB parser again to generate the like button:
fbbutton.innerHTML = '<div class="fb-like" ... ></div>';
FB.XFBML.parse();

Loading forms with .load kills the submit button in Firefox

I am currently loading several forms into a webpage with:
$(document).ready(function () {
$('#content').load('php_script.php', function() {
$(this).find('#someForm').ajaxForm(function() {
alert('Success!');
});
$(this).find('.someOtherForm').ajaxForm(function() {
alert('Success!');
});
});
});
This works in Chrome, Chromium and IE who loads the forms and everything works as it should (Clicking submit sends a request to the php-script defined in the form's action, which adds stuff to a db, and shows the alert dialog). In Firefox (v10.0.2) this code loads the forms into the DOM and displays them, but when clicking submit on any of the forms nothing happens.
At first I suspected ajaxForm, but changing the above code to:
$(document).ready(function () {
$('#content').load('php_script.php');
});
yields almost the same result, the difference being that the user is sent to the script defined as the action (Except for Firefox, where nothing happens).
How do I make Firefox not kill the submit button?
I solved it, bad HTML from my side:
<table><form ...>
<tr>...</tr>
</form></table>
Instead it should look like:
<form ...><table>
<tr>...</tr>
</table></form>
The validator did not catch this since it was loaded via jQuery (and I forgot to validate the page serving the forms), and Firefox buggered out.
The code above looks ok to me...
Have you had a look in firebug if there are any errors? Maybe there is a conflicting Id or something.
Maybe the form isnt completely loaded into the dom yet, might be worth giving live binding a try
Found this in the docs:
...jQuery uses the browser's .innerHTML property to parse the retrieved document and insert it into the current document. During this process, browsers often filter elements from the document such as , , or elements. As a result, the elements retrieved by .load() may not be exactly the same as if the document were retrieved directly by the browser...
If you inspect the form is it the same as in other browsers?

Ajax content getting loaded multiple times with JQuery UI Tabs

Hi
I am basically calling individual php pages (and their forms) via AJAX in separate JQueryUI tabs. The code is something like:
<div id="dock">
<ul>
<li>Home</li>
<li>Profile</li>
<li>Statistics</li>
<li>Pings</li>
</ul>
</div>
...
jQuery(function($) {
jQuery('#dock').tabs({'collapsible':false});
});
1) Now every time I click on the tabs, their content gets loaded fine but the previous content does not get destroyed. As a result, imagine if a tab was clicked (loaded) N times - a form is also submitted N times. As far as I have understood, multiple bindings occurs here and hence the multiple form submits. How can I prevent this?
2) I have separate forms in each tab. When multiple tabs are selected, multiple forms get loaded. Now if I submit a value (via AJAX) in any one of the form, the data is submitted across all the forms which were previously loaded (Checked with Firebug). How can I prevent this again ?
PS: Enabling caching in tabs partially solved problem #1, but does not help with problem #2.
PPS: I went through quite a few similar posts but I am still stuck :(
Thanks !
From the little bit of code there, it looks like your problems may arise from using the same page (index.php) for each of the tabs. Check these:
Does each form have a separate ID? They should.
Disable caching in both 'cache' and 'ajaxOptions'. This will make sure content is refreshed (and removed) with each click.
How are your forms submitting via AJAX? Regardless of the method, you should handle your form bindings for each tab select through the "load" option.
Try this...
$("#dock").tabs({
load: function (event, ui) {
//setup new content bindings here
},
cache: false,
ajaxOptions: {
cache: false
}
});

Resources