<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://shazwazza.com/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Shazwazza</title>
    <link>https://shazwazza.com/</link>
    <description>My blog which is pretty much just all about coding</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <image>
      <url>/media/0libq25y/frog.png?rmode=max&amp;v=1da0e911f4e6890</url>
      <title>Shazwazza</title>
      <link>https://shazwazza.com/</link>
    </image>
    <item>
      <guid isPermaLink="false">1310</guid>
      <link>https://shazwazza.com/post/smidge-plus-nuglify-bundling-minification-and-source-maps/</link>
      <category>Web Development</category>
      <title>Smidge + Nuglify bundling, minification and source maps</title>
      <description>&lt;p&gt;Smidge &lt;strong&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/releases/tag/v2.0.0-rtm" target="_blank"&gt;2.0.0 RTM&lt;/a&gt;&lt;/strong&gt; is finally here!&lt;/p&gt;
&lt;p&gt;What is Smidge? Smidge is a lightweight &lt;u&gt;runtime &lt;/u&gt;bundling library (&lt;em&gt;CSS/JavaScript file minification, combination, compression&lt;/em&gt;) for ASP.NET Core -  &lt;a rel="noopener noreferrer" href="/post/smidge-20-alpha-is-out/" target="_blank"&gt;&lt;em&gt;Here’s some more background info on Smidge&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s plenty of great &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/milestone/5" target="_blank"&gt;new features in the version 2.0.0&lt;/a&gt; , but in this post I’ll just highlight a couple of fun ones….&lt;/p&gt;
&lt;h2&gt;Nuglify and source maps&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/xoofx/NUglify" target="_blank"&gt;Nuglify&lt;/a&gt; if an ASP.NET Core port of the old &lt;a rel="noopener noreferrer" href="http://ajaxmin.codeplex.com/" target="_blank"&gt;AjaxMin&lt;/a&gt; library and this works very nicely with Smidge too. By default Smidge uses an updated version of &lt;a rel="noopener noreferrer" href="http://www.crockford.com/javascript/jsmin.html" target="_blank"&gt;JsMin&lt;/a&gt; that I maintain called &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/JsMinSharp" target="_blank"&gt;JsMinSharp&lt;/a&gt; for it’s JavaScript minification engine. JsMin works fairly well, it’s primary feature is that it’s &lt;em&gt;fast &lt;/em&gt;because it doesn’t come with any bells and whistles and doesn’t produce a &lt;a rel="noopener noreferrer" href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank"&gt;Syntax Tree&lt;/a&gt;. Nuglify on the other hand does produce a Syntax Tree which gives it loads of control over how the minification is done so that it can produce much smaller files, has the ability to rename/reduce parts of the JS and to produce &lt;a rel="noopener noreferrer" href="https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/" target="_blank"&gt;source maps&lt;/a&gt;. The downfall of all this control is that it becomes much slower but Smidge is smart enough to cache processed files on the server in a persistent state so it won’t re-process your files if it doesn’t need to.&lt;/p&gt;
&lt;p&gt;Here’s a quick benchmark of JsMin vs Nuglify to minify jQuery using the default options (and no source map). As you can see JsMin is substantially faster and is far better for memory but Nuglify can reduce the file size quite a lot more &lt;em&gt;(smaller Minified % is better)&lt;/em&gt;&lt;/p&gt;
&lt;table border="0" width="700" style="box-sizing: border-box; overflow: auto; margin-bottom: 16px; white-space: normal; word-spacing: 0px; margin-top: 0px; border-collapse: collapse; text-transform: none; border-spacing: 0px; orphans: 2; widows: 2; display: block; letter-spacing: normal; background-color: #ffffff; text-indent: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px;"&gt;
&lt;thead&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #ffffff;"&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Method&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Median&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;StdDev&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Scaled&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Scaled-SD&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Minified %&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 0&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 1&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Gen 2&lt;/th&gt;
&lt;th style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Bytes Allocated/Op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #ffffff;"&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;JsMin&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;10.2008 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.3102 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;1.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;51.75%&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;-&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;155,624.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="box-sizing: border-box; border-top: #cccccc 1px solid; background-color: #f8f8f8;"&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;Nuglify&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;69.0778 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.0180 ms&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;6.72&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;0.16&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;32.71%&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;53.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;22.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;15.00&lt;/td&gt;
&lt;td style="box-sizing: border-box; border: #dddddd 1px solid; padding: 6px 13px 6px 13px;"&gt;4,837,313.07&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Source maps you say? JsMin isn’t all that smart so it can’t produce source maps (&lt;em&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge/issues/57" target="_blank"&gt;yet&lt;/a&gt;&lt;/em&gt;) but Nuglify certainly can and by default the &lt;em&gt;Smidge.Nuglify&lt;/em&gt; package has this turned on by default. Here’s how you can get this working:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Follow the super easy Smidge &lt;a rel="noopener noreferrer" href="https://github.com/Shazwazza/Smidge#quick-start" target="_blank"&gt;quick start installation guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the Smidge.Nuglify package
&lt;div&gt;
&lt;div class="nuget-badge"&gt;
&lt;p&gt;&lt;code&gt;PM&amp;gt; Install-Package Smidge.Nuglify&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Add Smidge Nuglify to your services: &lt;code&gt;services.AddSmidgeNuglify();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use Smidge Nuglify in your Configure method: &lt;code&gt;app.UseSmidgeNuglify();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace JsMin  with Nuglify for the default pipeline:
&lt;pre&gt;&lt;code class="language-csharp"&gt;services.Configure(opt =&amp;gt;
{
    opt.PipelineFactory.OnCreateDefault = (type, pipeline) =&amp;gt; pipeline.Replace(opt.PipelineFactory);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;That’s it! Nuglify is now the JS minifier for the default pipeline and will produce source maps. You can configure the Nuglify settings in the &lt;em&gt;AddSmidgeNuglify&lt;/em&gt; method.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now you can debug via the source maps in dev tools:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://shazwazza.com/media/articulate/windows-live-writer-smidge-nuglify_9f43-image_4.png"&gt;&lt;img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" src="https://shazwazza.com/media/articulate/windows-live-writer-smidge-nuglify_9f43-image_thumb_1.png" border="0" alt="image" title="image" width="600" height="350" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;File watching&lt;/h2&gt;
&lt;p&gt;Smidge can now watch your source files and if any changes are detected it can auto cache bust the bundle and flag for re-processing.&lt;/p&gt;
&lt;p&gt;Previous to version 2.0.0 if you were in release mode all of the bundling/minification would be active but you really just wanted to test this behavior but unfortunately it meant that if you updated a js/css file you would have to go bump the Smidge version in the config file to clear out the server side persistent cache. In 2.0.0, you can configure your bundle with different environment options for both Debug and Production. For example, perhaps in Debug mode you still want your bundles to be active so that the minification, combination, compression, etc… is still happening but you want to still actively edit files … you can easily do this! Here’s a nice fluent syntax to achieve this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;bundles.CreateJs("my-application", "~/js/site.js", "~/js/app")
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
        .ForDebug(builder =&amp;gt; builder
            .EnableCompositeProcessing()
            .EnableFileWatcher()
            .SetCacheBusterType())
        .Build()
    );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this example the “my-application” bundle will do the following when being rendered in debug:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Still process the files in the bundle and minify, combine, compress into a composite file&lt;/li&gt;
&lt;li&gt;Attach file watchers to all files in the bundle&lt;/li&gt;
&lt;li&gt;Change the cache buster for this bundle to only survive the lifespan of the current app domain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And what’s cool is that if you edit any of the source files in this bundle it will auto cache bust to a new value and re-process the bundle when it’s next requested.&lt;/p&gt;
&lt;h2&gt;Debug vs Production?&lt;/h2&gt;
&lt;p&gt;There’s a few ways that you could render assets in either debug or production mode but this is probably the easiest and uses ASP.NET Core’s environment tag helpers. Notice the debug attribute on the script/link tags and that the src/href attributes just include the bundle name … this is using Smidge’s tag helpers to define which bundle to render and if it’s in debug mode.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;environment names="Development"&amp;gt;
	&amp;lt;link rel="stylesheet" href="my-css" debug="true" /&amp;gt;
	&amp;lt;script src="my-js" debug="true"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/environment&amp;gt;

&amp;lt;environment names="Staging,Production"&amp;gt;
	&amp;lt;link rel="stylesheet" href="my-css" /&amp;gt;
	&amp;lt;script src="my-js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/environment&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Thanks!&lt;/h2&gt;
&lt;p&gt;Big thanks to &lt;a rel="noopener noreferrer" href="https://github.com/dazinator" target="_blank"&gt;@dazinator&lt;/a&gt; for all the help, recommendations, testing, feedback, etc… and for the rest of the community for filing bugs, questions, and comments. Much appreciated :)&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:27 Z</pubDate>
      <a10:updated>2023-03-23T15:08:27Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1245</guid>
      <link>https://shazwazza.com/post/smidge-20-alpha-is-out/</link>
      <category>ASP.Net</category>
      <title>Smidge 2.0 alpha is out</title>
      <description>&lt;style&gt;
div.nuget-badge p code {
background: none;
background-color: #202020 !important;
border: 4px solid silver !important;
border-bottom-left-radius: 5px 5px !important;
border-bottom-right-radius: 5px 5px !important;
border-top-left-radius: 5px 5px !important;
border-top-right-radius: 5px 5px !important;
color: #e2e2e2 !important;
display: block !important;
font: normal normal normal 1.5em/normal 'andale mono', 'lucida console', monospace !important;
line-height: 1.5em !important;
overflow: auto !important;
padding: 15px !important;
}
&lt;/style&gt; &lt;img title="ASP.NET-Core-Logo_2colors_RGB_bitmap_MEDIUM" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="ASP.NET-Core-Logo_2colors_RGB_bitmap_MEDIUM" src="http://shazwazza.com/media/articulate/windows-live-writer-smidge-20-alpha-is-out_abc7-aspnet-core-logo_2colors_rgb_bitmap_medium_5.png" width="198" height="57"&gt;  &lt;p&gt;What is Smidge? Smidge is a lightweight &lt;u&gt;runtime &lt;/u&gt;bundling library (&lt;em&gt;CSS/JavaScript file minification, combination, compression&lt;/em&gt;) for ASP.NET Core. &lt;/p&gt; &lt;p&gt;&lt;img style="float: left; margin: 10px 20px 10px 0px; display: inline" src="https://raw.githubusercontent.com/Shazwazza/Smidge/master/assets/logo2.png" align="left"&gt;If you’ve come from ASP.NET 4.5 you would have been familiar with the &lt;a href="https://www.asp.net/mvc/overview/performance/bundling-and-minification" target="_blank"&gt;bundling/minification API&lt;/a&gt; and other bundling options like &lt;a href="https://github.com/shazwazza/clientdependency" target="_blank"&gt;ClientDependency&lt;/a&gt;, but that is no longer available in ASP.NET Core, instead it is advised to do all the bundling and pre-processing that you need as part of your build process …which certainly makes sense! So why create this library? A few reasons: some people just want to have a very simple bundling library and don’t want to worry about Gulp or Grunt or WebPack, in a lot of cases the overhead of runtime processing is not going to make any difference, and lastly, if you have created something like a CMS that dynamically loads in assets from 3rd party packages or plugins, you need a runtime bundler since these things don’t exist at build time.&lt;/p&gt; &lt;p&gt;Over the past few months I’ve been working on some enhancements to Smidge and have found a bit of time to get an &lt;a href="https://github.com/Shazwazza/Smidge/releases/tag/2.0.0-alpha" target="_blank"&gt;alpha released&lt;/a&gt;.&amp;nbsp; There’s loads of great new features in &lt;strong&gt;Smidge 2.0&lt;/strong&gt;! You can install via Nuget and is targets .NET Standard 1.6 and .NET Framework 4.5.2&lt;/p&gt; &lt;div class="nuget-badge"&gt; &lt;p&gt;&lt;code&gt;PM&amp;gt; Install-Package Smidge -Pre&lt;/code&gt;&lt;/p&gt;&lt;/div&gt; &lt;h2&gt;New to Smidge?&lt;/h2&gt; &lt;p&gt;It’s easy to get started with Smidge and there’s &lt;a href="https://github.com/Shazwazza/Smidge" target="_blank"&gt;lots of docs available on GitHub&lt;/a&gt; that cover installation, configuration, creating bundles and rendering&amp;nbsp; them.&lt;/p&gt; &lt;h2&gt;New Features&lt;/h2&gt; &lt;p&gt;Here’s a list of new features complete with lots of code examples&lt;/p&gt; &lt;h3&gt;Customizable Debug and Production options&lt;/h3&gt; &lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/issues/58" href="https://github.com/Shazwazza/Smidge/issues/58"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/issues/58&lt;/font&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Previous to version 2.0, you could only configure aspects of the Production options and the Debug assets that were returned were just the raw static files. With 2.0, you have full control over how your assets are processed in both Debug and Production configurations. For example, if you wanted you could have your assets combined but not minified in Debug mode. This will also allow for non native web assets such as TypeScript to have pre-processors running and able to work in Debug mode. &lt;/p&gt; &lt;p&gt;Example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;services.AddSmidge(_config)
    .Configure&amp;lt;SmidgeOptions&amp;gt;(options =&amp;gt;
    {
        &lt;span class="rem"&gt;//set the default e-tag options for Debug mode&lt;/span&gt;
        options.DefaultBundleOptions.DebugOptions.CacheControlOptions.EnableETag = &lt;span class="kwrd"&gt;false&lt;/span&gt;        
    });&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;Fluent syntax for declaring/configuring bundles&lt;/h3&gt;
&lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/issues/55" href="https://github.com/Shazwazza/Smidge/issues/55"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/issues/55&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to customize Debug or Production options per bundle, you can do so with a fluent syntax, for example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseSmidge(bundles =&amp;gt;
{                
    &lt;span class="rem"&gt;//For this bundle, enable composite files for Debug mode, enable the file watcher so any changes&lt;/span&gt;
    &lt;span class="rem"&gt;//to the files are automatically re-processed and cache invalidated, disable cache control headers&lt;/span&gt;
    &lt;span class="rem"&gt;//and use a custom cache buster. You could of course use the .ForProduction options too &lt;/span&gt;
    bundles.Create(&lt;span class="str"&gt;"test-bundle-2"&lt;/span&gt;, WebFileType.Js, &lt;span class="str"&gt;"~/Js/Bundle2"&lt;/span&gt;)
        .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
                .ForDebug(builder =&amp;gt; builder
                    .EnableCompositeProcessing()
                    .EnableFileWatcher()
                    .SetCacheBusterType&amp;lt;AppDomainLifetimeCacheBuster&amp;gt;()
                    .CacheControlOptions(enableEtag: &lt;span class="kwrd"&gt;false&lt;/span&gt;, cacheControlMaxAge: 0))
                .Build()
        );                
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;Customizable Cache Buster&lt;/h3&gt;
&lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/issues/51" href="https://github.com/Shazwazza/Smidge/issues/51"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/issues/51&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In version 1.0 the only cache busting mechanism was Smidge’s version property which is set in config, in 2.0 Smidge allows you to control how cache busting is controlled at a global and bundle level. 2.0 ships with 2 &lt;em&gt;ICacheBuster&lt;/em&gt; types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;ConfigCacheBuster &lt;/em&gt;– the default and uses Smidge’s version property in config&lt;/p&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;AppDomainLifetimeCacheBuster &lt;/em&gt;– if enabled will mean that the server/browser cache will be invalidated on every app domain recycle&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;If you want a different behavior, you can define you own &lt;em&gt;ICacheBuster&lt;/em&gt; add it to the IoC container and then just use it globally or per bundle. For example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//Set a custom MyCacheBuster as the default one for Debug assets:&lt;/span&gt;
services.AddSmidge(_config)
    .Configure&amp;lt;SmidgeOptions&amp;gt;(options =&amp;gt;
    {
        options.DefaultBundleOptions.DebugOptions.SetCacheBusterType&amp;lt;MyCustomCacheBuster&amp;gt;();       
    });

&lt;span class="rem"&gt;//Set a custom MyCacheBuster as the cache buster for a particular bundle in debug mode:&lt;/span&gt;
bundles.Create(&lt;span class="str"&gt;"test-bundle-2"&lt;/span&gt;, WebFileType.Js, &lt;span class="str"&gt;"~/Js/Bundle2"&lt;/span&gt;)
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForDebug(builder =&amp;gt; builder
                .SetCacheBusterType&amp;lt;MyCacheBuster&amp;gt;()
            .Build()
    );&lt;/pre&gt;
&lt;h3&gt;Customizable cache headers&lt;/h3&gt;
&lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/issues/48" href="https://github.com/Shazwazza/Smidge/issues/48"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/issues/48&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;You can now control if you want the &lt;em&gt;ETag&lt;/em&gt; header output and you can control the value set for max-age/s-maxage/Expires header at a global or bundle level, for example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//This would set the max-age header for this bundle to expire in 5 days&lt;/span&gt;
bundles.Create(&lt;span class="str"&gt;"test-bundle-5"&lt;/span&gt;, WebFileType.Js, &lt;span class="str"&gt;"~/Js/Bundle5"&lt;/span&gt;)
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForProduction(builder =&amp;gt; builder                                
                .CacheControlOptions(enableEtag: &lt;span class="kwrd"&gt;true&lt;/span&gt;, cacheControlMaxAge: (5 * 24)))
            .Build()
    );&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;Callback to customize the pre-processor pipeline per web file&lt;/h3&gt;
&lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/issues/59" href="https://github.com/Shazwazza/Smidge/issues/59"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/issues/59&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is handy in case you want to modify the pipeline for a given web file at runtime based on some criteria, for example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;services.AddSmidge(_config)
    .Configure&amp;lt;SmidgeOptions&amp;gt;(options =&amp;gt;
    {
        &lt;span class="rem"&gt;//set the callback&lt;/span&gt;
        options.PipelineFactory.OnGetDefault = GetDefaultPipelineFactory;
    });

&lt;span class="rem"&gt;//The GetDefaultPipeline method could do something like modify the default pipeline to use Nuglify for JS processing:&lt;/span&gt;

&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; PreProcessPipeline GetDefaultPipelineFactory(WebFileType fileType, IReadOnlyCollection&amp;lt;IPreProcessor&amp;gt; processors)
{
    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (fileType)
    {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; WebFileType.Js:
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; PreProcessPipeline(&lt;span class="kwrd"&gt;new&lt;/span&gt; IPreProcessor[]
            {
                processors.OfType&amp;lt;NuglifyJs&amp;gt;().Single()
            });                
    }
    &lt;span class="rem"&gt;//returning null will fallback to the logic defined in the registered PreProcessPipelineFactory&lt;/span&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
}

&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;File watching with automatic cache invalidation&lt;/h3&gt;
&lt;p&gt;&lt;a title="https://github.com/Shazwazza/Smidge/pull/42" href="https://github.com/Shazwazza/Smidge/pull/42"&gt;&lt;font size="2"&gt;https://github.com/Shazwazza/Smidge/pull/42&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt;&amp;nbsp;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;During the development process it would be nice to be able to test composite files but have them auto re-process and invalidate the cache whenever one of the source files changes… in 2.0 this is possible!&amp;nbsp; You can enable file watching at the global level or per bundle. Example:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//Enable file watching for all files in this bundle when in Debug mode&lt;/span&gt;
bundles.Create(&lt;span class="str"&gt;"test-bundle-7"&lt;/span&gt;,
    &lt;span class="kwrd"&gt;new&lt;/span&gt; CssFile(&lt;span class="str"&gt;"~/Js/Bundle7/a1.js"&lt;/span&gt;),
    &lt;span class="kwrd"&gt;new&lt;/span&gt; CssFile(&lt;span class="str"&gt;"~/Js/Bundle7/a2.js"&lt;/span&gt;))
    .WithEnvironmentOptions(BundleEnvironmentOptions.Create()
            .ForDebug(builder =&amp;gt; builder.EnableFileWatcher())
            .Build()
    );&lt;/pre&gt;
&lt;h2&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;This is an alpha release since there’s a few things that I need to complete. Most are already done but I just need to make Nuget packages for them:&lt;/p&gt;
&lt;h4&gt;&lt;/h4&gt;
&lt;h3&gt;More pre-processors&lt;/h3&gt;
&lt;p&gt;I’ve enabled support for a &lt;a href="https://github.com/xoofx/NUglify" target="_blank"&gt;Nuglify&lt;/a&gt; pre-processor for both CSS and JS (Nuglify is a fork of the &lt;a href="http://ajaxmin.codeplex.com/"&gt;Microsoft Ajax Minifier&lt;/a&gt; for ASP.NET Core + additional features). I also enabled support for an Uglify NodeJs pre-processor which uses &lt;a href="https://github.com/aspnet/JavaScriptServices" target="_blank"&gt;Microsoft.AspNetCore.NodeServices&lt;/a&gt; to invoke Node.js from ASP.NET and run the JS version of Uglify. I just need to get these on Nuget but haven’t got around to that yet.&lt;/p&gt;
&lt;h3&gt;A quick note on minifier performance &lt;/h3&gt;
&lt;p&gt;Though Nuglify and Uglify have a better minification engine (better/smarter size reduction) than JsMin because they create an &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" target="_blank"&gt;AST (Abstract Syntax Tree)&lt;/a&gt; to perform it’s processing, they are actually much slower and consume more resources than JsMin. Since Smidge is a Runtime bundling engine, its generally important to ensure that the bundling/minification is performed quickly. Smidge has strict caching so the bundling/minification will only happen once (depending on your &lt;em&gt;ICacheBuster&lt;/em&gt; you are using) but it is still recommended to understand the performance implications of replacing JsMin with another minifier. &lt;a href="https://github.com/Shazwazza/Smidge/wiki/Custom-pre-processing#minification-benchmarks" target="_blank"&gt;I’ve put together some benchmarks&lt;/a&gt; (NOTE: a smaller Minified % is better):&lt;/p&gt;
&lt;table style="box-sizing: border-box; overflow: auto; margin-bottom: 16px; font-family: ; white-space: normal; word-spacing: 0px; margin-top: 0px; border-collapse: collapse; text-transform: none; color: ; border-spacing: 0px; orphans: 2; widows: 2; display: block; letter-spacing: normal; background-color: rgb(255,255,255); text-indent: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px" width="700"&gt;
&lt;thead style="box-sizing: border-box"&gt;
&lt;tr style="box-sizing: border-box; border-top: rgb(204,204,204) 1px solid; background-color: rgb(255,255,255)"&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Method&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Median&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;StdDev&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Scaled&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Scaled-SD&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Minified %&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Gen 0&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Gen 1&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Gen 2&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;
&lt;th style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Bytes Allocated/Op&lt;/font&gt;&lt;/font&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody style="box-sizing: border-box"&gt;
&lt;tr style="box-sizing: border-box; border-top: rgb(204,204,204) 1px solid; background-color: rgb(255,255,255)"&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;JsMin&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;10.2008 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;0.3102 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;1.00&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;0.00&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;51.75%&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;155,624.67&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="box-sizing: border-box; border-top: rgb(204,204,204) 1px solid; background-color: rgb(248,248,248)"&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;Nuglify&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;69.0778 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;0.0180 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;6.72&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;0.16&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;32.71%&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;53.00&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;22.00&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;15.00&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;4,837,313.07&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="box-sizing: border-box; border-top: rgb(204,204,204) 1px solid; background-color: rgb(255,255,255)"&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;JsServicesUglify&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;1,548.3951 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;7.6388 ms&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;150.95&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;3.73&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;32.63%&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;0.97&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;-&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;
&lt;td style="box-sizing: border-box; border-top: rgb(221,221,221) 1px solid; border-right: rgb(221,221,221) 1px solid; border-bottom: rgb(221,221,221) 1px solid; padding-bottom: 6px; padding-top: 6px; padding-left: 13px; border-left: rgb(221,221,221) 1px solid; padding-right: 13px"&gt;&lt;font face="Segoe UI"&gt;&lt;font style="font-size: 12pt" color="#333333"&gt;576,056.55&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;The last benchmark may be a bit misleading because the processing is done via NodeJs which executes in a separate process so I'm unsure if the actual memory usage of that can be properly captured by &lt;a href="https://github.com/dotnet/BenchmarkDotNet"&gt;BenchmarkDotNet&lt;/a&gt; but you can see it's speed is much slower. 
&lt;h2&gt;Thanks!&lt;/h2&gt;
&lt;p&gt;Big thanks to &lt;a href="https://github.com/dazinator" target="_blank"&gt;@dazinator&lt;/a&gt; for all the help, recommendations, testing, feedback, etc… and for the rest of the community for filing bugs, questions, and comments. Much appreciated :)&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:19 Z</pubDate>
      <a10:updated>2023-03-23T15:08:19Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1269</guid>
      <link>https://shazwazza.com/post/introducing-smidge-an-aspnet-5-runtime-jscss-pre-processor/</link>
      <category>ASP.Net</category>
      <category>Web Development</category>
      <title>Introducing ‘Smidge’ – an ASP.NET 5 runtime JS/CSS pre-processor</title>
      <description>&lt;p&gt;During the past month I decided to dive deep into learning ASP.NET 5, and what better way to learn than to start a new OSS project :)&lt;/p&gt;
