1- // Copyright (C) 2023,2024 Gwyneth Llewelyn
2- //
3- // This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2.
4- //
5- // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
6- //
7- // You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1+ /**
2+ * postlocalstorage_functions.js
3+ * Handles the content storage of a post/reply/direct message inside localStorage.
4+ *
5+ * @author Gwyneth Llewelyn
6+ * @copyright © 2023,2024 by Gwyneth Llewelyn. Some rights reserved.
7+ * @license GPL-2.0-only
8+ */
89
10+ /**
11+ * @function anonymous
12+ *
13+ * @param {Object } message - This object (will be set to `this`).
14+ * @param {Document } doc - This object's DOM (will be set to `this.document`).
15+ */
916( function ( message , doc ) {
10- var nIntervId ; //
17+ /**
18+ * Handler for the SetInterval event, so we can remove it on submit.
19+ * @type {number }
20+ * @since 1.1.0
21+ */
22+ var nIntervId ;
1123
12- // One year = 31536000000 milliseconds.
24+ /**
25+ * Freshness interval in milliseconds.
26+ * One year = 31536000000 milliseconds.
27+ * @const {number}
28+ */
1329 const FRESHNESS_INTERVAL = 365 * 24 * 60 * 60 * 1000 ;
1430
1531 // If there is no localStorage support, give up
1632 if ( ! message . localStorage ) {
1733 console . debug ( "no local storage support" ) ;
1834 return ;
1935 }
20- // phpBB3 uses a textarea with name 'message', both for Quick Replies _and_ normal replies
36+ /**
37+ * phpBB3 uses a textarea with name 'message', both for Quick Replies _and_ normal replies
38+ * @type {Element? }
39+ */
2140 var textarea = doc . querySelector ( 'textarea[name="message"]' ) ;
2241 // no point in being around if this is nil; also: avoids crashing below (gwyneth 20220303)
2342 if ( ! textarea ) {
2443 console . warn ( "no phpBB3 content body textarea found" ) ;
2544 return ;
2645 }
27- // phpBB3 usually gives the subject/topic the name 'subject' — same for QR and normal replies.
46+ /**
47+ * phpBB3 usually gives the subject/topic the name 'subject' — same for QR and normal replies.
48+ * @type {Element? }
49+ */
2850 var subject = doc . querySelector ( 'input[name="subject"]' ) ;
2951 if ( ! subject ) {
3052 console . debug ( "no phpBB3 subject line found" ) ;
3153 // I have not decided what to do in this case! Possibly just:
3254 // subject = "(no subject)";
3355 }
34- // The key for the key/value pair in localStorage is the current URL.
56+ /**
57+ * The key for the key/value pair in localStorage is the current URL.
58+ * @type {string }
59+ */
3560 var key = message . location . href ;
3661 // Firefox seems to have an odd bug which affects clicking backspace in quick succession.
3762 // Kudos to @gvp9000 and for the fix below. (gwyneth 20240414)
4065 for ( let i = 0 ; i < count_hash_num - 1 ; i ++ ) {
4166 key = key . substring ( 0 , key . lastIndexOf ( '#' ) ) ;
4267 }
43- // JSON object to be saved with the textarea content + subject content + timestamp.
68+ /**
69+ * JSON object to be saved with the textarea content + subject content + timestamp.
70+ * @type {JSON? }
71+ */
4472 var item = null ;
45- // Event to be used for saving content on demand, when user switches pages.
46- // Note: both the 'pagehide' or 'beforeunload' are deprecated and should not be used.
73+
74+ /**
75+ * Event name to be used for saving content on demand, when user switches pages.
76+ *
77+ * Note: both the 'pagehide' or 'beforeunload' events are deprecated and should not be used here.
78+ * @const {string}
79+ */
4780 const unloadEvent = "visibilitychange" ;
4881
49- // If there's a localStorage entry for the current URL, update the textarea with the saved value.
82+ /**
83+ * JSON object describing what we store on the localStorage for each article/message.
84+ * @typedef StoredContent
85+ * @type {object }
86+ * @property {string } subject - Content of the "subject" input box (also known as "title").
87+ * @property {string } content - The actual content of the textarea box (the article/message itself).
88+ * @property {number } timestamp - Time in milliseconds since the Unix epoch, to deal with stale content.
89+ */
90+
91+ // If there's a `localStorage` entry for the current URL, update the textarea with the saved value.
5092 item = message . localStorage . getItem ( key ) ;
5193 if ( item ) {
94+ /**
95+ * JSON representation of one object in the localStorage.
96+ * @type {StoredContent? }
97+ */
5298 var data = JSON . parse ( item ) ;
99+ /** @since 1.1.0 */
53100 // Before 1.1.0, 'our' objects did not carry timestamps, so we need to check for them: (gwyneth 20240415)
54101 if ( data ?. timestamp ) {
55102 // check if data is stale.
68115 } else {
69116 // We don't know if the existing data is stale or not, since it comes from pre-1.1.0 times.
70117 // So, upgrade object to the new format, i.e. add a timestamp to existing content.
118+ /** @type {string } */
71119 let tempContent = data ?. content ?? "" ;
120+ /** @type {string } */
72121 let tempSubject = data ?. subject ?? "" ;
73122 message . localStorage . removeItem ( key ) ;
74123 item = JSON . stringify ( { "content" : tempContent , "subject" : tempSubject , "timestamp" : Date . now ( ) } ) ;
75124 message . localStorage . setItem ( key , item ) ;
76125 }
77126 }
78- //
79- // // Workaround for non-existing Object.hasOwn()
80- // function isIn(field, obj) {
81- // if ("hasOwn" in Object) {
82- // return Object.hasOwn(field, obj);
83- // }
84- // return (field in obj);
85- // }
86127
87- // This function will store the current value of the textarea in localStorage (or delete it if the textarea is blank) with a timestamp.
128+ /**
129+ * This function will store the current value of the textarea in localStorage (or delete it if the textarea is blank) with a timestamp.
130+ *
131+ * It gets triggered by the "type" events on the input and textarea elements,
132+ * @function updateStorage
133+ * @type EventListener
134+ */
88135 function updateStorage ( ) {
89136 // Note: if the visibilitychange event is being used, one should check to see if the visibilityState
90137 // is 'hidden' or 'visible'; but we're going to save to storage in both cases.
106153 // When the user presses a key just *once* inside the textarea, run the storage function when the page is unloaded.
107154 textarea . addEventListener (
108155 "keyup" ,
156+ /** @listens keyup */
109157 function ( ) {
110158 message . addEventListener ( unloadEvent , updateStorage ) ;
111159 nIntervId = message . setInterval ( updateStorage , 10000 ) ;
114162 // Same for the subject, I think:
115163 subject . addEventListener (
116164 "keyup" ,
165+ /** @listens keyup */
117166 function ( ) {
118167 message . addEventListener ( unloadEvent , updateStorage ) ;
119168 nIntervId = message . setInterval ( updateStorage , 10000 ) ;
120169 } , { once : true }
121170 ) ;
122171
123172 // When the form is submitted, delete the localStorage key/value pair.
124- textarea . form . addEventListener ( "submit" , function ( ) {
125- // ... except on Preview. We still want to keep the storage around during preview!
126- // Kudos to
127- if ( document . activeElement . value != 'Preview' ) {
128- message . localStorage . removeItem ( key ) ;
129- message . removeEventListener ( unloadEvent , updateStorage ) ;
130- message . clearInterval ( nIntervId ) ;
131- console . debug ( "Text submitted (not in preview!); removed from localStorage" ) ;
173+ textarea . form . addEventListener (
174+ "submit" ,
175+ /** @listens submit */
176+ function ( ) {
177+ // ... except on Preview. We still want to keep the storage around during preview!
178+ // Kudos to
179+ if ( document . activeElement . value != 'Preview' ) {
180+ message . localStorage . removeItem ( key ) ;
181+ message . removeEventListener ( unloadEvent , updateStorage ) ;
182+ message . clearInterval ( nIntervId ) ;
183+ console . debug ( "Text submitted (not in preview!); removed from localStorage" ) ;
184+ }
132185 }
133- } ) ;
186+ ) ;
134187} ) ( this , this . document ) ;
0 commit comments