PageLoaded Event Handler At Application Level - javascript

In my Windows 8 application, I need to run some code when a page is loaded, but I need to run it at the application level in my default.js file. Is there an event I can use to generically attach to when a page is loaded into the DOM?

In default.js, there's already a reference to WinJS.Navigation, so you could do something like:
nav.addEventListener("navigated", function (e) {
console.log('loaded a new page ' + e.detail.location);
});
That will fire when you navigate from page to page versus actually loading into the DOM (not sure how specific you mean that).
If you want to have something happen when you truly load a page into the DOM, you could add a override load in your pages that then invoke a method on WinJS.Application, for example (Where the unload is part of the page code you get already generated)
load: function()
{
WinJS.Application.doSomething();
},
unload: function () {
this._items.dispose();
},
and in the code for the application in app.js, you'd have
app.doSomething = function () { console.log("I did something"); }
There's a glitch here though that I'm hunting down. Once I override load, I'm seeing an HierarchyRequestError on the second invocation.

Related

How To Tell If a View Component Has Completely Loaded

I am having an issue with view components in .NET Core 2.0. I need to be able to detect when a view component has finished loading in the parent view.
Once the view component has loaded, I need to set focus on a specific field that is part of the view component.
Currently, I am using JQuery window.onload(). However, in window.onload() the view component and any subsequent JavaScript has not fully render yet.
Since it has not fully rendered the window.onload event can't find the specific field in the view component.
If I use setTimeout and set it's ms between 1000 and 3000, thus giving the view component time to finish loading, it works fine.
The problem with using setTimeout is that it isn't consistent. Depending on how long the page takes to load it may or may not set the focus on the specified field.
Here is the code jquery code.
var setSearchFocus = function () {
if ($("#divSearch").is(":visible")) {
$('#Diagnosis_Search').focus();
}
}
window.onload = function () {
setTimeout(setSearchFocus, 1000);
}
divSearch is the div in the parent view where the view component is rendered.
Diagnosis_Search is the name of the field in the view component that needs to receive focus.
Appreciate any help with an alternate way to determine when a page has completely loaded or the ablity to detect when a view component has finished loading.
Thanks!
If you're up to using jQuery, you're better off using the document ready event:
$(document).ready(function() {
setTimeout(setSearchFocus, 1000);
});
OnLoad will fire before the entire document/page is ready. Using the $(document).ready(... approach will wait until your page is ready (in other words, when the DOM elements you want to interact with are present and rendered).
This is one of the most common problems on web development. You're using window.onload which is not jquery. It is part of the Document Object Model (DOM) and as you have noticed it doesn't work as expected. This is why the guys # jquery came up with document ready:
$( document ).ready(function() {
console.log( "ready!" );
});
or just
$(function() { console.log("ready!"); });
https://learn.jquery.com/using-jquery-core/document-ready/
UPDATE: as per the comment on the other answer, I get that you've got to wait until an iframe loads your view component. Is that so? If it is, then try to listen to the iframe's document object, an iframe is like another whole webpage embedded on your site, so there's another document object for it. You can access this object from the parent by using
document.getElementById('divSearch').contentWindow.document
you see a document that contains other document, which is actually what we're doing with the iframe. Beware this line isn't going to work if the document you're loading on the iframe is not on the same origin (not part or the same web or in the same TLD), but as you told us that this is a viewComponent this isn't the case probably.
To sum up, try with $(iframe#youriframeid).ready(function() { console.log("ready!"); }) instead.

Use javascript (and jQuery and other libs) from parent document on iframe with several sources

good day all.
I'm working on a project in which there is an application that has one of its view implemented with an iframe, the iframe src is changed when the user clicks on some of the "parent" document. So basically there is always the same container, but the contents of the iframe will change according to the user choices.
let's say that there will be:
parent.html (which will have all the js logic)
child1.html
child2.html
...
each "child" page will be an html page with no (or very little) javascript. What I want to obtain is that when the user arrive on the child1.html, only the code that is global to every child is execute and of course also the code related to that page.
Let's say that on the child1.html there must be executed a couple of ajax calls, then some js to handle tables, and things like that. while on the child2.html there will be some forms whith their own validations, and another ajax call to send the forms (displayed on the child1.html).
There will be a big js library on parent.html that will contain the js code of every child page, so what I'd like to have is a way to "know" in which page I am and execute only the portion of code that is related to that page.
the structure should be something like:
var myGlobalObject = {username:undefined,foo:1}
if(childpage1.html){
if (myGlobalObject.username == undefined){
$.ajax(retrieve username);
$("#someTableIniFrame",iframeContext).doSomething();
}
}
if(childpage2.html){
$("body",iframeContext2).on("submit","#someFormOnChild2", function(){
//do something
});
}
and/or something on childpages that could execute only its code... like:
document.addEventListener("DOMContentLoaded", function(event) {
//execute only my part of the global js!
});
I hope to have been clear on what I'd like to obtain:
a parent page, with all the js used in childs, executed on demand OR with the capability to understand in which page we are.
several child page without or with a very little js.
Just for information, the iframe src will be changed by js on the parent page, by destroying the previous one and adding a new iframe with the new source.
If you want to keep all the Javascript in the parent page then you just really need a way to map the child pages to any code you wish to execute. This is a long way around doing something, but without further context it's difficult to suggest a more appropriate solution.
With that in mind, here's how I'd approach your problem.
First of all, I'd create an array of objects that defines what script to run for each child page...
var childScripts = [{
"src": "childpage1.html",
"init": function() {
// what to do when childpage1 is loaded
}
},
{
"src": "childpage2.html",
"init": function() {
// what to do when childpage2 is loaded
}
}];
Don't destroy and recreate the iFrame every time you want to load a new page, or (if you really have to), assign an event handler to the load event every time. You only have to do this once if you never destroy the iFrame...
$("#iframeId").on("load", function() {
var scriptInfo = childScripts.filter(function(childInfo) {
return window.location.href.slice(-childInfo.src.length) === childInfo.src;
});
for (var i in scriptInfo) {
scriptInfo[i].init();
}
});
Obviously replace the selector #iframeId with something that will find your iframe.
In short, you create an array that holds each child page filename (prefix with / so you don't run scripts on pages that end with the same thing, but aren't the same page), and a function that you want to execute when that page loads. You then parse that array each time the iframe is loaded and execute all associated functions. Realistically you'll only have 1 init function per child page, but that code will handle multiple instances.

jquery getscript causing loop

I am using .load to call content from a section of my site when someone clicks a link. I am then using getscript to load in any scripts that are needed that .load strips out.
However, the content call function is needed on links that are loaded from this loaded content.
I am therefore in a situation where there is a loop being created and multiple executions.
This isn't an issue if the user clicks on one or two links to load content from other pages, but if they do it for several links then I get a spike in CPU, and therefore need to find a solution.
I am not sure why there is this issue, as the script executions are done through user clicks, so there shouldn't be continual execution.
The script looks like this:
$(document).ready(function () {
$('.Select a').one("click", function () {
var toLoad = $(this).attr('href') + ' .containerPlus';
$("body").append($("<div class='loadedcontent'>").load(toLoad, function () {
$.getScript("scripts required for loaded content", function () {
$.getScript("load this script again");
}));
});
});
basically the user clicks on a link, this calls the content and loads it into a new container, scripts needed on that page are then loaded, and then finally this code is applied to any links within this loaded content that need it.
This is a loop, but as there is a click element, I wouldn't have thought the second execution wouldn't take place until another click event.
Thanks for any advice
Richard

Detect first page load with jQuery?

I need to detect the first time a page loads in jQuery so that I can perform some actions only when the page loads the first time a user navigates to that page. Similar to server side code page.ispostbasck. I have tested $(document).ready and it fires every time the page loads so this will not provide what I need. I have also tried the jQuery Load function - it also fires every page load. So by page load an example is that I have an HTML input tag on the page of type button and it does not fire a postback (like an asp.net button) but it does reload the page and fires $(document).ready
Thanks
You will have to use cookie to store first load information:
if (! $.cookie("cookieName")){
// do your stuff
// set cookie now
$.cookie("cookieName", "firstSet", {"expires" : 7})
}
Note: Above example uses jQuery Cookie plugin.
An event doesn't exist that fires only when the page is loaded for the first time.
You should use jQuery's .ready() event, and then persist the fact that you've handled a first time page load using your method of choice (i.e. cookie, session variable, local storage, etc.).
Note: This method will never be fool proof unless you can store this information at the user level in a DB. Otherwise, as soon as the user clears their cookies, or whatever method you choose, the "first time loaded" code will fire again.
I just ran into this problem and this is how I handled it. Keep track of the first time the page loads by using a variable initialLoad:
var initialLoad = true;
$(document).ready(function() {
...
...
...
initialLoad = false;
});
Then in other functions, you can do this:
if (initialLoad) {
//Do work that is done when the page was first refreshed/loaded.
} else {
//Do work when it's not the initial load.
}
This works well for me. If the user is already on the page and some jQuery functions run, I now know if that user just loaded the page or if they were already on the page.
The easy solution is to use jQuery ‘Once’ plugin
$(element).once('class-name', function() {
// your javascript code
});

Chrome Extension: How to reload/re-execute content script on Ajax request

I'm trying to execute a content script for a certain site (inject a button or change the link) however I would like to do this as the user browses the website.
The problem is that the web page is built dynamically with ajax requests as the user browses.
I had solved this earlier in an extension I had written by actually injecting my JavaScript into the web page.
I was wondering whether there is a better alternative of just being able to register for an ajaxComplete event or something similar in my content script so that I can re-execute.
I can do the following:
function listener()
{
console.debug("listener fired.");
}
document.addEventListener("DOMSubtreeModified", listener, false);
However that fires way too many times during one page load.
There is no ajax listener that I am aware of, but it wouldn't help much anyway as you need to catch when page is modified, not ajax request is sent/received (page modification usually happens later and can be not tied to ajax request at all).
DOMSubtreeModified is the right way to go, just implement some protection from too frequent calls:
function listener()
{
console.debug("listener fired.");
}
var timeout = null;
document.addEventListener("DOMSubtreeModified", function() {
if(timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(listener, 500);
}, false);
This way it would trigger listener if there was no other events within 500ms.
The best answer I found was a bit interesting and involved a bit of message passing in between the content scripts and the background.html file.
I'll post the code then explain:
Background.html
function updatePageAction(tabId)
{
chrome.tabs.sendRequest(tabId, {is_content_script: true}, function(response) {
if (response.is_content_script)
chrome.pageAction.show(tabId);
});
};
chrome.tabs.onUpdated.addListener(function(tabId, change, tab) {
if (change.status == "complete") {
updatePageAction(tabId);
}
});
content_script.js
// The background page is asking us to find an address on the page.
if (window == top) {
chrome.extension.onRequest.addListener(function(req, sender, sendResponse) {
if (req.is_content_script)
start_content_script();
sendResponse({is_content_script: true});
});
};
You want to solve updating or re-executing the script on DOM changes. Luckily the DOM changes involved a URL change (although it was AJAX DOM changes to update the page).
The URL change however fires a onUpdated event. However every tab is firing these "events" and we want to make sure we only care about the one in which we have matched our content scripts too (you can specify a match in the manifest!).
By passing a messgae to the content_script being executed in the current tab, we are asking "Are you my content script? If so, please re-start."

Categories

Resources