Where should I place jQuery Mobile pages generated dynamically - javascript

Does anyone know the best place to add the HTML code for jQuery Mobile pages that have been dynamically generated?
I have been adding them to the end of the <body>, however, this is causing problems with other jQuery mobile pages.
I have tried adding the jQuery Mobile pages into a div at the end of the page, however, their ids are no longer accessible via hrefs.
Link to Code: http://jakeserver.com/Apps/BostonLandmarks/B11/index.html
Any ideas?

I recommend you move all script within the individual page divs to a global script tag and then run that code within a pagecreate event of the page e.g.:
$(document).on('pagecreate','#landmarks', function(){
function setNewActiveTab(newTab){
$(".LandmarksTab").removeClass("ui-btn-active");
$(".LandmarksTab").removeClass("ui-btn-active");
$(".MoreTab").removeClass("ui-btn-active");
$(newTab).addClass("ui-btn-active");
}
assembleRows(landmarksArray);
assembleLandmarkPages(landmarksArray);
determineMapScreen();
});
Here is a working jsFiddle based on your code.
This will ensure that the code runs at the correct time with respect to jQM's page creation/enhancement.

Related

How to sandbox a div element?

I am trying to build a content editor. This contenteditor will load a HTML document (with JavaScript) into for example a #result element. The problem with this, is that if inside this HTML element there is for example $("input").hide();, then all of my inputs are gone throughout the whole page, so not just inside the loaded HTML (my goal).
What I want to do with the editor is when a client clicks on an element that represents something in the database, the info of this element will popup and the user will be able to edit this. (So, if a user hovers over a form with the class "contact-form" (which is in the database, connected to the loaded page) a new window will popup with information about this specific form element.
Also, I cannot completely disable Javascript, since the loaded HTML might contain Javascript for styling etc.
My goal: Remove Javascript, that can be annoying when a user loads in an HTML file. Like an alert(); Also, remove the ability for the Javascript to edit somehthing outside it's own DOM.
P.S. I am open to better workarounds like using an iframe for this, BUT I want to be able to hover over elements in interact with them.
Edit: It seems that this question might be a bit too broad, looking at the comments. Summary of my question: How can I disable alert() for a specific div and how can I create a sandbox so that code inside a div, can only change elements from inside that div.
What you're looking for is HTML sanitization. This is the process by which you remove any dangerous content from a snippet of HTML on the server, before it's loaded in the browser. There are plenty of sanitization libraries out there that can strip script tags, object tags, etc. Just remember, you can't sanitize using javascript because by the time you've injected your script, another malicious script may have already loaded and run.
The only way to effectively sandbox a javascript environment is with iframes. You'll notice that websites like CodePen, JSBin and JSFiddle use them extensively. There's something called the ShadowDOM, which is the basis of Web Components, but it isn't very well supported yet.
To make it possible to run your own frontend scripts that allow for hovering, you can inject your script after your sanitization process. This way, if it's loaded inside an iframe your script will also be loaded.
Finally, alert() doesn't belong to any elements on the DOM. You can trigger an alert as soon as the page loads, for example. However, if you're trying to prevent alerts from popping up on user interactions, you could try removing all event listeners from a particular element. This won't be necessary if you sanitize the HTML of script tags, however, since the script wouldn't have had a chance to load so there won't be any event listeners.
You can use ShadowDOM to load an html document into a host node. See also WHY SHADOW DOM?

JavaScript does not work well inside a loaded content in a DIV

I am creating an application with Symfony2, where I have a main menu of options depending on the option selected dynamically opens a tab at a lower div with the content for that option. Content is loaded with load() of Jquery in the container div.You can see in the picture below:
The first problem was that in the HTML loaded in each tab could not use the js file initially loaded in the index.html, as you can see in this example you should check out a notice when we click the content of each tab, but does nothing .
The solution to this problem was included in each HTML code to load the appropriate script, and it worked properly. But to do it this way, if two HTML carry the same js, when one of the contents some event runs is repetite many times as tabs we have created, that is, if I open two different options (each in its own tab both charge the same js) by clicking on the first event associated performed twice, whereas if I do it in the second only done once. In short, whenever a function of a js used, is repeated as many times as there are dynamically loaded on the tabs.
And I tried event.preventDefault();orevent.stopPropagation(); and it does not solve the problem.
Would it be okay that it js is included twice in the overall structure of HTML? (Included in the initial head and then the container div)
Dynamically loading HTML + JavaScript is not the best approach for this case. I suggest that you use some JavaScript SPA framework, like AngularJS or ReactJS. Both are very big and well supported projects, so you can find tons of documentation and tutorials. You'll most likely end up using Symfony only as a RESTful service and Angular/React taking care of the rest (template loading, sending request to server, etc). Also, js frameworks will take care of deep linking and in the end you'll have a better working, easier to maintain application.
It is a bit more work initially, especially until you bootstrap the application, but then it gets easier to maintain and implement new functionality, so it pays off in the end. With your current approach you soon will find yourself in a big mess full of 100s of templates, js callbacks, inclusions, etc. I'm saying this from a personal experience!
Well...
Jquery works like this: when you attach an event to html, if the html does not exist, the event is attached to nothing. If the element exists then the event is correctly attached. It attaches only to existing elements when the on function is execute. That is a correct behaviour. In the past it used to exist a .live method that did exactly what you want: you attached an event and if you create the element after the attachment, the new element also contained the event.
Adding the js twice is not the solution. As you said after a click the button will be executed twice.
Why do not attach the events after loading the content? If you load it in the page start you can do in the main file:
$(function(){ // will force to execute the on method after all the page is loaded.
$('.submenu .button').on ('click', function (){
...
});
});
If you load the menu by ajax, in the callback and after adding the html menu to the main you must use the code I wrote above.

JavaScript in jQuery mobile not working unless I refresh

I'm having a jQuery mobile page with JavaScript inside. The problem is the JavaScript doesn't work unless the page is refreshed. Here is my code:
jQuery(function($) {
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
To understand this problem you need to understand how jQuery Mobile works.
Your first problem is point where you are trying to initialize JavaScript. From your previous answers I can see you are using several HTML/ASP pages and all of your javascript is initialized form the page <head>. This is the main problem. Only the first HTML file should have JavaScript placed into the <head> content. When jQuery Mobile loads other pages into the DOM it loads only the <div> with a data-role="page" attribute. Everything else, including <head>, will be discarded.
This is because currently loaded page has a <head> already. No point in loading another pages <head> content. This goes even further. If you have several pages in a second HTML file, only the first one is going to be loaded.
I will not try to invent warm water here so here are links to my other 2 answers discussing this problem. Several solutions can be found there:
Why I have to put all the script to index.html in jquery mobile (or in this blog article)
Link fails to work unless refreshing
There's more then enough information there to give you an idea what to do.
The basic solutions to this problem are:
Put all of your JavaScript into a first HTML/ASP file
Move your JavaScript into <body>; to be more precise, move it into a <div> with data-role="page". As I already pointed out, this is the only part of a page that is going to be loaded.
Use rel="external" when switching between pages because it will trigger a full page refresh. Basically, you jQuery mobile that the page will act as a normal web application.
As Archer pointed out, you should use page events to initialize your code. But let me tell you more about this problem. Unlike classic normal web pages, when working with jQuery Mobile, document ready will usually trigger before page is fully loaded/enhanced inside the DOM.
That is why page events were created. There are several of them, but if you want your code to execute only once (like in case of document ready) you should use the pageinit event. In any other case use pagebeforeshow or pageshow.
If you want to find out more about page events and why they should be used instead of document ready take a look at this article on my personal blog. Or find it here.
Your question isn't exactly overflowing with pointers and tips, so I'm going with the thing that immediately sprung to mind when I saw it.
Document ready does not fire on page change with jQuery Mobile, due to "hijax", their method of "ajaxifying" all the links. Try this instead...
$(document).on("pageshow", function() {
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
Try pageinit like this
$(document).delegate("body", "pageinit", function() { // Use body or page wrapper id / class
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
seems like nothing ever worked for me. Tried many different fixes, but i made the site too messy, that even position of certain javascript files wouldn't make the site work. Enough talk, here is what i came up with.
// write it in head at top of all javascripts
<script type="text/javascript">
$(document).ready(function() {
// stops ajax load thereby refreshing page
$("a,button,form").attr('data-ajax', 'false');
// encourages ajax load, hinders refresh page (in case if you want popup or dialogs to work.)
$("a[data-rel],a[data-dialog],a[data-transition]").attr('data-ajax', 'true');
});
</script>

How to test whether a page has been "pagecreated" in Jquery Mobile?

I have a two page application. Both pages have all content created dynamically on the client.
Problem is, if I go page A > page B > page A > page B, on the second+ visit, page B does not get enhanced by Jquery Mobile anymore, although pagecreate triggers correctly. I'm stuck with a page of un-enhanced markup.
I can't call create on the separate widgets of the page, because widgets will be of random type and because I cannot call create prior to initialization. After receiving this error I called pagecreate manually on the un-enhanced page, which fixed all widgets.
Problem is, how can I detect if the page has been enhanced by JQM? Because I don't want to call this on an already enhanced page.
So, seemingly easy question:
How can I test if a page has been enhanced by Jquery Mobile?
Thanks for inputs!
It is pretty simple.
In case you were using trigger('pagecreate') to enhance page markup then use this to check if page container has been enhanced:
$(document).on('pagebeforeshow', '#index', function(){
alert($.mobile.activePage.hasClass('ui-page'));
});
Live example: http://jsfiddle.net/Gajotres/HthYd/
In case you are using trigger('create') to enhance only page content div use this to check if content container has been enhanced:
$(document).on('pagebeforeshow', '#index', function(){
alert($.mobile.activePage.find('[data-role="content"]').hasClass('ui-content'));
});
Live example: http://jsfiddle.net/Gajotres/8jcGb/
Of course, this cases will work only in case you are enhancing whole page or whole content.
EDIT :
And here's a real live example with a dynamically added page: http://jsfiddle.net/Gajotres/8jcGb/

better ways to load views using jquery

OK. Let me try to explain my problem. I have three pages index, profile, contact and three links or navigation buttons in the header. When user clicks on profile button profile.html is loaded dynamically from the server using jquery load() method and place it in the div called container. Same goes for all pages. Now I also load all of my jquery plugins including jquery shadow plugin, script.js and jquery library on the index page only once. Now what I have is that on profile page I have a div tag on which I want to apply a jquery shadow plugin in my script.js which is loaded in index page. But it does not work this way(no idea why). What I have to do to make it work is to add a script tag in profile page and inside this I apply this shadow plugin to div tag which is inside profile page.
So this is what I want to ask is, Is there a better way to load pages through ajax using jquery so that whatever javascript code I am applying to all of the pages should be applied to all pages?
Thanks in advance

Categories