Disable CSS Styles in Google Maps (3.14) Infowindow - javascript

In google maps version 3.14 there are some new css rules added for the custom infowindow. I use the infobox plugin and now many of my elements styles are overwritten.
For example:
.gm-style div,.gm-style span,.gm-style label,.gm-style a {
font-family: Roboto,Arial,sans-serif;
font-size:11px;
font-weight:400
}
.gm-style div,.gm-style span,.gm-style label {
text-decoration:none
}
.gm-style a,.gm-style label {
display:inline
}
.gm-style div {
display:block
}
.gm-style img {
border: 0;
padding: 0;
margin: 0
}
Is there any way to change that except that I have to overwrite this google styles via "!important"?
EDIT:
The font "Roboto" will be also loaded. If you care about performance, then that is not really great.
EDIT2:
Ok, !important isn't necessary. Overwriting the google styles is also possible with increasing the specificity of the CSS selectors. But this doesn't change that I have to overwrite all google styles. And the roboto font will loaded too.

From what I can see the new css rules are guaranteed to break styling for all markers, controls and info windows web wide, so maybe this will not remain in the 3.exp version long enough become part of an official release. In the meantime to protect you self against breaking changes like this. You should probably do two things:
1 Set a version on your link to the maps api. Something like
<script src="http://maps.googleapis.com/maps/api/js?v=3&libraries=geometry&sensor=true" type="text/javascript"></script>
will make sure that you are always accessing the current release version of the maps API. If you want to be more conservative you can specify the major and minor releases as well. If you specify a major and minor version then you can test updates to the maps API as part of your regular release schedule. If you are accessing the maps API as part of a wrapped mobile application then you cant control when your users update your app, so you will probably want to just set v=3 and then try to insulate your app from changes in the maps css (see 2. below)
2 Style your markers, controls, or info windows so that you better control the styling. For example, if you have a marker with html like
<div class="my-marker">...</div>
You can prevent the maps API from setting you font size by a css rule like
div.my-marker {
font-size: 18px;
...
}
Note, given maps API styles like
.gm-style div {
font-size: 11px;
...
}
you will have to specify the absolute sizes of you elements, relative measurements, like em's wont protect you against potential changes to, for example, font-size: 11px;

I had the same problem and Emads answer worked well for me after I addet a event listener.
google.maps.event.addListener(map, 'idle', function()
{
jQuery('.gm-style').removeClass('gm-style');
});
The problem is I still can't see any way to stop google loading the Roboto font.
EDIT: Well... there is a pretty easy way, to stop that.
Just use GET to load an older version of the google API like this:
<script src="http://maps.google.com/maps/api/js?v=3.13&sensor=false"></script>
In this API verion, google won't change the gm-style at all. So you don't need to override any classes or styles.

jQuery('.gm-style').removeClass('gm-style');
OR
find this in file /wp-content/themes/rentbuy/js/scripts.js
<div class="overlay-simple-marker"
and replace it with
<span class="overlay-simple-marker"

InfoBox also provides style element in options
var labelOptions = {
content: label,
boxStyle: {
//Insert style here
},
.
.
}

For those following this issue, please see the post by google in this thread:
https://groups.google.com/forum/#!topic/google-maps-js-api-v3/zBQ-IL5nuWs

This is a breaking change in version 3.14, because the elements are now styled by CSS rather than inline.
The default fonts used in labels and UI elements has changed. UI
elements are styled with CSS by the API, which means that custom CSS
that targets DOM elements on the map may require some adjustments if
you would like these to apply instead of the new default styling.
See changes in visual refresh for further details.
This is not a very good move by Google maps, because of the use of descendant selectors (on a div child!), which are not at all efficient.
To fix this you will need something quite specific like the following:
Given HTML
<div class="gm-style">
<div class="myClass-parent">
<div class="myClass">Lorem ipsum dolor</div>
</div>
</div>
Try something like
.myClass-parent > div.myClass
{
font-weight:600;
}
Simply styling div.myClass may not work.

