Links
-
Want to use some popular JS library? Think carefully about that.
-
A nice writeup of Javascript’s serious attempt to be serious. Basically newish features.
Hilarious Idiosyncrasies
Behold this gem.
('00'+(N.getMonth()+1).toString()).slice(-2);
I was trying to make a simple (ISO8601) date display show up on a web page and I learned some very fun things.
-
Javascript has no zerofill or sensible string formatting.
-
getMonth()
function returns indexed from 0. So September comes back as 8! -
Adding the date to a string silently makes the date number a string. Technically the
toString()
method is not needed here — but the parentheses are in this case.
JSON
Sometime, though rarely, it seems like a flat text file won’t do what you need; if you’re ever tempted to reach for XML, then JSON is probably appropriate. My Python notes cover dealing with JSON in Python programs.
JSON needs to use double quotes — it’s not optional like Python. For full details of just what comprises JSON formatting this is a good resource. Or check out https://jsonlint.com to see if your sample is valid.
But what if you’re just trying to sort out a mess on the command line?
Then it’s good to use the program jq
which does all JSON related
things a command line person would ever want done.
With no fancy filters or other arguments, jq
does a nice job of
formatting and syntax highlighting JSON.
Of course it does a lot more than that! Here is an example of trying to find out the weather service’s grid values for a certain geographic location.
$ wget -qO- --header="${UA}" 'https://api.weather.gov/points/43.0318815,-78.883944' |\
> jq '.properties.gridX,.properties.gridY'
34
53
Just need to look at some big JSON file and want to use a pager and keep the nice syntax highlighting?
jq -C . < assets/indexes/1.16.json | less -r
A nice overview of
jq
.
Here is a nice web interface to try jq
syntax
out live.
Often I need the simplest stupid little JSON thing and I just need to
see a quick reference to make sure I don’t confuse anything with
Python dict thinking. Here is that example with an example of how to
get jq
to check it.
$ cat xed.json
{
"name": "Chris X Edwards",
"website": "xed.ch"
}
$ jq '.' < xed.json
{
"name": "Chris X Edwards",
"website": "xed.ch"
}
Redirect
Obviously a symlink is best, but sometimes you need for people to type a directory like http://xed.ch/r and see a PDF.
<!DOCTYPE html>
<html>
<meta http-equiv="location" content="URL=http://xed.ch/resume/resume.pdf" />
<head><title>One Cool Resume On The Way</title></head>
<body>
<p>Attempting to redirect to: <b>http://xed.ch/resume/resume.pdf</b></p>
<p>Looks like you sensibly have disabled JavaScript! You win the internet!</p>
<p><a href="http://xed.ch/resume/resume.pdf">Click here</a> to do what must be done.</p>
<script>window.location.href="http://xed.ch/resume/resume.pdf";</script>
</body> </html>
Miscellaneous
This is an interesting way to specify a URL. Just type this in the address bar of the browser.
javascript:location.href="http://www.xed.ch";
Identity Operator
The ===
operator, properly called the identity equality operator,
does not check for any type conversion. It compares the values as it
is and produces the output on its basis. An example: '0' == 0
is true
but
'0' === 0
is false
. Makes perfect sense! Another example is null
compared to undefined
which has the same result.
Time And Date
<head><script type="text/javascript">
function fmtime() {
N= new Date(); H= N.getHours(); M= N.getMinutes(); S= N.getSeconds();
UH= N.getUTCHours();
Z= '00'; H= (Z+H).slice(-2); M= (Z+M).slice(-2); S= (Z+S).slice(-2);
y= N.getFullYear();
m= (Z+(N.getMonth()+1)).slice(-2);
d= (Z+N.getDate()).slice(-2);
o= H+':'+M+':'+S+' ' +y+'-'+m+'-'+d +' (' +UH+M+'+0)'
document.getElementById('clk').innerHTML= o
return fmtime;
}
</script></head>
<body onload="setInterval(fmtime(),1000);">
Current time:
<span id="clk" style="color:red"></span>
</body>
Note that this uses setInterval()
rather than setTimeOut()
.
Some
people use setTimeOut()
and call it recursively. Apparently this is
ok and not going to cause memory problems because of some weirdness
with the event loop. Still, it smells bad to me. If you need another
reason, the time out tries to really wait doing nothing for the
specified interval. Ironically. So if the code after the interval
takes a long time, the timeout still waits the specified amount of
time. The setInterval()
on the other hand sticks to a periodic
schedule as best it can. If your interval is 1s and your computation
takes .5s, the thing still fires every second.
This example also shows how to get a function to fire immediately and
then after every interval. The trick is to call it during the
setInterval()
function and have that function return itself.
This example also shows how to handle zerofill padding format problems.
Automatically Refreshing A Page
This will reload the page every 2 seconds.
<body onload="javascript:setTimeout("location.reload(true);",2000);">
How Big Is the Window or Screen
Note this is not recommended for serious purposes without way more research due to browser inconsistencies etc. This is just a quick tip that helped me get some information about my browser’s situation.
<html> <body onload="update_size()" onresize="update_size()"> <script> function update_size() { // Screen dimensions 1920x1280, that kind of thing. var dispw = window.screen.availWidth; var disph = window.screen.availHeight; // Visible document size. var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; document.getElementById("showw").innerHTML = width.toString(); document.getElementById("showh").innerHTML = height.toString(); document.getElementById("showsw").innerHTML = dispw.toString(); document.getElementById("showsh").innerHTML = disph.toString(); } </script> Screen dimensions: <span id="showsw">NA</span>, <span id="showsh">NA</span> <br> Document dimensions: <span id="showw">NA</span>, <span id="showh">NA</span> </body> </html>
Toggle Two Things
I created this to allow the user to toggle between displaying two SVG charts so that the differences between them could be more apparent.
<html> <body> <head><title>Toggle Test</title></head> <script type="text/javascript"> top.n= 0 function toggle_div() { n++; n%=2; if (n) { document.getElementById('one').style.display='none'; document.getElementById('two').style.display='block'; } else { document.getElementById('one').style.display='block'; document.getElementById('two').style.display='none'; } } </script> <span style="background-color:#cecece;" onclick="toggle_div();">Click me to toggle.</span> <div id="two" style="display:none;">TWO</div> <div id="one">ONE</div> </body> </html>
This is embeddable so you can try it out right here.
Spoilier Alerts
Related to general toggles is the idea of a spoiler alert. I programmed this technique the correct JavaScript way, by…
<div id="spoiler" style="display:none">
Secret message goes here.
</div>
<button title="Click to show/hide content" type="button"
onclick="if(document.getElementById('spoiler') .style.display=='none')
{document.getElementById('spoiler')
.style.display=''}else{document.getElementById('spoiler')
.style.display='none'}">Show/hide</button>
Radio Selection
<script type="text/javascript"> function radio_select(I) { var items= document.getElementsByClassName("item"); var x; for (x = 0; x<items.length; x++) { items[x].style.display = "none"; } document.getElementById(I).style.display='block'; } </script> <div class="item" id="A" style="display:block;"> <p><b>Algeria</b></p> </div> <div class="item" id="B" style="display:none;"> <p><b>Bulgaria</b></p> </div> <div class="item" id="C" style="display:none;"> <p><b>Cambodia</b></p> </div> <div class="item" id="D" style="display:none;"> <p><b>Dominican Republic</b></p> </div> <div class="item" id="E" style="display:none;"> <p><b>Egypt</b></p> </div> <div class="item" id="F" style="display:none;"> <p><b>France</b></p> </div> <div class="item" id="G" style="display:none;"> <p><b>The Gambia</b></p> </div> Click search term to select. <table border="on"> <tr> <td><span style="background-color:#ce7777;" onclick="radio_select('A');">Algeria</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('B');">Bulgaria</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('C');">Cambodia</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('D');">Dominican Republic</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('E');">Egypt</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('F');">France</span></td> <td><span style="background-color:#ce7777;" onclick="radio_select('G');">The Gambia</span></td> </tr> </table>
This is embeddable so you can try it out right here.
Algeria
Algeria | Bulgaria | Cambodia | Dominican Republic | Egypt | France | The Gambia |
It is possible to have the choice be set randomly every time the page
is reloaded. For example maybe you want to have many different search
engines used randomly from a single search box. To do this, rename the
ids above something like i0
, i1
, i2
, etc. and then add this.
<body onload="radio_select('i'+Math.floor(Math.random()*document.getElementsByClassName('item').length))">
HTML 5 Sliders
HTML 5 is fully of fancy new features. One that caught my eye for a
particular project I was working on is the new <input>
attribute
range. This basically allows slider bars to be an input method for
HTML forms. That’s almost never useful (which is why I suspect I
rarely see this in the wild) but when it is, it is very nice that it’s
built in these days. Here’s the
official docs.
Here’s an example I made that shows off a minimal use which updates the page, i.e. no form submission necessary for being useful.
<html> <body onload="document.getElementById('SValue').innerHTML=128"> 0 <input type="range" max="255" onchange="document.getElementById('SValue').innerHTML=this.value" /> 255 Value: <b id="SValue" >JavaScript Disabled!</b> <br/> 0 <input type="range" id="S1" max="300" value="5" onchange="document.getElementById('S2Value').setAttribute('width',this.value)" /> 300 <br/> <svg> <rect id="S2Value" x="0" y="0" width="5" height="10"/> </svg> </body> </html>
0 300
HTML 5 Canvas Tag
The canvas feature of HTML5 really changed the potential of Javascript. Being able to arbitrarily put points on the screen changed Javascript, for me, from a clumsy form box "validation" system to a much more interesting tool capable of really anything.
Today the problem with the canvas tag is that there is these days often an even better solution, SVG. Javascript also can control that. There are a lot of similarities as far as the Javascript goes. The main difference seems to be performance in certain contexts. If you don’t need the browser (as opposed to your Javascript code) to keep track of entities, then canvas is a much quicker way to render vectors to bitmap. However, if you want to have the browsers keep track of things so that you can, for example, style an element with a style sheet, then SVG is the best method. More details about this decision can be found here.
<p> <canvas id="canvas" width="838" height="220"> </canvas> <script> var canvasContext = document.getElementById("canvas").getContext("2d"); canvasContext.fillStyle = 'rgba(225, 225, 225, 1)'; canvasContext.fillRect(0, 0, 838, 220); canvasContext.fillStyle = 'rgba(125, 12, 200, 0.7)'; canvasContext.fillRect(250, 25, 150, 100); canvasContext.beginPath(); canvasContext.arc(450, 110, 100, Math.PI * 1/2, Math.PI * 3/2); canvasContext.lineWidth = 15; canvasContext.lineCap = 'round'; canvasContext.strokeStyle = 'rgba(25, 212, 200, 0.7)'; canvasContext.stroke(); canvasContext.beginPath(); canvasContext.arc(350, 110, 100, Math.PI , Math.PI *4); canvasContext.lineWidth = 15; canvasContext.lineCap = 'butt'; canvasContext.strokeStyle = 'rgba(202, 2, 202, 0.7)'; canvasContext.stroke(); </script> </p>
Output Of canvas Tag Example
Auto Complete
It’s all the rage to have a web utility that has some kind of form box that just can’t wait until you’re done typing. It has to automatically suggest a list of possibilities which remain, based on the constraint of what you’ve typed so far. This functionality is pretty well implemented in jQuery and there’s no need to reinvent the specific JavaScript code. However, using this effectively can be somewhat tricky. Most web resources seem to focus on a language, which for search engine purposes I will not mention, that is infamous for being a disaster with respect to web security. There are alternatives! The autocomplete function of jQuery can operate in many ways and the mode where it requests an external link to give it hints can be crafted in any way you like. I’m going to show how to use autocomplete with straight Python with no frameworks or exotic dependencies whatsoever.
First you need your HTML:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>A Tiny Test Of jQuery Autocomplete</title> <link rel="stylesheet" href="./jquery-ui.css" /> <script src="./jquery-1.8.2.js"></script> <script src="./jquery-ui.js"></script> <script> $(function() { $( "#tags" ).autocomplete({ source:"./tinysuggester.py" }); }); </script> </head> <body> <p>Test autocomplete with a Unix command.</p> <div class="ui-widget"><label for="tags">Search: </label><input id="tags" /></div> <p>Look <a href="http://api.jqueryui.com/autocomplete/">here</a> for specifications on jquery's autocomplete function. </p> <p>These required resources can be installed locally to ensure stability.</p> <ul> <li><a href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css"> The jquery CSS</a></li> <li><a href="http://code.jquery.com/jquery-1.8.2.js"> The JavaScript of jQuery itself</a></li> <li><a href="http://code.jquery.com/ui/1.9.0/jquery-ui.js"> The JavaScript of jQuery's UI widgets</a></li> <li><a href="./tinysuggester.py"> The suggester script</a></li> </ul> </body> </html>
First note that you need the jQuery software. Its location is outlined in the bottom part of the HTML. Just download this and keep a local copy. You’ll need the general jQuery stuff, the jQuery User Interface module and the jQuery style sheet (CSS) to make it all work.
The second thing to note is that the part of this web page
that is important to us happens in the last <script>
tag. This is
where the autocomplete
function is deployed. The important thing to
notice is the source
reference. This is where the completion routine
will take its list of suggestions from. It turns out that you can put
a static list there ( formatted either {"hint1":"rhino",
"hint2":"rhesus monkey"}
or ["ash","alder","aspen"]
- but don’t use
single quotes!).
In our example, the JavaScript will be having the browser call another URL and take the contents of what is delivered and make that into the suggestion list. So, you need a web resource that can produce the desired list. Again, this could be static, but just living on the remote server. There’s not much point to this. What you’re really after is spontaneously generating a list based on a sensible heuristic applied to your data set.
The obvious examples are to suggest all words that are in your master list which start with the letters the user just typed. For smaller lists, you could look for all records which contain the typed letters anywhere in them. You could do either of those things but with a cut off limit so no more than 10 or 50 suggestions are ever returned. If your data set is very big and contains other hints, you could do a quick sort by relevance (maybe most popular) before sending only the first 10.
Here is an example implemented in Python which will prompt with Unix
commands (just from /usr/bin
) which begin with the letters the user
has typed in. Note that when the user types some stuff, there are some
(controllable) parameters that
tell the jQuery routines how long to wait and how persistent to keep
submitting autocomplete attempts. When a request is made, however, the
URI that you specify in the source
field will be called with an
additional CGI style argument appended. If the URI is
./tinysuggester.py
as in our example and the user types "ps2", the
client will make a request that looks like
./tinysuggester.py?term=ps2
. Here’s what you can do with that.
#!/usr/bin/python import os def getpossibles(t): MAX= 10 # Return no more than this many suggestions. ol= list() # Output list. for f in os.listdir('/usr/bin'): if f.startswith(t): ol.append(f) MAX -= 1 if not MAX: break return ol # Handle the input which will look like this: # /path/suggester.py?term=ps2 term= os.environ["QUERY_STRING"].split('=')[1] possibles= getpossibles(term) content_type= 'Content-type: text/plain\n\n' print content_type + str(possibles).replace("'",'"')
As you can see the complex part is in the function getpossibles
.
This is the real essence of what the autocomplete is supposed to do
for your application which is why you must make your own. Here’s an
example of another one that uses a static list and no limits.
def getpossibles(t): db= ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"] return [w for w in db if t in w] # Return list of possibles.
You could (and often will need to) write one that makes a database look up and returns the query results.