How to wait until HTML file loads? - asynchronous

In a page I am working on I replace the HTML code in a DIV with different HTML, then using Javascript I insert additional HTML into a DIV the new code using innerHTML.
If that is confusing, the original HTML contained a form, the HTML that replaced it contains the response to the form's Submit, and the code I want to insert is the information from the form.
This seemed to work as long as I had alert code in the script, which I use to check the progress as I debug this. Once I removed the all of alert lines the insert would fail. I figure it has to do something with the asynchronous nature of page rendering, so I think I need to find a way to make sure the new HTML code has loaded before I try writing to the DIV it contains.
In the code below the script fails at show_member_info unless I uncomment the preceding alert line.
function handle_join(X)
{
do_trace('handle_update');
get_member_info();
send_emails(X);
do_trace('clear content');
document.getElementById("members_content").innerHTML='';
document.getElementById("members_image").innerHTML='';
do_trace('load content');
Load_HTML('members/joinConf.html','members_content');
// alert('show_member_info');
show_member_info();
show_trace();
}
How do I determine when the new HTML has loaded and is ready to be manipulated?
Thanks, Mike

The question is a bit dry, but from what i can understand the problem is that you are not awaiting Load_HTML and that's causing some issue with show_member_info.

Related

Print Friendly Page

So I would like to be able to have a print button for entries in our database so users can print an entry via a print friendly "form".
My thought was to create a separate page, add labels and have those labels pull the relevant information.
I know I can add the open widget information via this code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.TestPrint);
But I'm running into a few problems:
I can't get the page to open in a new window. Is this possible?
window.open(app.pages.TestPrint);
Just gives me a blank page. Does the browser lose the widget source once the new window opens?
I can't get the print option (either onClick or onDataLoad) to print JUST the image (or widget). I run
window.print();
And it includes headers + scroll bars. Do I need to be running a client side script instead?
Any help would be appreciated. Thank you!
To get exactly what you'd want you'd have to do a lot of work.
Here is my suggested, simpler answer:
Don't open up a new tab. If you use showPage like you mention, and provide a "back" button on the page to go back to where you were, you'll get pretty much everything you need. If you don't want the back to show up when you print, then you can setVisibility(false) on the button before you print, then print, then setVisibility(true).
I'll give a quick summary of how you could do this with a new tab, but it's pretty involved so I can't go into details without trying it myself. The basic idea, is you want to open the page with a full URL, just like a user was navigating to it.
You can use #TestPrint to indicate which page you want to load. You also need the URL of your application, which as far as I can remember is only available in a server-side script using the Apps Script method: ScriptApp.getService().getUrl(). On top of this, you'll probably need to pass in the key so that your page knows what data to load.
So given this, you need to assemble a url by calling a server script, then appending the key property to it. In the end you want a url something like:
https://www.script.google.com/yourappaddress#TestPage?key=keyOfYourModel.
Then on TestPage you need to read the key, and load data for that key. (You can read the key using google.script.url).
Alternatively, I think there are some tricks you can play by opening a blank window and then writing directly to its DOM, but I've never tried that, and since Apps Script runs inside an iframe I'm not sure if it's possible. If I get a chance I'll play with it and update this answer, but for your own reference you could look here: create html page and print to new tab in javascript
I'm imagining something like that, except that your page an write it's html content. Something like:
var winPrint = window.open('', '_blank', 'left=0,top=0,width=800,height=600,toolbar=0,scrollbars=0,status=0');
winPrint.document.write(app.pages.TestPage.getElement().innerHTML);
winPrint.document.close();
winPrint.focus();
winPrint.print();
winPrint.close();
Hope one of those three options helps :)
So here is what I ended up doing. It isn't elegant, but it works.
I added a Print Button to a Page Fragment that pops up when a user edits a database entry.
Database Edit Button code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showDialog(app.pageFragments.FragmentName);
That Print Button goes to a different (full) Page and closes the Fragment.
Print Button Code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.ModelName_Print);
app.closeDialog();
I made sure to make the new Print Page was small enough so that Chrome fits it properly into a 8.5 x 11" page (728x975).
I then created a Panel that fills the page and populated the page with Labels
#datasource.item.FieldName
I then put the following into the onDataLoad for the Panel
window.print();
So now when the user presses the Print Button in the Fragment they are taken to this new page and after the data loads they automatically get a print dialog.
The only downside is that after printing the user has to use a back button I added to return to the database page.
1.
As far as I know, you cannot combine window.open with app.pages.*, because
window.open would require url parameter at least, while app.pages.* is essentially an internal routing mechanism provided by App Maker, and it returns page object back, suitable for for switching between pages, or opening dialogs.
2.
You would probably need to style your page first, so like it includes things you would like to have printed out. To do so please use #media print
ex: We have a button on the page and would like to hide it from print page
#media print {
.app-NewPage-Button1 {
display : none;
}
}
Hope it helps.
1. Here is how it is done, in a pop up window, without messing up the current page (client script):
function print(widget, title){
var content=widget.getElement().innerHTML;
var win = window.open('', 'printWindow', 'height=600,width=800');
win.document.write('<head><title>'+title+'/title></head>');
win.document.write('<body>'+content+'</body>');
win.document.close();
win.focus();
win.print();
win.close();
}
and the onclick handler for the button is:
print(widget.root.descendants.PageFragment1, 'test');
In this example, PageFragment1 is a page fragment on the current page, hidden by adding a style with namehidden with definition .hidden{display:none;} (this is different than visible which in App Maker seems to remove the item from the DOM). Works perfectly...
2. You cannot open pages from the app in another tab. In principle something like this would do it:
var w=window.parent.parent;
w.open(w.location.protocol+'//'+w.location.host+w.location.pathname+'#PrintPage', '_blank');
But since the app is running in frame nested two deep from the launching page, and with a different origin, you will not be able to access the url that you need (the above code results in a cross origin frame access error). So you would have to hard code the URL, which changes at deployment, so it gets ugly very fast. Not that you want to anyway, the load time of an app should discourage you from wanting to do that anyway.