I too have been struggling with the added gm-styles and Roboto font loading since 3.14 was introduced.
Found this issue reported as a "bug" on the google maps API codebase. Please star and comment on it at http://code.google.com/p/gmaps-api-issues/issues/detail?can=2&start=0&num=100&q=font&colspec=ID%20Type%20Status%20Introduced%20Fixed%20Summary%20Stars%20ApiType%20Internal&groupby=&sort=&id=6078

In response to dorr Baums solution, for those using prototype js you can use the following to remove this class.
google.maps.event.addListener(map, 'idle', function() {
$$('.gm-style').invoke('removeClassName', 'gm-style');
});

Since Google changed the behavior of older versions it wont work anymore to load v1.13.
The new styles and roboto-font will always load. My new solution is to save every stylesheet into a separate file and include the following script:
google.maps.event.addListener(map, 'idle', function()
{
$('style').remove();
});
This will remove every style-tag written by googles api and keeps your own style save but the roboto font will still be loaded. I don't see any way to stop that.

I fixed this on my map by doing the following. Hope it helps
Create my own div inside the infowindow and set your own css.
<div class='iw'>infowindow content</div>
Set the link to the css file BEFORE! the google api in the page head.
Hold Ctrl & click refresh on your browser to force full refresh to load any css changes. I was using Firefox.

Instead of removing the class through DOM manipulations and instead of using an older Google Maps version which is obviously mostly unwanted, simple deactivate the style globally by resetting the font attribute:
.gm-style { font: initial !important; }
or put your Google Map into a container and style .gm-style inside your container:
<div class="MapContainer">
[google map component here]
</div>
and in your CSS style definitions:
.MapContainer .gm-style { font: initial; }

Related

How to ensure CSS :hover is applied to dynamically added element