&lt;p&gt;I chose to make a new new simple and extensible Javascript/CSS &lt;span style="text-decoration: underline;"&gt;runtime&lt;/span&gt; pre-processor for ASP.NET 5. It does file minification, combination and compression, has a nice file caching layer and it’s all done in async operations. I ported over a few ideas and code snippets from &lt;a href="https://github.com/Shazwazza/ClientDependency/" target="_blank"&gt;CDF (client dependency framework)&lt;/a&gt; but with a more modern approach. I’ve called it ‘Smidge’ = &lt;em&gt;something really small&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Shazwazza/Smidge" target="_blank"&gt;The project is on GitHub&lt;/a&gt;, it’s still a work in progress but its functional and there’s even some documentation! In the next few weeks I’ll get more of the code and docs updated and hopefully have a beta release out. In the meantime, you can clone the source, browse the code, build it and of course use it if you like.&lt;/p&gt;
&lt;h2&gt;Project details&lt;/h2&gt;
&lt;p&gt;It’s currently only targeting &lt;em&gt;aspnet50 &lt;/em&gt;and not the Core CLR… I didn’t start with Core CLR because there was some legacy code I had to port over and I wanted to get something up and working relatively quickly. It shouldn’t be too much work to convert to Core CLR and Mono, hopefully I’ll find time to do that soon. It’s referencing all of the beta-* libraries from the ASP.NET 5 nightly myget feeds since there’s some code I’m using that isn’t available in the current beta1 release (&lt;em&gt;like Microsoft.AspNet.WebUtilities.UriHelper&lt;/em&gt;). The target KRE version is currently &lt;em&gt;KRE-CLR-amd64 1.0.0-beta2-10760.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;I’ve put up an Alpha 1 release on Nuget, so you can install it from there:&lt;/p&gt;
&lt;div class="nuget-badge"&gt;
&lt;p&gt;PM&amp;gt; Install-Package Smidge -Pre&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There’s some &lt;a href="https://github.com/Shazwazza/Smidge/blob/master/README.md#install" target="_blank"&gt;installation instructions here&lt;/a&gt;, you’ll need to add the smidge.json file yourself for now, can’t figure out how to get VS 2015 (kpm pack) to package that up … more learning required!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;There’s certainly a lot of detective work involved in learning ASP.NET 5 but with the code being open source and browse-able/searchable on GitHub, it makes finding what you need fairly easy.&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:15 Z</pubDate>
      <a10:updated>2023-03-23T15:08:15Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1277</guid>
      <link>https://shazwazza.com/post/aspnet-5-linux-support-for-runtime-js-css-preprocessing-with-smidge/</link>
      <title>ASP.Net 5 Linux support for runtime JS &amp; CSS preprocessing with Smidge</title>
      <description>&lt;p&gt;I’ve been working on a side project called &lt;a href="https://github.com/Shazwazza/Smidge" target="_blank"&gt;Smidge&lt;/a&gt; which is a runtime JS &amp;amp; CSS preprocessor for ASP.Net 5. I started this late last year after the 2014 MS MVP Summit as a good starting point to deep dive into ASP.Net 5. I’ve been keeping the codebase up-to-date with the beta releases of ASP.Net 5, I have it cross compiled to both dnx451 and dnxcore50 and recently updated to use Beta 7. This week I decided to give running ASP.Net 5 CoreCLR on Linux… and the result is IT WORKS!&lt;/p&gt; &lt;p&gt;I have next to no experience with Linux and considering that, it wasn’t actually very difficult to get my test site for Smidge up and running. Here’s the info on how I set this up:&lt;/p&gt; &lt;h2&gt;Linux setup&lt;/h2&gt; &lt;p&gt;I decided to use Ubuntu 14.04.3 LTS. I installed in on Hyper-V on Windows 10 and that was all very easy. I also setup SSH with the server so that I could remote terminal to it which is much nicer than using the terminal through the UI interface of Ubuntu via Hyper-V. Then basically followed the instructions here: &lt;a title="https://github.com/aspnet/Home/blob/dev/GettingStartedDeb.md#getting-started-with-aspnet-5-and-linux" href="https://github.com/aspnet/Home/blob/dev/GettingStartedDeb.md#getting-started-with-aspnet-5-and-linux.issues"&gt;https://github.com/aspnet/Home/blob/dev/GettingStartedDeb.md#getting-started-with-aspnet-5-and-linux&lt;/a&gt; – except that I didn’t configure any Nuget package sources since that is built into dnvm now. Once that was done I used dnvm to install the default runtime:&amp;nbsp; &lt;strong&gt;dnvm upgrade. &lt;/strong&gt;This installed mono by default but for my purposes I needed ASP.Net 5 CoreCLR since that’s what Smidge is built against and I wanted to see this CoreCLR cross-platform stuff in action. Issuing this command does the trick: &lt;strong&gt;dnvm install 1.0.0-beta7 -r coreclr&lt;/strong&gt; . Now when I list the runtimes installed (&lt;strong&gt;dnvm list&lt;/strong&gt;) I get: &lt;/p&gt; &lt;p&gt;&lt;a href="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_2.png"&gt;&lt;img title="image" style="display: inline" alt="image" src="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_thumb.png" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;So now dnx is installed! We’re ready to go.&lt;/p&gt; &lt;h2&gt;dnu publish &amp;amp; bash&lt;/h2&gt; &lt;p&gt;What I really wanted to see was that I could build my solution on my Windows machine in Visual Studio and then export it and see if it would work on the Linux machine. Through the command line on Windows at the root of my project I used dnu publish (&lt;a title="https://github.com/aspnet/Home/wiki/DNX-utility#publish-dnu-publish" href="https://github.com/aspnet/Home/wiki/DNX-utility#publish-dnu-publish"&gt;https://github.com/aspnet/Home/wiki/DNX-utility#publish-dnu-publish&lt;/a&gt;) which outputs a ‘self-contained directory that can be launched’ = great! So I executed that command, it put the folder in my /bin folder for my current project and I copied over that directory to my Linux machine….&amp;nbsp; and realized I didn’t know what to do next ;)&lt;/p&gt; &lt;p&gt;I had a look through the files that dnu publish exports and the one that is listed in ASP.Net’s docs is the &lt;strong&gt;output/kestrel.cmd &lt;/strong&gt;(since the command in my project is named ‘kestrel’). Inside this file this is listed:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="str"&gt;@"dnx.exe"&lt;/span&gt; --appbase &lt;span class="str"&gt;"%~dp0approot\src\Smidge.Web"&lt;/span&gt; Microsoft.Dnx.ApplicationHost --configuration Debug kestrel %*&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;which if you want to translate to Linux, you could execute this at the Linux terminal at the root of this folder:&lt;/p&gt;&lt;pre class="csharpcode"&gt;dnx --appbase &lt;span class="str"&gt;"approot/src/Smidge.Web"&lt;/span&gt; Microsoft.Dnx.ApplicationHost --configuration Debug kestrel&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;… which will actually work, BUT it turns out there’s a way more &lt;em&gt;Linuxy &lt;/em&gt;way to do it. dnu publish also creates this file which isn’t in the docs:&amp;nbsp; &lt;strong&gt;output/kestrel &lt;/strong&gt;Having a look at this file, the first line is: &lt;strong&gt;#!/usr/bin/env bash &lt;/strong&gt;…&amp;nbsp; so I can only assume this is something for Linux since I’ve heard the term bash before. Turns out on Linux you can just do this in the terminal from the root of this folder!&lt;/p&gt;&lt;pre class="csharpcode"&gt;bash kestrel&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;Result:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_4.png"&gt;&lt;img title="image" style="display: inline" alt="image" src="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_thumb_1.png" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;WHOOHOOO!&lt;/p&gt;
&lt;h2&gt;Lets see it in action&lt;/h2&gt;
&lt;p&gt;Now that it’s running, I’ll jump over to the UI in Ubuntu and fire up the browser… Tada!!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_6.png"&gt;&lt;img title="image" style="display: inline" alt="image" src="http://shazwazza.com/media/articulate/windows-live-writer-e42f7a425c51_13ed8-image_thumb_2.png" width="600" height="889"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Problems along the way&lt;/h2&gt;
&lt;p&gt;I probably made the above sound a bit easier than it was ;) … I did run into a few setup issues along the way. &lt;/p&gt;
&lt;h4&gt;Problem #1&lt;/h4&gt;
&lt;p&gt;The first one was when I first tried to run dnx:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;failed to locate libcoreclr with error libunwind.so.8: cannot open shared object file: No such file or directory” when you run dnx or dnu command&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I solved this issue from reading about it on this nice post: &lt;a title="http://blogs.msdn.com/b/rdcdev/archive/2015/08/28/some-issues-when-hosting-asp-net-5-on-ubuntu-on-azure.aspx" href="http://blogs.msdn.com/b/rdcdev/archive/2015/08/28/some-issues-when-hosting-asp-net-5-on-ubuntu-on-azure.aspx"&gt;http://blogs.msdn.com/b/rdcdev/archive/2015/08/28/some-issues-when-hosting-asp-net-5-on-ubuntu-on-azure.aspx&lt;/a&gt; which has some other nice tricks if you run into Ubuntu issues with ASP.Net 5.&amp;nbsp; The solution was that I needed to run this command:&lt;/p&gt;&lt;pre class="csharpcode"&gt;sudo apt-get install libunwind8&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h4&gt;Problem #2&lt;/h4&gt;
&lt;p&gt;Then I got this exception:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The type initializer for 'libcrypto' threw an exception&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Which is referenced on this ASP.Net issue: &lt;a title="https://github.com/aspnet/dnx/issues/1806" href="https://github.com/aspnet/dnx/issues/1806"&gt;https://github.com/aspnet/dnx/issues/1806&lt;/a&gt; … and turns out that it’s also referenced on the above link. I can’t remember where exactly I found this solution but I had to run:&lt;/p&gt;&lt;pre class="csharpcode"&gt;apt-get install libcurl4-openssl-dev&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Problem #3&lt;/h4&gt;
&lt;p&gt;After fixing those 2 things, the bash kestrel command succeeded but when I went to test this in my browser, I just had a white screen. After Googling, I found this link: &lt;a title="http://stackoverflow.com/questions/28845892/blank-white-screen-on-error-with-kestrel-asp-net-5" href="http://stackoverflow.com/questions/28845892/blank-white-screen-on-error-with-kestrel-asp-net-5"&gt;http://stackoverflow.com/questions/28845892/blank-white-screen-on-error-with-kestrel-asp-net-5&lt;/a&gt; and as it turns out, I had the same issue. I forgot to add the error handling middleware. Perhaps when running in VS with IIS this is automatically taken care of for you… not sure. But in any case, it’s super important that you add it and you should add it as the first middleware so you can actually see if your other middleware fails, typically your ‘Configure’ method in your Startup class should start with:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    &lt;span class="rem"&gt;// Add the following to the request pipeline only in development environment.&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (env.IsDevelopment())
    {
        app.UseErrorPage();
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        &lt;span class="rem"&gt;// Add Error handling middleware which catches all application specific errors and&lt;/span&gt;
        &lt;span class="rem"&gt;// sends the request to the following path or controller action.&lt;/span&gt;
        app.UseErrorHandler(&lt;span class="str"&gt;"/Home/Error"&lt;/span&gt;);
    }
&lt;/pre&gt;
&lt;h4&gt;Problem #4&lt;/h4&gt;
&lt;p&gt;We’re not in Windows-land anymore! The errors I was getting were due to invalid file system paths. Turns out that .Net has always had this property: &lt;strong&gt;System.IO.Path.DirectorySeparatorChar &lt;/strong&gt;but there wasn’t much reason to use it since .Net only runs in Windows and that character is always backslash. So I had to change my hard coded backslash use to use this instead. Next file path issue was case sensitivity… DOH. The Smidge configuration file is: ~/smidge.json however in my c# code I was trying to load it in with “Smidge.json” which fails in Linux of course. &lt;/p&gt;
&lt;h4&gt;Problem #5&lt;/h4&gt;
&lt;p&gt;Static files… I’m so used to working with IIS I forgot that outside of IIS I’d need to make sure the static file middleware was used:&lt;/p&gt;&lt;pre class="csharpcode"&gt;app.UseStaticFiles();&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;I fixed that up and everything just worked… very freakin cool!!&lt;/p&gt;
&lt;h2&gt;Release – beta6&lt;/h2&gt;
&lt;p&gt;I’ve put up a new release on Nuget with these changes:&lt;/p&gt;
&lt;style type="text/css"&gt;
.nuget-badge code {
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    background-color: #202020;
    border: 4px solid silver;
    border-radius: 5px;
    box-shadow: 2px 2px 3px #6e6e6e;
    color: #e2e2e2;
    display: block;
    font: 1.5em 'andale mono','lucida console',monospace;
    line-height: 1.5em;
    overflow: auto;
    padding: 15px;
}
&lt;/style&gt;

&lt;div class="nuget-badge"&gt;
&lt;p&gt;&lt;code&gt;PM&amp;gt; Install-Package Smidge -Pre &lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;And the source is on GitHub: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;beta6 release: &lt;a title="https://github.com/Shazwazza/Smidge/releases/tag/1.0.0-beta5" href="https://github.com/Shazwazza/Smidge/releases/tag/1.0.0-beta6"&gt;https://github.com/Shazwazza/Smidge/releases/tag/1.0.0-beta6&lt;/a&gt; 
&lt;li&gt;home &amp;amp; docs: &lt;a title="https://github.com/Shazwazza/Smidge" href="https://github.com/Shazwazza/Smidge"&gt;https://github.com/Shazwazza/Smidge&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:15 Z</pubDate>
      <a10:updated>2023-03-23T15:08:15Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1273</guid>
      <link>https://shazwazza.com/post/umbraco-41-benchmarks-part-1/</link>
      <category>Umbraco</category>
      <category>Client Dependency</category>
      <title>Umbraco 4.1 Benchmarks Part 1</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;This is the first installment of what will hopefully be many Umbraco benchmark reports created by various members of the core team in the lead up to the launch of Umbraco 4.1. This benchmark report is about the request/response performance of the Umbraco back-office. This compares 4 different configurations: 4.0.3 with browser cache disabled (first run), 4.0.3 with browser cached files, 4.1 with browser cache disabled and 4.1 with browser cached files. These comparisons have been done by using newly installed Umbraco instances with ONLY the CWS package installed. The benchmark results were prepared by using &lt;a href="http://www.charlesproxy.com/" target="_blank"&gt;Charles Proxy&lt;/a&gt;.   &lt;style&gt;
