jquery .load( ) and trigger function AFTER new content loads? just like JavaScript onload event

Using jquery, I am swapping some content in a web page by use of jquery's .load() function. I want to trigger an event immediately once the content has actually been loaded, but not before and not after. I'm up for any graceful solution! Why? In this instance, I'm doing the old "fade out, swap content, fade in" approach. My problem? I want to fade back in AS SOON AS the new content is loaded.
Caveats:
Using a callback function as in $('#object').load(url, callback) triggers as soon as .load() function successfully executes (before the content is actually loaded). Useless here.
Using a timed delay for fading back in is not a graceful solution. Very "clunky", especially for those with faster Internet connectivity.
JavaScript's onload event trigger does not work, as the element that .load() is altering has already loaded into the HTML DOM.
jquery's .ready() function also does not work, as the actual element is already loaded.
I do not want to create an onload or .ready() sub-container element, because that's a workaround for what I'm actually trying, though it might be as graceful or more.
How can I fire a function when (and only when) the new .load() content is finally loaded, just like JavaScript's onload event does? Thanks much.
EDIT As it turns out, the jquery .load() function is working flawlessly, and I'm approaching this wrong.
Once the .load() function completes successfully, it calls any "callback" function included by the programmer, just like any other jquery function that accepts a callback as one of its "arguments".
The .load() function is complete once it either errors or successfully begins the HTML replacement and loading of new content, but that is IT! The content will then take however long it takes to load, but your .load call is already complete before that. Therefore, expecting the callback to run after the .load content has loaded will only disappoint you. ;)
I hope others can learn from this just as I did, including those who thought what I thought was the case. Proof: as stated in the jquery ajax .load page, the callback is executed when the request completes, not when the load completes. Eureka. Whoops. /EDIT
Try using a different method rather than load(), I would suggesting using get(). Something like this may be more useful to you...
var jqxhr = jQuery.get(url,vars);
jqxhr.success(function(data){
# This will only be called once the remote content has been loaded in
# The data will then be stored in the data param and can be used within your site
});
jqxhr.error(function(data){
# Something went wrong, never mind lets just handle it gracefully below...
});
I hope this is a solution to your problem!
For more information see http://api.jquery.com/jQuery.get/
I have quickly created this function below that may be of help to you... its not refined!
jQuery.fn.loadNewData = function() {
var object = jQuery(this);
var jqxhr = jQuery.get(arguments[0]);
// check for success
jqxhr.success(function(data) {
// load the data in
object.html(data);
});
jqxhr.error(function(){
alert('Failed to load data');
});
}
Using this you can call how similarly to how you would call the load() function.
jQuery('#object').loadNewData(url);
I think you might be misinterpreting what you are seeing. Depending on the browser you are using you won't see the new elements in the browser if you pop up an alert in the callback because it won't rerender the DOM until you cede control back to the browser. That doesn't mean you can't grab the new elements from the DOM and start fading them in. Take the following jsfiddle: http://jsfiddle.net/ttb55/8/ in Chrome it will show the first div when the second alert is up, then fade in the second div. In IE it won't show the first div when the second alert is up, this is the state I think you are in after load during the callback, but it still works once you hit ok because everything was in the DOM as promised.
Upon reading the jQuery docs pages for jQuery.get() and jQuery.load(), the callback argument is quoted as the following:
"A callback function that is executed if the request succeeds."
Let me stress the terms "request" and "succeeds". The request may succeed, but that does not mean that the content is loaded. Same problem as .load() — the functions aren't built the way I was thinking.
If I want to trigger an event once the new content finally loads, I'll need to take a different approach.
I could use the JS onload event, and trigger it by completely replacing an HTML element (having the replaced code contain an onload property). EDIT: Note that using HTML iframe elements is pretty awful, primitive, and "clunky". I just need to find a better way to trigger a function as soon as loading the new content finishes.
Also, I could use jQuery to check the .ready() state of new content, but ("AFAIK" / as far as I know) that will only work if the checked content is a new HTML element, not a preexisting HTML element whose interior content is changed. The jQuery .ready() status of any preexisting element will (AFAIK) already be shown as "ready" despite if new content is loading. Perhaps I am wrong about this, and I would like to be corrected if so.
Unless otherwise notified, this answer will be marked as the correct one. The original question was mistaken that .load() was all I needed. Cheers!

