HTML & JS: How to subscribe to events from an embedded webpage? - javascript

I'm experimenting with building modular stand-alone (serverless) websites that can be hosted on IPFS. One of the techniques I'm using to make the websites modular is by splitting single webpages across multiple HTML files and combining them by embedding them into each other,
for example:
Webpage files: Home.html, Sidebar.html
Code in Home.html:
<html>
<head></head>
<body>
<!some code>
<object id="Sidebar" data="Sidebar.html"></object>
<!some more code>
</body>
</html>
Here is an image of what the website looks like. Note the scroll-bar that shows the the sidebar is embedded.
Website-with-Embedded-Sidebar :
I want to make that when elements of text in the sidebar (in the embedded Sidebar.html) are clicked, the JavaScript in the main page (Home.html) can react,
i.e. I want my JavaScript in Home.html to subscribe to events in the embedded Sidebar,html.
Any ideas on how best to achieve this?

I found a workaround solution that can in some cases be a suitable alternative is to call functions in the parent html file from the context of the embedded document. So instead of subscribing to click events in the embedded document from the parent document, I do it the other way round: handling the events in the embedded document and from there calling functions in the parent document.
Here is some working code:
Embedded HTML document (in a file called embedded_file.html):
<body>
<div onclick="ClickHandler(this)">Test</div>
<script>
var ClickHandler = function(sender) {
parent.OnEmbeddedDocClick(sender);
};
</script>
</body>
Main HTML page:
<body>
<object data="./embedded_file.html"></object>
<script>
var OnEmbeddedDocClick = function(sender) {
window.alert("Text in embedded file got clicked.");
};
</script>
</body>
Note that to test this, most browsers require these two files to be hosted on some form of web server instead of being stored on the local machine's filesystem, otherwise the browser's same-origin policy blocks the embedded file from accessing the javascript in the parent html file.
Hosting the files on IPFS and testing it from there was enough to evade this issue.

Related

jQuery dynamic page loading - Other javascript is broken and how should i import page specific js?

