Preload a file on javascript event, before display it - javascript

I have several CSS files generated in PHP.
I change the current CSS file with a click event.
But it make a nasty white flash effect between each change (only on the first load of them, the next times they are in cache and there is not bad effect).
How could I preload (but not display) this CSS file by the click event ?
$('.button').click(function(){
// Here I would like to preload the file
...
// Here I display it
$("#css").attr("href","css.php?id="+$(this).attr('id'));
});
EDIT > Solution
/* HTML File */
<link type="text/css" rel="stylesheet" href="css.php?id=1" id="css"/>
<link type="text/css" href="css.php?id=2" id="nextcss"/>
/* JS file */
$('.button').click(function(){
// Preload the file
$("#nextcss").attr("href","css.php?id="+$(this).attr('id'));
/* Here a lot of code with ajax...*/
// Here I display it
$("#css").attr("href","css.php?id="+$(this).attr('id'));
});

I'm assuming this "flash effect" means that, as the CSS is being loaded, the new rules are being applied incrementally, but you want all them to be applied at once. Is that right? Maybe you could append the newly created css element to the dom (ensuring it will start loading), but adjust its attributes so it won't be interpreted as a stylesheet (for instance, not using rel="stylesheet"). When it's done loading, you adjust it again with the right value, that should make the whole change appear instantly.
Another option (though that will require changing your css) would be creating a class, to be applied to the body, and making sure every rule references elements inside body.myclass. When the css is done loading, apply that class to the body.

Related

How to apply Bootstrap styling classes globally before publishing/loading a web page

I'd like to apply Bootstrap classes globally to my website and not have all the website elements jump around as the Bootstrap classes get applied through jQuery.
For example, I'd like to make every h1 element have the Bootstrap classes text-center and border-bottom. To do this, I can use jQuery's .addClass() method to apply the appropriate Bootstrap classes to all matching elements. The problem is that every time a user goes to a different page on the website, the un-styled elements load first, then they jump around as the Bootstrap classes get applied. I'm assuming this happens because my jQuery script only runs after the page has finished loading.
To avoid this, I could just put the Bootstrap classes directly in the h1 element, like so: <h1 class="text-center border-bottom">...</h1>. Obviously this is not a good solution though because I don't want to have to "hard-code" the classes onto every h1 element across the site.
Is there a way to apply Bootstrap classes before loading/publishing the website so that the "jumping" of web page elements doesn't happen?
I'm currently hosting the website locally using XAMPP and I am using PHP to include the same header and footer across all pages. The header and footer contain the necessary Bootstrap styling and script resources.
What I like to do is wrap my HTML in a div, lets call it wrap. And in the page's head:
<style>.wrap{display:none;}</style>
then in my 'CSS` file have
.wrap{display:block;}
Then in the footer defer the loading of my css:
<noscript id="deferred-styles">
<link rel="stylesheet" type="text/css" href="compressed.css" />
</noscript>
<script>
var loadDeferredStyles = function() {
var addStylesNode = document.getElementById("deferred-styles");
var replacement = document.createElement("div");
replacement.innerHTML = addStylesNode.textContent;
document.body.appendChild(replacement)
addStylesNode.parentElement.removeChild(addStylesNode);
};
var raf = requestAnimationFrame || mozRequestAnimationFrame ||
webkitRequestAnimationFrame || msRequestAnimationFrame;
if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
else window.addEventListener('load', loadDeferredStyles);
</script>
This will "hide" the contents of the page until the CSS is full loaded.
I also compress all of my CSS into one file, which is easy as I developed a custom CMS and don't use wordpress, but that is a different conversation.

How to dynamically add css to ckeditor without a css file

I have a situation where I am storing dynamic css data about a text object in a database as json. I need to map that same css data into styles in CKEditor. I am successfully able to load the classes into the CKEDITOR styles dropdown by parsing the json into the style set by running:
CKEDITOR.stylesSet.add('myStyles',styleObj);
Unfortunately this does not fully work with the onscreen text because the css does not exists as a file.
I've also successfully generate the css into the head of the dom by appending the dynamically generated css to a style tag. Unfortunately this still does not connect the actual css generated to the CKEDITOR because it is in a separate context.
Does anyone know how I can either connect document level css to the CKEDITOR instance or generate the CSS in a way that CKEDITOR understands? I'd prefer not to write a temporary CSS file to disk for every single user who needs to view the text object.
I figured out the answer to this by using the CKEDITOR.addCss() function.
Instead of trying to load the css into the document head as styles, the process can be much simpler by running CKEDITOR.addCss() function.
The code looks like:
for each css style found in the json:
styleObj.push({name:this.name,element:'p',attributes: { 'class':cssClassName}});
var cssSheetString = '.'+cssClassName+' {font-family:'+this.fontFamily+'; font-size:'+fontSize+'; font-weight:'+this.fontStyle+'; text-decoration:'+textDecoration+'; } ';
CKEDITOR.addCss(cssSheetString);
after the loop ends then also add the styles object:
if(!CKEDITOR.stylesSet.registered.myStyles){
CKEDITOR.stylesSet.add('myStyles',styleObj);
}
Just for posterity. I've seen answers that say this will work
CKEDITOR.on('instanceCreated', function (event) {
event.editor.addCss(styles);
});
but it does not, you have to use
CKEDITOR.on('instanceCreated', function (event) {
CKEDITOR.addCss(styles);
});
also if your styles variable changes you have to destroy and recreate your ckeditor instance with the new styles.