Adding Refresh Tag to View

I need a view to refresh automatically every 20 seconds, and have added the following code to the view header via the views GUI - with no success. The code (or portions of it) are simply displayed on the view and no updating is performed. I've tried omitting both and just the ending ?php statement. If someone can tell me the proper code to use, or a better approach at updating the view automatically, I'd be very appreciative. Thanks.
print "<meta http-equiv=\"refresh\" content = \"20\" />;
There are a few modules that can take care of this for you via AJAX without refreshing the page.
This should take care of everything for you: http://drupal.org/project/ajax_views_refresh
Be sure to get the main AJAX module as the base.
A more complex one, if you want to code a bit: http://drupal.org/project/live_update
If you want to just refresh nodes and the view is on them you can do the old school refresh with this... http://drupal.org/project/refresh
Your code isn't coming through, but if it's php code make sure that the input format for the view header is set to "PHP Code"
Read the fine print under the text area. Sometimes PHP Code format doesn't require <?php tags. Some modules implement this differently.
Use drupal_set_html_head
For example:
drupal_set_html_head('<meta http-equiv="refresh" content = "20" />');

ajaxSubmit and Other Code. Can someone help me determine what this code is doing?

I've inherited some code that I need to debug. It isn't working at present. My task is to get it to work. No other requirements have been given to me. No, this isn't homework, this is a maintenance nightmare job.
ASP.Net (Framework 3.5), C#, jQuery 1.4.2. This project makes heavy use of jQuery and AJAX. There is a drop down on a page that, when an item is chosen, is supposed to add that item (it's a user) to an object in the database.
To accomplish this, the previous programmer first, on page load, dynamically loads the entire page through AJAX. To do this, he's got 5 div's, and each one is loaded from a jQuery call to a different full page in the website.
Somehow, the HTML and BODY and all the other stuff is stripped out and the contents of the div are loaded with the content of the aspx page. Which seems incredibly wrong to me since it relies on the browser to magically strip out html, head, body, form tags and merge with the existing html head body form tags.
Also, as the "content" page is returned as a string, the previous programmer has this code running on it before it is appended to the div:
function CleanupResponseText(responseText, uniqueName) {
responseText = responseText.replace("theForm.submit();", "SubmitSubForm(theForm, $(theForm).parent());");
responseText = responseText.replace(new RegExp("theForm", "g"), uniqueName);
responseText = responseText.replace(new RegExp("doPostBack", "g"), "doPostBack" + uniqueName);
return responseText;
}
When the dropdown itself fires it's onchange event, here is the code that gets fired:
function SubmitSubForm(form, container) {
//ShowLoading(container);
$(form).ajaxSubmit( {
url: $(form).attr("action"),
success: function(responseText) {
$(container).html(CleanupResponseText(responseText, form.id));
$("form", container).css("margin-top", "0").css("padding-top", "0");
//HideLoading(container);
}
}
);
}
This blows up in IE, with the message that "Microsoft JScript runtime error: Object doesn't support this property or method" -- which, I think, has to be that $(form).ajaxSubmit method doesn't exist.
What is this code really trying to do? I am so turned around right now that I think my only option is to scrap everything and start over. But I'd rather not do that unless necessary.
Is this code good? Is it working against .Net, and is that why we are having issues?
A google search for
jquery ajax submit
reveals the jQuery Form Plugin. Given that, is that file included on your page where the other code will have access to the method? Does this code work in Firefox and not IE?
Seems like there was too much jQuery fun going on. I completely reworked the entire code block since it was poorly designed in the first place.

