All posts in ‘Code’

Format and un-format money/currency in JavaScript

Here’s a couple of simple JavaScript money-formattin’ snippets I use all the time where currencies are handled.

The code in this post has been expanded into accounting.js, a tiny JS library with some handy methods for number, money and currency formatting. Check it out!

The first is a function to format money/currency in JavaScript, turning an integer or float into a formatted string (with customisable decimal precision, currency symbol, decimal- and thousands-separators).

The second is a regular expression that removes currency formatting, so that parseInt / parseFloat can be used to extract the value from a currency-formatted string.

JavaScript Money Format

This extends the native Number object, so that all new numbers (integers/floats) can have the moneyformat() method called on them. If you prefer not to extend JavaScript’s native Number object for any reason, this also works fine as a standalone function or a library method (examples below.)

// Extend the default Number object with a formatMoney() method:
// usage: someVar.formatMoney(decimalPlaces, symbol, thousandsSeparator, decimalSeparator)
// defaults: (2, "$", ",", ".")
Number.prototype.formatMoney = function(places, symbol, thousand, decimal) {
	places = !isNaN(places = Math.abs(places)) ? places : 2;
	symbol = symbol !== undefined ? symbol : "$";
	thousand = thousand || ",";
	decimal = decimal || ".";
	var number = this,
	    negative = number < 0 ? "-" : "",
	    i = parseInt(number = Math.abs(+number || 0).toFixed(places), 10) + "",
	    j = (j = i.length) > 3 ? j % 3 : 0;
	return symbol + negative + (j ? i.substr(0, j) + thousand : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousand) + (places ? decimal + Math.abs(number - i).toFixed(places).slice(2) : "");
};

NB: minified version below.

Some JS currency-formatting examples:

// Default usage and custom precision/symbol :
var revenue = 12345678;
console.log(revenue.formatMoney()); // $12,345,678.00
console.log(revenue.formatMoney(0, "HK$ ")); // HK$ 12,345,678

// European formatting:
var price = 4999.99;
console.log(price.formatMoney(2, "€", ".", ",")); // €4.999,99

// It works for negative values, too:
console.log( (-500000).formatMoney(0, "£ ") ); // £ -500,000

Currency to number – removing money formatting:

Say you have a currency-formatted string, eg. "HK$ -100,000.50" and you want to get the value from that, removing all currency formatting and thousand-separators. Default methods won’t get you very far: parseInt and parseFloat both return NaN (“not a number”, as the string had non-numeric characters in it.)

No problemo. A simple regex will take care of this:

var price = (12345.99).formatMoney(); // "$12,345.99"

// Remove non-numeric chars (except decimal point/minus sign):
priceVal = parseFloat(price.replace(/[^0-9-.]/g, '')); // 12345.99

NB: This only works where the decimal separator is a point (.) – if the separator is a comma (,), put a comma in the regex instead of a point, eg: /[^0-9-,]/g

Hope somebody finds this useful!

Non-Number.prototype version:

// To set it up as a global function:
function formatMoney(number, places, symbol, thousand, decimal) {
	number = number || 0;
	places = !isNaN(places = Math.abs(places)) ? places : 2;
	symbol = symbol !== undefined ? symbol : "$";
	thousand = thousand || ",";
	decimal = decimal || ".";
	var negative = number < 0 ? "-" : "",
	    i = parseInt(number = Math.abs(+number || 0).toFixed(places), 10) + "",
	    j = (j = i.length) > 3 ? j % 3 : 0;
	return symbol + negative + (j ? i.substr(0, j) + thousand : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousand) + (places ? decimal + Math.abs(number - i).toFixed(places).slice(2) : "");
}

// To create it as a library method:
myLibrary.formatMoney = function(number, places, symbol, thousand, decimal) {
	/* as above */
}

// Example usage:
formatMoney(54321); // $54,321
myLibrary.formatMoney(12345, 0, "£ "); // £ 12,345

Minified version of prototype method

Number.prototype.formatMoney=function(d,g,h,a){d=!isNaN(d=Math.abs(d))?d:2;g=g!==undefined?g:"$";h=h||",";a=a||".";var f=this,c=f<0?"-":"",e=parseInt(f=Math.abs(+f||0).toFixed(d),10)+"",b=(b=e.length)>3?b%3:0;return g+c+(b?e.substr(0,b)+h:"")+e.substr(b).replace(/(\d{3})(?=\d)/g,"$1"+h)+(d?a+Math.abs(f-e).toFixed(d).slice(2):"");};

Have any improvements, or spot any bugs? Comments appreciated!

Use jQuery.animate() to increment / decrement numeric text or an element’s value

