Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              //output: index.html

- var namespace = "pam"

- var author = "Frank Dip"
- var version = "Version 1.3"
- var title = "Pixel Art Maker"
- var description = "Pixel Art Maker. Using PUG, Bootstrap, SCSS, jQuery, HTML2canvas, and Font awesome. " + version + "."
- var link = "https://codepen.io/LeafDragon/";

//- Variable Chain
//-  File
- var savePNG = namespace + "-save-png"
- var saveJPEG = namespace + "-save-jpeg"
- var deleteConfirmation = namespace + "-delete--confirmation"
- var deleteButton = namespace + "-delete--button"

//- Border
- var border = namespace + "-border"
- var borderDefault = namespace + "-border--default"
- var borderLess = namespace + "-border--less"
- var borderColor = border + "--color"

//- Pixel Art
- var pixelArt = namespace + "-pixel-art"
- var pixelArtPikachu = namespace + "-pixel-art--pikachu"
- var pixelArtPokeball = namespace + "-pixel-art--pokeball"
- var pixelArtModal = pixelArt + "--modal"
- var pixelArtModalPikachu = pixelArtModal + "--pikachu"
- var pixelArtModalPokeball = pixelArtModal + "--pokeball"

//- Help
- var help = namespace + "-help"
- var helpView = namespace + "-help--view"
- var helpViewBody = namespace + "-help--view--body"
- var helpAbout = namespace + "-help--about"

//- Tool
- var colorPicker = namespace +"-color-picker"
- var tool = namespace + "-tool"
- var toolPaint = tool + "--paint"
- var toolDipper = tool + "--dipper"
- var toolEraser = tool + "--eraser"

//- Size Picker
- var sizePicker = namespace + "-size-picker"
- var sizePickerWidth = sizePicker + "--width"
- var sizePickerHeight = sizePicker + "--height"
- var sizePickerModal = sizePicker + "--modal"
- var sizePickerSubmit = sizePicker + "--submit"
- var label = namespace + "-label"

//- Main
- var main = namespace + "-main"
- var mainSizePicker = main + "--size-picker"
- var table = namespace + "-table"

doctype html
html(lang="en-US")
  head
    meta(charset="utf-8")
    title #{title}
    meta(name="description", content=description)
    meta(name="author", content="Frank Dip")
    meta(name="viewport", content="width=device-width, initial-scale=1.0, shrink-to-fit=no")
    link(href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    )
    link(href="styles\\styles.min.css", rel="stylesheet")
    script(defer="", src="https://use.fontawesome.com/releases/v5.0.7/js/all.js")
  body
    // Bootstrap Navbar 
    nav.navbar.navbar-expand-lg.navbar-dark.bg-dark.fixed-top
      div.navbar-brand
        a(href=link, target="_blank")
          img(src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1580937/profile/profile-512.jpg?1519351323", width="50px", data-toggle="tooltip", title="Leaf Dragon")
        |  Pixel Art Maker
      button.navbar-toggler(type="button", data-toggle="collapse", data-target="#navbarSupportedContent", aria-controls="navbarSupportedContent", aria-expanded="false", aria-label="Toggle navigation")
        span.navbar-toggler-icon
      #navbarSupportedContent.collapse.navbar-collapse
        ul.navbar-nav.mr-auto
          li.nav-item.dropdown
            a#navbarDropdown.nav-link.dropdown-toggle(href="#", role="button", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
              | File
            .dropdown-menu(aria-labelledby="navbarDropdown")
              a.dropdown-item(id=savePNG, href="#")
                i.fas.fa-download
                |  Save PNG
              a.dropdown-item(id=saveJPEG, href="#")
                i.fas.fa-download
                |  Save JPEG
              .dropdown-divider
              a.dropdown-item(href="#", data-toggle="modal" data-target="#" + deleteConfirmation)
                i.fas.fa-trash-alt
                |  Delete
          li.nav-item.dropdown
            a#navbarDropdown.nav-link.dropdown-toggle(href="#", role="button", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
              | Border
            .dropdown-menu(aria-labelledby="navbarDropdown")
              a.dropdown-item(id=borderDefault, href="#")
                i.fas.fa-table
                |  Default
              .dropdown-divider
              a.dropdown-item(id=borderLess, href="#")
                i.far.fa-square
                |  Borderless
              .dropdown-divider
              input.form-control.mr-sm-2(id=borderColor, type="color", value="#4DB6AC", data-toggle="tooltip", title="Border color")
          li.nav-item.dropdown
            a#navbarDropdown.nav-link.dropdown-toggle(href="#", role="button", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
              | Pixel Art
            .dropdown-menu(id=pixelArt, aria-labelledby="navbarDropdown")
              a.dropdown-item(href="#", data-toggle="modal" data-target="#" + pixelArtModalPikachu)
                svg(width=20, height=20)
                  path(
                    fill="yellow"
                    stroke="black"
                    d="M3 8 C5 8, -5 19, 10 19 C10 19, 25 20, 16 8 L20 0 L13 6 L7 6 L0 0 Z"
                  )
                  circle(cx=7, cy=11, r=1, fill="black")
                  circle(cx=13, cy=11, r=1, fill="black")
                  line(x1=9, y1=13, x2=11, y2=13, stroke="black")
                  path(fill="none", stroke="black", d="M7 15 C7 15, 10 17, 13 15")
                  circle(cx=4, cy=16, r=2, fill="red")
                  circle(cx=16, cy=16, r=2, fill="red")
                |  ピカチュー
              a.dropdown-item(href="#", data-toggle="modal" data-target="#" + pixelArtModalPokeball)
                svg(width=20, height=20)
                  defs
                    linearGradient(id="pokeball", x1=0, x2=0, y1=0, y2=1)
                      stop(offset="0%", stop-color="red")
                      stop(offset="45%", stop-color="red")
                      stop(offset="45%", stop-color="black")
                      stop(offset="55%", stop-color="black")
                      stop(offset="55%", stop-color="white")
                      stop(offset="100", stop-color="white")
                  circle(cx=10, cy=10, r=9, stroke="black", fill="url(#pokeball)")
                  circle(cx=10, cy=10, r=2, stroke="black", fill="white")
                |  Pokeball
          li.nav-item.dropdown
            a#navbarDropdown.nav-link.dropdown-toggle(href="#", role="button", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
              | Help
            .dropdown-menu(aria-labelledby="navbarDropdown")
              a.dropdown-item(href="#", data-toggle="modal", data-target="#" + helpView)
                i.fas.fa-question-circle
                |  View Help
              .dropdown-divider
              a.dropdown-item(href="#", data-toggle="modal", data-target="#" + helpAbout)
                i.fas.fa-info-circle
                |  About
    
    // Bootstrap container fluid
    .container-fluid
      // Bootstrap nav tab
      nav
        ul.nav.nav-tabs.justify-content-center
          li.nav-item(data-toggle="tooltip", title="Paint brush color")
            .nav-link
              input.form-control.mr-sm-2(id=colorPicker, type="color")
          li.nav-item(data-toggle="tooltip", title="Paint brush")
            a.nav-link.active(id=toolPaint, href="#")
              i.fas.fa-paint-brush.fa-2x
          li.nav-item(data-toggle="tooltip", title="Dipper")
            a.nav-link(id=toolDipper, href="#")
              i.fas.fa-eye-dropper.fa-2x
          li.nav-item(data-toggle="tooltip", title="Eraser")
            a.nav-link(id=toolEraser, href="#")
              i.fas.fa-eraser.fa-2x
          li.nav-item(data-toggle="tooltip", title="Size Picker")
            a.nav-link(data-toggle="collapse", href="#" + mainSizePicker, role="button", aria-expanded="false", aria-controls="collapseExample")
              i.fas.fa-table.fa-2x

      main.text-center(class=main)
        // Bootstrap collapse for the size picker 
        .collapse(id=mainSizePicker, class=mainSizePicker)
          .card.card-body
            form.form-inline.justify-content-center(id=sizePicker)
              label.mb-2.mr-sm-2(class=label, for=sizePickerWidth) Width:
              input.form-control.mb-2.mr-sm-2(id=sizePickerWidth, type="number", min="1", max="40", value="20", required="required")
              label.mb-2.mr-sm-2(class=label, for=sizePickerHeight) Height:
              input.form-control.mb-2.mr-sm-2(id=sizePickerHeight, type="number", min="1", max="48", value="20", required="required")
              .form-check.mb-2.mr-sm-2
                a.btn.btn-primary(data-toggle="modal" data-target="#" + sizePickerModal)
                  i.fas.fa-table
                  |  Submit
        table(id=table)

    // Modal Submit 
    .modal.fade(id=sizePickerModal, tabindex='-1', role='dialog', aria-labelledby='exampleModalLabel', aria-hidden='true')
      .modal-dialog(role='document')
        .modal-content
          .modal-header.bg-warning
            h5.modal-title
              i.fas.fa-exclamation-circle
              |  Submit?
            button.close(type='button', data-dismiss='modal', aria-label='Close')
              span(aria-hidden='true') ×
          .modal-body
            | Do you want to recreate the table elements?
          .modal-footer
            button.btn.btn-secondary(type='button', data-dismiss='modal') Close
            button.btn.btn-warning(id=sizePickerSubmit, type='button', data-dismiss='modal')
              i.fas.fa-exclamation-circle
              |  Submit
    // Modal Delete 
    .modal.fade(id=deleteConfirmation, tabindex='-1', role='dialog', aria-labelledby='exampleModalLabel', aria-hidden='true')
      .modal-dialog(role='document')
        .modal-content
          .modal-header.bg-danger
            h5.modal-title
              i.fas.fa-exclamation-triangle
              |  Delete?
            button.close(type='button', data-dismiss='modal', aria-label='Close')
              span(aria-hidden='true') ×
          .modal-body
            | Do you want to delete the table elements?
          .modal-footer
            button.btn.btn-secondary(type='button', data-dismiss='modal') Close
            button.btn.btn-danger(id=deleteButton, type='button', data-dismiss='modal')
              i.fas.fa-exclamation-triangle
              |  Delete
    // Modal Pikachu
    .modal.fade(id=pixelArtModalPikachu, tabindex='-1', role='dialog', aria-labelledby='exampleModalLabel', aria-hidden='true')
      .modal-dialog(role='document')
        .modal-content
          .modal-header.bg-warning
            h5.modal-title ピカチュー?
            button.close(type='button', data-dismiss='modal', aria-label='Close')
              span(aria-hidden='true') ×
          .modal-body
            | Do you want to recreate the table elements with a ピカチュー pixel art?
          .modal-footer
            button.btn.btn-secondary(type='button', data-dismiss='modal') Close
            button.btn.btn-warning.bg-warning(id=pixelArtPikachu, type='button', data-dismiss='modal')
              i.fas.fa-exclamation-circle
              |  ピカチュー
    // Modal Pokeball
    .modal.fade(id=pixelArtModalPokeball, tabindex='-1', role='dialog', aria-labelledby='exampleModalLabel', aria-hidden='true')
      .modal-dialog(role='document')
        .modal-content
          .modal-header.bg-warning
            h5.modal-title  Pokeball?
            button.close(type='button', data-dismiss='modal', aria-label='Close')
              span(aria-hidden='true') ×
          .modal-body
            | Do you want to recreate the table elements with a Pokeball pixel art?
          .modal-footer
            button.btn.btn-secondary(type='button', data-dismiss='modal') Close
            button.btn.btn-warning.bg-warning(id=pixelArtPokeball, type='button', data-dismiss='modal')
              i.fas.fa-exclamation-circle
              |  Pokeball
    // Modal help view 
    .modal.fade(id=helpView, tabindex='-1', role='dialog', aria-labelledby='exampleModalLongTitle', aria-hidden='true')
      .modal-dialog(role='document')
        .modal-content
          .modal-header.bg-info.text-white
            h5.modal-title
              i.fas.fa-question-circle
              |  Help
            button.close(type='button', data-dismiss='modal', aria-label='Close')
              span(aria-hidden='true') ×
          .modal-body(id=helpViewBody)
            p File &gt; 
              i.fas.fa-download
              span.font-weight-bold  Save PNG
              |  will save a png file of the drawn pixel art.
            p File &gt; 
              i.fas.fa-download
              span.font-weight-bold  Save JPEG
              |  will save a png file of the drawn pixel art.
            p File &gt; 
              i.fas.fa-trash-alt
              span.font-weight-bold  Delete
              |  will delete the canvas.
            p Border &gt; 
              i.fas.fa-table
              span.font-weight-bold  Default
              |  will delete the canvas.
            p Border &gt; 
              i.far.fa-square
              span.font-weight-bold  Borderless
              |  will color the border white.
            p Border &gt; 
              i.far.fa-square
              span.font-weight-bold  Color
              |  will color the border to selected color.
            p Pixel Art &gt; 
              svg(width=20, height=20)
                path(
                  fill="yellow"
                  stroke="black"
                  d="M3 8 C5 8, -5 19, 10 19 C10 19, 25 20, 16 8 L20 0 L13 6 L7 6 L0 0 Z"
                )
                circle(cx=7, cy=11, r=1, fill="black")
                circle(cx=13, cy=11, r=1, fill="black")
                line(x1=9, y1=13, x2=11, y2=13, stroke="black")
                path(fill="none", stroke="black", d="M7 15 C7 15, 10 17, 13 15")
                circle(cx=4, cy=16, r=2, fill="red")
                circle(cx=16, cy=16, r=2, fill="red")
              span.font-weight-bold  ピカチュー 
              |  will draw Pikachu.
            p Pixel Art &gt; 
              svg(width=20, height=20)
                defs
                  linearGradient(id="pokeball1", x1=0, x2=0, y1=0, y2=1)
                    stop(offset="0%", stop-color="red")
                    stop(offset="45%", stop-color="red")
                    stop(offset="45%", stop-color="black")
                    stop(offset="55%", stop-color="black")
                    stop(offset="55%", stop-color="white")
                    stop(offset="100", stop-color="white")
                circle(cx=10, cy=10, r=9, stroke="black", fill="url(#pokeball1)")
                circle(cx=10, cy=10, r=2, stroke="black", fill="white")
              span.font-weight-bold  Pokeball
              |  will draw a pokeball.
            p Help &gt; 
              i.fas.fa-question-circle
              span.font-weight-bold  View Help
              |  will display the help documentation.
            p Help &gt; 
              i.fas.fa-info-circle
              span.font-weight-bold  About
              |  will display the description.
            p
              i.far.fa-square
              span.font-weight-bold  Color
              |  will color the paint to selected color.
            p
              i.far.fa-square
              span.font-weight-bold  Width
              |  will set the width of the canvas.
            p
              i.far.fa-square
              span.font-weight-bold  Height
              |  will set the height of the canvas.
            p
              i.far.fa-square
              span.font-weight-bold  Submit
              |  will submit the form with the width and height information.
            p
              i.fas.fa-paint-brush
              span.font-weight-bold  Paint
              |  will select the paint brush.
            p
              i.fas.fa-eye-dropper
              span.font-weight-bold  Dipper
              |  will select the dipper to copy the selected color.
            p
              i.fas.fa-eraser
              span.font-weight-bold  Erase
              |  will select the eraser to erase the selected target.
            p
              i.fas.fa-eraser
              span.font-weight-bold  Double Click
              |  will erase the selected target with a double click.
          .modal-footer
            button.btn.btn-secondary(type='button', data-dismiss='modal') Close
    // Modal help about 
    .modal.fade(id=helpAbout, tabindex="-1", role="dialog", aria-labelledby="exampleModalCenterTitle", aria-hidden="true")
      .modal-dialog.modal-dialog-centered(role="document")
        .modal-content
          .modal-header.bg-info.text-white
            h5.modal-title
              i.fas.fa-info-circle
              |  About
            button.close(type="button", data-dismiss="modal", aria-label="Close")
              span(aria-hidden="true") ×
          .modal-body
            p Title: #{title}
            p Author: #{author}
            p Description: #{description}
            p Link: 
              a(href=link, target="_blank") Leaf Dragon(new tab)
          .modal-footer
            button.btn.btn-secondary(type="button", data-dismiss="modal") Close

    // Script 
    script(src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
      integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
      crossorigin="anonymous"
    )
    script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
      integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
      crossorigin="anonymous"
    )
    script(src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
      integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
      crossorigin="anonymous"
    )
    script(src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js")
    script(src="script\\script.js")

            
          
!
            
              $namespace: pam;

/// @author Frank Dip
/// Pixel Art
/// TODO: Look for ways to refactor
/// @version 1.2

 /********************************************//**
  * Animation
  ***********************************************/

/**
 * reticle
 * Creates an animation of inset box-shadow and outline.
 * Makes it easier to spot things.
 */
@keyframes reticle {
  0% {
    box-shadow: inset 0px 0px 2px 2px rgba(240,12,12,1);
    outline: 2px solid rgba(255,255,0,1);
  }

  50% {
    box-shadow: inset 0px 0px 2px 3px rgba(0,255,0,1);
    outline: 3px solid rgba(0,0,255,1);
  }

  100% {
    box-shadow: inset 0px 0px 2px 2px rgba(255,255,0,1);
    outline: 2px solid rgba(240,12,12,1);
  }
}

/////////////////////////////////////////////////
/// Placeholder Classes
/////////////////////////////////////////////////

// %reticle
%reticle {animation: 3s infinite alternate reticle;}

%cursor---pointer {cursor: pointer;}

%padding---zero {padding: 0;}

/********************************************//**
 *  HTML Elements
 ***********************************************/

body {padding-top: 90px;}

table,
tr,
td {
  margin: auto;
  border-collapse: collapse;
  border: 1px solid #4DB6AC;
}

tr {height: 20px;}

td {
  width: 20px;
  height: 20px;
  @extend %cursor---pointer;
  background-color: #FFF;
  &:hover {@extend %reticle;}
}

/********************************************//**
 *  ID
 ***********************************************/

##{$namespace} {
  &-border--color {
    @extend %padding---zero;
    @extend %cursor---pointer;
  }
  &-color-picker {
    @extend %padding---zero;
    @extend %cursor---pointer;
    width: 40px;
    height: 35px;
  }
}

