PrimeFaces Extension Sheet Restrict Decimal Places For Input - primefaces

I want to restrict decimal places up to 1. User shouldnt type multiple dots(1..99) and (1.99). I want 1.9 2.6 for ex. Not 2.66 then convert into 2.7 etc. I have to use pe:sheetcolumn. I tried to add p:inputnumber and other p: components than pe extension. But pe:sheetcolumn have to be. With below approach it just let user to type multiple dots and multiple decimal places. It just convert to 1 decimal after user entered value on screen with #0.0. But i want to restrict on input to type multiple decimal places than 1 and multiple dots. I thought about javascript keyup event but i think it would be bad approach. How can i achive that
<pe:sheetcolumn headerText="SOME" value="#{SOME.some}" colWidth="200"
colType="numeric" numericPattern="#0.0" >
</pe:sheetcolumn>
For example for p:inputNumber as you can see on image user cant type multiple dots and they cant add decimal places more than 6.
Example
I want to do same thing with pe:sheetColumn. How can i do that
My JSF VERSION : 2.2.1 PRÄ°MEFACES AND PRIMEFACES EXTENSION VERSION : 6.2

If you install this MonkeyPatch you can then tweak the output to do whatever your want. I am pretty sure you can get the current cell with var currentValue = this.getDataAtCell(row , col) If you add this JS to your app you can then tweak how it handles keypresses and validation.
I added this line for you
var currentValue = this.getDataAtCell(row , col); // VALUE HERE!
So you can validate whatever your want with your code and if there is already a "." don't accept another "." etc.
if (PrimeFaces.widget.ExtSheet) {
PrimeFaces.widget.ExtSheet.prototype.handleHotBeforeKeyDown = function(e) {
var selectedLast = this.getSelectedLast();
if (!selectedLast) {
return;
}
var row = selectedLast[0];
var col = selectedLast[1];
var celltype = this.getCellMeta(row, col).type;
var currentValue = this.getDataAtCell(row , col); // VALUE HERE!
var evt = e || window.event; // IE support
var key = evt.charCode || evt.keyCode || 0;
var shiftDown = e.shiftKey;
// #740 tab on last cell should focus this next component
if (this.allowTabOffSheet && key == 9) {
var lastRow = this.countRows() - 1;
var lastCol = this.countCols() - 1;
if ((!shiftDown && row === lastRow && col === lastCol) ||
(shiftDown && row === 0 && col === 0)) {
e.stopImmediatePropagation();
this.unlisten();
this.deselectCell();
//add all elements we want to include in our selection
var focusableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]):not([hidden]):not([aria-hidden="true"]), [tabindex]:not([disabled]):not([tabindex="-1"]):not([aria-hidden="true"])';
if (document.activeElement && document.activeElement.form) {
var focusable = Array.prototype.filter.call(document.activeElement.form.querySelectorAll(focusableElements),
function(element) {
//check for visibility while always include the current activeElement
return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
});
var index = focusable.indexOf(document.activeElement);
if (index > -1) {
var nextElement = focusable[index + 1] || focusable[0];
nextElement.focus();
}
}
}
return;
}
// prevent Alpha chars in numeric sheet cells
if (celltype === "numeric") {
// #766 do not block if just CTRL or SHIFT key
if (key === 16 || key === 17) {
return;
}
// #739 allow navigation
var ctrlDown = evt.ctrlKey || evt.metaKey; // Mac support
if (shiftDown || ctrlDown) {
// navigation keys
if (key == 9 || (key >= 35 && key <= 40)) {
return;
}
}
// check for cut and paste
var isClipboard = false;
// Check for Alt+Gr (http://en.wikipedia.org/wiki/AltGr_key)
if (ctrlDown && evt.altKey) isClipboard = false;
// Check for ctrl+c, v and x
else if (ctrlDown && key == 65) isClipboard = true; // a (select all)
else if (ctrlDown && key == 67) isClipboard = true; // c
else if (ctrlDown && key == 86) isClipboard = true; // v
else if (ctrlDown && key == 88) isClipboard = true; // x
// allow backspace, tab, delete, enter, arrows, numbers and keypad numbers
// ONLY home, end, F5, F12, minus (-), period (.)
// console.log('Key: ' + key + ' Shift: ' + e.shiftKey + ' Clipboard: ' + isClipboard);
var isNumeric = ((key == 8) || (key == 9) || (key == 13) ||
(key == 46) || (key == 110) || (key == 116) ||
(key == 123) || (key == 188) || (key == 189) ||
(key == 190) || ((key >= 35) && (key <= 40)) ||
((key >= 48) && (key <= 57)) || ((key >= 96) && (key <= 105)));
if ((!isNumeric && !isClipboard) || shiftDown) {
// prevent alpha characters
e.stopImmediatePropagation();
e.preventDefault();
}
}
}
}