I have a script that adds full images dynamically over thumbnails when you hover over them. I've also given the full images a CSS :hover style to make them expand to a larger width (where normally they are constrained to the dimensions of the thumbnail). This works fine if the image loads quickly or is cached, but if the full image takes a long time to load and you don't move the mouse while it's loading, then once it does appear it will usually stay at the thumbnail width (the non-:hover style) until you move the mouse again. I get this behavior in all browsers that I've tried it in. I'm wondering if this is a bug, and if there's a way to fix or work around it.
It may be worth noting that I've also tried to do the same thing in Javascript with .on('mouseenter'), and encountered the same problem.
Due to the nature of the issue, it can be hard to reproduce, especially if you have a fast connection. I chose a largish photo from Wikipedia to demonstrate, but to make it work you might have to change it to something especially large or from a slow domain. Also note that you may have to clear the cache for successive retries.
If you still can't reproduce, you can add an artificial delay to the fullimage.load before the call to anchor.show().
HTML:
<img id="image" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Cairo_International_Stadium.jpg/220px-Cairo_International_Stadium.jpg" />
CSS:
.kiyuras-image {
position: absolute;
top: 8px;
left: 8px;
max-width: 220px;
}
.kiyuras-image:hover {
max-width: 400px;
}
JS:
$(function () {
var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';
var fullimage = $('<img/>')
.addClass('kiyuras-image')
.load(function () {
anchor.show();
});
var anchor = $('<a/>').hide().append(fullimage);
$('body').prepend(anchor);
$("#image").on('mouseenter', function () {
fullimage.attr('src',fullimageurl);
$(this).off('mouseenter');
});
});
JS Bin
Updated JS Bin with 1.5-second delay added (Hopefully makes issue clearer)
Again: Reproducing the issue involves clearing your cache of the large image, and then hovering over the original image to initial the loading of large image, then not moving your mouse while it's loading. Intended behavior is for the large image to properly take on the :hover pseudo-class when it eventually loads. Issue I see when it takes longer than ~0.75 secs to load is that it does not take on :hover until you jiggle the mouse a little.
Edit: See my comments on #LucaFagioli's answer for further details of my use case.
Edit, the sequel: I thought I already did this, but I just tried to reproduce the issue in Firefox and I couldn't. Perhaps this is a Chrome bug?
Most browsers update their hover states only when the cursor moves over an element by at least one pixel. When the cursor enters the thumbnail's img it gets hover applied and runs your mouseenter handler. If you keep your cursor still until the full-sized image loads, your old img (the thumbnail) will keep the hover state and the new one won't get it.
To get it working in these browsers, move the hover pseudo-class to a common parent element in the CSS; for example, enclose both imgs in a span.
If the selectors are correct, CSS will be applied to all elements, dynamic or otherwise. This includes all pseudo classes, and will change as attributes in the DOM change.
[Edit: while my explanation might be of interest, pozs' solution above is nicer, so I suggest using that if you can.]
The hover pseudo-class specification is quite relaxed concerning when it should be activated:
CSS does not define which elements may be in the above states,
or how the states are entered and left. Scripting may change
whether elements react to user events or not, and different
devices and UAs may have different ways of pointing to, or
activating elements.
In particular, it is not being activated when you update the visibility of the anchor element on load.
You can get around this fairly easily: copy the hover styles to a class, intercept the cursor moving over the element that it will eventually cover, and based on that add or remove your class from the element.
Demo: JS Bin (based on your delayed example).
Javascript:
$("#image")
.on('mouseenter', function () {
fullimage.attr('src',fullimageurl).toggleClass('mouseover', true);
$(this).off('mouseenter');
})
.mouseleave(function() {
fullimage.toggleClass('mouseover', false);
});
CSS:
.kiyuras-image:hover, .kiyuras-image.mouseover {
max-width: 400px;
}
TL;DR: You cannot rely on :hover applying to dynamically added elements underneath the cursor. However, there are workarounds available in both pure CSS and Javascript.
I'm upvoting both Jordan Gray and posz' answers, and I wish I could award them both the bounty. Jordan Gray addressed the issue re: the CSS specification in a somewhat conclusive way and offered (another) working fix that still allowed for :hover and other CSS effects like transitions, except on load. posz provided a solution that works even better and avoids Javascript for any of the hover events; I provide essentially the same solution here, but with a div instead of a span. I decided to award it to him, but I think Jordan's input was essential. I'm adding and accepting my own answer because I felt the need to elaborate more on all of this myself. (Edit: Changed, I accepted posz')
Jordan referenced the CSS2 spec; I will refer instead to CSS3. As far as I can tell, they don't differ on this point.
The pseudo-class in question is :hover, which refers to elements that the user has "designated with a pointing device." The exact definition of the behavior is deliberately left vague to allow for different kinds of interaction and media, which unfortunately means that the spec does not address questions like: "Should a new element that appears under the pointing device have this pseudo-class applied?" This is a hard question to answer. Which answer will align with user intent in a majority of cases? A dynamic change to a page the user is interacting with would normally be a result of ongoing user interaction or preparation for the same. Therefore, I would say yes, and most current browsers seem to agree. Normally, when you add an element under the cursor, :hover is immediately applied. You can see this here: The jsbin I originally posted. Note that if there's a delay in loading the larger image, you may have to refresh the page to get it to work, for reasons I'll go into.
Now, there's a similar case where the user activates the browser itself with the cursor held stationary over an element with a :hover rule; should it apply in that case? The mouse "hover" in this case was not a result of direct user interaction. But the pointing device is designating it, right? Besides, any movement of the mouse will certainly result in an unambiguous interaction. This is a harder question to answer, and browsers answer it in different ways. When you're activating them, Chrome and Firefox do not change :hover state until you move the mouse (Even if you activated them with a click!). Internet Explorer, on the other hand, updates :hover state as soon as it's activated. In fact, it updates it even when it's not active, as long as it's the first visible window under the mouse. You can see this yourself using the jsbin linked above.
Let's return to the first case, though, because that's where my current issue arises. In my case, the user hasn't moved the mouse for a significant length of time (over a second), and an element is added directly underneath the cursor. This could more easily be argued to be a case where user interaction is ambiguous, and where the pseudo-class should not be toggled. Personally, I think that it should still be applied. However, most browsers do not seem to agree with me. When you hover over the image for the first time and then do not move your mouse in this jsbin (Which is the one I posted in my question to demonstrate the issue, and, like the first one, has a straightforward :hover selector), the :hover class is not applied in current Chrome, Opera, and IE. (Safari also doesn't apply it, but interestingly, it does if you go on to press a key on the keyboard.) In Firefox, however, the :hover class is applied immediately. Since Chrome and Firefox were the only two I initially tested with, I thought this was a bug in Chrome. However, the spec is more or less completely silent on this point. Most implementations say nay; Firefox and I say aye.
Here are the relevant sections of the spec:
The :hover pseudo-class applies while the user designates an element with a pointing device, but does not necessarily activate it. For example, a visual user agent could apply this pseudo-class when the cursor (mouse pointer) hovers over a box generated by the element. User agents not that do not support interactive media do not have to support this pseudo-class. Some conforming user agents that support interactive media may not be able to support this pseudo-class (e.g., a pen device that does not detect hovering).
[...]
Selectors doesn't define if the parent of an element that is ‘:active’ or ‘:hover’ is also in that state.
[...]
Note: If the ‘:hover’ state applies to an element because its child is designated by a pointing device, then it's possible for ‘:hover’ to apply to an element that is not underneath the pointing device.
So! On to the workarounds! As several have zealously pointed out in this thread, Javascript and jQuery provide solutions for this as well, relying on the 'mouseover' and 'mouseenter' DOM events. I explored quite a few of those solutions myself, both before and after asking this question. However, these have their own issues, they have slightly different behavior, and they usually involve simply toggling a CSS class anyway. Besides, why use Javascript if it's not necessary?
I was interested in finding a solution that used :hover and nothing else, and this is it (jsbin). Instead of putting the :hover on the element being added, we instead put it on an existing element that contains that new element, and that takes up the same physical space; in this case, a div containing both the thumbnail and the new larger image (which, when not hovered, will be the same size as the div and thumbnail). This would seem to be fairly specific to my use case, but it could probably be accomplished in general using a positioned div with the same size as the new element.
Adding: After I finished composing this answer, pozs provided basically the same solution as above!
A compromise between this and one of the full-Javascript solutions is to have a one-time-use class that will effectively rely on Javascript/DOM hover events while adding the new element, and then remove all that and rely on :hover going forward. This is the solution Jordan Gray offered (Jsbin)
Both of these work in all the browsers I tried: Chrome, Firefox, Opera, Safari, and Internet Explorer.
From this part of your question: "This works fine if the image loads quickly or is cached, but if the full image takes a long time to load and you don't move the mouse while it's loading,"
Could it be worth while to "preload" all of the images first with JavaScript. This may allow all of the images to load successfully first, and it may be a little more user friendly for people with slower connections.
You could do something like that : http://jsfiddle.net/jR5Ba/5/
In summary, append a loading layout in front of your image, then append a div containing your large image with a .load() callback to remove your loading layer.
The fiddle above has not been simplified and cleaned up due to lack of time, but I can continue to work on it tomorrow if needed.
$imageContainer = $("#image-container");
$image = $('#image');
$imageContainer.on({
mouseenter: function (event) {
//Add a loading class
$imageContainer.addClass('loading');
$image.css('opacity',0.5);
//Insert div (for styling) containing large image
$(this).append('<div><img class="hidden large-image-container" id="'+this.id+'-large" src="'+fullimageurl+'" /></div>');
//Append large image load callback
$('#'+this.id+'-large').load(function() {
$imageContainer.removeClass('loading');
$image.css('opacity',1);
$(this).slideDown('slow');
//alert ("The image has loaded!");
});
},
mouseleave: function (event) {
//Remove loading class
$imageContainer.removeClass('loading');
//Remove div with large image
$('#'+this.id+'-large').remove();
$image.css('opacity',1);
}
});
EDIT
Here is a new version of the fiddle including the right size loading layer with an animation when the large picture is displayed : http://jsfiddle.net/jR5Ba/6/
Hope it will help
Don't let the IMG tag get added to the DOM until it has an image to download. That way the Load event won't fire until the image has been loaded. Here is the amended JS:
$(function () {
var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';
var fullimage = $('<img/>')
.addClass('kiyuras-image')
.load(function () {
anchor.show(); // Only happens after IMG src has loaded
});
var anchor = $('<a/>').hide();
$('body').prepend(anchor);
$("#image").on('mouseenter', function () {
fullimage.attr('src',fullimageurl); // IMG has source
$(this).off('mouseenter');
anchor.append(fullimage); // Append IMG to DOM now.
});
});
I did that and it worked on Chrome (version 22.0.1229.94 m):
I changed the css as that:
.kiyuras-image{
position: absolute;
top: 8px;
left: 8px;
max-width: 400px;
}
.not-hovered{
max-width: 220px;
}
and the script this way:
$(function(){
var fullimageurl = 'http://upload.wikimedia.org/wikipedia/commons/3/32/Cairo_International_Stadium.jpg';
var fullimage = $('<img/>')
.addClass('kiyuras-image')
.load(function () {
anchor.show();
});
var anchor = $('<a/>').hide().append(fullimage);
$('body').prepend(anchor);
$('.kiyuras-image').on('mouseout',function(){
$(this).addClass('not-hovered');
});
$('.kiyuras-image').on('mouseover',function(){
$(this).removeClass('not-hovered');
});
$("#image").one('mouseover', function(){
fullimage.attr('src',fullimageurl);
});
});
Basically I think it's a Chrome bug in detecting/rendering the 'hover' status; in fact when I tried to simply change the css as:
.kiyuras-image{
position: absolute;
top: 8px;
left: 8px;
max-width: 400px;
}
.kiyuras-image:not(:hover) {
position: absolute;
top: 8px;
left: 8px;
max-width: 220px;
}
it still didn't worked.
PS: sorry for my english.
I'm not 100% sure why the :hover declaration is only triggered on slight mouse move. A possible reason could be that technically you may not really hover the element. Basically you're shoving the element under the cursor while it is loading (until the large image is completely loaded the A element has display: none and can therefore impossible be in the :hover state). At the same time, that doesn't explain the difference with smaller images though...
So, a workaround is to just use JavaScript and leave the :hover statement out of the equation. Just show the user the two different IMG elements depending on the hover state (toggles in JavaScript). As an extra advantage, the image doesn't have to be scaled up and down dynamically by the browser (visual glitch in Chrome).
See http://jsbin.com/ifitep/34/
UPDATE: By using JavaScript to add an .active class on the large image, it's entirely possible to keep using native CSS animations. See http://jsbin.com/ifitep/48

JavaScript Cursor Change (and change back again)

I have this page that does some funky database stuff that takes a couple seconds to process, and in the meantime I'd like to set a "wait" cursor so the user doesn't flip out and keep clicking the button. I've looked at the
document.body.style.cursor = "wait"
thing, the problem with this is that it only works when the mouse is over the body of the page (i.e. still shows normal pointer if it's over a button). How can I set it so that no matter where the mouse is on the page, it shows a wait icon?
A second part to this question is, once it's done it's thing, how do I set it back? If I set it back to "default", this seems to override any "hover" cursor changes I had set in my CSS (so it no longer becomes a hand when over a specified object, etc.).
EDIT: the first answer works nicely, except in IE it doesn't refresh the cursor (so you notice the change of cursor type) until you actually move the cursor. Any fixes?
What I suggest is two things:
a) Better write a CSS like
body.waiting * { cursor: wait; }
b) Use the JS to handle the body class
/* when you need to wait */
document.body.className = 'waiting';
/* to remove the wait state */
document.body.className = ''; // could be empty or whatever you want
You might want to add the class instead of replace the whole class attribute, what I suggest is to use something like jQuery for that.
EDIT 2019: don't use jQuery for just this, use classList
The styling should be handled via CSS, as stated by W3C.com:
CSS is the language for describing the presentation of Web pages, including colors, layout, and fonts. ... The separation of HTML from CSS makes it easier to maintain sites, share style sheets across pages, and tailor pages to different environments. This is referred to as the separation of structure (or: content) from presentation.
As suggested by Tom Rogerro, add a line to your CSS file:
body.waiting * { cursor: wait; }
However, your script should not overwrite the entire list of class names. Tom suggested setting the class names via jQuery, but jQuery is unnecessary in this case. Simple Javascript can do this.
To add a class name 'waiting' to the document body:
document.body.classList.add('waiting');
To remove a class name 'waiting' from the document body:
document.body.classList.remove('waiting');
For your first problem, try using cursor: wait !important;.
For your second problem, the default cursor for elements is cursor: auto;, not cursor: default; or cursor: inherit;.
If you are happy using JQuery then a quick way to solve this would be to use:
$('*').css('cursor','wait')
I don't know how elegant this is but it has been working for me,
Not an answer to the question, but a way of achieving what is wanted.
Make a div (see class below) visible when you are loading.
ensures no element is accessible and dimmed display indicates this.
you can add an animated gif to indicate something is going on instead of the cursor.
.loading{
position:fixed;
height:100%;
width:100%;
left:0;
top:0;
cursor:wait;
background:#000;
opacity:.5;
z-index:999}
Any elements that don't inherit the cursor by default (such as buttons) will need to set the cursor to inherit:
someButton.style.cursor = 'inherit';
To go back to the default for an element (and not break things like :hover with a forced cursor), set it to an empty string:
document.body.style.cursor = '';
I tried everything but finally this jquery worked, especially if you want wait cursor over all elements including buttons and links.
define at the top of angular .ts file
declare var $: any;
and then where ever you want wait cursor:
$('*').css('cursor','wait');
and remove wait:
$('*').css('cursor','auto');
To fully replace the CSS toggling behaviour, we can simply use this inline:
<img
src=https://cdn.sstatic.net/Img/unified/sprites.svg
onmouseover="this.style.cursor = 'crosshair'"
>