/********************************************//**
 *  Classes
 ***********************************************/

.#{$namespace} {
  &-help {cursor: help;}
  
  &-label {@extend %cursor---pointer;}
  
  &-main {
    margin: 1em auto;
    &--size-picker {margin-bottom: 1em;}
  }
}

            
          
!
            
              let namespace = "pam";

/**
 * @author Frank Dip
 * @desc Pixel Art Maker
 * Not using JS design pattern Module yet.
 * TODO: Refactor to DRY code
 * @version 1.4
 */

/********************************************//**
 *  DOM Selectors jQuery
 ***********************************************/

const $body = $("body");

const $savePNG = $(`#${namespace}-save-png`);
const $saveJPEG = $(`#${namespace}-save-jpeg`);
const $deleteButton = $(`#${namespace}-delete--button`);

const $borderDefault = $(`#${namespace}-border--default`);
const $borderLess = $(`#${namespace}-border--less`);
const $borderColor = $(`#${namespace}-border--color`);

const $pixelArtPikachu = $(`#${namespace}-pixel-art--pikachu`);
const $pixelArtPokeball = $(`#${namespace}-pixel-art--pokeball`);

const $colorPicker = $(`#${namespace}-color-picker`);

const $sizePicker = $(`#${namespace}-size-picker`);
const $sizePickerWidth = $(`#${namespace}-size-picker--width`);
const $sizePickerHeight = $(`#${namespace}-size-picker--height`);
const $sizePickerSubmit= $(`#${namespace}-size-picker--submit`);

