Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 11 of 11
  1. #1
    New Coder
    Join Date
    Jun 2012
    Location
    San Diego
    Posts
    60
    Thanks
    46
    Thanked 0 Times in 0 Posts

    How to write quotes within quotes?

    I am trying to switch a class out with JavaScript, but can't figure out how to do double quotes (quotes within quotes) "class='product correct'";

    From this

    Code:
     class=product neutral //background color is grey
    to this

    class=product correct //background color is green

    CSS:
    Code:
        if (trueProduct == 12){
        		document.getElementById("userAnswer").innerHTML = "class='product correct'";	
        		}
    HTML

    Code:
    <span id="userAnswer" class="product neutral"></span>

  • #2
    Regular Coder
    Join Date
    Aug 2012
    Posts
    145
    Thanks
    0
    Thanked 26 Times in 26 Posts
    For a change to the class using javascript, couldn't you just use the className property?

    Code:
    function test(){
    var x = document.getElementById('demo');
    var y = prompt('enter value 12');
    if(y==12){
    document.getElementById('demo').className = 'hi1';
    }
    }
    So i'm not sure if this is what your were looking for but for the double quotes to show up within the innerHTML you could escape them:

    Code:
    function here(){
    document.getElementById('demo').innerHTML = "class=\"product correct\"";
    }
    i just combined all the above down here:
    Code:
    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript">
    window.addEventListener('load',test,false);
    function test(){
    var x = document.getElementById('demo');
    var y = prompt('enter value 12');
    if(y==12){
    document.getElementById('demo').className = 'hi1';
    }
    }
    function here(){
    document.getElementById('demo').innerHTML = "class=\"product correct\"";
    }
    </script>
    <style type="text/css">
    .hi{
    background:gray
    }
    .hi1{
    background:green;
    }
    </style>
    </head>
    <body>
    <p id="demo" class="hi">Testing out</p>
    <span id="test" class="hi">hi</span><br/>
    <button onclick="here()">click</button>
    </body>
    </html>
    hope this helps
    1 Corinthians 15:3-4 / Ephesians 2:8-9 - What or Who are you living for? Jesus is returning very soon

  • Users who have thanked Brandnew for this post:

    ryanjohnsond (06-22-2013)

  • #3
    Supreme Master coder! Philip M's Avatar
    Join Date
    Jun 2002
    Location
    London, England
    Posts
    18,315
    Thanks
    203
    Thanked 2,565 Times in 2,543 Posts
    Not a problem of quotes. Should be

    if (trueProduct == 12) {
    document.getElementById("userAnswer").className='productCorrect';
    }

    You may not have a space in a class name. Including spaces actually denotes multiple classes - product and correct.

    Your css should read

    .productCorrect{background-color:green}

    Quizmaster: Who in 1840 married Prince Albert of Saxe-Coburg Gotha?
    Contestant: Wallis Simpson
    Last edited by Philip M; 06-21-2013 at 08:51 AM.

    All the code given in this post has been tested and is intended to address the question asked.
    Unless stated otherwise it is not just a demonstration.

  • Users who have thanked Philip M for this post:

    ryanjohnsond (06-22-2013)

  • #4
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,387
    Thanks
    32
    Thanked 288 Times in 282 Posts
    Quote Originally Posted by ryanjohnsond View Post
    I am trying to switch a class out with JavaScript
    Unless you're restricting your code to one class per element, this is, unfortunately, a complicated process without the DOMTokenList interface and classList property of DOM4. IE9 and lower don't support either.

    You can create some functions that will allow you to manipulate classes on demand:

    Code:
    // Adds an HTML element to a specified class.
    HTMLElement.prototype.add_class = function (class_name) {
    	// If the DOM4 DOMTokenList interface and classList property are supported, add the specified class name to the class list.
    	if (typeof DOMTokenList === "function" && this.classList instanceof DOMTokenList) {
    		this.classList.add(class_name);
    	}
    	// IE9
    	else {
    		// If there’s no class attribute, create one with the specified class name as its value.
    		if (!this.hasAttribute("class")) {
    			this.setAttribute("class", class_name);
    		}
    		// Utilize an existing class attribute by appending a space and the specified class name.
    		else {
    			this.setAttribute("class", this.getAttribute("class") + " " + class_name);
    		}
    	}
    };
    
    // Removes an HTML element from a specified class.
    HTMLElement.prototype.remove_class = function (class_name) {
    	// If the DOM4 DOMTokenList interface and classList property are supported, remove the specified class name from the class list.
    	if (typeof DOMTokenList === "function" && this.classList instanceof DOMTokenList) {
    		this.classList.remove(class_name);
    	}
    	// IE9
    	else {
    		// Output Expression: /(?:^class_name$|^class_name |( class_name )|class_name$)/
    		class_name = new RegExp("(?:^" + class_name + "$|^" + class_name + " |( " + class_name + " )| " + class_name + "$)");
    		// If the target class name is delimited by spaces within the attribute value, replace the class name and delimiting spaces with a single space. For example, "classA class_name classB" will become "classA classB".
    		if (this.getAttribute("class").match(class_name).length > 1) {
    			this.setAttribute("class", this.getAttribute("class").replace(class_name, " "));
    		}
    		// If the target class name has an adjacent space, removed both the class name and adjacent space. For example, "class_name classA" and "classA class_name" will both become "classA" and "class_name" will become "" (an empty string).
    		else {
    			this.setAttribute("class", this.getAttribute("class").replace(class_name, ""));
    			// If the class attribute is empty, remove it.
    			if (this.getAttribute("class").length === 0) {
    				this.removeAttribute("class");
    			}
    		}
    	}
    };
    
    // For a given HTML element, replaces one class with another.
    HTMLElement.prototype.replace_class = function (replaced_class, replacement_class) {
    	this.remove_class(replaced_class);
    	this.add_class(replacement_class);
    };
    Example usage:

    Code:
    document.getElementById("userAnswer").replace_class("neutral", "correct");
    I also have a live example up at https://patrick.dark.name/web.dev/cf...thread.297229/ and a more complicated example (using the same code via class.manipulation.js) at https://patrick.dark.name/web.dev/cf...thread.295827/.
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • Users who have thanked Arbitrator for this post:

    ryanjohnsond (06-22-2013)

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,688
    Thanks
    80
    Thanked 4,653 Times in 4,615 Posts
    Sorry, Philip. You are dead wrong. Or you misunderstood the question. He has *TWO* class names applied to the element. Not one name with a space.

    And I don't know why Arbitrator makes it so complicated.

    RYAN: You can't possibly do what you are trying to do using innerHTML.

    All you want/need is something dirt simple. Just change the className. And there is no issue of quotes within quotes, because you don't need them.

    A demo:
    Code:
    <!DOCTYPE>
    <html>
    <head>
    <style type="text/css">
    .product {
        font-style: italic;
        font-size: xx-large;
    }
    .info {
        font-size: medium;
        font-weight: bold;
    }
    .red {
        color: red;
    }
    .blue {
        color: blue;
    }
    </style>
    </head>
    <body>
    <div id="demo" class="product blue">
    This is just to demonstrate the concept
    </div>
    
    <input type="button" class="blue info" id="tryit" value="click me" />
    
    <script type="text/javascript">
    document.getElementById("tryit").onclick = function( )
        {
            this.className = "product red";
            document.getElementById("demo").className = "product red";
        }
    </script>
    </body>
    </html>
    Works in Chrome, FF, MSIE 9. Untested in older MSIE, but I have done this kind of stuff for many years, I think since MSIE 5 days, and it works fine.
    Last edited by Old Pedant; 06-21-2013 at 11:26 PM.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    ryanjohnsond (06-22-2013)

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,688
    Thanks
    80
    Thanked 4,653 Times in 4,615 Posts
    And finally, just FYI, Ryan:

    You *can* use quotes within quotes in JavaScript. Various ways:

    Code:
    var s1 = 'This is a string with "embedded" quotes';
    var s2 = "This is a string with \"embedded\" quotes";
    var t = "This is a string with 'embedded' apostrophes";
    var t = 'This is a string with \'embedded\' apostrophes';
    And in any case, it can never HURT to "escape" a quote *OR* apostrophe:
    Code:
    var u1 = "It\'s okay to \"escape\" quotes and apostophes even if it isn\'t needed";
    var u2 = 'It\'s okay to \"escape\" quotes and apostophes even if it isn\'t needed';
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    ryanjohnsond (06-22-2013)

  • #7
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,387
    Thanks
    32
    Thanked 288 Times in 282 Posts
    Quote Originally Posted by Old Pedant View Post
    And I don't know why Arbitrator makes it so complicated.
    I was trying to create something...
    • ... generic that can be re-used multiple times within a page or across a site.
    • ... code that alters a single class completely independent of whatever other classes are applied to the element.
    • ... something that wouldn't leave behind any extraneous spaces in the class attribute when classes are added and removed from the DOM.
    • ... something compatible with IE9. (I decided to ignore IE8 to minimize complexity, but may come back and fix that later. I'm seeing usage figures that vary between <10% to >20%.)

    Anyway, your code works, to be sure, but it requires that you know that the other class is product and breaks as soon as another class ends up on that element since your code will overwrite the new class(es). For example, one day, this code...

    Code:
    <div id="demo" class="product blue">
    This is just to demonstrate the concept
    </div>
    ... may become this code...

    Code:
    <div id="demo" class="product blue sparkle">
    This is just to demonstrate the concept
    </div>
    Now all assignments to className need to be re-written to add the sparkle class or else the sparkle class simply vanishes during the attribute write process.

    Plus I just learned of the existence of DOMTokenList this morning and couldn't resist using it. Always nice to learn how to use something new plus it's *way* simpler than the add_class and remove_class functions I had previously written. If I stick to only the code at hand, I get the simple and powerful:

    Code:
    if (trueProduct == 12){
    	document.getElementById("userAnswer").classList.remove("neutral");
    	document.getElementById("userAnswer").classList.add("correct");	
    }
    Now one just has to wait for IE9 and lower to die off.
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • Users who have thanked Arbitrator for this post:

    ryanjohnsond (06-22-2013)

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,688
    Thanks
    80
    Thanked 4,653 Times in 4,615 Posts
    No disagreement, Arbitrator! Clearly my code is a hack to just one thing. But if you look at what he was attempting, I truly think it is all he needed.

    I do think, though, that a simple string based solution will work 98% of the time, even for adding/removing/altering single classes within a set of them. Your code takes care of the other 2%, but is a bit overkill in most cases.
    Code:
    function removeClass( fromObj, name )
    {
        var names = fromObj.className.split(" ");
        var newnames = [ ];
        for ( var n = 0; n < names.length; ++n )
        {
            // skipping over "" means we lose any extraneous space previously there
            if ( names[n] !== "" && names[n] !== name ) { newnames.push(names[n]); }
        }
        fromObj.className = names.join(" ");
    }
    function addClass( toObj, name )
    {
        removeClass( toObj, name ); // just in case somebody does something silly
        toObj.className += " " + name;
    }
    function changeClass( obj, fromName, toName )
    {
        removeClass( obj, fromName );
        obj.className += " " + toName;
    }
    Won't that work for 98% of the cases?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    ryanjohnsond (06-22-2013)

  • #9
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,387
    Thanks
    32
    Thanked 288 Times in 282 Posts
    Quote Originally Posted by Old Pedant View Post
    I do think, though, that a simple string based solution will work 98% of the time, even for adding/removing/altering single classes within a set of them.
    I was specifically avoiding the string-based className in favor of methods I consider more readable (has/get/setAttribute), though I do think split and join are fine. You present an interesting alternative approach. I did consider using split myself, but didn't do so in the end; I might have had I remembered that there was a join method. I don't think I've ever used join before.

    Worth noting that your code contains a typo and a minor flaw. Firstly, names.join(" ") was presumably supposed to be newnames.join(" "). Secondly, changeClass will result in the same class name being appended multiple times if assigned to, say, a button that calls the function with the same arguments multiples times. That's not exactly tidy, but there's no harm done, I suppose. Thankfully, that issue is easily remedied by invoking another instance of removeClass:

    Code:
    function changeClass(obj, fromName, toName) {
    	removeClass(obj, fromName);
    	removeClass(obj, toName);
    	obj.className += " " + toName;
    }
    I'll look into seeing if array-based methods are simpler than my current code when used with has/get/setAttribute. I like to avoid regular expressions when possible.

    Quote Originally Posted by Old Pedant View Post
    Your code takes care of the other 2%, but is a bit overkill in most cases.
    As far as I can tell, your code covers the same "98%" of use cases regarding functionality.

    And both your and my code are hardly full proof. Unfortunately, the spec allows four other characters to be used as spaces for the purpose of the class attribute. I made the assumption that I won't see something like...

    Code:
    <p class="product
    neutral">This is filler text.</p>
    ... or...

    Code:
    <p class="			product&#xc;neutral">This is filler text.</p>
    ... even though both of those are perfectly valid.
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • Users who have thanked Arbitrator for this post:

    ryanjohnsond (06-22-2013)

  • #10
    Supreme Master coder! Philip M's Avatar
    Join Date
    Jun 2002
    Location
    London, England
    Posts
    18,315
    Thanks
    203
    Thanked 2,565 Times in 2,543 Posts
    Quote Originally Posted by Old Pedant View Post
    Sorry, Philip. You are dead wrong. Or you misunderstood the question. He has *TWO* class names applied to the element. Not one name with a space.
    You may well be right, but I do not see how you deduced that.

    All you want/need is something dirt simple. Just change the className. And there is no issue of quotes within quotes, because you don't need them.
    Is that not the same as the answer I offered?

    All the code given in this post has been tested and is intended to address the question asked.
    Unless stated otherwise it is not just a demonstration.

  • Users who have thanked Philip M for this post:

    ryanjohnsond (06-22-2013)

  • #11
    New Coder
    Join Date
    Jun 2012
    Location
    San Diego
    Posts
    60
    Thanks
    46
    Thanked 0 Times in 0 Posts

    Thumbs up

    Quote Originally Posted by Philip M View Post
    You may well be right, but I do not see how you deduced that.
    Is that not the same as the answer I offered?
    Sorry abut that. I should have written my code exmple more clearly.

    I had two classes declared: class="class1 class2" to make one cascaded effect. ".product" declared font style. ".neutral" declared its background color.

    Pedant, I had no idea you could add an event handler on things like a getElementById; and on top of that, load a function into an event handler.

    Code:
    document.getElementById("tryit").onclick = function( )
    Arbitrator, thank you very much for the detailed code. It's above my paygrade, atm; but I will study it. I've already marked your site. thnx!
    Last edited by ryanjohnsond; 06-24-2013 at 08:09 AM.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •