Dynamic loading of CSS in Dojo/Dijit? - javascript

The tutorial "Creating a custom widget" proposes a directory structure for a dijit widget, that includes 'css' directory. Everything else in the example is dymanicly loaded using AMD, but not CSS. The authors write:
Now, with that in place, we just need to add the CSS to our head on
our page, and we have a nicer looking author list!
However, does Dojo/Dijit has any mechanism that doesn't required putting all possible CSS stuff in HTML HEAD or some aggregating CSS (imports)?
It is possible to simply add the section to the header, but it requires checking first, if it was already loaded, and probably waiting for CSS to load. Is there some build-in solution for making that things?

See http://davidwalsh.name/amd-xstyle and https://github.com/kriszyp/xstyle#amd-plugin-loader
A brief example of usage, straight from the docs:
define(["xstyle!./path/to/file.css"], function(){
// module starts after css is loaded
});
There have been some issues in the past when combining this with Dojo builds. However, it appears #kriszyp has now documented this stuff fairly well - https://github.com/kriszyp/xstyle#building-with-amd-plugin

Related

How to combine good result with google page speed and putting css on bottom of the page?

I am trying to get good results for pageSpeed with google on my page.
I got good results but putting CSS and JS on bottom of the page.
But I got the problem: my page renders without CSS, then got rendered normally after css is loaded (it produces like a page flash)
I tried to solve by putting style on body display: none
then added the jquery document.ready and put display to normal, but my google page speed results went down again.
Is there a solution/tip to get good pageSpeed results with good rendering of the page.
Unfortunately with HTTP/1 we are forced to bundle all our css rule-sets into one file to prevent multiple resource requests, this won't be the case with HTTP/2.
Speed is definitely something you would want to improve in a website, but the important point here is how fast useable content is in front of the visitors. The resources you use will eventually increase in size, this shouldn't be proportional to the time the user waits to be able to use the page. Focus on perceived performance.
What is the current problem with CSS files located in the head tag?
A: They block rendering until the file is loaded.
What can you do about it?
There is a specification that involves the preload keyword used in the link tag to load css files asynchronously.
This specification defines the preload keyword that may be used with
link elements. This keyword provides a declarative fetch primitive
that initiates an early fetch and separates fetching from resource
execution.
Source: w3
This, however, is still not fully supported by browsers. (Browser support here).
A solution is to use loadCSS which is basically a polyfill.
The new <link rel="preload"> standard enables us to load stylesheets
asynchronously, without blocking rendering, and loadCSS provides a
JavaScript polyfill for that feature to allow it to work across
browsers, as well as providing its own JavaScript method for loading
stylesheets.
Finally, the technique that is commonly proposed is the following:
Load a stylesheet with the critical css rule-sets to be able to display
information to the user, such as layout formatting, this is included as you normally would, in the head tag with <link>.
Load the stylesheet with the css rule-sets that are not critical to the initial rendering of the page which will be loaded with loadCSS.
Notes:
If you go down this path make sure to check tools like
webpagetest.org to test perceived performance.

does ember.js care whether its called at the top or at the bottom of a page

So after looking at a few examples it looks like ember apps call 'ember.js' and
'jquery.js' at the top/head of an html page.
All the jquery sites I worked on called jquery at the bottom of the page.
(just before the ending body tag)
I want to migrate these sites to ember bit by bit...
So the question is, when developing an ember.js application, should
the scripts be included/called first or last
Javascript library/framework must be called before the scripts that use the library/framework. That is why you e.g. get a "$ is not defined" error when jQuery is linked at the bottom of the HTML structure and there's a jQuery code before the library is loaded.
So, the thing you need to keep in mind is to load ember.js before you use it. Of course, best website-performance/SEO practice is to keep your scripts "low", before the closing <body> tag.

Remove all CSS rules

