CSS Inliner in Javascript (premailer) - javascript

I use CKEDITOR 4 and I want to filter a HTML content to insert the style directly in the HTML Elements like MailChimp with its CSS inliner (http://beaker.mailchimp.com/inline-css). But I have to do in Javascript must, someone an idea?
I can use jQuery and PrototypeJs.
I can't use an external API.
My test jsFiddle with CKEditor (on paste) : http://jsfiddle.net/EpokK/utW8K/7/
In :
<style>
.test {
outline: 1px solid red;
}
</style>
<div class="test">Hello</div>
Out :
<div style="outline: 1px solid red;">Hello</div>
I find this solution : http://tikku.com/scripts/websites/tikku/css_inline_transformer_simplified.js
but this trick opens a tab and it is blocked by default in Firefox ...
API solution : http://premailer.dialect.ca/

Edit: Cleaning up my GH account from unfinished PoCs I removed the tool mentioned below, so the link leads to a 404. There's someone else's project, though, which may interest you: http://styliner.slaks.net/
I created simple CSS styles inliner - styliner.
It works on Firefox and Chrome. May also work on IE9+ and Safari 6, but I haven't tested it yet. This version does not need a new window - it uses iframe (so it may not work on IE - it always needs some tricks to make iframes work :).
It lacks support for CSS specificity, so at least for now, to use it, you would have to sort rules manually. But maybe I'll find some time to add this feature soon.

I'm not sure if this will help but I found this nice little jQuery/javascript method that can be embedded into a page - http://devintorr.es/blog/2010/05/26/turn-css-rules-into-inline-style-attributes-using-jquery/
I've edited it a little to support IE and also to support a page with multiple CSS files attached applying the styles in the correct order. The if(rules[idx].selectorText.indexOf("hover") == -1) line is necessary because jQuery (as of 1.8) can't use the :hover selector anymore apparently.
$(document).ready(function ($) {
var rules;
for(var i = document.styleSheets.length - 1; i >= 0; i--){
if(document.styleSheets[i].cssRules)
rules = document.styleSheets[i].cssRules;
else if(document.styleSheets[i].rules)
rules = document.styleSheets[i].rules;
for (var idx = 0, len = rules.length; idx < len; idx++) {
if(rules[idx].selectorText.indexOf("hover") == -1) {
$(rules[idx].selectorText).each(function (i, elem) {
elem.style.cssText = rules[idx].style.cssText + elem.style.cssText;
});
}
}
$('style').remove();
$('script').remove();
$('link').remove();
}
});
The page can then be copy/pasted into the email body.

Related

.focus() is not working in Chrome and Edge

For our website, we use Internet Browser before and it was totally fine with no errors but starting from yesterday we migrated to modern browsers and when we click, we get error message Uncaught TypeError: document.hwinv.datatyp.options.focus is not a function in the developer tool. Error is causing in document.hwin.datatyp.options.focus(); line. Before using in Edge, it was totally fine and right now, it is causing that error. May I know how can I fix it? Added JS Fiddle link to check. Also, I saw adding setTimeout but I don't know how that works.
JsFiddle link, U can see the the bottom of the web, there is 2 button and If i click those buttons, causing the error for .focus()
function gonext()
{
var myIndex = document.hwinv.datatyp.options.selectedIndex;
var chkvalue=document.hwinv.datatyp.options[myIndex].value;
if(!(chkvalue))
{
document.hwinv.datatyp.options.focus();
alert("Please select Hardware Type!");
}
else
{
document.hwinv.step.value='11';
document.hwinv.submit();
}
}
<body style="margin=0px;" alink="#0000ff" vlink="#0000ff" bgcolor="#ffffff" window.focus="document.hwinv.datatyp.options.focus();">
<form name="hwinv" method="post" action="inventory.php" target="bottomview">
Welcome to StackOverflow!
Oh boy. If this is the sort of HTML that your site has, then migrating it to use more "modern" HTML, CSS and JS is going to be quite a long process. But it has to be done, now that IE is officially dead.
Alternative: Use "Internet Explorer Mode" in Edge
You may not be aware that there is a way to switch Edge into running a site almost identically to how IE would have done it. Which might be enough to get your site working again. I found some decent instructions for how to do that.
However, I wouldn't rely on that as a long-term solution. At some point, you are going to need to migrate this site to use HTML5, CSS3, and modern JS. But it might help you out in a pinch.
Fixing your code
To start with, the specific answer to your question about the exception is that the focus() method doesn't exist on the .options property of select inputs. Rather, it exists on the select input object itself.
But we also want to deal with the other antiquated markup in the snippet you posted.
window.focus="..." is not a thing. There are on____ attributes on elements - such as onfocus in your case, but it is considered bad practice to use it, typically. Instead, register an event handler in the JS code like I do below.
style="margin=0px" is wrong. Within inline style attributes, the syntax is property: value, not property=value.
alink, vlink and bgcolor attributes should be replaced with the appropriate CSS, as I have done below. alink corresponds to body a, vlink corresponds to body a:visited and bgcolor corresponds to body { background-color: white; }.
function gonext() {
var myIndex = document.hwinv.datatyp.options.selectedIndex;
var chkvalue = document.hwinv.datatyp.options[myIndex].value;
if (!(chkvalue)) {
document.hwinv.datatyp.focus();
alert("Please select Hardware Type!");
} else {
document.hwinv.step.value = '11';
document.hwinv.submit();
}
}
document.addEventListener('DOMContentLoaded', function () {
document.hwinv.datatyp.focus();
});
body {
margin: 0;
background-color: white;
}
body a {
color: blue;
}
body a:visited {
color: blue;
}
<body>
<form name="hwinv" method="post" action="inventory.php" target="bottomview">
<select name="datatyp">
<option>Hammer</option>
<option>Spanner</option>
<option>Other</option>
</select>
</form>
</body>

Jquery to pure JS

I have some script in jquery, but i have a problem that on page i dont use Jquery, this is just example what i need, it is much more complex.
$('img').each(function(){
$(this).removeAttr('width');
$(this).removeAttr('height');
$(this).addClass('img-responsive');
});
It is for moving attributes from images and adding class responsive, because user uses a lot TinyMce and by default it is putting witdh and height. I know maybe there is some plugin for TinyMce but i need some common solution
This should work but you may need to modify for all browsers:
document.querySelectorAll('img').forEach(function (e) {
e.removeAttribute('width')
e.removeAttribute('height')
e.classList.add('img-responsive')
})
See documentation for compatibility:
Element.removeAttribute
Element.classList
Array.prototype.forEach
var images = document.querySelectorAll("img");
for (var i = 0; i < images.length; i++) {
images[i].removeAttribute("width");
images[i].removeAttribute("height");
images[i].classList.add("img-responsive");
}

Moving Caret to start when focused

I'm trying to replicate a facebook like comments section bevaviour so when a user wants to add a new comment the text color is fading and the caret is at the begenning of the new massage. I'm using this code:
var inp = document.getElementsByTagName('input')[1];
if (inp.createTextRange) {
var part = inp.createTextRange();
part.move("character", 1);
part.select();
} else if (inp.setSelectionRange){
inp.setSelectionRange(1, 1);
}
and it seems to work but when I try to put it inside a Jquery selector like this:
$("#massages_body input").focus(function(){
$(this).css('color', 'rgba(128,128,128,0.4)');
if ($(this).createTextRange) {
var part = $(this).createTextRange();
part.move("character", 1);
part.select();
} else if ($(this).setSelectionRange){
$(this).setSelectionRange(1, 1);
}
});
it doest'nt work at all. I'm sure i'm using Jquery or Javascript wrong here but I can't find the problem. Thanks for your help!
What I believing you are thinking of is Facebook's use of form input placeholders which are a part of the HTML5 spec and supported by all major and modern browsers.
You can use this library to reproduce that effect for legacy browsers as well: Placeholders.js

testing support for overflow-y:auto in browsers

I want to test if a particular css property attribute is supported in the browser. For a css property, i can do it like
var overflowSupport = document.createElement("detect").style["overflow-y"] === ""
But what if i have to check for a particular class or attribute. For example, i want to test the support for
overflow-y:auto
and use it for scrolling a large div, where supported, and use iScroll at other places.
How can i do that? Pls help.
Kind of an old question, but I thought I'd share my finds here, especially because the code sample given by Inkbug does not work as you would expect.
Overflow property support
overflow-y has been around since the CSS2.1 times (however it's been standardized pretty recently, in the css3 spec). For that reason, the support on desktop browsers is very decent.
Now, what you're asking here is whether or not the scrolling behavior actually works when we specify overflow-y: scroll on a particular element.
This behavior was introduced fairly recently in mobile browsers. More precisely, Apple introduced it in iOS 5 with a -webkit vendor prefix (see page 176 of Apple's documentation).
I can't find specific info for Android though.
What I can say about support for overflow-scrolling (vendor prefixed or not):
latest nexus7 (Android 4.1.1): yes
Android 2.3.x: no
iOS >= 5: yes
iOS < 5: no
Feature detection for scrolling-overflow
If you want to give scrolling behavior to an element, I would advise using feature detection.
Here's a gist showing how you can detect this scrolling-overflow property (it's been integrated in Modernizr since). If you don't want to use Modernizr, here is a simpler version that does pretty much the same:
/**
* Test to see if overflow-scrolling is enabled.
*/
var hasCSSProperty = function(prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(document.body, null)[prop];
} else {
return document.body.currentStyle[prop];
}
};
var supportOverflowScrolling = function() {
if (hasCSSProperty('overflow-scrolling') ||
hasCSSProperty('-webkit-overflow-scrolling') ||
hasCSSProperty('-moz-overflow-scrolling') ||
hasCSSProperty('-o-overflow-scrolling')) {
return true;
} else {
return false
}
};
When one assigns an invalid value to a dom style, it gets rejected. Therefore this should work:
var testOverflowEl = document.createElement( "x-test" );
testOverflowEl.style.overflowY = "auto";
var overflowSupport = testOverflowEl.style.overflowY === "auto";
Arnaud Brosseau's reply surely deserves the checkmark.
Anyway, consider also using Modernizr.
Using their addTest and testAllProps API functions, you can easily check for any css property support:
Modernizr.addTest('overflow-y',function(){
return Modernizr.testAllProps('overflowY'); /* camel case here */
});
Then you can check it with JavaScript:
if(Modernizr.overflowY){
/* do something if supported */
}
but it will also add a class to the <html> tag, so that you can custom rules on CSS too:
.overflowY #element {
/* style for browsers supporting overflow-y */
}
.no-overflowY #element {
/* style for browsers NOT supporting overflow-y */
}

