Jump to content
  • 0

Ввод по маске


Great Rash
 Share

Question

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

Задача:

Организовать ввод суммы денег. Тысячи должны отделяться пробелом.

Выглядеть это должно так:

999

9 999

99 999

999 999

9 999 999

и т.п.

Вот тут я застрял. Подскажите идею, алгоритм или просто с чего начать.

Link to comment
Share on other sites

11 answers to this question

Recommended Posts

  • 0

:)

Я уже ваш скрипт пытался изучить. По запросу "javascript ввод по маске" гугль выдает его на первых позициях.

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

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

UPD: В идеале, если вас не затруднит конечно, неплохо было бы увидеть этот код с комментариями (про человеческие имена переменных я и не надеюсь).

Edited by Great Rash
Link to comment
Share on other sites

  • 0

Родилась у меня одна идея.

При автозамене 9999 на 9 999 нужно добавлять лишний пробел, в скрипте потом нужно всегда учитывать его, чтобы не было лишнего удаления или при изменении цифры в середине. Это лишний код, малопонятный к тому-же будет, и с огромным потенциалом к будущим ошибкам.

Есть вариант прикольнее. Делаем визуальный стиль, который будет создавать видимость поля ввода. В этот контейнер помещаем инпут на длинну всего 3х символов. При вводе четвертого - создаем еще одно поле ввода, и нужный символ переносим туда. Если удаляется последний символ в поле ввода - прибиваем инпут и фокус переносим в следующее поле. При удалении поля в середине, пересоздаем все поля наново.

Но и этот вариант не лишен проблем. Выделить все не получится, нужно делать эмуляцию.

Link to comment
Share on other sites

  • 0

Идея очень интересная, но слишком уж извратная. Плюс не понятно как отправлять эти данные на сервер. Вообще есть у меня уже код, который тоже не лишен проблем, а именно если я хочу отредактировать сумму где-то порсередине, то получаю кукиш. Может поможете решить эту проблему? Хотя я даже не знаю насколько нормален такой подход...

Код:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />

<script type="text/javascript">
MoneyInput = function() {};

MoneyInput.prototype.generateHTML = function(parent, hidId, hidName, value) {
var prnt = this;

// create temporary container to find out symbol width
this.temp = document.createElement('div');
this.temp.style.display = 'inline';
this.temp.innerHTML = '0';
document.body.appendChild(this.temp);
this.numWidth = this.temp.offsetWidth;
this.temp.innerHTML = ' ';
this.spaceWidth = this.temp.offsetWidth;
this.temp.parentNode.removeChild(this.temp);
this.temp = null;

// create main HTML
this.container = document.createElement('div');
this.container.className = 'money-cont';

if (parent != null) {
parent.appendChild(this.container);
} else {
document.body.appendChild(this.container);
}

this.hidden = document.createElement('input');
this.hidden.type = 'hidden';
this.hidden.id = hidId;
this.hidden.name = hidName;
this.container.appendChild(this.hidden);

this.rub = document.createElement('input');
this.rub.type = 'text';
this.rub.name = 'noname';
this.rub.maxLength = 19;
this.rub.value = '0';
this.rub.style.width = (this.numWidth * 15 + 2) + (this.spaceWidth * 4) + 'px';
this.rub.className = 'money-rub';
this.container.appendChild(this.rub);

this.container.appendChild(document.createTextNode('.'));

this.cop = document.createElement('input');
this.cop.type = 'text';
this.cop.name = 'noname';
this.cop.maxLength = 2;
this.cop.value = '00';
this.cop.style.width = this.numWidth * 2 + 2 + 'px';
this.cop.className = 'money-cop';
this.container.appendChild(this.cop);

if (value && value != '') {
this.hidden.value = value;
var valArr = value.split('.');

this.rub.value = valArr[0];
this.cop.value = valArr[1];
}

this.rub.onkeyup = function(e) {
e = e || window.event;
var key = e.which || e.keyCode;

if (key == 190 || key == 191 || key == 110 || key == 39) {
if (prnt.cop.setSelectionRange) {
prnt.cop.focus();
prnt.cop.setSelectionRange(0, 0);
} else if (prnt.cop.createTextRange) {
var range = prnt.cop.createTextRange();
range.collapse(true);
range.moveEnd('character', 0);
range.moveStart('character', 0);
range.select();
}
}

prnt.validateInput();
}

this.rub.onblur = function() {
if (this.value == '') {
this.value = '0';
}
}

this.rub.onchange = function() {
prnt.hidden.value = this.value + '.' + prnt.cop.value;
}

this.cop.onkeyup = function(e) {
e = e || window.event;
var key = e.which || e.keyCode;

if (key == 37) {
prnt.rub.focus();
}

if (prnt.getCaretPosition() == 0 && this.value != '') {
if (key == 97 || key == 49) {
this.value = 1;
} else if (key == 98 || key == 50) {
this.value = 2;
} else if (key == 99 || key == 51) {
this.value = 3;
} else if (key == 100 || key == 52) {
this.value = 4;
} else if (key == 101 || key == 53) {
this.value = 5;
} else if (key == 102 || key == 54) {
this.value = 6;
} else if (key == 103 || key == 55) {
this.value = 7;
} else if (key == 104 || key == 56) {
this.value = 8;
} else if (key == 105 || key == 57) {
this.value = 9;
} else if (key == 96 || key == 48) {
this.value = 0;
}
}

this.value = this.value.replace(/\D/g, '');
}

this.cop.onblur = function() {
if (this.value == '') {
this.value = '00';
}
}

this.cop.onfocus = function() {
if (this.value == '00') {
this.value = '';
}
}

this.cop.onchange = function() {
prnt.hidden.value = prnt.rub.value + '.' + this.value;

}
}

