[Lab Javascstip] -Một ứng dụng nhỏ JavaScript WYSIWYG Editor

Nội dung bài viết

Video học lập trình mỗi ngày

Xin chào cộng đồng javascsript. 

Mình là Thành Nam, là một thành viên mới của cộng đồng javascript anonystick. Chúc tất cả các bạn có một bài đọc thật vui vẻ. 

Để tiếp theo "Cuộc thi ứng dụng nhỏ sử dụng javascript" những ví dụ chỉ dùng javascript thì bài này mình sẽ giới thiệu cho các bạn một ứng dụng mà mình đã tham khảo rất nhiều nơi. Đó là ứng dụng editor WYSIWYG. 

WYSIWYG là gì? 

WYSIWYG (viết tắt của What You See Is What You Get trong tiếng Anh), thường được dịch là "những gì bạn đang thấy là những gì bạn sẽ nhận được" và hiểu như là "Giao diện tương tác tức thời - mắt thấy tay làm", thường được dùng trong các chương trình ứng dụng văn phòng, các chương trình biên soạn, thiết kế web... Các công cụ dùng giao diện này cho phép ta có thể thấy ngay những thay đổi mà người viết mã, hay một thiết kế viên web vừa thực hiện, nhằm tiết kiệm thời gian chỉnh sửa các lỗi hay những điểm không ưng ý một cách dễ dàng và nhanh chóng.

Hình ảnh demo: 

editor su dung javascript

Code demo và source full: các bạn xem dưới bài viết nhé.

Mình copy source rất chi tiết các bạn tham khảo và add vào page của mình nếu cần.

1 - HTML

<html>
  <head>
    <title>Editor</title>
    <link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet">
    <script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
  </head>
  <body onload="wisiwyg.init()">
  <a target='_blank' href="https://anonystick.com"><h1>Demo Editor</h1></a>
  <div id="editor-wrapper">
    <ul class="tabs">
      <li onClick="tab.editor(this)" class="active"> <i class="fa fa-edit"></i> Editor</li>
      <li onClick="tab.code(this)"> <i class="fa fa-code"></i> Code</li>
    </ul>
    <ul class="toolbar">
      <li data-cmd="clean"> <i class="fa fa-file"></i> </li>
      <li data-cmd="undo"> <i class="fa fa-undo"></i> </li>
      <li data-cmd="redo"> <i class="fa fa-redo"></i> </li>
      <li data-cmd="removeFormat"> <i class="fa fa-eraser"></i> </li>
      <li data-cmd="bold"> <i class="fa fa-bold"></i> </li>
      <li data-cmd="italic"> <i class="fa fa-italic"></i> </li>
      <li data-cmd="underline"> <i class="fa fa-underline"></i> </li>
      <li data-cmd="justifyleft"> <i class="fa fa-align-left"></i> </li>
      <li data-cmd="justifycenter"> <i class="fa fa-align-center"></i> </li>
      <li data-cmd="justifyright"> <i class="fa fa-align-right"></i> </li>
      <li data-cmd="insertorderedlist"><i class="fa fa-list-ol"></i></li>
      <li data-cmd="insertunorderedlist"><i class="fa fa-list-ul"></i></li>
      <li data-cmd="formatblock" data-args="blockquote"><i class="fa fa-quote-left"></i></li>
      <li data-cmd="outdent"><i class="fa fa-outdent"></i></li>
      <li data-cmd="indent"><i class="fa fa-indent"></i></li>
      <li data-cmd="createlink"><i class="fa fa-link"></i></li>
      <li data-cmd="cut"><i class="fa fa-cut"></i></li>
      <li data-cmd="copy"><i class="fa fa-copy"></i></li>
      <li data-cmd="paste"><i class="fa fa-paste"></i></li>
      <li data-cmd="fontSize"><i class="fa fa-text-height"></i></li>
      <li data-cmd="fontName"> <i class="fa fa-font"></i> </li>
    </ul>
    <div id="editor" class="editor" contentEditable="true" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></div>
    <div class="footer">
      Created By Ahmet BEDİR
    </div>
  </div>
</body>
</html>

2 - CSS

body{
  margin:0;
  padding:0;
  font-family:arial,sans-serif;
  -webkit-user-select:none;
  background-color:#111;
  
  a{    
    text-decoration: none;    
    h1{
      text-align:center;
      color:#FFDD1B;
      font-family: 'Pacifico', cursive;
      -webkit-transition: all 0.5s;
      -moz-transition: all 0.5s;
      transition: all 0.5s;
      cursor:pointer;      
      -webkit-animation: neon 1.5s ease-in-out infinite alternate;
      -moz-animation: neon 1.5s ease-in-out infinite alternate;
      animation: neon 1.5s ease-in-out infinite alternate;

      &:hover{
        color:#c03;
        -webkit-animation: neon1 1.5s ease-in-out infinite alternate;
        -moz-animation: neon1 1.5s ease-in-out infinite alternate;
        animation: neon1 1.5s ease-in-out infinite alternate;
      }
    }
  }
  
  ul,li{
    list-style:none;
    margin:0;
    padding:0;
  }
  
  #editor-wrapper{  
    width: calc(100vw / 1.5);
    margin: 20px auto;  
    border:2px solid #ddd;
    border-radius: 3px;
    overflow:hidden;
    ul.tabs {
      overflow:auto;
      background: #eee;
      li{
        padding:7px 20px;
        float:left;
        cursor:pointer;

        &.active{
          background-color:#ddd; 
        }      
        &:hover{
          background-color:#bbb;
        }
      }
    }
    ul.toolbar {
      border-top:2px solid #ddd;
      overflow:auto;
      background: #f1f1f1; 
      li{
        padding:7px 10px;
        float:left;
        cursor:pointer;

        &.active{
          background-color:#ddd; 
        }      
        &:hover{
          background-color:#bbb;
        }
      }
    }
    .editor{
      background-color:#fff;
      width:99%;
      min-height:200px;
      height:calc(100vh / 2.5);
      overflow:auto;
      padding:5px;
      border-top:2px solid #ddd;
      resize:vertical;
      outline:none;
    }
    .footer{
      border-top:2px solid #ddd;
      background-color:#eee;
      text-align:right;
      padding:3px 15px;
      font-size:12px;
      color:#aaa;       
      font-family: 'Pacifico', cursive;
    }
  }
  
}