Automated DD Belated png script

I've been using http://www.dillerdesign.com/experiment/DD_belatedPNG/ for a while now and it has solved most of my IE6 png headaches.
I wonder though, whether there is a way of automating it so that I don't have litter my code with class="png" or adding the ids of html elements using background images to a JS file. - I don't care really that this would slow IE6 down - It's easier to explain to a client that the website is slow due to their browser than it is to explain why everything has a grey background!
I'm not really a JS expert but I guess grabbing the src attribute and adding the file name to the class isn't difficult. - Somehow parsing the CSS and and adding the id of the containing element sounds difficult if not impossible though??
This isn't tested but here is my jQuery solution which should work. It basically checks all img elements for a .png extension then checks all elements except img for a background image with a .png extension
You may need to add in extra code to check for CSS background property as well as background-image. With the body * selector I would imagine a lot of overhead on pages with lots of elements but I'm with you, I don't care how long it takes IE6 users to load the page if they don't care about updating their browser
$(function() {
$('img').each(function() {
if(this.src.split('.').pop() == 'png') {
DD_belatedPNG.fixPng(this)
}
});
$('body *:not(img)').each(function() {
if($(this).css('background-image').split('.').pop().replace(/("|\')\)/,'') == 'png') {
DD_belatedPNG.fixPng(this);
}
});
});
EDIT: I found this quite an interesting challenge so wrote up a pure JavaScript solution. It needs to be run when the DOM is ready though, so if you really don't want to use jQuery or another framework with a DOM ready function you'll have to use Dean Edwards' method, like so:
document.write('<script type="text/javascript" id="domready" defer="defer" src="javascript:void(0)"><\/script>');
document.getElementById("domready").onreadystatechange = function() {
if (this.readyState == "complete") {
var imgs = document.getElementsByTagName('img')
for(i=0; i < imgs.length; i++) {
if(imgs[i].src.toLowerCase().search(/\.png$/) != -1) {
DD_belatedPNG.fixPng(imgs[i]);
}
}
var children = document.body.getElementsByTagName('*');
for(i=0; i < children.length; i++) {
var bg = children[i].currentStyle.backgroundImage;
if(bg != 'none' && bg.toLowerCase().search(/\.png("|\')?\)$/) != -1) {
DD_belatedPNG.fixPng(children[i]);
}
}
}
}

Categories