Okay, so this one is gonna be a doozy!
NOTE: This will be for a windows desktop application running sqlite and mongoose, so loading times are not as important (to me, for now) and there will be no connection to a non-local server.
I have searched all over and couldn't find anything that is specific to my situation, most seem to load into an iframe or use that framework provided by css-tricks.com
I am using my own (sorta) framework. The libraries i am using are bootstrap 3, jquery 2.1.4, jqueryui 1.12.1, and Bootstrap-select v1.12.1
index.php will have all content dynamically loaded into a div#wrapper and will act as the head of all page loading. This is the skeleton of my index.php. In sidebar.html the links have the attribute 'pagetoload', jquery catches the click event and loads the data into div#wrapper
<body>
<?php require_once("res/sidebar.html"); ?>
<div class="container-fluid" id="body-container">
<div id="wrapper" style="border:1px black solid;">
<!-- dynamic page content will be loaded here-->
</div>
</div>
<script src="res/js/jquery.js"></script>
<script src="res/js/jquery-ui.js"></script>
<script src="res/js/bootstrap.js"></script>
<script src="res/js/bootstrap-select.js"></script>
<script src="res/js/menu-handling.js"></script>
<script>
//index.php js
$(document).ready(function () {
$.get("home.php", function (data) {
$("div#wrapper").html(data);
});
$("a.loader").click(function (e) {
e.preventDefault();
$.get($(this).attr("pagetoload"), function (data) {
$("div#wrapper").html(data);
});
});
//dateFormat 10/dd/yy to constrain input only to october
//get current month number and constrain to prevent additions to wrong month
$("#date-input").datepicker({
dateFormat: "12/dd/yy"
, constrainInput: true
});
$("#date-input").focus(function () {
$(this).datepicker("show");
});
});
</script>
</body>
Each page that will be dynamically loaded will ideally contain minimal php and only contain the necessary html/css/js for that page. My issue is for example, after loading one page such as my dbviewer.php (which contains js and gives me the asynchronous loading warning) and reloading home.php into the container, javascript no longer works. The javascript for each page are inline tags.
I have tried piling all the javascript for every dynamic page into index.php so that it's all loaded on startup, but the issue arises that it still won't work. What is the best method make this dynamic loading work while having each page modular. I have tried to researching this but only stuff like using the hashTag thing comes up.
If you need more code from my files please post, i think i explained it enough for you to understand as there is nothing too wild going on outside of index.php Just scripts inside each dynamic page that basically interacts with dom elements using jquery.
I'm leaving this answer because it helped you, and also can be usefull as a general rule of thumb for any developer out there that can find himself in similar situation.
So when developing the app you have to separate all javascript, css assets in master file to host them on first pageload. (maybe it's event better for performance)
All other server generated files (php, node.js etc) files you have do structure to only be data source for pages that users click or land to .. or at least try to..
after that you have to trigger
$.ajax().callback
function on frontend to do job on each page. Such as page effects, data manipulation and etc .. Callback is very important because that's when data was actually loaded!
cheers, k

Calling a content page's javascript from a master pages javascript

I am working on a web app that can display data in two drastically different formats. To do this, I am using a master page with two different content pages for the differing views. I am using .svc files to do AJAX style server requests. I would like to be able to do a service call from the master pages javascript, then run the appropriate onSuccess javascript method (which would ideally lie in another .js file) to display the data based on which content page I am in. I am guessing this would be done with some kind of function delegate, but I am new to web development and not sure how to do this. Any help would be greatly appreciated.
If you can do everything on one page, your HTML will probably look something like this:
<!DOCTYPE html>
<html>
<head>
<script src="masterScript.js"></script>
<script src="module/childScript.js"></script>
<script>
console.log(globalVariableFromMasterScript)
doSomethingFromChildScript(globalVariableFromMasterScript)
</script>
</head>
<body>
<p>This is the html page</p>
</body>
</html>
This was a stupid question... Just attach different js files to the content pages. Give the functions the same name and it works fine.

How to load image before javascript

I'm currently looking to improve the perception of a web application by ensuring that the company logo is downloaded ahead of the javascript.
To do this I moved the javascript references below the img element for the company logo.
For example:
<img src="/Images/Logo.jpg" alt="My Company"/>
<script type="/Scripts/MyScripts.js"></script>
When looking at Google Chrome Developer Tools I can see that the call for the logo is made however it remains as "pending" until all the javascript on the page has been downloaded.
Why is this happening? How can I ensure that the company logo is loaded ahead of the javascript?
Try to use $(window).load for your scripts if you're using jQuery.
$( window).load(function() {
//put js code here
});
According to the this site :
The window load event executes a bit later when the complete page is
fully loaded, including all frames, objects and images. Therefore
functions which concern images or other page contents should be placed
in the load event for the window or the content tag itself.
As for separate files that you have to add to your site using <script src='path/to/file'>, I recommend using $.getScript.
$.getScript("path/to/file");
Here is the $.getScript manual.
Browser has to download and execute JS files as soon as one occurs during HTML markup parsing (at least due to possible usage of document.write in the scripts).
One of the best solutions would be adding onload event handler which loads your script dynamically when page is ready:
<script type="text/javascript">
window.addEventListener("load",function () {
var elem = document.createElement("script");
element.src = "file.js";
document.body.appendChild(element);
, false);
</script>

JQuery: Combine multiple pages into one

I am developing an application by using phonegap and jQuery Mobile. Phonegap recommends a single document structure. As 5 divs or more in a document are pretty unclear, I'm trying to split up my pages (the div's) into multiple documents. As soon as phonegap loads the app, I want to insert these documents into the index.html.
function loadPage(external_document) {
var docname=external_document+".html";
$.get(docname, function(data) {
console.log(docname+" loading");
$("body").append($(data).find("body"));
$("head").append($(data).find("head"));
console.log(docname+" loaded");
});
}
document.addEventListener("deviceready", function(){
loadPage("DialogCredentials");
}, false);
DialogCredentials.html
<html>
<head>
<script type="text/javascript" src="js/DialogCredentials.js"></script>
</head>
<body>
<div data-role="page" id="dlg_credentials">
<div data-role="header"><h1>Login</h1></div>
<div data-role="content">
...
</div>
</div><!-- /page -->
</body>
</html>
As soon as the loadPage gets executed there should be a <div id="dlg_credentials"… and the corresponding javascript tag in the dom of my main document. But it isn't. There are no errors shown in the web inspector.
So what am I doing wrong here?
Without setting up a test case for you, if you really want to separate your pages to make your coding easier I would recommend to load the pages the standard way for jQuery Mobile i.e.
$.mobile.changePage( "about/us.html", { transition: "slideup"} );
This way you aren't reinventing the wheel and it satisfies your request. The overhead will be negligible compared to your proposed solution in any case let alone taking into account you want the first page to render quickly rather than to be blocked by inserting many pages before any html is rendered in any case. Since they will be local on the device in any case Phonegap will be able to serve them very quickly.
One thing to remember when loading pages through jQuery Mobile is that it strips out anything in the target page outside of the
data-role="page|dialog|popup"
tag and therefore to load custom page-specific javascript I would recommend you include the script tag directly below the
data-role="page"
opening tag and set any page initialization to occur on "pageinit"
<div data-role="page" id="options" data-theme="a">
<script type="text/javascript">
$(document).bind('pageinit', initializeOptions());
function initializeOptions() {
// do your page initialization here . . .
}
</script>
<!-- rest of page continues here . . . . -->
and then continue with the rest of your page as needed. That way it will be parsed when the page is loaded via the $.mobile.changePage method.
Hope that helps.
Dynamic loading is a feature of several Javascript frameworks. AngularJS and Backbone.js for example. Maybe take a look at their approach to loading multiple views?
I have previously worked on an app that did this by adding an empty div for each view to the index.html, and then dynamically loading the Javascript for each view on demand. The Javascript for the views was responsible for rendering the HTML into the div for that view.

Snap Shot widget for dynamic DOM nodes

I'm using Snap.com service to create snapshots to Wikipedia links on my web page. It works fine with the links in the page when page is loaded. But it doesn't work when new links are created and inserted into the web page via Javascript.
The Snap.com script is called once when the page is loaded:
<html>
<body>
...
<script type="text/javascript" src="http://shots.snap.com/ss/my-id/snap_shots.js"></script>
</body>
</html>
Is there a way to reacivate their script after new DOM nodes are created in the document? Or some other way to solve this issue?
I've found the solution by inspecting Snap.com sources.
The following code forces Snap.com to reprocess the page:
SNAP_COM.shot_main_js_called = false;
SNAP_COM.shot_main_js();

Categories

Resources