Авторские статьи Хранение данных без cookies

Discussion in 'Статьи' started by Евгений Минаев, 1 Jun 2008.

  1. Евгений Минаев

    Евгений Минаев Elder - Старейшина

    Joined:
    12 Nov 2007
    Messages:
    55
    Likes Received:
    169
    Reputations:
    159
    ----[ Browser Storage ... under0x77ater ]

    ----[ NITRO ... ]


    "Стою на шестом этаже пятиэтажного дома, да это незаконно, но здесь многим так знакомо"

    Cookies впервые появились в Netscape, чтобы не хранить данные на веб сервере. Технология прижилась и даже с ростом вместимости жестких дисков до сих пор широко применяется. С появлением ajaxа и вследствие многократного увеличения запросов, приходится каждый раз при посылке запроса посылать также и cookies, что ведет к росту трафика, да и ограничение на них всего три килобайта. Первым эту проблему попытались исправить в Microsoft, внедрив поддержку userData в свой браузер пятой версии, но только после публикации предварительного описания HTML5 технология стала освещаться в различных веб изданиях. В статье расскажется об использовании данных в браузере на примерах Internet Explorer и Mozilla Firefox.

    ----[ WHAT THE FUCK ?! ... ]

    Из преимуществ можно отметить такие факты, как : уменьшение трафика, неограниченная длина данных, да и просто гарантия что у вас будет не как у всех xD. Применений такому способу масса - сохранение черновиков в веб формах, автозаполненных данных, хранение неособо важных данных, как дата последнего посещения, поисковый запрос или, например, название темы оформления сайта. Из достоинств метода можно выделить еще и безопасность - злоумышленник будет весьма удивлен отсутствию кук на сниффере. Но это вопрос времени.

    Так почему бы и не воспользоваться таким мощным и удобным средством?

     
    #1 Евгений Минаев, 1 Jun 2008
    Last edited: 1 Jun 2008
    2 people like this.
  2. Евгений Минаев

    Евгений Минаев Elder - Старейшина

    Joined:
    12 Nov 2007
    Messages:
    55
    Likes Received:
    169
    Reputations:
    159
    ----[ USER DATA ... ]

    userData появился в пятой версии Microsoft Internet Explorer и использовался для запоминания расположения элементов. Все данные представлены в виде связанной xml структуры в файле с расположением в Application Data/Microsoft/Internet Explorer/UserData. Первым технологию заметили программисты из Google. Чуть позже userData стали использовать как механизм хранения данных между сессиями. Все хранимые методы и свойства становятся доступными после события window.onload.

    Для начала работы с userData следует прописать определенную конструкцию в стиль документа.

    ie\:userdata {behavior:url(#default#userData);}

    После этого можно приступать к работе с данными, используя методы объекта.

    | Свойства
    |
    | expires
    | Устанавливает или возвращает дату устаревания информации в хранилище
    |
    | XMLDocument
    | Возвращает ссылку на объект XMLDocument, предоставляемый объектом
    |
    | Методы
    |
    | load (
    | параметр object userDat Элемент, которому назначено поведение userData
    | параметр string sStoreName Имя хранилища данных
    | результат nothing )
    |
    | Метод load осуществляет чтение информации из хранилища данных.
    | Для правильного выполнения метода load, элемент должен содержать установленный атрибут ID.
    | <html xmlns:IE>
    | <head>
    | <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    | <style type='text/css'>
    | ie\:userdata {behavior:url(#default#userData);}
    | </style>
    | </head>
    |
    | <body onload='oUserData.load("sDataStor");'>
    | <ie:userData ID="oUserData" />
    | </body>
    | </html>
    |
    | save (
    | параметр object userDat Элемент, которому назначено поведение userData
    | параметр string sStoreName Имя хранилища данных
    | результат nothing )
    |
    | Метод save осуществляет запись информации в хранилище данных. Доступность хранилища зависит от адреса ресурса, использующего
    | это хранилище. Для того, что бы ресурс мог обратится к хранилищу данных, адрес ресурса, загружающего информацию из указанного
    | хранилища данных, должен совпадать с адресом ресурса, создавшего это хранилище с точностью до всех используемых папок.
    | <html xmlns:IE>
    | <head>
    | <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    | <style type='text/css'>
    | ie\:userdata {behavior:url(#default#userData);}
    | </style>
    | </head>
    |
    | <body onunload='oUserData.save("sDataStor");'>
    | <ie:userData ID="oUserData" />
    | </body>
    | </html>
    |
    | setAttribute (
    | параметр string sAttrName Имя ключа
    | параметр string vAttrValue Назначаемое ключу значение
    | результат nothing )
    |
    | Метод setAttribute устанавливает значение нужному ключу, и в случае его отсутсвия сама добавляет ключ.
    |
    | getAttribute (
    | параметр string sAttrName Имя ключа
    | результат nothing )
    |
    | Метод getAttribute возвращает значение ключа или пустую строку.
    |
    | removeAttribute (
    | параметр string sAttrName Имя ключа
    | результат nothing )
    |
    | Метод getAttribute возвращает значение ключа или пустую строку.
    |
    |
    | <HEAD>
    |
    | <STYLE>
    | .userData {behavior:url(#default#userdata);}
    | </STYLE>
    |
    | <SCRIPT>
    | function fnGet(){
    | oPersistInput.load("oDataStore");
    | oPersistInput.value=oPersistInput.getAttribute("sPersistAttr");
    | }
    | function fnSet(){
    | oPersistInput.setAttribute("sPersistAttr",oPersistInput.value);
    | oPersistInput.save("oDataStore");
    | }
    | function fnRem(){
    | oPersistInput.removeAttribute("sPersistAttr");
    | oPersistInput.save("oDataStore");
    | }
    | </SCRIPT>
    | </HEAD>
    |
    | <BODY>
    | <INPUT type=text class=userData id=oPersistInput>
    | <INPUT type=button value="Get Attribute" onclick="fnGet()">
    | <INPUT type=button value="Set Attribute" onclick="fnSet()">
    | <INPUT type=button value="Remove Attribute" onclick="fnRem()">
    | </BODY>
    |

    ----[ WINDOW.NAME ... ]

    DOM свойство я решил затронуть не просто так. Первым этот метод хранения данных предложил использовать Thomas Frank, в силу сохранения свойства на протяжении всей сессии жизни окна / закладки и является необязательным. Для удобства хранения данных я решил использовать структуру
    ключ1=значение1&ключ2=значение2...ключn=значениеn. Мой маленький набор функций позволяет заменять значения данных, добавлять новые и удалять существующие.

    [​IMG]

    | function replaceKey(key, value) {
    | if(window.name == '' || window.name.indexOf(key) == -1){
    | alert('No data in storage saved')
    | return;
    | }
    | delKey(key);
    | addKey(key,value);
    | }
    |
    | function addKey(key, value) {
    | myStorage = window.name;
    | if(myStorage.indexOf(key+'=')!= -1) {
    | alert('Yet another key');
    | return;
    | }
    | myStorage += key + '=' + encodeURIComponent(value) +'&';
    | window.name = myStorage;
    | }
    |
    | function getKey(key){
    | if(window.name == '' || window.name.indexOf(key) == -1){
    | alert('No data in storage saved')
    | return;
    | }
    | myStorage = window.name;
    | temp = myStorage.substring(myStorage.indexOf(key)+key.length,myStorage.length);
    | temp = temp.substring(1,temp.indexOf('&'));
    | return temp;
    | }
    |
    | function delKey(key){
    | if(window.name == '' || window.name.indexOf(key) == -1){
    | alert('No data in storage saved')
    | return;
    | }
    | value = getKey(key);
    | myStorage = window.name;
    | rExp = key + '=' + value + '&';
    | window.name = myStorage.replace(rExp, '');
    | }
    |
    | replaceKey (
    | параметр string key Имя ключа
    | параметр string value Значение
    | результат nothing )
    |
    | Фунцкция replaceKey удаляет меняет значение ключа на новое.
    |
    | addKey (
    | параметр string key Имя ключа
    | результат nothing )
    |
    | Функция addKey добавляет значение к уже сущестующим.
    |
    | delKey (
    | параметр string key Имя ключа
    | результат nothing )
    |
    | Функция delKey удаляет ключ из массива данных.
    |
    | getKey (
    | параметр string key Имя ключа
    | результат string temp Значение )
    |
    | Функция getKey возвращает значение ключа.
    |
    | <html>
    | <head>
    | <title>Пример к статье</title>
    | <script type="text/javascript" src="ex.js"></script>
    | </head>
    |
    | <body>
    | Hello world
    | <script type="text/javascript">
    | addKey('key1','value1');
    | // window name = key1=value1&
    | addKey('key2','value2');
    | // window name = key1=value1&key2=value2&
    | delKey('key2');
    | // window name = key1=value1&
    | replaceKey('key1','newvalue');
    | // window name = key1=newvalue&
    | </script>
    | </body>
    | </html>

    ----[ STORAGE ... ]

    Описание модели, реализующей хранение данных на стороне клиента, появилось в html 5 (http://www.whatwg.org/specs/web-apps/current-work/#storage0).
    Данный способ является на данный момент самым удобным и даже кроссбраузерным.Люди в w3c представляют структуру storage так

    Mozilla Firefox предлагает использовать два типа хранилищей - sessionStorage и globalStorage. Первый доступен только на протяжение времени жизни страницы и как только страница закрывается получить доступ к данным уже невозможно. Получить состояние storage можно через dom свойство Dom.storage.enabled

    | // Сохраняем в sessionStorage переменную username со значением antichat
    | sessionStorage.username = "antichat";
    | // Проверяем, сохранилась ли переменная
    | alert( "username = " + sessionStorage.username );


    | // Получаем дескриптор текстового поля
    | var field = document.getElementById("field");
    |
    | // Если включен режим автосохранения, загружаем черновик
    | if ( sessionStorage.autosave ) {
    | field.value = sessionStorage.autosave;
    | }
    |
    | // Проверяем каждую секунду содержимое текстового поля на изменения
    | setInterval(function(){
    | // Сохраняем в черновик
    | sessionStorage.autosave = field.value;
    | }, 1000);

    GlobalStorage позволяет держать данные на протяжение длительного промежутка времени.

    | // Сохранить переменную snippet в globalStorage только для сайта antichat.ru
    | globalStorage['antichat.ru'].snippet = "underWHAT?!";

    Счетчик посещения

    | // parseInt используется для перевода переменной visits в число
    | // все данные в *Storage хранятся в виде строки
    | globalStorage['mozilla.org'].visits =
    | parseInt( globalStorage['mozilla.org'].visits || 0 ) + 1;

    Пример #1 http://aaronboodman.com/halfnote/
    Пример #2 http://channy.creation.net/work/firefox/domstorage/#

    Thomas Frank написал библиотеку sessvars, облегчающей работу с globalStorage ( http://www.thomasfrank.se/sessvars.js )

    Единственная переменная-свойство объекта sessvars, которую вы не должны трогать, это $, потому что она содержит ряд полезных методов:

    Методы

    | sessvars.$.clearMem()
    | Очищает sessvars
    |
    | sessvars.$.usedMem()
    | Возвращает объем используемой памяти в килобайтах
    |
    | sessvars.$.usedMemPercent()
    | Возвращает объем используемой памяти в процентах от общего возможного объема
    |
    | sessvars.$.debug()
    | Выводит окно дебага вверху страницы (как в примере выше)
    |
    | sessvars.$.flush()
    | Явно сохраняет текущее состояние sessvars, так что все данные будут сохранены когда будет совершен переход на другую страницу. Это редко бывает необходимо, так как в нормальной ситуации это делается автоматически при событии unload.

    Флаги

    Также есть ряд различных флагов, которыми вы можете устанавливать поведение sessvars:

    | sessvars.$.prefs.memlimit
    | По умолчанию - 2000
    | Указывает объем данных в Кб, разрешенный для хранения в sessvars. По умолчанию 2000 Кб, так как Opera 9.25 имеет ограничение чуть выше этого числа. У остальных браузеров (IE7.0, Firefox 1.5/2.0 и Safari 3.0) ограничение намного выше - 10 Мб не представляют сложности для этих браузеров.

    | sessvars.$.prefs.autoFlush
    | true/false, по умолчанию true
    | Определяет, будет ли метод flush() вызываться автоматически

    | sessvars.$.prefs.crossDomain
    | true/false, по умолчанию false
    | Если флаг установлен в true, содержимое sessvars можно читать из разных доменов (если оба сайта используют sessvars.js).

    | sessvars.$.prefs.includeFunctions
    | true/false, по умолчанию false
    | Определяет, будет ли sessvars сохранять функции.

    | sessvars.$.prefs.includeProtos
    | true/false, по умолчанию false
    | Если true, то будут сохранены свойства, назначенные прототипам различных данных или объектов. Редко бывает необходимо.

    ----[ PersistJS ... ]

    PersistJS - первая javascript библиотека, которую можно поправу назвать кроссбраузерной ( http://pablotron.org/?cid=1557 )
    В данный момент он поддерживает следующие механизмы:

    | Flash 8
    | Google Gears
    | localstorage
    | whatwg_db
    | globalstorage
    | UserData (Internet Explorer)
    | cookie: хранение данных при помощи Cookie.

    Cookies используются только в случае отсутствия остальных способов.

    Сохранение данных
    | // создаем новое хранилище данных
    | var store = new Persist.Store('My Data Store');
    |
    | // данные для хранения
    | var data = "Некая длинная строка ...........";
    |
    | // сохраняем данные
    | store.set('saved_data', data);

    Получение данных
    | // получаем данные и показываем их пользователю
    | store.get('saved_data', function(ok, val) {
    | if (ok)
    | alert('saved data = ' + val);
    | });

    Удаление данных
    | store.remove('saved_data');

    Пример #1 http://jstoolbox.com/demo/persistjs/test/test_flash.html

    ----[ OUTRO ... ]

    При написании статьи были использованы материалы с сайта habrahabr.ru, jstoolbox.com, developer.mozilla.org и msdn.microsoft.com.

    Надеюсь, что информация не пройдет мимо, потому что эта статья как Ктулху - всё равно рано или поздно придёт и захавает. 2008
     
    #2 Евгений Минаев, 1 Jun 2008
    Last edited: 1 Jun 2008
    1 person likes this.
  3. DIAgen

    DIAgen Banned Life!

    Joined:
    2 May 2006
    Messages:
    1,055
    Likes Received:
    376
    Reputations:
    460
    На хабре тож рассматривался вопрос хранения данных не в кукисах а в window.name, а на PHPconf 2008 у Ильи Канторова был доклад о хранение даных на стороне клиента в Browser Persistence (хранение данных в DOM), но пока это еще не поддерживаю современные браузеры...

    Надо будет почитать и разобраться в этой технологии, и использовать уже ее :)
     
    2 people like this.
  4. Дикс

    Дикс Elder - Старейшина

    Joined:
    16 Apr 2006
    Messages:
    1,194
    Likes Received:
    227
    Reputations:
    26
    почитал по диагонали, storage показался наиболее простым для понимания.

    кто что думает по поводу userData, Storage и window.name? (последний имхо самый неудобный - надо парсить)
    кто использовал эти методы и какова у них кроссбраузерность?
     
  5. Корвин

    Корвин Elder - Старейшина

    Joined:
    26 Feb 2007
    Messages:
    256
    Likes Received:
    31
    Reputations:
    3
    у меня трабл с sessvars.js, в оепре и осле данных сехраняются, а в мазиле *уй, не подскажете как мона исправить, переделывать не хотелось бы, имхо весь сайт уже сделан, только мазила подвела...