MoneyInput.prototype.validateInput = function() {
var leftPart = this.rub.value.replace(/\D/g, '');

if (leftPart.length == 4) {
var lastNum = leftPart.substr(leftPart.length - 3, leftPart.length);
var ost = leftPart.substr(0, leftPart.length - 3);

leftPart = ost + ' ' + lastNum;
} else if (leftPart.length > 4) {
var lastNum = '';
var ost = '';
var res = '';
var tmpStr = '';
var arr = leftPart.split(' ');

for (var i = 0; i < arr.length; i++) {
tmpStr += arr[i];
}

while (true) {
lastNum = tmpStr.substr(tmpStr.length - 3, tmpStr.length);
ost = tmpStr.substr(0, tmpStr.length - 3);
res = ' ' + lastNum + res;

if (ost.length >= 4) {
tmpStr = ost;
} else {
res = ost + res;
break;
}
}

leftPart = res;
}

while ( leftPart.length > 1 && leftPart.indexOf('0') == 0 ) {
leftPart = leftPart.substr( 1, leftPart.length);
}

this.rub.value = leftPart;
}

MoneyInput.prototype.getCaretPosition = function() {
var caretPos = 0;

if (document.selection) {
this.cop.focus();
var sel = document.selection.createRange();
sel.moveStart('character', -this.cop.value.length);
caretPos = sel.text.length;
} else if (this.cop.selectionStart || this.cop.selectionStart == '0') {
caretPos = this.cop.selectionStart;
}

return caretPos;
}

MoneyInput.prototype.addValueChangeListener = function(evt, func) {
if (document.addEventListener) {
this.hidden.addEventListener(evt, func, false);
} else if (document.attachEvent) {
this.hidden.attachEvent('on' + evt, func);
} else {
this.hidden['on' + evt] = func;
}
}

MoneyInput.prototype.addEventListener = function(evt, func) {
if (document.addEventListener) {
this.rub.addEventListener(evt, func, false);
this.cop.addEventListener(evt, func, false);
} else if (document.attachEvent) {
this.rub.attachEvent('on' + evt, func);
this.cop.attachEvent('on' + evt, func);
} else {
this.rub['on' + evt] = func;
this.cop['on' + evt] = func;
}
}
</script>
</head>

