CSS by data-attribute will not refresh/repaint - javascript

In a HTML5/JS application we have a view with some styles depending on the data-attribute of elements:
like
<li data-level="0"></li>
or
<li data-level="1"></li>
CSS
li[data-level^="1"] {
/* some styles */
}
This seems to work just fine everywhere on page reload.
But when the data-attribute get set programmatically via JS, the CSS properties get rendered in all relevant desktop browsers, but not in mobile safari.
JS part looks like this:
this.$el.attr('data-level', this.model.getLevel())
Any ideas on how to force to apply those properties (refresh/repaint something) ?
I would like to avoid using the class attribute and different classes as things are more complex than shown here...

ok, changing data attributes simply doesn't seem to trigger a redraw of the element in all browsers !?
Changing the class attribute however does.
Kind of a workaround, but does the trick.
this.$el
.attr('data-level', this.model.getLevel())
.addClass('force-repaint')
.removeClass('force-repaint');
As seen here: Changing a data attribute in Safari, but the screen does not redraw to new CSS style

In my case, I was working with a font icon generated with icomoon and using the data attribute data-icon to change the HTML entity dynamically.
On page reload, it would work in tandem with this css:
[data-icon]:before {
content: attr(data-icon);
}
But without reload, and even by changing classes, it didn't change, just displayed the code.
<span class="font-icon" data-icon=""></span>
What worked for me was using this function, which I edited to the following (assuming code in the shape of e901):
export class StringUtils {
static emptyElement = document.createElement('div');
static fontCodeToSymbol(code: string): string {
let element = StringUtils.emptyElement;
let symbol: string | nullable = `&#x${code};`;
if (symbol && typeof symbol === 'string') {
element.innerHTML = symbol;
symbol = element.textContent;
element.textContent = '';
}
return symbol || '';
}
}
Which would directly feed the correct character in data-icon:
<span class="font-icon" data-icon=""></span>

Related

Add hanging indent to CKEditor on web page [duplicate]

I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}

addClass(); jQuery Function Not Working in Firefox

