Raphael JS - Prevent text highlighting when clicking - javascript

DEMO: http://jsfiddle.net/p7Lze6nh/
Using Raphael JS 2.1.2 and I'm trying to disable text highlighting when an element is clicked. It does it on Chrome, but not on IE for some reason. I don't have FF on this laptop at the moment to test.
The code is relatively straightforward-
var paper = Raphael(0, 0, 125, 125);
paper.canvas.style.backgroundColor = "Black";
var a = 0;
text1 = paper.text(10, 10, a).attr({"text-anchor":"start", fill:"white"});
rect1 = paper.rect(10, 50, 50, 50).attr({fill:"white"});
rect1.click(function(){
inc()
});
function inc() {
a++;
text1.attr({text: a});
}
I've tried using the 'user-select: none' and other various CSS rules found via examples for the div containing the paper, but that didn't work. I've also tried using
text1.userSelect = "none";
...and the others directly into javascript, but I didn't get anywhere, either. I recall Cookie Clicker having this problem, but I can't seem to find the solution in the code. But, it also uses canvas instead of Raphael.

User select should work ok, but not in the format shown. You can't just set an object variable like that.
Using css styling, it can be done like this...
text {
-moz-user-select: none;
-webkit-user-select: none;
}
jsfiddle
and slightly different version setting class direct...
.donthighlight {
-moz-user-select: none;
-webkit-user-select: none;
}
text1.node.setAttribute("class","donthighlight");
jsfiddle
I guess be wary some older browsers may not support this, which is a reason Raphael is often used, and extend the css to include the other browsers.

Related

Using getComputedStyle with IE 11

