Привет всем читателем Habr. В данной статье мы будем продолжать писать свой онлайн редактор кода.

В этой статье мы сделаем функцию сохранения кода в localStorage и по обновлению страницы этот код будет вставляться в эти 3 поля, а также сделаем функцию скачивания этого кода в виде файла.

Изменения кода с первой части


В прошлой части в комментариях один пользователь попросил сделать задержку перед проигрыванием кода.

Новый код:

var htmlEditor = ace.edit("html-editor");
htmlEditor.setTheme("ace/theme/monokai");
htmlEditor.session.setMode("ace/mode/html");

var cssEditor = ace.edit("css-editor");
cssEditor.setTheme("ace/theme/monokai");
cssEditor.session.setMode("ace/mode/css");

var jsEditor = ace.edit("js-editor");
jsEditor.setTheme("ace/theme/monokai");
jsEditor.session.setMode("ace/mode/javascript");

function playCode() {

htmlEditor.getSession().on('change', function() {
 update();
})
cssEditor.getSession().on('change', function() {
 update();
})
jsEditor.getSession().on('change', function() {
 update();
})

function update() {
var res = document.getElementById('result').contentWindow.document;
res.open();
res.write('<style>' + cssEditor.getValue() + '</style>');
res.write('<script>' + jsEditor.getValue() + '</script>');
res.write(htmlEditor.getValue());
res.close();
}
}
setTimeout(playCode, 2000);

Теперь приступаем к новому коду.

Сохранения кода в localStorage


Перед js кодом мы создадим кнопку, которая по нажатию будет сохранять код

<ul>
<li class="save" id="save_code"> Сохранить</li>
</ul>

Сейчас мы добавим код, который будет отправлять данные в localStorage, а потом брать их.

var saveBtn = document.getElementById('save_code');
  saveBtn.addEventListener("click", () => {
    var htmlSave = htmlEditor.getValue();
    var cssSave = cssEditor.getValue();
    var jsSave = jsEditor.getValue();
    localStorage.setItem('htmlSave', htmlSave);
    localStorage.setItem('cssSave', cssSave);
    localStorage.setItem('jsSave', jsSave);

    alert('Код сохранен!');
  });

  window.onload = () => {
    var htmlSave = (localStorage.getItem("htmlSave"));
    var cssSave = (localStorage.getItem("cssSave"));
    var jsSave = (localStorage.getItem("jsSave"));
      htmlEditor.session.replace(new ace.Range(0, 0, 1, 1), htmlSave);
      cssEditor.session.replace(new ace.Range(0, 0, 1, 1), cssSave);
      jsEditor.session.replace(new ace.Range(0, 0, 1, 1), jsSave);
    }

Функции каждой строки:

localStorage.setItem('htmlSave', htmlSave); — этот код выполняет отправку html кода в localStorage, где 'htmlSave' — это название переменной в localStorage, а htmlSave — это переменная, которая берет код из поля (мы ее вызвали здесь: var htmlSave = htmlEditor.getValue();)

localStorage.getItem(«htmlSave») — этот код достает переменную htmlSave из localStorage.

htmlEditor.session.replace(new ace.Range(0, 0, 1, 1), htmlSave); — меняет код из поля из заменяет его на код из localStorage.

Скачивания кода


Теперь мы создадим функцию, которая будет скачивать html, css, js код в виде файла, но перед этим нам надо сделать разметку html.

<ul>
<li id="save_code"> Сохранить</li>
<li id="download_html"> Скачать Html файл</li>
<li id="download_css"> Скачать Css файл</li>
<li id="download_js"> Скачать Js файл</li>

                     		</li>
</ul>

Сейчас нам надо сделать функцию, которая будет скачивать файл. Чтобы не прописывать один и тот же код несколько раз мы сделаем одну функцию и вызовем ее 3 раза с разными данными.

  var htmlDownload = document.getElementById('download_html');
    var cssDownload = document.getElementById('download_css');
    var jsDownload = document.getElementById('download_js');


function download(clickElm, variable, fileType, fileName) {
    this.clickElm = clickElm;
    this.variable = variable;
    this.fileType = fileType;
    this.fileName = fileName;

    clickElm.addEventListener("click", () => {
        var code = ace.edit(variable);
        var textToWrite = code.getValue();
        var textFileAsBlob = new Blob([textToWrite], {type:fileType});
        var fileNameToSaveAs = fileName;
      
        var downloadLink = document.createElement("a");
        downloadLink.download = fileNameToSaveAs;
        downloadLink.innerHTML = "Download File";
        if (window.webkitURL != null)
        {
          downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else
        {
          downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
          downloadLink.onclick = destroyClickedElement;
          document.body.appendChild(downloadLink);
        }
      
        downloadLink.click();
      });
}

function destroyClickedElement(event)
{
  document.body.removeChild(event.target);
}

У функции download, мы указали аргументы, которые будет вызываться у не повторяющийся элементов, из них:

  • clickElm — элемент по которому произойдет клик.
  • variable — переменная, которая берет данные из поля.
  • fileType — тип файла при скачивании
  • fileName- имя файла

Теперь нам нужно вызвать функцию 3 раза для скачивания html, css и js файла.

download(htmlDownload, "html-editor", "text/plain", "index.html");
download(cssDownload, "css-editor", "text/plain", "style.css");
download(jsDownload, "js-editor", "text/js", "app.js");

Вот и все.

Редактор, который у нас получится — Редактор кода онлайн.

Комментарии (8)


  1. interprise
    01.02.2019 22:32

    Если убрать галочку «Авто проигрыватель», то выполняется воспроизведение. не думаю что это логичное поведение. И не плохо бы залить это на гитхаб, не скажу что это что-то уникальное, но без гит хаба жизни нету.


    1. Rapprogtrain Автор
      01.02.2019 23:47

      я думаю к 3 части уже успею залить на github


      1. zivgta
        02.02.2019 00:59

        У меня одного не работает выполнение js? Проверяю в консоли на вашем же сайте — работает, пишу в поле для js — нет


        1. Rapprogtrain Автор
          02.02.2019 12:30

          А ты списал код с первой части?


          1. zivgta
            02.02.2019 14:27

            Я зашёл на твой сайт в конце статьи и там пробовал)


  1. ddinochrome
    02.02.2019 14:10

    Интересная разработка с концептуальной точки зрения — получается, что веб-страница может изменять сама себя в реальном времени. Мне нравится) Ещё порадовал многопользовательский режим.
    Единственное, на мой взгляд для полноты функционала не хватает функции «Экспортировать», которая собирает 3 куска кода в единую рабочую хтмл-страницу и сохраняет её на диск в работоспособном состоянии. Тогда можно будет поработать над веб-страничкой с коллегами (например, художником и верстальщиком), сэкспортировать её в файл и выложить на свой хостинг без каких-либо промежуточных правок вне редактора правок.
    Сейчас если сохранить по отдельности файлы html, css и js, то html в браузере работать не будет — надо будет прописывать ему линки на стили и скрипты. Это не очень удобно.


  1. gnaeus
    02.02.2019 14:14

    А почему Ace, а не Monaco Editor? В последнем автокомплит и "go to definition" есть из коробки.


    1. ddinochrome
      02.02.2019 14:25

      Мне тоже Monaco Editor гораздо больше нравится. Недавно перешёл на него с Ace'а в своих проектах, весьма доволен. Но он не настолько популярен пока что как более пожилые CodeMirror и Ace — меньше ссылок и материалов на него. Поэтому многие о нём элементарно могут и не знать)