2

I get two error messages when trying to load the page with the code below. The error messages are:

  1. "Uncaught TypeError: Cannot set property 'href' of null at HTMLAnchorElement.col.(anonymous function).onclick (http://www.jimbrink.org/:363:17)"
  2. "Uncaught ReferenceError: bindEvents is not defined at (index):375"

I'm trying to create a link that, when clicked, would switch to another css file (with different fonts).

(BONUS QUESTION: Is there a way for the link to toggle between the two stylesheets?)

I've taken this from another StackOverflow question, but I can't seem to get the code to work my situation.

Here's the link:

                <li><a href="#" class="changeStyle" data-style="css/style.comicsans.css" data-type="text/css" data-rel="stylesheet">JB's Fav Font</a></li>

Here's the js function from the bottom of the page:

<!-- cssswitcher js -->
<script type='text/javascript'>
window.onload = function bindEvents(){

  var css=document.getElementById('style');
  var col=document.querySelectorAll('a.changeStyle');

  /* iterate through collection and assign listener */
  for( var n in col )if( col[n].nodeType==1 ) col[n].onclick=function(e){
    e.preventDefault();/* prevent jumping to top of page etc */
    var el=typeof(e.target)!='undefined' ? e.target : e.srcElement;

    /* assign style attributes */
    css.href=el.dataset.style;
    css.rel=el.dataset.rel;
    css.type=el.dataset.type;

    /* store reference to style selected in localstorage */
    localStorage.setItem( 'style', el.dataset.style );
    };

  /* if there is a reference to the user's css choice in storage, assign it */
  if( localStorage.getItem( 'style' )!=null ) css.href=localStorage.getItem( 'style' );
  }

  document.addEventListener( 'DOMContentLoaded', bindEvents, false );
</script>
Micah Cobb
  • 91
  • 7
  • 2
    No element at `html` at Question has `id` set to `"style"`. – guest271314 Dec 28 '16 at 04:33
  • Yeah. But shouldn't css.style be set from "el.dataset.style", which is defined in the code? – Micah Cobb Dec 28 '16 at 05:05
  • What does `console.log(css)` log at `console` following `var css=document.getElementById('style');`? You can select the element using attribute selectors. Though current `html` at Question does not contain element having `id` `"style"`? – guest271314 Dec 28 '16 at 05:26

2 Answers2

3

First, start by defining the original style like this:

HTML:

<link id="style" rel="stylesheet" type="text/css" href="style.css" />

Notice the id=style that we'll use to find the element. That might fix your first error.

For the second one, you have to decide whether to use document.addEventListener( 'DOMContentLoaded', bindEvents, false ); or window.onload because they're different functions. This might help you window.onload vs. body.onload vs. document.onready.

So, now we can do some Javascript:

HTML (the links):

 <li><button onclick='setStyle("css/style.comicsans.css")'>JB's Fav Font</button></li>
 <li><button onclick='setStyle("css/style.other.css")'>Other Font</button></li>

First, notice that I'm only using a parameter to call setStyle function on click, and btw it's better to work with <button>, this way we get a cleaner result.

Javascript:

var cssStyle = document.getElementById('style');

window.onload = function(){
    if(localStorage && localStorage.getItem("style"))
        cssStyle.href = localStorage.getItem("style");
};

function setStyle(newStyle){
    cssStyle.href = newStyle;

    if(localStorage)
        localStorage.setItem("style", newStyle);
};

BONUS: But if you are only be using two styles, then try to simplify, and do a shorthand method to do this:

HTML:

<li><button onclick='toggleStyle()'>Toggle</button></li>

<!-- cssswitcher js -->
<script type='text/javascript'>

    var cssStyle = document.getElementById('style');
    var listStyles = ["css/style.comicsans.css", "css/style.other.css"];

    window.onload = function(){
        if(localStorage && localStorage.getItem("style"))
            cssStyle.href = localStorage.getItem("style");
    };

    function toggleStyle(){
        var previousStyle = cssStyle.href;

        if(previousStyle.endsWith(listStyles[0]))
            newStyle = listStyles[1];
        else
            newStyle = listStyles[0];

        cssStyle.href = newStyle;

        if(localStorage)
            localStorage.setItem("style", newStyle);
    };
</script>
Community
  • 1
  • 1
Camilo
  • 163
  • 6
  • Also, It would be a better idea to know if you only need to change the font because there is going to be a faster way to get that. Something like changing the `font-family` style or so. Something like this: [http://www.w3schools.com/jsref/prop_style_fontfamily.asp](http://www.w3schools.com/jsref/prop_style_fontfamily.asp) – Camilo Dec 28 '16 at 05:45
  • Amazing answer! Thanks so much! – Micah Cobb Dec 28 '16 at 08:17
1

I did this in one of my projects using JQuery, I hope this will help you :

HTML :

<ul id="projectList">
  <li class="project">Lorem Lorem</li>
  <li class="project viewed">Lorem Lorem</li>
  <li class="project viewed selected">Lorem Lorem</li>
  <li class="project viewed selected">Lorem Lorem</li>
  <li class="project viewed">Lorem Lorem</li>
</ul>

JavaScript with Dynamic CSS Code :

var data = {
  "projectColors": {
    "viewedColor": "#fffc20",
    "selectedColor": "#ff7920"
  }
};

var style = $(document.createElement("style")).attr("type", "text/css");
style.append("#projectList .project.viewed {color: " + data.projectColors.viewedColor + ";}");
style.append("#projectList .project.selected {color: " + data.projectColors.selectedColor + ";}");
style.appendTo("head");

JSFiddle :

https://jsfiddle.net/nikdtu/9gberp5o/

Nikhil Maheshwari
  • 2,042
  • 16
  • 21