Is there a way to wipe out all CSS rules once style sheets have already been loaded?
I have to use a proprietary JavaScript library (ESRI's ArcGIS Server API) which is built on top of Dojo. I make extensive use of Dojo's widgets and would like to use Dojo's claro theme but unfortunately the ESRI library mungs up the CSS by loading in off-site CSS files (and probably CSS rules hard-coded in the JS). This ends up mangling the Claro theme.
So many Dojo widget CSS classes get rewritten and new rules get created that just wiping out all CSS and reloading the standard Dojo stylesheets seems easier/safer.
Something like the following would be nice:
* {none}
but I figure I'll have to end up using either Dojo or jQuery to accomplish this.
check out this bookmarklet called RefreshCSS by Paul Irish:
javascript:(function(){var h,a,f;a=document.getElementsByTagName('link');for(h=0;h<a.length;h++){f=a[h];if(f.rel.toLowerCase().match(/stylesheet/)&&f.href){var g=f.href.replace(/(&|%5C?)forceReload=\d+/,'');f.href=g+(g.match(/\?/)?'&':'?')+'forceReload='+(new Date().valueOf())}}})()
It refreshes the CSS stylesheets on a page, without refreshing the page itself.
I think you could do some alterations to it and get it to do what you want?
Another approach using jQuery that might work is to run this once the page has loaded:
$('head link, head style').remove();
Nope. Sadly, such a thing does not exist.
The answers to these related questions give pretty much the rundown on what is possible in terms of workarounds.
Is there a way to “sandbox” an html block away from its page's CSS without using iframes?
Reset CSS for a certain area of the page?
prevent meyer reset css to mess with dynamic content
How to reset css in middle of html document ?
There is always document.head.innerHTML = ""; But it really cleans house so you have to store away any scripts,metatags, titles or whatever you want to save and add them again.

YUI: ensuring DOM elements and scripts are ready

If I put my inline script after the DOM elements it interacts with, should I still use YUI 3's domready event?
I haven't noticed any problems, and it seems like I can count on the browser loading the page sequentially. (I already use YUI().use('node', ... to make sure the YUI functions I need have been loaded since the YUI script is a separate file.)
Is there a way to speed up the loading of widgets like YUI 2's calendar?
I load the appropriate script in <head> element of my page. I use YUI().use('yui2-calendar', ... to make sure the Calendar widget is available. Unfortunately, this causes a short but noticeable delay when I load my page with the calendar. If I omit the YUI().use('yui2-calendar', ... code then it shows up without a noticeable delay - but I guess this could cause the Calendar to not show up at all if the YUI script doesn't load in time?
With regards to #2, is it possible to reduce the visual artifact of the calendar not being present and then showing up?
I've made it slightly better by specifying a height and width for the parent div so that at least the space is already allocated => minimal shifting around when it does load.
You don't need domready if the code that accesses DOM elements comes after those elements in the markup. This applies to DOM scripting in general, not just YUI.
yui2-calendar is not identical to yahooapis.com/2.8.0r4/build/calendar/calendar-min.js. The former includes some wrapping code to sandbox the Calendar API and its dependencies in the YUI 3 instance environment. If you're including the YUI 2 scripts in the <head> (which you arguably should place at the end of the <body>), you don't need to use yui2-calendar. Doing so just loads the Calendar code twice. Otherwise, to leverage YUI 3's dynamic async loading, you can remove the <script>s from the <head> and just use('yui2-calendar'). You can get the appearance of speeding up the time to render by including the yui2-* combo <script> in your markup after the yui-min.js seed file. Note the Loader will always fetch the css file, so you don't need to include that in the markup.
<script src="http://yui.yahooapis.com/combo?3.1.0/build/yui/yui.js"></script>
<script src="http://yui.yahooapis.com/combo?2in3.1/2.8.0/build/yui2-yahoo/yui2-yahoo.js&2in3.1/2.8.0/build/yui2-dom/yui2-dom.js&2in3.1/2.8.0/build/yui2-event/yui2-event.js&2in3.1/2.8.0/build/yui2-calendar/yui2-calendar.js"></script>
You can include the css and markup of a rendered Calendar on page load, then render into the markup container. I don't think YUI 2 calendar has the notion of progressive enhancement of existing markup baked in, but I could be wrong. It should clobber the static table markup with its generated markup and vivify the UI.
If it's after the said nodes in question, then you don't need DOMContentLoaded (or domready).

dojo.require issues

I'm having trouble configuring my initial installation of dojo to include the widget framework correctly.
Following most of the code I see, including dijit should look like this:
dojo.require("dijit");
and that's that. Unfortunately, that doesn't seem to work.
Using this initializes the widgets correctly, but there's some weird behavior from the standard dijit methods that makes me think that I'm doing it wrong:
dojo.require("dijit.dijit");
Is there an element of configuring dojo that I'm missing? The files are all placed as they are in the 1.2.3 distribution, underneath another javascript folder.
You don't actually have to include dijit, just point directly to widgets you want to use: dojo.require("dijit.Dialog");. Weird widget behavior could be explained also by:
missing theme css files: check with FireBug that everything gets loaded
missing theme class attribute: add class="tundra" to the body element
missing djConfig="parseOnLoad: true"

Categories