Cool trick I learnt recently: jQuery.animate() is not just for doing cool effects – you can animate values, and text in the DOM, too (still a cool effect, I think). Demo below.

Instead of calling animate() on a standard jQuery DOM object, to animate the element:

$('#element').animate({width:100}, ... )

You can also call the method on a hash object, to animate all of the object’s properties:

$({someProperty: 0}).animate({someProperty: 123}, ... )

This works by animating the values in the object from their initial state, which you passed into jQuery(), to their finished state (the first parameter to .animate()).

Animating a DOM object’s text value with jQuery:

This code animates a value from 0 to 110 (with “swing” easing and 1 second duration) and uses a custom step function to update the DOM element with the value, on each ‘step’ of the ‘animation’. Click the link below to run it.

// Animate the element's value from 0% to 110%:
jQuery({someValue: 0}).animate({someValue: 110}, {
	duration: 1000,
	easing:'swing', // can be anything
	step: function() { // called on every step
		// Update the element's text with rounded-up value:
		$('#el').text(Math.ceil(this.someValue) + "%");
	}
});

Try it out!

Click the link to change the value: Do it!

Amount of fun: 0%

The Loneliest WordPress Plugin

Saw this on a friend’s site recently. He’d installed every plugin under the sun (the site was a bit of a mess). Among the dozen or so other plugin activation/error notices that crowded out every admin screen, I caught this masterpiece of a guilt-trip error message:

The “Add Link To Facebook” plugin’s author seems to be feeling a little insecure. It’s bad enough that there’s a notification telling you that the only way to remove this notification (from EVERY admin screen!) is to tick the “I have rated this plugin, most glorious plugin-developer overlord” checkbox in the settings page. Not only that, but it needed to be in an error message format?

Filed under the “not-to-do” checklist of WordPress plugin development, I think.

WordPress – How to exclude post formats (aside, status, etc) from RSS / Feeds

If you’re using the WordPress 3.1 Post Formats feature to publish formatted content (like ‘aside’, ‘status’, ‘chat’, ‘quote’, etc.), it’s likely that you’ll want to exclude certain post formats from your RSS feed so as not to clutter up peoples viewers with random crap.

For me, that means removing status posts – short-form updates, under 140 characters (often cross-posted from Twitter) and aside posts – random thoughts or short paragraphs, without title (or intellectual value, usually.)

tl;dr: Here’s how to exclude certain post formats from WordPress’s RSS feed:

1. Open up your theme’s functions.php file and insert the following code (in case you’re not 100% up on PHP, just make sure it’s inside <?php   ?> tags or your site will break.)

// Hide post formats from WordPress generated RSS feeds:
function exclude_post_formats_from_feeds( &$wp_query ) {

	// Only do this for feed queries:
	if ( $wp_query->is_feed() ) {

		// Array of post formats to exclude, by slug,
		// e.g. "post-format-{format}"
		$post_formats_to_exclude = array(
			'post-format-status',
			'post-format-aside'
		);

		// Extra query to hack onto the $wp_query object:
		$extra_tax_query = array(
			'taxonomy' => 'post_format',
			'field' => 'slug',
			'terms' => $post_formats_to_exclude,
			'operator' => 'NOT IN'
		);

		$tax_query = $wp_query->get( 'tax_query' );
		if ( is_array( $tax_query ) ) {
			$tax_query = $tax_query + $extra_tax_query;
		} else {
			$tax_query = array( $extra_tax_query );
		}
		$wp_query->set( 'tax_query', $tax_query );
	}
}

// Call the above hook function before every WordPress query:
add_action( 'pre_get_posts', 'exclude_post_formats_from_feeds' );