Detecting when styles disabled

What's the best way to detect, with JS, if the user has disabled your stylesheets? Is there a reliable way even?
How about asking them?
<div style="display:none">This site relies on CSS, please go to our CSS free version of this site</div>
Something easy would be to check the body background color for instance.
However, how likely is it someone disables CSS and not Javascript? (dunno what you use it for obviously)
I would have a small, empty div sit on the screen. When the page loads, use JS to check the 'display' property of that div. If it's 'none', then your css has successfully been loaded. If not, they may have to turned off / changed your styles.
If you're in control of the stylesheet you can have a "calibration" style.
Have a classname that applies some CSS property to an element. A good cross-browser safe property can be background-color.
When loading your JS try to dinamically create an element and apply the classname to it. Check if the properties match (the one on the element with the one you're expecting).
BoltClock's comment comes close. You can use window.getComputedStyles(calibrationElement, null) but that will fail in older IE browser versions.
See documentation for getComputedStyles
Feel free to remove the "calibration" node after you've checked it.
Assuming your primary external or inline stylesheet is loaded before the script, you can use this:
if (document.styleSheets.length){} // stylesheets are disabled
https://developer.mozilla.org/en-US/docs/DOM/document.styleSheets
It's IE5+ compatible too as per: http://www.jr.pl/www.quirksmode.org/dom/w3c_css.html
The caveat is that, if styles are turned off after the window has loaded (which only causes a browser repaint), the document.styleSheets object won't change on the fly. Additionally, as noted in the comments below, this will not work for Firefox when using the View -> Page Style -> No Style feature, for which styles are still loaded, just not applied to the view.
To detect the initial state across browsers, or changes on window.onresize, it can be done with a style reset on the body, with the following code placed after <body> or in a DOMContentLoaded event:
if (document.body.clientWidth !== document.documentElement.clientWidth) {
// Styles are disabled or not applied
}
This works if you use body { margin: 0; } in your stylesheets (with no particular custom width), because it makes the body element the same width as documentElement (a.k.a. the <hmtl> element) while styles are active.
When styles are turned off or disabled, the body.clientWidth will revert to the browser's default body width, which always has a margin (8px by default in CSS 2.1 major browsers ) and therefore different from documentElement.clientWidth.
Should your site design use a specific margin other than 8px for the body, here is an alternative option:
if (document.body.clientWidth === document.documentElement.clientWidth-16) {
// user styles are disabled or not applied (IE8+ default browser style applies)
}
At least in Safari, part of the difficulty is that with CSS off the elements still report CSS attributes. But if you test on the actual rendering of a property then you can tell. Width is probably the simplest (and most common) property you can test on.
Below is a sample script (it uses jQuery, but could easily be un-jQueryfied) that will test for CSS. We just load an empty div on the page, give it a width of 3px using CSS, and then test that div's width. If the width is not 3 then CSS is disabled. Obviously you have to make sure that this doesn't colide with any other styles you might have that could cause the width to be other than 3. But it gives the general idea.
<html>
<head>
<title>Test</title>
<style type="text/css">
#testCSS {width: 3px;}
</style>
</head>
<body>
<div id="testCSS"></div>
<div id="message"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
if (jQuery("#testCSS").width() != 3) jQuery("#message").html("CSS Disabled");
});
</script>
</body>
</html>
Edit: sorry about the messy code example. It doesn't seem to like my code tags. Here's a JSfiddle with the code. Obviously you won't be able to disable CSS and test there, but you can pull the code from it: http://jsfiddle.net/3FvdL/1/

