{"id":38943,"date":"2018-06-21T03:01:04","date_gmt":"2018-06-20T17:01:04","guid":{"rendered":"http:\/\/www.rjmprogramming.com.au\/ITblog\/?p=38943"},"modified":"2018-06-20T21:29:40","modified_gmt":"2018-06-20T11:29:40","slug":"monthly-chronicler-localstorage-tutorial","status":"publish","type":"post","link":"https:\/\/www.rjmprogramming.com.au\/ITblog\/monthly-chronicler-localstorage-tutorial\/","title":{"rendered":"Monthly Chronicler LocalStorage Tutorial"},"content":{"rendered":"<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\"><img decoding=\"async\" style=\"float:left;border: 15px solid pink;\" alt=\"Monthly Chronicler LocalStorage Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler_ls.jpg\" title=\"Monthly Chronicler LocalStorage Tutorial\"  \/><\/a><p class=\"wp-caption-text\">Monthly Chronicler LocalStorage Tutorial<\/p><\/div>\n<p>Are you familiar with <a target=_blank title='Web storage information from w3schools' href='https:\/\/www.w3schools.com\/html\/html5_webstorage.asp'>&#8220;LocalStorage&#8221;<\/a> at the client side of web application usage, as an alternative to HTTP Cookie usage?  It can store much more information than HTTP Cookies, but has no expiry date as such.  This is not to say that you can&#8217;t &#8220;removeItem&#8221; &#8220;LocalStorage&#8221; entries.<\/p>\n<p>Where and why is this of interest in terms of our &#8220;Monthly Chronicler&#8221; web application last talked about with the recent <a title='Monthly Chronicler Date Range Tutorial' href='#mcdrt'>Monthly Chronicler Date Range Tutorial<\/a>?  Well, as you can imagine, especially for somebody using this web application like a &#8220;Diary&#8221; the daily entries could get quite long.  &#8220;LocalStorage&#8221; can handle this data where HTTP Cookies will &#8220;fail&#8221;.<\/p>\n<p>What does it mean to &#8220;fail&#8221; in Javascript?  Think, the (Javascript) use of <a target=_blank title='Try\/Catch information from w3schools' href='https:\/\/www.w3schools.com\/js\/js_errors.asp'>try\/catch<\/a> in our proof of concept of this idea below &#8230;<\/p>\n<p><code><br \/>\n&lt;!doctype html&gt;<br \/>\n&lt;html&gt;<br \/>\n&lt;head&gt;<br \/>\n&lt;title&gt;Proof of concept HTTP Cookies to localStorage usage - RJM Programming - June, 2018&lt;\/title&gt;<br \/>\n&lt;style&gt; td { text-align: center; } &lt;\/style&gt;<br \/>\n&lt;script type='text\/javascript'&gt;<br \/>\nvar qcok=true, cok=true, uselocal=false;<br \/>\nvar str=\"0123456789\", prestr=\"0123456789\";<br \/>\nfunction vr_cookieVal(thisl) {<br \/>\n   var tCookie, subfor=\"\";<br \/>\n     if (uselocal) {<br \/>\n           if (localStorage) {<br \/>\n           var lthere=null;<br \/>\n           eval(\"lthere=localStorage.\" + thisl);<br \/>\n   if (lthere) {<br \/>\n    subfor=thisl + '=' + localStorage.getItem(thisl) + \"; \";<br \/>\n    tCookie=subfor.split(\"; \");<br \/>\n   }<br \/>\n           }<br \/>\n           }<br \/>\n   if (subfor != \"\" || document.cookie != '') {<br \/>\n   if (subfor == \"\") {<br \/>\n     tCookie=document.cookie.split(\"; \");<br \/>\n   }<br \/>\n   for (var j=0; j&lt;tCookie.length; j++) {<br \/>\n    if ((\"\" + thisl.trim()) == tCookie[j].split(\"=\")[0]) {<br \/>\n      return decodeURIComponent(tCookie[j].split(\"=\")[1]);<br \/>\n    }<br \/>\n   }<br \/>\n  }<br \/>\n  return '';<br \/>\n}<br \/>\nfunction vr_setCookie(thisl, thisg) { \/\/ thanks to JavaScript and Ajax by Tom Negrino and Dori Smith<br \/>\n   var expireDate = new Date();<br \/>\n   expireDate.setMonth(expireDate.getMonth()+6);<br \/>\n   try {<br \/>\n      if (uselocal) {<br \/>\n        if (localStorage) {<br \/>\n        localStorage.setItem(thisl, encodeURIComponent(thisg));<br \/>\n   return true;<br \/>\n        } else {<br \/>\n   document.cookie = \"\" + thisl + \"=\" + encodeURIComponent(thisg) + \"; expires=\" + expireDate.toGMTString();<br \/>\n   if (vr_cookieVal(thisl) != thisg) return false;<br \/>\n   return true;<br \/>\n        }<br \/>\n      } else {<br \/>\n   document.cookie = \"\" + thisl + \"=\" + encodeURIComponent(thisg) + \"; expires=\" + expireDate.toGMTString();<br \/>\n   if (vr_cookieVal(thisl) != thisg) return false;<br \/>\n   return true;<br \/>\n      }<br \/>\n    } catch(error) {<br \/>\n      try {<br \/>\n      if (uselocal) {<br \/>\n   document.cookie = \"\" + thisl + \"=\" + encodeURIComponent(thisg) + \"; expires=\" + expireDate.toGMTString();<br \/>\n   return false;<br \/>\n      } else {<br \/>\n   expireDate.setMonth(expireDate.getMonth()-6);<br \/>\n   document.cookie = \"\" + thisl + \"=; expires=\" + expireDate.toGMTString();<br \/>\n        if (localStorage) {<br \/>\n        localStorage.setItem(thisl, encodeURIComponent(thisg));<br \/>\n   return false;<br \/>\n        } else {<br \/>\n   document.cookie = \"\" + thisl + \"=\" + encodeURIComponent(thisg) + \"; expires=\" + expireDate.toGMTString();<br \/>\n   return false;<br \/>\n        }<br \/>\n      }<br \/>\n      } catch(errortwo) {<br \/>\n   return false;<br \/>\n      }<br \/>\n    }<br \/>\n}<br \/>\nfunction startoff() {<br \/>\n  if (qcok && cok) {<br \/>\n    str+=prestr; \/\/\"0123456789\";<br \/>\n    if (str.length &lt; 520) prestr=str;<br \/>\n    document.title='' + str.length;<br \/>\n    cok=vr_setCookie(\"ourstring\", str);<br \/>\n    cok=vr_setCookie(\"ourstring2\", str);<br \/>\n    if (cok) {<br \/>\n      document.getElementById('Cookie').innerHTML='' + str.length;<br \/>\n      document.getElementById('Cookie2').innerHTML='' + str.length;<br \/>\n  setTimeout(startoff,200);<br \/>\n    } else {<br \/>\n      uselocal=true;<br \/>\n      document.getElementById('localStorage').innerHTML='' + str.length;<br \/>\n      document.getElementById('localStorage2').innerHTML='' + str.length;<br \/>\n  setTimeout(startoff,200);<br \/>\n    }<br \/>\n  } else {<br \/>\n  prestr=str.substring(0,2000);<br \/>\n  qcok=false;<br \/>\n  cok=true;<br \/>\n  for (var ii=0; ii&lt;1; ii++) {<br \/>\n    str+=prestr; \/\/\"0123456789\";<br \/>\n    document.title='' + str.length;<br \/>\n    cok=vr_setCookie(\"ourstring\", str);<br \/>\n    cok=vr_setCookie(\"ourstring2\", str);<br \/>\n    if (cok) {<br \/>\n      document.getElementById('localStorage').innerHTML='' + str.length;<br \/>\n      document.getElementById('localStorage2').innerHTML='' + str.length;<br \/>\n  setTimeout(startoff,200);<br \/>\n    } else if (document.getElementById('localStorage').innerHTML.indexOf(' failed at ') == -1) {<br \/>\n      localStorage.removeItem(\"ourstring\");<br \/>\n      localStorage.removeItem(\"ourstring2\");<br \/>\n      document.getElementById('localStorage').innerHTML+=' failed at ' + str.length;<br \/>\n      document.getElementById('localStorage2').innerHTML+=' failed at ' + str.length;<br \/>\n      prestartoff();<br \/>\n    }<br \/>\n  }<br \/>\n  }<br \/>\n}<br \/>\nfunction prestartoff() {<br \/>\n  var xexpireDate = new Date(); xexpireDate.setMonth(xexpireDate.getMonth()-6); document.cookie = \"\" + \"ourstring\" + \"=; expires=\" + xexpireDate.toGMTString(); document.cookie = \"\" + \"ourstring2\" + \"=; expires=\" + xexpireDate.toGMTString();<br \/>\n}<br \/>\n&lt;\/script&gt;<br \/>\n&lt;\/head&gt;<br \/>\n&lt;body onload='  prestartoff(); startoff();'&gt;<br \/>\n&lt;table style='width:100%;'&gt;<br \/>\n&lt;tr&gt;&lt;th&gt;Cookie&lt;\/th&gt;&lt;th&gt;localStorage&lt;\/th&gt;&lt;\/tr&gt;&lt;tr&gt;<br \/>\n&lt;td id=Cookie&gt;&lt;\/td&gt;&lt;td id=localStorage&gt;&lt;\/td&gt;&lt;\/tr&gt;<br \/>\n&lt;td id=Cookie2&gt;&lt;\/td&gt;&lt;td id=localStorage2&gt;&lt;\/td&gt;&lt;\/tr&gt;<br \/>\n&lt;\/table&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<br \/>\n<\/code><\/p>\n<p> &#8230; and that you can either download to your local web server (such as <a target=_blank title='MAMP' href='http:\/\/mamp.info'>MAMP<\/a> local Apache\/PHP\/MySql) and execute to test this yourself.<\/p>\n<p>&#8220;Failure&#8221; is relative.  How do you learn without failure?  Why do we come down so hard on &#8220;failure&#8221; when a lot of what we learn can only be learnt through failure?  I expect an answer to these by tomorrow, otherwise we&#8217;ll just have to tell your parents, OK?!  Well, no, it&#8217;s not OK &#8230; it&#8217;s okay &#8230; but, well it&#8217;s not OK &#8230; okay?!<\/p>\n<p>It could be some time, or never that today&#8217;s (<a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Geographicals\/diff.php?one=http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html---GETME\" title=\"monthly_chronicler.html\">changed code of<\/a>) <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html---GETME\" title=\"monthly_chronicler.html\">monthly_chronicler.html<\/a>&#8216;s <a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\" title=\"Click picture\">live run<\/a> link comes into play, but we&#8217;re here for the &#8220;long game&#8221;.  <a target=_blank title='Long games' href='https:\/\/www.quora.com\/What-has-been-the-longest-professional-sports-game-ever'>Quidditch<\/a>, anyone?!<\/p>\n<hr>\n<p id='mcdrt'>Previous relevant <a target=_blank title='Monthly Chronicler Date Range Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/monthly-chronicler-date-range-tutorial\/'>Monthly Chronicler Date Range Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\"><img decoding=\"async\" style=\"float:left;border: 15px solid pink;\" alt=\"Monthly Chronicler Date Range Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler_daterange.jpg\" title=\"Monthly Chronicler  Date Range Tutorial\"  \/><\/a><p class=\"wp-caption-text\">Monthly Chronicler Date Range Tutorial<\/p><\/div>\n<p>Today&#8217;s crucial Javascript function is called &#8220;nothing&#8221; (or more specifically <i>setTimeout(nothing,600);<\/i> (to have a small delay to when it gets used)).  How did this come to pass?  Well, today, with some new onclick event logic allowing for the user to define date range &#8220;Monthly Chronicle&#8221; data entries, we define new <i>onclick<\/i> logic on a whole lot of table td (cell) HTML elements.  You click on a table cell then click on another (or its nested <i>a<\/i> link) and that&#8217;s two dates ready to define a date range &#8230; right?  Well, yes, &#8220;right&#8221;, but with event logic, events flow through to parent HTML elements as well, and so without some care, we could end up with ugly consequences &#8230; right?!<\/p>\n<p>Without that care, of calling &#8220;nothing&#8221; (a Javascript function that resets some arrays &#8230;<\/p>\n<p><code><br \/>\nfunction nothing() {<br \/>\n    range=[];<br \/>\n    tdclicklist=[];<br \/>\n}<br \/>\n<\/code><\/p>\n<p> &#8230; back to pre-cell clicking (or touching) days <font size=1>&#8230; <a target=_blank title='?' href='https:\/\/getyarn.io\/yarn-clip\/1737ecbf-d33d-4830-baf2-7db3f1f51d5b'>good times<\/a><\/font>) <a target=_blank title='?' href='https:\/\/www.youtube.com\/watch?v=3gg2Jv2ebns'>a lot<\/a>, at the correct times for <em>non-cell &#8220;nested&#8221;<\/em> &#8230;<\/p>\n<p><code><br \/>\nfunction getinfo(bb) {<br \/>\n  if ((document.URL.split('#')[0] + '&').indexOf('close=&') != -1) theopen='';<br \/>\n  var rv='', sparerv='';<br \/>\n  rv=vr_cookieVal('c' + bb);<br \/>\n  if (rv != '') {<br \/>\n    sparerv=rv.replace(\/\\'\/g,'`').replace(\/\\\"\/g,'`');<br \/>\n    while (sparerv.indexOf(String.fromCharCode(10)) != -1) {<br \/>\n      sparerv=sparerv.replace(String.fromCharCode(10), ' ');<br \/>\n    }<br \/>\n    while (sparerv.indexOf('&lt;br&gt;') != -1) {<br \/>\n      sparerv=sparerv.replace('&lt;br&gt;', ' ');<br \/>\n    }<br \/>\n    while (sparerv.indexOf('&lt;div&gt;') != -1) {<br \/>\n      sparerv=sparerv.replace('&lt;div&gt;', ' ');<br \/>\n    }<br \/>\n    while (sparerv.indexOf('&lt;\/div&gt;') != -1) {<br \/>\n      sparerv=sparerv.replace('&lt;\/div&gt;', ' ');<br \/>\n    }<br \/>\n    while (sparerv.indexOf('&nbsp;') != -1) {<br \/>\n      sparerv=sparerv.replace('&nbsp;', ' ');<br \/>\n    }<br \/>\n    return '&lt;details <em>onclick=\"setTimeout(nothing,600);\"<\/em> title=\"' + sparerv.split('&lt;')[0] + '\" id=dt' + bb + theopen + '&gt;&lt;summary <em>onclick=\"setTimeout(nothing,600);\"<\/em> title=\"' + sparerv.split('&lt;')[0] + '\" id=sy' + bb + '&gt;&lt;\/summary&gt;&lt;div <em>onclick=\"setTimeout(nothing,600);\"<\/em> onblur=\"makeit(' + \"'c\" + bb + \"',this.innerHTML\" + ');\" contenteditable=\"true\"&gt;' + rv + '&lt;\/details&gt;';<br \/>\n  }<br \/>\n  return rv;<br \/>\n}<br \/>\n<\/code><\/p>\n<p> &#8230; elements, we&#8217;ll not be able to differentiate a click of an <i>a<\/i> link (ie. right on the number) from a &#8220;first of two&#8221; click date range definition.<\/p>\n<p>If you think about it, this &#8220;propogation&#8221; of event logic (and please know there are Javascript methods such as <a target=_blank title='Javascript stopPropogation information from w3schools' href='https:\/\/www.w3schools.com\/jsref\/event_stoppropagation.asp'>stopPropogation<\/a> which may help you out here too, as an alternative approach) can actually be used to your advantage the other way when you want to departmentalize several things you want to do with a click (or touch) anywhere within a table cell.  It&#8217;s just not what we want today, though.<\/p>\n<p>And so, apart from &#8220;nothing&#8221;, what do we have today amongst the new Javascript logic for this?<\/p>\n<p><code><br \/>\n<em>var appendmode=false;<br \/>\nvar xtowhat='', xdwo='', xnta='';<br \/>\nvar tdclicklist=[];<br \/>\nvar range=[];<br \/>\n<\/em><em><br \/>\nfunction qt(twp, suggestion) {<br \/>\n  var dateo;<br \/>\n  if (tdclicklist.length == 1) {<br \/>\n    var towhat=tdclicklist[0];<br \/>\n    range=[];<br \/>\n    var tds=document.getElementsByTagName('a');<br \/>\n    for (var ia=eval(-1 + tds.length); ia&gt;=0; ia--) {<br \/>\n      if (tds[ia].id.substring(1).length == towhat.substring(1).length && tds[ia].id.substring(1) &gt;= towhat.substring(1) && tds[ia].id.substring(1) &lt;= twp) {<br \/>\n       dateo=new Date(eval(tds[ia].id.substring(1).substring(0,4)), eval(-1 + eval(tds[ia].id.substring(1).substring(4,6))), eval(tds[ia].id.substring(1).substring(6,8)));<br \/>\n       range.push('d' + tds[ia].id.substring(1) + ',' + daysofweek[dateo.getDay()]);<br \/>\n      }<br \/>\n    }<br \/>\n    tdclicklist=[];<br \/>\n    if (range.length == 0) return suggestion;<br \/>\n    appendmode=false;<br \/>\n    return 'date range from date ' + range[eval(-1 + range.length)].split(',')[1] + ', ' + towhat.substring(1).substring(6) + ' ' + months[eval(-1 + eval(towhat.substring(1).substring(4,6)))] + ' ' + towhat.substring(1).substring(0,4) + ' to ' + suggestion + ' (prefix by + to append what is said here to any pre-existing chronicles)';<br \/>\n  }<br \/>\n  return suggestion;<br \/>\n}<br \/>\n<\/em><em><br \/>\nfunction tdclick(tdo) {<br \/>\n if (tdclicklist.length == 1) {<br \/>\n  document.getElementById('a' + tdo.id.substring(2)).click();<br \/>\n } else {<br \/>\n  tdclicklist.push('a' + tdo.id.replace('td',''));<br \/>\n }<br \/>\n}<br \/>\n<\/em><em><br \/>\nfunction preask() {<br \/>\n    ask(xtowhat, xdwo, xnta);<br \/>\n    if (range.length == 1) {<br \/>\n     document.getElementById('t' + xtowhat).style.backgroundColor='yellow';<br \/>\n     range=[];<br \/>\n      tdclicklist=[];<br \/>\n    } else {<br \/>\n     if (range.length &gt;= 1) {<br \/>\n      document.getElementById('t' + xtowhat).style.backgroundColor='yellow';<br \/>\n      xdwo=range[0].split(',')[1];<br \/>\n      xtowhat=range[0].split(',')[0];<br \/>\n      setTimeout(preask, 500);<br \/>\n     } else {<br \/>\n      document.getElementById('t' + xtowhat).style.backgroundColor='yellow';<br \/>\n      tdclicklist=[];<br \/>\n      range=[];<br \/>\n      appendmode=false;<br \/>\n     }<br \/>\n    }<br \/>\n}<br \/>\n<\/em><br \/>\nfunction ask(towhat, dwo<em>, nta<\/em>) {<br \/>\n  <em>xtowhat=towhat;<br \/>\n  xdwo=dwo;<\/em><br \/>\n  var retval=document.getElementById(towhat).innerHTML.split('&lt;\/div&gt;&lt;\/details&gt;')[0].split('&lt;\/details&gt;')[0].split('&lt;\/div&gt;')[0];<br \/>\n  if (retval.indexOf('&lt;\/summary&gt;') != -1) {<br \/>\n    retval=retval.split('&lt;\/summary&gt;')[1];<br \/>\n    if (retval.indexOf('\"&gt;') != -1) {<br \/>\n      retval=retval.replace(retval.split('\"&gt;')[0] + '\"&gt;','');<br \/>\n    while (retval.indexOf(String.fromCharCode(10)) != -1) {<br \/>\n      retval=retval.replace(String.fromCharCode(10), ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;br&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;br&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;div&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;div&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;\/div&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;\/div&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&nbsp;') != -1) {<br \/>\n      retval=retval.replace('&nbsp;', ' ');<br \/>\n    }<br \/>\n    }<br \/>\n  } else if (retval.indexOf('&lt;div') != -1 && retval.indexOf('\"&gt;') != -1) {<br \/>\n    retval=retval.replace(retval.split('\"&gt;')[0] + '\"&gt;','');<br \/>\n    while (retval.indexOf(String.fromCharCode(10)) != -1) {<br \/>\n      retval=retval.replace(String.fromCharCode(10), ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;br&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;br&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;div&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;div&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&lt;\/div&gt;') != -1) {<br \/>\n      retval=retval.replace('&lt;\/div&gt;', ' ');<br \/>\n    }<br \/>\n    while (retval.indexOf('&nbsp;') != -1) {<br \/>\n      retval=retval.replace('&nbsp;', ' ');<br \/>\n    }<br \/>\n  }<br \/>\n  var newretval;<br \/>\n  <em>if (nta.trim() != '') {<br \/>\n  if (appendmode && retval != '') {<br \/>\n  newretval=retval + ' &lt;br&gt;' + nta;<br \/>\n  } else {<br \/>\n  newretval=nta;<br \/>\n  }<br \/>\n  } else {<\/em><br \/>\n  if (document.URL.toLowerCase().replace('http:\/\/localhost','https:\/\/localhost').indexOf('http:') == 0 || (!passwordpassed &#038;& passwordrequired)) {<br \/>\n    newretval=prompt('What do you want to chronicle for <em>' + qt(towhat.substring(1), '<\/em>date ' + dwo + ', ' + towhat.substring(1).substring(6) + ' ' + months[eval(-1 + eval(towhat.substring(1).substring(4,6)))] + ' ' + towhat.substring(1).substring(0,4)<em>)<\/em> + '?  (NB: &lt;br&gt; is line feed)', retval);<br \/>\n  } else {<br \/>\n    newretval=prompt('What do you want to chronicle for <em>' + qt(towhat.substring(1), '<\/em>date ' + dwo + ', ' + towhat.substring(1).substring(6) + ' ' + months[eval(-1 + eval(towhat.substring(1).substring(4,6)))] + ' ' + towhat.substring(1).substring(0,4)<em>)<\/em> + '?  (NB: &lt;br&gt; is line feed) (append with ?password=[yourPassword] to ask for a password to access from here on)', retval);<br \/>\n  }<br \/>\n  <em>}<\/em><br \/>\n  if (newretval == null) {<br \/>\n    return retval;<br \/>\n  <em>} else if (nta == '' && newretval != '') {<br \/>\n    if (newretval.substring(0,1) == '+') {<br \/>\n      appendmode=true;<br \/>\n      if (retval != '') {<br \/>\n      if (newretval != '') xnta=newretval.substring(1);<br \/>\n      var xnewretval=retval + ' &lt;br&gt;' + newretval.substring(1);<br \/>\n      newretval=xnewretval;<br \/>\n      } else {<br \/>\n      if (newretval != '') xnta=newretval.substring(1);<br \/>\n      newretval=newretval.substring(1);<br \/>\n      }<br \/>\n    } else {<br \/>\n      xnta=newretval;<br \/>\n    }<\/em><br \/>\n  }<br \/>\n  if (newretval.indexOf('?password=') != -1) {<br \/>\n    \/\/document.getElementById('pd').innerHTML=newretval.split('?password=')[0];<br \/>\n    makepd(document.getElementById('pd').innerHTML, newretval.split('?password=')[1]);<br \/>\n  }<br \/>\n  if (newretval.indexOf('\/password\/') != -1) {<br \/>\n    \/\/document.getElementById('pd').innerHTML=newretval.split('\/password\/')[0];<br \/>\n    makepd(document.getElementById('pd').innerHTML, newretval.split('\/password\/')[1]);<br \/>\n  }<br \/>\n  if (newretval.split('?password=')[0].split('\/password\/')[0] != retval) {<br \/>\n    vr_setCookie('c' + towhat.substring(1), newretval.split('?password=')[0].split('\/password\/')[0]);<br \/>\n  }<br \/>\n  document.getElementById(towhat).innerHTML='&lt;div onblur=\"makeit(' + \"'c\" + towhat.substring(1) + \"',this.innerHTML\" + ');\" contenteditable=\"true\"&gt;' + newretval + '&lt;\/div&gt;';<br \/>\n  <em>if (range.length == 1) {<br \/>\n    range=[];<br \/>\n    tdclicklist=[];<br \/>\n  } else if (range.length &gt; 1) {<br \/>\n    document.getElementById('t' + towhat).style.backgroundColor='yellow';<br \/>\n    range.shift();<br \/>\n    if (range.length &gt;= 1) {<br \/>\n      xdwo=range[0].split(',')[1];<br \/>\n      xtowhat=range[0].split(',')[0];<br \/>\n      setTimeout(preask, 500);<br \/>\n    }<br \/>\n  } else {<br \/>\n    range=[];<br \/>\n    tdclicklist=[];<br \/>\n    setTimeout(nothing, 600);<br \/>\n  }<\/em><br \/>\n  return newretval;<br \/>\n}<br \/>\n<\/code><\/p>\n<p> &#8230; set into motion via the new <em>onclick<\/em> logic for table cells established in the document.body onload event <i>populate<\/i> function&#8217;s &#8230;<\/p>\n<p><code><br \/>\n     mstr=mstr.replace(' title=' + thedayindex + '&amp;gt;', ' <em>onclick=\"tdclick(this);\"<\/em> title=' + thedayindex + ' id=td' + tddaystr + '&amp;gt;' + alink(dmoy, tddaystr, daysofweek[eval(thedayindex % 7)]));<br \/>\n<\/code><\/p>\n<p> &#8230; where you will see us [array].<a target=_blank title='Javascript array push method information from w3schools' href='https:\/\/www.w3schools.com\/jsref\/jsref_push.asp'>push<\/a><font size=1>ing<\/font> and  [array].<a target=_blank title='Javascript array shift method information from w3schools' href='https:\/\/www.w3schools.com\/jsref\/jsref_shift.asp'>shift<\/a><font size=1>ing<\/font> and you can appreciate the value of <a target=_blank title='Javascript setTimeout method information from w3schools' href='http:\/\/www.w3schools.com\/jsref\/met_win_settimeout.asp'><i>setTimeout<\/i><\/a> delays when creating your own event simulations.<\/p>\n<p>You can join with us, trying this out at (<a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Geographicals\/diff.php?one=http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html--GETME\" title=\"monthly_chronicler.html\">the changed<\/a>) <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html--GETME\" title=\"monthly_chronicler.html\">monthly_chronicler.html<\/a>&#8216;s <a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\" title=\"Click picture\">live run<\/a> link.<\/p>\n<hr>\n<p id='mcppt'>Previous relevant <a target=_blank title='Monthly Chronicler Password Protect Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/monthly-chronicler-password-protect-tutorial\/'>Monthly Chronicler Password Protect Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\"><img decoding=\"async\" style=\"float:left;border: 15px solid pink;\" alt=\"Monthly Chronicler Password Protect Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler_pp.jpg\" title=\"Monthly Chronicler Password Protect Tutorial\"  \/><\/a><p class=\"wp-caption-text\">Monthly Chronicler Password Protect Tutorial<\/p><\/div>\n<p>When you have sensitive data involving personal information and monetary matters you ideally need to &#8230;<\/p>\n<ul>\n<li>involve SSL (ie. https: type URLs) &#8230; and as far as passwords are concerned &#8230;<\/li>\n<li>it is best to hash your passwords rather than encrypt them<\/li>\n<\/ul>\n<p> &#8230; but just bear in mind there is a fair bit to that latter idea.  Today, we are going to offer users a way to shield prying eyes from seeing their &#8220;diary&#8221; entries with our &#8220;Monthly Chronicler&#8221; web application, but we will not be hashing passwords to achieve this.  Please do not think that none of the concepts below will not affect your security of data here &#8230;<\/p>\n<ul>\n<li>somebody clearing the web browser cache &#8230; though the affect of this is that your data is wiped rather than found out<\/li>\n<li>somebody examining the HTTP Cookies separately to find your data &#8230; there is mild encryption, but as you will read on the &#8220;net&#8221;, encryption is not enough for true password protection, database usage with password hashing is much better<\/li>\n<\/ul>\n<p> &#8230; nevertheless, for the most part, what we do today extending the functionalities introduced with yesterday&#8217;s <a title='Monthly Chronicler Primer Tutorial' href='#mcpt'>Monthly Chronicler Primer Tutorial<\/a> serve a purpose for the vast majority of users on the net, that being if you indicate that you want some data not to be shared, then the user, as a reasonable person, will oblige, and not go snooping.<\/p>\n<p>Our simple approach today is that with either or both &#8230;<\/p>\n<ul>\n<li>personal details &#8230; and\/or &#8230;<\/li>\n<li>any date clicked\/touched to chronicle something<\/li>\n<\/ul>\n<p> &#8230; now has functionality available to the user (by appending ?password=[theirPassword] to their displayed data) to password protect the current <i>web browser and https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html<\/i> usage pairing.  Others not knowing this password (and personal details pairing) can still use the web application, but any HTTP Cookie stored information &#8220;does not stick&#8221; for them.<\/p>\n<p>Feel free to rejoin us, trying it out at (<a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Geographicals\/diff.php?one=http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html-GETME\" title=\"monthly_chronicler.html\">the changed<\/a>) <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html-GETME\" title=\"monthly_chronicler.html\">monthly_chronicler.html<\/a>&#8216;s <a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\" title=\"Click picture\">live run<\/a> link.<\/p>\n<hr>\n<p id='mcpt'>Previous relevant <a target=_blank title='Monthly Chronicler Primer Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/monthly-chronicler-primer-tutorial\/'>Monthly Chronicler Primer Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\"><img decoding=\"async\" style=\"float:left;border: 15px solid pink;\" alt=\"Monthly Chronicler Primer Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.jpg\" title=\"Monthly Chronicler Primer Tutorial\"  \/><\/a><p class=\"wp-caption-text\">Monthly Chronicler Primer Tutorial<\/p><\/div>\n<p>We&#8217;ve got a new web application for you today.  We&#8217;re calling it a &#8220;Monthly Chronicler&#8221;, which is a web application like a &#8220;Calendar&#8221; or &#8220;Planner&#8221; or &#8220;Diary&#8221;, where the user can personalize the entries according to a date, with whatever information they want.<\/p\n\n\n\n<p>This idea is of limited applicability unless it is a bit accountable, and at this first draft, the accountability comes in the form of saving a user&#8217;s personalized data into <a target=_blank title='Cookie information from w3schools' href='http:\/\/www.w3schools.com\/js\/js_cookies.asp'>HTTP Cookie<\/a> data form.  As you might know from online shopping experience that you have, the use of HTTP Cookies can mean a web application can resume another call of the web application and load in your previous data, ideal for a &#8220;Monthly Chronicler&#8221;.<\/p>\n<p>Other features are &#8230;<\/p>\n<ul>\n<li>use of HTML details\/summary element pairing (to allow for display. or not, of previously entered data) &#8230; nesting &#8230;<\/li>\n<li>use of HTML div contenteditable=&#8221;true&#8221; (for ease of user editing purposes)<\/li>\n<\/ul>\n<p>Join us trying it out at <a target=_blank href=\"http:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html_GETME\" title=\"monthly_chronicler.html\">monthly_chronicler.html<\/a>&#8216;s <a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\" title=\"Click picture\">live run<\/a> link. With such a web application it can suit being a web browser&#8217;s home page to &#8230;<\/p>\n<ul>\n<li><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html\" title=\"Click picture\">just show you your calendar of entries for the current year<\/a> ( https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html )<\/li>\n<li><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?today=y\" title=\"Click picture\">highlight today&#8217;s date on the &#8220;monthly chronicler&#8221;<\/a> ( https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?today=y )<\/li>\n<li><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?clicktoday=y\" title=\"Click picture\">click today&#8217;s date ready for you to &#8220;diarise&#8221;<\/a> ( https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?clicktoday=y )<\/li>\n<li><a target=_blank href=\"https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?year=2017\" title=\"Click picture\">show a previous year&#8217;s activities<\/a> ( https:\/\/www.rjmprogramming.com.au\/HTMLCSS\/monthly_chronicler.html?year=2017 )<\/li>\n<\/ul>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d38862' onclick='var dv=document.getElementById(\"d38862\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/calendar\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d38862' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d38884' onclick='var dv=document.getElementById(\"d38884\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/password\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d38884' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d38906' onclick='var dv=document.getElementById(\"d38906\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/array\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d38906' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d38943' onclick='var dv=document.getElementById(\"d38943\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/localStorage\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d38943' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Are you familiar with &#8220;LocalStorage&#8221; at the client side of web application usage, as an alternative to HTTP Cookie usage? It can store much more information than HTTP Cookies, but has no expiry date as such. This is not to &hellip; <a href=\"https:\/\/www.rjmprogramming.com.au\/ITblog\/monthly-chronicler-localstorage-tutorial\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,14,37],"tags":[103,180,2591,2584,2442,1860,2310,2582,342,386,400,2586,576,652,2415,2585,861,1564,2583,997,2588,2135,1114,1126,2587,2589,1682,2311,1581,2590,1319,2409],"class_list":["post-38943","post","type-post","status-publish","format-standard","hentry","category-elearning","category-event-driven-programming","category-tutorials","tag-array","tag-calendar","tag-catch","tag-chronicler","tag-contenteditable","tag-cookie","tag-details","tag-diary","tag-div","tag-encryption","tag-event","tag-hashing","tag-html","tag-javascript","tag-localstorage","tag-monthly-chronicler","tag-onclick","tag-password","tag-planner","tag-programming","tag-propogate","tag-push","tag-security","tag-settimeout","tag-shift","tag-simulation","tag-ssl","tag-summary","tag-table-cell","tag-try","tag-tutorial","tag-web-storage"],"_links":{"self":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/38943"}],"collection":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/comments?post=38943"}],"version-history":[{"count":6,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/38943\/revisions"}],"predecessor-version":[{"id":38952,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/38943\/revisions\/38952"}],"wp:attachment":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/media?parent=38943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/categories?post=38943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/tags?post=38943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}