Pull to refresh

Притча о потерянном состоянии

Reading time 5 min
Views 1.3K
— Здра…
— А-а-а!
— Ну ты чего?
— Я вас боюсь!
— Чего это?
— Вы вечно меня унижаете…
— Хех, ну ладно, больше не буду.
— Правда?
— Доо, хочешь конфетку с аяксом?
— Конечно!
— Тада давай, лети к нам в Питер. Вот список авиарейсов на которые есть билеты отсортированный по цене: rasp.yandex.ru/search?cityFrom=Санкт-Петербург&cityTo=Москва
— Эм… что-то вы наврали дяденька — там вообще все рейсы из Москвы в Питер, отсортированные по времени отправления.
— Гм… действительно, не хорошо получилось… а значешь почему?
— Нэ?
— Потому что состояние приложения не отражается на uri. Поэтому каждый раз заходя на эту страницу из закладок, тебе придётся заново устанавливать фильтрацию и сортировку.
— Блоо, как же быть?
— Смириться, ибо как посетитель ты уже ничего не сможешь сделать.
— А если бы я был разработчиком?
— Тогда ты мог бы пойти по пути REST и сделать так, чтобы состояние приложения полностью зависело от uri.
— Но тогда будет перезагрузка страницы.
— А ты меняй только hash-part страницы.
— Но как я узнаю, что uri изменился?
— Для этого есть библиотеки.
— А что если состояние моего приложения — это многомерная структура?
— Используй Hiqus.
— Ой, как всё это сложно…
— Да чего там сложного? Смотри:
HashState.listen( function(){ // вешаем обработчик изменения хэша<br>    console.log( 'state changed to: ' + HashState ) // дампим всё состояние<br>    console.log( 'filters: ' + HashState.sub( 'filters' ) ) // дампим лишь состояние фильтров<br>    console.log // выводим состояние сортировки<br>    (    'order by: '<br>    +    HashState.get( 'order', 'by' )<br>    +    ' '<br>    +    ( HashState.get( 'order', 'reverse' ) ? 'desc' : 'asc' )<br>    )<br>})

— А менять как состояние?
— Да элементарно:
HashState.put( 'order:by:cost' )<br>HashState.put( 'order', 'reverse', true )<br>HashState.put( 'filters', { type: 'airplane', free: true } )

— А стирать?
— Да тоже не проблема:
HashState( '' ) // стираем вообще всё<br>HashState.put( 'filters', '' ) // стираем лишь состояние фильтров

— Вроде ничего сложного.
— Имено. Лови либу и дуй на всех порах в Питер, а то всё вкусное съедят:
var HashState= new function(){<br><br>Version: 1<br>Description: 'stores data in hash part of uri'<br>License: 'public domain'<br><br>Implementation:<br><br>var handlers= []<br>var latency= 25<br>var timer= 0<br>var hrefLast= ''<br>var dataLast= null<br>var data= null<br><br>var has= function( list, item ){<br>    for( var i= list.length - 1; i >= 0; --i ) if( list[i] === item ) return true<br>    return false<br>}<br>var drop= function( list, item ){<br>    for( var i= list.length - 1; i >= 0; --i ) if( list[i] === item ) list.splice( i, 1 )<br>}<br><br>var listen= function( handler ){<br>    if( has( handlers, handler ) ) return<br>    handlers.push( handler )<br>    schedule()<br>}<br>var forget= function( handler ){<br>    drop( handlers, handler )<br>    if( !handlers.length ) freeze()<br>}<br><br>var freeze= function(){<br>    timer= clearTimeout( timer )<br>}<br>var schedule= function(){<br>    freeze()<br>    timer= setTimeout( update, latency )<br>}<br><br>var update= function(){<br>    var href= document.location.href<br>    if( href !== hrefLast ){<br>        data= Hiqus( href.replace( /^[^#]*#?/, '' ) )<br>        if( dataLast+'' != data )<br>            for( var i= 0, len= handlers.length; i < len; ++i )<br>                handlers[i].call()<br>        hrefLast= href<br>        dataLast= data<br>    }<br>    if( timer ) schedule()<br>}<br>var change= function( data ){<br>    document.location= '#' + data<br>}<br><br>var HashState= function(){<br>    if( !arguments.length ) return Hiqus( data )<br>    change( data= Hiqus.apply( null, arguments ) )<br>    return HashState<br>}<br><br>HashState.prototype= function(){<br>    this.listen= function( handler ){<br>        listen( handler )<br>        return this<br>    }<br>    this.forget= function( handler ){<br>        forget( handler )<br>        return this<br>    }<br>    this.revive= function(){<br>        schedule()<br>        return this<br>    }<br>    this.freeze= function(){<br>        freeze()<br>        return this<br>    }<br>    this.put= function(){<br>        HashState( data.put.apply( data, arguments ) )<br>        return this<br>    }<br>    this.get= function(){<br>        return data.get.apply( data, arguments )<br>    }<br>    this.sub= function(){<br>        return data.sub.apply( data, arguments )<br>    }<br>    this.toString= function(){<br>        return ''+HashState()<br>    }<br>    return this<br>}.apply( HashState )<br><br>update()<br><br>Export: return HashState<br><br>Usage:<br><br>HashState.listen( function(){ // observe changing<br>    console.log( 'state changed to: ' + HashState ) // all state<br>    console.log( 'filters: ' + HashState.sub( 'filters' ) ) // sub state<br>    console.log<br>    (    'order by: '<br>    +    HashState.get( 'order', 'by' ) // one value<br>    +    ' '<br>    +    ( HashState.get( 'order', 'reverse' ) ? 'desc' : 'asc' )<br>    )<br>})<br>HashState( '' ) // clear all<br><br>// add parameters<br>HashState.put( 'order:by:cost' )<br>HashState.put( 'order', 'reverse', true )<br>HashState.put( 'filters', { type: 'airplane', free: true } )<br>HashState.put( 'filters', '' )<br><br>}
Tags:
Hubs:
+76
Comments 44
Comments Comments 44

Articles