jQuery Mobile DOM Page Reuse - javascript

I find that jQuery mobile is not reusing loaded pages.
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
if (activePage.hasClass("search-page")) {
var controller = activePage.data("controller");
if (!controller) {
controller = new SearchController(activePage);
activePage.data("controller", controller);
}
controller.loadPage();
}
});
Then later...
$.mobile.pageContainer.pagecontainer("change", "search.html");
which is an html document that contains
<div data-role="page" class="search-page">
However, upon each navigation to search.html, activatePage.data("controller") is null and so I reinitialize my SearchController.
I thought jQuery mobile reused pages already loaded into the DOM?

jQuery Mobile works with two distinct page template solution.
Multi opage - Where every page is part of a single HTML file
Multi HTML - Where single page is part of a single HTML file
You can of course mix those templates.
When jQuery Mobile is initialized for the first time initial HTML file is fully loaded into the DOM. This content will stay in the DOM until page is refreshed (or you remove it forcefully which is bad decision).
Every other HTML page will get loaded when you transition to it and it will get removed as soon as you transition from it. Basically it will stay alive in the DOM as long as is active.
So, in few words, only pages found in initial HTML file will permanently stay in the DOM, everything else will get loaded/removed as you activate it.

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.

Issue with ID's in browser when same content is loaded a second time in a div

I am creating a website where all my content is loaded into a div name content. my menubar is also loaded in to a div name menu.
The problem arises when i click the same link for a second time. So for instance i would click on members.php for a second time, the content is loaded into the div but some of my functions dont work as expected as they rely on and id which has been set. An ID can only be used once so when i load the page for the second time the ID doenst work. I would have to remove it before loading the content another time (which isnt an option) - as there are many ids.
i would be using jquery to load the content into the div. for instance $('#content').load('members.php');
but upon doing this the second time my id's would not work (content of the first page load stays intact) is there a way to reload that div.
Also is this normal behavior?
You can use a flag to define if this content loaded before or not, check it every time you call the loading function if it is not loaded before then load it, else no need to reload it again.
//initialize members_loaded variable when your page start.
var members_loaded = false;
//then when you want to load data check for it, change it to true in your complete function (when ajax done)
if(!members_loaded){
$( "#content" ).load( "members.php", function() {
members_loaded = true;
});
}

will_paginate pagination links javascript not working

I have a simple jQuery script that plays/pauses video on hover that is working correctly when I first load the page, (e.g page 1) in rails with will_paginate gem.
My problem is that when I click to the next page or any other pages in particular, the jQuery script is not working but when I viewed the page source, the javascript code is still present.
I have to reload the page in order to get it to work?
var figure = $(".video").hover( hoverVideo, hideVideo);
//video is a div class that my videos use, this is at index.html.erb
function hoverVideo(e) {
$('video',this).get(0).play();
}
function hideVideo(e) {
$('video',this).get(0).pause();
}
Your problem is that when your page is changed i believe the page refreshes with ajax and newly created elements have no events attached to them. The simplest solution is:
$(document).on('mouseenter','.video', hoverVideo ).on('mouseleave','.video',hideVideo );
This way jquery will always call mouseenter / mouseleave function but only fire your function when the element has specified class .video. So you don't worry anymore whether your newly created elements have any events attached to them or no

JQuery Mobile do X to every div with given class

I'm building a JQuery mobile site which has an image slider on 2 pages. The sliders are activated using the following JS:
$(function () {
$("#slider").excoloSlider();
});
where '#slider' is the name of the div that gets rendered as the slider.
I have this slider on the 2 pages and have given both the same id, and don't want to insert the above code into both pages. To make things easy I want to be able to make add the above code into a.js file that I'm referencing at the top of both pages.
However, the script only kicks in when one of the pages are the first page to be navigated to. So, I assume this means the code is only being called in the once, and due to the AJAX loading of the subsequent page, it isnt called when this new page loads.
So, how can I run the code to affect any/all pages which feature the slider?
I dont know how many times you have to call .excoloSlider(); function. In case you have to call it each time the page is visited, then you need to use any of these page events, pagecontainershow or pagecontainerbeforeshow.
If you use pagecontainershow, you can run .excoloSlider(); on #slider even if you have the same id in a different page. This way, you specify in which page to look for #slider.
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
/* check if #slider is within active page */
var slider = activePage.find("#slider").not(".slider");
if(slider) {
slider.excoloSlider();
}
});
Update
I have added .not(".slider") selector to exclude already rendered slider. The function .excoloSlider() will be called on new sliders only.
Demo
Try to use class instead of id since id is unique, then you can change your jQuery code to:
$(function () {
$(".slider").excoloSlider();
});
Use jQuery Mobile API for the navigation system
$(window).on( "navigate", function( event, data ) {
$("#slider").excoloSlider();
});
Edit
Use pageinit
From the jQM docs:
Important: Use $(document).bind('pageinit'), not $(document).ready()
The first thing you learn in jQuery is to call code inside the
$(document).ready() function so everything will execute as soon as the
DOM is loaded. However, in jQuery Mobile, Ajax is used to load the
contents of each page into the DOM as you navigate, and the DOM ready
handler only executes for the first page. To execute code whenever a
new page is loaded and created, you can bind to the pageinit event.
This event is explained in detail at the bottom of this page.

Categories

Resources