точка и запятая

WMix

герр M:)ller
Партнер клуба
очень часто возникает задача считать цифорки и достатачно часто эти цифорки являются дробными числами.
так уж повелось что англичане разделяют целую часть от дробной точкой, а русские да и множество других "расс" запятой...

задача в полях разрешить писать запятые, но задача не только сменить после почты эти запятые на точки или из точек сделать запятые во время создания формы, но и активно использовать значения на уровне яваскрипт...

и вот тут начинается геморой... насчитано минимум 4 места...

могу представить себе некую функцию на яваскрипт типо гет и сет которые меняют эти значения на правильные

могу представить также скрытые переменные, которые меняют каждый свое поле после изменения и содержат дробные значения в оригинале..

а как это делает сообщество?
 

AmdY

Пью пиво
Команда форума
зачем точку менять на клиенте, если можно на сервере. обычно формы делают так, что они поддерживают валидацию и фильтрацию входных данных.
 

WMix

герр M:)ller
Партнер клуба
представь что при изменении onkeyup мне нужно в зависимости от введенного значения пересчитать другое поле, которое также содержит запятую...
пример, ввели цену продажи, нужно посчитать ндс уже на клиенте при вводе... получается при считывании полей в javascript нужно продажа.replace(/,/,'.') далее умножить разделить и далее ндс.replace(/\./,',') при записи в поле... и после в php нужно сделать тоже самое... ну куда уже не хуже?
 

fixxxer

К.О.
Партнер клуба
Если у тебя нормальный код на нормальном фреймворке - то добавляешь в форму фильтр, и готово.
Если лапша с $_POST ручками, могу посоветовать начать использовать фреймворки.

На js тебе в любом случае дергать parseFloat, ну дернешь вместо него intlParseFloat со своим реплейсом, че.
 

fixxxer

К.О.
Партнер клуба
Немного оффтоп.
Хотел сначала посоветовать использовать локали (вроде как LC_NUMERIC для тех же целей). Мне это всегда только мешало, и у меня везде безусловно выставляется setlocale(LC_NUMERIC, 'C'), но подумалось - вроде тут самое то. Решил проверить. Нахожусь в удивлении.

Код:
> php -r 'setlocale("LC_ALL", "ru_RU.UTF-8"); var_dump(floatval("3.14"), floatval("3,14"), strval(3.14));'
float(3,14)
float(3)
string(4) "3,14"
WUT?

Может, я что-то не понимаю? А если так...
Код:
> php -r 'setlocale("LC_ALL", "ru_RU.UTF-8"); var_dump(floatval(strval(3.14)));'
float(3)
WUT???

Гуглю, нахожу:
if ((lc.decimal_point)[0] != '.') {
/* set locale back to C */
setlocale(LC_NUMERIC, "C");
}
Это прекрасно.
[2012-06-22 11:05 UTC] schindler dot andor at empo dot deletethis dot hu
Yes, this is not a bug. This is a huge epic fail. This is a great example, why people hate PHP.
 

WMix

герр M:)ller
Партнер клуба
fixxxer
и это тоже по теме, заодно про баги просветимся (фиг бы с этими разделителями тысяч, продавец сотнями считает), тут получается и на клиенте и на сервере менять переменные,...

задача такая

как бы закрутить так, чтоб сервер генерил правильный гетер и сетер для явыскрипт....

вообще я представляю себе нереальный CSS который форматирует число в зависимости от LOCALE...
почему все так плохо?
 

WMix

герр M:)ller
Партнер клуба
fixxxer
AmdY
я так понимаю, вы тоже напишете
в яваскрипт на каждый onkeyup по replace(/,/,'.') и по replace(/\./,',')
а в пхп при _POST str_replace(',','.' $_POST['var']) хоть это у вас фильтр завется, а при рендинге формы str_replace('.',',' $var) дабы не пугать пользователей
 

fixxxer

К.О.
Партнер клуба
нет

лично я в php напишу что-то вроде
PHP:
class FloatIntlFilter implements FilterInterface {

     protected $dec_separator;

     public function __construct($dec_separator = ',') {
         $this->dec_separator = $dec_separator;
     }

     public function filter(&$value) {
         return floatval(strtr($value, $this->dec_separator, '.'))
     }

}
...

Form::construct()
...
    ->addFilters(array(
        'fieldName' => new FloatIntlFilter
    ))
в js, недолго думая, напишу
Код:
function parseFloatIntl(str) {
    return parseFloat(str.replace(',', '.'));
}
а в шаблоне буду просто использовать http://twig.sensiolabs.org/doc/filters/number_format.html
 

Redjik

Джедай-мастер
fixxxer
ага, так же делаю...
локали ничего кроме батхерта не вызывали у меня...
особенно если вдруг на сервере не стоит русская локаль, а ты уже час трахаешься с ней и не можешь понять - почему не работает =)))
 

fixxxer

К.О.
Партнер клуба
А хз, где оно, но вот это поведение

php -r 'setlocale("LC_ALL", "ru_RU.UTF-8"); var_dump(floatval(strval(3.14)));'
float(3)

у меня везде воспроизводится, где локаль вообще есть. Правда, 5.4 под рукой нет.
 

WMix

герр M:)ller
Партнер клуба
придумал такую штуку... осталось все скрутить вместе на php
PHP:
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
		<script src="http://jshashtable.googlecode.com/files/jshashtable-2.1.js"></script>
		<script src="http://jquery-numberformatter.googlecode.com/files/jquery.numberformatter-1.2.3.min.js"></script>
	</head>
	<body>

		<h1>Example</h1>
		<form>
			<label for="netto">Нетто:</label>
			<input class="decimal" name="netto" id="netto" value="100,00" />

			<label for="tax">Ндс:</label>
			<input class="decimal" name="tax" id="tax" value="18,00" />

			<label for="brutto">Брутто:</label>
			<input class="decimal" name="brutto" id="brutto" value="118,00" />
		</form>

	</body>
</html>
PHP:
$(window).load(function () {
	var page_locale = "ru"; // генерится на PHP
	// перепишем $().val()
	(function ($) {
		var originalVal = this.originalVal = $.fn.val;
		$.fn.val = function(value) {
			if (typeof value == 'undefined') {
				value = originalVal.call(this);
				if( $(this).hasClass('decimal') ){
					value = $.parseNumber(value, {format:"#.00", locale:page_locale});
				}
				return value;
			}
			else {
				if( $(this).hasClass('decimal') ){
					value = $.formatNumber(value, {format:"#.00", locale:page_locale});
				}
				return originalVal.call(this, value);
			}
		};
	})(jQuery);

	// пробуем с этим работать
	//  netto  - 100%
	//  tax    -  18%
	//  brutto - 118%

	$('#netto').keyup( function(){
		var netto = $(this).val();
		$('#tax').val( netto * 0.18 );
		$('#brutto').val( netto * 1.18 );
	});

	$('#brutto').keyup( function(){
		$('#tax').val( $(this).val() * 18/118 );
		$('#netto').val( $(this).val() * 100/118 );
	});

});
 

WMix

герр M:)ller
Партнер клуба
вот еще красивое решение

if you extend String object like this..

PHP:
String.prototype.float = function() { 
  return parseFloat(this.replace(',', '.')); 
}
.. you can run it like this

PHP:
"554,20".float()
> 554.20
 
Сверху