NOTE: This has an update below. I will likely change description as it is not a getComputedStyle issue, it is an issue actually with print-media and the fact that Internet Explorer now supports document.styleSheets[].cssRules.
I am a bit confused on this as I thought this worked and I am not sure it just recently broke. I am using getComputedStyle which I thought was support in all modern browsers, but I do not get the expected answer with IE 11. Given this code:
getRealStyle: function(elm, attributes) {
var returnObj = {};
var computed = getComputedStyle(elm);
for(var i=0; i<attributes.length; i++) {
returnObj[attributes[i]] = computed[attributes[i]];
}
return returnObj;
},
Where "attributes" is an array of names which I am interested in getting the computed CSS for. It is like this:
attributes: [
'lineHeight',
'alignmentBaseline',
'backgroundImage', 'backgroundPosition', 'backgroundRepeat', 'backgroundColor',
'baselineShift',
'borderTopWidth','borderTopStyle','borderTopColor',
'borderBottomWidth','borderBottomStyle','borderBottomColor',
'borderLeftWidth','borderLeftStyle','borderLeftColor',
'borderRightWidth','borderRightStyle','borderRightColor',
'borderCollapse',
'clear', 'color',
'display', 'direction', 'dominantBaseline',
'fill', 'float',
'fontStyle', 'fontVariant', 'fontWeight', 'fontSize', 'fontFamily',
'height',
'listStyleType', 'listStyleImage',
'marginTop', 'marginBottom', 'marginLeft', 'marginRight','orphans',
'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
'pageBreakAfter', 'pageBreakBefore',
'stroke', 'strokeWidth',
'strokeOpacity', 'fillOpacity',
'tableLayout',
'textAlign', 'textAnchor','textDecoration', 'textIndent', 'textTransform', 'textShadow',
'verticalAlign',
'widows', 'width'],
The only problem I seem to have is "backgroundColor".
If I pass in an "elem" h1 and:
If I set on the "h1" style="background-color:rgb(238, 238, 238);"
The computed background color is returned correctly in IE 11, Chrome, Firefox
If however I set the "h1" style in CSS like this:
h1{
border-top:3px solid #111111;
background-color:rgb(238, 238, 238);
font-size:30px;
padding:3px 10px 3px 0px;
}
The computed background-color in IE only is returned as transparent. Chrome and Firefox do not have his problem.
Even more strange in that sample, "attributes" also contains entries for the border like borderTopColor and that is correctly computed with that code in all browsers including IE.
The page in question is here:
http://www.cloudformatter.com/CSS2Pdf
The code runs when selecting the "Out PDF" button.
If you format this with Chrome, the "h1" at the top of the page in the resulting PDF will have the silver background because the background-color is picked up in getComputedStyle. The border-top will also be there. But if you format in IE11 the background-color will be missing because it is returned as "transparent" but the border will be there and both of these are set in the css.
Similar behavior you can see here http://www.cloudformatter.com/CSS2Pdf.Demos.InlineElements
The "Exception" box is 100% in css. The border works but the color and image does not as they are missing. The font color is also missing as that is set in CSS ... but not everything in CSS is ignored. I even added a few console write's (left is IE, right is Chrome).
IN the above code, I have tried this so far and IE returns "transparent" for the background-color BUT returns the correct color for the border:
getRealStyle: function(elm, attributes) {
var returnObj = {};
var computed = getComputedStyle(elm);
if (elm.localName == 'h1'){
console.log('***** ' + elm.localName + ' *****');
console.log('BackgroundColor: ' + computed.backgroundColor);
console.log('PropValue: ' + computed.getPropertyValue('background-color'));
console.log('BorderTopColor: ' + computed.borderTopColor);
}
for(var i=0; i<attributes.length; i++) {
returnObj[attributes[i]] = computed[attributes[i]];
}
return returnObj;
},
So, am I missing something here or is getComputedStyle not working for IE 11 for something's in external CSS?
UPDATE:
After hours and hours I have isolated the issue as NOT being getComputedStyle. It turns out that IE is working and in fact doing so as we expected in our coding. It is the other browsers that had issues we had not noted until now.
The code uses document.styleSheets[].cssRules to iterate over all CSS and extract print media directives to apply for the PDF formatting. One of those linked CSS files on a remote server is "bootstrap.min.css" and buried within it were CSS rules like no background, all black text, etc.
Well, if you run the code in Firefox and try to access the cssRules, it was actually a caught security error so they are not read. On Chrome, it does not throw any (obvious) error but returns "null". So these browsers "worked" because these CSS rules were never read.
Along comes IE and low and behold, it supports it. It reads the values from a remote CSS without failing or security warning. And because of that, the CSS from "bootstrap.min.css" to do all that stuff was being applied.
So, to fix this for all browsers I only needed to follow the advice here:
Accessing cross-domain style sheet with .cssRules
And then implement rules to skip the print media in certain files (like bootstrap.min.css)
Just so that this question is closed out, you can examine the question above for the update.
As it turns out, some recent version of Internet Explorer now supports document.styleSheets[] and more importantly supports extracting the cssStyles from those styleSheets no matter if they are hosted locally or remotely.
This change caused our code to start reading a remotely hosted CSS style that was not previously read and not noticed because it actually errors in Chrome and Firefox.
So getting access to remotely hosted CSS stylesheets as an object does not require anything with Internet Explorer now (it works without any changes) but does require one to something different in Chrome and Firefox (like setting crossorigin="anonymous" on the link tag).

jQuery: how to make css('line-height') work cross-browser

I'm supporting IE8 and up.
$(something).css('line-height');
In Chrome this returns 32px but in IE8 it returns normal
How do I get around this? Maybe a native javascript variation?
Seems like this is a webkit vs. IE issue. Not sure about FF, but there are a couple options for how to fix it. Overtly specifying a pixel value will work. But I don't like doing that because it's harder to keep things in proportion if you scale the text, etc with media queries. I was able to get it working by overtly specifying the line-height in ems (rather then letting it inherit). It's also relevant that it was previously set to rems which IE8 doesn't recognize.
function lineHeight(element){
var tmp=$("<div>test</div>");
element.append(tmp);
tmp.css({"padding":"0","margin":"0","border":"0"});
var height = tmp[0].clientHeight;
tmp.remove();
return height;
}
jsfiddle in FF and Chrome return 20px but on IE8 18px