2. Edit the array of post formats to exclude. In the example, I’ve excluded ‘status’ and ‘aside’ formats, but you can do any (in the format post–format–{aside/gallery/link/image/quote/status/video/audio/chat}.

The above code is fairly self-explanatory – it is fired on every WordPress request, but only activates if it’s a feed, and removes the formats you supplied (in this case, ‘status’ and ‘aside’ will be excluded).

In any case, comment below if you need any advice or help. Good luck!

Based on wordpress.stackexchange.com/questions/18412/how-to-exclude…

Rainbow Text Highlighting with CSS and Lettering.js

Just a fun little thing I threw together last night – text that highlights in rainbow colours when you select it. Check it out!
Rainbow Text Highlighting with CSS and Lettering.js

Rainbow Text Highlighting Demo

While I was doing it I made some changes to lettering.js, to allow repetitive numbering of <span>s (eg. 1,2,3,1,2,3), which I’ll submit as a pull request in case anybody else thinks it’d be useful.

Sample text courtesy of Vegan Ipsum.

Functional Parameters – a neat JavaScript Design Pattern

If your JavaScript application / library / plugin has default and settable parameters or options, for example a url or a color, and your code expects a string, what happens if the user (the developer) wants to pass in a function that returns a string, instead?

The url / url() parameter in Backbone.js

‘Collections’ in Backbone.js have a url parameter, from where the data is fetched. It can either be a string, or a function that returns a string.

In Backbone, when defining your collection, all of these are valid:

url: "http://www.example.com/ajax/" // a string
...
url: app.pileOfAwesome // a function
...
url: function() {
	return app.someValue ? "static.php" : app.buildQuery();
}

In the first example, the object’s URL is defined as a string, whereas in the second and third, the URL is a function that returns a string.

Backbone’s source code uses Underscore.js‘s _.isFunction() to test whether the URL was a string or a dynamic function, and thus returns either object.url or object.url():

var getUrl = function(object) {
	if (!(object && object.url)) return null;
	return _.isFunction(object.url) ? object.url() : object.url;
};

This is different from many other libraries and plugins, which (given the above example) would always expect the url parameter to be a string, and will fail if a function is given. #1

It strikes me that it doesn’t take too much extra work to allow functional parameters (that may not be the correct terminology, but it’s what I’ve taken to calling it) – so let’s look at an example, using the perennial favourite, an imaginary jQuery plugin. #2

Functional Parameters in jQuery Plugins

This could also apply to jQuery plugins, which often feature a defaults or options object that’s passed in like so:

// The plugin call:
$('#element').reportify({
	person: "primeMinister",
	warningLevel : "mauve"
});

// Inside the plugin:
reportify.defaults = {
	person: "",
	warningLevel : "whiteSmoke"
}

What happens if I want to call this plugin and pass in a function that returns the current status of an external module, which may change without notice?

$('#element').reportify({
	person: someModule.getNextInCommand, // a function
	warningLevel : anotherModule.alertLevel // a function
});

The example reasoning behind this could be that, every time the plugin fires its internal flashyLight() method, it should use the return value of someModule.getNextInCommand(), which changes regulary.

For most plugins (and libraries, for that matter) I would need to re-instantiate/initialise the plugin/library each and every time the value of someModule.getNextInCommand() changes. Nightmare!

Again, probably not the best example, but how hard would it have been for the author of the Reportify plugin to make a simple check, like the Backbone example above, to find out whether the parameters were functions (in which case, execute them) or plain strings?

I think the code from Backbone.js above demonstrates that it’s pretty trivial to implement in most cases. I’m definitely going to go back through lots of my code and try to implement it wherever it would be useful.

One example

edit: Just occurred to me that some sample code might come in handy to wrap this up. Here’s a small example, from the comments below, that demonstrates how a plugin might implement this:

// Get the url option, from either function or string:
var urlString = (typeof options.url === "function") ? options.url() : options.url;

# 1 There are probably certain cases where this makes more sense than others (URL parameters are a great example) so it may not be necessary to implement for every parameter, but it’s a good thing to keep in mind.

# 2 I originally had the imaginary jQuery plugin name as Alertify but, true to web-2.0-naming-convention-form, that’s actually already a plugin. Go figure.

Sometimes you need to manually clear WordPress’s rewrite rules in MySQL / PHPMyAdmin

Recently while setting up a WordPress site on a Cherokee server (no Apache/mod_rewrite), I made a little miscalculation (ahem) which resulted in the permalink structure being changed to something inaccessible, thus preventing us from being able to access the site whatsoever.

The wp-admin backend was also inaccessible because we are using a custom static login page, so access to the /wp-admin/ directory was routed to a static /login/ page (which, because of the fudged permalink rules, was unavailable. Huh?

(Long story short – servers without mod_rewrite need the start of the permalink structure to be eg. /index.php/%year%/%postname%/)

Naturally, I jumped into PHPMyAdmin to inspect the site’s options, and changed the permalink_structure in the wp_options table manually.

This won’t fix the problem if you’re unable to access the backend, though, as WordPress caches its rewrite rules until something changes in the site that would effect a permalinks flush (or until the permalinks page is visited). The cached rewrite rules will ignore the updated permalink structure, so you’re still screwed.

Solution: Manually flush WordPress’s rewrite rules with PHPMyAdmin

Find the rewrite_rules option key in the wp_options table, hit edit, and delete everything in there. Then save it. This will force WordPress to rebuild it when you try to access anything. Fixed!

This is admittedly a pretty obscure problem, but I hope it helps somebody someday.