const $toolPaint = $(`#${namespace}-tool--paint`);
const $toolDipper = $(`#${namespace}-tool--dipper`);
const $toolEraser = $(`#${namespace}-tool--eraser`);

const $table = $(`#${namespace}-table`);

const $helpViewBody = $(`#${namespace}-help--view--body`);

const $tooltip = $("[data-toggle='tooltip']");

/********************************************//**
 * Model
 ***********************************************/

/**
 * @desc Holds the pixel art
 */
const pixel = [
  {
    name: "ピカチュー",
    modal: {
      id: `${namespace}-pixel-art--modal--pikachu`
    },
    width: 28,
    height: 24,
    color: {
      picker: "#FFEA00",
      background: "#FFEA00"
    },
    art: [
      {
        // Black
        color: "#000000",
        pixel: [
          {tr: 1, td: 1},
          {tr: 1, td: 2},
          {tr: 1, td: 27},
          {tr: 1, td: 28},
          {tr: 2, td: 1},
          {tr: 2, td: 2},
          {tr: 2, td: 3},
          {tr: 2, td: 4},
          {tr: 2, td: 25},
          {tr: 2, td: 26},
          {tr: 2, td: 27},
          {tr: 2, td: 28},
          {tr: 3, td: 1},
          {tr: 3, td: 2},
          {tr: 3, td: 3},
          {tr: 3, td: 5},
          {tr: 3, td: 24},
          {tr: 3, td: 26},
          {tr: 3, td: 27},
          {tr: 3, td: 28},
          {tr: 4, td: 1},
          {tr: 4, td: 2},
          {tr: 4, td: 3},
          {tr: 4, td: 6},
          {tr: 4, td: 7},
          {tr: 4, td: 22},
          {tr: 4, td: 23},
          {tr: 4, td: 26},
          {tr: 4, td: 27},
          {tr: 4, td: 28},
          {tr: 5, td: 2},
          {tr: 5, td: 3},
          {tr: 5, td: 8},
          {tr: 5, td: 21},
          {tr: 5, td: 26},
          {tr: 5, td: 27},
          {tr: 6, td: 2},
          {tr: 6, td: 3},
          {tr: 6, td: 9},
          {tr: 6, td: 10},
          {tr: 6, td: 13},
          {tr: 6, td: 14},
          {tr: 6, td: 15},
          {tr: 6, td: 16},
          {tr: 6, td: 19},
          {tr: 6, td: 20},
          {tr: 6, td: 26},
          {tr: 6, td: 27},
          {tr: 7, td: 3},
          {tr: 7, td: 11},
          {tr: 7, td: 12},
          {tr: 7, td: 17},
          {tr: 7, td: 18},
          {tr: 7, td: 26},
          {tr: 8, td: 4},
          {tr: 8, td: 25},
          {tr: 9, td: 4},
          {tr: 9, td: 25},
          {tr: 10, td: 5},
          {tr: 10, td: 7},
          {tr: 10, td: 22},
          {tr: 10, td: 24},
          {tr: 11, td: 6},
          {tr: 11, td: 23},
          {tr: 12, td: 6},
          {tr: 12, td: 23},
          {tr: 12, td: 7},
          {tr: 13, td: 5},
          {tr: 13, td: 8},
          {tr: 13, td: 9},
          {tr: 13, td: 20},
          {tr: 13, td: 21},
          {tr: 13, td: 24},
          {tr: 13, td: 6},
          {tr: 14, td: 5},
          {tr: 14, td: 7},
          {tr: 14, td: 9},
          {tr: 14, td: 10},
          {tr: 14, td: 19},
          {tr: 14, td: 20},
          {tr: 14, td: 22},
          {tr: 14, td: 24},
          {tr: 14, td: 23},
          {tr: 15, td: 5},
          {tr: 15, td: 7},
          {tr: 15, td: 8},
          {tr: 15, td: 9},
          {tr: 15, td: 10},
          {tr: 15, td: 19},
          {tr: 15, td: 20},
          {tr: 15, td: 21},
          {tr: 15, td: 22},
          {tr: 15, td: 24},
          {tr: 15, td: 6},
          {tr: 16, td: 5},
          {tr: 16, td: 8},
          {tr: 16, td: 9},
          {tr: 16, td: 14},
          {tr: 16, td: 15},
          {tr: 16, td: 20},
          {tr: 16, td: 21},
          {tr: 16, td: 24},
          {tr: 17, td: 4},
          {tr: 17, td: 25},
          {tr: 18, td: 4},
          {tr: 18, td: 12},
          {tr: 18, td: 14},
          {tr: 18, td: 15},
          {tr: 18, td: 17},
          {tr: 18, td: 25},
          {tr: 19, td: 4},
          {tr: 19, td: 13},
          {tr: 19, td: 14},
          {tr: 19, td: 15},
          {tr: 19, td: 16},
          {tr: 19, td: 25},
          {tr: 20, td: 5},
          {tr: 20, td: 13},
          {tr: 20, td: 16},
          {tr: 20, td: 24},
          {tr: 21, td: 6},
          {tr: 21, td: 13},
          {tr: 21, td: 16},
          {tr: 21, td: 23},
          {tr: 22, td: 7},
          {tr: 22, td: 8},
          {tr: 22, td: 14},
          {tr: 22, td: 15},
          {tr: 22, td: 21},
          {tr: 22, td: 22},
          {tr: 23, td: 9},
          {tr: 23, td: 10},
          {tr: 23, td: 11},
          {tr: 23, td: 18},
          {tr: 23, td: 19},
          {tr: 23, td: 20},
          {tr: 24, td: 12},
          {tr: 24, td: 13},
          {tr: 24, td: 14},
          {tr: 24, td: 15},
          {tr: 24, td: 16},
          {tr: 24, td: 17}
        ]
      },
      // Yellow
      {
        color: "#FFEA00",
        pixel: [
          {tr: 3, td: 4},
          {tr: 3, td: 25},
          {tr: 4, td: 4},
          {tr: 4, td: 5},
          {tr: 4, td: 24},
          {tr: 4, td: 25},
          {tr: 5, td: 4},
          {tr: 5, td: 5},
          {tr: 5, td: 6},
          {tr: 5, td: 7},
          {tr: 5, td: 22},
          {tr: 5, td: 23},
          {tr: 5, td: 24},
          {tr: 5, td: 25},
          {tr: 6, td: 4},
          {tr: 6, td: 5},
          {tr: 6, td: 6},
          {tr: 6, td: 7},
          {tr: 6, td: 8},
          {tr: 6, td: 21},
          {tr: 6, td: 22},
          {tr: 6, td: 23},
          {tr: 6, td: 24},
          {tr: 6, td: 25},
          {tr: 7, td: 4},
          {tr: 7, td: 5},
          {tr: 7, td: 6},
          {tr: 7, td: 7},
          {tr: 7, td: 8},
          {tr: 7, td: 9},
          {tr: 7, td: 10},
          {tr: 7, td: 13},
          {tr: 7, td: 14},
          {tr: 7, td: 15},
          {tr: 7, td: 16},
          {tr: 7, td: 19},
          {tr: 7, td: 20},
          {tr: 7, td: 21},
          {tr: 7, td: 22},
          {tr: 7, td: 23},
          {tr: 7, td: 24},
          {tr: 7, td: 25},
          {tr: 8, td: 5},
          {tr: 8, td: 6},
          {tr: 8, td: 7},
          {tr: 8, td: 8},
          {tr: 8, td: 9},
          {tr: 8, td: 10},
          {tr: 8, td: 11},
          {tr: 8, td: 12},
          {tr: 8, td: 13},
          {tr: 8, td: 14},
          {tr: 8, td: 15},
          {tr: 8, td: 16},
          {tr: 8, td: 17},
          {tr: 8, td: 18},
          {tr: 8, td: 19},
          {tr: 8, td: 20},
          {tr: 8, td: 21},
          {tr: 8, td: 22},
          {tr: 8, td: 23},
          {tr: 8, td: 24},
          {tr: 9, td: 5},
          {tr: 9, td: 6},
          {tr: 9, td: 7},
          {tr: 9, td: 8},
          {tr: 9, td: 9},
          {tr: 9, td: 10},
          {tr: 9, td: 11},
          {tr: 9, td: 12},
          {tr: 9, td: 13},
          {tr: 9, td: 14},
          {tr: 9, td: 15},
          {tr: 9, td: 16},
          {tr: 9, td: 17},
          {tr: 9, td: 18},
          {tr: 9, td: 19},
          {tr: 9, td: 20},
          {tr: 9, td: 21},
          {tr: 9, td: 22},
          {tr: 9, td: 23},
          {tr: 9, td: 24},
          {tr: 10, td: 6},
          {tr: 10, td: 8},
          {tr: 10, td: 9},
          {tr: 10, td: 10},
          {tr: 10, td: 11},
          {tr: 10, td: 12},
          {tr: 10, td: 13},
          {tr: 10, td: 14},
          {tr: 10, td: 15},
          {tr: 10, td: 16},
          {tr: 10, td: 17},
          {tr: 10, td: 18},
          {tr: 10, td: 19},
          {tr: 10, td: 20},
          {tr: 10, td: 21},
          {tr: 10, td: 23},
          {tr: 11, td: 7},
          {tr: 11, td: 8},
          {tr: 11, td: 9},
          {tr: 11, td: 10},
          {tr: 11, td: 11},
          {tr: 11, td: 12},
          {tr: 11, td: 13},
          {tr: 11, td: 14},
          {tr: 11, td: 15},
          {tr: 11, td: 16},
          {tr: 11, td: 17},
          {tr: 11, td: 18},
          {tr: 11, td: 19},
          {tr: 11, td: 20},
          {tr: 11, td: 21},
          {tr: 11, td: 22},
          {tr: 12, td: 7},
          {tr: 12, td: 8},
          {tr: 12, td: 9},
          {tr: 12, td: 10},
          {tr: 12, td: 11},
          {tr: 12, td: 12},
          {tr: 12, td: 13},
          {tr: 12, td: 14},
          {tr: 12, td: 15},
          {tr: 12, td: 16},
          {tr: 12, td: 17},
          {tr: 12, td: 18},
          {tr: 12, td: 19},
          {tr: 12, td: 20},
          {tr: 12, td: 21},
          {tr: 12, td: 22},
          {tr: 13, td: 6},
          {tr: 13, td: 7},
          {tr: 13, td: 10},
          {tr: 13, td: 11},
          {tr: 13, td: 12},
          {tr: 13, td: 13},
          {tr: 13, td: 14},
          {tr: 13, td: 15},
          {tr: 13, td: 16},
          {tr: 13, td: 17},
          {tr: 13, td: 18},
          {tr: 13, td: 19},
          {tr: 13, td: 22},
          {tr: 13, td: 23},
          {tr: 14, td: 6},
          {tr: 14, td: 11},
          {tr: 14, td: 12},
          {tr: 14, td: 13},
          {tr: 14, td: 14},
          {tr: 14, td: 15},
          {tr: 14, td: 16},
          {tr: 14, td: 17},
          {tr: 14, td: 18},
          {tr: 14, td: 23},
          {tr: 15, td: 6},
          {tr: 15, td: 11},
          {tr: 15, td: 12},
          {tr: 15, td: 13},
          {tr: 15, td: 14},
          {tr: 15, td: 15},
          {tr: 15, td: 16},
          {tr: 15, td: 17},
          {tr: 15, td: 18},
          {tr: 15, td: 23},
          {tr: 16, td: 6},
          {tr: 16, td: 7},
          {tr: 16, td: 10},
          {tr: 16, td: 11},
          {tr: 16, td: 12},
          {tr: 16, td: 13},
          {tr: 16, td: 16},
          {tr: 16, td: 17},
          {tr: 16, td: 18},
          {tr: 16, td: 19},
          {tr: 16, td: 22},
          {tr: 16, td: 23},
          {tr: 17, td: 5},
          {tr: 17, td: 6},
          {tr: 17, td: 9},
          {tr: 17, td: 10},
          {tr: 17, td: 11},
          {tr: 17, td: 12},
          {tr: 17, td: 13},
          {tr: 17, td: 14},
          {tr: 17, td: 15},
          {tr: 17, td: 16},
          {tr: 17, td: 17},
          {tr: 17, td: 18},
          {tr: 17, td: 19},
          {tr: 17, td: 20},
          {tr: 17, td: 23},
          {tr: 17, td: 24},
          {tr: 18, td: 5},
          {tr: 18, td: 10},
          {tr: 18, td: 11},
          {tr: 18, td: 13},
          {tr: 18, td: 16},
          {tr: 18, td: 18},
          {tr: 18, td: 19},
          {tr: 18, td: 24},
          {tr: 19, td: 5},
          {tr: 19, td: 10},
          {tr: 19, td: 11},
          {tr: 19, td: 12},
          {tr: 19, td: 17},
          {tr: 19, td: 18},
          {tr: 19, td: 19},
          {tr: 19, td: 24},
          {tr: 20, td: 6},
          {tr: 20, td: 9},
          {tr: 20, td: 10},
          {tr: 20, td: 11},
          {tr: 20, td: 12},
          {tr: 20, td: 17},
          {tr: 20, td: 18},
          {tr: 20, td: 19},
          {tr: 20, td: 20},
          {tr: 20, td: 23},
          {tr: 21, td: 7},
          {tr: 21, td: 8},
          {tr: 21, td: 9},
          {tr: 21, td: 10},
          {tr: 21, td: 11},
          {tr: 21, td: 12},
          {tr: 21, td: 17},
          {tr: 21, td: 18},
          {tr: 21, td: 19},
          {tr: 21, td: 20},
          {tr: 21, td: 21},
          {tr: 21, td: 22},
          {tr: 22, td: 9},
          {tr: 22, td: 10},
          {tr: 22, td: 11},
          {tr: 22, td: 12},
          {tr: 22, td: 13},
          {tr: 22, td: 16},
          {tr: 22, td: 17},
          {tr: 22, td: 18},
          {tr: 22, td: 19},
          {tr: 22, td: 20},
          {tr: 23, td: 12},
          {tr: 23, td: 13},
          {tr: 23, td: 14},
          {tr: 23, td: 15},
          {tr: 23, td: 16},
          {tr: 23, td: 17}
        ]
      },
      // Red
      {
        color: "#FF0000",
        pixel: [
          {tr: 17, td: 7},
          {tr: 17, td: 8},
          {tr: 17, td: 21},
          {tr: 17, td: 22},
          {tr: 18, td: 6},
          {tr: 18, td: 7},
          {tr: 18, td: 8},
          {tr: 18, td: 9},
          {tr: 18, td: 20},
          {tr: 18, td: 21},
          {tr: 18, td: 22},
          {tr: 18, td: 23},
          {tr: 19, td: 6},
          {tr: 19, td: 7},
          {tr: 19, td: 8},
          {tr: 19, td: 9},
          {tr: 19, td: 20},
          {tr: 19, td: 21},
          {tr: 19, td: 22},
          {tr: 19, td: 23},
          {tr: 20, td: 7},
          {tr: 20, td: 8},
          {tr: 20, td: 14},
          {tr: 20, td: 15},
          {tr: 20, td: 21},
          {tr: 20, td: 22},
          {tr: 21, td: 14},
          {tr: 21, td: 15}
        ]
      },
      // White
      {
        color: "#FFFFFF",
        pixel: [
          {tr: 14, td: 8},
          {tr: 14, td: 21},
        ]
      }
    ]
  },
  {
    name: "Pokeball",
    modal: {
      id: `${namespace}-pixel-art--modal--pokeball`
    },
    width: 14,
    height: 14,
    color: {
      picker: "#FF0000",
      background: "#FF0000"
    },
    art: [
      {
        color: "#000000",
        pixel: [
          {tr: 1, td: 6},
          {tr: 1, td: 7},
          {tr: 1, td: 8},
          {tr: 1, td: 9},
          {tr: 2, td: 4},
          {tr: 2, td: 5},
          {tr: 2, td: 10},
          {tr: 2, td: 11},
          {tr: 3, td: 3},
          {tr: 3, td: 12},
          {tr: 4, td: 2},
          {tr: 4, td: 13},
          {tr: 5, td: 2},
          {tr: 5, td: 13},
          {tr: 6, td: 1},
          {tr: 6, td: 7},
          {tr: 6, td: 8},
          {tr: 6, td: 14},
          {tr: 7, td: 1},
          {tr: 7, td: 6},
          {tr: 7, td: 9},
          {tr: 7, td: 14},
          {tr: 8, td: 1},
          {tr: 8, td: 2},
          {tr: 8, td: 3},
          {tr: 8, td: 4},
          {tr: 8, td: 5},
          {tr: 8, td: 6},
          {tr: 8, td: 9},
          {tr: 8, td: 10},
          {tr: 8, td: 11},
          {tr: 8, td: 12},
          {tr: 8, td: 13},
          {tr: 8, td: 14},
          {tr: 9, td: 1},
          {tr: 9, td: 7},
          {tr: 9, td: 8},
          {tr: 9, td: 14},
          {tr: 10, td: 2},
          {tr: 10, td: 13},
          {tr: 11, td: 2},
          {tr: 11, td: 13},
          {tr: 12, td: 3},
          {tr: 12, td: 12},
          {tr: 13, td: 4},
          {tr: 13, td: 5},
          {tr: 13, td: 10},
          {tr: 13, td: 11},
          {tr: 14, td: 6},
          {tr: 14, td: 7},
          {tr: 14, td: 8},
          {tr: 14, td: 9}
        ]
      },
      {
        color: "#FF0000",
        pixel: [
          {tr: 2, td: 6},
          {tr: 2, td: 7},
          {tr: 2, td: 8},
          {tr: 2, td: 9},
          {tr: 3, td: 4},
          {tr: 3, td: 5},
          {tr: 3, td: 6},
          {tr: 3, td: 7},
          {tr: 3, td: 8},
          {tr: 3, td: 9},
          {tr: 3, td: 10},
          {tr: 3, td: 11},
          {tr: 4, td: 3},
          {tr: 4, td: 4},
          {tr: 4, td: 5},
          {tr: 4, td: 6},
          {tr: 4, td: 7},
          {tr: 4, td: 8},
          {tr: 4, td: 9},
          {tr: 4, td: 10},
          {tr: 4, td: 11},
          {tr: 4, td: 12},
          {tr: 5, td: 3},
          {tr: 5, td: 4},
          {tr: 5, td: 5},
          {tr: 5, td: 6},
          {tr: 5, td: 7},
          {tr: 5, td: 8},
          {tr: 5, td: 9},
          {tr: 5, td: 10},
          {tr: 5, td: 11},
          {tr: 5, td: 12},
          {tr: 6, td: 2},
          {tr: 6, td: 3},
          {tr: 6, td: 4},
          {tr: 6, td: 5},
          {tr: 6, td: 6},
          {tr: 6, td: 9},
          {tr: 6, td: 10},
          {tr: 6, td: 11},
          {tr: 6, td: 12},
          {tr: 6, td: 13},
          {tr: 7, td: 2},
          {tr: 7, td: 3},
          {tr: 7, td: 4},
          {tr: 7, td: 5},
          {tr: 7, td: 10},
          {tr: 7, td: 11},
          {tr: 7, td: 12},
          {tr: 7, td: 13}
        ]
      }
    ]
  }
];

/**
 * @desc Keeps track of which tool is active
 * TODO: Test if JS design module can be used.
 */
const tool = {
  paint: true,
  dipper: false,
  eraser: false,
  painting: function() {
    this.paint = true,
    this.dipper = false,
    this.eraser = false
  },
  dipping: function() {
    this.paint = false;
    this.dipper = true;
    this.eraser = false;
  },
  erasing: function() {
    this.paint = false;
    this.dipper = false;
    this.eraser = true;
  }
};

/**
 * @desc Converts rgb to hex
 * @param {string} color_value Takes a string in rgb format
 */
function rgba2hex(color_value) {
	if (!color_value) return false;
	let parts = color_value.toLowerCase().match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/),
	    length = color_value.indexOf('rgba') ? 3 : 2; // Fix for alpha values
	delete(parts[0]);
	for (var i = 1; i <= length; i++) {
		parts[i] = parseInt( parts[i] ).toString(16);
		if (parts[i].length == 1) parts[i] = '0' + parts[i];
	}
	return '#' + parts.join('').toUpperCase(); // #F7F7F7
}

/********************************************//**
 * Controller
 ***********************************************/

 /**
  * @desc Creates the pixel art links
  * Creates the table on load
  * Creates the help documentation
  * Makes the bootstrap tooltip work
  */