Printable Version of Google Visualizations DataTable

I have a custom routing application that takes information for a route from google maps. It then creates a Google Visualizations DataTable to hold all the steps in the route.
My current problem is that in order to reduce overflow for very large routes, I have enabled paging in the options of the DataTable. This leads to a not so printer friendly version because only the portion of the data that is shown in the table will be printed. The other portions of the table are loaded dynamically by the API when you click prev and next.
Is there a not so hard way to get the DataTable to be printer friendly when it comes time without sacrificing the ability to have paging enabled?
This is the way that I ended up solving this problem. I will not accept my own answer just in case someone has something much more elegant.
Originally I had:
var visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, {
sort: "disable",
allowHtml: true,
showRowNumber: true,
page: "enable",
pageSize: 9
});
I added another one that went to a div that I would hide with css.
//Create a second Visualization that Will be hidden.
var visualization = new google.visualization.Table(document.getElementById('printerFriendly'));
visualization.draw(data, {
sort: "disable",
allowHtml: true,
showRowNumber: true,
page: "disable"
});
Then I added the following rules to one of my css files.
#media print
{
#table{ display:none; }
}
#media screen
{
#printerFriendly{ display:none;}
}
This hides one table during normal use and hides the other during printing. I was hoping for something a little cleaner than this but this solution was very easy to implement.
There's a few ways you could do it.
If the changes you need in order to make the page "printer friendly" can be done purely by changing the CSS styling, then all you need to do is add another style sheet for print media:
<link rel="stylesheet" href="print.css" type="text/css" media="print" />
That is a pretty easy and transparent way to do it: the print media style sheet that will be used for printing, while your original style sheet will be used for web viewing.
So you could change the way things are displayed, or even toggle visibility whether it's being viewed on the web or printed...that should get you where you need to be.
To be honest I'm not too familiar with what you're doing, but it sounds like the user has to make a new request for each page...in that case just CSS styling will not help you.
You'll have to either make the information available all on one page ( just parts invisible), or set up a function in the app, or an option, et cetera that spits out a printer-friendly version.
#media print
{
#table > div > div { overflow: visible !important; }
}
This will solve your problem.
Explain:
2'nd div below #id used to create table have overflow: auto. This lead to fit info in this block. Changing it to overflow: visible will lead to show it content.
Check how it works on developer.mozilla.org/en-US/docs/Web/CSS/overflow

