Michael Bruce
Michael Bruce

Reputation: 11337

Amending my code: currently using toggle() and toggleClass()

Some of my code does not communicate what it needs to.

On these IDs

I added a class called .selected. The way I wrote the code, works great as is. But, when I remove selected from any of those IDs, I would then have to add new CSS and add "display: none" to any of the corresponding viewport containers:

I do realize that I can create some if statements but I also would like to learn some new methods / functions that can help me. One thing I like is clear readable code that is efficient. So having a bunch of un-needed checks and loops is not my goal.

Based off the method I chose to use toggle() and toggleClass() does not communicate well together (in my code) when trying to manually remove .selected class without manually adding a display: none to my ID container divs.

The reason I would want to manually remove the .selected class is because I might want to change the default ID containers that are open when the app loads.


Would someone be willing to shed some new light on some different ideas on how to approach this?


My Editable code on CSSDeck < basically like jsfiddle or jsbin.

Javascript

    $('.code-container').css('height', $(window).innerHeight() - 39 + "px");
$(window).resize(function () {
    $('.code-container').css('height', $(window).innerHeight() - 39 + "px");
});


$("[id$=button]").click(function () {

    $(this).toggleClass('selected');

    // creates the name of a viewport ID. "view-" + html of button
    var viewID = "#" + $(this).html() + "-container";
    $(viewID).toggle();

    var viewSize = $(window).innerWidth()/$('.selected').length;
    $(".code-container").css("width", viewSize);
}
);

$('#run').click( function() {
    var html = $('#htmlCode').val();
    var css = $('#cssCode').val();
    var js = $('#jsCode').val();
    $('#iframe').contents().find("html").html("<style>" + css + "</style>" + html);
});

HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Code Player</title>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
    <link rel="stylesheet" href="style.css" />

</head>

<body>

    <div id="wrapper">

        <div id="header">
            <p id="logo">CodePlayer</p>
            <nav>
                <ul>
                    <li id="html-button"    class="toggle selected no-highlight">html</li>
                    <li id="css-button"     class="toggle selected no-highlight">css</li>
                    <li id="js-button"      class="toggle selected no-highlight">js</li>
                    <li id="result-button"  class="toggle selected no-highlight">result</li>
                </ul>
            </nav>
            <div id="run" class="no-select">Run</div>
        </div>

        <div id="html-container" class="code-container">
            <div class="code-label">HTML</div>
            <textarea id="htmlCode"></textarea>
        </div>
        <div id="css-container" class="code-container">
            <div class="code-label">CSS</div>
            <textarea id="cssCode"></textarea>
        </div>
        <div id="js-container" class="code-container">
            <div class="code-label">JS</div>
            <textarea id="jsCode"></textarea>
        </div>
        <div id="result-container" class="code-container">
            <div class="code-label">Result</div>
            <iframe id="iframe"></iframe>
        </div>



    </div>

    <script type="text/javascript" src="script.js"></script>
</body>

</html>

CSS

/* Global Settings */
* { padding: 0; margin: 0;}
body {
    font-size: 14px;
    font-family: sans-serif;
}
.no-highlight {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

/* Header Logo Toggles and Buttons */
#header {
    width: 100%; height: 28px;
    background-color: #222;
    padding: 4px;
}
#header #logo {
    color: #fff;
    font-weight: 500;
    position: absolute;
    left: 10px; top: 4px;
    font-size: 1.5em;
    line-height: 28px

}
#header nav {   
    width: 226px; height: 28px;
    margin: auto;
}

/* Look and Feel of buttons */
#header li, #run {
    width: 50px; height: 26px;
    background-color: #000;
    color: #aaa;
    border: 1px solid #00a2ff;
    border-radius: 6px;
    font-size: .8em;
    text-transform: uppercase;
    line-height: 26px;
    text-align: center;
    list-style: none;
    float: left;
    cursor: pointer;
}
/* ads margin ONLY between li elements */
#header li+li {
    margin-left: 6px;
}
/* Run button positioning */
#run {
    position: absolute;
    right: 10px; top: 4px;
}
/* special class to differentiate toggled buttons */
#header .selected, #header #run {
    background-color: #000;
    color: #fff;
}

/* end of Button styling */






/* code-container is the html, css, js and result viewports */
.code-container {
    width: 25%;
    float: left;
    position: relative;
    display: none;
}
/* textarea for user input of code */
.code-container textarea {
    width: 100%; height: 100%;
    padding: 18px 3px 3px 3px;
    font-size: 1.2em;
    border-right: 1px solid #222;
    font-family: monospace;
    box-sizing: border-box;
}
/* viewport name */
.code-label {
    position: absolute;
    top: 5px; right: 5px;
}
/* viewport for the code output result */
iframe {
    width: 100%; height: 100%;
    border: none;
}

Upvotes: 0

Views: 100

Answers (1)

Alp
Alp

Reputation: 29739

Your approach is good. Nevertheless there are certain points which can be improved in your realization.

Here are my proposals:

  1. Don't rely on the innerHtml of your button's for identifying them. I introduced a new data-pane attribute. You could use the id as well (if you strip the "-button" substring)
  2. Use named functions and structure your code
  3. Hide all .container elements by default in your CSS and show all panes with "selected" buttons when bootstrapping your application

Here is a DEMO

The changes

HTML

I removed the selected class of the first item for demonstration purposes. Also I added the data-pane attribute:

<li id="html-button"    class="toggle no-highlight" data-pane="html">html</li>
<li id="css-button"     class="toggle selected no-highlight" data-pane="css">css</li>
<li id="js-button"      class="toggle selected no-highlight" data-pane="js">js</li>
<li id="result-button"  class="toggle selected no-highlight" data-pane="result">result</li>

CSS

I added display: none;

.code-container {
    width: 25%;
    float: left;
    position: relative;
    display: none;
}

JS

I rewrote major parts of it, but here are only the new parts.

This shows all panes that are selected when the app starts:

  $('.selected').each(function() {
    var pane = $(this).data('pane');
    showPane(pane);
  });

This gives you the information you need to decide what to toggle:

  var pane = $(this).data('pane');
  var isSelected = $(this).hasClass('selected');

  if(isSelected) {  
    hidePane(pane);
  } else {
    showPane(pane);
  }

These are the new show and hide functions. They bundle all needed actions to update the view:

function showPane(pane) {
  $('#' + pane + '-button').addClass('selected');
  $('#' + pane + '-container').show();
  updateContainers();
}

function hidePane(pane) {
  $('#' + pane + '-button').removeClass('selected');
  $('#' + pane + '-container').hide();
  updateContainers();
}

function updateContainers() {
  var viewSize = $(window).innerWidth() / $('.selected').length;
  $(".code-container").css("width", viewSize);
}

As you can see, no manual display: none; is needed.

Upvotes: 1

Related Questions