$(_ => {
  drawPixel(pixel[0]);
  $tooltip.tooltip();
});

/**
 * @desc Saves the file to a png
 */
$savePNG.click(_ => {
  html2canvas($table, {
    onrendered: function (canvas) {
      const a = document.createElement('a');
      a.href = canvas.toDataURL();
      a.download = 'pixelart.png';
      a.click();
    }
  });
});

/**
 * @desc Saves the file to a jpeg
 */
$saveJPEG.click(_ => {
  html2canvas($table, {
    onrendered: function (canvas) {
      const a = document.createElement('a');
      a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
      a.download = 'pixelart.jpeg';
      a.click();
    }
  });
});

/**
 * @desc Deletes the table children
 */
$deleteButton.click(_ => clearTableChildren());

/**
 * @desc Restores border
 * Can't use saved DOM selectors yet
 * TODO: Figure out how to use save DOM selectors
 */
$borderDefault.click(_ => {
    $(`#${namespace}-table`).css("border", "");
    $(`#${namespace}-table tr`).css("border", "");
    $(`#${namespace}-table td`).css("border", "");
});

/**
 * @desc Removes border
 * Can't use saved DOM selectors yet
 * TODO: Figure out how to use save DOM selectors
 */
$borderLess.click(_ => {
  $(`#${namespace}-table tr`).css("border", "none");
  $(`#${namespace}-table td`).css("border", "none");
});