Quickly repaint array of unicode symbols in JavaScript

I want to change background/foreground color of many symbols with the same CSS class. Right now I'm doing it with jQuery — like $('back_COLORED').css('background-color', '#00FF00'), but this approach is slow when there are many elements with such class (>900).
Seems it's because jQuery don't change CSS rules itself, but finds all elements one-by-one and applies inline styles to them. At least, this is what I see in inspector. So, the question is:
How can I change the CSS rules itself?
Will it be much faster?
Can I make it cross-browser (IE6 doesn't count)?
UPD: I'm trying to make some kind of color scheme editor. The source is at http://github.com/kurokikaze/cinnabar/. Don't mind PHP things, editor is fully client-side (with just some libraries fetched from the net).
UPD2: Tried canvas approach, still slow. Canvas branch is at http://github.com/kurokikaze/cinnabar/tree/canvas.
The most cross-browser friendly way to override a class definition is to write a new rule and add it to the end of the last stylesheet in the document. You can edit an existing style rule, but even some recent browsers can make it difficult.
function newRule(selector, csstext){
var SS= document.styleSheets, S= SS[SS.length-1];
// this example assumes at least one style or link element
if(S.rules){
S.addRule(selector,csstext,S.rules.length);
}
else if(S.cssRules){
S.insertRule(selector+'{'+csstext+'}'),S.cssRules.length)
}
}
newRule('.someclass','background-color:#0f0');
You can add as many 'property:value;' bits in the csstext as you need.
Remember to prefix a '.' to a class name or a '#' to an id,
and the css must be written as a style rule (with-hyphens, not camelCase).
Of course, it will not override inline styles, and it is overkill for small, local changes.
It also may make the redrawing of the page more obvious than changing one element at a time,
but it may be just what you need here.
There are different ways depending on which browser you are dealing with. This is documented on Quirks Mode.
Some libraries provide an abstraction layer, such as YUI's StyleSheet utility.
There should be a significant performance boost since you aren't using JS/DOM to cycle through all the elements.
Another approach would be to predefine your styles:
body.foo .myElements { … }
And then edit document.body.className
If you can select the parent div by id, maybe you could select by tag inside it? Or are there elements of the same kind that should change color and that should not, inside the parent?
It would be nice to have an idea of what you're building here. 900+ objects seems to be a lot... maybe a completely different approach could be used? Canvas, SVG?
Try hiding the items you want to change before changing them, make the change and then display them again. This is common practice to speed up things as you minimize the repaint events in the viewport. In this case when you only setting one css property it might not be that of a benefit but it´s worth a try I say.
Try:
$('back_COLORED').hide();
$('back_COLORED').css('background-color', '#00FF00');
$('back_COLORED').show();
or
$('back_COLORED').hide().css('background-color', '#00FF00').show();
I would stick in trying changing a CSS property, instead of parsing the DOM.It is about the CSS engine vs. DOM+JS here, and the winner is clear.
It happens I just uploaded a tiny library that replaces CSS by Javascript: jstyle
This is may be an overkill, but you will find in the source code of jstyle.js all the code you need to update cross browser the CSS properties of your page.
I think a better solution would be to write a more specific CSS rule (that would override the normal colour) that can be activated by simply changing one element's css class.
So for example if you had the following structural markup:
<div id="container">
<span class="colored">Test 1</span>
<span class="colored">Test 2</span>
</div>
And CSS:-
.colored { background-color: red; }
.newcolor .colored { background-color: blue; }
Then in your jquery you add the .newcolor class to the container div:-
$('#container').addClass('.newcolor');
When you do that the second CSS rule will override the first because it is more specific.
Inject the css code into a style tag:
var style = $('style').attr({
type:"text/css",
media:"screen",
id:'changeStyle'
}).html('.tempClass { color:red } .tempClass p { background:blue }').prependTo('body');
and on every changes on your color with color picker you only rewrite the html inside of #changeStyle tag.
Have no idea if it works (didn't tested) but you should give a try.
This is jQuery pluggin for work with css rules: http://flesler.blogspot.com/2007/11/jqueryrule.html
not sure about its performance, but worth a try.

Categories

Resources