nostromos bLog






* all entries (445)
* concerts (28)
* misc (120)
* techtalk (18)
* travel (241)
  `-bruxelles_07 (8)
  `-canada_14 (22)
  `-hongkong_09 (13)
  `-iceland_10 (14)
  `-ireland_16 (7)
  `-japan_13 (22)
  `-paris_06 (1)
  `-poland_10 (3)
  `-russia_10 (12)
  `-scotland_15 (11)
  `-sweden_09 (10)
  `-taiwan_12 (22)
  `-tokyo_08 (14)
  `-usa_09 (10)
* zoo (38)
  `-abroad (8)
  `-linz (3)
  `-misc (11)
  `-schoenbrunn (16)


08(01), 07(03), 06(03), 05(02), 04(02), 03(02)
12(02), 11(01), 10(08), 09(03), 07(17), 06(01), 05(04), 04(03), 03(02), 02(02), 01(06)
12(05), 11(02), 10(01), 09(01), 08(02), 07(04), 06(01), 05(02), 04(03), 03(02), 02(02), 01(01)
12(01), 11(02), 09(09), 08(16), 07(02), 06(03), 05(04), 04(03), 02(03), 01(02)
12(03), 11(01), 10(02), 09(01), 08(23), 07(03), 06(02), 05(01), 04(02), 03(02)
12(03), 11(02), 10(01), 09(01), 08(23), 05(02)
09(04), 08(01), 06(01), 05(02), 04(02), 03(01), 02(01)
11(01), 10(02), 09(15), 08(01), 07(02), 06(04), 04(12), 01(06)
12(05), 11(01), 10(06), 09(12), 08(02), 07(02), 06(01), 05(01), 04(10), 02(01), 01(05)
12(02), 08(01), 07(15), 06(02), 05(03), 02(02), 01(03)
12(05), 11(01), 07(24), 06(06), 05(03), 04(02), 01(01)
12(01), 11(01), 10(07), 09(01), 08(04), 07(05), 06(04), 05(06), 04(01), 03(04), 02(06), 01(04)
12(04), 11(02), 10(03), 09(04), 08(03), 07(04), 04(01)
07(01), 05(01)
08(01)
10(01)

Mon, 21 Oct 2013
nginx, subs_filter, and perl (0 comments)
++ alert ++ tech-talk ++ alert ++ tech-talk ++ alert ++
nina was surfing one of my many galleries on my homepage and then mentioned, that it would be much more convenient to proceed to the next image in the gallery by clicking on the image, rather then moving the mouse to the "<<Prev" or "Next>>" links on each gallery slide page. and, as always, she was right. so, in order to change the galleries, i had two possibilities. first one would be to rerun the llgal command on all of my galleries (which would be a total of 446 galleries, at the time of writing). or, in other words this means craft a nice bash one-liner, and then wait a long time and consume a lot of cpu power. second approach would be to tweak my nginx configuration. and that was the approach i preferred, as it would give me more flexibility in changing all galleries at once in one central file. after a little research it seemed the "subs_filter" module (mind the "s" here, as there's also a "sub_filter" module that has several limitations that made it rather useless for this task) was the perfect choice. and soon i had my clickable image, but it had some flaws, like what if it was the last slide? the crafted link would then point to a non existing slide. hm, not very nice. this meant digging again and also a little deeper into the possibilities nginx offers to modify html code and configurations. and while i'm at it, why not split the image into two clickable areas. one on the right half of the image to proceed to the next slide, and one on the left to go back to the previous slide? research showed the solution to this problem would either involve either a lua or a perl module to do the trick. of course i went the camel path and crafted a nice little sub-routine that would create a variable that i could feed back to nginx and back to the "subs_filter". here is the nginx.conf part:
location ~ "(.*)/slide_(\d*)\.html$" { subs_filter '<img src([^>]*>)' '$slide_navigation<img src$1\n </div>' r; }
for all locations that contain "/slide_<some_number>.html" run the sub filter, and change all occurrences of the first argument to the stuff defined in the second argument. to get stuff into the "$slide_navigation" variable, i used the "perl_set" command. this command is run as soon as nginx finds the variable name in a directive, which means, it is only called when there's a request for a document matching the "/slide_*.html" pattern. here is the perl part of the magic in the nginx.conf file:
perl_set $slide_navigation 'sub { my $r = shift; my $curr_slide = $r->uri; $curr_slide =~ m/(.*)\/slide_(\d*)(\..*)$/; my $path = $1 . "/slide_"; my $path_prefix = $1; my $slidenumber = $2; my $path_postfix = $3; my $prev_slide = $path . (sprintf("%0" . length($slidenumber) . "d", (($slidenumber - 1)))) . $path_postfix; my $next_slide = $path . (sprintf("%0" . length($slidenumber) . "d", (($slidenumber + 1)))) . $path_postfix; if (! -e "/path/to/htdocs/$prev_slide") { $prev_slide = $path_prefix . "/"; } elsif (! -e "/path/to/htdocs/$next_slide") { $next_slide = $path_prefix . "/"; } my $slide_navigation = "<div [...]><a [...] $prev_slide>" . "<div [...]><a [...] $next_slide>" ; return $slide_navigation; };';
the "<div [...]>" and "<a [...]>" tags at the end include loads of css stuff to create the clickable zones for the previous and next image. additionally the "<div>" tag wraps around the "<a>" and "<img>" tag, so i can place the link directly on the image. notice the "</div>" tag is closed in the "subs_filter" directive, not in the perl part. for more details, feel free to have a look at the page source code of any gallery. so far i was pleased with my achievements, but now that i have the links to the previous and next slide, i lost the ability to right click on the image to copy the image location - that is not what i had intended. looking at the html code of the slides i found out, that llgal always places the image file name in a line after the actual image. it is only prefixed by blanks, so that makes it easy to match with a regular expression - a good thing for another "subs_filter". so i added it right after the first one in the nginx configuration file. here is the second "subs_filter" in the nginx.conf file:
subs_filter '^\ *((_|i)mg_\d*)' '<a class="image" href="./$1.jpg">$1</a>' ir;
ha, a link to the image location right under the image (with it's own css class definition) - nice. awesome, so now you can click on the images to get to the previous or next image, or back to the index if there is no previous or next image, and i a have a link to the picture location too. but while i'm (still) at it, why not add google analytics to every html document? and - you might have guessed it - once more, another line of "subs_filter" does the trick. google recommends to place it right before the closing "HEAD" tag. here is the google analytics "subs_filter" part:
subs_filter '(</head>)' '$google_analytics$1' r;
and here is the perl part for the GA magic:
perl_set $google_analytics 'sub { my $google_analytics = <<"EOF"; <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push([\'_setAccount\', \'UA-45399354-1\']); _gaq.push([\'_trackPageview\']); (function() { var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true; ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\'; var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s); })(); </script> EOF };';
done. excellent, a clickable gallery, google analytics code included, all without modifying a single existing html document. all hail to the power of nginx, perl, and regular expressions.

top [
^
]

[ prev | index | next ]