Inserting CSS for an Element from a input field

Is there any easy way to take in a block of CSS from the user from an textarea and add this styling to the styling for a specific div?
See I'm creating a simple code preview tool like codePen, so far I have two textarea inputs, one for Html and one for CSS, as the user types in the Html input this updates the preview pane, this works, now I want to do it for CSS.
CSS textarea could contain a few blocks like:
h1 {
font-size:23px;
}
.myClass {
//Somestyle
}
Now I want this CSS to be contained in the
<div id="preview"></div>
So it doesnt effect the rest of the page, so a manual example would be
$('preview h1').css('font-size','23px');
Anyway to automate this?
Do it like this. Hope it works.
Add a style block for dynamic styling.
<style id="dynamicCss">
</style>
on the apply button click handler, set the style
$('#btnApplyStyle').click(function(){
$('#dynamicCss').html('').html($('#txtaCustomCss').val());
});
See the Fiddle here.
Please use developer tools to see the new style tag added to head section.
This script simply adds rule to the document. If you don't want that behavior, you can use this plugin in combination with my logic to set scope for rule. You will need to place the style tag inside of the container and add a scoped attribute to style for it to work. Please see the documentation.
If you want to use the iframe approach instead, you'll first need an HTML document to host inside of the iframe. The iframe document should be loaded for the same origin (protocol + domain) as the host document (cross-document cross-domain stuff is tricky otherwise). With your application, this is probably not an issue.
Host page:
<iframe id="preview" src="preview.html"></iframe>
To make things easier on yourself, this iframe document could load a script with convenience functions for injecting the HTML and CSS from the host.
preview.html:
<html>
<head>
<script src="preview.js"></script>
<style type="text/css" id="page-css"></style>
</head>
<body></body>
</html>
preview.js:
function setHTML(html) {
document.querySelector('body').innerHTML = html;
}
function setCSS(css) {
var stylesheet = document.querySelector('#page-css');
// Empty the stylesheet
while (stylesheet.firstChild) {
stylesheet.removeChild(stylesheet.firstChild);
}
// Inject new CSS
stylesheet.appendChild(document.createTextNode(css));
}
Now, from the host page, you can call these functions whenever your text inputs change:
document.querySelector('#preview').contentWindow.setCSS(someCSS);
This plugin may come in handy: https://github.com/websanova/wJSNova/downloads .
Edited
Insert the text of the rules in one of the existing cssStyleSheets you have.
It will be something like
window.document.styleSheets[0].insertRule("a{color:red;}",window.document.styleSheets[0].cssRules.length)
The first parameter is the rule to insert and the second is the index.
Fiddle
The only problem here is that this will affect all the DOM on the page maybe looking for a way to add the #preview before each css rule to get something like
#preview h1{}

How to load and analyze page in background without loading images/scripts?

What's the best way to get usable DOM for an AJAX-requested page without loading any related images/scripts/etc?
Backstory:
I want to load a page in background, then perform a sort of data-mining on it (this is a browser extension, so I can't control the pages themselves). I do not want to spend time loading images and running scripts on the background page, since it is only page contents I need.
load data via ajax
strip all the tags containing src and href attributes, or simply change the value of those attributes with data:null. If data also contains inline style you should remove all statements containing a reference to external resources (e.g. background and border images, .htc components, xul bindings, .ico cursor)
append filtered data to the DOM and analyze it
step 2 could be achieved through a regular expression in javascript. e.g.
/* here we are in the ajax "success" callback */
...
data = data.replace(/(src|href|style)=['"]([^'"]+?)['"]/gi,
function(match, attribute) {
return (attribute.toLowerCase() === 'style')
? attribute + '=""' /* remove all inline style */
: attribute + '="data:null"'; /* href and src set to data:null */
})
/* append filtered data */
$(data).appendTo($('body_or_other_element'))
If possible, use jQuery, as I mentioned above. It makes it easy to select portions of the page DOM as needed.
Here are some examples:
You can grab tags href attribute like this: $("a", $(ajax_response)).attr("href");
Title's contents: $("title", $(ajax_response)).html();
You might have to test out the selectors to see which work best, but, I think this would be an easy way of going about this.

Best way to move html content from .js file to .html file - completed

I have links such that when the user clicks on them, the DOM is quckly updated using the methods below.
Basically, I just set the innerHTML document to the text and the page updates.
However I would like html code with other html code when applicable. This is the only place in my .js file that has a significant amount of text. How do I move this?
/*
link - quick dom links - would like to find a way to move this into xhtml where it belongs
*/
function o2(a,b)
{
return document.getElementById(a).innerHTML=b;
}
function l1()
{
........
I would recommend putting all of the possible HTML into your HTML file. Assign a unique id to each element and use CSS to hide them all or all but one by default (using 'display: none'). Then your javascript function can simply change CSS based on which html fragment you need to be visible.

Categories