Статьи

Создание постоянных заметок с локальным хранилищем

HTML5 локальное хранилище похоже на куки на стероидах; он невероятно прост в использовании и все же очень мощный. В этом уроке я покажу вам, как создать функцию «заметок», которая позволит вашим пользователям делать постоянные заметки при просмотре вашего сайта.


Из-за динамической природы этого проекта, на самом деле не так много кода для обычной старой семантической разметки. Мы просто смоделируем веб-страницу, собрав немного наполнителя:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
   <html>
   <head>
       <meta charset=’utf-8′ />
       <title>HTML 5 complete</title>
       <link rel=»stylesheet» href=»default.css» />
       <link rel=»stylesheet» href=»stickies/stickies.css» />
       <!—[if IE]>
       <script src=»https://html5shiv.googlecode.com/svn/trunk/html5.js»></script>
       <![endif]—>
   </head>
   <body>
       <article>
           <header>
               <h1> Sample Article Title</h1>
           </header>
           <p>Lorem ipsum dolor.
           <!— a few lorem-ipsum paragraphs later .
           <footer>
               <p>Copyright 2010 Andrew Burgess</p>
           </footer>
       </article>
 
       <script src=»http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js»></script>
       <script src=»http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js»></script>
       <script src=»json2.js»></script>
       <script src=»stickies/stickies.js»></script>
       <script>
       </script>
   </body>
   </html>

Здесь следует отметить несколько важных вещей: мы включаем два CSS-файла: первый — это простой стиль страницы, который мы назвали default.css . Затем у нас есть специальные CSS-файлы для стилей, связанных с нашими заметками; он называется stickies.css , и, как вы можете видеть, он находится в папке «stickies». Внизу мы включаем четыре сценария:

  • jQuery, из CDN Google
  • Пользовательский интерфейс JQuery, из CDN Google
  • JSON2, от Дугласа Крокфорда
  • Наш собственный stickies.js , который находится в каталоге «stickies»

Затем у нас есть пустой тег сценария, который мы будем использовать для запуска двигателя чуть позже.

И это все для HTML!