I have a script that picks a random background image for the body element of my document from a directory called bg-images. If the chosen background image has "_dark" in the image file name, I would like to add a special class to the body element.
Here is the jQuery I'm using. It works great in Chrome & Safari, but does nothing in Firefox:
var backgroundImage = $('body').css('background');
var isitdark = "_dark";
if (backgroundImage.indexOf( isitdark ) != -1 ) {
$('body').addClass("dark");
} else {
$('body').removeClass("dark");
}
How come this doesn't do anything in Firefox? Is there a better way of writing it?
I've tried adding "type=text/javascript" to all my script tags but that doesn't seem to help and the rest of the jQuery on my site works correctly in all browsers.
You're not getting the background image with $('body').css('background'); Use .css('background-image')
var backgroundImage = $('body').css('background-image');
It's not necessary because the string _dark will or will not be there but if you want to you can remove the url() or url("")
var backgroundImage = /url\(\s*(['"]?)(.*?)\1\s*\)/g.exec($('body').css('background-image'))[2];
Works fine in FF
http://jsfiddle.net/mNX3A/
background is a shorthand property. Shorthand properties are not guaranteed to be retrieved correctly with css:
Retrieval of shorthand CSS properties (e.g., margin, background, border), although functional with some browsers, is not guaranteed.
If you specifically want to get background-image, get background-image:
var backgroundImage = $('body').css('background-image');

How to dynamically set and modify CSS in JavaScript?

I have some JavaScript code that creates some div elements and it sets their CSS properties.
Because I would like to decouple CSS logic from my JavaScript code and because CSS is easier to read in its own .css file, I would like to set the CSS className of my element and then dynamically inject some values into the defined CSS property.
Here is what I would like to do :
style.css:
.myClass {
width: $insertedFromJS
}
script.js:
var myElement = document.createElement("div");
myElement.className = "myClass";
I want to do something like this but at that point myElement.style.width is empty
myElement.style.width.replaceAll("$insertedFromJS", "400px");
I think my problem here is that after the call to myElement.className = "myClass", the CSS is not yet applied.
If I understand your question properly, it sounds like you're trying to set placeholder text in your css file, and then use javascript to parse out the text with the css value you want to set for that class. You can't do that in the way you're trying to do it. In order to do that, you'd have to grab the content of the CSS file out of the dom, manipulate the text, and then save it back to the DOM. But that's a really overly-complicated way to go about doing something that...
myElement.style.width = "400px";
...can do for you in a couple of seconds. I know it doesn't really address the issue of decoupling css from js, but there's not really a whole lot you can do about that. You're trying to set css dynamically, after all.
Depending on what you're trying to accomplish, you might want to try defining multiple classes and just changing the className property in your js.
Setting the style, might be accomplished defining the inner-page style declaration.
Here is what i mean
var style = document.createElement('style');
style.type = 'text/css';
style.cssText = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);
document.getElementById('someElementId').className = 'cssClass';
However the part of modifying it can be a lot of tricky than you think. Some regex solutions might do a good job. But here is another way, I found.
if (!document.styleSheets) return;
var csses = new Array();
if (document.styleSheets[0].cssRules) // Standards Compliant {
csses = document.styleSheets[0].cssRules;
}
else {
csses = document.styleSheets[0].rules; // IE
}
for (i=0;i<csses.length;i++) {
if ((csses[i].selectorText.toLowerCase()=='.cssClass') || (thecss[i].selectorText.toLowerCase()=='.borders'))
{
thecss[i].style.cssText="color:#000";
}
}
could you use jQuery on this? You could use
$(".class").css("property", val); /* or use the .width property */
There is a jQuery plugin called jQuery Rule,
http://flesler.blogspot.com/2007/11/jqueryrule.html
I tried it to dynamically set some div sizes of a board game. It works in FireFox, not in Chrome. I didn't try IE9.

How to reset the style properties to their CSS defaults in javascript?

On a php generated page there are several elements like this:
<td class="defaultTDStyle" style="color:userDefinedCustomColor" id="myTDId"></td>
So there is a default style and I apply several extra styles that override the style defined in the CSS.
Is there a way to remove these added styles from javascript?
It seems the obj.style.color="default" and obj.style.color="auto" don't work. How can I reset the color to the CSS default from javascript?
If recollection serves, obj.style.color="" should work... I don't know if it's right though.
Set the style property values to the empty string:
obj.style.color = "";
The new way:
el.attributeStyleMap.delete('color')
or clear everything:
el.attributeStyleMap.clear()
Not all browsers support this yet though. See StylePropertyMap on MDN for more details and browser compatibility.
See also CSS Typed Object Model and Working with the new CSS Typed Object Model.
You could save the attribute style before overriding it, and then apply it again. Like this:
// Get element styling
const element = document.getElementById('someId');
const style = element.getAttribute('style');
const classList = element.classList;
/** Code for overriding element styling goes here **/
// Retrieve original styling
const newClassList = element.classList;
for (let item of newClassList)
element.classList.remove(item);
for (let item of classList)
element.classList.add(item);
element.setAttribute('style', style);

How can I undo the setting of element.style properties?

I have an element in my document that has a background color and image set through a regular CSS rule.
When a certain event happens, I want to animate that item, highlighting it (I'm using Scriptaculous, but this question applies to any framework that'll do the same).
new Effect.Highlight(elHighlight, { startcolor: '#ffff99', endcolor: '#ffffff', afterFinish: fnEndOfFadeOut });
The problem i'm facing is that after the animation is done, the element is left with the following style (according to FireBug):
element.style {
background-color:transparent;
background-image:none;
}
Which overrides the CSS rule, since it's set at the element level, so I'm losing the background that the item used to have...
What I'm trying to do is, in the callback function I'm running after the animation is done, set the style properties to a value that'll make them "go away".
var fnEndOfFadeOut = function() {
elHighlight.style.backgroundColor = "xxxxx";
elHighlight.style.backgroundImage = "xxxxx";
}
What I'm trying to figure out is what to put in "xxxx" (or how to do the same thing in a different way).
I tried 'auto', 'inherit', and '' (blank string), and neither worked (I didn't really expect them to work, but I'm clueless here).
I also tried elHighlight.style = ""; which, expectably, threw an exception.
What can I do to overcome this?
I know I can put a span inside the element that I'm highlighting and highlight that span instead, but I'm hoping I'll be able to avoid the extra useless markup.
Chances are you're not setting the style on the correct element. It's probably being set somewhere up the line in a parent node.
elHighlight.style.backgroundColor = "";
elHighlight.style.backgroundImage = "";
You can also remove all the default styling by calling:
elHighlight.style.cssText = "";
In any case, you'll still have to do this on the specific element that is setting these properties, which means you may need to do a recursion on parentNode until you find it.
Try
elHighlight.style.removeProperty('background-color')
elHighlight.style.removeProperty('background-image')
have you tried elHightlight.style.background = "";?
I have a highlighter code on my site and this works
function highlight(id) {
var elements = getElementsByClass("softwareItem");
for (var ix in elements){
elements[ix].style.background = ""; //This clears any previous highlight
}
document.getElementById(id).style.background = "#E7F3FA";
}
An HTML element can have multiple CSS classes. Put your highlight information inside a CSS class. Add this class to your element to highlight it. Remove the class to undo the effect.

Categories

Resources