<body>

<script type="text/javascript">
var money = new MoneyInput();
money.generateHTML(null, 'test', 'test', '');
</script>

</body>
</html>

Edited by Great Rash
Link to comment
Share on other sites

  • 0
Идея очень интересная, но слишком уж извратная. Плюс не понятно как отправлять эти данные на сервер. Вообще есть у меня уже код, который тоже не лишен проблем, а именно если я хочу отредактировать сумму где-то порсередине, то получаю кукиш. Может поможете решить эту проблему? Хотя я даже не знаю насколько нормален такой подход...

Сразу скажу, подход менять. Мало того, что формируется HTML через DOM, так еще и отсутствует форма ввода с привычными функциями и поведением.

Link to comment
Share on other sites

  • 0

А чем плохо формировать HTML скриптом? Так я наоборот получаю больше контроля над элементом. Что значит "форма ввода с привычными функциями и поведением"? Что вы имеете в виду?

Link to comment
Share on other sites

  • 0
А чем плохо формировать HTML скриптом? Так я наоборот получаю больше контроля над элементом. Что значит "форма ввода с привычными функциями и поведением"? Что вы имеете в виду?

Да, вы получаете полный контроль. Ровно для одного случая. Как только вы захотите использовать код повторно, когда требования к структуре будут другими, вам придется переписывать этот код. Очень эффективно!

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

Link to comment
Share on other sites

  • 0
Форма ввода - инпут тайп текст. Имею в виду, что этот элемент имеет базовое поведение, которое понятно пользователю и программисту. Отправка формы, очистка формы, дефолтные значения, выделение всего текста, скроллируемое содержимое при вводе длинного текста и многое другое.

Это вы сейчас описали <textarea>. Текстареа не подходит по дизайну, никакого скролла быть не должно, плюс в ие у нее всегда виден (пусть и неактивный) скроллбар, что тоже не подходит.

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

Но вернемся к теме. Есть какие-нибудь идеи как справиться с позицией каретки? Я имею ввиду как запоминать позицию, не учитывая пробелы?

Упростил метод, вставляющий пробелы:

Mask.prototype.doReplace = function() {
var fieldText = this.input.value.replace(/\D/g, '');
var bufer = '';

if (fieldText.length > 3) {
while (fieldText.length > 3) {
var tail = fieldText.substr(fieldText.length - 3, fieldText.length);
fieldText = fieldText.substr(0, fieldText.length - 3);
bufer = ' ' + tail + bufer;
}
}

this.input.value = fieldText + bufer;
}

Все, разобрался с позицией каретки! :) Решение было до безобразия простым (правда доходил до него почти 2 дня, аж башка разламывается)! s0rr0w спасибо за помощь, надо серьезно подумать над вашими словами о гибкости кода.

Edited by Great Rash
Link to comment
Share on other sites

  • 0
Это вы сейчас описали <textarea>. Текстареа не подходит по дизайну, никакого скролла быть не должно, плюс в ие у нее всегда виден (пусть и неактивный) скроллбар, что тоже не подходит.

Нет, я описал <input type="text">

Нажмите на кнопку в любом инпуте и подержите секунд 5. Размер элемента остался тот же, но содержимое внутри скроллируется.

Все, разобрался с позицией каретки! :) Решение было до безобразия простым (правда доходил до него почти 2 дня, аж башка разламывается)! s0rr0w спасибо за помощь, надо серьезно подумать над вашими словами о гибкости кода.

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

Link to comment
Share on other sites

  • 0

не понимаю куда скроллируется? Вправо вы имеете ввиду? Вообще я задал ограничение в 17 символов из-за того, что навряд ли будут вводится бОльшие суммы. Или вы мне вообще не про то хотите сказать?

Link to comment
Share on other sites

  • 0
не понимаю куда скроллируется? Вправо вы имеете ввиду? Вообще я задал ограничение в 17 символов из-за того, что навряд ли будут вводится бОльшие суммы. Или вы мне вообще не про то хотите сказать?

Вправо, вправо :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy