Author: Barry van Oudtshoorn

  • Canvas Swarms

    I’ve been meaning to start playing with the HTML5 <canvas> element for a while now, and yesterday I took the opportunity. I translated a Processing sketch I made a while ago into JavaScript (with a few minor enhancements).

    Essentially, 1 to 3 swarms of particles move around the canvas, reproducing when the conditions are just right, and dying of old age. Quite simple, but the patterns produced can be really quite pretty.

    One interesting thing that I discovered whilst doing this is that you can’t pass around a canvas’ context at the instantiation of a MooTools class — it complains about wrapped natives. That’s why, if you like in the source JavaScript, you’ll see me pass the actual context around to various functions. I’d be interested in hearing if anyone has a workaround for this, because this is, well, a bit clunky.

  • HTML: IE file submission

    I’ve been bumping up against an interesting bug in Internet Explorer recently, and, having just found the solution, thought I’d share it with you.

    The problem is that in Internet Explorer (tested 7 & 8), when your document is in quirks mode, uploading a file sometimes just sends through the file name, without the actual body of the request. Put the document into standards mode, and it all works. It should be noted that this is when you’re dynamically setting up the elements used with JavaScript.

    The cause? In quirks mode, the enctype attribute isn’t supported. So whilst setting “encType” on the form element to the correct “multipart/form-data” will indeed set this attribute, it won’t actually cause the upload to include the file. Instead, you need to set the encoding attribute to this value, too. It certainly doesn’t help that the MSDN article on the <input type=”file”> element tells you to set “enctype”, but makes no mention of “encoding”.

    I couldn’t find any reference to this problem on the intertubes (although maybe I just didn’t look hard enough), so hopefully this will help someone.

  • Javascript: Print a single element

    Sometimes, you’ll want to allow users the ability to print only a part of your page; for example, a table but not the various links around the page. It’s possible to use a printing stylesheet, but this can cause severe headaches when you need different parts printed at different times. Really, we want to be able to just say element.printElement(), and have it just work. That’s what the MooTools function below does. It’s loosely based around the concepts outlined at this website.

    [sourcecode language=”javascript”]Element.implement({
    printElement: function(docTitle) {
    var strName = ‘printer-‘ + (new Date()).getTime();
    var styles = [];
    $$(‘link[type=text/css]’).each(function(style) {
    styles.push(‘‘);
    });
    var title = docTitle || document.title;
    var that = this.getParent();
    var iframe = new IFrame({
    name: strName,
    styles: {
    width: 1,
    height: 1,
    position: ‘absolute’,
    left: -9999
    },
    events: {
    load: function() {
    var doc = window.frames[strName].document,
    win = window.frames[strName];
    var f = function() {
    if (!doc.head) {
    f.delay(10);
    return;
    }
    // We need to delay printing so that styles are applied.
    (function() {
    doc.title = title;
    // IE7 won’t let us adopt() here for some reason, and we can’t do anything to the head.
    doc.body.innerHTML = styles.join(”) + that.innerHTML;
    (function() {
    win.focus(); // IE needs the window to be focused.
    win.print();
    }).delay(100);
    }).delay(200);
    };
    f();
    }
    }
    }).inject($(document.body));
    (function() {
    iframe.dispose();
    }).delay(30000);
    }
    });[/sourcecode]

  • Songs for the Cure 2010

    Last year, I was proud to be part of the inaugural Indie Music Cancer Drive. Along with a whole lot of very talented artists, I contributed music to a compilation album, “Songs for the Cure”. All the proceeds from the sales of this album went to the American Cancer Society.

    Songs for the Cure 2010

    This year, I am once again contributing. I just finished work on the track I will be contributing, so I thought it high time I let everyone know about this. Josh Whelchel, the organiser of the drive (and a fantastic musician to boot), has set a target of $10,000 for this year. If you donate $25 or more, you receive a physical copy of the (two disc!) album; otherwise, you receive the album digitally.

    Here’s the official media release:

    Indie Music Cancer Drive to Release Songs for the Cure ’10 Album

    Twenty-eight artists join together to raise money for the American Cancer Society and aim to raise $10,000.

    Cincinnati, OH, January 24th, 2010. – The Indie Music Cancer Society will release it’s 2010 compilation, Songs for the Cure ’10 on March 1st, 2010 and forward 100% of all donations and profits to the American Cancer Society through its Relay for Life event held on April 23rd, 2010 at the University of Cincinnati. The album will feature music from over twenty-eight (28) diverse artists, including Select Start, big giant circles, Alec Holowka, Two Seconds Away, Jay Tholen, Josh Whelchel, Renee Winter, and others. The organization is currently accepting donations, and all donors of $25 or more before MARCH 1, 2010 will receive a free physical copy of the album. Supporters with $10 or more will receive a free digital copy. Genres represented include Pop, Rock, Alternative, Chiptunes, Instrumental, Opera, Classical, Avant-Garde, Jazz, Fusion, and many others. The organization raised over $6,000 for the event last year and is still forwarding profits from last year’s album, available on iTunes, Amazon, and others. A full list of artists can be found at the Songs for the Cure ’10 website at http://www.cancerdrive.org. The fundraiser aims to raise $10,000 by April 23rd, 2010, preceding a digital release of the album to iTunes, Amazon, CDBaby, and other retailers. Donations are accepted through http://www.cancerdrive.org.

    For more information please contact:

    JOSH WHELCHEL
    (513) 549-2336
    http://www.cancerdrive.org

    So there you have it. And for good measure, here’s the promotional video:

  • Another new theme

    I was never really happy with my previous 2010 theme, so I’ve gone and done a completely new one.

    This new one makes extensive use of CSS3 properties, such as gradients and shadows. It looks best in Firefox >= 3.6,followed by Safari >= 4, then Chrome >= 4, Opera >= 10, and IE >= 8. Theoretically, Firefox and Safari/Chrome support the same level of features, but the webkit gradient syntax is absolutely awful. It’s confusing, needlessly complex, and poorly thought-out, in my opinion. Contrast the following two lines:
    [sourcecode language=css]background: -moz-linear-gradient(top, #111, #333);
    background: -webkit-gradient(linear, left top, left bottom, from(#222), to(#333));[/sourcecode]
    See what I mean?

    Gecko (Firefox), Webkit (Safari), and Trident (IE) rendering.

  • Clean Word markup

    When writing a web-app that accepts formatted input from users, you’ll often find that they will copy and paste text from Microsoft Word. Unfortunately, Word fills the markup with lots of unnecessary and unwanted muck. To clean this all up, I wrote the following function (directly implemented on the String prototype below):

    [sourcecode language=javascript]String.implement({
    sanitiseWord: function() {
    var s = this.replace(/\r/g, ‘\n’).replace(/\n/g, ‘ ‘);
    var rs = [];
    rs.push(//g); // Comments
    rs.push(/.+?<\/title>/g); // Title<br /> rs.push(/<(meta|link|.?o:|.?style|.?div|.?head|.?html|body|.?body|.?span|!\[)[^>]*?>/g); // Unnecessary tags<br /> rs.push(/ v:.*?=”.*?”/g); // Weird nonsense attributes<br /> rs.push(/ style=”.*?”/g); // Styles<br /> rs.push(/ class=”.*?”/g); // Classes<br /> rs.push(/( ){2,}/g); // Redundant  s<br /> rs.push(/</p><p>(\s| )*?<\/p>/g); // Empty paragraphs<br /> rs.each(function(regex) {<br /> s = s.replace(regex, ”);<br /> });<br /> return s.replace(/\s+/g, ‘ ‘);<br /> }<br /> });[/sourcecode]</p><p>If you’re not using MooTools, the function will look something like this:<br /> [sourcecode language=javascript]String.prototype.sanitiseWord = function() {<br /> // function body here…<br /> };[/sourcecode]</p><h2>Usage</h2><p>[sourcecode language=javascript]var s = “(some awful Word markup)”.sanitiseWord();[/sourcecode]</p><p>In one of the tests I ran, the input went from around 7000 characters to just 700.</p><h2>Example</h2><p><iframe data-lazyloaded="1" src="about:blank" style="width: 100%; height: 300px" data-litespeed-src="http://mootools.net/shell/26Jpf/embedded/"></iframe></p><p>Some of the regular expressions I used were adapted from C# ones in <a href="http://www.codinghorror.com/blog/archives/000485.html">a post by Jeff Atwood</a>.</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2010-01-20T12:21:24+08:00"><a href="https://barryvan.com.au/2010/01/clean-word-markup/">2010-01-20</a></time></div></div></li><li class="wp-block-post post-403 post type-post status-publish format-standard hentry category-css category-html category-programming category-web-design"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2010/01/full-width-text-inputs-without-extraneous-markup-or-scripting/" target="_self" >Input elements that fill their container</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p>Previously, this post advocated the use of “text-indent” on a padding-less, border-less, 100% width input. This works, but it’s quite clunky, and old versions of IE don’t support text-indent, so it just looks bad. A much better solution is to</p><h1>Just use box-sizing.</h2><p>As pointed out in the comments, the simplest solution is to simply change the box-sizing model of the input element to “border-box”, rather than the default “content-box”. In the example below, I’ve given the containing div a 4px whiteborder.</p><p>[sourcecode language=”xhtml”]</p><div style="background:#000; width:200px; border: solid 4px #fff;"><input style="-moz-box-sizing: border-box; box-sizing: border-box; display: block; padding: 4px; width: 100%; height: 100%; background: #fff; opacity: 0.5; border: solid 1px #666;" type="text" value="text input"/></div><p>[/sourcecode]</p><div style="background:#000; width:200px; border: solid 4px #fff;"><input style="-moz-box-sizing: border-box; box-sizing: border-box; display: block; padding: 4px; width: 100%; height: 100%; background: #fff; opacity: 0.5; border: solid 1px #666;" type="text" value="text input"/></div><p>Note that for Firefox, you still need to use the -moz- prefix; it’s supported unprefixed in all the other major browsers, though.</p><p>Updated 2012-08-03.</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2010-01-06T08:56:34+08:00"><a href="https://barryvan.com.au/2010/01/full-width-text-inputs-without-extraneous-markup-or-scripting/">2010-01-06</a></time></div></div></li><li class="wp-block-post post-332 post type-post status-publish format-standard hentry category-javascript category-mootools category-programming tag-javascript tag-mootools tag-regex tag-string tag-tips"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2009/12/limiting-the-contents-of-a-string-via-regex/" target="_self" >Limiting the contents of a string via RegEx</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p>Often, you will need to prevent users from entering data that doesn’t conform to a specific pattern. For example, you may want to allow users to enter only numbers or only valid email addresses. To this end, I’ve written a little utility function that returns the “standardised” version of a string, according to the regex you supply.</p><p>[sourcecode language=”javascript”]String.implement({<br /> limitContent: function(allowedRegex) {<br /> return $splat(this.match(allowedRegex)).join(”);<br /> }<br /> });[/sourcecode]</p><p>Basically, the function takes the result of evaluating the regular expression on the string, converts it into an array if it isn’t one, and then joins the array’s elements together with an empty string.</p><h2>Examples:</h2><p>[sourcecode language=”javascript”]console.log(“12345”.limitContent(/.{4}/)); // Only allow four characters<br /> console.log(“joe@mail.com”.limitContent(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/)); // Only allow email addresses<br /> [/sourcecode]</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2009-12-24T17:10:49+08:00"><a href="https://barryvan.com.au/2009/12/limiting-the-contents-of-a-string-via-regex/">2009-12-24</a></time></div></div></li><li class="wp-block-post post-323 post type-post status-publish format-standard hentry category-announcements category-letters category-political tag-censorship tag-filtering tag-internet"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2009/12/open-letter-to-m-keenan-stirling-mp/" target="_self" >Internet censorship: Letter #1</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p><em>The letter below is written to my local MP regarding Australia’s proposed internet censoring.</em></p><p>Dear Mr Keenan,</p><p>I am writing to you concerning the soon to be trialed internet filtering scheme. As a resident of the City of Stirling and a UWA-qualified computer scientist, I have reservations over the efficacy, utility, impact, and morality of this initiative.</p><p>Firstly, the internet encompasses more than just web pages and web sites. The so-called “deep web” is thought to be many times larger than the “surface web” (that which can be examined by Google, for example). Where the majority of websites use the HTTP protocol to transfer data, which is subject to filtering under the proposed system, the deep web makes use of a wide variety of alternative data interchange systems, including torrents, UseNet, and VPNs. None of these will be filtered under the scheme, yet it is here that much of the undesirable content is to be found. <a href="#ref-1">[1]</a></p><p>Prior to the change of federal government, a system was in place whereby anyone could obtain free filtering software from the Australian government. This software ran on the computers themselves, and thus placed the onus for preventing unsuitable material from arriving on those in charge of the computers. In other words, parents were responsible for the well-being and safety of their children whilst online — in my opinion, a far more desirable state of affairs. <a href="#ref-2">[2]</a></p><p>The federal government has been extolling the virtues of high-speed internet across the country. Whilst I applaud this initiative, I have to question the sense of improving internet speeds across the country, only to then drastically reduce them by the introduction of mandatory internet filtering. In tests, it has been shown that filtering can reduce access speed by 10ms, and, due to bottle-neck difficulties, much longer times. Surely this is nonsensical. <a href="#ref-3">[3]</a></p><p>My final, and perhaps most significant, issue with the proposed implementation is that the “blacklist” of blocked sites will be inaccessible to the public. Australia is a nation founded on the ideals of a free, democratic, and transparent government. To make this list unavailable suggests that the filtering may be politically or privately motivated, politicians’ assurances notwithstanding. <a href="#ref-4">[4]</a></p><p>I ask that you carefully consider the issues I have raised, and that you stand and speak against this system.</p><p>Yours faithfully,</p><p>Barry van Oudtshoorn</p><p><a name="ref-1">[1]</a> <a href="http://www.nytimes.com/2009/02/23/technology/internet/23search.html?_r=1&th&emc=th" target="_blank">http://www.nytimes.com/2009/02/23/technology/internet/23search.html?_r=1&th&emc=th</a><br /> <a name="ref-2">[2]</a> <a href="http://www.netalert.gov.au/about_netalert.html" target="_blank">http://www.netalert.gov.au/about_netalert.html</a><br /> <a name="ref-3">[3]</a> <a href="http://www.efa.org.au/censorship/mandatory-isp-blocking/#SS_7" target="_blank">http://www.efa.org.au/censorship/mandatory-isp-blocking/#SS_7</a><br /> <a name="ref-4">[4]</a> <a href="http://www.thestandard.com/news/2008/10/13/no-opt-out-filtered-internet" target="_blank">http://www.thestandard.com/news/2008/10/13/no-opt-out-filtered-internet</a></p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2009-12-23T07:32:31+08:00"><a href="https://barryvan.com.au/2009/12/open-letter-to-m-keenan-stirling-mp/">2009-12-23</a></time></div></div></li><li class="wp-block-post post-319 post type-post status-publish format-standard hentry category-classical category-music-downloads category-music tag-music tag-orchestral"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2009/12/music-lament/" target="_self" >[Music] Lament</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p>About a month ago, I was playing around on the piano, and I came up with a fragment of melody that I couldn’t get out of my head. I played with it, twisting it around, pushing it in different directions, seeing what I could do with it. Ultimately, I turned it into a full piece of music, and this is the result.</p> [audio:http://www.barryvan.com.au/music/Lament.mp3]<p>Like this track? Buy it at <a href="http://www.thesixtyone.com/barryvan/songs/new/">thesixtyone</a>, and help feed an impoverished (well, not really) programmer.</p><p>You can also listen to one of the (early) improvisations I played on this theme by downloading the recording I made on my phone <a href="http://www.barryvan.com.au/music/Lament-Improv.m4a">here</a>.</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2009-12-04T09:12:03+08:00"><a href="https://barryvan.com.au/2009/12/music-lament/">2009-12-04</a></time></div></div></li><li class="wp-block-post post-314 post type-post status-publish format-standard hentry category-edm category-music-downloads category-music category-poprock tag-electronic"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2009/11/music-ventilate/" target="_self" >[Music] Ventilate</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p>Well, it’s been a fair while since I last uploaded a piece of music — over two months, in fact! So here’s my latest piece.</p><p>This piece actually started out as an experiment — I recently got my hands on all sorts of <a href="http://www.barryvan.com.au/2009/11/komplete/">shiny new toys</a>, and my DAW <a href="http://lpchip.com/modplug/viewtopic.php?t=3432">got an awesome upgrade</a>, so I couldn’t resist seeing what I could do with them.</p><p>I managed to use all but one of the products that came with Komplete to make this track — FM8, Massive, Reaktor, Guitar Rig, Kontakt, and Battery. Much fun. 😀</p> [audio:http://www.barryvan.com.au/music/Ventilate.mp3]<p>Hmm… For some reason, the version of this uploaded to <a href="http://www.thesixtyone.com/barryvan/song/Ventilate/6BhImCRwnsR/">thesixtyone</a> gets some distortion on the bass during the intro section. I’ve tried uploading at various bitrates, multiple times, but it still keeps on happening. I think they must be doing some re-encoding. :/ Very annoying.</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2009-11-27T10:06:52+08:00"><a href="https://barryvan.com.au/2009/11/music-ventilate/">2009-11-27</a></time></div></div></li><li class="wp-block-post post-312 post type-post status-publish format-standard hentry category-announcements category-music-downloads tag-komplete tag-music tag-purchases"><div class="wp-block-group alignfull has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"><h2 class="wp-block-post-title has-x-large-font-size"><a href="https://barryvan.com.au/2009/11/komplete/" target="_self" >Komplete</a></h2><div class="entry-content alignfull wp-block-post-content has-medium-font-size has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained"><p>I am so excited, I’m giggling like a schoolgirl. I just unwrapped a package that I received from Germany: <a href="http://www.native-instruments.com/#/en/products/producer/komplete-6/?content=949" target="_blank">Native Instruments’ Komplete</a>. It’s installing now.</p><p>In the (large and encouragingly heavy) box, I found the following exciting items:</p><ol><li>Eight (yes, eight!) DVDs full of awesomeness</li><li>Seven hefty printed manuals (in a boxed seat, no less)</li><li>Four large (5″x1″) ‘Native Instruments’ stickers</li><li>Ten small (2.5″x0.5″) ‘Native Instruments’ stickers</li><li>A neck clip thing, with a very shiny stainless steel clip and detacher thinggy</li></ol><p>In terms of software, Komplete means that my Native Instruments collection now comprises</p><ul><li>Kontakt 2</li><li>Kontakt 3</li><li>Kontakt 4</li><li>Battery 3</li><li>Guitar Rig</li><li>FM8</li><li>Reaktor</li><li>Massive</li><li>Absynth</li></ul><p>I am SO EXCITED!!!</p></div><div style="margin-top:var(--wp--preset--spacing--40);" class="wp-block-post-date has-small-font-size"><time datetime="2009-11-18T18:20:30+08:00"><a href="https://barryvan.com.au/2009/11/komplete/">2009-11-18</a></time></div></div></li></ul><div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"></div><div class="wp-block-group alignwide has-global-padding is-layout-constrained wp-block-group-is-layout-constrained"><nav class="alignwide wp-block-query-pagination is-content-justification-space-between is-layout-flex wp-container-core-query-pagination-is-layout-b2891da8 wp-block-query-pagination-is-layout-flex" aria-label="Pagination"> <a href="https://barryvan.com.au/author/admin/page/10/" class="wp-block-query-pagination-previous"><span class='wp-block-query-pagination-previous-arrow is-arrow-arrow' aria-hidden='true'>←</span>Previous Page</a><div class="wp-block-query-pagination-numbers"><a class="page-numbers" href="https://barryvan.com.au/author/admin/">1</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="https://barryvan.com.au/author/admin/page/9/">9</a> <a class="page-numbers" href="https://barryvan.com.au/author/admin/page/10/">10</a> <span aria-current="page" class="page-numbers current">11</span> <a class="page-numbers" href="https://barryvan.com.au/author/admin/page/12/">12</a> <a class="page-numbers" href="https://barryvan.com.au/author/admin/page/13/">13</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="https://barryvan.com.au/author/admin/page/16/">16</a></div> <a href="https://barryvan.com.au/author/admin/page/12/" class="wp-block-query-pagination-next">Next Page<span class='wp-block-query-pagination-next-arrow is-arrow-arrow' aria-hidden='true'>→</span></a></nav></div></div></main><footer class="wp-block-template-part"><div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--50)"><div class="wp-block-group alignwide is-layout-flow wp-block-group-is-layout-flow"><div class="wp-block-group alignfull is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-e5edad21 wp-block-group-is-layout-flex"><div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex"><div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:100%"><h2 class="wp-block-site-title"><a href="https://barryvan.com.au" target="_self" rel="home">barryvan</a></h2></div><div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"><div style="height:var(--wp--preset--spacing--40);width:0px" aria-hidden="true" class="wp-block-spacer"></div></div></div><div class="wp-block-group is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-570722b2 wp-block-group-is-layout-flex"><nav class="is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-fe9cc265 wp-block-navigation-is-layout-flex"><ul class="wp-block-navigation__container is-vertical wp-block-navigation"><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Blog</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">About</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">FAQs</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Authors</span></a></li></ul></nav><nav class="is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-fe9cc265 wp-block-navigation-is-layout-flex"><ul class="wp-block-navigation__container is-vertical wp-block-navigation"><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Events</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Shop</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Patterns</span></a></li><li class=" wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Themes</span></a></li></ul></nav></div></div><div style="height:var(--wp--preset--spacing--70)" aria-hidden="true" class="wp-block-spacer"></div><div class="wp-block-group alignfull is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-91e87306 wp-block-group-is-layout-flex"><p class="has-small-font-size">Twenty Twenty-Five</p><p class="has-small-font-size"> Designed with <a href="https://wordpress.org" rel="nofollow">WordPress</a></p></div></div></div></footer></div> <script type="speculationrules">{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"\/*"},{"not":{"href_matches":["\/wp-*.php","\/wp-admin\/*","\/wp-content\/uploads\/*","\/wp-content\/*","\/wp-content\/plugins\/*","\/wp-content\/themes\/twentytwentyfive\/*","\/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}</script> <script id="wp-block-template-skip-link-js-after" type="litespeed/javascript">(function(){var skipLinkTarget=document.querySelector('main'),sibling,skipLinkTargetID,skipLink;if(!skipLinkTarget){return} sibling=document.querySelector('.wp-site-blocks');if(!sibling){return} skipLinkTargetID=skipLinkTarget.id;if(!skipLinkTargetID){skipLinkTargetID='wp--skip-link--target';skipLinkTarget.id=skipLinkTargetID} skipLink=document.createElement('a');skipLink.classList.add('skip-link','screen-reader-text');skipLink.id='wp-skip-link';skipLink.href='#'+skipLinkTargetID;skipLink.innerText='Skip to content';sibling.parentElement.insertBefore(skipLink,sibling)}())</script> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://barryvan.com.au/wp-content/litespeed/js/1518570de88f10e7f6bc3a4483a1a761.js?ver=ba8cd"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body></html> <!-- Page optimized by LiteSpeed Cache @2025-07-28 17:25:14 --> <!-- Page cached by LiteSpeed Cache 7.2 on 2025-07-28 17:25:12 --> <!-- Guest Mode --> <!-- QUIC.cloud UCSS in queue -->