Inputs Outputs Visualization

Angular @Inputs and @Outputs visualization of presentation components

by kontrach

HTML

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<div class="code">
  <p class='component-first-line'>
    @<span class="decorator">Component</span> ({
  </p>
  <div class="metadata">
    <p class="selector-part">
      <span class="props">
        selector:
      </span>
      &nbsp;
      <span class="string">
        '
        <span class="selector">user-card</span>
        '
      </span>,
    </p>
    <div class="template-part">
      <span class="props">
        template:
      </span>
      &nbsp;<span class="string">`</span>
        <pre class="string template">  &lt;p&gt;
    &lt;span&gt;Name: {{person.name}}&lt;/span&gt;
    &lt;span&gt;Age: {{person.age}}&lt;/span&gt;
    &lt;button (click)="addAge.emit()"&gt;Add age&lt;/button&gt;
  &lt;/p&gt;</pre>
      <span class="string">`</span>
    </div>
  </div>
})
<div class="class">
  <span class="export">export</span> 
  <span class="decorator">class</span> 
  <span class="className">PresentationalComponent</span> {
  <div class="class-body">
    <p class="input-line">
      @<span class="decorator">Input</span>() 
      <span class="props">person</span>: 
      <span class="className">Person</span>;
    </p>
    <p class="output-line">
      @<span class="decorator">Output</span>() 
      <span class="props">addAge</span> = 
      <span class="decorator">new</span> 
      <span class="className">EventEmitter</span>();
    </p>
  </div>
</div>
}
</div>

<button class="next-step">Next step</button><button class="clear-queue">
Clear Queue
</button>

SCSS

p, pre{margin:0 0 5px 0;}
.code {
  color: black;
  font-size: 1.2em;
  position: relative;
  .props {
    color: blue;
  }
  .string {
    color: brown;
  }
  .decorator{
    color: darkblue;
  }
  .metadata{
    padding-left: 20px;
  }
  .template-part{
    position: relative;
  }
  .template.copy{
    top: 0;
    left: 0;
    position: absolute;
  }
  .export{
    color: purple;
  }
  .className{
    color: darkgreen;
  }
  .class-body{
    padding-left:15px;
  }
  .props.copy{
    position: absolute;
  }
}

.selector {
  position: relative;
}
.open-tag,
.close-tag{
  position: absolute;
  &:before{
    font-weight: bold;
  }
  &:after{
    content:'>';
    font-weight: bold;
    float: right;
  }
}

.open-tag{
  &:before{
    content:'<';
  }
}
.close-tag{
  &:before{
    content:'</';
  }
}

JavaScript

const $selector = $('.selector');
const $openTag = $selector.clone();
const $template = $('.template');
const $templateCopy = $template.clone().addClass('copy');
const $nextBtn = $('.next-step');
let $closeTag;

const config = {
  delay: 900
}

let clicksNum = 0;
let n;

$nextBtn.click(function(){
  if (clicksNum === 0) {
    registerQueue();
    n = $openTag.queue( "fx" );
  }
  clicksNum++;
  console.info(Math.abs(n.length - 4))
  console.dir(n);
  $openTag.dequeue();
});

$('.clear-queue').click(() => {
  $openTag
    .clearQueue()
    .queue([
      moveOpeningTagToRight,
      addClosingTag,
      moveClosingTagToRight,
      putClosingTagDown,
      putTemplateInsideTag
    ])
})

function registerQueue(){
	$openTag
    .queue(moveOpeningTagToRight)
    .queue(addClosingTag)
    .queue(moveClosingTagToRight)
    .queue(putClosingTagDown)
    .queue(putTemplateInsideTag)
    .queue(addInput)
    .queue(addOutput)
    //.queue(function(){
    //console.log($(this));
      //$(this).animate({width:'+=30'}, config.delay).dequeue();
    //});

}

function moveOpeningTagToRight(){
	$selector.after($openTag.addClass('open-tag'));
  $openTag
    .animate({left: '+=300'}, config.delay)
}

function addClosingTag(){
	$closeTag = $openTag.clone();
  $closeTag
    .addClass('close-tag')
    .removeClass('open-tag');
  
	$openTag
    .after($closeTag)
    .dequeue();
}

function moveClosingTagToRight(){
  $closeTag
    .animate(
      {left: '+=100'},
      config.delay
    );
}

function putClosingTagDown(){
  $closeTag
    .animate({
        left: '-=100',
        top: '+=115'
      }, 
      config.delay, 
      () => $(this).dequeue()
    );
}

function putTemplateInsideTag(){
  $template.after($templateCopy);
  $templateCopy
    .animate({
      left: '+=460'
    }, config.delay); 
}

function addInput(){
  $input = $('.input-line .props');
  $inputCopy = $input.clone().addClass('copy');
  $input.after( $inputCopy );
  
  $inputCopy
    .animate({
      left:...