Search code examples
javascriptjqueryhtmlclonepre

clone div with jquery and show as code


I need to show the code of some Divs in page. Div should be cloned into pre tag with proper spacing and identation and should work in ie8.

I'm a starter so don't really know if i'm doing it correct way, so far i wrote this

Html

//create button after div
    $("<div class='btn'>click to show code</div>").insertAfter(".content-wrapper");

    //create pre wrapper after button
    $("<pre></pre>").insertAfter(".btn");

    //hide the pre so can slidetoggle later
    $("pre").hide();
    
    $(".btn").one("click", function() {
    
      var cloned = $(this).prev().clone();
      var code = $(cloned).html().replace(/</g, "&lt;").replace(/>/g, "&gt;");
      $(this).next().append(code);
    
    });
    
    $(".btn").click(function() {
      $(this).next().slideToggle("fast", function() {
      });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="wrapper-all">
            <div class="content-wrapper">
                <div class="example-div">
                    <span>lorem ipsum first</span>
                </div>
            </div>
        </div>

        <div class="wrapper-all">
            <div class="content-wrapper">
                <div class="example-div">
                    <span>lorem ipsum second</span>
                </div>
            </div>
        </div>

jsfiddle

It dynamically adds, button and pre after the .content-wrapper divs which can be slide toggled.

ie8 completeley ignores whitespaces, and in chrome,firefox some unwanted whitespaces appearing, the outputed code should respect the identation of the original divs, but remove the spaces from left and code should start from zero whitespace to the left.


Solution

  • I had some success with the following method, loosely based on other answers here. It seems a little "brute-forcey" and may be brittle depending on how well your HTML is formatted.

    Basically, it splits the lines of HTML content into an array. It determines the number of spaces at the beginning of the first line and removes that number of spaces from all lines. This resets indentation so that the first line is not indented and subsequent lines are only indented relative to the first line.

    So, if the first line is indented by 15 spaces and the second line is indented by 20 spaces, the first line will not be indented and the second line will be indented by 5 spaces (20-15).

    $(".btn").one("click", function () {
    
        var cloned = $(this).prev('.content-wrapper').clone(),
    
            // Get the code from the clone and split it by new lines.
            // Then filter the array to remove blank lines.
            code = $(cloned).html().split("\n").filter(function (n) {
                return (n.replace(/\s+$/, '') != '');
            }),
    
            // Determine the number of spaces on the left of the first line
            spacesOnLeft = code[0].match(/^ */)[0].length;
    
        // loop through each line, removing unnecessary indentation spaces.
        // Append the line to the output area
        for (i in code) {
            var $output = $(this).next(),
                existing_text=$output.text(),
                new_text=code[i].substring(spacesOnLeft);
            $output.text(existing_text + new_text + '\n');
        }
    
    });
    

    Test below:

    //create button after div
    $("<div class='btn'>show code</div>").insertAfter(".content-wrapper");
    //create pre wrapper after button
    $("<pre></pre>").insertAfter(".btn");
    //hide the pre so can slidetoggle later
    $("pre").hide();
    
    $(".btn").one("click", function() {
    
      var cloned = $(this).prev('.content-wrapper').clone(),
        code = $(cloned).html().split("\n").filter(function(n) {
          return (n.replace(/\s+$/, '') != '');
        }),
        spacesOnLeft = code[0].match(/^ */)[0].length;
    
      for (i in code) {
          var $output = $(this).next(),
              existing_text=$output.text(),
              new_text=code[i].substring(spacesOnLeft);
          $output.text(existing_text + new_text + '\n');
      }
    
    });
    
    $(".btn").click(function() {
      $(this).next().slideToggle("fast", function() {});
    });
    .wrapper-all {
      margin-bottom: 40px;
    }
    .example-div {
      padding: 40px;
      background-color: #ecf0f1;
      text-align: center;
    }
    .btn {
      padding: 8px 20px;
      background-color: #1abc9c;
      color: white;
      width: auto;
      cursor: pointer;
      margin: 0 auto;
      text-align: center;
      text-transform: uppercase;
      transition: background-color 0.16s ease-in-out;
    }
    .btn:hover {
      background-color: #16a085;
    }
    pre {
      background-color: #34495e;
      color: white;
      margin: 0;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <div class="wrapper-all">
        <div class="content-wrapper">
            <div class="example-div">
                <span>lorem ipsum first</span>
            </div>
        </div>
    </div>
    <div class="wrapper-all">
        <div class="content-wrapper">
            <div class="example-div">
                <span>lorem ipsum second</span>
            </div>
        </div>
    </div>