// (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License. // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. // All other rights reserved. /// /// /// /// /// Type.registerNamespace('AjaxControlToolkit'); AjaxControlToolkit.FilteredTextBoxBehavior = function(element) { /// /// The FilteredTextBoxBehavior is used to prevent invalid characters from being entered into a textbox /// /// /// The textbox element this behavior is associated with /// AjaxControlToolkit.FilteredTextBoxBehavior.initializeBase(this, [element]); this._keypressHandler = null; this._changeHandler = null; this._intervalID = null; this._filterType = AjaxControlToolkit.FilterTypes.Custom; this._filterMode = AjaxControlToolkit.FilterModes.ValidChars; this._validChars = null; this._invalidChars = null; this._filterInterval = 250; this.charTypes = { }; this.charTypes.LowercaseLetters = "abcdefghijklmnopqrstuvwxyz"; this.charTypes.UppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; this.charTypes.Numbers = "0123456789"; } AjaxControlToolkit.FilteredTextBoxBehavior.prototype = { initialize : function() { /// /// Initialize the behavior /// AjaxControlToolkit.FilteredTextBoxBehavior.callBaseMethod(this, 'initialize'); var element = this.get_element(); this._keypressHandler = Function.createDelegate(this, this._onkeypress); $addHandler(element, 'keypress', this._keypressHandler); this._changeHandler = Function.createDelegate(this, this._onchange); $addHandler(element, 'change', this._changeHandler); var callback = Function.createDelegate(this, this._intervalCallback); this._intervalID = window.setInterval(callback, this._filterInterval); }, dispose : function() { /// /// Dispose the behavior /// var element = this.get_element(); $removeHandler(element, 'keypress', this._keypressHandler); this._keypressHandler = null; $removeHandler(element, 'change', this._changeHandler); this._changeHandler = null; window.clearInterval(this._intervalID); AjaxControlToolkit.FilteredTextBoxBehavior.callBaseMethod(this, 'dispose'); }, _getValidChars : function() { /// /// Get all the valid characters /// /// /// All valid characters /// if (this._validChars) return this._validChars; this._validChars = ""; for (type in this.charTypes) { var filterType = AjaxControlToolkit.FilterTypes.toString(this._filterType); if (filterType.indexOf(type) != -1) { this._validChars += this.charTypes[type]; } } return this._validChars; }, _getInvalidChars : function() { /// /// Get all the invalid characters (in case of custom filtering and InvalidChars mode) /// /// /// All invalid characters /// if (!this._invalidChars) { this._invalidChars = this.charTypes.Custom; } return this._invalidChars; }, _onkeypress : function(evt) { /// /// Handler for the target textbox's key press event /// /// /// Event info /// // This handler will only get called for valid characters in IE, we use keyCode // // In FireFox, this will be called for all key presses, with charCode/which // being set for keys we should filter (e.g. the chars) and keyCode being // set for all other keys. // // scanCode = event.charCode // // In Safari, charCode, which, and keyCode will all be filled with the same value, // as well as keyIdentifier, which has the string representation either as "end" or "U+00000008" // // 1) Check for ctrl/alt/meta -> bail if true // 2) Check for keyIdentifier.startsWith("U+") -> bail if false // 3) Check keyCode < 0x20 -> bail // 4) Special case Delete (63272) -> bail var scanCode; // Note (Supergibbs): Changed to handle all majors browsers // IE and Safari only fires for valid characters // Firefox sets charCode to 0 and uses keyCode for special keys // Opera always fires but you cannot distinguish which are valid or special keys if ( (((/* ff */ evt.rawEvent.charCode == 0) || (/* opera */ evt.rawEvent.keyCode == evt.rawEvent.which && evt.rawEvent.charCode == undefined)) && ((evt.rawEvent.keyCode == Sys.UI.Key.pageUp) || (evt.rawEvent.keyCode == Sys.UI.Key.pageDown) || (evt.rawEvent.keyCode == Sys.UI.Key.up) || (evt.rawEvent.keyCode == Sys.UI.Key.down) || (evt.rawEvent.keyCode == Sys.UI.Key.left) || (evt.rawEvent.keyCode == Sys.UI.Key.right) || (evt.rawEvent.keyCode == Sys.UI.Key.home) || (evt.rawEvent.keyCode == Sys.UI.Key.end) || (evt.rawEvent.keyCode == 46 /* Delete */))) || (evt.ctrlKey /* Control keys */)) { return; } if (evt.rawEvent.keyIdentifier) { // Safari // Note (Garbin): used the underlying rawEvent insted of the DomEvent instance. if (evt.rawEvent.ctrlKey || evt.rawEvent.altKey || evt.rawEvent.metaKey) { return; } if (evt.rawEvent.keyIdentifier.substring(0,2) != "U+") { return; } scanCode = evt.rawEvent.charCode; if (scanCode == 63272 /* Delete */) { return; } } else { scanCode = evt.charCode; } if (scanCode && scanCode >= 0x20 /* space */) { var c = String.fromCharCode(scanCode); if(!this._processKey(c)) { evt.preventDefault(); } } }, _processKey : function(key) { /// /// Determine whether the key is valid or whether it should be filtered out /// /// /// Character to be validated /// /// /// True if the character should be accepted, false if it should be filtered /// // Allow anything that's not a printable character, // e.g. backspace, arrows, etc. Everything above 32 // should be considered allowed, as it may be Unicode, etc. var filter = ""; var shouldFilter = false; if (this._filterMode == AjaxControlToolkit.FilterModes.ValidChars) { filter = this._getValidChars(); // Determine if we should accept the character shouldFilter = filter && (filter.length > 0) && (filter.indexOf(key) == -1); } else { filter = this._getInvalidChars(); // Determine if we should accept the character shouldFilter = filter && (filter.length > 0) && (filter.indexOf(key) > -1); } // Raise the processKey event and allow handlers to intercept // and decide whether the key should be allowed var eventArgs = new AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs(key, AjaxControlToolkit.TextBoxWrapper.get_Wrapper(this.get_element()).get_Value(), shouldFilter); this.raiseProcessKey(eventArgs); // If a processKey handler decided the key should be allowed, just // return true and pass it through (note that the default value of // allowKey is the opposite of shouldFilter so it will work as normal // if no one is handling the event) if (eventArgs.get_allowKey()) { return true; } // Else if it was decided that it shouldn't be allowed, // raise the Filtered event and return false to filter the key this.raiseFiltered(new AjaxControlToolkit.FilteredTextBoxEventArgs(key)); return false; }, _onchange : function() { /// /// Handler for the target textbox's key change event which will filter /// the text again (to make sure no text was inserted without keypresses, etc.) /// var wrapper = AjaxControlToolkit.TextBoxWrapper.get_Wrapper(this.get_element()); var text = wrapper.get_Value() || ''; var result = new Sys.StringBuilder(); for (var i = 0; i < text.length; i++) { var ch = text.substring(i, i+1); if (this._processKey(ch)) { result.append(ch); } } // change the value only if it is different if (wrapper.get_Value() != result.toString()) { wrapper.set_Value(result.toString()); } }, _intervalCallback : function() { /// /// Method that is repeatedly called to purge invalid characters from the textbox /// this._changeHandler(); }, get_ValidChars : function() { /// /// A string consisting of all characters considered valid for the textbox, if /// "Custom" is specified as the field type. Otherwise this parameter is ignored. /// return this.charTypes.Custom; }, set_ValidChars : function(value) { if (this._validChars != null || this.charTypes.Custom != value) { this.charTypes.Custom = value; this._validChars = null; this.raisePropertyChanged('ValidChars'); } }, get_InvalidChars : function() { /// /// A string consisting of all characters considered invalid for the textbox, if "Custom" is specified as the field type. Otherwise this parameter is ignored. /// return this.charTypes.Custom; }, set_InvalidChars : function(value) { if (this._invalidChars != null || this.charTypes.Custom != value) { this.charTypes.Custom = value; this._invalidChars = null; this.raisePropertyChanged('InvalidChars'); } }, get_FilterType : function() { /// /// FilterType - A the type of filter to apply, as a comma-separated combination of /// Numbers, LowercaseLetters, UppercaseLetters, and Custom. If Custom is specified, /// the ValidChars field will be used in addition to other settings such as Numbers. /// return this._filterType; }, set_FilterType : function(value) { if (this._validChars != null || this._filterType != value) { this._filterType = value; this._validChars = null; this.raisePropertyChanged('FilterType'); } }, get_FilterMode : function() { /// /// FilterMode - The filter mode to apply when custom filtering is activated; supported values are ValidChars and InvalidChars. /// return this._filterMode; }, set_FilterMode : function(value) { if (this._validChars != null || this._invalidChars != null || this._filterMode != value) { this._filterMode = value; this._validChars = null; this._invalidChars = null; this.raisePropertyChanged('FilterMode'); } }, get_FilterInterval : function() { /// /// An integer containing the interval (in milliseconds) in which /// the field's contents are filtered /// return this._filterInterval; }, set_FilterInterval : function(value) { if (this._filterInterval != value) { this._filterInterval = value; this.raisePropertyChanged('FilterInterval'); } }, add_processKey : function(handler) { /// /// Add an event handler for the processKey event /// /// /// Event handler /// /// this.get_events().addHandler('processKey', handler); }, remove_processKey : function(handler) { /// /// Remove an event handler from the processKey event /// /// /// Event handler /// /// this.get_events().removeHandler('processKey', handler); }, raiseProcessKey : function(eventArgs) { /// /// Raise the processKey event /// /// /// Event arguments for the processKey event /// /// var handler = this.get_events().getHandler('processKey'); if (handler) { handler(this, eventArgs); } }, add_filtered : function(handler) { /// /// Add an event handler for the filtered event /// /// /// Event handler /// /// this.get_events().addHandler('filtered', handler); }, remove_filtered : function(handler) { /// /// Remove an event handler from the filtered event /// /// /// Event handler /// /// this.get_events().removeHandler('filtered', handler); }, raiseFiltered : function(eventArgs) { /// /// Raise the filtered event /// /// /// Event arguments for the filtered event /// /// var handler = this.get_events().getHandler('filtered'); if (handler) { handler(this, eventArgs); } } } AjaxControlToolkit.FilteredTextBoxBehavior.registerClass('AjaxControlToolkit.FilteredTextBoxBehavior', AjaxControlToolkit.BehaviorBase); AjaxControlToolkit.FilterTypes = function() { /// /// Character filter to be applied to a textbox /// /// /// Custom Characters /// /// /// Numbers (0123456789) /// /// /// Uppercase Letters (ABCDEFGHIJKLMNOPQRSTUVWXYZ) /// /// /// Lowercase Letters (abcdefghijklmnopqrstuvwxyz) /// throw Error.invalidOperation(); } AjaxControlToolkit.FilterTypes.prototype = { Custom : 0x1, Numbers : 0x2, UppercaseLetters : 0x4, LowercaseLetters : 0x8 } AjaxControlToolkit.FilterTypes.registerEnum('AjaxControlToolkit.FilterTypes', true); AjaxControlToolkit.FilterModes = function() { /// /// Filter mode to be applied to a textbox /// /// /// Provide a list of valid characters /// /// /// Provide a list of invalid characters /// throw Error.invalidOperation(); } AjaxControlToolkit.FilterModes.prototype = { ValidChars : 0x1, InvalidChars : 0x2 } AjaxControlToolkit.FilterModes.registerEnum('AjaxControlToolkit.FilterModes', true); AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs = function(key, text, shouldFilter) { /// /// Event arguments used when the processKey event is raised /// /// /// Key to be processed /// /// /// Current text in the textbox /// /// /// Whether the character should be filtered given the current /// FilteredTextBox settings /// AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs.initializeBase(this); this._key = key; this._text = text; this._shouldFilter = shouldFilter; this._allowKey = !shouldFilter; } AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs.prototype = { get_key : function() { /// /// Key to be processed /// return this._key; }, get_text : function() { /// /// Current text in the textbox /// return this._text; }, get_shouldFilter : function() { /// /// Whether the character should be filtered given the current /// FilteredTextBox settings /// return this._shouldFilter; }, get_allowKey : function() { /// /// Whether or not the key will be filtered. It defaults to the opposite of /// shouldFilter and should be set by handlers of the processKey event. /// return this._allowKey; }, set_allowKey : function(value) { this._allowKey = value; } } AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs.registerClass('AjaxControlToolkit.FilteredTextBoxProcessKeyEventArgs', Sys.EventArgs); AjaxControlToolkit.FilteredTextBoxEventArgs = function(key) { /// /// Event arguments used when the filtered event is raised /// /// /// Key that was filtered /// AjaxControlToolkit.FilteredTextBoxEventArgs.initializeBase(this); this._key = key; } AjaxControlToolkit.FilteredTextBoxEventArgs.prototype = { get_key : function() { /// /// Key that was filtered /// return this._key; } } AjaxControlToolkit.FilteredTextBoxEventArgs.registerClass('AjaxControlToolkit.FilteredTextBoxEventArgs', Sys.EventArgs); if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();