@-webkit-keyframes neon {
  from {
    text-shadow: 0 0 10px #111, 0 0 20px #111, 0 0 30px #111, 0 0 40px #FFDD1B, 0 0 70px #FFDD1B, 0 0 80px #FFDD1B, 0 0 100px #FFDD1B, 0 0 150px #FFDD1B;
  }
  to {
    text-shadow: 0 0 5px #111, 0 0 10px #111, 0 0 15px #111, 0 0 20px #FFDD1B, 0 0 35px #FFDD1B, 0 0 40px #FFDD1B, 0 0 50px #FFDD1B, 0 0 75px #FFDD1B;
  }
}

@-moz-keyframes neon {
  from {
    text-shadow: 0 0 10px #111, 0 0 20px #111, 0 0 30px #111, 0 0 40px #FFDD1B, 0 0 70px #FFDD1B, 0 0 80px #FFDD1B, 0 0 100px #FFDD1B, 0 0 150px #FFDD1B;
  }
  to {
    text-shadow: 0 0 5px #111, 0 0 10px #111, 0 0 15px #111, 0 0 20px #FFDD1B, 0 0 35px #FFDD1B, 0 0 40px #FFDD1B, 0 0 50px #FFDD1B, 0 0 75px #FFDD1B;
  }
}


@keyframes neon {
  from {
    text-shadow: 0 0 10px #111, 0 0 20px #111, 0 0 30px #111, 0 0 40px #FFDD1B, 0 0 70px #FFDD1B, 0 0 80px #FFDD1B, 0 0 100px #FFDD1B, 0 0 150px #FFDD1B;
  }
  to {
    text-shadow: 0 0 5px #111, 0 0 10px #111, 0 0 15px #111, 0 0 20px #FFDD1B, 0 0 35px #FFDD1B, 0 0 40px #FFDD1B, 0 0 50px #FFDD1B, 0 0 75px #FFDD1B;
  }
}

@-webkit-keyframes neon1 {
  from {
    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #FF1177, 0 0 70px #FF1177, 0 0 80px #FF1177, 0 0 100px #FF1177, 0 0 150px #FF1177;
  }
  to {
    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #FF1177, 0 0 35px #FF1177, 0 0 40px #FF1177, 0 0 50px #FF1177, 0 0 75px #FF1177;
  }
}

@-moz-keyframes neon1 {
  from {
    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #FF1177, 0 0 70px #FF1177, 0 0 80px #FF1177, 0 0 100px #FF1177, 0 0 150px #FF1177;
  }
  to {
    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #FF1177, 0 0 35px #FF1177, 0 0 40px #FF1177, 0 0 50px #FF1177, 0 0 75px #FF1177;
  }
}

@keyframes neon1 {
  from {
    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #FF1177, 0 0 70px #FF1177, 0 0 80px #FF1177, 0 0 100px #FF1177, 0 0 150px #FF1177;
  }
  to {
    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #FF1177, 0 0 35px #FF1177, 0 0 40px #FF1177, 0 0 50px #FF1177, 0 0 75px #FF1177;
  }
}



Source code tai day : Download Source Code

Demo Tai day : See Demo Here


3 - Javascript

var wisiwyg = {
  init:  function(){
    wisiwyg.editor = document.getElementById("editor");
    
    Array.from(document.querySelectorAll('.toolbar li')).forEach(function(toolbar){
      toolbar.addEventListener("click", function(){
        var cmd = this.dataset.cmd, args = this.dataset.args;
            
        wisiwyg.command(cmd, args);
      });
    });
  },
  command: function(cmd, args){    
    args = cmd == 'clean' ? wisiwyg.editor.innerHTML='' : args;
    args = cmd == 'createlink' ? prompt("URL:","http://") : args;
    args = cmd == 'fontSize' ? prompt("Font-Size (1-7):","3") : args;
    args = cmd == 'fontName' ? prompt("Font-Name:","Arial") : args;
    
    document.execCommand(cmd, false, args);
    wisiwyg.editor.focus(); 
  }
}

var tab = {
  editor: function(e){
    if(e.classList == 'active') return ;
    wisiwyg.editor.innerHTML = wisiwyg.editor.innerText;
    tab.activate(0);
  },
  code: function(e){
    if(e.classList == 'active') return ;
    wisiwyg.editor.innerText = wisiwyg.editor.innerHTML;
    tab.activate(1);
  },
  activate: function(index){
    document.querySelector(".tabs li.active").classList.remove("active");
    var tabs = document.querySelectorAll(".tabs li");
    tabs[index].classList.add('active');
  }
}

Source code tai day : Download Source Code

Demo Tai day : See Demo Here

Nguồn tham khảo tại: 

Copyright (c) 2019 by thanhnam (https://codepen.io/thanhnam/pen/OGvwGq) 

Fork of an original work by Ahmet Bedir (https://codepen.io/ahmetbedir/pen/xYwYEP)

Có thể bạn đã bị missing