├── README.md ├── example └── simple.html └── jquery.localStorageTextareas.js /README.md: -------------------------------------------------------------------------------- 1 | localStorage memory for textareas 2 | ================================= 3 | 4 | By Pablo Villalba for [Teambox](http://teambox.com) collaboration software. 5 | 6 | Usage 7 | ----- 8 | 9 | Saves textareas, inputs or selects to localStorage when the data-save-id attribute 10 | is defined as a unique string identifier for that textarea. 11 | 12 | 13 | 14 | 18 | 19 | - Typing on an input field will save its value locally every 200 ms. 20 | - Clicking on an empty field will load the saved value if there is one. 21 | - Calling $(selector).loadSavedTextareas() will restore input or textareas saved. 22 | 23 | READ THE CODE to understand how it works, it's not so long :) 24 | 25 | Notes 26 | ----- 27 | 28 | - Depends on underscore.js, jQuery 1.7. 29 | - You will need to manually clear localStorage if you need it. 30 | 31 | Licence 32 | ------- 33 | 34 | MIT Licence, do whatever you want with it :) 35 | -------------------------------------------------------------------------------- /example/simple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jquery.localStorageTextareas 5 | 6 | 7 | 8 | 9 | 14 | 20 | 21 | 22 |

Demo for textareas with localStorage

23 |

This textarea has a data-save-id attribute with a unique id.

24 |

Edit it and reload the page. When clicking it, the content will be loaded from what you typed before.

25 | 26 |

Of course, clicking on it to load it isn't ideal at all. That's why you can call $(document).loadSavedTextareas() to load it when the page is loaded:

27 |

28 | $(document).loadSavedTextareas();
29 |     
30 |
31 | 32 |
33 |

The textarea below is loaded by calling $("#container").loadSavedTextareas() after the page loads, so you don't need to click on it:

34 |
35 | 36 |
37 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /jquery.localStorageTextareas.js: -------------------------------------------------------------------------------- 1 | // Saves textareas to localStorage when the data-save-id attribute is defined 2 | // as a unique string identifier for that textarea. 3 | // 4 | // 5 | // 6 | // Typing on a textarea will save its value locally every 200 ms. 7 | // Clicking on an empty textarea will load the saved value if there is one. 8 | // Calling $(selector).loadSavedTextareas() will restore textareas saved. 9 | // 10 | // READ THE CODE to understand how it works, it's not so long :) 11 | // 12 | // Notes: 13 | // 14 | // - Depends on Modernizr.js, underscore.js, jQuery 1.7. 15 | // - You will need to manually clear localStorage if you need it. 16 | // 17 | // By Pablo Villalba, for Teambox 4 (http://teambox.com) 18 | 19 | 20 | (function () { 21 | 22 | // Don't load if localStorage isn't supported 23 | function localStorageSupported() { 24 | try { 25 | return !!localStorage.getItem; 26 | } catch (e) { 27 | return false; 28 | } 29 | } 30 | 31 | if (!localStorageSupported()) { 32 | return; 33 | } 34 | 35 | var saveTextarea, dirty = {}; 36 | 37 | function id(el) { 38 | return "textareas-autosave/" + $(el).attr('data-save-id'); 39 | } 40 | 41 | // setItem wrapper to fix some localStorage issues in *le* iPad 42 | // More info: http://stackoverflow.com/questions/2603682/ 43 | function setkey(key, val) { 44 | localStorage.removeItem(key); 45 | localStorage.setItem(key, val); 46 | } 47 | 48 | // Save text to its unique identifier at most every 200ms 49 | saveTextarea = _.debounce(function (event) { 50 | setkey(id(this), $(this).val()); 51 | $(this).attr("data-restored", true); 52 | dirty[id(this)] = true; 53 | }, 200); 54 | 55 | // Load text for the textarea if clicked and it's empty 56 | function loadTextarea(event) { 57 | var _id = id(this) 58 | , msg = "There is a saved version for this content. Would you like to restore the saved version?" 59 | , should_restore; 60 | // Only attempt to restore if there's saved content 61 | // and we haven't restored it yet. 62 | if (localStorage.getItem(_id) && !$(this).attr("data-restored")) { 63 | should_restore = 64 | // Empty.. 65 | $(this).val().length === 0 || 66 | // ..or different that what we have saved (request confirmation) 67 | ($(this).val() !== localStorage.getItem(_id) && confirm(msg)); 68 | if (should_restore) { 69 | $(this).val(localStorage.getItem(_id)); 70 | $(this).attr("data-restored", true); 71 | dirty[id(this)] = true; 72 | } 73 | } 74 | } 75 | 76 | /** 77 | * Load all textareas on demand 78 | * 79 | * Usage: $(".container").loadSavedTextareas(); 80 | * 81 | * @return {jQuery} 82 | */ 83 | $.fn.loadSavedTextareas = function () { 84 | var _id = id; 85 | return this.each(function () { 86 | var id = _id; 87 | // Restore input and textarea as text 88 | $(this).find("input[data-save-id],textarea[data-save-id]").each(function () { 89 | var $this = $(this); 90 | if ($this.val().length === 0) { 91 | $this.val(localStorage.getItem(id(this))); 92 | $this.attr("data-restored", true); 93 | dirty[id(this)] = true; 94 | } 95 | }); 96 | // Restore select as a value 97 | $(this).find("select[data-save-id]").each(function () { 98 | var saved = localStorage.getItem(id(this)); 99 | if (saved) { 100 | $(this).val(saved).attr("data-restored", true); 101 | dirty[id(this)] = true; 102 | } 103 | }); 104 | }); 105 | }; 106 | 107 | /** 108 | * Remove a given textarea 109 | * 110 | * Usage: $("textarea, input, select").clearSavedTextarea(); 111 | * 112 | * @return {jQuery} 113 | */ 114 | $.fn.clearSavedTextarea = function () { 115 | var _id = id(this); 116 | 117 | if (localStorage.getItem(_id)) { 118 | localStorage.removeItem(_id); 119 | } 120 | 121 | return this; 122 | }; 123 | 124 | // Iterate over all textareas to see if they should be cleared 125 | // from the DOM 126 | function resetEmptyTextareas(event) { 127 | $("select[data-save-id],input[data-save-id],textarea[data-save-id]").each(function (i, t) { 128 | var _id = id(t) 129 | , is_saved = localStorage.getItem(_id) 130 | , is_empty = t.value ? t.value.length === 0 : true 131 | , is_dirty = dirty[_id]; 132 | 133 | if (is_saved && is_empty && is_dirty) { 134 | localStorage.removeItem(_id); 135 | } 136 | }); 137 | } 138 | 139 | // Bind events 140 | $(document).on("change", "select[data-save-id]", saveTextarea); 141 | $(document).on("keyup", "select[data-save-id],input[data-save-id],textarea[data-save-id]", saveTextarea); 142 | $(document).on("click", "select[data-save-id],input[data-save-id],textarea[data-save-id]", loadTextarea); 143 | $(document).ajaxSuccess(resetEmptyTextareas); 144 | 145 | }()); 146 | --------------------------------------------------------------------------------