1// Example Usage: 2// var pageCache = SnapbackCache({ 3// bodySelector: "#recordings", 4// }) 5// 6// pageCache.markDirty("comment/1") 7// 8// Required options: 9// * bodySelector: Element to be cached and position saved 10// Optional options: 11// * finish Pass function to get things on your page to "finish" that you don't want to cache in an inbetween state. 12// By default we finish jQuery Animations. 13// * refreshItems You may mark items dirty in your DOM as things are edited but might still be in the 14// page cache, this is a callback for refreshing those dirty items. Using above example 15// refreshItems function would be passed arguement ["comment/1"] 16// * removeAutofocus Pass function to remove items that cause your page to autofocusing. Autofocus behavior can screw with 17// setting your scroll position. 18// 19// Events: 20// * snapback-cache:cached Triggered when a cache has been set. The cachedPage object is returned with 21// the event (triggered on bodySelector) 22// * snapback-cache:loaded Triggered when a cache has been loaded. The cachedPage object is returned with 23// the event (triggered on bodySelector) 24var SnapbackCache = (function(options) { 25 var options = options || {} 26 27 var SessionStorageHash = (function() { 28 var set = function(namespace, key, item){ 29 var storageHash = sessionStorage.getItem(namespace); 30 if (!storageHash) { 31 storageHash = {} 32 } else { 33 storageHash = JSON.parse(storageHash) 34 } 35 36 if (item) { 37 storageHash[key] = JSON.stringify(item) 38 } else { 39 delete storageHash[key] 40 } 41 42 sessionStorage.setItem(namespace, JSON.stringify(storageHash)) 43 } 44 45 var get = function(namespace, key, item){ 46 var storageHash = sessionStorage.getItem(namespace) 47 48 if(storageHash){ 49 storageHash = JSON.parse(storageHash) 50 if(storageHash[key]){ 51 return JSON.parse(storageHash[key]) 52 } 53 } 54 55 return null 56 } 57 58 return { 59 set: set, 60 get: get 61 } 62 })() 63 64 var enabled = true 65 66 var disable = function() { 67 enabled = false 68 } 69 70 var enable = function () { 71 enabled = true 72 } 73 74 var supported = function(){ 75 return !!(sessionStorage && history && enabled) 76 } 77 78 var setItem = function(url, value){ 79 if(value){ 80 // only keep 10 things cached 81 trimStorage() 82 } 83 SessionStorageHash.set("pageCache", url, value) 84 } 85 86 var getItem = function(url){ 87 return SessionStorageHash.get("pageCache", url) 88 } 89 90 var removeItem = function(url){ 91 setItem(url, null) 92 } 93 94 var disableAutofocusIfReplacingCachedPage = function(){ 95 if(typeof options.removeAutofocus === "function"){ 96 if(willUseCacheOnThisPage()){ 97 options.removeAutofocus() 98 } 99 } 100 } 101 102 var cachePage = function(filterOut, callbackFunction){ 103 if (typeof filterOut === 'function') { 104 callbackFunction = filterOut 105 filterOut = null 106 } 107 108 if (!supported()){ 109 if(callbackFunction){ 110 callbackFunction() 111 } 112 return; 113 } 114 115 // get jQuery animations to finish 116 jQuery(document).finish() 117 if (typeof options.wait === "function") 118 options.finish() 119 120 // Give transitions/animations a chance to finish 121 setTimeout(function(){ 122 if (typeof options.removeAutofocus === "function") 123 options.removeAutofocus() 124 125 var $cachedBody = jQuery(options.bodySelector) 126 if (filterOut) { 127 $cachedBody = $cachedBody.clone().find(filterOut).replaceWith("").end() 128 } 129 130 var cachedPage = { 131 body: $cachedBody.html(), 132 title: document.title, 133 positionY: window.pageYOffset, 134 positionX: window.pageXOffset, 135 cachedAt: new Date().getTime() 136 } 137 138 // help to setup the next page of infinite scrolling 139 if (typeof options.nextPageOffset === "function") 140 cachedPage.nextPageOffset = options.nextPageOffset() 141 142 setItem(document.location.href, cachedPage) 143 144 jQuery(options.bodySelector).trigger("snapback-cache:cached", cachedPage) 145 146 if(callbackFunction){ 147 callbackFunction() 148 } 149 }, 10) 150 } 151 152 var loadFromCache = function(noCacheCallback){ 153 // Check if there is a cache and if its less than 15 minutes old 154 if(willUseCacheOnThisPage()){ 155 var cachedPage = getItem(document.location.href) 156 157 // replace the content and scroll 158 jQuery(options.bodySelector).html(cachedPage.body) 159 160 // try to make sure autofocus events don't run. 161 if (typeof options.removeAutofocus === "function") 162 options.removeAutofocus() 163 164 // IE 10+ needs a delay to stop the autofocus during dom load 165 setTimeout(function(){ 166 window.scrollTo(cachedPage.positionX, cachedPage.positionY) 167 }, 1); 168 169 // pop the cache 170 removeItem(document.location.href) 171 172 jQuery(options.bodySelector).trigger("snapback-cache:loaded", cachedPage) 173 174 // refresh any obsolete recordings in the activity feed 175 var dirties = getDirties() 176 if(dirties){ 177 if (typeof options.refreshItems === "function") 178 options.refreshItems(dirties) 179 180 clearDirty() 181 } 182 183 return false;
184 } 185 else{ 186 if(noCacheCallback){ 187 noCacheCallback() 188 } 189 else{ 190 return 191 } 192 } 193 } 194 195 var clearDirty = function() { 196 sessionStorage.removeItem("pageCache-dirty") 197 } 198 199 var getDirties = function() { 200 var raw = sessionStorage.getItem("pageCache-dirty") 201 if (raw) { 202 var json = JSON.parse(raw) 203 return jQuery.map(json, function(value, key){ 204 return key 205 }) 206 } else { 207 return null 208 } 209 } 210 211 var markDirty = function(item) { 212 SessionStorageHash.set("pageCache-dirty", item, true) 213 } 214 215 var trimStorage = function(){ 216 var storageHash = sessionStorage.getItem("pageCache"); 217 if(storageHash){ 218 storageHash = JSON.parse(storageHash); 219 220 var tuples = []; 221 222 for (var key in storageHash) { 223 tuples.push([key, storageHash[key]]) 224 } 225 // if storage is bigger than size, sort them, and remove oldest 226 if(tuples.length >= 10){ 227 tuples.sort(function(a, b) { 228 a = a[1].cachedAt; 229 b = b[1].cachedAt; 230 return b < a ? -1 : (b > a ? 1 : 0); 231 }); 232 233 for (var i = 0; i < (tuples.length + 1 - 10); i++) { 234 var key = tuples[i][0]; 235 delete storageHash[key]; 236 } 237 238 sessionStorage.setItem(namespace, JSON.stringify(storageHash)); 239 } 240 } 241 } 242 243 var willUseCacheOnThisPage = function(){ 244 if (!supported()){ 245 return false; 246 } 247 248 var cachedPage = getItem(document.location.href) 249 250 // Check if there is a cache and if its less than 15 minutes old 251 if(cachedPage && cachedPage.cachedAt > (new Date().getTime()-900000)){ 252 return true; 253 } 254 else{ 255 return false; 256 } 257 } 258 259 jQuery(document).ready(function(){ 260 disableAutofocusIfReplacingCachedPage() 261 }); 262 263 jQuery(window).load(function(){ 264 loadFromCache() 265 }); 266 267 return { 268 enable: enable, 269 disable: disable, 270 remove: removeItem, 271 loadFromCache: loadFromCache, 272 cachePage: cachePage, 273 markDirty: markDirty, 274 willUseCacheOnThisPage: willUseCacheOnThisPage 275 } 276});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.