/**
 * @desc Changes the colors of the border
 * Can't use saved DOM selectors yet
 * TODO: Figure out how to use save DOM selectors
 */
$borderColor.on("click change", _ => {
  $(`#${namespace}-table`).css("border-color", $borderColor.val());
  $(`#${namespace}-table tr`).css("border-color", $borderColor.val());
  $(`#${namespace}-table td`).css("border-color", $borderColor.val());
});

/**
 * @desc Creates the piakchu pixel art
 * @param {object} pixel[0] Object with pikachu art
 */
$pixelArtPikachu.click(_ => drawPixel(pixel[0]));

/** 
 * @desc Creates the pokeball pixel art
 * @param {object} pixel[1] Object with pokeball art
 */
$pixelArtPokeball.click(_ => drawPixel(pixel[1]));

/**
 * @desc Submits the form
 */
$sizePickerSubmit.click(_ => $sizePicker.submit());

/**
 * @desc On submit of the form, creates a table
 * @param {event} event Uses the event to prevent default of the form
 */
$sizePicker.on("submit", event => {
  event.preventDefault();
  setTable($sizePickerWidth.val(), $sizePickerHeight.val());
});

/**
 * @desc Sets the paint tool to true and active
 */
$toolPaint.on("click", _ => {
  tool.painting();
  toolSetClass(tool);
});

