<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HTML &#8211; Johnny Morano&#039;s Tech Articles</title>
	<atom:link href="https://jmorano.moretrix.com/tag/html/feed/" rel="self" type="application/rss+xml" />
	<link>https://jmorano.moretrix.com</link>
	<description>Ramblings of an old-fashioned space cowboy</description>
	<lastBuildDate>Sat, 09 Apr 2022 07:31:04 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>

<image>
	<url>https://jmorano.moretrix.com/wp-content/uploads/2022/04/cropped-jmorano_emblem-32x32.png</url>
	<title>HTML &#8211; Johnny Morano&#039;s Tech Articles</title>
	<link>https://jmorano.moretrix.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Datatables and Perl (and a little bit of jQuery)</title>
		<link>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/</link>
					<comments>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/#comments</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Wed, 09 Oct 2013 14:05:45 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=1014</guid>

					<description><![CDATA[Recently I&#8217;ve stumbled on a pretty cool OpenSource project called &#8221;datatables&#8221; (http://datatables.net/), which allows to easily create tables&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Recently I&#8217;ve stumbled on a pretty cool OpenSource project called &#8221;datatables&#8221; (<a title="Datatables" href="http://datatables.net/" target="_blank" rel="noopener">http://datatables.net/</a>), which allows to easily create tables in HTML that can be:</p>



<ul class="wp-block-list"><li>sorted</li><li>searched</li><li>paginated</li><li>scroll infinitely</li><li>themed</li><li>&#8230;</li></ul>



<p>And most important: it&#8217;s for free! I&#8217;ve always wanted to create an infinite scrolling table and now it&#8217;s just too easy:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$(document).ready( function() {
    oTable = $('#ip_data').dataTable( {
        "bProcessing":     true,
        "bServerSide":     true,
        "bPaginate":       true,  
        "bScrollInfinite": true,
        "bScrollCollapse": true,
        "sScrollY":        "200px",
        "sAjaxSource":     "get_ip_data.pl",
    } );
} );
</pre>



<p>And that&#8217;s it! Well, ok, you need to include the Javascript file and CSS files of the Datatables Project of course and you need to create the table in HTML.</p>



<p>For instance:</p>



<figure id="ip_data" class="wp-block-table"><table><thead><tr><th>IP</th><th>Country</th><th>City</th><th>Latitude</th><th>Longitude</th></tr></thead><tbody><tr><td>Loading data from server</td></tr></tbody><tfoot><tr><th>IP</th><th>Country</th><th>City</th><th>Latitude</th><th>Longitude</th></tr></tfoot></table></figure>



<pre class="wp-block-preformatted">&nbsp;</pre>



<p>And then you will need a Perl script providing you the data for the table.<br />The below example allows to</p>



<ul class="wp-block-list"><li>search the tables</li><li>scroll infinitely</li><li>sort on the columns</li></ul>



<p>It also supplies the Datatables table with a total amount or rows in the database table.</p>



<p>This following script will be saved as &#8221;get_ip_data.pl&#8221;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/usr/bin/perl
use strict; use warnings;
use DBI;
use JSON;
use CGI;

my @columns = qw/ip country_name city latitude longitude/;

my $q = CGI-&amp;gt;new;
my $db = DBI-&amp;gt;connect("dbi:mysql:host=localhost;db=testdb", 'testuser', 'xxxsecret');

my $params = $q-&amp;gt;Vars;

# Get the total count of rows in the table
my $sql_count = "select count(id) from geo_data";
my $count = $db-&amp;gt;selectrow_arrayref($sql_count)-&amp;gt;[0];

# Start building up the database query
my @values;
my $sql = "select ip,country_name,city,latitude,longitude from geo_data";

# if a search parameter was supplied in the AJAX call, build the WHERE part in the SQL statement
if( $params-&amp;gt;{sSearch} ){
    $sql .= ' WHERE ';
    $sql .= 'ip LIKE ? OR country_name LIKE ? or city LIKE ? or latitude LIKE ? or longitude LIKE ?';
    push @values, ('%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%');
}

# if a sorting parameter was supplied in the AJAX call, build up the ORDER BY part in the SQL statement
if( $params-&amp;gt;{iSortingCols} ){
    $sql .= ' ORDER BY';
    foreach my $c (0 .. ( $params-&amp;gt;{iSortingCols} -1 )){
        $sql .= ' ' . $columns[ $params-&amp;gt;{"iSortCol_$c"} ] . ' ' . $params-&amp;gt;{"sSortDir_$c"};
        $sql .= ','
    }
    $sql =~ s/,$//;
}

# Limit the output and also allow to paginate or scroll infinitely
$sql .= " LIMIT ? OFFSET ?";
push @values, (($params-&amp;gt;{iDisplayLength} &amp;gt; 0 ? $params-&amp;gt;{iDisplayLength} : 25), ( $params-&amp;gt;{iDisplayStart} // 0));

# Fetch the data from the database
my $data = $db-&amp;gt;selectall_arrayref($sql, { Slice =&amp;gt; [] }, @values);

# Return the JSON object
print $q-&amp;gt;header('application/json');
my $json = encode_json({ aaData =&amp;gt; $data, iTotalRecords =&amp;gt; $count, iTotalDisplayRecords =&amp;gt; $count, sEcho =&amp;gt; int($params-&amp;gt;{sEcho}) });
print $json;
</pre>



<p>An example can be found overhere: <a title="Charon Map" href="http://www.moretrix.com/~insaniac/map/map.pl" target="_blank" rel="noopener">http://www.moretrix.com/~insaniac/map/map.pl</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Perl/Ajax with JSON</title>
		<link>https://jmorano.moretrix.com/2011/03/perlajax-with-json/</link>
					<comments>https://jmorano.moretrix.com/2011/03/perlajax-with-json/#respond</comments>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Tue, 29 Mar 2011 14:18:42 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=555</guid>

					<description><![CDATA[I just discovered this very interesting article about Perl, CGI, Template and Ajax using JSON. I&#8217;m going to&#8230;]]></description>
										<content:encoded><![CDATA[<p>I just discovered this very interesting article about Perl, CGI, Template and Ajax using JSON.</p>
<p>I&#8217;m going to use to beef up my image browser which I quickly wrote to simply the contents of directory full with images. (can be found overhere <a href="http://yamamoto.moretrix.com/~insaniac/grtp/">http://yamamoto.moretrix.com/~insaniac/grtp/</a></p>
<p>Here&#8217;s the link to the <a href="http://rohan.almeida.in/archives/get-started-with-jquery-ajax-and-json-in-your-perl-web-applications">article</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/03/perlajax-with-json/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Retrieve a file from an authenticated website (in Perl)</title>
		<link>https://jmorano.moretrix.com/2011/02/retrieve-a-file-from-an-authenticated-website-in-perl/</link>
					<comments>https://jmorano.moretrix.com/2011/02/retrieve-a-file-from-an-authenticated-website-in-perl/#comments</comments>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Wed, 09 Feb 2011 09:52:56 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[HTML]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=475</guid>

					<description><![CDATA[At my daily job as a Perl developer, I was asked to write a Perl script which would&#8230;]]></description>
										<content:encoded><![CDATA[<p>At my daily job as a Perl developer, I was asked to write a Perl script which would download a backup file from a certain web interface. The file however, was in a secured part of the web site. This means, that the script would first have to authenticate against the web site and then afterwards retrieve the requested file.</p>
<p>Thanks to the great <a href="http://search.cpan.org/~gaas/libwww-perl-5.837/lib/LWP.pm"><code>LWP</code></a> Perl module, this is again a rather easy and simple job.<br />
<span id="more-475"></span><br />
Let&#8217;s start by explaining the script step-by-step:</p>
<ol>
<li>Call your modules
<pre class="brush:perl">
#!/usr/bin/perl
use strict; use warnings;

use LWP;
use HTTP::Cookies;
use HTTP::Request;
use File::Path qw{mkpath};
</pre>
<p>The modules <code>HTTP::Cookies</code> and <code>HTTP::Request</code> are required to create the cookie jar file and to make a HTTP request (duh!). These two modules will create the objects that are required for the LWP user-agent object we are about to create.
</li>
<li>Check your temporary path:
<pre class="brush:perl">
my $HOME = $ENV{HOME} . '/tmp';
mkpath $HOME   unless -d $HOME;
</pre>
<p>We will need this location to save our cookie jar file and the file we want to download
</li>
<li>Create a cookie jar and a LWP user-agent:
<pre class="brush:perl">
# create a cookie jar on disk
my $cookies = HTTP::Cookies->new(
        file     => $HOME.'/cookies.txt',
        autosave => 1,
        );

# create an user-agent and assign the cookie jar to it
my $http = LWP::UserAgent->new();
$http->cookie_jar($cookies);
</pre>
<p>No rocket science here, just create the objects!
</li>
<li>Send the authentication request:
<pre class="brush:perl">
# try to log in
my $login = $http->post(
        'https://www.example.com/auth/login.pl', [
            username => 'user',
            password => 'secret', ]
        );
</pre>
<p>Once authenticated, the web site will create a cookie containing a session ID. This cookie will allow us to download the file we need from the secured part of the web site.
</li>
</ol>
<p>From this point on, it is required to check whether the log in succeeded and then continue with downloading the file. If the log in failed, an error message should be displayed with the reason on the failure.</p>
<pre class="brush:perl">
# check if log in succeeded
if($login->is_success){
    print "- logged in successfullyn";
    print "- requesting file, might take a whilen";

    # make request to download the file
    my $url       = 'https://www.example.com/auth/files/backup.zip';
    my $file_req  = HTTP::Request->new('GET', $url);
    my $get_file  = $http->request( $file_req );

    # check request status
    if($get_file->is_success){
        print "--> downloaded $url, saving it to filen";

        # save the file content to disk
        open my $fh, '>', $HOME.'/backup.zip' 
                                         or die "ERROR: $!n";
        print $fh $get_file->decoded_content;
        close $fh;

        print "nsaved file:n";
        print "-------------n";
        print "filename:  ".$get_file->filename."n";
        print "size:      ".(-s $HOME.'/backup.zip')."n";
    }
    else {
        die "ERROR: download of $url failed: " . $get_file->status_line . "n";
    }
}
else {
    die "ERROR: login failed: " . $login->status_line . "n";
}
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/02/retrieve-a-file-from-an-authenticated-website-in-perl/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Centering a CSS div layer in your browser window</title>
		<link>https://jmorano.moretrix.com/2010/12/centering-a-css-div-layer-in-your-browser-window/</link>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Wed, 15 Dec 2010 13:50:09 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=435</guid>

					<description><![CDATA[Some time ago I needed to create a popup window on a web page, and it had be&#8230;]]></description>
										<content:encoded><![CDATA[<p>Some time ago I needed to create a popup window on a web page, and it had be centered in the browser window. &#8220;Couldn&#8217;t be that hard&#8221; was my first thought, although I haven&#8217;t programmed anything in JavasScript for years.</p>
<p>So using CSS and Javascript, this was actually a pretty easy job to do. The only hard thing to do, was making it browser indepedent. But in the end, even this wasn&#8217;t so hard at all since most of these steps have been thoroughly described on the Interweb.<br />
<span id="more-435"></span><br />
What we will need is</p>
<ul>
<li>a CSS file</li>
<li>a JavaScript file</li>
<li>a HTML file</li>
</ul>
<p>The CSS portion is actually very easy:<br />
&#8211; Save this into a file called <em>style.css</em></p>
<pre class="brush:css">
#blanket {
    display: block;
    position:absolute;
    width:100%;
    height: 100%;
    top:0px;
    left:0px;
    z-index: 9998;
    background-color:#111;
    opacity: 0.65;
    filter:alpha(opacity=65);
}
#popUpDiv {
    display: block;
    position:absolute;
    width:450px;
    height:500px;
    z-index: 9999;
    overflow: auto;
    padding-left: 4px;
    padding-right: 4px;
    background-color:#eeeeee;
}
</pre>
<p>As you can see: no rocket science. We create two layers: blanket and popUpDiv. The blanket layer will create a gray transparent layer over the entire page. The popUpDiv layer will create &#8230; well, I think it&#8217;s clear what this layer will do <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>The JavaScript portion contains a bit more code. It will contain four functions:</p>
<ul>
<li>toggle(): toggle the visibility of a layer</li>
<li>create_blanket(): calculate the size of the blanket and display</li>
<li>create_popup(): calculate the position of the popup layer and display</li>
<li>popup(): wrapper function which calls toggle(), create_blanket(), create_popup()</li>
</ul>
<p>Let&#8217;s start with the <em>toggle()</em> function, because that&#8217;s the shortest and easiest one.</p>
<pre class="brush:javascript">
function toggle(div_id) {
        var el = document.getElementById(div_id);

        if (el.style.display == 'none') {
                el.style.display = 'block';
        }
        else {
                el.style.display = 'none';
        }
}
</pre>
<p>Again, no rocket science. This procedure has been described and explained a million times on the Interweb, I will not redo it overhere.</p>
<p>Secondly, the <em>create_blanket()</em> function requires a bit more attention, since it&#8217;s more than 4 lines of code. <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
In this function, we will try to get the window height. We&#8217;ll do this in two different ways: one for Mozilla based browsers, one for Internet Exploder browsers.</p>
<pre class="brush:javascript">
if (typeof window.innerHeight != 'undefined') {
    height = window.innerHeight;
}
else {
    height = document.documentElement.clientHeight;
}
</pre>
<p>But then again &#8230; we could have just called <code>document.documentElement.clientHeight</code> since this is also supported by Mozilla based browsers.<br />
The variable <em>height</em> will contain the browser height.<br />
But, since we don&#8217;t all have huge screens which eliminates the usage of scrollbars, we will have to check if this <em>height</em> variable is smaller or bigger than the scroll area of the browser. </p>
<pre class="brush:javascript">
if ((height > document.body.parentNode.scrollHeight)
        && (height > document.body.parentNode.clientHeight)) {

        blanket_height = height;
}
else {
        if (document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight) {
                blanket_height = document.body.parentNode.clientHeight;
        }
        else {
                blanket_height = document.body.parentNode.scrollHeight;
        }
}
</pre>
<p>And finally we&#8217;ll create this blanket:</p>
<pre class="brush:javascript">
var blanket = document.getElementById('blanket');
blanket.style.height = blanket_height + 'px';
</pre>
<p>So on with the <em>create_popup()</em> function. This function will first retrieve information about the different dimensions required to calculate the position of the popup. The following information is required:</p>
<ul>
<li>scroll_width: amount of pixels scrolled from left</li>
<li>scroll_height: amount of pixels scrolled from top</li>
<li>client_width: width of the browser (without scrollbars, menubars, padding, &#8230;)</li>
<li>client_height: height of the browser (without scrollbars, menubars, padding, &#8230;)</li>
<li>popup_width: popup width defined in CSS stylesheet file</li>
<li>popup_height: popup height defined in CSS stylesheet file</li>
</ul>
<p>First the scroll width and scroll height:</p>
<pre class="brush:javascript">
if( typeof( window.pageYOffset ) == 'number' ) {
        //Netscape compliant
        scroll_height = window.pageYOffset;
        scroll_width = window.pageXOffset;
} 
else if( document.body
        && ( document.body.scrollLeft || document.body.scrollTop ) ) {
        //DOM compliant
        scroll_height = document.body.scrollTop;
        scroll_width = document.body.scrollLeft;
} 
else if( document.documentElement
        && ( document.documentElement.scrollLeft
            || document.documentElement.scrollTop ) ) {
        //IE6 standards compliant mode
        scroll_height = document.documentElement.scrollTop;
        scroll_width = document.documentElement.scrollLeft;
}
</pre>
<p>Secondly the client height and width:</p>
<pre class="brush:javascript">
var client_height = document.body.parentNode.clientHeight;
var client_width  = document.body.parentNode.clientWidth;
</pre>
<p>And last the popup height and width as stated in the CSS stylesheet file:</p>
<pre class="brush:javascript">
var popup_height = parseInt(window.getComputedStyle(popUpDiv, "").getPropertyValue('height'));
var popup_width  = parseInt(window.getComputedStyle(popUpDiv, "").getPropertyValue('width'));
</pre>
<p>We need to wrap these values from the CSS stylesheet file around the JavaScript function <em>parseInt()</em> since the <em>.getPropertyValue()</em> function will return the values with &#8216;px&#8217; at the end. (e.g.: 400px)</p>
<p>Based on the above information, the position from top and left will be calculated:</p>
<pre class="brush:javascript">
var left    = client_width  / 2 + scroll_width  - (popup_width / 2);
var top     = client_height / 2 + scroll_height - (popup_height / 2);
</pre>
<p>The only thing left to do is, is sending these position values to the browser by simply changing the CSS values for this DIV object:</p>
<pre class="brush:javascript">
popUpDiv.style.left  = left + 'px';
popUpDiv.style.top   = top + 'px';
</pre>
<p>The final function, popup(), will be the wrapper function called from within the HTML code.</p>
<pre class="brush:javascript">
function popup(windowname) {
    create_blanket(windowname);
    create_popup(windowname);
    toggle('blanket');
    toggle(windowname);
}   
</pre>
<p>So now we only need some HTML code to test this!<br />
<a href="http://moretrix.com/~insaniac/popup/">Click here</a> to have a demo page (so where you could do right click + &#8216;View Source&#8217;)</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
