We have a parent site that provides the real estate for our applications to be added. The flow is described as below
Parent site has a menu.
One of the "links" on the menu points to our
application
When you click on it, the parent site internally parses
the response from our application (including html and javascript)
and loads it within a container. Sort of a portlet. This parsing is problematic, because once the javascript is loaded, it remains in the head tag.
Thereafter, we can use our code to control the application in a SPI manner.
Problem arises, when the user clicks on the menu again, because steps 1-4 get repeated. Thus we end up reloading javascript, which fails spectacularly. Some of the problems include
Angular is reloaded.
Modules get reloaded.
If I defer the loading of Angular conditionally via document.write, then I have to ensure that angular is loaded before the modules are defined.
If I manually bootstrap the application, then I cannot bootstrap it again and I need flags to maintain.
I was able to write a script to ensure that everything is loaded only once, but now the problem is that the DOM does not get "processed" once the user clicks the link again. It is as if the entire DOM content has refreshed with the angular tags and directives, and the javascript is already loaded, but it does not "process" this new DOM content.
What can I do to ensure that newly added DOM via a third party plugin/script/code is recognized by existing angular code?
Related
Suppose you have some kind of listing and you allow this listing to be rendered via CSS either as a list or as a grid (via a varying CSS class or data attribute). Since this is purely a rendering issue it required not (re)processing by the web server, thus you can also simply implement the switch on the client side via JavaScript.
However, suppose you want to save the client's view mode choice, e.g. in the localStorage. Now when the page is rendered, the appropriate view mode needs to be restored.
But what is the best practice here in order to prevent the switch from the default view to the saved view to be visible when the content is above the fold?
Consider the following crude example: http://jsfiddle.net/yaubvq8d/27/
Here the JavaScript for changing the view mode and also loading the saved view mode from the localStorage is at the end of the body, which is obviously not ideal. To visualize the problem I also integrated an externally loaded JavaScript, that blocks rendering of the page for 2 seconds - so it takes at least 2 seconds, before the JavaScript for managing the view mode is actually executed. During these two seconds you first see the default view (which is the grid view) and then it would switch to whatever view you had previously selected (to test this you obviously have to click on "List" first and then run the fiddle again).
The only obvious solution I can think of is defining the view mode in a parent container (let's say the body) and then execute the JavaScript to load the view mode from the local storage right after the starting tag of the parent container.
But are there any other best practices, that I might miss?
I you have a highly interactive event driven page in rails 5.0.0.1 with Turbolinks.
Having different interactions on different pages, events like window.resize will trigger on pages where I don't really need it.
Is it worth to sacrifice navigation time by disabling Turbolinks to serve page specific javascript, or should I not care and just use if statement in Jquery to check if certain elements are present in the page using their ID.
What is the rails way of doing this?
It is not recommended to serve page specific assets such as javascript. This slows down the user experience since navigating to a new page triggers another asset download.
The whole point of the Rails Asset Pipeline is to gather your assets, minify them and concatenate them all into a single file that the browser downloads only once, the first time a user navigates to your page.
Yes, use jQuery to check if certain elements exist to run some behavior.
The way I've found useful is to not think about js behaviors as page specific but rather, widget specific. e.g. if there's a sortable table in the DOM then initialize the sortable table widget i.e. $(".sortable").sortable()
The above example uses the jQuery plugins pattern. Place your behavior/widget logic inside the jQuery plugin and it will only run when the selector finds elements e.g. $("#nonexistant").something(), something() will not be called. $("#definitelyExists").somethingElse(), somethingElse() will be called.
In the preceding examples, when an element is found and the function is called, the this of the function references the matched elements and you can run your behavior logic on them.
Im loading a Dynamic HTMLs with JS into a div in a index page.
the index page div will be updated with another HTML file dynamically using JQuery.load function, according to the users action in the page.
The HTML also contains JS, and JS files are loading into DOM and its working perfectly as expected. but the problem is whenever a new HTML and JS is loaded, the DOM is getting updated, and its not refreshed.
the variables in previous JS files are still visible in Firefox dom stack.
i need to clear/refresh the DOM whenever a new HTML is loaded.
This application needs to be supported in IE8, so im not using angularJS. Heared angular is clearing DOM while loading new innerHTML files for Single page application.
please help me to clear DOM or suggest me any library files are available?
There is likely to be no silver bullet for this problem. Your scripts shall probably have some custom event or callback during which they would clear/reset/refresh variables that are set to DOM elements. This event or callback then should be called every time the document is updated through the usage of innerHTML.
I'm coding in MeteorJS
I'm using a bootstrap based theme.
The dropdowns etc based on bootstrap, driven by plugin javascript code, don't work. Javascript code I write separately (to handle a login button, for example) does work.
There are no errors generated in the console at any time.
Any idea on the potential issues/how to debug this?
The most commom issue by FAR is the unique way that Meteor renders pages.
A normal theme is created with a traditional load order in mind:
a browser goes to a page and starts to parse the HTML from TOP to BOTTOM
As it goes from top to bottom it builds the DOM nodes of the page.
The browser loads the scripts tags that are down at the very bottom of the page, after most of the HTML code.
99.9% of the time these scripts at the bottom of the page require certain DOM nodes to be in existence for them to work. In the traditional top-down approach, this isn't a problem because all the relevant HTML is above these script tags.
Meteor does not have a top-down approach. If anything, it inserts sections of HTML into the page at different times, which means if you are coding in a top-down way, it's highly likely that at least some of your theme's script files get loaded before the HTML that they need to run are rendered on the page.
Your example of a login button event handling is a perfect example.
You first need the browser to parse
<button id="login-button"></button>
into a DOM node so that your accompanying event handler can work:
$('#login-button').click(function(){ //do something});
What that code is doing is first looking for something with #login-button, then attaching a click event listener to it. If #login-button doesn't exist by the time it runs, it has nothing to attach the listener to, and therefore your event handler won't run when the button is eventually clicked.
I'm making a game using JavaScript, currently I'm using window.location = "somepage.html" to perform navigation but I'm not sure if that is the correct way to do it. As I said in the title I've choosed Blank App Template so I do not have any navigator.js or something like.
Can you guys tell me the best way to do it?
Although you can use window.location to perform navigation, I'm sure you've already noticed a few of the downsides:
The transition between pages goes through a black screen, which is an artifact of how the underlying HTML rendering engine works.
You lose your script context between pages, e.g. you don't have any shared variables or namespaces, unless you use HTML5 session storage (or WinRT app data).
It's hard to wire up back buttons, e.g. you have to make sure each destination page knows what page navigated to it, and then maintain a back stack in session storage.
It's for these reasons that WinJS + navigator.js created a way to do "pages" via DOM replacement, which is the same strategy used by "single page web apps." That is, you have a div in default.html within which you load an unload DOM fragments to give the appearance of page navigation, while you don't actually ever leave the original script context of default.html. As a result, all of your in-memory variables persist across all page navigations.
The mechanics work like this: WinJS.Navigation provides an API to manage navigation and a backstack. By itself, however, all it really does is manage a backstack array and fire navigation-related events. To do the DOM replacement, something has to be listening to those events.
Those listeners are what navigator.js implements, so that's a piece of code that you can pull into any project for this purpose. Navigator.js also implements a custom control called the PageControlNavigator (usually Application.PageControlNavigator) is what implements the listeners.
That leave the mechanics of how you define your "pages." This is what the WinJS.UI.Pages API is for, and navigator.js assumes that you've defined your pages in this way. (Technically speaking, you can define your own page mechanisms for this, perhaps using the low-level WinJS.UI.Fragments API or even implementing your own from scratch. But WinJS.UI.Pages came about because everyone who approached this problem basically came up with the same solution, so the WinJS team provided one implementation that everyone can use.)
Put together then:
You define each page as an instance of WinJS.UI.Pages.PageControl, where each page is identified by its HTML file (which can load its own JS and CSS files). The JS file contains implementations of a page's methods like ready, in which you can do initialization work. You can then build out any other object structure you want.
In default.html, define a single div for the "host container" for the page rendering. This is an instance of the PageControlNavigator class that's defined in navigator.js. In its data-win-options you specify "{home: }" for the initial page that's loaded.
Whenever you want to switch to another page, call WinJS.Navigation.navigate with the identifier for the target page (namely the path to its .html file). In response, it will fire some navigating events.
In response, the PageControlNavigator's handlers for those events will load the target page's HTML into the DOM, within its div in default.html. It will then unload the previous page's DOM. When all of this gets rendered, you see a page transition--and a smooth one because we can animate the content in and out rather than go through a black screen.
In this process, the previous page control's unload method is called, and the init/load/processed/ready methods of the new page control are called.
It's not too hard to convert a blank app template into a nav template project--move your default.html/.css/.js content into a page control structure, add navigator.js to default.html (and your project), and put a PageControlNavigator into default.html. I suggest that you create a project from the nav app template for reference. Given the explanation above, you should be able to understand the structure.
For more details, refer to Chapter 3 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition, where I talk about app anatomy and page navigation with plenty of code examples.