I want to spruce up some areas of my website with a few jQuery animations here and there, and I'm looking to replace my AJAX code entirely since my existing code is having some cross-browser compatibility issues. However, since jQuery is a JavaScript library, I'm worried about my pages not functioning correctly when JavaScript is turned off or doesn't exist in a user's browser.
I'll give an example: Currently, I'm using a pure CSS tooltip to give my users (players, the site is a browser game) information on other users. For example, if the other players in the game satisfy one or more conditions, a target icon is displayed next to their name, and upon hovering over that target icon information regarding the reasons behind the target is displayed. This is useful information, as it helps my players to know who they should plan to attack next in the game.
Currently, I do such tooltips using CSS. I have a parent div that holds the image of the target icon of class "info". I then have a div inside of that with class "tooltip" that, on the hover state of the "info" class that it is contained in, is shown, but on the normal state is hidden. I thought it was rather clever when I read about it, and since no JavaScript is used it works on any CSS compliant browser.
I would like to use jQuery to achieve the same effect, mostly because it would look much cleaner, but also because I believe quick and subtle animations can make such things "randomly appearing" make a lot more sense to the user, especially on the first encounter. I'm just wondering if the two will conflict. This is only one example of this, there are numerous other examples where the inability to use JavaScript would hinder the site.
So what I'm asking I guess is, how does one make a jQuery site degrade gracefully on browsers that do not support JavaScript, but otherwise do support most CSS? My goal is for the site to function on a basic level for all users, regardless of choice in browser. The animation is a good example, but I'm also worried about the more dynamic bits, like the auto-updating with AJAX, etc. Are there any good resources on how to achieve this, or do you have any advice about the best way such degradability could be achieved?
Thanks
PS: Totally irrelevant, but Firefox seems to think that "degradability" isn't a word, but "biodegradability" (with the "bio" prefix) is. Weird...
If you consider the "Cascading Order" of css, could you not just add a css style at the very end of all your previous css definition in order to cancel any css effect you currently have for tooltip effect ?
That css rule would only be declared if Javascript is activated and JQuery detected.
That way, you are sure your css tooltip effect is not in conflict with your JQuery effect.
Something like:
a.info:hover span{ display:none}
with the use of "js_enabled" class to make this css rule conditional.
You also can do it by adding css rule on the fly:
function createCSSRule(rule,attributes)
{
//Create the CSS rule
var newRule = "\n"+rule+"{\n";
for (var attribute in attributes)
{
newRule += "\t" + attribute + ": " + attributes[attribute] + ";\n";
}
newRule += "}\n";
//Inject it in the style element or create a new one if it doesn't exist
styleTag = $E('style[type="text/css"]') || new Element("style").setProperty('type','text/css').injectInside(document.head);
if(window.ie)
{
styleTag.styleSheet.cssText += newRule;
}
else
{
styleTag.appendText(newRule);
}
}
The most simple solution for Separation of CSS and Javascrip is to remove your css class
function jscss(a,o,c1,c2)
{
switch (a){
case 'swap':
o.className=!jscss('check',o,c1)?o.className.replace(c2,c1): <-
o.className.replace(c1,c2);
break;
case 'add':
if(!jscss('check',o,c1)){o.className+=o.className?' '+c1:c1;}
break;
case 'remove':
var rep=o.className.match(' '+c1)?' '+c1:c1;
o.className=o.className.replace(rep,'');
break;
case 'check':
return new RegExp('\\b'+c1+'\\b').test(o.className)
break;
}
}
This example function takes four parameters:
a
defines the action you want the function to perform.
o
the object in question.
c1
the name of the first class
c2
the name of the second class
Possible actions are:
swap
replaces class c1 with class c2 in object o.
add
adds class c1 to the object o.
remove
removes class c1 from the object o.
check
test if class c1 is already applied to object o and returns true or false.
If something can be done completely in CSS I say keep it that way. If lack of javascript in the browser is a concern, then most of the time I show the entire page unaffected.
Say for instance I'm going to use jQuery to toggle an element when a checkbox is clicked. On page load I look at the checkbox and update the element accordingly. If javascript is not enabled the element will still appear and the site will still be usable. Just not as nice.
Man, you have a browser-based game, right? You have less than 1% users with JS disabled! And that 1% is the apocalyptic number because I can BET that you have less than that ;)
Anyhow, if you are really concerned about this, just do the site without any JavaScript. And make it functional 100%. After your site works completely without any JS flavour, just start to improve with jQuery (or any other library; jQuery is the best :P ). But with careful: do not change ANY of you HTML. It's easier than it looks ;)
And yes, if you have things that work without JS (like those tooltips) keep it!
Related
I know it's possible to change css attributes on elements on the current page:
$('.changeMyStyle').css("color", "#FF0000");
But this won't affect new elements added after the change is made.
I know it's possible to remove, add, or swap out css stylesheets to re-style a page after it's been loaded:
$('link.swappableStylesheet').attr('href', 'path/to/new/style.css');
But this is a poor solution for changing one or two attributes, especially to programmatically-determined values (such as changing color from a colorpicker).
I could probably grab a stylesheet's raw data, search it, and modify it:
var sheet= document.styleSheets[0];
var rules= 'cssRules' in sheet? sheet.cssRules : sheet.rules; // IE compatibility
rules[0].style.padding= '0.32em 2em';
// assumes the first entry in the first stylesheet is the one you want to modify.
// if it's not, you have to search to find the exact selector you're looking for
// and pray it's not in a slightly different order
But that's also a poor solution and requires IE-compatibility hacks.
This linked answer also suggests appending another <style> element and adding css there. That could work for narrow cases, but it's still not ideal (and the answer is 5 years old, so new tools may be available now).
Is there a way to alter the page's css at a selector & attribute level instead of stylesheet level or DOM element level? jQuery and vanilla javascript solutions both welcome, as well as libraries designed to do this specifically. Ideally I'd like something that's as easy and versatile as
$(document).stylesheet('.arbitraryCssSelector.Here').put('color', '#FF0000');
...where .stylesheet('.Here.arbitraryCssSelector') would modify the exact same style entry.
Even Chrome's dev tools just modifies the stylesheet it's using when you make modifications or add new rules. There's not currently a way around it, but you can keep a dedicated stylesheet at the bottom of the page that you update with the newest rules. If it's empty or contains invalid rules it will just fall back to the current stylesheet. If any library exists out there this is how it would do it, and it's very little code.
I think the key to keeping it uncluttered is to simply keep overwriting one stylesheet instead of adding new stylesheets to the DOM.
document.getElementById("dynamic-color").addEventListener("input", function () {
document.getElementById("dynamic-styles").innerHTML = "label { color: " + this.value + " }";
});
label {
color: blue;
}
<label for="#dynamic-color">Change the label's color!</label>
<input id="dynamic-color" />
<style id="dynamic-styles"></style>
I am still having trouble understanding regex. I am also not even sure if you can target a whole page...but without knowledge of how to format regex, its getting play with it.
I have a trademarked name that appears throughout my page. I'd like to use JS to add a (r) to the end of it every time it appears.
Can jquery/js accomplish this?
$("body").each(function() {
this.innerHTML = this.innerHTML.replace(
'breathe right',
'breathe right(r)');
});
Thanks!
This is a good use case for the CSS :after pseudo-element:
CSS
.product-name:after {
content: " \00AE"; /* add restricted symbol after every element with the product-name class */
}
HTML
<span class="product-name">My Product</span>
Working Demo
The easiest way is to wrap your product name in a span and tag it with a class. I'm not sure if that's less work that just adding the symbol to your markup to begin with, though.
The benefit of this approach is it would allow you to easily apply other styles to your product name, like bolding the text or changing the font color.
You can read more about the :after pseudo-element here.
Yes, but it won't be efficient if you tell jQuery to search the entire document. To make it efficient, you'll need to have jQuery get a specific location to search if you want any efficiency in it.
You don't need jQuery :
document.body.innerHTML = document.body.innerHTML.replace(/breathe right/g, 'breathe right(r)')
I'm aware that this is an 'old question' by now, but I have searched and not yet found an explanation that makes sense to me.
Note: I know just enough html, css, and wordpress to have developed my website: (http://www.gregorygainsborough.com), and am just beginning to learn javascript.
If you visit my site, you'll see the problem - much of the content is revealed when various boxes are hovered on. On tablet, since there is no :hover, I'd like to make it do this:
First tap -> reveal the style that would have been applied on :hover.
Second tap -> follow the link like a mouse click would.
ALSO helpful would be to 'close' the :hover style when a) another element is tapped, or b) ten seconds elapse.
Thanks for any help you can offer. I'm aware that some of this will be above my js knowledge at present, and I'm looking for explanations or references which can help me target my learning and close that gap.
I would in PHP make a IF statement to check if Tablet is used.
You can use this Library for this. Then I would in the IF statement echo this javascript out:
var clicked = 0;
$('a.iftablet').on('click',function(){
var old_clicked = clicked;
var number = $(this).attr('tablet_id'); // Get the tablet ID for this item
var clicked = number;
if (old_clicked != number){ return false;} // This might do the trick, so that on first click, it doesn't link.
});
NOTE: I use jQuery, so you need the jQuery library.
NOTE 2: Add class="iftablet" to the links around the boxes, and add as well tablet_id="X" (Where X is a unique number for that box, so that when click on one box, the others will disapear).
Maybe there is some errors on the code, put then let me know. Good luck
I have a site that is in English and Spanish, and in each page of the site there is a link that leads to the Spanish version of that specific page, so if the user were on the "home.php" page, it would look like this:
<div id="language">
<ul class="language">
<li class="english"></li>
<li class="divider"></li>
<li class="spanish"></li>
</ul>
</div>
What I would like to do is leave the href and the class in the <a> tags in the HTML blank and assign a class and an href URL to the <a> depending on the page the user is on, that way I could, for example, just add that language div to an external file, and use an <include> to attach it to each page. To accomplish this I'm using the following code:
$('ul.menubar a').each(function(){
if(location.href.match('home.php')){
$('ul.language li.english a').addClass('active');
$('ul.language li.english a').append(function() {
$(this).attr('onclick', 'return false;');
});
$('ul.language li.spanish a').addClass('notactive');
$('ul.language a[href!="home.php"]').append(function() {
$(this).attr('href', 'inicio.php');
});
}
}
The problem is that the English version of the site has 4 links in the navigation bar (home.php, services.php, aboutus.php, contact.php), and the Spanish version likewise (with the corresponding translation of the URL names). I think that having to repeat that code 8 times (1 for each link, 4 links in each language) would be excessive and would actually add more code than simply adding the class and href url in the HTML. The point of using JS would be to simplify things.
So I basically would like to know if anyone can think of a better way to do this, that wouldn't require that much code. I'm trying to avoid having to, in the event that I'd need to change something, have to edit each different page. Also, I would like to know if this is the best way to achieve want I want to do using JavaScript.
HTML is best suited for managing content. CSS is best suited for presenting that content, and JavaScript is best suited for determining how that content behaves. Instead of trying to inject links and control the HTML from JavaScript; instead, leave the content where it belongs, inside the HTML, and use JavaScript to define one or two event-handlers to take action based on the class values on the hyperlinks themselves.
You already have a class on your English hyperlinks, and a separate class on your Spanish hyperlinks, so you can use this to your advantage.
Writing the Click Handlers:
Since toggling your "Language switch" most likely causes a boolean value to be set, you can use two click handlers to target all of your English links and all of your Spanish links, and then control the behavior based on the value of that switch at the time the links are clicked.
// handler for all English links
$('li.english a').click(function(event) {
event.preventDefault();
if(/* Switch is english */) {
window.location = $(this).attr("href");
}
});
// handler for all Spanish links
$('li.spanish a').click(function() {
event.preventDefault();
if(/* Switch is SPANISH */) {
window.location = $(this).attr("href");
}
});
Note that when a link is clicked, we first check the switch. Depending on it's value, we either redirect to that hyperlink, or simply prevent the default behavior -- going to a new page -- from completing.
Handling the Presentation:
Now, your other problem is going to be that, assuming your Spanish site and your English site are one in the same, you'll now see 8 hyperlinks in total. Again, this is where your switch can come in handy.
// single handedly hide or display the relevant content, based on the switch
function switchToEnglish() {
$('.english').show();
$('.spanish').hide();
}
function switchToSpanish() {
$('.spanish').show();
$('.english').hide();
}
Now, I don't know what else is contained in your switch function, but the general idea here is that we don't need to modify the content. We just need to show and hide the content. You'd need to integrate this concept into your existing switch function, if you don't already have something like this in place.
There are several advantages in this approach:
Your Web designers will still see href's in the HTML and can read and understand the HTML without needing your help or needing to go and look at JavaScript code. Not only will they see familiar patterns that they're used to seeing, but you'll likely have a better working relationship with them.
Search engines spidering your site will be able to read the links and follow them.
Browsers without JavaScript will be able to process the links. Some people seem to care about this. I don't. But it's worth mentioning anyway.
In summary, you're right about it being easier to manage in HTML. By using this technique, you can eliminate the repetition in the code that you're rightfully concerned about, and also move the content back to the HTML, as your gut is telling you is the correct thing to do. Not only will your code be more readable, but you'll get better SEO results as well.
In firefox, I have the following fragment in my .css file
tree (negative){ font-size: 120%; color: green;}
Using javascript, how do I change the rule, to set the color to red?
NOTE:
I do not want to change the element.
I want to change the rule.
Please do not answer with something like
...
element.style.color = 'red';
What you're looking for is the document.styleSheets property, through which you can access your css rules and manipulate them. Most browsers have this property, however the interface is slightly different for IE.
For example, try pasting the following in FF for this page and pressing enter:
javascript:alert(document.styleSheets[0].cssRules[1].cssText)
For me that yields the string "body { line-height: 1; }". There are methods/properties that allow you to manipulate the rules.
Here's a library that abstracts this interface for you (cross-browser): http://code.google.com/p/sheetup/
function changeCSSRule (stylesheetID, selectorName, replacementRules) {
var i, theStylesheet = document.getElementById(stylesheetID).sheet,
thecss = (theStylesheet.cssRules) ? theStylesheet.cssRules : theStylesheet.rules;
for(i=0; i < thecss.length; i++){
if(thecss[i].selectorText == selectorName) {
thecss[i].style.cssText = replacementRules;
}
}
};
You can change CSS rules in style sheets through the CSS Object Model (currently known as DOM Level 2 Style). However, if you literally have "tree (negative)" in your style sheet that rule will be dropped and not appear in the Object Model at all.
As there is no HTML element tree I am going to assume that tree is the id or class of another element.
You would first retrieve the DOM element by id:
var tree = document.getElementById("tree");
Now tree represents your DOM element and you can manipulate it any way you like:
tree.style.color = "red";
Here is a great reference for mapping css properties to their javascript equivalent.
I'm not sure you can do actual class/selector overrides. You would need to target each element that used the .tree class and set the CSS. The quickest and easiest way would be through jQuery (or another similar framework):
$('.tree').each(function() { this.style.color = "red"; });
You could even use the built-in CSS functions:
$('.tree').css('color', 'red');
(I did it the first way to show you how standard JS would do it. The $(...) part is jQuery for selecting all elements with the .tree class. If you're not using jQuery, you'd need alternative code.)
If tree is an ID, not a class (there should only be one on the page) so using getElementById should be fine. Your code should look like the other answer.
for( var i in document.getElementsByTagName("tree") ){
document.getElementsByTagName("tree")[i].style.color = "red";
}
As I said in another answer's comment, I've never seen this done how you want. I've only ever targeted elements the same way as the CSS renderer would and changed each element style.
I did see this though: jQuery.Rule
It sounds like it does what you want but the demo causes my browser to flip out a bit. I'd invite you to look at the source to see it really does do what you want, and if you want to use it without jQ, use it as a starting point.
Edit: yes this should work. It works by appending another <style> tag to the page and writing out your overrides within. It's fairly simple to follow if you wanted to port it to plain JS.
For debugging, you can use Firebug to change the CSS rules on-the-fly.
If you want to change the rendered css rules from one page request to the next then some sort of server-side scripting will be required. Otherwise the original style sheet would simply reload at the next page request.
If you want to use an event on the first page to force the server-side action then you can use AJAX to actually change the CSS rule for the user.
"I want to change the rule so that
when I navigate to the next page, I
don't have to make all the changes
again."
It sounds like what you might want then is a remote request ("ajax") back to the server with the request you want to make, and generate a dynamic stylesheet which is sent back to the client?
How/why is this Firefox specific?
I want to change the rule so that when I navigate to the next page, I don't have to make all the changes again.
There are two approaches I can think of here. Namely client side and/or server side.
Client side:
Store the theme setting into cookies and load them up next time by javascript.
Server side:
If your site have an login system, you may also store the user preference into the database and generate the webpages with this inforamtion in mind next time on.
Utimately, you are still writing things like element.style.color =. But, they should get what you want.