Dynamically loading content on local HTML page [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Context:
Basically I'm attaching a little HTML help doc to go with my program (not meant to be on a server, viewed locally). HTML just because I'm most comfortable in making docs in it but I also want it to have some interactivity/dynamic content which I can't do in a PDF or whatever.
I'm dynamically replacing the content when you click on a link instead of making every page need it's own HTML page, which is just something I'm used to doing so I can change the menu and banner and whatever else on a single 'main' html file without having to adjust every single other html file for one tiny change in the shared stuff.
Current Method:
Right now it's all done through javascript and jQuery. When a user clicks a link, I use jQuery's load() function to load the appropriate content (an html file) and replace the content div with what's in the loaded html file. Currently just using relative links. E.g. the core function is something like below:
$("#ContentBox").load("content/faq.html");
This actually worked a few weeks ago when I first wrote it. It's not like I built the whole thing and didn't test its core concept until just now. But now it seems all the browsers are blocking it. Chrome says:
XMLHttpRequest cannot load file:///C:/[....]/content/home.html. Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https, chrome-extension-resource. `
Question:
So I understand why it's happening as it's a potential security risk to allow that, I just want to figure a good way around it that still does what I want (if it's possible). I mean I could just preload all the content as huge string variables in the javascript file or as hidden divs that get turned on and off, but I was hoping for something a little more elegant.
And I can't expect all users of my program to setup a local web server just to view to help doc.
I've considered the File and FileReader classes but they require a user input for a lot of functions. There's also iFrames but that introduces all sorts of weirdness that needs to be accounted for and I hate iFrames.

If this is all local content then you should not be loading it via ajax. One option you have at your disposal is to set up your help files as local Javascript templates. You can then refer to them using a template library like mustache or underscore and link to them in your application like so:
<script type="text/template" src="local/helpfile.js" />
If you don't want to use a templating library then you can set up helpfile.js as JSON data, but you'll need to escape quote characters first.

If your help docs are to be viewed on a Windows machine only, you should look into using HTML Applications to get rid of the cross-origin issues. Or you can work around it by combining all of the source code files in hidden textareas. I've done it lol

To anyone still interested this is the solution I settled on as of now. At the end of the body are all the divs with the different page content styled like so:
<div id='PageName' class='content-div'>
<!-- content goes here -->
</div>
<div id='AnotherPage' class='content-div'>
<!-- content goes here -->
</div>
The id is important as that becomes the name of the page and the class type, which you can name whatever, I used to hide them with visibility:hidden; as well as gave it absolute positioning at 0,0 - just in case - so that they don't interact with other elements and screw up the layout.
On the page loading, along with a bunch of other functions, I store the elements into a javascript associative object by page name.
var content = {};
function onLoadThisGetsCalledSomewhere() {
// loop through all of those divs
$(".div-content").each(
function() {
// using $(this) to grab the div in the scope of the function here
var element = $(this).element;
var name = $(this).attr('id');
// remove it from the html (now it exists only in the content object)
element.detach();
// remove that style class that makes it invisible
element.removeClass('content-div');
// put it into memory
content[name] = element;
}
);
}
So when a link to another page is clicked, the onclick does something like switchPage(pageName) let's say.
function switchPage(requestedPage) :
// somewhat simplified, real version has case and null checks that take you to 404 page
var contentElement = content[requestedPage];
// replace content in some container div where you want content to go
$("#TheContentContainer").empty().append( contentElement );
// have to adjust size (width possibly too but I had a fixed width)
$("#TheContentContainer").height( contentElement.height() );
}
I'm not at the same computer so I'm writing all this up anew, not copy/pasting so there may be some bugs/typos (Caveat emptor - I'll fix it tomorrow). The version I used is somewhat more complicated as well since I have subpages as well as dynamically handled menu bar changes. Also features so that you can open the "links" correctly in new windows/tabs if such an action is made. But that's not important here now.
It's not too different I suppose with hidden divs (the benefit here is the detach() function to remove it from the html) or just storing long strings of html code in java vars (much more readable than that though), but I think it's advantage is is much cleaner (IMHO) and so far I like it. The one downside is with lots of pages you get one huge HTML doc that can be a pain to go through to edit one specific page but any decent editor should have a bookmark feature to make it a little easier to get to the line you're looking for. Also cause of that a bad idea if not local, but then again if it's online just use the jQuery load() function.

Related

How can I edit html inside an iframe using javascript

I am working on automating a process within my business, part of which is sending an email through SalesForce. We don't have access to the SF API and the email has to be sent through salesforce in order to keep the communication searchable for the coworkers.
I need to use a template which can be selected in SalesForce, however this function does not work in IE (which our RPA solution uses) so I need to build this email from scratch.
I see two options for this:
Use the HTML to recreate the format with the right variables. This entails inserting/injecting/manipulating HTML.
Copy the format into memory/the clipboard, edit it programatically and paste it into the SF interface
This question will be about option 1. I will post an additional question with regards to the second option separately and edit this question to include that link. EDIT: Here is the link to the other question!
Now on to the question:
We use the Blue Prism RPA software suite. It has a possibility to insert javascript fragments into a website and subsequently invoke them. I was hoping that I could create a javascript fragment that recreates the template, insert it and then invoke it. I have been working on this for the past week and have hardly gotten any further.
I now am able to add basic text into the required field, but have found that to be able to use the template structure I need to use a different, HTML based, field. This field I find lives inside an iframe.
I have had zero experience with javascript prior to this week (luckily it seems similar to c# in which I do have experience) and now this iframe has me stumped. Apparently when you use Selenium or similar you can switch the driver to the new iframe but I don't have that option, it needs to be done through surface automation. Within javascript as well as the console I can not get it to target the separate document within the iframe. Apparently the iframe contents are not incorporated in that way in the bigger webpage.
So my question is this: How can I "switch focus" to the iframe using javascript? How can I then edit the iframe contents through javascript? Any help, tips etc. would be highly appreciated!
If you go to developer tools in the browser (F12 or right-click inspect) you can use the inpsect tool to get the path you are looking for. an iframe is just another window inside the window and once you have the 'base path' you can then extend further into the window from the iframe base path.
You can access frames one of two ways I know of;
document.getElementById('the frame you are looking for goes here').contentWindow.targetFunction();
and/or
window.frames[0].otherfunctions
where 0 is the Nth order of frame on the window in case there are others.
once you find that path you can interact with sub-elements on that iframe by getting the path to it from within the iframe.
some things to watch out for. frames not loading yet so make sure the frame you want is loaded and no other frame is moving it around the screen at run time. Also make sure the child frame is in the same domain, I think calling javascript has issues when going cross-domain i.e. it doesn't work (stand to be corrected there though maybe it depends on group settings)
Supply some code or the layout of the page and could give you a code example but top of my head the format will look like this
var doc = window.frames[0]
var thing = getElementById(doc.getElementByPath('maybePath')
'perform some set operations like set innerhtml to thing you desire

Javascript: are some things too simple to link externally? [duplicate]

This question already has answers here:
When to use onclick in HTML?
(3 answers)
Closed 4 years ago.
I'm really new to JavaScript. So this might be a basic question? I would just like some explanation, if possible.
I'm working on some web development that has JS. However, I have the requirement that all files (JS and CSS) have to be linked through external sheets, and with complex functions that makes sense, but with some of the simple JS I'm a little confused as to what that means.
With CSS, you can do inline styling, or in the header in style tags, or in an external sheet. There are some JS interactions where I can't tell if it has to be where it is, or if there is a way to move it to an external sheet.
For Example, this basic "bulb on/off"
The js here is onclick=document.getElementById(...) (Changing an image by clicking on it/on a button)
Is this kind of code stuff that can even go in an external sheet? is my internal analogy of inline/tags/external CSS fitting to apply to Javascript, too, or does JS work differently? I just don't want to get counted off for not having stuff in the right place.
What you need to understand is that the "scope" of what you are working with when you use JavaScript, is the user's viewport. Internally represented as a tree of objects which we call the DOM (document object model). The browser fetches these external sheets, JavaScript files, html etc. and then loads them into the DOM.
JavaScript is all about just one thing: manipulating the DOM.
Depending on when your JavaScript is executed, it will manipulate the DOM in the state it is in at that exact moment.
The usual moment that programmers choose to execute their code is right after DOM-ready. This is a moment in time after which all external pieces of code/styling etc. have been fetched and initialized into the DOM, therefore allowing you to be sure, that your code is working against the full scope of content that you'd also see while browsing the page right after it loads.
Zooming in on your question about placing code in an external file: sure, its possible. As at one point this file would be imported and loaded into the DOM. The code inside would be executed at the point where this file is loaded, or when you hook into the DOM-ready event to start up the code inside this file.
You have a legitimate question here (apologies for the opinion - but good on you for giving it a go!).
This is from the Mozilla developer page (https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics)
Next, in your index.html file enter the following element on a new
line just before the closing tag:
<script src="scripts/main.js"></script>
This is basically doing the same job as the element for CSS — it applies the JavaScript to the page,
so it can have an effect on the HTML (along with the CSS, and anything else on the page).
In your sample code you wrote onclick=document.getElementById(...).
This should actually be written as
onclick=function() {
document.getElementById(...)...
}

Effeciency, hidden HTML or JavaScript DOM appending?

I am working on a simple Cordova app with about 4 page types and I am trying to think through which is the better way to handle the inner HTML templates.
Hidden HTML hard coded into the HTML files that is hidden and populated/revealed by my JS.
Using a JS template system and appending and removing from the DOM.
I feel that appending all that to the DOM for a page is inefficient when I could just update the sections that change. But perhaps an append is lightweight enough where I shouldn't worry about it.
There are a number of ways you can do it. In terms of load on the browser. That is hard to say. From your question it is hard to know what is in these pages, what are you displaying, is it live data, static html etc.
When you first plot out an app, if you are from the old class of building multiple page websites, it can be a little concerning as to how well your app/page will run with all those pages crammed in to one, and all that data plus code.
The answer is, amazingly well. If done properly in modern browsers, and for example Ipads the app will run to near native performance.
The options you have are
Map all the pages into one HTML document. Hide each page content using css display:none, flip them into view using css animation, fading or just display:block.
Use a javascript routing library to map urls to blocks of code that deal with each page, this makes mapping out your app much easier, and means that buttons can just link to your pages, like a real website. see http://projects.jga.me/routie/
Building all the page templates into one page can make it hard to code, as the page becomes enormous, consider breaking the inner content of each page into separate files, you can then give each page holder a url and use a small xhr request to load the page on-the fly, once loaded you can cache it into memory or even local-storage, depending on whether you remove it when it is closed or keep it hidden.
In my experience you can put an enormous number or nodes into one page and have very little speed drop, bear in mind if you use something like jquery and do a lot of $(".page > .page1 > .items li") your going to have a slow app.
Tips
Use element ID's everywhere document.getElementById(..) is 100's of times faster in a loop that $(...)
cache elements when you find them, if you need them later store them in a memory cache.
keep for loop inner code to a minimum.
use a decent click touch libary like http://hammerjs.github.io/ and delegate all the events of the body tag or at least on each page.
If you need to touch the server, load data, think dom first, device second server later. A good app is a responsive app, that responds to the user instantly.
I know this has been posted a while ago, but for the sake of the users I am going to add my answer.
I completely agree with MartinWebb but my answer will shed some light on the results of his options. I am currently working on a similar project. Please note that this answer pertains to cordova (previously called phonegap) specifically. My app has about 5 pages with +-20 different components (input's, div's, h1's, p's, etc.). This is what i tried and the result of each:
jQuery was my first option, mainly because it is easy to use and reduces the amount of code required to accomplish a said goal. Result: First time I tried this approach I though I would spice it up with animations and transformations. The result of this was a very unresponsive app. I removed the animation and transformation, however due to the nature of my application I required multiple dynamically added components and jQuery just wasn't up for the task.
Css display:none and visible:hidden was my next option. I used javascript's dom to display certain div's. Result: This works if your not planning on switching many div shortly after one another eg. a simple menu. It quickly became apparent that this wasn't going to work. Also this does not eliminate my need for the dom. Remember document.getElementById('menu').style.display = "none"; is still part of the dom. This as a solution, for me, is poor. There is a reason that var menu= document.createElement('div'); is part of the language. Which brings me to my last option.
Building a page 90% on javascript's dom was my last option. Logically I could not see how 600 lines of code cold trump one .innerHTML or .style.display = "block"; but it did. Result: It was by far the most responsive of all the solutions.
I'm not saying that all webpages should be coded with dom appending, but as I stated previously, for a cordova app of a few pages (<6), with a few components a javascript dom appending approach would be best. It takes longer to code, but you will be rewarded with control and efficiency. I would suggest coding the backbone of your app in html and populating and controlling with javascript's dom.
Best of luck.
The first option, <div>s with display:none; would be more efficient by a small margin, but you can get the best of both worlds by compiling your JavaScript and templates together into a single file using something like browserify or require.js.

Custom View Engine to solve the Javascript/PartialView Issue?

I have seen many questions raised around PartialViews and Javascript: the problem is a PartialView that requires Javascript, e.g. a view that renders a jqGrid:
The partial View needs a <div id="myGrid"></div>
and then some script:
<script>
$(document).ready(function(){
$('#myGrid').jqGrid( { // config params go here
});
}
</script>
The issue is how to include the PartialView without littering the page with inline tags and multiple $(document).ready tags.
We would also like to club the results from multiple RenderPartial calls into a single document.Ready() call.
And lastly we have the issue of the Javascript library files such as JQuery and JQGrid.js which should ideally be included at the bottom of the page (right before the $.ready block) and ideally only included when the appropriate PartialViews are used on the page.
In scouring the WWW it does not appear that anyone has solved this issue. A potential way might be to implement a custom View Engine. I was wondering if anyone had any alternative suggestions I may have missed?
This is a good question and it is something my team struggled with when JQuery was first released. One colleague wrote a page base class that combined all of the document ready calls into one, but it was a complete waste of time and our client's money.
There is no need to combine the $(document).ready() calls into one as they will all be called, one after the other in the order that they appear on the page. this is due to the multi-cast delegate nature of the method and it won't have a significant affect on performance. You might find your page slightly more maintainable, but maintainability is seldom an issue with jQuery as it has such concise syntax.
Could you expand on the reasons for wanting to combine them? I find a lot of developers are perfectionists and want their markup to be absolutely perfect. Rather, I find that when it is good enough for the client, when it performs adequately and displays properly, then my time is better spent delivering the next requirement. I have wasted a lot of time in the past formatting HTML that no-one will ever look at.
Any script that you want to appear at the bottom of the page should go inside the ClientScriptManager.RegisterStartupScript Method as it renders at the bottom of the page.
http://msdn.microsoft.com/en-us/library/z9h4dk8y.aspx
Edit Just noticed that your question was specific to ASP.NET MVC. My answer is more of an ASP.NET answer but in terms of the rendered html, most of my comments are still relevant. Multiple document.ready functions are not a problem.
The standard jQuery approach is to write a single script that will add behaviour to multiple elements. So, add a class to the divs that you want to contain a grid and call a function on each one:
<script language="text/javascript">
$(document).ready(function(){
$('.myGridClass').each(function(){
$(this).jqGrid( {
// config params can be determined from
//attributes added to the div element
var url = $(this).attr("data-url");
});
});
}
</script>
You only need to add this script once on your page and in your partial views you just have:
<div class="myGridClass" data-url="http://whatever-url-to-be-used"></div>
Notice the data-url attribute. This is HTML5 syntax, which will fail HTML 4 validation. It will still work in HTML 4 browsers. It only matters if you have to run your pages through html validators. And I can see you already know about HTML5
Not pretty but as regards your last point can you not send the appropriate tags as a ViewData dictionary in the action that returns the partial?

How does one properly test a javascript widget?

So, I've written a little javascript widget. All a user has to do is paste a script tag into the page, and right below it I insert a div with all of the content the user has requested.
Many sites do similar things, such as Twitter, Delicious and even StackOverflow.
What I'm curious about is how to test this widget to make sure that it will work properly on everyone's webpage. I'm not using an iframe, so I really want to make sure that this code will work when inserted most places. I know it looks the same in all browsers.
Suggestions? Or should I just build one hundred web pages and insert my script tag and see if it works? I would hope there is an easier way than that.
Once you have confirmed that your javascript works cross-browser in a controlled environment, here are some things that might cause problems when used on an actual website:
CSS
You're using a CSS class that is already being used (for a different purpose) by the target website
You're using positioning that might interfere with the site's CSS
The elements you are using are being styled by the website's CSS (you might want to use some sort of "reset" CSS that applies only to your widget)
HTML
You're creating elements with the same id attribute as an element that already exists on the website
You're specifying a name attribute that is already being used (while name can be used for multiple elements, you may not be expecting that)
Javascript
What is the expected behaviour without Javascript enabled? If your script creates everything, is it acceptable for nothing to be present without JS?
At very basic you should make sure your widget works for following test-cases. I am sure then it will work on all web-pages -
http/https: There should not be any warning for HTTPS pages for unencrypted content.
<script> / <no-script>: What if JavaScript is disabled? Is your widget still visible?
What happens when third-party cookies are disabled? Does your widget still work?
Layout-box restrictions: When parent div element's size is less than your widget. Does your widget overflow the given size and destroys owners page?
By keeping all your Javascripts under a namespace (global object) with a very unique name, you should be pretty much OK. Also, you can simply use an anonymous function if you just want to print out something.
Similar question: How to avoid name clashes in JavaScript widgets

Categories

Resources