.stats th {background-color:#ffffcc;color:black;}
.stats td, .stats th {
border-top:solid 1px black;
border-right:solid 1px black;
border-top:solid 1px black;
}
.stats td.first, .stats th.first {
border-left:solid 1px black;
}
.stats tr.bottom td, .stats td.bottom {
border-bottom:solid 1px black;
}
.stats tr.one { background-color:#ededed;}
.stats tr.two { background-color:#dcdcdc;}
.stats tr.three { background-color:#ededed;}
.stats tr.four {background-color:#d6f5f5;}&lt;/style&gt;  &lt;table class="stats" cellspacing="0" cellpadding="2" width="623"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th class="first" valign="top" width="110"&gt;Test&lt;/th&gt; &lt;th valign="top" width="168"&gt;Stats&lt;/th&gt; &lt;th valign="top" width="68"&gt;4.0.3&lt;/th&gt; &lt;th valign="top" width="107"&gt;4.0.3 &lt;br&gt;client cached&lt;/th&gt; &lt;th valign="top" width="69"&gt;4.1&lt;/th&gt; &lt;th valign="top" width="99"&gt;4.1 &lt;br&gt;client cached&lt;/th&gt;&lt;/tr&gt; &lt;tr class="one"&gt; &lt;td class="first" valign="top" rowspan="2" width="110"&gt;&lt;strong&gt;Content app&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="168"&gt;Completed Requests&lt;/td&gt; &lt;td valign="top" width="68"&gt;68&lt;/td&gt; &lt;td valign="top" width="107"&gt;7&lt;/td&gt; &lt;td valign="top" width="69"&gt;46&lt;/td&gt; &lt;td valign="top" width="99"&gt;6&lt;/td&gt;&lt;/tr&gt; &lt;tr class="one"&gt; &lt;td valign="top" width="168"&gt;Response (KB)&lt;/td&gt; &lt;td valign="top" width="68"&gt;687.05&lt;/td&gt; &lt;td valign="top" width="107"&gt;72.48&lt;/td&gt; &lt;td valign="top" width="69"&gt;431.41&lt;/td&gt; &lt;td valign="top" width="99"&gt;32.54&lt;/td&gt;&lt;/tr&gt; &lt;tr class="two"&gt; &lt;td class="first" valign="top" rowspan="2" width="110"&gt;&lt;strong&gt;Edit content &lt;br&gt;home page&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="168"&gt;Completed Requests&lt;/td&gt; &lt;td valign="top" width="68"&gt;50&lt;/td&gt; &lt;td valign="top" width="107"&gt;2&lt;/td&gt; &lt;td valign="top" width="69"&gt;34&lt;/td&gt; &lt;td valign="top" width="99"&gt;1&lt;/td&gt;&lt;/tr&gt; &lt;tr class="two"&gt; &lt;td valign="top" width="168"&gt;Response (KB)&lt;/td&gt; &lt;td valign="top" width="68"&gt;385.10&lt;/td&gt; &lt;td valign="top" width="107"&gt;47.28&lt;/td&gt; &lt;td valign="top" width="69"&gt;343.36&lt;/td&gt; &lt;td valign="top" width="99"&gt;12.07&lt;/td&gt;&lt;/tr&gt; &lt;tr class="three"&gt; &lt;td class="first" valign="top" rowspan="2" width="110"&gt;&lt;strong&gt;Expand all &lt;br&gt;content nodes&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="168"&gt;Completed Requests&lt;/td&gt; &lt;td valign="top" width="68"&gt;17&lt;/td&gt; &lt;td valign="top" width="107"&gt;17&lt;/td&gt; &lt;td valign="top" width="69"&gt;16&lt;/td&gt; &lt;td valign="top" width="99"&gt;16&lt;/td&gt;&lt;/tr&gt; &lt;tr class="three"&gt; &lt;td valign="top" width="168"&gt;Response (KB)&lt;/td&gt; &lt;td valign="top" width="68"&gt;18.47&lt;/td&gt; &lt;td valign="top" width="107"&gt;18.47&lt;/td&gt; &lt;td valign="top" width="69"&gt;13.96&lt;/td&gt; &lt;td valign="top" width="99"&gt;10.85&lt;/td&gt;&lt;/tr&gt; &lt;tr class="four"&gt; &lt;td class="first bottom" valign="top" rowspan="2" width="110"&gt;&lt;strong&gt;TOTALS&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" width="168"&gt;Completed Requests&lt;/td&gt; &lt;td valign="top" width="68"&gt;135&lt;/td&gt; &lt;td valign="top" width="107"&gt;26&lt;/td&gt; &lt;td valign="top" width="69"&gt;96&lt;/td&gt; &lt;td valign="top" width="99"&gt;23&lt;/td&gt;&lt;/tr&gt; &lt;tr class="bottom four"&gt; &lt;td valign="top" width="168"&gt;Response (KB)&lt;/td&gt; &lt;td valign="top" width="68"&gt;1063.62&lt;/td&gt; &lt;td valign="top" width="107"&gt;138.23&lt;/td&gt; &lt;td valign="top" width="69"&gt;788.73&lt;/td&gt; &lt;td valign="top" width="99"&gt;55.46&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: the above is based on &amp;lt;compilation debug=”&lt;strong&gt;false&lt;/strong&gt;”&amp;gt; being set in the web.config. If it is set to true, the compression, combination and minification for both the ClientDependency framework and ScriptManager is not enabled. Also, this is not based on having IIS 7’s dynamic/static compression turned on, these benchmarks are based on Umbraco performing ‘as is ‘ out of the box which will be the same for IIS 6.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Though there’s only 3 tests listed above, these results will be consistent throughout all applications in the Umbraco back office in version 4.1.&lt;/p&gt; &lt;p&gt;The 4.1 difference:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;In 4.0.3, all ScriptResource calls generated by ScriptManager were not being compressed or minified. This was due to a browser compatibility flag that was set in the base page (this was probably very old code from pre v3!).  &lt;li&gt;Script managers in the back-office have the ScriptMode=”release” explicitly set (for minification of ScriptResource.axd)  &lt;li&gt;The &lt;a href="http://farmcode.org/page/ASPNet-ClientDependency-Framework.aspx" target="_blank"&gt;ClientDependency&lt;/a&gt; framework is shipped with 4.1 and all of the back office registers it’s JavaScript and CSS files with this framework. This allows for:  &lt;ul&gt; &lt;li&gt;Combination, compression, minification of dependencies  &lt;li&gt;Rogue script/style detection (for those scripts/styles that weren’t registered with the framework will still get compressed/minified)  &lt;li&gt;Compression/minification of specified Mime types, in this case all JSON requests in the back office (namely the tree)  &lt;li&gt;Compression/minification of all JavaScript web service proxy classes (‘asmx/js’ requests that are made by registering web services with the ScriptManager &lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Much of the back office client scripting in 4.1 has been completely refactored. Most of the JavaScript has been rewritten and a ton of file cleanup has been done. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Compared to 4.0.3, this is a HUGE difference with some serious performance benefits!&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1305</guid>
      <link>https://shazwazza.com/post/client-dependency-framework-beta-released/</link>
      <category>Client Dependency</category>
      <title>Client Dependency Framework Beta Released</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;I’ve posted a new Beta release on CodePlex, you can get it here: &lt;a href="http://clientdependency.codeplex.com/Release/ProjectReleases.aspx" target="_blank"&gt;http://clientdependency.codeplex.com/Release/ProjectReleases.aspx&lt;/a&gt;. On the releases tab includes a sample web site that has most of the functionality that you can do so please download it for a documentation reference.&lt;/p&gt;  &lt;h2&gt;Newest changes &amp;amp; additions&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Namespace and codebase changes/steamlining&lt;/li&gt;    &lt;li&gt;Proper versioning added&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Versioning is done on a global basis in the config&lt;/li&gt;      &lt;li&gt;Old versions are retained and can still be accessed from the Client Dependency URL that was previously used (if necessary) &lt;/li&gt;      &lt;li&gt;Versioned composite files names are prefixed with the version number (i.e. version 2 files will be prefixed with '2_') so it's easy to figure out which files are old &lt;/li&gt;      &lt;li&gt;The composite file map also reflects which composite file sets are under a specific version&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Provider model extended to support 2 types of providers: &lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;File Registration Providers        &lt;ul&gt;         &lt;li&gt;Still comes with 2 providers: page header provider and a lazy loading JavaScript client based provider&lt;/li&gt;       &lt;/ul&gt;     &lt;/li&gt;      &lt;li&gt;Composite File Providers: &lt;/li&gt;      &lt;ul&gt;       &lt;li&gt;Comes with the standard provider: CompositeFileProcessor &lt;/li&gt;        &lt;li&gt;You can implement your own provider to customize the way that files are combined, compressed, minified, etc... if the standard provider isn't exactly what you are after&lt;/li&gt;     &lt;/ul&gt;   &lt;/ul&gt;    &lt;li&gt;Forced providers! You can now force a dependency to use a particular provider. This can be useful if you want to ensure that a particular script or stylesheet is rendered on to the page differently. For example, you may want to ensure that a script is lazy loaded (using the lazy load provider) but the rest are rendered in the page header. &lt;/li&gt;    &lt;li&gt;Utility methods added to the ClientDependencyLoader for more dynamic implementations &lt;/li&gt;    &lt;li&gt;A test website is included in the release which doubles as documentation, it includes:      &lt;ul&gt;       &lt;li&gt;Standard page header provider example &lt;/li&gt;        &lt;li&gt;Forced providers example &lt;/li&gt;        &lt;li&gt;Lazy load provider example &lt;/li&gt;        &lt;li&gt;Dynamically registering dependencies in your code behind &lt;/li&gt;        &lt;li&gt;Registering dependencies with attributes and via aspx controls&lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Things //TODO:&lt;/h2&gt;  &lt;p&gt;I’ve finished off versioning so at least i can cross that off from the previous list. But there’s still more to do:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Implement functionality for jQuery CDN&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;This will be a new control/attribute to easily include jQuery in your project&lt;/li&gt;      &lt;li&gt;You will have the option to select which CDN you want to use (Microsoft or Google), or you can supply an address (like your own CDN/web server)&lt;/li&gt;      &lt;li&gt;Though this framework will be included in Umbraco 4.1, we’ll be leaving this functionality out of the Umbraco build as we realize that there are quite a few installs that operate behind a firewall that won’t have access to the CDN.&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Implement skeleton for Microsoft AJAX 4 CDN&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Again, this will be another new control/attribute to easily include Microsoft’s new brand of AJAX with their CDN solution&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Add support for MVC&lt;/li&gt;    &lt;li&gt;Support for JS/CSS Minification with options to disable per dependency&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;The reason this hasn’t been implemented yet is that I’ve found a lot of scripts/stylesheets break with minification so we need to be able to turn this on/off on a per file basis&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;Some more documentation/examples in the example web application&lt;/li&gt; &lt;/ul&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1307</guid>
      <link>https://shazwazza.com/post/clientdependency-now-supporting-mvc/</link>
      <category>Client Dependency</category>
      <title>ClientDependency now supporting MVC</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;I’m please to announce that the ClientDependency framework now supports MVC! It’s very easy to implement using HtmlHelper extension methods. Here’s some quick examples:  &lt;p&gt;Make a view dependent on a CSS file based on a path defined as “Styles”&lt;/p&gt;&lt;pre&gt;&amp;lt;% Html.RequiresCss("Content.css", "Styles"); %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Make a view dependent on jQuery using a full path declaration:&lt;/p&gt;&lt;pre&gt;&amp;lt;% Html.RequiresJs("/Js/jquery-1.3.2.min.js"); %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Rendering the Style blocks and defining a global style path:&lt;/p&gt;&lt;pre&gt;&amp;lt;%= Html.RenderCssHere(new BasicPath("Styles", "/Css")) %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Rendering the Script block (no global script path defined):&lt;/p&gt;&lt;pre&gt;&amp;lt;%= Html.RenderJsHere() %&amp;gt;&lt;/pre&gt;
&lt;p&gt;There’s still a provider model for MVC but it uses a slightly different implementation from Web Forms. The same &lt;code&gt;compositeFiles&lt;/code&gt; provider model is used but instead of the &lt;code&gt;fileRegistration&lt;/code&gt; provider model that is used in Web Forms, a new mvc &lt;code&gt;renderers&lt;/code&gt; provider model is used. A renderer provider is similar to the Web Forms &lt;code&gt;fileRegistration&lt;/code&gt; providers but instead of registering the markup in the page using the page life cycle, a renderer provider is used to render out the html block necessary to embed in the page.&lt;/p&gt;
&lt;p&gt;All of the functionality that existed in Web Forms exists in MVC. You can make as many views that you want dependent on as many of the same or different client files that you want and the system will still sort by position and priority and remove all duplicate registrations. Rogue scripts &amp;amp; styles still get processed by the composite file provider in MVC. Currently however, if you place user or composite controls on your views that have Client Dependencies tagged with either the control or attribute method used in Web Forms, these will not be registered with the view and output with the renderer.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;MVC pages have been added to the demo project as examples so have a look! You can download the source &lt;a style="font-size: 16pt" href="http://clientdependency.codeplex.com/SourceControl/list/changesets" target="_blank"&gt;HERE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For full details and documentation go &lt;a style="font-size: 16pt" href="http://clientdependency.codeplex.com/" target="_blank"&gt;HERE&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1249</guid>
      <link>https://shazwazza.com/post/sifr-vs-cufon-text-replacement-and-you/</link>
      <category>Web Development</category>
      <title>sIFR vs. cufón: Text replacement and you</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;There are two reasons I use dynamic text replacement:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Plain text in a browser window is never as smooth as it is in the design (except in Safari),&lt;/li&gt;
&lt;li&gt;The designs I'm given almost always use fancy (non-&lt;a href="http://web.mit.edu/jmorzins/www/fonts.html"&gt;web based&lt;/a&gt;) fonts for headings, intro text etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Currently I subscribe to two solutions, both client-side: &lt;a href="http://www.mikeindustries.com/blog/sifr"&gt;sIFR&lt;/a&gt; and  &lt;a href="http://wiki.github.com/sorccu/cufon"&gt;cuf&amp;oacute;n&lt;/a&gt;.  If you want a quick answer to "what should I use?" then here it is: if you want replacement for long sentences and headings, use sIFR.  If you want replacement for a few words on a button or in a menu, use cuf&amp;oacute;n.  If you want to know more, read on...&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://www.mikeindustries.com/blog/sifr"&gt;sIFR&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;How sIFR works&lt;/h3&gt;
&lt;p&gt;sIFR uses javascript to dynamically embed a Flash object in the place of specified HTML text elements.  The Flash object is essentially an empty SWF (compiled Flash file) which includes the characters of the font you want to use.  When javascript embeds the SWF in the HTML, it passes the SWF arguments such as text-content, font-size, color, rollover behaviour and many more.  Some of these properties javascript takes from the CSS applied to the text, and some are overridden by &lt;code&gt;sifr-config.js&lt;/code&gt;, which is a human-readable config file containing additional formatting tweaks.&lt;/p&gt;
&lt;h3&gt;How to use sIFR&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://dev.novemberborn.net/sifr3/nightlies/"&gt;Download the source&lt;/a&gt; (only &lt;code&gt;sifr.js&lt;/code&gt;, &lt;code&gt;sifr-config.js&lt;/code&gt; and &lt;code&gt;sifr.css&lt;/code&gt; are actually needed).&lt;/li&gt;
&lt;li&gt;Generate a font SWF from a True Type Font file.  You can do this manually with Adobe Flash (like &lt;a href="http://wiki.novemberborn.net/sifr3/How+to+use"&gt;this&lt;/a&gt;) but it is easier to use &lt;a href="http://www.sifrgenerator.com/wizard.html"&gt;this online generation tool&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Link to &lt;code&gt;sifr.css&lt;/code&gt; in the head of your HTML page.&lt;/li&gt;
&lt;li&gt;Link to both scripts in the head of your HTML page, first &lt;code&gt;sifr.js&lt;/code&gt;, then &lt;code&gt;sifr-config.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;sifr-config.js&lt;/code&gt; to read in the font SWF you created and use CSS selector syntax to select the HTML text elements you want to replace.&lt;/li&gt;
&lt;li&gt;Tweak away in &lt;code&gt;sifr-config.js&lt;/code&gt; until the text looks right when sIFR is both enabled and disabled, in case the user is missing Flash (iPhones don't have Flash as of early 2010!).&lt;/li&gt;
&lt;/ol&gt; 
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.mikeindustries.com/blog/sifr"&gt;sIFR 2.07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.novemberborn.net/sifr3/"&gt;sIFR 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;a href="http://wiki.github.com/sorccu/cufon"&gt;cuf&amp;oacute;n&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;How cuf&amp;oacute;n works&lt;/h3&gt;
&lt;p&gt;cuf&amp;oacute;n is entirely javascript and works in all major browsers (including IE6).  You still need to generate a font file, but this is output to a javascript file similar in size to the equivalent sIFR SWF font file.  cuf&amp;oacute;n looks at selected blocks of text and replaces each word with a dynamically generated image (using the HTML &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; tag), or in IE's case, a VML object (&lt;a href="http://en.wikipedia.org/wiki/Vector_Markup_Language"&gt;Vector Markup Language&lt;/a&gt;).  As a consquence of this, increasing the text size of the page either doesn't affect cuf&amp;oacute;n-replaced text or expands the image, blurring it.  Except in IE, which scales the text perfectly.&lt;/p&gt;
&lt;h3&gt;How to use cuf&amp;oacute;n&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download the source (all you need is &lt;code&gt;&lt;a href="http://cufon.shoqolate.com/js/cufon-yui.js"&gt;cufon-yui.js&lt;/a&gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Generate a font file from a True Type Font.  You are unfortunately dependent on &lt;a href="http://cufon.shoqolate.com/generate/"&gt;this online generator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Link to &lt;code&gt;cufon-yui.js&lt;/code&gt; in the head of your HTML page.  Beneath it, link to any font files you've generated.&lt;/li&gt;
&lt;li&gt;You may also want to create another file, &lt;code&gt;cufon-config.js&lt;/code&gt;, to hold selector information much the same way as &lt;code&gt;sifr-config.js&lt;/code&gt; does.&lt;/li&gt;
&lt;li&gt;Populate &lt;code&gt;cufon-config.js&lt;/code&gt; with what HTML text elements you want to replace.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Legality&lt;/h2&gt;
&lt;p&gt;Font foundaries are seemingly run by people who are very freaked out that their fonts are going to leak for free.  Hence, the vast majority of fonts can't legally be embedded directly into the CSS (what, you didn't know about that?  It's been around a while in some form or another - the &lt;a href="http://www.w3.org/TR/css3-fonts/#the-font-face-rule"&gt;@font-face&lt;/a&gt; directive allows you to supply the font file for obscure font-families - but it's only legal with open source fonts).&lt;/p&gt;
&lt;p&gt;Because sIFR uses Flash, and Adobe has a cordial agreement with the font foundaries in Switzerland (or wherever) which allows anyone to embed pretty much any font in a .swf, sIFR is totally legal.  cuf&amp;oacute;n... cuf&amp;oacute;n not so much.  Although both supply a compiled/obfuscated font resource in &lt;code&gt;.swf&lt;/code&gt;/&lt;code&gt;.js&lt;/code&gt; format respectively, and are basically the same from the font foundaries' point of view, they haven't got around to adding "Allows embedding using javascript methods" to their fonts' terms of use agreements.  And I wouldn't count on it...&lt;/p&gt;
&lt;p&gt;So in short, use cuf&amp;oacute;n. Go on, it's young and fresh and rad!  Push the font foundaries to legalise it!  But remember: you read that in a blog post...I'm not going to be your lawyer if they come after you.&lt;/p&gt;
&lt;h2&gt;Comparison&lt;/h2&gt;
&lt;table border="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;sIFR&lt;/th&gt; &lt;th&gt;cuf&amp;oacute;n&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core file-size (not including fonts)&lt;/td&gt;
&lt;td&gt;30KB&lt;/td&gt;
&lt;td&gt;18KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Independent of Flash&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resizes nicely&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor-selectable text&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Doesn't flicker on load&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Independent of online font-generator&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Online font-generator supports Open fonts (.otf)&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supported in all browsers&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Degrades gracefully&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legal&lt;/td&gt;
&lt;td&gt;&amp;radic;&lt;/td&gt;
&lt;td&gt;&amp;times;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1259</guid>
      <link>https://shazwazza.com/post/a-few-new-controls-in-umbraco-41/</link>
      <category>Umbraco</category>
      <title>A Few New Controls in Umbraco 4.1</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;Currently the codebase in Umbraco 4.0.x uses quite a few iframes to render ‘controls’ as this functionality has existed this way from way back in the day and had never been upgraded… until now! &lt;/p&gt;  &lt;p&gt;IFrames should be used sparingly, they have their uses but to render an iframe instead of a User Control is just adding overhead to the page, the client and server cpu/memory consumption and is not so cool. Here’s a nice benchmark on iframe performance: &lt;a title="http://www.stevesouders.com/blog/2009/06/03/using-iframes-sparingly/" href="http://www.stevesouders.com/blog/2009/06/03/using-iframes-sparingly/"&gt;http://www.stevesouders.com/blog/2009/06/03/using-iframes-sparingly/&lt;/a&gt; . As you can see, you should use iframes ONLY when completely necessary. &lt;/p&gt;  &lt;p&gt;So on to the good news… Here’s some new controls that have been created in 4.1 (which will remove many of these iframes and make things a whole lot nicer to use)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;/umbraco/controls/Tree/TreeControl.ascx&lt;/strong&gt;       &lt;ul&gt;       &lt;li&gt;Will render a new tree based on the properties set &lt;/li&gt;        &lt;li&gt;This makes the following Obsolete: treeInit.aspx, treePicker.aspx&amp;#160; (though, these pages are still used to load trees in modal windows for pickers but shouldn’t be used directly in your code)          &lt;ul&gt;           &lt;li&gt;Both of these pages now simply wrap the TreeControl &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;Example usage:          &lt;br /&gt;          &lt;pre&gt;&amp;lt;umb2:Tree runat=&amp;quot;server&amp;quot; ID=&amp;quot;DialogTree&amp;quot; 
    App=&amp;quot;media&amp;quot; TreeType=&amp;quot;media&amp;quot; IsDialog=&amp;quot;true&amp;quot; 
    CustomContainerId=&amp;quot;TinyMCEInsertImageTree&amp;quot; ShowContextMenu=&amp;quot;false&amp;quot; 
    DialogMode=&amp;quot;id&amp;quot; FunctionToCall=&amp;quot;dialogHandler&amp;quot; /&amp;gt;&lt;/pre&gt;

        &lt;br /&gt;&lt;/li&gt;

      &lt;li&gt;There’s quite a few other properties that allow you to customize the tree to your needs &lt;/li&gt;

      &lt;li&gt;There’s also a very in-depth JavaScript API &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;/umbraco/controls/Images/ImageViewer.ascx&lt;/strong&gt; 

    &lt;ul&gt;
      &lt;li&gt;This is a nifty ajax control that will take a media item id and display the image &lt;/li&gt;

      &lt;li&gt;There’s a simple JavaScript library attached to it that allows you to dynamically update the media id to force an ajax request to refresh the image (amongst other methods) &lt;/li&gt;

      &lt;li&gt;This makes the following Obsolete: /umbraco/dialogs/imageViewer.aspx 
        &lt;ul&gt;
          &lt;li&gt;The old codebase for imageViewer has been retained (though it should probably just wrap this control :) &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;

      &lt;li&gt;Example usage: 
        &lt;br /&gt;

        &lt;pre&gt;&amp;lt;umb3:Image runat=&amp;quot;server&amp;quot; ID=&amp;quot;ImageViewer&amp;quot; 
    ViewerStyle=&amp;quot;ThumbnailPreview&amp;quot; LinkTarget=&amp;quot;_blank&amp;quot; 
    ClientCallbackMethod=&amp;quot;onImageLoaded&amp;quot; /&amp;gt;&lt;/pre&gt;

        &lt;br /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;/umbraco/controls/UploadMediaImage.ascx&lt;/strong&gt; 

    &lt;ul&gt;
      &lt;li&gt;This control is essentially what you see when you load up TinyMCE, select the insert image button, then click on the ‘Create New’ tab. It contains the logic to enter a name, select a file to upload and select the media tree node to upload it to. &lt;/li&gt;

      &lt;li&gt;There’s a handy JavaScript callback method you can define so that it’s executed once the upload is complete. Tons of parameters are passed to the callback containing all of the information about the file/image. &lt;/li&gt;

      &lt;li&gt;This makes the following Obsolete: /umbraco/dialog/uploadImage.aspx &lt;/li&gt;

      &lt;li&gt;Example usage: 
        &lt;br /&gt;

        &lt;pre&gt;&amp;lt;umb4:MediaUpload runat=&amp;quot;server&amp;quot; ID=&amp;quot;MediaUploader&amp;quot; 
    OnClientUpload=&amp;quot;onFileUploaded&amp;quot; /&amp;gt;&lt;/pre&gt;

        &lt;br /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, on to the ‘pickers’! There’s quite a few picker controls in the codebase that all essentially do the same thing but the code for them was pretty much replicated everywhere, so i decided to streamline the whole thing which should make it quite easy for anyone to make their own pickers!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;umbraco.controls.BaseTreePicker.BaseTreePicker&lt;/strong&gt; (in the &lt;em&gt;umbraco.controls&lt;/em&gt; assembly) 

    &lt;ul&gt;
      &lt;li&gt;(yes i know the namespace and control are the same name, but that’s the way it is currently! :) &lt;/li&gt;

      &lt;li&gt;From the name, you would probably determine that this control is an abstract control… and you’d be correct. &lt;/li&gt;

      &lt;li&gt;This control implements: &lt;em&gt;IDataEditor&lt;/em&gt; (so that it can be used as the data editor for Umbraco data type controls), and &lt;em&gt;INamingContainer&lt;/em&gt; for obvious reasons. &lt;/li&gt;

      &lt;li&gt;This control exposes many properties and methods for you to modify and override to customize the picker. &lt;/li&gt;

      &lt;li&gt;The abstract properties are &lt;em&gt;ModalWindowTitle&lt;/em&gt; (the title of the window that gets displayed) and &lt;em&gt;TreePickerUrl&lt;/em&gt; (the URL to load in the modal window that is displayed) &lt;/li&gt;

      &lt;li&gt;This pretty much handles everything for a basic tree picker and the JavaScript has been refined to use real classes! Wow! ;) &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;umbraco.editorControls.mediaChooser&lt;/strong&gt; (in the &lt;em&gt;umbraco.editorControls&lt;/em&gt; assembly) 

    &lt;ul&gt;
      &lt;li&gt;This is the umbraco data type to select a media item from the media tree &lt;/li&gt;

      &lt;li&gt;It’s been upgraded to inherit from &lt;em&gt;BaseTreePicker&lt;/em&gt; and overrides the JavaScript rendered to support Tim’s new fandangled media picker (similar to the TinyMCE media picker) &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;umbraco.editorControls.pagePicker&lt;/strong&gt; (in the &lt;em&gt;umbraco.editorControls&lt;/em&gt; assembly) 

    &lt;ul&gt;
      &lt;li&gt;This is the umbraco data type to select a content node from the content tree &lt;/li&gt;

      &lt;li&gt;It’s been upgraded to inherit from &lt;em&gt;BaseTreePicker&lt;/em&gt; … it really doesn’t have any special functionality apart from setting the title and the tree picker url since all of the required functionality is in the BaseTreePicker &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;umbraco.controls.ContentPicker&lt;/strong&gt; (in the &lt;em&gt;umbraco&lt;/em&gt; assembly) 

    &lt;ul&gt;
      &lt;li&gt;This pretty much does the same thing as all of the above controls, actually it’s nearly identical to the pagePicker only you have to specify the AppAlias and TreeAlias to load for the picker. &lt;/li&gt;

      &lt;li&gt;It’s been upgraded to inherit from &lt;em&gt;BaseTreePicker&lt;/em&gt; also &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So basically, everything will look pretty much the same, but will be a lot faster and MUCH easier to develop with if you’re creating custom packages or whatever. It’s all backwards compatible (apart from the JavaScripting) but under the hood is much different.&lt;/p&gt;

&lt;p&gt;So now at least when you load up the TinyMCE insert image dialog, you end up with 1 frame (the modal dialog) instead of 4!&lt;/p&gt;

&lt;p&gt;Oh yeah, and this hasn’t been checked in to the 4.1 branch as of today… perhaps next week!&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1244</guid>
      <link>https://shazwazza.com/post/jquery-popup-bubble-extension/</link>
      <category>Web Development</category>
      <title>jQuery popup bubble extension</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;UPDATED (2009-05-25)! &lt;/p&gt; &lt;p&gt;Here's a quick and extensible framework to enable popup windows, popup bubbles, or popup anything. Currently the framework doesn't create extra DOM elements or style anything differently. It relies on the developer to create the DOM element that will be the popup bubble (or whatever). This extension give you the flexibility to bind any number of events to show or hide the bubble. It also supports having the bubble hide on a timer and comes with a complete event model allowing you to intercept the hide and show bubble events (and cancel them if needed) and fire your own methods upon completion. &lt;/p&gt; &lt;p&gt;I've included a full demo html page to demonstrate some different implementations. &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Here's the code: &lt;a href="/file.axd?file=2009%2f5%2fAlertBubble.zip"&gt;AlertBubble.zip (20.74 kb)&lt;/a&gt; &lt;/li&gt; &lt;li&gt;Here's a &lt;a href="/sourcecode/sourcecode/jquerypopupbubble/AlertBubble.htm" target="_blank"&gt;demo&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Here's an example of the usage: &lt;/p&gt;&lt;pre&gt;$(".bubble").AlertBubble(
{
	fadeTime: 500,
	hideEvent: [
		{selector: $("#hideButton"), event: "click"}
	],
	showEvent: [
		{selector: $("#showButton"), event: "click"}
	],
	showOnStart: true,
	text: "I am a bubble",
	hideTimer:2000
});
&lt;/pre&gt;The above code turns the elements with the class of .bubble into an AlertBubble. The parameters passed in are the parameters that are supported by this class: &lt;br&gt;
&lt;ul&gt;
&lt;li&gt;fadeTime: the milliseconds to fade in/out. Default = 200&amp;nbsp; &lt;li&gt;text: the text to show in the html element. If set to false (by default) it will use the markup that currently exists in the element. 
&lt;li&gt;hideEvent/showEvent 
&lt;ul&gt;
&lt;li&gt;Allows you to add/remove as many event handlers to show or hide the alert bubble &lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;showOnStart: if the bubble should show on page load or only when showOnStart exists 
&lt;li&gt;hideTimer: If set, then the bubble will hide after the set number of milliseconds after shown. Default is false. 
&lt;li&gt;onBeforeShowCallback: a function to call before the bubble is shown. If a callback is specified, it must return true for the code to proceed to show the bubble. 
&lt;li&gt;onBeforeHideCallback: a function to call before the bubble is hidden. If a callback is specified, it must return true for the code to proceed to hide the bubble. 
&lt;li&gt;onAfterShowCallback: a function to call after the bubble is shown. 
&lt;li&gt;onAfterHideCallback: a function to call after the bubble is hidden. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The extension also has a simple API that can be accessed to show/hide the bubble on demand as well as using events. This is done by storing the API object for the popup bubble extension in the jQuery data object for the popup bubble selector. &lt;/p&gt;
&lt;p&gt;API methods: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;showBubble() 
&lt;li&gt;hideBubble() &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;To access the API, you can retrieve it from the jQuery data object with the key "AlertBubble": &lt;/p&gt;&lt;pre&gt;var api = $(".myselector").data("AlertBubble"); 
&lt;/pre&gt;
&lt;p&gt;Example: &lt;/p&gt;&lt;pre&gt;$(".bubble").each(function() {
	var api = $(this).data("AlertBubble");
	if (api != null) {
		api.hideBubble();
	}
});
&lt;/pre&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1173</guid>
      <link>https://shazwazza.com/post/jquery-vertical-align/</link>
      <category>Web Development</category>
      <title>jQuery Vertical Align</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;UPDATED! (2009-04-29) &lt;/p&gt;  &lt;p&gt;An easy way to vertical align elements with one line of code: &lt;/p&gt;  &lt;pre&gt;$('.innerText').VerticalAlign();&amp;#160; &lt;/pre&gt;

&lt;p&gt;&lt;em&gt;I've removed the parameters as it turns out if you pass in a negative offset using padding, IE6 throws an error and JavaScript fails to continue executing. If you get the following error in IE6 debugging, it may be due to passing in a negative value to a padding css attribute, or similar:&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;&lt;strong&gt;invalid argument jquery J[G]=K&lt;/strong&gt;&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;It's fairly easy to structure your html to not require a vertical align offset so it's really not needed anyways.&lt;/em&gt; 

  &lt;br /&gt;

  &lt;br /&gt;&lt;strike&gt;It also supports a couple of parameters:&lt;/strike&gt; 

  &lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strike&gt;offset = the number of pixels to offset the vertical alignment&lt;/strike&gt; 

    &lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;&lt;strike&gt;usePadding = true/false. the default is false which uses a margin to align, if set to true, it uses padding &lt;/strike&gt;

    &lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;strike&gt;$('.innerText').VerticalAlign({offset:-20, usePadding:true})&lt;/strike&gt;&lt;/pre&gt;

&lt;p&gt;Get the source:&amp;#160; &lt;a href="/file.axd?file=2009%2f4%2fVerticalAlign.zip"&gt;VerticalAlign.zip (290.00 bytes)&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1210</guid>
      <link>https://shazwazza.com/post/super-easy-jquery-events/</link>
      <category>Web Development</category>
      <title>Super easy jQuery events</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;&lt;p&gt;I've been using &lt;a title="jQuery" href="http://www.jquery.com"&gt;jQuery &lt;/a&gt;for a while but haven't really been using it much in the form of building custom classes or libraries. I've been working on re-developing &lt;a title="Umbraco" href="http://www.umbraco.org"&gt;Umbraco&lt;/a&gt;'s JavaScript tree using &lt;a title="jsTree" href="http://www.jstree.com/"&gt;jsTree&lt;/a&gt; (which is great by the way!) and have been writing a JavaScript library to support it. As with most code libraries, events play an important role in writing clean and effective code. In the past I've always used simple callback methods for &amp;quot;event handling&amp;quot; in JavaScript, but this isn't really an event system since it doesn't allow more than one subscriber. After some quick research, jQuery has this all built into the core, and by adding a couple very simple methods to your JavaScript classes, they will instantly support an event model! &lt;/p&gt;  &lt;p&gt;Quick example:&amp;#160; &lt;/p&gt;  &lt;pre&gt;var myObject = {
	addEventHandler: function(fnName, fn) {
		$(this).bind(fnName, fn);
	},
	removeEventHandler: function(fnName, fn) {
		$(this).unbind(fnName, fn);
	},
	doSomething: function() {
		$.event.trigger(&amp;quot;somethingHappening&amp;quot;, [this, &amp;quot;myEventArgs&amp;quot;]);
	}
}&lt;/pre&gt;

&lt;p&gt;The above example is an object defining 2 functions to manage it's event model and another method which raises an event called &amp;quot;somethingHappened&amp;quot; with an array of arguments that will get bubbled to the event handlers. &lt;/p&gt;

&lt;p&gt;To subscribe to the events is easy: &lt;/p&gt;

&lt;pre&gt;function onSomethingHappening(EV, args) {
	alert(&amp;quot;something happened!&amp;quot;);
	alert(&amp;quot;sender: &amp;quot; + args[0]);
	alert(&amp;quot;e: &amp;quot; + args[1]);
}
//subscribe to the event:
myObject.addEventHandler(&amp;quot;somethingHappening&amp;quot;, onSomethingHappening);&lt;/pre&gt;

&lt;p&gt;You'll notice that the above event handler function has 2 arguments, one called &amp;quot;EV&amp;quot; and one called &amp;quot;args&amp;quot;. The EV parameters is the &lt;a title="jQuery Event Object" href="http://docs.jquery.com/Events/jQuery.Event"&gt;jQuery event object&lt;/a&gt; and the second one is the custom arguments object that was created when raising the event. &lt;/p&gt;

&lt;p&gt;Since Umbraco's admin section uses an iframe approach, i though that managing events between the iframes would be an issue since they are all using seperate jQuery instantiations, but by raising and consuming events with the above method, this is no problem. &lt;/p&gt;
&lt;a title="jQuery" href="http://www.jquery.com"&gt;&lt;img alt="" src="/image.axd?picture=2009%2f3%2flogo_jquery.png" /&gt;&lt;/a&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1237</guid>
      <link>https://shazwazza.com/post/aspnet-client-dependency-framework-rc1-released/</link>
      <category>Client Dependency</category>
      <title>ASP.Net Client Dependency Framework RC1 Released!</title>
      <description>&lt;div class="imported-post"&gt;This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.&lt;/div&gt;With the community feedback, bug reports, patches, etc… I’ve managed to find time to upgrade this library to a release candidate status. We do use this framework in many production websites but it was great to hear from other in regards to specific bugs that were found relating to particular environments. These bugs have all been fixed up and this library is looking very stable. &lt;/p&gt;  &lt;p&gt;You can download the binaries &lt;a href="http://clientdependency.codeplex.com/releases/view/42193" target="_blank"&gt;&lt;strong style="font-size: 22px"&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Better yet, I’ve put together a near complete documentation library on CodePlex &lt;a href="http://clientdependency.codeplex.com/documentation" target="_blank"&gt;&lt;strong style="font-size: 22px"&gt;here&lt;/strong&gt;&lt;/a&gt; !!&lt;/p&gt;  &lt;p&gt;I still think the best way to learn about this project is to download the source code from CodePlex &lt;a href="http://clientdependency.codeplex.com/SourceControl/list/changesets" target="_blank"&gt;&lt;strong style="font-size: 22px"&gt;here &lt;/strong&gt;&lt;/a&gt;and have a look at the demo web application included.&lt;/p&gt;  &lt;p&gt;Moving forward, the next phase for this library is to add MVC support and another file registration provider called PlaceholderProvider which will give you even more granular control over where dependencies can be rendered in your markup. MVC support should be fairly straight forward and we’ll include a demo project for this as well.&lt;/p&gt;  &lt;p&gt;Well definitely be releasing a final version soon after the next Umbraco 4.1 release candidate is released (which will hopefully be fairly soon!)&lt;/p&gt;  &lt;p&gt;Happy day! Any and all feedback, bug reports and patches are definitely appreciated!&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:14 Z</pubDate>
      <a10:updated>2023-03-23T15:08:14Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1243</guid>
      <link>https://shazwazza.com/post/injecting-javascript-into-other-frames/</link>
      <category>Web Development</category>
      <title>Injecting JavaScript into other frames</title>
      <description>&lt;p&gt;The beautiful part of JavaScript is that it is ridiculously flexible and lets you do things that ‘probably’ shouldn’t be done. Here’s a good example of that. &lt;/p&gt;  &lt;p&gt;During &lt;a title="uComponents" href="http://uComponents.codeplex.com" target="_blank"&gt;uComponents&lt;/a&gt; development I stumbled upon a situation where I needed to attach a JavaScript method to the top-level frame from inside of an iframe. Well in fact it turns out this is quite easy, you can do something like this:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:b2b7db1f-4968-4424-90e5-74aef73189b9" class="wlWriterEditableSmartContent"&gt;&lt;pre style=" width: 538px; height: 20px;background-color:White;overflow: hidden;"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #000000;"&gt;window.top.doThis &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt;() { alert(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;woot!&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;); }&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;However, since we’re attaching the ‘doThis’ method to the main frame from an inner iframe, when the inner iframenavigates to another page, this function will no longer exist on the main frame… So this clearly isn’t going to work if we want to be able to call the ‘doThis’ method from the inner frame no matter when and where it navigates to… Conundrum! &lt;/p&gt;

&lt;p&gt;So the next possibility is to try to just inject a script block into the main frame from the iframewhich actually does work in Firefox and Chrome but fails in Internet Explorer and Safari. &lt;em&gt;(This snippet of code requires that you have jQuery loaded in the main frame)&lt;/em&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:8de3a41f-d280-4f2c-a969-b8f027f818be" class="wlWriterEditableSmartContent"&gt;&lt;pre style=" width: 458px; height: 88px;background-color:White;overflow: hidden;"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; js &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;function doThis() { alert('woot!'); }&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; injectScript &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
        .attr(&lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;type&lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;text/javascript&lt;/span&gt;&lt;span style="color: #000000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
        .html(js);
window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;head&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;).append(injectScript);&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;In the above, we’re creating a string function, creating a &amp;lt;script&amp;gt; block with jQuery, appending the string function to the script block and then appending this script block to the &amp;lt;head&amp;gt; element of the main frame. But as i said before, Firefox and Chrome are ok with this but Internet Explorer and Safari will throw JavaScript exceptions such as: &lt;strong&gt;Unexpected call to method or property access&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, so unless you don’t want to be cross browser, this isn’t going to work. It took me a while to figure out that you can do this, but this does work. Yes it looks pretty dodgy, and it probably is. In reality, attempting to do something like this is pretty dodgy to begin with. So here it is &lt;em&gt;(this works in Internet Explorer 8 (probably earlier ones too), Firefox 3.6 (probably earlier ones too) and Chrome 5 (probably earlier ones too) and i didn’t get around to testing Safari but I am assuming it works)&lt;/em&gt;:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:ef246e3a-c9e9-4a00-953a-ce41cf099551" class="wlWriterEditableSmartContent"&gt;&lt;pre style=" width: 635px; height: 210px;background-color:White;overflow: hidden;"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; iframe &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;#dummyIFrame&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;);
&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (iframe.length &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; html &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;script type='text/javascript'&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
                &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;this.window.doThis = function() { alert('woot'); };&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
                &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/script&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    iframe &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;iframe id='dummyIFrame'&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
                .append(html)
                .hide()
                .css(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;width&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;0px&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
                .css(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;height&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;0px&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;);
    window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;body&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;).append(iframe);
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;So i guess this requires a bit of explanation. All browsers seem to let you create iframes dynamically which also means that you can put whatever content into the iframes while it’s being created, including script blocks. Here’s what we’re doing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;checking if our ‘dummy’ iframe already exists (since we don’t want to create multiple dummy iframes since we only need one), if it doesn't: &lt;/li&gt;

  &lt;li&gt;create an html text block including the script that will attach the ‘doThis’ method to the ‘this.window’ object &lt;em&gt;(which for some reason will be referring to the window.top object)&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;next we create an iframe element and append the html text block, and then make sure the iframe is completely hidden &lt;/li&gt;

  &lt;li&gt;finally, we append the iframe to the main window’s body element &lt;/li&gt;
&lt;/ul&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:a4477b2f-25ba-41cc-a332-dce82c870058" class="wlWriterEditableSmartContent"&gt;&lt;pre style=" width: 497px; height: 20px;background-color:White;overflow: hidden;"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #000000;"&gt;window.top.doThis();&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;Nice! So this pretty much means that you can create code from an inner frame and attach it to a different frame, then have that code run in the context of the main frame with the main frame’s objects and script set.&lt;/p&gt;

&lt;p&gt;One last thing that i found out you can do, though i wouldn’t recommend it because i think it might start filling up your memory. But this is also possible:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:54c85647-7adb-41e2-a3e5-47d4cb1380bb" class="wlWriterEditableSmartContent"&gt;&lt;pre style=" width: 635px; height: 129px;background-color:White;overflow: hidden;"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #000000;"&gt;
&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="color: #000000;"&gt; html &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;script type='text/javascript'&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
            &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;this.window.doThis = function() { alert('woot'); };&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
            &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;this.window.doThis();&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
            &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;/script&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
iframe &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; window.top.$(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;iframe id='dummyIFrame'&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
            .append(html);&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;

&lt;p&gt;All that is happening here is that I’m attaching the ‘doThis’ method to the main frame’s window object, calling it directly after and then creating an iframe in memory with this script block. The funny part is that the method executes straight away and I haven’t attached the iframe to the DOM anywhere! &lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:09 Z</pubDate>
      <a10:updated>2023-03-23T15:08:09Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1238</guid>
      <link>https://shazwazza.com/post/listening-for-validation-changes-in-angularjs/</link>
      <category>Web Development</category>
      <title>Listening for validation changes in AngularJS</title>
      <description>&lt;p&gt;In some applications it can be really useful to have controllers listen for validation changes especially in more complicated AngularJS apps where ‘ng-repeat’ is used to render form controls. There’s plenty of cases where a parent scope might need to know about validation changes based on child scopes… one such case is a validation summary. There’s a couple ways to implement this (and probably more) but they all seem a bit hacky such as:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Apply a $watch to the current form object’s $valid property in the parent scope, then use jQuery to look for elements that have a class like ‘invalid’  &lt;ul&gt; &lt;li&gt;You could then use the scope() function on the DOM element that ng-repeat is used on to get any model information about the invalid item&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;In child scopes you could apply a $watch to individual form elements’ $valid property then change the $parent scope’s model values to indicate validation changes&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Instead what I wanted to achieve was a re-usable way to ‘bubble’ up validation changes from any scope’s form element to ancestor scopes without having to do any of the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;No jquery DOM selection  &lt;li&gt;No hard coding of form names to access the validation objects  &lt;li&gt;No requirement to modifying other scopes’ values&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;Implementation&lt;/h2&gt; &lt;p&gt;The way I went about this was to create a very simple custom directive which I’ve called ‘val-bubble’ since it has to do with validation and it ‘bubbles’ up a message to any listening scopes. An input element might then look like this:&lt;/p&gt; &lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="FirstName"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="text"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;required&lt;/span&gt; &lt;span style="color: #ff0000"&gt;val-bubble&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;Then in an outer scope I can then listen for validation changes and do whatever I want with the result:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;scope.$on(&lt;span style="color: #006080"&gt;"valBubble"&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(evt, args) {&lt;br&gt;    alert(&lt;span style="color: #006080"&gt;"Validation changed for field "&lt;/span&gt; + args.ctrl.$name + &lt;span style="color: #006080"&gt;". Valid? "&lt;/span&gt; + args.isValid);&lt;br&gt;});&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The args object contains these properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;isValid = is the field valid 
&lt;li&gt;ctrl = the current form controller object for the field 
&lt;li&gt;scope = the scope bound to the field being validated 
&lt;li&gt;element = the DOM element of the field being validated 
&lt;li&gt;expression = the current $watch expression used to watch this fields validation changes&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;With all of that information you can easily adds some additional functionality to your app based on the current validating inputs such as a validation summary or whatever.&lt;/p&gt;
&lt;h2&gt;Custom directive&lt;/h2&gt;
&lt;p&gt;The val-bubble custom directive is pretty simple, here’s the code and an explanation below:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 500px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;app.directive(&lt;span style="color: #006080"&gt;'valBubble'&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (formHelper) {&lt;br&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; {&lt;br&gt;        require: &lt;span style="color: #006080"&gt;'ngModel'&lt;/span&gt;,&lt;br&gt;        restrict: &lt;span style="color: #006080"&gt;"A"&lt;/span&gt;,&lt;br&gt;        link: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (scope, element, attr, ctrl) {&lt;br&gt;&lt;br&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!attr.name) {&lt;br&gt;                &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #006080"&gt;"valBubble must be set on an input element that has a 'name' attribute"&lt;/span&gt;;&lt;br&gt;            }&lt;br&gt;                &lt;br&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; currentForm = formHelper.getCurrentForm(scope);&lt;br&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!currentForm || !currentForm.$name)&lt;br&gt;                &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #006080"&gt;"valBubble requires that a name is assigned to the ng-form containing the validated input"&lt;/span&gt;;&lt;br&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;//watch the current form's validation for the current field name&lt;/span&gt;&lt;br&gt;            scope.$watch(currentForm.$name + &lt;span style="color: #006080"&gt;"."&lt;/span&gt; + ctrl.$name + &lt;span style="color: #006080"&gt;".$valid"&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (isValid, lastValue) {&lt;br&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (isValid != undefined) {&lt;br&gt;                    &lt;span style="color: #008000"&gt;//emit an event upwards &lt;/span&gt;&lt;br&gt;                    scope.$emit(&lt;span style="color: #006080"&gt;"valBubble"&lt;/span&gt;, {&lt;br&gt;                        isValid: isValid,       &lt;span style="color: #008000"&gt;// if the field is valid&lt;/span&gt;&lt;br&gt;                        element: element,       &lt;span style="color: #008000"&gt;// the element that the validation applies to&lt;/span&gt;&lt;br&gt;                        expression: &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.exp,   &lt;span style="color: #008000"&gt;// the expression that was watched to check validity&lt;/span&gt;&lt;br&gt;                        scope: scope,           &lt;span style="color: #008000"&gt;// the current scope&lt;/span&gt;&lt;br&gt;                        ctrl: ctrl              &lt;span style="color: #008000"&gt;// the current controller&lt;/span&gt;&lt;br&gt;                    });&lt;br&gt;                }&lt;br&gt;            });&lt;br&gt;        }&lt;br&gt;    };&lt;br&gt;});&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The first thing we’re doing here is limiting this directive to be used only as an attribute and ensuring the element has a model applied to it. Then we make sure that the element has a ‘name’ value applied. After that we are getting a reference to the current form object that this field is contained within using a custom method: &lt;em&gt;formHelper.getCurrentForm&lt;/em&gt; … more on this below. Lastly we are applying a $watch to the current element’s $valid property and when this value changes we $emit an event upwards to parent/ancestor scopes to listen for. &lt;/p&gt;
&lt;h2&gt;formHelper&lt;/h2&gt;
&lt;p&gt;Above I mentioned that I wanted a re-usable solution where I didn’t need to hard code things like the current form name. &lt;span style="text-decoration: line-through"&gt;Unfortunately Angular doesn’t really provide a way to do this OOTB (as far as I can tell!)&lt;/span&gt; &lt;em&gt;(Update! see here on how to access the current form: &lt;/em&gt;&lt;a href="http://shazwazza.com/post/Reference-the-current-form-controller-in-AngularJS"&gt;&lt;em&gt;http://shazwazza.com/post/Reference-the-current-form-controller-in-AngularJS&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt; so I’ve just created a simple factory object that finds the current form object applied to the current scope. The type check is fairly rudimentary but it works, it’s simply checking each property that exists on the scope object and tries to detect the object that matches the definition of an Angular form object:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 500px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;app.factory(&lt;span style="color: #006080"&gt;'formHelper'&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() {&lt;br&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; {&lt;br&gt;        getCurrentForm: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(scope) {&lt;br&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; form = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;br&gt;            &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; requiredFormProps = [&lt;span style="color: #006080"&gt;"$error"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$name"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$dirty"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$pristine"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$valid"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$invalid"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$addControl"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$removeControl"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$setValidity"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"$setDirty"&lt;/span&gt;];&lt;br&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; p &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; scope) {&lt;br&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_.isObject(scope[p]) &amp;amp;&amp;amp; !_.isFunction(scope[p]) &amp;amp;&amp;amp; !_.isArray(scope[p]) &amp;amp;&amp;amp; p.substr(0, 1) != &lt;span style="color: #006080"&gt;"$"&lt;/span&gt;) {&lt;br&gt;                    &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; props = _.keys(scope[p]);&lt;br&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (props.length &amp;lt; requiredFormProps.length) &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;br&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (_.every(requiredFormProps, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;(item) {&lt;br&gt;                        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; _.contains(props, item);&lt;br&gt;                    })) {&lt;br&gt;                        form = scope[p];&lt;br&gt;                        &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;br&gt;                    }&lt;br&gt;                }&lt;br&gt;            }&lt;br&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; form;&lt;br&gt;        }  &lt;br&gt;    };&lt;br&gt;});&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;NOTE: the above code has a dependency on UnderscoreJS&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So now you can just apply the val-bubble attribute to any input element to ensure it’s validation changes are published to listening scopes!&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1180</guid>
      <link>https://shazwazza.com/post/reference-the-current-form-controller-in-angularjs/</link>
      <category>Web Development</category>
      <title>Reference the current form controller in AngularJS</title>
      <description>&lt;p&gt;I previously wrote a post about &lt;a href="http://shazwazza.com/post/Listening-for-validation-changes-in-AngularJS"&gt;Listening for validation changes in AngularJS&lt;/a&gt; which with my knowledge at that time required a handy hack to get a reference to the currently scoped form controller (ngForm) for a given input control. I also complained a bit that it seemed that angular didn’t really provide a way to reference the current form controller without this little hack… well, it turns out I was wrong! :)&lt;/p&gt; &lt;p&gt;AngularJS seems kind of like ASP.Net MVC in the early days when there wasn’t much documentation…&amp;nbsp; It definitely pays off to read through the source code to figure out how to do more complicated things. I had a bit of a ‘light bulb’ moment when I realized that ngForm was itself a directive/controller and had recently noticed that the ‘require’ parameter of setting up a directive allows you to search for controllers in the current directives ancestry (i.e. prefix the required controller with a hat: ^ )&lt;/p&gt; &lt;h2&gt;What does the require parameter of a directive do?&lt;/h2&gt; &lt;p&gt;Lets face it, the &lt;a href="http://docs.angularjs.org/guide/directive" target="_blank"&gt;directive documentation&lt;/a&gt; for AngularJS is in desperate need of being updated so that human beings can understand it (as noted by the many comments at the bottom). So I’ll try to explain what the ‘require’ parameter actually does and how to use it. &lt;/p&gt; &lt;p&gt;We’ll create a simple custom validation directive which will invalidate a field if the value is “blah”&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;function&lt;/span&gt; blahValidator() {
    &lt;span class="kwrd"&gt;return&lt;/span&gt; {
        require: &lt;span class="str"&gt;'ngModel'&lt;/span&gt;,
        link: &lt;span class="kwrd"&gt;function&lt;/span&gt;(scope, elm, attr, ctrl) {
            
            &lt;span class="kwrd"&gt;var&lt;/span&gt; validator = &lt;span class="kwrd"&gt;function&lt;/span&gt;(value) {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (ctrl.$viewValue == &lt;span class="str"&gt;"blah"&lt;/span&gt;) {
                    ctrl.$setValidity(&lt;span class="str"&gt;'blah'&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;
                }
                &lt;span class="kwrd"&gt;else&lt;/span&gt; {
                    ctrl.$setValidity(&lt;span class="str"&gt;'blah'&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;);
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; value;
                }
            };

            ctrl.$formatters.push(validator);
            ctrl.$parsers.push(validator);
        }
    };
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;You’ll notice that we have a ‘require’ parameter specified for ‘ngModel’. What is happening here is that when we assign this directive to an input field, angular will ensure that the input field also has a defined ng-model attribute on it as well. Then angular will pass in the instance of the ng-model controller to the ‘ctrl’ parameter of the link function.&lt;/p&gt;
&lt;p&gt;So, the ‘require’ parameter dictates what the ‘ctrl’ parameter of the link function equals. &lt;/p&gt;
&lt;p&gt;You can also require multiple controllers:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://shazwazza.com/media/articulate-import/image_34.png"&gt;&lt;img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://shazwazza.com/media/articulate-import/image_thumb_32.png" width="462" height="138"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NOTE: the ctrl/ctrls parameter in the above 2 examples can be called whatever you want&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Special prefixes&lt;/h2&gt;
&lt;p&gt;Angular has 2 special prefixes for the ‘require’ parameter: &lt;/p&gt;
&lt;p&gt;^ = search the current directives ancestry for the controller&lt;/p&gt;
&lt;p&gt;? = don’t throw an exception if the required controller is not found, making it ‘optional’ not a requirement&lt;/p&gt;
&lt;p&gt;You can also combine them so angular will search the ancestry but it can be optional too such as: ^?ngController'&lt;/p&gt;
&lt;p&gt;In the above example, the blahValidator will only work if the directive is declared inside of an ng-controller block.&lt;/p&gt;
&lt;h2&gt;Referencing the current ng-form&lt;/h2&gt;
&lt;p&gt;Given the above examples, and knowing the ngForm itself is a controller we should be able to just make a requirement on ngForm and have it injected into the directive. BUT, it wont work the way you expect. For some reason angular references the ngForm controller by the name “form” which i discovered by browsing the source of angular.&lt;/p&gt;
&lt;p&gt;So now its easy to get a reference to the containing ngForm controller, all you need to do is add a ‘require’ parameter to your directive that looks like:&lt;/p&gt;&lt;pre class="csharpcode"&gt;require: '^form'&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
and it will be injected into your ctrl parameter of your link function.</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1292</guid>
      <link>https://shazwazza.com/post/uploading-files-and-json-data-in-the-same-request-with-angular-js/</link>
      <category>Web Development</category>
      <title>Uploading files and JSON data in the same request with Angular JS</title>
      <description>&lt;p&gt;I decided to write a quick blog post about this because much of the documentation and examples about this seems to be a bit scattered. What this achieves is the ability to upload any number of files with any other type of data in &lt;strong&gt;one&lt;/strong&gt; request. For this example we’ll send up JSON data along with some files.&lt;/p&gt; &lt;h2&gt;File upload directive&lt;/h2&gt; &lt;p&gt;First we’ll create a simple custom file upload angular directive&lt;/p&gt; &lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; height: 261px; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 420px; width: 97.99%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; height: 243px; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;app.directive(&lt;span style="color: #006080"&gt;'fileUpload'&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;br&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; {&lt;br&gt;        scope: &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;,        &lt;span style="color: #008000"&gt;//create a new scope&lt;/span&gt;&lt;br&gt;        link: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (scope, el, attrs) {&lt;br&gt;            el.bind(&lt;span style="color: #006080"&gt;'change'&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;event&lt;/span&gt;) {&lt;br&gt;                &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; files = &lt;span style="color: #0000ff"&gt;event&lt;/span&gt;.target.files;&lt;br&gt;                &lt;span style="color: #008000"&gt;//iterate files since 'multiple' may be specified on the element&lt;/span&gt;&lt;br&gt;                &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; i = 0;i&amp;lt;files.length;i++) {&lt;br&gt;                    &lt;span style="color: #008000"&gt;//emit event upward&lt;/span&gt;&lt;br&gt;                    scope.$emit(&lt;span style="color: #006080"&gt;"fileSelected"&lt;/span&gt;, { file: files[i] });&lt;br&gt;                }                                       &lt;br&gt;            });&lt;br&gt;        }&lt;br&gt;    };&lt;br&gt;});&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The usage of this is simple:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;file-upload&lt;/span&gt; &lt;span style="color: #ff0000"&gt;multiple&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The ‘multiple’ parameter indicates that the user can select multiple files to upload which this example fully supports.&lt;/p&gt;
&lt;p&gt;In the directive we ensure a new scope is created and then listen for changes made to the file input element. When changes are detected with emit an event to all ancestor scopes (upward) with the file object as a parameter.&lt;/p&gt;
&lt;h2&gt;Mark-up &amp;amp; the controller&lt;/h2&gt;
&lt;p&gt;Next we’ll create a controller to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a model to bind to 
&lt;li&gt;Create a collection of files 
&lt;li&gt;Consume this event so we can assign the files to&amp;nbsp; the collection 
&lt;li&gt;Create a method to post it all to the server&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;NOTE: I’ve put all this functionality in this controller for brevity, in most cases you’d have a separate factory to handle posting the data&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With the controller in place, the mark-up might look like this (and will display the file names of all of the files selected):&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 200px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ng-controller&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Ctrl"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;file-upload&lt;/span&gt; &lt;span style="color: #ff0000"&gt;multiple&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt; &lt;span style="color: #ff0000"&gt;ng-repeat&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file in files"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;{{file.name}}&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The controller code below contains some important comments relating to how the data gets posted up to the server, namely the ‘Content-Type’ header as the value that needs to be set is a bit quirky. &lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 1000px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; Ctrl($scope, $http) {&lt;br&gt;&lt;br&gt;    &lt;span style="color: #008000"&gt;//a simple model to bind to and send to the server&lt;/span&gt;&lt;br&gt;    $scope.model = {&lt;br&gt;        name: &lt;span style="color: #006080"&gt;""&lt;/span&gt;,&lt;br&gt;        comments: &lt;span style="color: #006080"&gt;""&lt;/span&gt;&lt;br&gt;    };&lt;br&gt;&lt;br&gt;    &lt;span style="color: #008000"&gt;//an array of files selected&lt;/span&gt;&lt;br&gt;    $scope.files = [];&lt;br&gt;&lt;br&gt;    &lt;span style="color: #008000"&gt;//listen for the file selected event&lt;/span&gt;&lt;br&gt;    $scope.$on(&lt;span style="color: #006080"&gt;"fileSelected"&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;event&lt;/span&gt;, args) {&lt;br&gt;        $scope.$apply(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {            &lt;br&gt;            &lt;span style="color: #008000"&gt;//add the file object to the scope's files collection&lt;/span&gt;&lt;br&gt;            $scope.files.push(args.file);&lt;br&gt;        });&lt;br&gt;    });&lt;br&gt;    &lt;br&gt;    &lt;span style="color: #008000"&gt;//the save method&lt;/span&gt;&lt;br&gt;    $scope.save = &lt;span style="color: #0000ff"&gt;function&lt;/span&gt;() {&lt;br&gt;        $http({&lt;br&gt;            method: &lt;span style="color: #006080"&gt;'POST'&lt;/span&gt;,&lt;br&gt;            url: &lt;span style="color: #006080"&gt;"/Api/PostStuff"&lt;/span&gt;,&lt;br&gt;            &lt;span style="color: #008000"&gt;//IMPORTANT!!! You might think this should be set to 'multipart/form-data' &lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// but this is not true because when we are sending up files the request &lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// needs to include a 'boundary' parameter which identifies the boundary &lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// name between parts in this multi-part request and setting the Content-type &lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// manually will not set this boundary parameter. For whatever reason, &lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// setting the Content-type to 'false' will force the request to automatically&lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// populate the headers properly including the boundary parameter.&lt;/span&gt;&lt;br&gt;            headers: { &lt;span style="color: #006080"&gt;'Content-Type'&lt;/span&gt;: &lt;span style="color: #0000ff"&gt;false&lt;/span&gt; },&lt;br&gt;            &lt;span style="color: #008000"&gt;//This method will allow us to change how the data is sent up to the server&lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// for which we'll need to encapsulate the model data in 'FormData'&lt;/span&gt;&lt;br&gt;            transformRequest: &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (data) {&lt;br&gt;                &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; formData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FormData();&lt;br&gt;                &lt;span style="color: #008000"&gt;//need to convert our json object to a string version of json otherwise&lt;/span&gt;&lt;br&gt;                &lt;span style="color: #008000"&gt;// the browser will do a 'toString()' on the object which will result &lt;/span&gt;&lt;br&gt;                &lt;span style="color: #008000"&gt;// in the value '[Object object]' on the server.&lt;/span&gt;&lt;br&gt;                formData.append(&lt;span style="color: #006080"&gt;"model"&lt;/span&gt;, angular.toJson(data.model));&lt;br&gt;                &lt;span style="color: #008000"&gt;//now add all of the assigned files&lt;/span&gt;&lt;br&gt;                &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; i = 0; i &amp;lt; data.files; i++) {&lt;br&gt;                    &lt;span style="color: #008000"&gt;//add each file to the form data and iteratively name them&lt;/span&gt;&lt;br&gt;                    formData.append(&lt;span style="color: #006080"&gt;"file"&lt;/span&gt; + i, data.files[i]);&lt;br&gt;                }&lt;br&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; formData;&lt;br&gt;            },&lt;br&gt;            &lt;span style="color: #008000"&gt;//Create an object that contains the model and files which will be transformed&lt;/span&gt;&lt;br&gt;            &lt;span style="color: #008000"&gt;// in the above transformRequest method&lt;/span&gt;&lt;br&gt;            data: { model: $scope.model, files: $scope.files }&lt;br&gt;        }).&lt;br&gt;        success(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (data, status, headers, config) {&lt;br&gt;            alert(&lt;span style="color: #006080"&gt;"success!"&lt;/span&gt;);&lt;br&gt;        }).&lt;br&gt;        error(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (data, status, headers, config) {&lt;br&gt;            alert(&lt;span style="color: #006080"&gt;"failed!"&lt;/span&gt;);&lt;br&gt;        });&lt;br&gt;    };&lt;br&gt;};&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;h2&gt;Handling the data server-side&lt;/h2&gt;
&lt;p&gt;This example shows how to handle the data on the server side using ASP.Net WebAPI, I’m sure it’s reasonably easy to do on other server-side platforms too.&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; border-top: silver 1px solid; font-family: 'Courier New', courier, monospace; border-right: silver 1px solid; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; margin: 20px 0px 10px; border-left: silver 1px solid; line-height: 12pt; padding-right: 4px; max-height: 500px; width: 97.5%; background-color: #f4f4f4"&gt;&lt;pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: 'Courier New', courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"&gt;&lt;p&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; async Task&amp;lt;HttpResponseMessage&amp;gt; PostStuff()&lt;br&gt;{&lt;br&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!Request.Content.IsMimeMultipartContent())&lt;br&gt;    {&lt;br&gt;        &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpResponseException(HttpStatusCode.UnsupportedMediaType);&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    var root = HttpContext.Current.Server.MapPath(&lt;span style="color: #006080"&gt;"~/App_Data/Temp/FileUploads"&lt;/span&gt;);&lt;br&gt;    Directory.CreateDirectory(root);&lt;br&gt;    var provider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MultipartFormDataStreamProvider(root);&lt;br&gt;    var result = await Request.Content.ReadAsMultipartAsync(provider);&lt;br&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (result.FormData[&lt;span style="color: #006080"&gt;"model"&lt;/span&gt;] == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br&gt;    {&lt;br&gt;        &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpResponseException(HttpStatusCode.BadRequest);&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    var model = result.FormData[&lt;span style="color: #006080"&gt;"model"&lt;/span&gt;];&lt;br&gt;    &lt;span style="color: #008000"&gt;//TODO: Do something with the json model which is currently a string&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #008000"&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;    &lt;span style="color: #008000"&gt;//get the files&lt;/span&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var file &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; result.FileData)&lt;br&gt;    {                &lt;br&gt;        &lt;span style="color: #008000"&gt;//TODO: Do something with each uploaded file&lt;/span&gt;&lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Request.CreateResponse(HttpStatusCode.OK, &lt;span style="color: #006080"&gt;"success!"&lt;/span&gt;);&lt;br&gt;}&lt;/p&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
  </channel>
</rss>