Alexandr
Alexandr

Reputation: 65

ExtJS Two and more separators on numberfields

Tell me, please, how you can use two types of separator digital input field? You can use only one standard methods, but at a different keyboard layout, there is a need to use another, keeping the data in one format, that is the '.'

Input: 10,789 or 10.789 Save: 10.789

I use Ext.form.NumberField for editing integral field.

Part of my code:

var editor = new Ext.ux.grid.RowEditor({
    saveText: LANG['update'],
    listeners: {
        afteredit: function(object, changes, r, rowIndex) {
            Ext.MessageBox.alert(LANG['alert_info'], LANG['memory']); }

        }
    }
});

 var userGrid = new Ext.grid.GridPanel({
        id: 'status-form',
        region:'center',
        margins: '5 5 5 5',
        store: Gstore,
        iconCls: 'icon-grid',
        plugins: [editor, summary],

        cm: new Ext.grid.ColumnModel([

            {header: "ID", width: 30, sortable: true, dataIndex: 'idb', renderer: formatID},
            {xtype: 'datecolumn', header: LANG['date'], width: 70, sortable: true, dataIndex: 'date', 
                groupRenderer: Ext.util.Format.dateRenderer('M Y'), 
                format: 'd/m/Y',
                editor: new Ext.form.DateField({
                    value: (new Date()).format('d/m/Y'), 
                    //format: 'd/m/Y',
                    minValue: '01/01/2010',
                    //minText: 'Please Check Correct Data',
                    maxValue: (new Date()).format('d/m/Y'),
                    editable: false
                })
            },
            {header: LANG['title'], width: 150, sortable: true, dataIndex: 'title', 
                editor: new Ext.form.TextField({}),
                summaryType: 'count',
                summaryRenderer: function(v, params, data){
                    return ((v === 0 || v > 1) ? LANG['Tasks']+ ': '+ v: '1 '+LANG['Task']);
                }
            },
            {header: LANG['lenght'], width: 60, sortable: true, dataIndex: 'lenght', renderer: formatKM, align: 'center', 
                summaryType: 'sum',
                summaryRenderer: Ext.util.Format.cifres2,
                editor: new Ext.form.NumberField({
                    allowNegative: false,
                    decimalPrecision: 2,
                    //decimalSeparator: ',',
                    maxValue: 1000
                    //allowBlank: false
                })
            },
            {header: LANG['time'], width: 30, sortable: true, dataIndex: 'time', align: 'center', 
                renderer: formatTimeStr,
                summaryType: 'sum22',

                editor: new Ext.form.NumberField({
                    //format: 'H:i',
                    allowNegative: false,
                    decimalPrecision: 2,
                    decimalSeparator: ':'
                })
            },
            {header: LANG['vsr'], width: 50, sortable: true, dataIndex: 'vsr', renderer: formatKM, align: 'center',  
                summaryType: 'average',
                summaryRenderer: Ext.util.Format.cifres2,
                editor: new Ext.form.NumberField({
                    allowNegative: false,
                    decimalPrecision: 2,
                    maxValue: 100

                })
            },
            {header: LANG['vmax'], width: 50, sortable: true, dataIndex: 'vmax', renderer: formatKM, align: 'center',
                summaryType: 'max',
                summaryRenderer: Ext.util.Format.cifres2,
                editor: new Ext.form.NumberField({
                    allowNegative: false,
                    decimalPrecision: 2,
                    maxValue: 100
                })
            }, ............

Upvotes: 1

Views: 1563

Answers (3)

Umut
Umut

Reputation: 176

I implemented this with easy way. My method is enable key events of number field and check if pressed key is ',' than add a '.' to value. That is the implementation;

Ext.create('Ext.form.Panel', {
title: 'On The Wall',
width: 300,
bodyPadding: 10,
renderTo: Ext.getBody(),
items: [{
    xtype: 'numberfield',
    anchor: '100%',
    name: 'bottles',
    fieldLabel: 'Bottles of Beer',
    enableKeyEvents : true,
    value: 99,
    maxValue: 99,
    minValue: 0,
    listeners : {
        keypress : function(view, e){
                if(e.getKey() == 44)
                    view.setRawValue(view.getRawValue() +'.');
           }
        }
    }]
});

Upvotes: 1

Alexandr
Alexandr

Reputation: 65

The solution is found here: http://habrahabr.ru/post/137966/ (russian lang) Since there is seen a solution for version> 4.0, and I have worth less had to change the code, replacing the standard JS functions.Vykladyvayu it here, maybe someone will need:

To begin at the header of the page to connect сursor.js

// Author: Diego Perini <[email protected]>
var sb = new Array(
    'leftbox', 'rightbox', 'scrollLeft', 'scrollRight', 
    'caretPos', 'maxLength', 'textLength', 'availLength',
    'beforeCaret', 'afterCaret', 'selectedText'
)

var leftbox = {};
var rightbox = {};
var scrollLeft = {};
var scrollRight = {};
var caretPos = {};
var maxLength = {};
var textLength = {};
var availLength = {};
var beforeCaret = {};
var afterCaret = {};
var selectedText = {};

/*
for (var i in sb) {
    var v = '"var '+sb[i]+' = {}"';
    eval(v);
}
*/

var os = 0
var oe = 0
function update(o) {
    var t = o.value, s = getSelectionStart(o), e = getSelectionEnd(o)
    if (s == os && e == oe) return
    caretPos.firstChild.nodeValue = s
    maxLength.firstChild.nodeValue = o.getAttribute('maxLength')
    textLength.firstChild.nodeValue = t.length
    availLength.firstChild.nodeValue = o.getAttribute('maxLength') - t.length
    afterCaret.firstChild.nodeValue = t.substring(s).replace(/ /g, '\xa0') || '\xa0'
    beforeCaret.firstChild.nodeValue = t.substring(0, s).replace(/ /g, '\xa0') || '\xa0'
    selectedText.firstChild.nodeValue = t.substring(s, e).replace(/ /g, '\xa0') || '\xa0'
    rightbox.value = scrollRight.firstChild.nodeValue = t.substring(s).replace(/ /g, '\xa0') || '\xa0'
    leftbox.value = scrollLeft.firstChild.nodeValue = t.substring(0, s).replace(/ /g, '\xa0') || '\xa0'
    os = s
    oe = e
    return true
}

function setup() {
    for (var i in sb) eval(sb[i] + ' = document.getElementById(sb[i])')
    update(document.getElementById('textbox'))
}

function getSelectionStart(o) {
    if (o.createTextRange) {
        var r = document.selection.createRange().duplicate()
        r.moveEnd('character', o.value.length)
        if (r.text == '') return o.value.length
        return o.value.lastIndexOf(r.text)
    } else return o.selectionStart
}

function getSelectionEnd(o) {
    if (o.createTextRange) {
        var r = document.selection.createRange().duplicate()
        r.moveStart('character', -o.value.length)
        return r.text.length
    } else return o.selectionEnd
}

and connect the plugin:

Ext.ns('Ext.ux.form');

/**
 * @class Ext.ux.form.NumberInputFilter
 * @extends Ext.form.NumberField 
 * Plugin (ptype = 'numberinputfilter')  
 * @param allowedDecimalSeparators: ',.:-' and other
 * @ptype numberinputfilter
 */

Ext.ux.form.NumberInputFilter = Ext.extend(Ext.form.NumberField, {

    initComponent: function(){
        Ext.ux.form.NumberInputFilter.superclass.initComponent.call(this);
    },
    init : function(field) {
        if (!(field && field.isXType('numberfield'))) {
            return;
        }
        Ext.apply(field, {
            allowedDecimalSeparators : this.allowedDecimalSeparators,
            checkValue : function(newChar) {
                var raw = this.getRawValue();
                var el = Ext.get(this.id).dom;
                // functions taken from here http://javascript.nwbox.com/cursor_position/
                // and connected to a separate file cursor.js
                var start = getSelectionStart(el);
                var end = getSelectionEnd(el);
                if (start != end) {
                    // delete the selected text from the expected values
                    raw = raw.substring(0, start) + raw.substring(end);
                }
                if (Ext.isEmpty(raw)) {
                    return (newChar == this.decimalSeparator || (this.minValue < 0) && newChar == '-') || newChar.search('/^\d$/');
                }
                if (raw.length == this.maxLength) {
                    return false;
                }
                if (newChar == this.decimalSeparator && (!this.allowDecimals || raw.indexOf(this.decimalSeparator) != -1)) {
                    return false;
                }
                // form the intended meaning
                raw = raw.substring(0, start) + newChar + raw.substring(start);
                raw = raw.split(new RegExp(this.decimalSeparator.replace("/([-.*+?^${}()|[\]\/\\])/g", "\\$1")));

                return (!raw[0] || this.intRe.search(raw[0])) && (!raw[1] || this.decRe.search(raw[1]));
            },
            filterKeys : function(e){
                if (e.ctrlKey && !e.altKey) {
                    return;
                }
                var key = e.getKey(),
                    charCode = String.fromCharCode(e.getCharCode());

                if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
                    return;
                }

                if(!Ext.isGecko && e.isSpecialKey() && !charCode){
                    return;
                }
                // begin hack
                if (charCode != this.decimalSeparator && this.allowedDecimalSeparators.indexOf(charCode) != -1) {
                    // if the input character is not a decimal point, 
                    // But it is one of the alternatives, 
                    // Replace it with a decimal point
                    charCode = this.decimalSeparator;
                    if (Ext.isIE) {
                        // in the IE code of the pressed key can be substituted directly
                        e.browserEvent.keyCode = charCode.charCodeAt(0);
                    } else if (Ext.isGecko) {
                        // for gecko-engine slowing Event
                        e.stopEvent();
                        // create a new event with the modified code of the pressed key
                        var newEvent = document.createEvent('KeyEvents');
                        // Mandatory event must be cancelable 
                        // As it can be reversed, if the decimal 
                        // Delimiter is entered in the field
                        newEvent.initKeyEvent(
                            e.browserEvent.type,
                            e.browserEvent.bubbles,
                            true, //cancellable
                            e.browserEvent.view,
                            e.browserEvent.ctrlKey,
                            e.browserEvent.altKey,
                            e.browserEvent.shiftKey,
                            e.browserEvent.metaKey,
                            0, // keyCode
                            charCode.charCodeAt(0) // charCode
                        );
                        e.getTarget().dispatchEvent(newEvent);
                        // event generated, nothing doing.
                        return;
                    } else if (Ext.isWebKit) {
                        // stopped event
                        e.stopEvent();
                        // into webkit initKeyboardEvent dont work, use TextEvent
                        if (this.checkValue(charCode)) {
                            var newEvent = document.createEvent('TextEvent');
                            newEvent.initTextEvent(
                                'textInput', 
                                e.browserEvent.bubbles,
                                true,
                                e.browserEvent.view,
                                charCode
                            );
                            e.getTarget().dispatchEvent(newEvent);
                        }
                        return;
                    }
                }
                if (!this.checkValue(charCode)) {
                  e.stopEvent();
                }
                // end hack
            },
            updateDecimalPrecision : function(prec, force) {              
                if (prec == this.decimalPrecision && force !== true) {
                    return;
                }
                if (!Ext.isNumber(prec) || prec < 1) {
                    this.allowDecimals = false;
                } else {
                    this.decimalPrecision = prec;
                }
                var intRe = '^';
                if (this.minValue < 0) {
                    intRe +=  '-?';
                }
                intRe += '\\d' + (Ext.isNumber(this.integerPrecision) ? '{1,' + this.integerPrecision + '}' : '+') + '$';
                this.intRe = new RegExp(intRe);
                if (this.allowDecimals) {
                    this.decRe = new RegExp('^\\d{1,' + this.decimalPrecision + '}$');
                } else {
                    delete this.decRe;
                }
            },

            fixPrecision : function(value) {
                // support decimalSeparators
                if (Ext.isString(value)) {
                    value = value.replace(new RegExp('[' + (this.allowedDecimalSeparators + this.decimalSeparator).replace("/([-.*+?^${}()|[\]\/\\])/g", "\\$1")  + ']'), '.'); 
                }
                // end hack
                var me = this,
                    nan = isNaN(value),
                    precision = me.decimalPrecision;
                if (nan || !value) {
                    return nan ? '' : value;
                } else if (!me.allowDecimals || precision <= 0) {
                    precision = 0;
                }
                console.info(parseFloat(parseFloat(value).toFixed(precision)));
                return parseFloat(parseFloat(value).toFixed(precision));
            }
        });
        field.updateDecimalPrecision(field.decimalPrecision, true);
    }
});
Ext.preg('numberinputfilter', Ext.ux.form.NumberInputFilter);

Use any separator, what we like in a digital field, just listing them:

.....
            {header: LANG['lenght'], width: 60, sortable: true, dataIndex: 'lenght', renderer: formatKM, align: 'center', 
                summaryType: 'sum',
                summaryRenderer: Ext.util.Format.cifres2,
                editor: new Ext.form.NumberField({
                    allowNegative: false,
                    decimalPrecision: 2,
                    plugins: new Ext.ux.form.NumberInputFilter({
allowedDecimalSeparators : ',.-'
}),
                    maxValue: 1000,
                    allowBlank: false
                })

            },
.....

Upvotes: 0

Oğuz &#199;elikdemir
Oğuz &#199;elikdemir

Reputation: 4980

I used this in my project but I don't know it's fit your request.

First, checking the value where it's number and has "." then put proper value based on this condition. If it's not has "." in the value then calling the replace function.

value.match(/^[0-9]+\.?[0-9]*$/) ? Number(value) : Number((value.replace(',', '.')));

Upvotes: 0

Related Questions