How do I convert this css to javascript

I want to hide the cursor for my browser based game. I don't want to do this until the game starts.
I have this in CSS: * { cursor: none }. How would I do this in JavaScript? My target browser is Chrome and only Chrome.
You can do
document.body.style.cursor='none';
A note about your CSS : it's better to avoid as much as possible the * selector, especially when you can just set a style to the body.
<div id="nocursor"></div>
<script type="text/javascript">
document.getElementById('nocursor').style.cursor = 'none';
</script>
It still uses css, but I assume that this is what you were looking for.

javascript - changing a class' style

I've been working with jQuery for a while, but now I want to write something in pure javascript and it's prooving to be challenging..
One of my biggest problems at the moment is that I haven't found a way to set/change styling for a class. This is not a problem for elements with id, but I want to change the styling for a group of elements with the same class and not just for one element with an id..
In jQuery I would just write:
$('.someClass').css('color','red')
Is there really no simple equivalence to this in pure js?
Try the following
var all = document.getElementsByClassName('someClass');
for (var i = 0; i < all.length; i++) {
all[i].style.color = 'red';
}
Note: As Cheery pointed out getElementsByClassName won't work in IE. The linked question has a nice way to work around this limitation
javascript document.getElementsByClassName compatibility with IE
I find it easier to use CSS variables. You can set the class to use a variable and then change that value in Javascript, thus changing the CSS.
If you style the class like:
:root {
--some-color: red;
}
.someClass {
color: var(--some-color);
}
Then you can change the variable's value in Javascript with
document.documentElement.style.setProperty('--some-color', '(random color)');
(random color) can then be anything that would be considered a valid CSS color (eg. blue, black, #626262, rgb(12, 93, 44))
Updating the value in JS automatically updates the page as well.
And of course, this can be done with any property, not just color. Here is an example that changes the padding of a class:
CSS
:root {
--some-padding: 12px;
}
.someClass {
padding: var(--some-padding);
}
Javascript
// Set padding to 15px
document.documentElement.style.setProperty('--some-padding', '15px');
// Set padding to 5rem
document.documentElement.style.setProperty('--some-padding', '5rem');
// Set padding to 25%
document.documentElement.style.setProperty('--some-padding', '25%');
Useful example: toggle dark / light mode:
(How to use css properties to dynamically set css properties)
// set to light mode:
document.documentElement.style.setProperty('--bg-color', getComputedStyle(document.documentElement).getPropertyValue('--bg-color-light'));
// set to dark mode:
document.documentElement.style.setProperty('--bg-color', getComputedStyle(document.documentElement).getPropertyValue('--bg-color-dark'));
With the respective css:
:root {
--bg-color: black;
--bg-color-light: white;
--bg-color-dark: black;
body {
background-color: var(--bg-color);
}
Sources
How to declare and use CSS variables: https://www.w3schools.com/css/css3_variables.asp
How to update a CSS variable in JS: https://css-tricks.com/updating-a-css-variable-with-javascript/
var sheet = document.createElement('style')
sheet.innerHTML = ".someClass {color: red;}";
document.body.appendChild(sheet);
What you want to change is the style sheet, I guess? Thats possible in Javascript, see
Quirksmode: Change CSS
Totally Pwn CSS with Javascript (in Internet Archive)
Is the only way to change a style to do it per-element in JavaScript? (possible duplicate)
I'm afraid there is no library for that, I really would like to see one...
var all = document.getElementsByClassName('someClass');
for (var i = 0; i < all.length; i++) {
all[i].className += " red";
}
For better coding style add another class to the elements with the code above and then use CSS to change the color of all elements like this:
.red {
color:red;
}
You can use selector library, for example Sizzle: http://sizzlejs.com/ but if you want pure JS that I guess you are stuck with getting all the elements, and then programatically "handpicking" the ones that have classes you are interested in using RegEx like this for example:
This is an equivalent of your JQuery oneliner:
for( i in document.all) document.all[i].className && /\bpost-text\b/g.test(document.all[i].className) && (document.all[i].style.color = "red")
:)
If you don't need it in one line you can make it faster (and much more readable):
var myClassName = "someClass";
var regexp = RegExp("\\b"+myClassName+"\\b/g");
var elements = document.all;
for( i in elements){
var this_element = elements[i];
if(regexp.test(this_element.className){
this_element.style.color = "red";
}
}
If "for( i in object)" doesn't work for you, just use classic for loop "for(var i = 0; i < elements.length; i++)".
It could be 'beautified' a bit with the use of some slightly more advanced JS concepts (array function mappings, folding and such), which JS version are you coding agains? I guess it's not ECMA Script 5, right?
Also, check out this question/answer Get All Elements in an HTML document with a specific CSS Class

Issue in Chrome, removing CSS with jQuery stays in chrome

I'm currently working on a table application heavily coded in javascript using jQuery.
When you click on a td cell jQuery pushes 2px solid black to the border property. Then on blur I remove the style attribute with removeAttr to make it revert back to the stylesheet settings. Works fine in IE9, but when I test it in Chrome, the left border resizes, but stays black.
The only thing that seems to get rid of this is opening the console. When I blur with the console open the style tag removes so I don't understand why it's still rendering a black border on the left. Any ideas?
EDIT: I've made a video showing the problem I'm experiencing.
http://www.youtube.com/watch?v=JCmYNOO5u4I
Here's the code:
$("td.display").live('mouseenter', function () {
$(this).addClass('selected');
}).live('mouseleave', function () {
$(this).removeClass('selected');
});
The CSS is:
table TD.selected {
border: 2px solid;
border-color: Black;
}
Rather than using $.removeAttr, use $.css to restore the CSS. $.removeAttr isn't going to work properly due to how CSS persists, most likely.
What you should really do is add a class on focus, then remove that class on blur. That is, $.addClass and $.removeClass, documented at the respective links.
Instead of using JavaScript to achieve this trivial effect, use CSS. The :hover pseudo-selector is well-supported in all modern browsers.
td.display:hover {
border: 2px solid black;
}
I have adjusted your selectors, since <td> elements are always contained in a <table> element.
Demo: http://jsfiddle.net/JKM7e/
Update
This is one of the many table-css-related bugs in Chrome. A work-around is to initiate a re-render. To solve the issue, let Chrome render the page again. This fix should not activate in non-webkit browsers, so an additional variable is added.
I've also optimized your code, and replaced the deprecated live with on. The new revision can be found here.
// true if webkit, false otherwise
var isWebkit = !!$('<div style="-webkit-border-radius:1px">')[0].style.cssText.length;
$(document).on('blur', 'input.editCell', function () {
var $thisParent = $(this).parent(); // <-- Optimizing by caching
// Remove Highlight and bold around cell
$thisParent.removeClass('selected');
var colRow = $thisParent.attr('id').split('_');
$('th:containsExactly(' + colRow[0] + ')').removeAttr('style');
$('td.yAxis:containsExactly(' + colRow[1] + ')').removeAttr('style');
// Change class back to display
$thisParent.attr('class', 'display');
// Take the entered value and put it in the cell
$thisParent.html(this.value);
// if(isFunction(this.value) === 'SUM')
if (isWebkit) { // Fix for Webkit bug: render the table again
// Without jQuery, for efficiency
var style = document.getElementById('spreadsheetTable').style;
style.color = '#111'; //<--1. Change style
setTimeout(function(){style.color='';}, 4); //<--2. Fix
}
});
Two options:
- instead of removeAttr, reset the style with .css()
- use a class instead, and use toggleClass() in the focus and our events
The second option is definitely preferable.

Categories