/**
 * @desc Sets the dipper tool to true and active
 */
$toolDipper.on("click", _ => {
  tool.dipping();
  toolSetClass(tool);
});

/**
 * @desc Sets the erase tool to true and active
 */
$toolEraser.on("click", _ => {
  tool.erasing();
  toolSetClass(tool);
});

/**
 * @desc Allows to paint on the table
 * @param {event} event Uses the event target to select each td
 * @param {boolean} down Used to determine if the paintTool should be active
 * @param {object} tool Used to determine which tool is active
 */
(_ => {
  let down = false;
  $table.on("mousedown", "td", event => {
    down = true;
    toolBar(event, down, tool);
  }).on("mouseover", "td", event => toolBar(event, down, tool))
  .on("mouseup", _ => down = false)
  .on("mouseleave", _ => down = false);
})();

/**
 * @desc Erases the background color to default on double click
 */
$table.on("dblclick", "td", event => {
  $(event.target).css("background-color", "");
});

/********************************************//**
 * View
 ***********************************************/
/**
 * @desc Changes the classes tools
 */
function toolSetClass(ele) {
  if (ele.paint === true) {
    $toolPaint.addClass("active");
  } else if (ele.paint === false) {
    $toolPaint.removeClass("active");
  }

  if (ele.dipper === true) {
    $toolDipper.addClass("active");
  } else if (ele.dipper === false) {
    $toolDipper.removeClass("active");
  }

  if (ele.eraser === true) {
    $toolEraser.addClass("active");
  } else if (ele.eraser === false) {
    $toolEraser.removeClass("active");
  }
}

/**
 * @desc Paints the canvas table
 * @param {event} event Sets the event from the target
 * @param {boolean} down Sets if the tool should be active
 * @param {object} tool Uses data from the object for which to use
 */
function toolBar(event, down, tool) {
  if (down) {
    if (tool.paint === true) {
      $(event.target).css("background-color", $colorPicker.val());
    } else if (tool.dipper === true) {
      const hex = rgba2hex($(event.target).css("background-color"));
      $colorPicker.val(hex);
    } else if (tool.eraser === true) {
      $(event.target).css("background-color", "");
    }
  }
}

/**
 * @desc Removes table children
 */
function clearTableChildren() {$table.empty();}

/**
 * @desc Creates the table
 * @param {number} width Takes a number to create the columns
 * @param {number} height Takes a number to create the rows
 */
function setTable(width, height) {
  const tbody = document.createElement("tbody");
  clearTableChildren();
  for (let i = 0; i < height; i++) {
    const row = tbody.insertRow(i);
    for (let j = 0; j < width; j++) {
      const cell = row.insertCell(j);
    }
  }
  $table.append(tbody);
}

/**
 * @desc Makes the pixel art.
 * @param {object} ele Takes an object to draw the art.
 */
function drawPixel(ele) {
  $sizePickerWidth.val(ele.width);
  $sizePickerHeight.val(ele.height);
  $colorPicker.val(ele.color.picker);
  setTable(ele.width, ele.height);
  ele.art.forEach(ele1 => {
    ele1.pixel.forEach(ele2 => {
      $(`tr:nth-child(${ele2.tr}) td:nth-child(${ele2.td})`).css("background", ele1.color);
    });
  });
}

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console