📜 ⬆️ ⬇️

Happy end of my story with a script for comfortable reading Habr

In my first post I described why I chose the option of studying JavaScript with the fulfillment of the task I had set myself to write a browser extension. Since that time, I have never had the idea that everything is in vain. As the script was being written, the mandatory points of ordinary study — thematic articles and educational materials — did not go anywhere. However, in this case there was an excellent catalyst - your own imagination.
Since I constantly read Habr, some, in my humble opinion, roughness in usability immediately found a place in the list of irresistible desires for improvement.

And the place of honor was taken by the idea of ​​displaying tracker updates without the need for additional transitions and, preferably, in one block.
Of course, the whole point was how to get the data, but you need to show them somewhere. Therefore, the path from simple to complex began with a container for the received updates:

var trackerLink = document.querySelector('.userpanel > .top > a.count'); trackerLink.href = '#tracker_updates'; var updates = document.createElement('ul'); updates.className = 'updates'; updates.style.display = 'none'; userpanel.appendChild(updates); trackerLink.onclick = function (event) { event.preventDefault(); updates.style.display = (updates.style.display != 'none' ? 'none' : 'block'); }; 


And logically I started writing the function of parsing the tracker pages:
')
  function getUpdates(url, getUrl) { var xmlhttp = new XMLHttpRequest(); xmlhttp.responseType = 'document'; xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var tracks = xmlhttp.responseXML.querySelectorAll(url); for (i = 0; i < tracks.length; i++) { var post = tracks[i]; post.removeChild(post.firstElementChild); updates.appendChild(post); post.outerHTML = post.outerHTML.replace(/td/g, "li"); } } } xmlhttp.open("GET", getUrl, true); xmlhttp.send(); } getUpdates('tr.new > td.event_type', '/tracker/subscribers/'); getUpdates('tr.new > td.mention_type', '/tracker/mentions/'); 


The result was a list of updates to subscribers and new references to the user. That's right, the main thing - the update posts. And with them everything happened a little differently, as it was required to still display the counter of new comments for each post:

  (function () { var xmlhttp = new XMLHttpRequest(); xmlhttp.responseType = 'document'; xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var tracks = xmlhttp.responseXML.querySelectorAll('tr.new > td.post_title'); var commentCounts = xmlhttp.responseXML.querySelectorAll('tr.new > td.comment_count'); for (i = 0; i < tracks.length; i++) { var track = tracks[i]; var commentCount = commentCounts[i].firstChild.nextSibling; commentCount.className = 'count'; track.appendChild(commentCount); updates.appendChild(track); track.outerHTML = track.outerHTML.replace(/td/g, "li"); } }; xmlhttp.open("GET", '/tracker/', true); xmlhttp.send(); })(); 


I wrapped the request in an anonymous self-calling function because all the parts described earlier were executed as a single named function.
Here's what it looks like in the screenshot.
image


Everything is good, but surely not everyone wants every time to click the button to display all the hidden pictures or to expand the tree of answers to comments. Suddenly you need only a custom panel. And here it was decided to finally add management settings, so that comfort was truly such. Almost immediately came to the option of storing the settings in local storage, and then the process got up, since it would be more appropriate to use the methods for working with local storage for each browser. I started by studying the Chrome Storage API and ... ... I finished it too, because it’s too expensive to build an amusement park for everyone, but I wanted a happy future for everyone at once. There were some ideas, but due to lack of experience and just for the sake of the advice of the experienced he turned to spmbt for help. He just suggested to me an elegant version in the form of three simple functions:

 var setLocStor = function(name, hh){ if(!localStorage) return; localStorage['custom_'+ name] = JSON.stringify({h: hh}); }, getLocStor = function(name){ return (JSON.parse(localStorage && localStorage['custom_'+ name] ||'{}')).h; } ,removeLocStor = function(name){localStorage.removeItem('custom_'+ name);} 


As far as I understand, in the case of using the Chrome Storage API, requests will be executed asynchronously (please correct me, as I can be wrong).

I will not torture you with footcloths with the code and briefly mention that I created named checkboxes with the default value disabled, and to disable the feature, the value was changed to enabled. When you click on each checkbox, a key-value pair is written to local storage. When the settings block is called, the local storage records are read and the corresponding states are assigned to the checkboxes (if the value of the disabled key is set, the checkbox is false and if enabled is true). The functions responsible for the feature “listen” to the value of their key in local storage and are performed only if the value is disabled, that is, the checkbox “disable” in the settings is not set.
Screenshot with settings
image


And at the end of a long story a small bonus in the form of displaying current karma and user rating by clicking on the user's avatar in his comments.
What it looks like
image


Well, that's all, I was convinced that combining the pleasant with the useful in learning is not only possible, but necessary. It is more interesting to study if there is an incentive that comes every day in the form of a couple of ideas. Even if the result of the work was useful only to you and a few friends, then there is absolutely no reason to think about the dubiousness of the event - you have received not just another studied minimum, but a new hobby.

Now, the development of the script will depend on the free time and new offers / womens, and I will continue to consolidate the knowledge gained in practice and invent more complex tasks for myself to further study JavaScript.

Thanks to everyone who read it and, I hope, convinced someone to repeat the “samurai way”.
I would appreciate constructive criticism and recommendations.

Chrome webstore link
Github Link

Update - now the karma and user rating are displayed by clicking on his avatar (previously the event “blocked” click on the user name and the button to display a link to this comment). I hope this small change arrived in time.

Source: https://habr.com/ru/post/192444/


All Articles