Содержимое default.css невероятно просто:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
body {
       margin:0;
       padding:0;
       background:#ccc;
       font:14px/1.5 «Helvetica Neue», Helvetica, Arial, san-serif;
   }
   article, footer, header { display: block;
   article {
       width:880px;
       background:#fff;
       margin:auto;
       padding:40px;
   }
   article header {
       color:#474747;
       border-bottom:1px solid #474747
   }
   article footer {
       font-size:90%;
       color:#ccc;
   }

Это оно; теперь есть CSS из stickies.css нужно следить … но у нас пока нет этой разметки. Итак, давайте запустим немного JavaScript, и когда это будет сделано, мы рассмотрим CSS для заметок.


Вот скелет для нашего приложения JavaScript:

01
02
03
04
05
06
07
08
09
10
11
12
13
var STICKIES = (function () {
       var initStickies = function () {},
           openStickies = function () {},
           createSticky = function (data) {},
           deleteSticky = function (id) {},
           saveSticky = function () {},
           markUnsaved = function () {};
            
       return {
           open : openStickies,
           init : initStickies
       };
   }());

У нас здесь есть несколько интересных техник. Во-первых, это самозанятая функция: может показаться, что мы присваиваем функцию переменной STICKIES , но если вы внимательно посмотрите на конец функции, вы увидите, что мы запускаем ее сразу. Как подсказка — чтобы напомнить нам, что это не нормальная функция — мы заключаем всю функцию в скобки. Итак, STICKIES — это не функция, это возвращаемое значение этой функции, которая в данном случае является объектом.

Это подводит нас к следующей технике: закрытие. Обратите внимание, что из шести создаваемых нами функций только две из них предоставляются пользователю (на самом деле, только одна необходима для использования, которое мы планируем; если бы мы хотели создать поддержку для создания заметок на вашем веб-сайте, мы могли бы предоставить createSticky и deleteSticky ). Даже несмотря на то, что самопричастная функция завершает выполнение еще до того, как мы используем методы, мы сможем использовать другие функции, которые мы определили.

Хорошо, давайте перейдем к содержанию этих функций.


Начнем с рассмотрения функции initStickies :

1
2
3
4
5
6
7
8
var initStickies = function initStickies() {
       $(«<div />», {
           text : «+»,
           «class» : «add-sticky»,
           click : function () { createSticky();
       }).prependTo(document.body);
       initStickies = null;
   },

Это довольно просто. Мы будем использовать jQuery для создания элементов совсем немного, и мы используем специальный синтаксис в v. 1.4: это передает литерал объекта со спецификациями для элемента в качестве второго параметра функции jQuery. Здесь мы создаем кнопку для создания новой заметки. Это означает, что нам нужен новый div ; мы устанавливаем текст в «+» и присваиваем ему класс «add-sticky»; затем мы устанавливаем обработчик щелчка для вызова метода createSticky (важно вызывать createSticky из функции, а не вызывать обработчик щелчка непосредственно для createSticky ; это потому, что createSticky может принимать один параметр, и мы не не хочу, чтобы это был объект события). Наконец, мы добавляем этот div к телу. Мы заканчиваем, устанавливая initStickies к null ; да, мы по существу избавляемся от функции, которую мы выполняем. Это гарантирует нам, что эта функция будет запущена только один раз; мы не хотим, чтобы пользователь нашего API случайно добавлял на страницу несколько кнопок «Добавить заметку».

Давайте перейдем к следующему методу openStickies :

1
2
3
4
5
6
openStickies = function openStickies() {
       initStickies && initStickies();
       for (var i = 0; i < localStorage.length; i++) {
           createSticky(JSON.parse(localStorage.getItem(localStorage.key(i))));
       }
   },

Мы начнем с запуска initStickies … но что с необычным синтаксисом? Ну, вы, вероятно, знакомы с оператором && : логическим оператором AND. Обычно вы используете его для проверки нескольких условий в операторе if. Вот что он на самом деле делает: он вычисляет первое выражение, и если оно оказывается верным, он продолжает оценивать второе выражение. В этом случае, если initStickies еще не был установлен в null, мы запустим функцию. Это позволяет избежать ошибки, которая может возникнуть при попытке запустить нулевую переменную как функцию.

Далее мы зацикливаемся на каждом элементе в localStorage. Вот что мы делаем в этом цикле for (изнутри наружу):

  • localStorage.key() — отличная функция, которая возвращает имя localStorage значения localStorage ; он принимает число в качестве параметра. Это отличный способ localStorage каждый элемент в localStorage .
  • Получив ключ для хранимого элемента, мы можем передать его в localStorage.getItem() чтобы получить его значение.
  • Затем мы передаем это значение в JSON.parse() ; это из библиотеки Крокфорда. Поскольку мы JSON.stringify() несколько значений для каждой заметки, мы используем JSON.stringify() на другом конце, чтобы превратить объект в строку JSON, которую мы храним. Здесь мы конвертируем его из строки обратно в объект.
  • Наконец, мы передаем этот объект в createSticky() , который превращает его обратно в заметку.

Теперь давайте посмотрим на этот метод createSticky .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
createSticky = function createSticky(data) {
       data = data ||
        
       return $(«<div />», {
           «class» : «sticky»,
           ‘id’ : data.id
            })
           .prepend($(«<div />», { «class» : «sticky-header»} )
               .append($(«<span />», {
                   «class» : «status-sticky»,
                   click : saveSticky
               }))
               .append($(«<span />», {
                   «class» : «close-sticky»,
                   text : «trash»,
                   click : function () { deleteSticky($(this).parents(«.sticky»).attr(«id»));
               }))
           )
           .append($(«<div />», {
               html : data.text,
               contentEditable : true,
               «class» : «sticky-content»,
               keypress : markUnsaved
           }))
       .draggable({
           handle : «div.sticky-header»,
           stack : «.sticky»,
           start : markUnsaved,
           stop : saveSticky
        })
       .css({
           position: «absolute»,
           «top» : data.top,
           «left»: data.left
       })
       .focusout(saveSticky)
       .appendTo(document.body);
   },

Да, это долго, но это не будет слишком сложно. Во-первых, обратите внимание, что эта функция принимает объект данных; как мы только что видели в openStickies , мы передаем сохраненные данные этой функции. Однако, если мы не передаем какие-либо данные (т. Е. Создаем совершенно новую заметку), мы создадим объект заметки по умолчанию. Поскольку все заметки должны быть созданы в одной точке, все заметки начнутся с этой конфигурации. Обратите внимание, что для идентификатора заметки мы используем +new Date() ; этот предопределенный унарный оператор плюс преобразует дату, которую мы получаем от новой даты, в число, поэтому это утверждение приводит к числу, представляющему число миллисекунд с 1 января 1970 года. Очевидно, что это число будет постоянно меняться, поэтому это отличный способ уникально идентифицировать каждую заметку.

Оставшаяся часть функции представляет собой длинную цепочку связанных методов jQuery. Прежде чем пройти через это, обратите внимание, что мы возвращаем результат. Если мы предоставим этот метод разработчикам, использующим наш mirco-API, он вернет ссылку на элемент div с заметкой.

Итак, вот что происходит:

  • Сначала мы создаем div который является оболочкой заметки. Используя этот полезный синтаксис jQuery 1.4, мы присваиваем ему класс «sticky» и идентификатор объекта данных.

  • Затем мы добавляем div к этому; этот div получает класс «sticky-header». div.sticky-header добавляются два div.sticky-header . Первый, span.sticky-status , получает обработчик щелчка, который вызывает функцию saveSticky . Тем не менее, это на самом деле скрытая функция: этот диапазон будет отображать статус прикрепленного: сохранен или не сохранен. Там будет несколько способов, которыми sticky сохраняет свои данные в localStorage ; Возможно, что пользователь подумает, что нажатие на «несохраненный» сохранит заметку, поэтому мы предоставим им эту функцию. Второй диапазон, span.close-sticky , будет кнопкой удаления: когда пользователь localStorage по нему, мы удалим localStorage из localStorage помощью метода deleteSticky . Мы передаем этот метод идентификатор заметки.

  • Затем мы добавляем еще один div к основному div.sticky ; обратите внимание, что мы установили свойство html в data.text ; когда мы сохраняем текст заметки, мы используем метод jQuery html() , потому что использование text() избавляет от разрывов строк. Мы также установили contentEditable:true для этого div, потому что это содержимое заметки. Таким образом, он также получает класс sticky-content . Наконец, когда на этом элементе нажата клавиша (что означает, что пользователь изменяет содержимое), мы хотим пометить его как несохраненный, поэтому мы вызовем эту функцию (что мы вскоре сделаем).

  • Теперь мы используем функцию перетаскивания пользовательского интерфейса jQuery, чтобы сделать заметку подвижной. В нашем объекте параметра мы используем свойство handle чтобы наши заметки могли перемещаться только из строки заголовка. Свойство stack является селектором для перетаскиваемых элементов, которые нужно «сложить»; установив это, текущая заметка всегда будет наверху. Наконец, когда мы начинаем перетаскивать заметку, мы хотим пометить ее как «несохраненную» (потому что мы также должны сохранить ее координаты), а когда мы перестанем перетаскивать, мы сохраним эту заметку.

  • Далее мы устанавливаем несколько стилей для нашего div.sticky ; мы позиционируем его абсолютно, а затем устанавливаем его верхнее и левое значения равными значениям в объекте данных. Таким образом, заметка сохранит свою позицию и содержание, когда мы обновим страницу.

  • Наконец, мы установим обработчик события для того, когда мы focusout на липком (по сути, кликаем за ним после щелчка внутри него): мы хотим сохранить липкое. Наконец, мы добавим его к телу. Для справки вот структура HTML, которую мы должны были сгенерировать:

1
2
3
4
5
6
7
8
9
<div class=»sticky ui-draggable» id=»1281194825332″ style=»position: absolute; top: 40px; left: 40px;»>
    <div class=»sticky-header»>
            <span class=»sticky-status»>
            <span class=»close-sticky»>trash
    </div>
    <div contenteditable=»true» class=»sticky-content»>
        Note Here
    </div>
</div>

И это наша функция createSticky .

Теперь у нас есть функция deleteSticky ; это действительно просто:

1
2
3
4
deleteSticky = function deleteSticky(id) {
       localStorage.removeItem(«sticky-» + id);
       $(«#» + id).fadeOut(200, function () { $(this).remove(); });
   },

Как вы помните, функция deleteSticky принимает идентификатор заметки в качестве параметра. localStorage.removeItem() — это метод часа: мы передаем ему ключ к локально сохраненному значению, чтобы удалить эту пару ключ-значение (обратите внимание, что когда мы сохраняем данные заметки, мы добавляем «sticky-» к Я бы). Затем мы находим элемент с заданным идентификатором, исчезаем и удаляем его. Примечание удалено!

Второй-последний может быть самым важным методом сегодня: saveSticky : это клей, который заставляет все это работать.

01
02
03
04
05
06
07
08
09
10
11
saveSticky = function saveSticky() {
       var that = $(this), sticky = (that.hasClass(«sticky-status») || that.hasClass(«sticky-content»)) ?
       obj = {
           id : sticky.attr(«id»),
           top : sticky.css(«top»),
           left: sticky.css(«left»),
           text: sticky.children(«.sticky-content»).html()
       }
       localStorage.setItem(«sticky-» + obj.id, JSON.stringify(obj));
       sticky.find(«.sticky-status»).text(«saved»);
   },

Первая строка немного разрешает: есть три разных элемента, из которых мы можем вызвать эту функцию. Во-первых, мы «jQuerify» this в that ; затем, если элемент имеет классы «sticky-status» или «sticky-content», мы получим родителя div.sticky ; если у него нет ни одного из этих классов, то это сам div.sticky , так что мы просто воспользуемся этим.

Затем нам нужно получить значения, которые мы хотим сохранить. Как видите, мы получаем идентификатор со смещением сверху и слева и HTML дочернего .sticky-content ; помните, что мы используем html() вместо text() потому что хотим сохранить разрывы строк. Затем мы используем localStorage.setItem для хранения данных. Помните, что он принимает два параметра: ключ и значение для хранения. Поскольку localStorage хранит только строки, мы используем JSON.stringify() для преобразования объекта в строку.

И наконец, измените статус закрепления на «сохранен».

У нас есть одна последняя функция, которая является просто вспомогательной функцией:

1
2
3
4
markUnsaved = function markUnsaved() {
       var that = $(this), sticky = that.hasClass(«sticky-content») ?
       sticky.find(«.sticky-status»).text(«unsaved»);
   }

Опять же, мы должны начать с разрешения ссылки на div.sticky ; как только мы это сделаем, мы можем просто найти диапазон состояния и установить текст как «несохраненный».

Хотите верьте, хотите нет, но в этом весь JavaScript.


Теперь, когда мы знаем, какова наша разметка, мы можем ее стилизовать. Это довольно просто; но посмотрите, и я сделаю несколько комментариев в конце:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
:focus {
       outline:0;
   }
   .add-sticky {
       cursor: default;
       position:absolute;
       top:1px;
       left:1px;
       font-size:200%;
       background:#000;
       color:#fff;
       border:2px solid #fff;
       border-radius:40px;
       -webkit-border-radius:40px;
       -moz-border-radius:40px;
       text-align:center;
       line-height:25px;
       width:30px;
       height:30px;
   }
   .add-sticky:hover {
       background: #474747;
   }
   .sticky {
       width:300px;
       background:#fdfdbe;
       box-shadow:3px 3px 10px rgba(0,0,0,0.45);
       -webkit-box-shadow:3px 3px 10px rgba(0,0,0,0.45);
       -moz-box-shadow:3px 3px 10px rgba(0,0,0,0.45);
   }
   .sticky-content {
       min-height:150px;
       border-left:3px double rgba(238, 150, 122, .75);
       margin-left:30px;
       padding:5px;
   }
   .sticky-header {
       padding:5px;
       background:#f3f3f3;
       border-bottom:2px solid #fefefe;
       box-shadow:0 3px 5px rgba(0,0,0,0.25);
       -webkit-box-shadow:0 3px 5px rgba(0,0,0,0.25);
       -moz-box-shadow:0 3px 5px rgba(0,0,0,0.25);
   }
   .sticky-status {
       color:#ccc;
       padding:5px;
   }
   .close-sticky {
       background:#474747;
       float:right;
       cursor:default;
       color:#ececec;
       padding:1px 5px;
       border-radius:20px;
       -webkit-border-radius:20px;
       -moz-border-radius:20px;
   }

Здесь есть несколько интересных мест:

  • Некоторые браузеры обводят элементы вокруг элементов с помощью contenteditable=true при редактировании содержимого. Мы не хотим этого, поэтому мы избавляемся от этого с помощью нашей декларации :focus .
  • Кнопка «Добавить стикер» расположена в верхнем левом углу; он выглядит примерно как «Добавить панель инструментов Widget» в Mac OS X.
  • Мы используем CSS3-свойства border-radius и box-shadow (и их соответствующие воплощения с префиксами поставщиков).
  • Мы также используем rgba() для наших теневых цветов. Он принимает четыре параметра: красный, жадный и синий цвета и значение альфа (прозрачность).

Кроме этого, это просто ваш стандартный CSS. Вот как должна выглядеть стилизованная заметка:

Заметка

Теперь, когда мы создали наш API, пришло время начать его; мы можем сделать это из дополнительного пустого тега script в нашем файле index.html :

1
STICKIES.open();

Ну, мы сделали! Вот конечный продукт в действии:

Это все, что у меня есть на сегодня; Как вы планируете использовать локальное хранилище HTML5, чтобы оживить ваши веб-проекты? Дай мне знать в комментариях!