Related

html numeric keyboard plus comma sign [duplicate]

I am creating a web page where I have an input text field in which I want to allow only numeric characters like (0,1,2,3,4,5...9) 0-9.
How can I do this using jQuery?
Note: This is an updated answer. Comments below refer to an old version which messed around with keycodes.
jQuery
Try it yourself on JSFiddle.
There is no native jQuery implementation for this, but you can filter the input values of a text <input> with the following inputFilter plugin (supports Copy+Paste, Drag+Drop, keyboard shortcuts, context menu operations, non-typeable keys, the caret position, different keyboard layouts, validity error message, and all browsers since IE 9):
// Restricts input for the set of matched elements to the given inputFilter function.
(function($) {
$.fn.inputFilter = function(callback, errMsg) {
return this.on("input keydown keyup mousedown mouseup select contextmenu drop focusout", function(e) {
if (callback(this.value)) {
// Accepted value
if (["keydown","mousedown","focusout"].indexOf(e.type) >= 0){
$(this).removeClass("input-error");
this.setCustomValidity("");
}
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
} else if (this.hasOwnProperty("oldValue")) {
// Rejected value - restore the previous one
$(this).addClass("input-error");
this.setCustomValidity(errMsg);
this.reportValidity();
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
} else {
// Rejected value - nothing to restore
this.value = "";
}
});
};
}(jQuery));
You can now use the inputFilter plugin to install an input filter:
$(document).ready(function() {
$("#myTextBox").inputFilter(function(value) {
return /^\d*$/.test(value); // Allow digits only, using a RegExp
},"Only digits allowed");
});
Apply your preferred style to input-error class. Here's a suggestion:
.input-error{
outline: 1px solid red;
}
See the JSFiddle demo for more input filter examples. Also note that you still must do server side validation!
Pure JavaScript (without jQuery)
jQuery isn't actually needed for this, you can do the same thing with pure JavaScript as well. See this answer.
HTML 5
HTML 5 has a native solution with <input type="number"> (see the specification), but note that browser support varies:
Most browsers will only validate the input when submitting the form, and not when typing.
Most mobile browsers don't support the step, min and max attributes.
Chrome (version 71.0.3578.98) still allows the user to enter the characters e and E into the field. Also see this question.
Firefox (version 64.0) and Edge (EdgeHTML version 17.17134) still allow the user to enter any text into the field.
Try it yourself on w3schools.com.
Here is the function I use:
// Numeric only control handler
jQuery.fn.ForceNumericOnly =
function()
{
return this.each(function()
{
$(this).keydown(function(e)
{
var key = e.charCode || e.keyCode || 0;
// allow backspace, tab, delete, enter, arrows, numbers and keypad numbers ONLY
// home, end, period, and numpad decimal
return (
key == 8 ||
key == 9 ||
key == 13 ||
key == 46 ||
key == 110 ||
key == 190 ||
(key >= 35 && key <= 40) ||
(key >= 48 && key <= 57) ||
(key >= 96 && key <= 105));
});
});
};
You can then attach it to your control by doing:
$("#yourTextBoxName").ForceNumericOnly();
Inline:
<input name="number" onkeyup="if (/\D/g.test(this.value)) this.value = this.value.replace(/\D/g,'')">
Unobtrusive style (with jQuery):
$('input[name="number"]').keyup(function(e)
{
if (/\D/g.test(this.value))
{
// Filter non-digits from input value.
this.value = this.value.replace(/\D/g, '');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="number">
You could just use a simple JavaScript regular expression to test for purely numeric characters:
/^[0-9]+$/.test(input);
This returns true if the input is numeric or false if not.
or for event keycode, simple use below :
// Allow: backspace, delete, tab, escape, enter, ctrl+A and .
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
// Allow: Ctrl+A
(e.keyCode == 65 && e.ctrlKey === true) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
var charValue = String.fromCharCode(e.keyCode)
, valid = /^[0-9]+$/.test(charValue);
if (!valid) {
e.preventDefault();
}
You can use on input event like this:
$(document).on("input", ".numeric", function() {
this.value = this.value.replace(/\D/g,'');
});
But, what's this code privilege?
It works on mobile browsers(keydown and keyCode have problem).
It works on AJAX generated content too, because We're using "on".
Better performance than keydown, for example on paste event.
Short and sweet - even if this will never find much attention after 30+ answers ;)
$('#number_only').bind('keyup paste', function(){
this.value = this.value.replace(/[^0-9]/g, '');
});
Use JavaScript function isNaN,
if (isNaN($('#inputid').val()))
if (isNaN(document.getElementById('inputid').val()))
if (isNaN(document.getElementById('inputid').value))
Update:
And here a nice article talking about it but using jQuery: Restricting Input in HTML Textboxes to Numeric Values
$(document).ready(function() {
$("#txtboxToFilter").keydown(function(event) {
// Allow only backspace and delete
if ( event.keyCode == 46 || event.keyCode == 8 ) {
// let it happen, don't do anything
}
else {
// Ensure that it is a number and stop the keypress
if (event.keyCode < 48 || event.keyCode > 57 ) {
event.preventDefault();
}
}
});
});
Source: http://snipt.net/GerryEng/jquery-making-textfield-only-accept-numeric-values
I use this in our internal common js file. I just add the class to any input that needs this behavior.
$(".numericOnly").keypress(function (e) {
if (String.fromCharCode(e.keyCode).match(/[^0-9]/g)) return false;
});
Simpler one for me is
jQuery('.plan_eff').keyup(function () {
this.value = this.value.replace(/[^1-9\.]/g,'');
});
Why so complicated? You don't even need jQuery because there is a HTML5 pattern attribute:
<input type="text" pattern="[0-9]*">
The cool thing is that it brings up a numeric keyboard on mobile devices, which is way better than using jQuery.
You can do the same by using this very simple solution
$("input.numbers").keypress(function(event) {
return /\d/.test(String.fromCharCode(event.keyCode));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="numbers" name="field_name" />
I referred to this link for the solution. It works perfectly!!!
You can try the HTML5 number input:
<input type="number" value="0" min="0">
For non-compliant browsers there are Modernizr and Webforms2 fallbacks.
The pattern attribute in HTML5 specifies a regular expression that the element's value is checked against.
<input type="text" pattern="[0-9]{1,3}" value="" />
Note: The pattern attribute works with the following input types: text, search, url, tel, email, and password.
[0-9] can be replaced with any regular expression condition.
{1,3} it represents minimum of 1 and maximum of 3 digit can be entered.
Something fairly simple using jQuery.validate
$(document).ready(function() {
$("#formID").validate({
rules: {
field_name: {
numericOnly:true
}
}
});
});
$.validator.addMethod('numericOnly', function (value) {
return /^[0-9]+$/.test(value);
}, 'Please only enter numeric values (0-9)');
Here is two different approaches:
Allow numeric values with decimal point
Allow numeric values without decimal point
APPROACH 1:
$("#approach1").on("keypress keyup blur",function (e) {
$(this).val($(this).val().replace(/[^0-9\.]/g,''));
if ((e.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) {
event.preventDefault();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Numeric with decimal point</h2><br/>
<span>Enter Amount</span>
<input type="text" name="amount" id="approach1">
APPROACH 2:
$("#approach2").on("keypress keyup blur",function (event) {
$(this).val($(this).val().replace(/[^\d].+/, ""));
if ((event.which < 48 || event.which > 57)) {
event.preventDefault();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Numeric without decimal point</h2><br/>
<span>Enter Amount</span>
<input type="text" name="amount" id="approach2">
try it within html code it self like onkeypress and onpast
<input type="text" onkeypress="return event.charCode >= 48 && event.charCode <= 57" onpaste="return false">
If have a smooth OneLiner:
<input type="text" onkeypress="return /[0-9]/i.test(event.key)" >
function suppressNonNumericInput(event){
if( !(event.keyCode == 8 // backspace
|| event.keyCode == 46 // delete
|| (event.keyCode >= 35 && event.keyCode <= 40) // arrow keys/home/end
|| (event.keyCode >= 48 && event.keyCode <= 57) // numbers on keyboard
|| (event.keyCode >= 96 && event.keyCode <= 105)) // number on keypad
) {
event.preventDefault(); // Prevent character input
}
}
I came to a very good and simple solution that doesn't prevent the user from selecting text or copy pasting as other solutions do. jQuery style :)
$("input.inputPhone").keyup(function() {
var jThis=$(this);
var notNumber=new RegExp("[^0-9]","g");
var val=jThis.val();
//Math before replacing to prevent losing keyboard selection
if(val.match(notNumber))
{ jThis.val(val.replace(notNumber,"")); }
}).keyup(); //Trigger on page load to sanitize values set by server
You can use this JavaScript function:
function maskInput(e) {
//check if we have "e" or "window.event" and use them as "event"
//Firefox doesn't have window.event
var event = e || window.event
var key_code = event.keyCode;
var oElement = e ? e.target : window.event.srcElement;
if (!event.shiftKey && !event.ctrlKey && !event.altKey) {
if ((key_code > 47 && key_code < 58) ||
(key_code > 95 && key_code < 106)) {
if (key_code > 95)
key_code -= (95-47);
oElement.value = oElement.value;
} else if(key_code == 8) {
oElement.value = oElement.value;
} else if(key_code != 9) {
event.returnValue = false;
}
}
}
And you can bind it to your textbox like this:
$(document).ready(function() {
$('#myTextbox').keydown(maskInput);
});
I use the above in production, and it works perfectly, and it is cross-browser. Furthermore, it does not depend on jQuery, so you can bind it to your textbox with inline JavaScript:
<input type="text" name="aNumberField" onkeydown="javascript:maskInput()"/>
I think it will help everyone
$('input.valid-number').bind('keypress', function(e) {
return ( e.which!=8 && e.which!=0 && (e.which<48 || e.which>57)) ? false : true ;
})
Here is a quick solution I created some time ago. you can read more about it in my article:
http://ajax911.com/numbers-numeric-field-jquery/
$("#textfield").bind("keyup paste", function(){
setTimeout(jQuery.proxy(function() {
this.val(this.val().replace(/[^0-9]/g, ''));
}, $(this)), 0);
});
This is why I recently wrote to accomplish this. I know this has already been answered but I'm leaving this for later uses.
This method only allows 0-9 both keyboard and numpad, backspaces, tab, left and right arrows (normal form operations)
$(".numbersonly-format").keydown(function (event) {
// Prevent shift key since its not needed
if (event.shiftKey == true) {
event.preventDefault();
}
// Allow Only: keyboard 0-9, numpad 0-9, backspace, tab, left arrow, right arrow, delete
if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105) || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 37 || event.keyCode == 39 || event.keyCode == 46) {
// Allow normal operation
} else {
// Prevent the rest
event.preventDefault();
}
});
I wrote mine based off of #user261922's post above, slightly modified so you can select all, tab and can handle multiple "number only" fields on the same page.
var prevKey = -1, prevControl = '';
$(document).ready(function () {
$(".OnlyNumbers").keydown(function (event) {
if (!(event.keyCode == 8 // backspace
|| event.keyCode == 9 // tab
|| event.keyCode == 17 // ctrl
|| event.keyCode == 46 // delete
|| (event.keyCode >= 35 && event.keyCode <= 40) // arrow keys/home/end
|| (event.keyCode >= 48 && event.keyCode <= 57) // numbers on keyboard
|| (event.keyCode >= 96 && event.keyCode <= 105) // number on keypad
|| (event.keyCode == 65 && prevKey == 17 && prevControl == event.currentTarget.id)) // ctrl + a, on same control
) {
event.preventDefault(); // Prevent character input
}
else {
prevKey = event.keyCode;
prevControl = event.currentTarget.id;
}
});
});
You would want to allow tab:
$("#txtboxToFilter").keydown(function(event) {
// Allow only backspace and delete
if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 ) {
// let it happen, don't do anything
}
else {
// Ensure that it is a number and stop the keypress
if ((event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {
event.preventDefault();
}
}
});
Here is an answer that uses jQuery UI Widget factory. You can customize what characters are allowed easily.
$('input').numberOnly({
valid: "0123456789+-.$,"
});
That would allow numbers, number signs and dollar amounts.
$.widget('themex.numberOnly', {
options: {
valid : "0123456789",
allow : [46,8,9,27,13,35,39],
ctrl : [65],
alt : [],
extra : []
},
_create: function() {
var self = this;
self.element.keypress(function(event){
if(self._codeInArray(event,self.options.allow) || self._codeInArray(event,self.options.extra))
{
return;
}
if(event.ctrlKey && self._codeInArray(event,self.options.ctrl))
{
return;
}
if(event.altKey && self._codeInArray(event,self.options.alt))
{
return;
}
if(!event.shiftKey && !event.altKey && !event.ctrlKey)
{
if(self.options.valid.indexOf(String.fromCharCode(event.keyCode)) != -1)
{
return;
}
}
event.preventDefault();
});
},
_codeInArray : function(event,codes) {
for(code in codes)
{
if(event.keyCode == codes[code])
{
return true;
}
}
return false;
}
});
This seems unbreakable.
// Prevent NULL input and replace text.
$(document).on('change', 'input[type="number"]', function (event) {
this.value = this.value.replace(/[^0-9\.]+/g, '');
if (this.value < 1) this.value = 0;
});
// Block non-numeric chars.
$(document).on('keypress', 'input[type="number"]', function (event) {
return (((event.which > 47) && (event.which < 58)) || (event.which == 13));
});
Need to make sure you have the numeric keypad and the tab key working too
// Allow only backspace and delete
if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9) {
// let it happen, don't do anything
}
else {
// Ensure that it is a number and stop the keypress
if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 96 && event.keyCode <= 105)) {
}
else {
event.preventDefault();
}
}
I wanted to help a little, and I made my version, the onlyNumbers function...
function onlyNumbers(e){
var keynum;
var keychar;
if(window.event){ //IE
keynum = e.keyCode;
}
if(e.which){ //Netscape/Firefox/Opera
keynum = e.which;
}
if((keynum == 8 || keynum == 9 || keynum == 46 || (keynum >= 35 && keynum <= 40) ||
(event.keyCode >= 96 && event.keyCode <= 105)))return true;
if(keynum == 110 || keynum == 190){
var checkdot=document.getElementById('price').value;
var i=0;
for(i=0;i<checkdot.length;i++){
if(checkdot[i]=='.')return false;
}
if(checkdot.length==0)document.getElementById('price').value='0';
return true;
}
keychar = String.fromCharCode(keynum);
return !isNaN(keychar);
}
Just add in input tag "...input ... id="price" onkeydown="return onlyNumbers(event)"..." and you are done ;)

HTML5 - type="number" prevents non-numbers in Chrome but not in IE & FF

I'm coding a site in MVC and I have a price field in my form.
My Razor code looks like this:
#Html.EditorFor(model => model.Price, new { htmlAttributes = new { #class = "myclass", min = 0, max = 1000000 } })
and my ViewModel property looks like this:
[Display(Name = "Price")]
[Range(0, 1000000, ErrorMessage="Please enter a valid Price")]
public int Price { get; set; }
In Chrome the user can't enter any other characters than . but in Firefox and Internet Explorer they can, which is not what I want.
Is it correct that HTML5 standards do not extend to the UI? And does Chrome doing a bonus? Or should IE and FF block letters (e.g. characters like $) and I have done something wrong?
EDIT: If I begin the input with, say, $ in IE it blanks the control upon losing focus. In Firefox it remains.
I resolved this by using JQuery. These are the steps:
1) Create an external file to load - MyUtils.js
2) Paste in this JQuery code:
// Use like: $('#SomeId').forceNumeric()
jQuery.fn.forceNumeric = function (intsOnly) {
return this.each(function () {
$(this).keydown(function (e) {
var key = e.which || e.keyCode;
if (!e.shiftKey && !e.altKey && !e.ctrlKey &&
// numbers
key >= 48 && key <= 57 ||
// Numeric keypad
key >= 96 && key <= 105 ||
// Backspace and Tab and Enter
key == 8 || key == 9 || key == 13 ||
// Home and End
key == 35 || key == 36 ||
// left and right arrows
key == 37 || key == 39 ||
// Del and Ins
key == 46 || key == 45)
{
// ints only: look for a decimal. Disallow comma
// minus and period on keypad
if ((intsOnly) && (key == 190 || key == 188 || key == 109 || key == 110)) {
return false;
}
// Input is OKAY
return true;
}
return false;
});
});
}
3) On the page you want to use this, load the js file
e.g. script src="/Scripts/MyUtils.js"
4) Apply the method to the field on setup
$('#Price').forceNumeric(true);

Texbox restrict characters and symbols and only allow numeric values with only one decimal point

Texbox restrict entering characters and symbols and only allow numeric values with only one decimal point.maximum length 4 and one value after decimal point.For eg: .2,12.3,1444
Here is the code in html to allow only one decimal point in a textbox:
<script type="text/javascript" language="javascript">
function isNumberKey(evt) {
var charCode = (evt.charCode) ? evt.which : event.keyCode
if (charCode > 31 && (charCode < 48 || charCode > 57) && charCode != 46)
return false;
else {
var input = document.getElementById("txtChar").value;
var len = document.getElementById("txtChar").value.length;
var index = document.getElementById("txtChar").value.indexOf('.');
if (index > 0 && charCode == 46) {
return false;
}
if (index >0 || index==0) {
var CharAfterdot = (len + 1) - index;
if (CharAfterdot > 2) {
return false;
}
}
if (charCode == 46 && input.split('.').length >1) {
return false;
}
I want to done this in asp.net using c#.This code is not properly working in asp.net.
Please Check this Link - Validate Input Field which will allows Only Float...
$(function(){
$('.float-input').keyup(function(e){
var entered_value = $(this).val();
var regexPattern = /^\d{0,8}(\.\d{1,2})?$/;
//Allow only Number as well 0nly 2 digit after dot(.)
if(regexPattern.test(entered_value)) {
$(this).css('background-color', 'white');
$('.err-msg').html('');
} else {
$(this).css('background-color', 'red');
$('.err-msg').html('Enter a valid Decimal Number');
}
});
});

Change keyboard button effects on HTML

Whilst in a html textarea input, I want the tab keyboard button to act like a Word processor-style indentation key rather than skipping to the next element.
How can this be done?
google is your friend! link
function insertTab(o, e)
{
var kC = e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which;
if (kC == 9 && !e.shiftKey && !e.ctrlKey && !e.altKey)
{
var oS = o.scrollTop;
if (o.setSelectionRange)
{
var sS = o.selectionStart;
var sE = o.selectionEnd;
o.value = o.value.substring(0, sS) + "\t" + o.value.substr(sE);
o.setSelectionRange(sS + 1, sS + 1);
o.focus();
}
else if (o.createTextRange)
{
document.selection.createRange().text = "\t";
e.returnValue = false;
}
o.scrollTop = oS;
if (e.preventDefault)
{
e.preventDefault();
}
return false;
}
return true;
}
<textarea onkeydown="insertTab(this, event);"></textarea>

JQuery SVG making objects droppable

I am trying to build a seating reservation web app using SVG. Imagine, I've created rectangles in the svg, which represents an empty seat. I want to allow user to drop an html "image" element on the "rect" to reserve the seat.
However, I couldn't get the droppable to work on the SVG elemnets. Any one has any idea why this is so? Here is the code:
$('#target').svg();
var svg = $("#target").svg('get');
svg.rect(20, 10, 100, 50, 10, 10, { fill: '#666', class: "droppable" });
$('rect')
.droppable({
accept: '.product',
tolerance: 'touch',
drop: function (event, ui) {
alert('df');
}
}
I looked in to the jQuery-ui source and figured out why it wasn't working with SVGs. jQuery thinks they have a width and height of 0px, so the intersection test fails.
I wrapped $.ui.intersect and set the correct size information before passing the arguments through to the original function. There may be more proportion objects that need fixing but the two I did here are enough to fix my :
$.ui.intersect_o = $.ui.intersect;
$.ui.intersect = function(draggable, droppable, toleranceMode) {
//Fix helper
if (draggable.helperProportions && draggable.helperProportions.width === 0 && draggable.helperProportions.height === 0) {
draggable.helperProportionsBBox = draggable.helperProportionsBBox || $(draggable.element).get(0).getBBox();
draggable.helperProportions = draggable.helperProportionsBBox;
}
//Fix droppable
if (droppable.proportions && droppable.proportions.width === 0 && droppable.proportions.height === 0) {
droppable.proportionsBBox = droppable.proportionsBBox || $(droppable.element).get(0).getBBox();
droppable.proportions = droppable.proportionsBBox;
}
return $.ui.intersect_o(draggable, droppable, toleranceMode);
};
With jQuery UI 1.11.4 I had to change Eddie's solution to the following, as draggable.proportions is now a function:
$.ui.intersect_o = $.ui.intersect;
$.ui.intersect = function (draggable, droppable, toleranceMode, event) {
//Fix helper
if (draggable.helperProportions && draggable.helperProportions.width === 0 && draggable.helperProportions.height === 0) {
draggable.helperProportionsBBox = draggable.helperProportionsBBox || $(draggable.element).get(0).getBBox();
draggable.helperProportions = draggable.helperProportionsBBox;
}
if (droppable.proportions && !droppable.proportions().width && !droppable.proportions().height)
if (typeof $(droppable.element).get(0).getBBox === "function") {
droppable.proportionsBBox = droppable.proportionsBBox || $(droppable.element).get(0).getBBox();
droppable.proportions = function () {
return droppable.proportionsBBox;
};
}
return $.ui.intersect_o(draggable, droppable, toleranceMode, event);
};
If you want to restrict the drop on svg elements to hit on visible content only (for example in polygons) you might want to use this addition to Peter Baumann's suggestion:
$.ui.intersect_o = $.ui.intersect;
$.ui.intersect = function (draggable, droppable, toleranceMode, event) {
//Fix helper
if (draggable.helperProportions && draggable.helperProportions.width === 0 && draggable.helperProportions.height === 0) {
draggable.helperProportionsBBox = draggable.helperProportionsBBox || $(draggable.element).get(0).getBBox();
draggable.helperProportions = draggable.helperProportionsBBox;
}
if (droppable.proportions && !droppable.proportions().width && !droppable.proportions().height)
if (typeof $(droppable.element).get(0).getBBox === "function") {
droppable.proportionsBBox = droppable.proportionsBBox || $(droppable.element).get(0).getBBox();
droppable.proportions = function () {
return droppable.proportionsBBox;
};
}
var intersect = $.ui.intersect_o(draggable, droppable, toleranceMode, event);
if (intersect) {
var dropTarget = $(droppable.element).get(0);
if (dropTarget.ownerSVGElement && (typeof (dropTarget.isPointInFill) === 'function') && (typeof (dropTarget.isPointInStroke) === 'function')) {
var x = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left + draggable.helperProportions.width / 2,
y = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top + draggable.helperProportions.height / 2,
p = dropTarget.ownerSVGElement.createSVGPoint();
p.x = x;
p.y = y;
p = p.matrixTransform(dropTarget.getScreenCTM().inverse());
if(!(dropTarget.isPointInFill(p) || dropTarget.isPointInStroke(p)))
intersect = false;
}
}
return intersect;
};
In case if anyone has the same question in mind, droppable doesn't work in jquery SVG. So in the end, I did the following to create my own droppable event:
In draggable, set the target currently dragged been dragged to draggedObj ,
In the mouse up event, check if the draggedObj is null, if it's not null, then drop the item according to the current position. ( let me know if you need help on detecting the current position)