Archive for category Javascript

Highcharts- Highlight the last clicked bar

This is handy, only really if you have charts which, on click, have drill down data which pops up, perhaps in a table underneath or something- I basically just wanted to highlight the last clicked column in a column chart;

Check it out on jsFiddle : http://jsfiddle.net/shawson/CkkbF/8/

2 Comments

Recursive jQuery Drop Down Menu’s

Following on from my previous post about drop downs, I recently expanded the code to allow for sub menus- as many levels deep as you would like.

The Code:

$(document).ready(function () { // Shawsons' Teeny-Tiny Recursive Drop Downs!
    $('.drop-down-menu>li>ul').hide().mouseleave(function () {
        $('.highlighted', this).removeClass('highlighted');
        $(this).hide();
    });
    $('.drop-down-menu li>a').mouseenter(function () {
        var menu_root = $(this).parent().parent();
        $('ul', menu_root).hide();
        $('.highlighted', menu_root).removeClass('highlighted');
        $('>ul', $(this).addClass('highlighted').parent()).show();
    }).mouseleave(function (o) {
        if ($(this).parent().has($(o.relatedTarget)).length < 1) {
            $('ul', $(this).parent()).hide();
        }
    });
});

The Markup:

<ul class="drop-down-menu">
        <li>Drop Down Menu - Demo Title : </li>
        <li><a href="">Menu 1</a>
            <ul>
                <li><a href="a.htm">a</a></li>
                <li><a href="b.htm">b</a></li>
                <li><a href="c.htm">c &raquo;</a>
                    <ul>
                        <li><a href="c-a.htm">c-a</a></li>
                        <li><a href="c-b.htm">c-b &raquo;</a>
                          <ul>
                              <li><a href="c-b-a.htm">c-b-a</a></li>
                              <li><a href="c-b-b.htm">c-b-b &raquo;</a>
                                  <ul>
                                      <li><a href="c-b-b-a.htm">c-b-b-a</a></li>
                                  </ul>
                              </li>
                          </ul>
                        </li>
                        <li><a href="c-c.htm">c-c</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li><a href="">Menu 2</a>
            <ul>
                <li><a href="d.htm">d</a></li>
                <li><a href="e.htm">e</a></li>
                <li><a href="f.htm">f</a></li>
            </ul>
        </li>
    </ul>

Some CSS:


