A Virtual Homehttps://blog.avirtualhome.com/2018-03-28T09:03:00-04:00Replace JPEG libraries with MozJPEG2018-03-28T09:03:00-04:002018-03-28T09:03:00-04:00Peter van der Doestag:blog.avirtualhome.com,2018-03-28:/replace-jpeg-libraries-with-mozjpeg/<p>For a project in Python we had to squeeze more bytes out of <span class="caps">JPG</span> files using Pillow. Currently MozJPEG fits that bill but there isn&rsquo;t a repository available to install it on&nbsp;Ubuntu.</p><p>For an image heavy site we were building we needed to squeeze more bytes out of the <span class="caps">JPEG</span> files. We use <a href="http://pillow.readthedocs.io/en/latest/">Pillow</a> within our Python project to create thumbnails which in turn uses the <span class="caps">JPEG</span> libraries installed on your system, so we had to look for a 1-on-1 replacement of the system jpeg&nbsp;libraries.</p> <p>For Ubuntu you can use <a href="https://libjpeg-turbo.org/">libjpeg-turbo</a> but using <a href="https://github.com/mozilla/mozjpeg">MozJPEG</a> by Mozilla makes the thumbnails even smaller. The only problem we ran into was the fact there is no repository you can add in Ubuntu and therefore we had to compile MozJPEG&nbsp;manually.</p> <p>If you just want to skip the steps go to <a href="#tldr">tl;dr</a>. All the steps need to be ran as&nbsp;root.</p> <h4 id="install-requirements">Install&nbsp;requirements</h4> <p>To compile MozJPEG you need to install some&nbsp;requirements.</p> <div class="highlight"><pre><span></span>apt -y install build-essential cmake libtool autoconf automake m4 nasm pkg-config </pre></div> <p>and then configure the dynamic linker run-time bindings <div class="highlight"><pre><span></span>ldconfig /usr/lib </pre></div></p> <h4 id="get-mozjpeg-source">Get MozJPEG&nbsp;source</h4> <p>We&rsquo;ll be working with version 3.2 of the MozJPEG library. <div class="highlight"><pre><span></span>wget https://github.com/mozilla/mozjpeg/archive/v3.2.tar.gz tar xf v3.2.tar.gz </pre></div></p> <h4 id="configure-and-install">Configure and&nbsp;Install</h4> <p>Before we can configure and install we have to create the configuration. Go to the directory you extract the archive&nbsp;in.</p> <div class="highlight"><pre><span></span><span class="nb">cd</span> mozjpeg-3.2 autoreconf -fiv </pre></div> <p>To keep source and build separate we&rsquo;ll do the build in it&rsquo;s own&nbsp;directory.</p> <div class="highlight"><pre><span></span>mkdir build <span class="nb">cd</span> build sh ../configure --with-jpeg8 make install <span class="nv">libdir</span><span class="o">=</span>/usr/lib/x86_64-linux-gnu <span class="nv">prefix</span><span class="o">=</span>/usr </pre></div> <p>We have to copy one source file over as it&rsquo;s not included in the build. <div class="highlight"><pre><span></span>cp ../jpegint.h /usr/include/jpegint.h </pre></div></p> <p>That&rsquo;s it, now almost any program on your server that use the <span class="caps">JPEG</span> libraries to create images will be using MozJPEG and making the files much smaller than with the standard or even libjpeg-turbo&nbsp;libraries.</p> <h4 id="tldr"><span class="caps">TL</span>;<span class="caps">DR</span></h4> <p>The script below will do all the above steps. Remember to run this as&nbsp;root.</p> <div class="highlight"><pre><span></span><span class="c1">#/bin/sh</span> apt -y install build-essential cmake libtool autoconf automake m4 nasm pkg-config ldconfig /usr/lib rm -rf mozjpeg-3.2 wget https://github.com/mozilla/mozjpeg/archive/v3.2.tar.gz tar xf v3.2.tar.gz <span class="nb">cd</span> mozjpeg-3.2 autoreconf -fiv mkdir build <span class="nb">cd</span> build sh ../configure --with-jpeg8 make install <span class="nv">libdir</span><span class="o">=</span>/usr/lib/x86_64-linux-gnu <span class="nv">prefix</span><span class="o">=</span>/usr cp ../jpegint.h /usr/include/jpegint.h </pre></div> <h4 id="bonus">Bonus</h4> <p>If you use Pillow in your Python project and it was already installed you need to reinstall it, we ran into issues where after reinstalling it still would not use the MozJPEG libraries. In order to make that work, we had to recompile Pillow. The code below will recompile&nbsp;pillow</p> <div class="highlight"><pre><span></span>pip install --upgrade --no-cache-dir --force-reinstall --no-binary :all: --compile -v Pillow </pre></div>Create a custom 410 error page in NGINX2018-03-23T08:03:00-04:002018-03-23T08:03:00-04:00Peter van der Doestag:blog.avirtualhome.com,2018-03-23:/create-custom-410-error-page-nginx/<p>I had a need to create a 410 page for a whole bunch pages. As it turns out it was not as easy as it&nbsp;sounds</p><p>When converting this blog from WordPress to Pelican I decided I just ditch a whole bunch of articles I had written in WordPress. According to several articles on the net it is best practice to have pages you delete return a 410 page. For a better user experience I wanted used to land on a page that looks like part of the&nbsp;blog.</p> <p>As I&rsquo;m using <span class="caps">NGINX</span> you can utilize the map function to create a new variable whose value depends on values of one or more of the source variables specified in the first parameter. I created a file called <code>old_request.nginx</code> in the directory <code>/etc/nginx/snippets/</code></p> <div class="highlight"><pre><span></span>map $request_uri $gone_var { /the-avh-amazon-plugin-has-reached-its-end-of-life/ 1; /wordpress-plugin-update-avh-first-defense-against-spam-v3-0/ 1; /end-of-the-avh-amazon-plugin/ 1; /wordpress-plugin-update-avh-extended-categories/ 1; } </pre></div> <p>This file just needs to be included in your configuration file, and if you want to have a custom 410 error page you just have to tell <span class="caps">NGINX</span> which file to use when it encounters a 410&nbsp;error.</p> <div class="highlight"><pre><span></span>include snippets/old_request.nginx; server { .... error_page 404 /404.html; error_page 410 /410.html; if ($gone_var) { return 410; } location / { .... } } </pre></div> <p>Easy enough, <strong><span class="caps">NOT</span></strong>. The above configuration does not work. If you try to browse one of the URLs mentioned in the the <code>old_request.nginx</code> file you get the default <span class="caps">NGINX</span> 410 error page and not the file you said it should&nbsp;show.</p> <p>To fix this we have to use a named location. A named location has the <code>@</code> prefix. Such a location is not used for a regular request processing, but instead used for request&nbsp;redirection.</p> <div class="highlight"><pre><span></span>include snippets/old_request.nginx; server { .... error_page 404 /404.html; error_page 410 @gone; if ($gone_var) { return 410; } location @gone { rewrite ^(.*)$ /410.html break; } location / { .... } } </pre></div> <p>And now your custom 410 error page&nbsp;works.</p>Move from WordPress to Pelican2018-03-11T22:15:24-04:002018-03-17T23:03:00-04:00Peter van der Doestag:blog.avirtualhome.com,2018-03-11:/move-from-wordpress-to-pelican/<p>I have been playing with the thought of moving my blog from WordPress to a static website generator for years and I finally pulled the&nbsp;trigger.</p><p>I have been playing with the thought of moving my blog from WordPress to a static website generator for&nbsp;years.</p> <p>I never really had the energy to start this projects, for several reasons. I know I could never find a theme that is completely to my liking so I would have to change it, possibly altering some code. There were some generator written in <span class="caps">PHP</span>, my language of choice for a long time, but they seemed not very mature. The best known static web site generator was Jekyll, written in Ruby and I really couldn&rsquo;t get the energy to start learning Ruby on the side. The other reason that was keeping me from moving was how to move all my articles from WordPress to the static&nbsp;generator.</p> <p>I started working for <a href="https://oneilinteractive.com/">ONeil Interactive</a> in 2017. We build websites for the home building industry and the language of choice is Python. We started looking into building an internal site for documenting our projects. We develop in Python and it was quickly decided the static generator should be written in Python as it would make it easier to extend the generator if&nbsp;needed.</p> <p>As a result of this project I decided to bite the bullet for my personal site as well. After a quick look at the site <a href="https://www.staticgen.com/">StaticGen</a> and some quick research I decided to go with <a href="https://github.com/getpelican/pelican">Pelican</a>. Of course I needed a theme, and there is never a theme that completely satisfies my needs but my starter theme is <a href="https://github.com/kdeldycke/plumage">Plumage by Kevin Deldycke</a>. I&rsquo;ve modified it to work with Bootstrap 4, and used the <a href="https://bootswatch.com/slate/">Slate theme by Bootswatch</a>.</p> <p>I only moved two articles from my old blog as the rest of the articles were not visited that often. I still have them in the database so if it&rsquo;s ever needed I can pull them&nbsp;up.</p> <p>Oh in case you were wondering, for the project at work we decided to go with <a href="https://www.mkdocs.org/">MkDocs</a></p>Adding SSL certificates to Google Chrome Linux (Ubuntu)2010-02-02T20:36:00-05:002010-02-02T20:36:00-05:00Peter van der Doestag:blog.avirtualhome.com,2010-02-02:/adding-ssl-certificates-to-google-chrome-linux-ubuntu/<p>Google Chrome in Linux doesn&rsquo;t have a <span class="caps">SSL</span> certificate manager, it relies on the <span class="caps">NSS</span> Shared <span class="caps">DB</span>. In order to add <span class="caps">SSL</span> certificates to the database you will have to use the command line. I will explain how you can add the CAcert certificates and a very easy way to add self-signed&nbsp;certificates.</p><p>Google Chrome in Linux doesn&rsquo;t have a <span class="caps">SSL</span> certificate manager, it relies on the <span class="caps">NSS</span> Shared <span class="caps">DB</span>. In order to add <span class="caps">SSL</span> certificates to the database you will have to use the command line. I will explain how you can add the CAcert certificates and a very easy way to add self-signed&nbsp;certificates.</p> <p>You will have to install some tools first: <div class="highlight"><pre><span></span>sudo apt-get install libnss3-tools sudo apt-get install curl </pre></div></p> <h3 id="adding-cacert-certificates">Adding CAcert&nbsp;certificates</h3> <p>Lets start with adding the CAcert certificates, this will help with a lot of&nbsp;sites</p> <div class="highlight"><pre><span></span>curl -k -o <span class="s2">&quot;cacert-root.crt&quot;</span> <span class="s2">&quot;http://www.cacert.org/certs/root.crt&quot;</span> curl -k -o <span class="s2">&quot;cacert-class3.crt&quot;</span> <span class="s2">&quot;http://www.cacert.org/certs/class3.crt&quot;</span> certutil -d sql:<span class="nv">$HOME</span>/.pki/nssdb -A -t TC -n <span class="s2">&quot;CAcert.org&quot;</span> -i cacert-root.crt certutil -d sql:<span class="nv">$HOME</span>/.pki/nssdb -A -t TC -n <span class="s2">&quot;CAcert.org Class 3&quot;</span> -i cacert-class3.crt </pre></div> <h3 id="adding-self-signed-certificates">Adding self-signed&nbsp;certificates</h3> <p>There are certain sites that use self-signed certificates and you need to add them individually to the database and there are two options to do&nbsp;this:</p> <h4 id="using-firefox">Using&nbsp;Firefox</h4> <p>You can use Firefox to look at the certificate and then export the certificate to a file. This file can be used to import the certificate into the <span class="caps">DB</span>. Let&rsquo;s say you export the file as a.pem now you can import this&nbsp;file</p> <div class="highlight"><pre><span></span>certutil -d sql:<span class="nv">$HOME</span>/.pki/nssdb -A -t TC -n <span class="s2">&quot;A Name&quot;</span> -i a.pem </pre></div> <p>Even though this works, it&rsquo;s quiet cumbersome and there is a better&nbsp;way</p> <h4>Using my little&nbsp;script</h4> <p>I have created a little script that will retrieve the certificate and imports it into the <span class="caps">DB</span>.</p> <p>Create a file, lets call it import-cert.sh and the contents of the file is as&nbsp;follows:</p> <div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span> <span class="c1">#</span> <span class="c1"># usage: import-cert.sh remote.host.name [port]</span> <span class="c1">#</span> <span class="nv">REMHOST</span><span class="o">=</span><span class="nv">$1</span> <span class="nv">REMPORT</span><span class="o">=</span><span class="si">${</span><span class="nv">2</span><span class="k">:-</span><span class="nv">443</span><span class="si">}</span> <span class="nb">exec</span> <span class="m">6</span>&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="nb">exec</span> &gt; <span class="nv">$REMHOST</span> <span class="nb">echo</span> <span class="p">|</span> openssl s_client -connect <span class="si">${</span><span class="nv">REMHOST</span><span class="si">}</span>:<span class="si">${</span><span class="nv">REMPORT</span><span class="si">}</span> <span class="m">2</span>&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span>sed -ne <span class="s1">&#39;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&#39;</span> certutil -d sql:<span class="nv">$HOME</span>/.pki/nssdb -A -t TC -n <span class="s2">&quot;</span><span class="nv">$REMHOST</span><span class="s2">&quot;</span> -i <span class="nv">$REMHOST</span> <span class="nb">exec</span> <span class="m">1</span>&gt;<span class="p">&amp;</span><span class="m">6</span> <span class="m">6</span>&gt;<span class="p">&amp;</span>- </pre></div> <p>Make sure the script is&nbsp;executable.</p> <p>To add a certificate from a site you type the following: <div class="highlight"><pre><span></span>import-cert.sh dirae.lunarservers.com <span class="m">2083</span> </pre></div> In this case it uses port 2083 instead of the default port 443. If it&rsquo;s the default port you don&rsquo;t have to include the&nbsp;port.</p> <p>To see which certificates are included your database: <div class="highlight"><pre><span></span>certutil -L -d sql:<span class="nv">$HOME</span>/.pki/nssdb </pre></div></p> <p>And should you want to delete a certificate <div class="highlight"><pre><span></span>certutil -D -n &lt;the name&gt; -d sql:<span class="nv">$HOME</span>/.pki/nssdb </pre></div></p> <p>I hope this solves a lot of frustrations about big red screens when accessing secure&nbsp;websites.</p>How to create nested forms.2008-10-01T13:13:00-04:002008-10-01T00:00:00-04:00Peter van der Doestag:blog.avirtualhome.com,2008-10-01:/how-to-create-nested-forms/<p>Even though I write this article with the perspective on a plugin for WordPress the solution can used anywhere. The example I&rsquo;ll use to explain how to create a form within a form, aka nested forms, will have no direct links to WordPress but will merely show how to create a form within a&nbsp;form.</p><p>Update: December 6, 2015 - Fixed several bugs in the&nbsp;code.</p> <p>Even though I write this article with the perspective on a plugin for WordPress the solution can used anywhere. The example I&rsquo;ll use to explain how to create a form within a form, aka nested forms, will have no direct links to WordPress but will merely show how to create a form within a&nbsp;form.</p> <p>For my <span class="caps">AVH</span> Amazon plugin I wanted to add a metabox with a form on the Post and Page pages. The purpose of the metabox was to give the user the ability to create the shortcode without having to remember, and type for that matter, all the&nbsp;options.</p> <p>I wanted users to have the ability to look up their wishlist, show them a the items on their wishlist and give them the option to select one. The problem with this is not so much the form itself, that is pretty straight forward, but the Post and Page pages are almost completely wrapped in a form. The metabox resides with in that form and by design you can&rsquo;t have a form inside a form in <span class="caps">HTML</span>. It was jQuery, the awesome javascript framework, that bailed me&nbsp;out.</p> <p>This is what I try to accomplish but is invalid <span class="caps">HTML</span> code. <div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">form</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;post.php&quot;</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">textarea</span> <span class="na">cols</span><span class="o">=</span><span class="s">&quot;20&quot;</span> <span class="na">rows</span><span class="o">=</span><span class="s">&quot;5&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;search.php&quot;</span><span class="p">&gt;</span> Item: <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text&quot;</span> <span class="na">size</span><span class="o">=</span><span class="s">&quot;10&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;item&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Search&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;output&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span> </pre></div> <p><i>Explanation:</i><br /> The form has a text area for writing a article and on hitting the submit button the file post.php would be called.<br /> When you fill out the Item box and hit the Search button the file search.php is called. In that file a search will be performed and the output, a list of items, will be displayed between the div&nbsp;tag.</p> <p><h3>The basic <span class="caps">HTML</span></h3><br /> As mentioned earlier I&rsquo;ll be using jQuery to get this done so you have to make sure you include jQuery in your <span class="caps">HTML</span>. I have to remove the nested form, change the submit button into a regular button, wrap the nested form in a div tag and to make things easier later on give the items of the nested form an id&nbsp;tag.</p> <div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text/javascript&quot;</span> <span class="na">src</span><span class="o">=</span><span class="s">&quot;jquery.js&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text/javascript&quot;</span><span class="p">&gt;</span> <span class="c1">// we will add our javascript code here</span> <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;post.php&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">textarea</span> <span class="na">rows</span><span class="o">=</span><span class="s">&quot;5&quot;</span> <span class="na">cols</span><span class="o">=</span><span class="s">&quot;20&quot;</span> <span class="na">wrap</span><span class="o">=</span><span class="s">&quot;physical&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;nestedform&quot;</span><span class="p">&gt;</span> Item: <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text&quot;</span> <span class="na">size</span><span class="o">=</span><span class="s">&quot;10&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;item&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;item&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;button&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;search&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Search&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;output&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span> </pre></div> <p><h3>Adding the actions to the&nbsp;elements</h3><br /> To add an action when you you click on the Search button or press enter when you are typing something in the Item box we need to add some javascript to intercept these&nbsp;actions.</p> <div class="highlight"><pre><span></span><span class="nx">jQuery</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#search&#39;</span><span class="p">).</span><span class="nx">click</span><span class="p">(</span><span class="nx">submit_search</span><span class="p">);</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#nestedform&#39;</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">).</span><span class="nx">keydown</span><span class="p">(</span><span class="nx">keypressed</span><span class="p">);</span> <span class="p">});</span> </pre></div> <p><i>Explanation</i><br /> Line 2: When the element with id search is clicked we call the function submit_search<br /> Line 3: Within the section defined by id #nestedform we search for the element input. When a key is down in those input fields, in our situation it&rsquo;s only one input filed, we call the function&nbsp;keypressed.</p> <p>These are the two functions we&nbsp;call:</p> <div class="highlight"><pre><span></span><span class="kd">function</span> <span class="nx">submit_search</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">values</span> <span class="o">=</span> <span class="p">[];</span> <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">;</span> <span class="nx">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#item&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">();</span> <span class="k">if</span> <span class="p">(</span><span class="nx">values</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span> <span class="nx">do_submit</span><span class="p">(</span><span class="s1">&#39;#output&#39;</span><span class="p">,</span> <span class="nx">values</span><span class="p">);</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nx">alert</span><span class="p">(</span><span class="s1">&#39;No Item given&#39;</span><span class="p">);</span> <span class="p">}</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span> <span class="p">}</span> <span class="kd">function</span> <span class="nx">keypressed</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">charcode</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">which</span><span class="p">)</span> <span class="o">?</span> <span class="nx">event</span><span class="p">.</span><span class="nx">which</span> <span class="o">:</span> <span class="nb">window</span><span class="p">.</span><span class="nx">event</span><span class="p">.</span><span class="nx">keyCode</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="nx">charcode</span> <span class="o">==</span> <span class="mi">13</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">submit_search</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span> <span class="p">}</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> </pre></div> <i>Explanation:</i><br> Line 3: We prevent any default actions to take place, we only want our action to run.<br /> Line 4: We add the value, whatever we typed, of the input filed with id item in an array<br /> Line 5-9: We check if there is a value, if there is we call a function which I&rsquo;ll explain later, otherwise we show an alert on the screen.<br /> Line 14: We get the character code of teh key that is pressed down. In <span class="caps">IE</span> we don&rsquo;t have event.which so we have to use window.event.keyCode.<br /> Line 15-17: If the enter key was pressed we call the submit function, making it similar to pressing the button.<br /></p> <p><h3>The submit&nbsp;function</h3><br /> To submit the &ldquo;form&rdquo; we have do an ajax call with jQuery.<br /> <div class="highlight"><pre><span></span><span class="kd">function</span> <span class="nx">do_submit</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">,</span> <span class="nx">submit_values</span><span class="p">)</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span> <span class="kd">var</span> <span class="nx">posting</span> <span class="o">=</span> <span class="nx">jQuery</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span> <span class="s2">&quot;search.php&quot;</span><span class="p">,</span> <span class="p">{</span> <span class="s1">&#39;search_values[]&#39;</span><span class="o">:</span> <span class="nx">submit_values</span> <span class="p">});</span> <span class="nx">posting</span><span class="p">.</span><span class="nx">done</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">show</span><span class="p">();</span> <span class="p">};</span> <span class="p">}</span> </pre></div> <i>Explanation</i><br /> Line 2: In case we do a second search we want to hide the previous output.<br /> Line 3-11: The actual call to search through Ajax.<br /> Line 4: The php file we want to call.<br /> Line 5: The actions passed to the php file. Similar to the search?action<br /> Line 7: The output will be shown at the element with the <span class="caps">ID</span> passed on to submit_output.<br /> Line 9: We have to show the output to the&nbsp;user.</p> <p><h3>The final <span class="caps">HTML</span></h3> The final <span class="caps">HTML</span> looks like this.<br /> <div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text/javascript&quot;</span> <span class="na">src</span><span class="o">=</span><span class="s">&quot;jquery.js&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text/javascript&quot;</span><span class="p">&gt;</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#search&#39;</span><span class="p">).</span><span class="nx">click</span><span class="p">(</span><span class="nx">submit_search</span><span class="p">);</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#nestedform&#39;</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">).</span><span class="nx">keydown</span><span class="p">(</span><span class="nx">keypressed</span><span class="p">);</span> <span class="p">});</span> <span class="kd">function</span> <span class="nx">submit_search</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">values</span> <span class="o">=</span> <span class="p">[];</span> <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">;</span> <span class="nx">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">jQuery</span><span class="p">(</span><span class="s1">&#39;#item&#39;</span><span class="p">).</span><span class="nx">val</span><span class="p">();</span> <span class="k">if</span> <span class="p">(</span><span class="nx">values</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span> <span class="nx">do_submit</span><span class="p">(</span><span class="s1">&#39;#output&#39;</span><span class="p">,</span> <span class="nx">values</span><span class="p">);</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="nx">alert</span><span class="p">(</span><span class="s1">&#39;No Item given&#39;</span><span class="p">);</span> <span class="p">}</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span> <span class="p">}</span> <span class="kd">function</span> <span class="nx">keypressed</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span> <span class="kd">var</span> <span class="nx">charcode</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">which</span><span class="p">)</span> <span class="o">?</span> <span class="nx">event</span><span class="p">.</span><span class="nx">which</span> <span class="o">:</span> <span class="nb">window</span><span class="p">.</span><span class="nx">event</span><span class="p">.</span><span class="nx">keyCode</span><span class="p">;</span> <span class="k">if</span> <span class="p">(</span><span class="nx">charcode</span> <span class="o">==</span> <span class="mi">13</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">submit_search</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span> <span class="p">}</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="p">}</span> <span class="kd">function</span> <span class="nx">do_submit</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">,</span> <span class="nx">submit_values</span><span class="p">)</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span> <span class="kd">var</span> <span class="nx">posting</span> <span class="o">=</span> <span class="nx">jQuery</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span> <span class="s2">&quot;search.php&quot;</span><span class="p">,</span> <span class="p">{</span> <span class="s1">&#39;search_values[]&#39;</span><span class="o">:</span> <span class="nx">submit_values</span> <span class="p">});</span> <span class="nx">posting</span><span class="p">.</span><span class="nx">done</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span> <span class="nx">jQuery</span><span class="p">(</span><span class="nx">submit_output</span><span class="p">).</span><span class="nx">show</span><span class="p">();</span> <span class="p">};</span> <span class="p">}</span> <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">&quot;post&quot;</span> <span class="na">action</span><span class="o">=</span><span class="s">&quot;post.php&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">textarea</span> <span class="na">rows</span><span class="o">=</span><span class="s">&quot;5&quot;</span> <span class="na">cols</span><span class="o">=</span><span class="s">&quot;20&quot;</span> <span class="na">wrap</span><span class="o">=</span><span class="s">&quot;physical&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;submit&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Post&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;nestedform&quot;</span><span class="p">&gt;</span> Item: <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text&quot;</span> <span class="na">size</span><span class="o">=</span><span class="s">&quot;10&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;item&quot;</span> <span class="na">name</span><span class="o">=</span><span class="s">&quot;item&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;button&quot;</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;search&quot;</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;Search&quot;</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;output&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span> <span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span> </pre></div> <br /> I hope I gave you a basic understanding how to nest forms with jQuery. For my plugin I had to change some minor things because of the way WordPress handles the Page and Post pages. If anybody is interested I could write up a follow up explaining what I ran into.<p></p>