UpdatePanel - Any ideas on how to avoid a flicker in UI? - ASP.NET/Jquery

I have rather a complex UI. However, for the purpose of this question, let's say that there is a HTML table that renders UILayout1 by default (say default mode). There is a button that a user can use to toggle between the default mode and a preview mode (UILayout2)
When in preview mode, there are some columns in the table that are invisible and there are reordering of rows. I am using JS (jquery) on load to check the mode and change it accordingly.
The table and the toggle button are in UpdatePanels.
Functionally, everything works as expected. However, when a user toggles between default and preview mode or vice versa, there is this short time interval in which the the table renders in default and then JS runs to make changes.
This results in degraded UI experience. Are there any creative ways to avoid this "flicker"?
you can use DIVs or don't use update panel in your UI generation use any concept else
The problem is likely to be that your code is running on load. I'm assuming that you're doing this using the standard jQuery method of running code on load, and not using the window's onload event. In any case, even using jQuerys $(document).ready(...) will be too slow if you have a lot of other javascript files to load, as the .ready event isn't fired on the document until all javascript includes have loaded.
You should be able to work around the issue by including your code that modifies the table just after the html for the table in your page and not running it on load i.e. make sure you don't wrap it in $(document).ready(...);
For this approach to work, you will need to have all javascript required by the code which is modifying the table included earlier in the page.
If you have other non-essential javascript files included, you should try to include them later in the page.
I'm not 100% sure how being inside an update panel will affect it - you will need to make sure that your code is being re-triggered when the updatepanel updates, but I believe this should all happen automatically.
Presumably your UI is controlled by CSS? You might be able to get rid of the flickering by adding something like this at the start of your JavaScript or in the <head> of your HTML:
if (previewMode) {
document.documentElement.className = 'preview';
}
Then if you modify your CSS rules that apply to your preview mode to reflect the HTML element having the class="preview" to something like:
.preview table .defaultMode {
display:none;
}
hopefully your table should render correctly first time and will not need to be re-drawn.

Resources