.drop-down-menu { display:block; }
.drop-down-menu li { float:left; padding: 8px; }
.drop-down-menu>li>a { padding:8px; }
.drop-down-menu li ul
{
    position:absolute;
    background-color:#fff;
    border: 1px solid #999;
    border-radius: 0px 7px 7px 7px; -moz-border-radius:0px 7px 7px 7px; -webkit-border-radius:0px 7px 7px 7px;
    padding:5px;
    width: 50px;
}
.drop-down-menu li ul a {
   display:block;
   width:50px;
}
.drop-down-menu li ul li ul
{
    margin-left:50px;
    margin-top: -20px;
}
.drop-down-menu li ul li { float:none; }
.drop-down-menu li ul li a { color:#000; }
.drop-down-menu li ul a.highlighted { background-color:#F68833; }

Demo :

 

2 Comments

Adding cross browser consistent keyboard short-cuts to your website

I wanted to employ keyboard short cuts to a frequently used internal web app used within the company- Pinch o’ the proverbial piss I thought- I’ll just use access keys! I’ve used them before on front facing sites for accessibility- but when I actually came to document these keys for the users I realised that support across different browsers is a mess;

IE Alt + {key}then hit return
Firefox Alt + Shift + {key}
Chrome Alt + {key} (the most sensible implementation, in my opinion)

IE also seems to refuse to aknowlege the links unless they are currently visible, and as the options I was short cutting existed in drop down menus this was no good, as they existing in bulleted lists which are “display:none” until the user mouses-over the menu bar (using my tiny drop down menu code)!

So to get around this I wrote some jQuery which standardises the short cuts- note this is no good for normal accessibility uses as it’s a new key combo which none of the browsers use, so without documentation no one will know- but for my use on an internal system it’s perfect.

I took the decision to make all the short cuts Ctrl+Alt+{key}, and wanted to keep using the accesskey attribute on my links rather than introduce another mechanism for dictating which keys triggered what- I also wanted to ensure if the link had a javascript onclick handler, instead of navigating away, we respect the handler and simply trigger that. Here’s the code;

$(document).keydown(function(e) {
	if (e.ctrlKey && e.altKey && e.which >= 65 && e.which <= 122) {
		e.preventDefault();

		var key = String.fromCharCode(e.which);
		var the_link = $("a[accesskey=" + key.toLowerCase() + "]");

		if (typeof(the_link) != 'undefined') {
			// does this link have a javascript assigned click handler, or do we simply send the user to the links href value?
			var events = $.data( $(the_link).get(0), 'events' );
			if (typeof(events) != 'undefined') {
				if (typeof(events.click) != 'undefined') {
					$(the_link).click();
					return;
				}
			}
			window.location = $(the_link).attr('href');
		}
	}
});

1 Comment

Quick & Tiny jQuery Drop Down Menus

Note: this has been superseded by the recursive drop down menu script.

The Code:

$(document).ready(function () { // Shawsons' Teeny-Tiny Drop Downs!
    $('.drop-down-menu li ul').hide().mouseleave(function () {
        $(this).hide();
    });
    $('.drop-down-menu>li>a').mouseenter(function () {
        $('ul', $(this).parent().parent()).hide();
        $('ul', $(this).parent()).show();
    }).mouseleave(function (o) {
        if ($(this).parent().has($(o.relatedTarget)).length < 1) {
            $('ul', $(this).parent()).hide();
        }
    });
});

The Markup:

<ul class="drop-down-menu">
        <li>Available Actions : </li>
        <li><a href="">Menu 1</a>
            <ul>
                <li><a href="a.htm">a</a></li>
                <li><a href="b.htm">b</a></li>
                <li><a href="c.htm">c</a></li>
            </ul>
        </li>
        <li><a href="">Menu 2</a>
            <ul>
                <li><a href="d.htm">d</a></li>
                <li><a href="e.htm">e</a></li>
                <li><a href="f.htm">f</a></li>
            </ul>
        </li>
    </ul>

Some CSS:

.drop-down-menu { display:block; }
.drop-down-menu li { float:left; padding: 8px; }
.drop-down-menu li a { padding:8px; }
.drop-down-menu li ul
{
    position:absolute;
    background-color:#fff;
    border: 1px solid #999;
    border-radius: 0px 7px 7px 7px; -moz-border-radius:0px 7px 7px 7px; -webkit-border-radius:0px 7px 7px 7px;
    padding:5px;
}
.drop-down-menu li ul li { float:none; }
.drop-down-menu li ul li a { color:#000; }
.drop-down-menu li ul li:hover { background-color:#F68833; }

2 Comments

Grouped pagination links function in JavaScript

I just created a JavaScript port of an awesome bit of pagination code I first used years and years ago while working in Classic ASP, originally written by Dave Child who I was working with at the time. The original can be found on this site here.

It’s an awesome script when you have 100′s of pages of data (which probably suggests you need to implement some good filtering and search features to save your poor users..) and presents the links like so..

« Prev 1 2 3 … 7 [8] 9 … 208 209 210 Next »

function BuildGroupedPagination(current_page, total_pages, base_url, seperator)
{
	var url = base_url;
	var strPages = "";
	var intMaxPages = 0;
	var intMinPages = 0;
	var intPaginI = 0;

    if (typeof(seperator) == 'undefined')
    {
        seperator = " ";
    }

	if (total_pages > 10)
	{
		if (total_pages > 3)
		{
			intMaxPages = 3;
		}
		else
		{
			intMaxPages = total_pages;
		} 

		for (intPaginI = 1; intPaginI <= intMaxPages; intPaginI++)
		{

			if (intPaginI == current_page)
			{
				strPages += "<strong>[" + intPaginI + "]</strong>";
			}
			else
			{
				strPages += "<a href=\"" + url + intPaginI + "\">" + intPaginI + "</a>";
			} 

			if (intPaginI < intMaxPages)
			{
				strPages += seperator;
			}
		} 

		if (total_pages > 3)
		{
			if ((current_page > 1) && (current_page < total_pages))
			{
				if (current_page > 5)
				{
					strPages += " ... ";
				}
				else
				{
					strPages += seperator;
				} 

				if (current_page > 4)
				{
					intMinPages = current_page;
				}
				else
				{
					intMinPages = 5;
				} 

				if (current_page < total_pages - 4)
				{
					intMaxPages = current_page;
				}
				else
				{
					intMaxPages = total_pages - 4;
				} 

				for (intPaginI = intMinPages - 1 ; intPaginI <= intMaxPages + 1; intPaginI++)
				{
					if (intPaginI == current_page)
					{
						strPages += "<strong>[" + intPaginI + "]</strong>";
					}
					else
					{
						strPages += "<a href=\"" + url + intPaginI + "\">" + intPaginI + "</a>";
					}

					if (intPaginI < intMaxPages + 1)
					{
						strPages += seperator;
					}
				}

				if (current_page < total_pages - 4)
				{
					strPages += " ... ";
				}
				else
				{
					strPages += seperator;
				}
			}
			else
			{
				strPages += " ... ";
			} 

			for (intPaginI = total_pages - 2; intPaginI <= total_pages; intPaginI++) {
				if (intPaginI == current_page) {
					strPages += "<strong>[" + intPaginI + "]</strong>";
				}
				else {
					strPages += "<a href=\"" + url + intPaginI + "\">" + intPaginI + "</a>";
				} 

				if (intPaginI < total_pages) {
					strPages += seperator;
				}
			}
		}
	}
	else
	{
		for (intPaginI = 1; intPaginI <= total_pages; intPaginI++)
		{
			if (intPaginI == current_page)
			{
				strPages += "<strong>" + intPaginI + "</strong>";
			}
			else
			{
				strPages += "<a href=\"" + url + intPaginI + "\">" + intPaginI + "</a>";
			} 

			if (intPaginI < total_pages)
			{
				strPages += seperator;
			}
		}
	}
	return strPages;
}

3 Comments

jqZoomage jQuery component

I’ve built a simple jQuery plugin for use on a website I’m building and am in the process of submitting it to the jQuery plugins website. It’s a simple zoom panel, allowing your users to mouse over portions of your small image, to see a close up view. Ideal for use on product details page or similar.

Screenshot

Installation

Just add a reference to the script at the bottom of your page (where all your js should be anyway!)- as shown in the demo, this is a basic example;

$(window).ready(function() {
	$("#dinky-img").zoomage({
		zoomedImageContainer: "#big-img",
		zoomedImageUrl: "big-image.gif",
		stayActiveOnMouseOut: false,
		zoomedImageStartsCentered: true
	});
});

There are a couple of styles which are required for the view finder, and the mask which goes over the image (allowing you to customise the look)- add these rules to your style sheet somewhere;

#zoomage-view-finder { border: 1px solid #fff; }
.zoomage-view-finder-surround { background-color:#fff; opacity:0.7; }

As a general point, it’s best to run the script in a $(window).load() rather than the standard $(document).load(), as this ensures that all the images are loaded before the script begins, otherwise the script runs and grabs the width() and height() of the image to work out ratios, but these get returned as 0′s! More info on this can be found on the stack overflow issue about this

Configuration

zoomedImageContainer * Required *
Default Value : “#zoom-image-container”
This is the jQuery selector for the div which will act as the close up view for your image.

zoomedImageUrl * Required *
Default Value : “”
This is the URL of the zoomed image file. I generally use images 3 times larger than the original, however there isn’t a limit. The scale ratio is calculated on load.

stayActiveOnMouseOut
Default Value : false
If this is set to true, the view finder will continue to show in it’s last position even when the mouse pointer is moved off of the image. If false, the view finder will disappear on mouse out.

zoomedImageStartsCentered
Default Value : true
Indicates that, on load, the zoomed image view shows the center of the image.

centerOnMouseOut
Default Value : true
If true, on mouse out, the zoomed view will return to the center of the zoomed image.

Live Demo

You can check out a real life working version of it here!

Tested across all the major modern browsers (IE9/ FF4/ Chrome10)- give me a shout if you spot an issue.

Download

Current Version 1.2 – 2011-09-10
Unminified Development Version
Minified Production Version

Licence

This plugin is available for use under the MIT licence. For more info see http://codeblog.shawson.co.uk/storage/jquery.zoomage/licence.txt

jQuery Plugin Site Link

The official jQuery Plugin catalogue link for this plugin is http://plugins.jquery.com/project/jqZoomage

11 Comments

New Adobe HTML5 Animation tool “Edge”- free tech preview

A real nail in the coffin for Flash, as it’s own parents (Adobe) release a free tech demo version of Edge- A new editor that lets you make flash style animations– without Flash! Instead the animations are scripted using standards html5, JavaScript and CSS3. Having been hand coding stuff like this over the past year (for 8week game and the like) I’m interested to see what kind of code this tool actually spits out! Check it out herel; http://t.co/I46QFYm

3 Comments

Adding minification and obfuscation of your Javascript and CSS to your ASP.net build process using Yahoo YUI Compressor

I’ve just finished integrating Yahoo’s YUI Compressor into the MSBuild process for a new web probject I’m working on, and I thought I would document the process as there doesn;t seem to be a start to finish guide about anywhere.

To start with, let me just explain the structure I use for new Solutions;

C:\_Dev\MyNewWebsite\
C:\_Dev\MyNewWebsite\Artwork\
C:\_Dev\MyNewWebsite\BuildTools\
C:\_Dev\MyNewWebsite\Docs\
C:\_Dev\MyNewWebsite\Source\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.sln
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Controls\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Images\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Scripts\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Services\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Styles\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\MyNewWebsiteWeb.csproj
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\MyNewWebsiteEntities.csproj
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\
C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\MyNewWebsiteInterfaces.csproj
C:\_Dev\MyNewWebsite\ThirdParty\

Firstly, download the dot net port of the YUI compressor from codeplex. I then extracted this into a new folder in the BuildTools folder. (there should be 2 dll files and one txt licence file.)

I then created a new MSBuild file called build-minify.xml, in the MyNewWebsite.Web project folder. That file looks like this;

<?xml version="1.0" encoding="utf-8"?>
<!-- http://yuicompressor.codeplex.com/wikipage?title=Sample%20MSBuild.xml%20File&amp;amp;amp;amp;amp;ProjectName=yuicompressor -->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask
         TaskName="CompressorTask"
         AssemblyFile="..\..\BuildTools\Yahoo.Yui.Compressor-v1.5.0.0\Yahoo.Yui.Compressor.dll" />

  <ItemGroup>
    <CssFiles Include="$(SourceLocation)Styles\Fonts.css"/>
    <CssFiles Include="$(SourceLocation)Styles\Site.css"/>

    <CssIE Include="$(SourceLocation)Styles\IE.css"/>
    <CssIE6 Include="$(SourceLocation)Styles\IE6.css"/>

    <JsAll Include="$(SourceLocation)Scripts\jquery-1.6.1.min.js" />
    <JsAll Include="$(SourceLocation)Scripts\jquery-ui-1.8.14.custom.min.js" />
    <JsAll Include="$(SourceLocation)Scripts\json2.js" />
    <JsAll Include="$(SourceLocation)Scripts\jqModal-r14.js" />
    <JsAll Include="$(SourceLocation)Scripts\jquery.tipsy.js" />
    <JsAll Include="$(SourceLocation)Scripts\jquery.scrollTo-1.4.2.min.js" />
    <JsAll Include="$(SourceLocation)Scripts\jquery.localscroll-1.2.7.min.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-alert.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-validation.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-rollovers.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-custom-accordion.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-vehicle-lookup.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-sandbox.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-finance-calculator.js" />
    <JsAll Include="$(SourceLocation)Scripts\chinook-apply-now.js" />

  </ItemGroup>

  <Target Name="Minimize">
    <CompressorTask
              CssFiles="@(CssFiles)"
              DeleteCssFiles="false"
              CssOutputFile="Styles/Site.rel.css"
              CssCompressionType="YuiStockCompression"
              DisableOptimizations="Nope"
              EncodingType="Default"
              LineBreakPosition="-1"
              LoggingType="ALittleBit"
              ThreadCulture="en-gb"
              IsEvalIgnored="false"
            />

    <CompressorTask
              CssFiles="@(CssIE)"
              DeleteCssFiles="false"
              CssOutputFile="Styles/IE.rel.css"
              CssCompressionType="YuiStockCompression"
              DisableOptimizations="Nope"
              EncodingType="Default"
              LineBreakPosition="-1"
              LoggingType="ALittleBit"
              ThreadCulture="en-gb"
              IsEvalIgnored="false"
            />

    <CompressorTask
              CssFiles="@(CssIE6)"
              DeleteCssFiles="false"
              CssOutputFile="Styles/IE6.rel.css"
              CssCompressionType="YuiStockCompression"
              DisableOptimizations="Nope"
              EncodingType="Default"
              LineBreakPosition="-1"
              LoggingType="ALittleBit"
              ThreadCulture="en-gb"
              IsEvalIgnored="false"
            />

    <CompressorTask
      JavaScriptFiles="@(JsAll)"
      ObfuscateJavaScript="true"
      PreserveAllSemicolons="true"
      DisableOptimizations="false"
      EncodingType="Default"
      DeleteJavaScriptFiles="false"
      LineBreakPosition="-1"
      JavaScriptOutputFile="Scripts/chinook.rel.js"
      LoggingType="ALittleBit"
      ThreadCulture="en-gb"
      IsEvalIgnored="false"
		/>
  </Target>
</Project>

You can create whatever ItemGroups you’d like- then just create a compressor task for each. For a rundown of the settings, check out the link in the comment at the top of the XML there. In the above file I had decided to compress all of my Javascript into a single file called chinook.rel.js, and my fonts and site css file rolled into one file, keeping the ie6 css separate, but still minifying it down.

The next step is to add it to the normal build. I opened the solution in Visual Studio, right clicked my web project and selected properties. Go to “Build Events” and add the following post-build event;

$(MSBuildBinPath)\msbuild.exe  $(ProjectDir)build-minify.xml /target:Minimize

Now you can test it out by building your project. The new minified files are dumped out, in my case to the Scripts folder. Now that the files are there, I need a way of telling my release version of the website to use these instead of the raw, human-readable versions; but I still want to continue using the human-readable versions for development.

To achieve this I use pre-processor directives. These are most commonly seen in the c# code behind files, but can also be used in the aspx files. I added the following lines at the bottom of my master page;

    <% #if (!DEBUG) %>
    <script src="Scripts/chinook.rel.js" type="text/javascript"></script>
    <% #else %>
    <script src="Scripts/jquery-1.6.1.min.js" type="text/javascript"></script>
    <script src="Scripts/jqModal-r14.js" type="text/javascript"></script>
    <script src="Scripts/chinook-alert.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.14.custom.min.js" type="text/javascript"></script>
    <script src="Scripts/chinook-vehicle-lookup.js" type="text/javascript"></script>
    <script src="Scripts/chinook-sandbox.js" type="text/javascript"></script>
    <script src="Scripts/chinook-finance-calculator.js" type="text/javascript"></script>
    <script src="Scripts/jquery.scrollTo-1.4.2.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery.localscroll-1.2.7.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery.tipsy.js" type="text/javascript"></script>
    <script src="Scripts/json2.js" type="text/javascript"></script>
    <script src="Scripts/chinook-validation.js" type="text/javascript"></script>
    <script src="Scripts/chinook-apply-now.js" type="text/javascript"></script>
    <script src="Scripts/chinook-rollovers.js" type="text/javascript"></script>
    <script type="text/javascript" src="Scripts/chinook-custom-accordion.js"></script>
    <% #endif %>

So if the project is NOT running in debug mode, I import my full chinook.rel.js include which has everything already included, otherwise I manually include all the human readable, separate files.

And that’s pretty much it. Make sure you thoroughly retest your site with your combined java script file, as sometimes minification can cause issues with some code.

2 Comments

Front end web developer coding standards

Well put together, and generally good advice about the finer details of javascript (closures, truthy values) for someone starting out.

http://taitems.github.com/Front-End-Development-Guidelines/

No Comments

Adding Javascript Unit Testing/ Compression to your MSBuild

A couple of resources- I shall add to this post as I look into this myself.  I basically want to add steps to my project file, so msbuild will run javascript tests (qUnit) and perform minification/ combines all the js source files.

No Comments