Automatically convert percentage input values
Several of the form fields in an application I am building using CakePHP collect percentages for their values. I would like the users to be to see and edit percentages in the familiar percentage (24.5%) format, but I want to store it in decimal (.245) format in order to ease calculation logic. Since there's several of these fields, I'd rather not have to write the conversion logic into the controllers for every single percentage field.
Is anyone aware of a simple solution to automatically performing this conversion, or am I stuck writing a custom helper/behavior to solve this problem?
Solution
I ended up writing a jQuery plugin that handles this. Here it is, for anyone who might need it in the future:
/**
* Input Percent
*
* Percentages are tricky to input because users like seeing them as 24.5%, but
* when using them in calculation their value is actually .245. This plugin
* takes a supplied field and automatically creates a percentage input.
*
* It works by taking an input element and creating a hidden input with the same
* name immediat开发者_Go百科ely following it in the DOM. This has the effect of submitting
* the proper value instead of the human only one. An onchange method is then
* bound to the original input in order to keep the two synced.
*
* Potential Caveats:
* * There will be two inputs with the same name. Make sure anything you
* script against this field is prepared to handle that.
*
* @author Brad Koch <kochb@aedisit.com>
*/
(function($) {
$.fn.inputPercent = function() {
return this.each(function() {
var display_field = this;
var value_field = $('<input type="hidden" />').get(0);
// Initialize and attach the hidden input.
$(value_field).attr('name', $(this).attr('name'));
$(value_field).val($(display_field).val());
$(display_field).after(value_field);
$(display_field).after('%');
// Convert the display field's proper percent value into the display format.
if (isFinite($(display_field).val())) {
$(display_field).val($(display_field).val() * 100);
}
// Enable synchronization between the two.
$(this).bind('change', function () {
var value = $(display_field).val();
// Handle non-numeric values.
if (isFinite(value)) {
$(value_field).val(value / 100);
} else {
$(value_field).val(value);
}
});
});
};
})(jQuery);
Usage:
$('input.percent').inputPercent();
You could write some simple javascript (use whatever your favourite framework is, or plain js) to convert fields with a class of #percentage just before submit.
Alternatively, and also dealing with users without javascript; in the model, add the beforeSave() method, check if the number is < 1 or not and if not, divide by 100.
You could also add a simple component or helper to convert the internal number back to a percentage for display, if NumberHelper can't help.
There is already a helper for this - the NumberHelper
http://book.cakephp.org/view/1455/toPercentage
The only drawback that I have found is that if you store your data as a decimal representation of a percentage (ie .045 = 4.5%) instead of as the actual percentage (ie .045 = .045%) then you will have to multiply by 100 before converting.
ie:
<?php echo $this->Number->toPercentage( 51.5 ); // 51.5% ?>
<?php echo $this->Number->toPercentage( .245 * 100 ); // 24.5% ?>
I recently wrote a plugin to convert from and to json to store in the DB. https://github.com/dereuromark/tools/blob/master/models/behaviors/jsonable.php
you could easily modify it to convert from and to percentage. you need some custom
afterFind
and
beforeSave
to do so.
then attach it to your model like so:
$actsAs = array('Percentage');
精彩评论