Unable to run the following js code in IE11 or IE9 - javascript

I've made a simple html page with some js code, i've used all vanilla JS and checked to be using all compatibile functions with IE.
The issue is that the following page runs in Google Chrome as it have to, while in IE it's not working, i've tryed in IE11 and IE9 and it's not working in both.
The code is just adding click event to three buttons, button + / - which change the quantity inside the input and the confirm button.
The js looks like this:
<script>
const btns = document.querySelectorAll('.btn-qty');
const confirms = document.querySelectorAll('.btn-success');
const inputs = document.querySelectorAll('.qty')
confirms.forEach(function(confirm) {
confirm.addEventListener('click', confirmHandler);
});
function confirmHandler(event) {
event.preventDefault();
let product_id = this.getAttribute("data-product-id");
let option_id = this.getAttribute("data-option-id");
let iva = parseInt(this.getAttribute("data-iva"));
let price = this.getAttribute("data-price");
let qty = this.getAttribute("data-qty");
window.location.href = "_?productId=" + product_id + "&optionId=" + option_id + "&iva=" + iva + "&price=" + price + "&qty=" + qty
}
inputs.forEach(function(input) {
input.addEventListener('change', function(event) {
event.preventDefault();
let btn = input.parentNode.querySelector(".input-group-prepend").querySelector('.btn-qty');
let confirm = input.parentNode.parentNode.querySelector('.btn-success')
let curVal = parseInt(input.value)
confirm.setAttribute('data-qty', curVal)
if (curVal >= 1) {
btn.removeAttribute('disabled');
}else if(curVal <= 1){
btn.setAttribute('disabled', true);
}
});
});
btns.forEach(function(btn) {
btn.addEventListener('click', function(event) {
event.preventDefault();
let input = btn.parentNode.parentNode.querySelector('.qty')
let curVal = parseInt(input.value)
let type = btn.getAttribute("data-type");
if (type == 'minus') {
if (curVal > 1) {
input.value = curVal - 1
input.dispatchEvent(new Event('change'));
}
if (parseInt(input.value) == 1) {
btn.setAttribute('disabled', true)
}
}else if (type == 'plus'){
input.value = curVal + 1
input.dispatchEvent(new Event('change'));
}
});
});
</script>
Here is the same code run on Chrome (top) and IE11 (bottom)
Here is a JSfiddle of the code

I agree with Ivar's suggestion. We need to add polyfill for forEach in IE, then it can work with NodeList and HTMLCollection in IE. Please add the following polyfill:
var ctors = [typeof NodeList !== "undefined" && NodeList, typeof HTMLCollection !== "undefined" && HTMLCollection];
for (var n = 0; n < ctors.length; ++n) {
var ctor = ctors[n];
if (ctor && ctor.prototype && !ctor.prototype.forEach) {
ctor.prototype.forEach = Array.prototype.forEach;
if (typeof Symbol !== "undefined" && Symbol.iterator && !ctor.prototype[Symbol.iterator]) {
Object.defineProperty(ctor.prototype, Symbol.iterator, {
value: Array.prototype[Symbol.itereator],
writable: true,
configurable: true
});
}
}
}
Besides, there's another error in this line in IE:
input.dispatchEvent(new Event('change'));
You need to use the following codes to use dispatchEvent in IE:
var event = document.createEvent("Event");
event.initEvent("change", false, true);
input.dispatchEvent(event);

Related

java script load issue with ng build --prod

my javascript file for multiple email(multiple_emails.js plugin) is working fine with ng serve my code :
(function( $ ){
$.fn.multiple_emails = function(options) {
// Default options
var defaults = {
checkDupEmail: true,
theme: "Bootstrap",
position: "top",
invalid:"Invalid Email Id"
};
// Merge send options with defaults
var settings = $.extend( {}, defaults, options );
var deleteIconHTML = "";
if (settings.theme.toLowerCase() == "Bootstrap".toLowerCase())
{
deleteIconHTML = '<span class="glyphicon glyphicon-remove"></span>';
}
else if (settings.theme.toLowerCase() == "SemanticUI".toLowerCase() || settings.theme.toLowerCase() == "Semantic-UI".toLowerCase() || settings.theme.toLowerCase() == "Semantic UI".toLowerCase()) {
deleteIconHTML = '<i class="remove icon"></i>';
}
else if (settings.theme.toLowerCase() == "Basic".toLowerCase()) {
//Default which you should use if you don't use Bootstrap, SemanticUI, or other CSS frameworks
deleteIconHTML = '<i class="basicdeleteicon">Remove</i>';
}
return this.each(function() {
var to_id = this.id;
var orig_id=to_id;
console.log(to_id);
var arr = to_id.split('_');
to_id = arr[1];
console.log("to_id",to_id);
setTimeout(function(){
console.log($('.licls'+to_id).length);
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
},200);
//$orig refers to the input HTML node
var $orig = $(this);
var $list = $('<ul class="multiple_emails-ul" id=ul_'+to_id+' />'); // create html elements - list of email addresses as unordered list
console.log($(this).val());
if ($(this).val() != '' && IsJsonString($(this).val())) {
$.each(jQuery.parseJSON($(this).val()), function( index, val ) {
$list.append($('<li class="multiple_emails-email licls'+to_id+'"><span class="email_name" data-email="' + val.toLowerCase() + '">' + val + '</span></li>')
.prepend($(deleteIconHTML)
.click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); })
)
);
});
}
var $input = $('<input type="text" class="multiple_emails-input text-left" id= input_'+to_id+' />').on('keyup', function(e) { // input
console.log($(this).attr('id'));
$(this).removeClass('multiple_emails-error');
$('#'+orig_id).parent().find("label").remove();
var input_length = $(this).val().length;
var keynum;
if(window.event){ // IE
keynum = e.keyCode;
}
else if(e.which){ // Netscape/Firefox/Opera
keynum = e.which;
}
//if(event.which == 8 && input_length == 0) { $list.find('li').last().remove(); } //Removes last item on backspace with no input
// Supported key press is tab, enter, space or comma, there is no support for semi-colon since the keyCode differs in various browsers
if(keynum == 9 || keynum == 32 || keynum == 188) {
display_email($(this), settings.checkDupEmail);
}
else if (keynum == 13) {
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
display_email($(this), settings.checkDupEmail);
//Prevents enter key default
//This is to prevent the form from submitting with the submit button
//when you press enter in the email textbox
e.preventDefault();
}
}).on('blur', function(event){
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
$('#'+orig_id).parent().find("label").remove();
if ($(this).val() != '') { display_email($(this), settings.checkDupEmail); }
});
var $container = $('<div class="multiple_emails-container contnr_'+to_id+'" />').click(function() { $input.focus(); } ); // container div
// insert elements into DOM
if (settings.position.toLowerCase() === "top")
$container.append($list).append($input).insertAfter($(this));
else
$container.append($input).append($list).insertBefore($(this));
/*
t is the text input device.
Value of the input could be a long line of copy-pasted emails, not just a single email.
As such, the string is tokenized, with each token validated individually.
If the dupEmailCheck variable is set to true, scans for duplicate emails, and invalidates input if found.
Otherwise allows emails to have duplicated values if false.
*/
function display_email(t, dupEmailCheck) {
console.log(t.attr('id'));
//Remove space, comma and semi-colon from beginning and end of string
//Does not remove inside the string as the email will need to be tokenized using space, comma and semi-colon
var arr = t.val().trim().replace(/^,|,$/g , '').replace(/^;|;$/g , '');
//Remove the double quote
arr = arr.replace(/"/g,"");
//Split the string into an array, with the space, comma, and semi-colon as the separator
arr = arr.split(/[\s,;]+/);
var errorEmails = new Array(); //New array to contain the errors
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
for (var i = 0; i < arr.length; i++) {
var res_arr=JSON.parse($orig.val().toLowerCase().split(','))
//Check if the email is already added, only if dupEmailCheck is set to true
if ( dupEmailCheck === true && res_arr.indexOf(arr[i].toLowerCase()) != -1) {
if (arr[i] && arr[i].length > 0) {
new function () {
var existingElement = $list.find('.email_name[data-email=' + arr[i].toLowerCase().replace('.', '\\.').replace('#', '\\#') + ']');
existingElement.css('font-weight', 'bold');
setTimeout(function() { existingElement.css('font-weight', ''); }, 1500);
}(); // Use a IIFE function to create a new scope so existingElement won't be overriden
}
}
else if ( pattern.test(arr[i]) == true && res_arr.indexOf(arr[i].toLowerCase()) == -1) {
if($('#ulcls'+t.attr('id')).length < 4) {
$list.append($('<li class="multiple_emails-email licls'+to_id+'"><span class="email_name" data-email="' + arr[i].toLowerCase() + '">' + arr[i] + '</span></li>')
.prepend($(deleteIconHTML)
.click(function(e) { $(this).parent().remove(); refresh_emails(); e.preventDefault(); })
)
);
}
}
else
errorEmails.push(arr[i]);
}
// If erroneous emails found, or if duplicate email found
if(errorEmails.length > 0) {
t.val(errorEmails.join("; ")).addClass('multiple_emails-error');
t.after('<label for='+orig_id+' style="color:#cc5965;">'+settings.invalid+'</label>');
}else {
$('#'+orig_id).parent().find("label").remove();
t.val("");
}
refresh_emails ();
}
function refresh_emails () {
var emails = new Array();
var container = $orig.siblings('.multiple_emails-container');
container.find('.multiple_emails-email span.email_name').each(function() { emails.push($(this).html()); });
$orig.val(JSON.stringify(emails)).trigger('change');
if($('.licls'+to_id).length > 4){
$('#input_'+to_id).css('display','none');
}else {
$('#input_'+to_id).css('display','block');
}
}
function IsJsonString(str) {
try { JSON.parse(str); }
catch (e) { return false; }
return true;
}
$(document).ready(function(){
$('#input_'+to_id).on("cut copy paste",function(e) {
e.preventDefault();
});
});
return $(this).hide();
});
};
})(jQuery);
But when i compile it with ng build --prod it's gives TypeError: $(...).multiple_emails is not a function , if it's not working correctly any other tool to convert from JavaScript to typescript ?
i had convert js into typesript using online compiler but nothing happened.
solved!!!!
finally i figure out the problem. it is in angular-cli.json.when i place my multiple_email.js after jquery-3.1.1.min.js,jquery.validate.min.js then it works like charm...!!! #rajesh thanks

Advancing Stage in jQuery

I have the following code, I'm relatively new to JavaScript, so can anyone tell me why it isn't advancing to stage 1 + show me how it's done?
var textContainer = '#text';
var inputLine = 'input';
var username = null;
var stage = 0;
$(function(){
if(0 == stage){
$(function(){
$(textContainer).text('What is your name?');
$(inputLine).focus();
$(inputLine).keypress(function(e){
if (e.keyCode == 13 && !e.shiftKey) {
e.preventDefault();
username = $(this).val();
$(this).val('');
stage = 1;
}
});
});
}
if(1 == stage){
$(textContainer).text('Hi there, ' + username + '.');
}
});
What you have there doesn't make much sense, so I'm guessing this is what you're trying to do :
$(function(){
var textContainer = $('#text'),
inputLine = $('input');
textContainer.text('What is your name?');
inputLine.focus().on('keyup', function(e){
if (e.which === 13) {
e.preventDefault();
textContainer.text('Hi there, ' + this.value + '.');
this.value = "";
}
});
});
FIDDLE
There is no way stage could be anything other than zero right after it's set to zero?
What happens inside the event handler, happens "later", so checking stage after the event handler still gives you ... wait for it .... zero ?

Focus button from javascript withour clicking it

I call
element.focus();
Where element is HTMLInputElement of type=button.
But then the browser clicks the button! That's in mozilla and chrome.
How do i highlight the button with selection, but not initiate the click event?
No .focus() doesn't click the button or submits the form: http://jsbin.com/onirac/1/edit
It does exactly what you want it to.
Well, i've identified the reason.
I was handling the onkeydown event for Enter key.
The solution is to use
e.preventDefault();
function ConvertEnterToTab(s, e, numSkipElements) {
var keyCode = e.keyCode || e.htmlEvent.keyCode;
if (keyCode === 13) {
var tabIndex = s.tabIndex || s.inputElement.tabIndex;
if (numSkipElements == undefined) {
numSkipElements = 0;
}
var nextElement = FindNextElementByTabIndex(tabIndex + numSkipElements);
if (nextElement != undefined) {
nextElement.focus();
return e.preventDefault ? e.preventDefault() : e.htmlEvent.preventDefault(); // this is the solution
}
}
}
function FindNextElementByTabIndex(currentTabIndex, maxTabIndex) {
if (maxTabIndex == undefined) {
maxTabIndex = 100;
}
var tempIndex = currentTabIndex + 1;
while (!$('[tabindex='+ tempIndex+ ']')[0] || tempIndex === maxTabIndex) {
tempIndex++;
}
return $('[tabindex=' + tempIndex + ']')[0];
}

Switch between two textareas only when pressing Tab button

Normally when a user is visiting a web page and pressing TAB button on a keyboard, the selection moves from one element to another starting from the begining of the page.
I am looking for a solution to switch between two particular text areas by pressing TAB button on a keyboard with an initial focus on the first one when web page is loaded? All other elements on the page have to be ignored for this TAB key press event.
How can I achive this?
Thanx for your help!
= Update =
I have managed to make it work under Firefox 12.0 . IE and Chrome do not work properly. Asuming the text area IDs are #ICCID and #MSISDN, the Jquery looks like this:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$(document).ready(function() {
$("#ICCID").focus();
});
var $inp = $('.cls');
$inp.bind('keydown', function(e) {
var key = e.which;
if (key == 9) {
e.preventDefault();
var nxtIdx = $inp.index(this) + 1;
$(".cls:eq(" + nxtIdx + ")").focus();
//Simulate Enter after TAB
var textInput = $("#MSISDN").val();
var lines = textInput .split(/\r|\r\n|\n/);
if (lines > 1) {
$("#MSISDN").on("keypress", function(e) {
if (e.keyCode == 9) {
var input = $(this);
var inputVal = input.val();
setTimeout(function() {
input.val(inputVal.substring(0,inputVal.length) + "\n");
}, 1);
}
});
}
}
if (key == 9) {
e.preventDefault();
var nxtIdx = $inp.index(this) - 1;
$(".cls:eq(" + nxtIdx + ")").focus();
//Simulate Enter after TAB
$("#ICCID").on("keypress", function(e) {
if (e.keyCode == 9) {
var input = $(this);
var inputVal = input.val();
setTimeout(function() {
input.val(inputVal.substring(0,inputVal.length) + "\n");
}, 1);
}
});
}
});
});
</script>
Catch the keydown action using jQuery, determine which textarea has focus, and then use the focus() method to set the focus to the other textarea.
Supposing that your textareas have id="textarea1" and id="textarea2". First you can set focus to the first textarea when the page loads by doing : $('#textarea1').focus();
$("body").keypress(function(e) {
var code = (e.keyCode ? e.keyCode : e.which);
switch(code)
{
case 9:
if($("#textarea1").focus()){
//First one has focus, change to second one
$("#textarea2").focus();
}
else if($("#textarea2").focus()) {
//Second one has focus, change to first one
$("#textarea1").focus();
}
}
});
Ok I have found the solution for for my task! It also includes the simulation of ENTER key just after the TAB key event, so user do not need to hit ENTER to go to the new line. Tested with IE9, FF12, Chrome 18.0.x
Here it is:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<!-- Switching between ICCIDs and MSISDNs textareas + simulating ENTER key pressing after the TAB key event - START -->
<script type="text/javascript">
$(function() {
$(document).ready(function() {
$("#ICCID").focus();
});
var $inp = $('.cls');
$inp.bind('keydown', function(e) {
var key = e.which;
if (key == 9) {
e.preventDefault();
var nxtIdx = $inp.index(this) + 1;
$(".cls:eq(" + nxtIdx + ")").focus();
//Simulate Enter after TAB
var textInput = $("#MSISDN").val();
var lines = textInput .split(/\r|\r\n|\n/);
if (lines > 1) {
$("#MSISDN").on("keyup", function(e) {
if (e.keyCode == 9 || e.which == 9) {
var input = $(this);
var inputVal = input.val();
setTimeout(function() {
input.val(inputVal.substring(0,inputVal.length) + "\r\n");
}, 1);
}
});
}
}
if (key == 9) {
e.preventDefault();
var nxtIdx = $inp.index(this) - 1;
$(".cls:eq(" + nxtIdx + ")").focus();
//Simulate Enter after TAB
$("#ICCID").on("keyup", function(e) {
if (e.keyCode == 9 || e.which == 9) {
var input = $(this);
var inputVal = input.val();
setTimeout(function() {
input.val(inputVal.substring(0,inputVal.length) + "\r\n");
}, 1);
}
});
}
});
});
</script>
<!-- Switching between ICCIDs and MSISDNs textareas + simulating ENTER key pressing after the TAB key event - END -->
What about this.... Im to bored at work i think..
http://jsbin.com/uqalej/3/
HTML:
<input/>
<textarea id="t1"></textarea>
<textarea id="t2"></textarea>
<input/>
<button onClick='window.toggleBetween=true;'>Init</button>
<button onClick='window.toggleBetween=false;'>Destroy</button>
JS:
var d = document,
t1 = d.getElementById("t1"),
t2 = d.getElementById("t2"),
nodeType, nodeTypes = [],
i, iLen,
y, yLen;
nodeTypes.push( d.getElementsByTagName("textarea") );
nodeTypes.push( d.getElementsByTagName("input") );
nodeTypes.push( d.getElementsByTagName("select") );
i = 0;
iLen = nodeTypes.length;
for ( ; i < iLen; i++ ) {
nodeType = nodeTypes[i];
y = 0;
yLen = nodeType.length;
for ( ; y < yLen; y++ ) {
if ( nodeType[y] != t1 && nodeType[y] != t2 ) {
nodeType[y].onfocus = function() {
if ( window.toggleBetween )
t1.focus();
};
}
}
}
Using javascript on page load:
document.getElementById("textarea1").focus();
document.getElementById('textarea1').tabIndex="1";
document.getElementById('textarea2').tabIndex="2";

Getting Deleted character

in in Input field, if the user presses Backspace or Delete key, is there a way to get the deleted character.
I need to check it against a RegExp.
Assuming the input box has an id 'input'. Here is how with least amount of code you can find out the last character from the input box.
document.getElementById("input").onkeydown = function(evt) {
const t = evt.target;
if (evt.keyCode === 8) { // for backspace key
console.log(t.value[t.selectionStart - 1]);
} else if (evt.keyCode === 46) { // for delete key
console.log(t.value[t.selectionStart]);
}
};
<input id="input" />
The following will work in all major browsers for text <input> elements. It shouldn't be used for <textarea> elements because the getInputSelection function doesn't account for line breaks correctly in IE. See this answer for a (longer) function that will do this.
function getInputSelection(input) {
var start = 0, end = 0;
input.focus();
if ( typeof input.selectionStart == "number" &&
typeof input.selectionEnd == "number") {
start = input.selectionStart;
end = input.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
if (range) {
var inputRange = input.createTextRange();
var workingRange = inputRange.duplicate();
var bookmark = range.getBookmark();
inputRange.moveToBookmark(bookmark);
workingRange.setEndPoint("EndToEnd", inputRange);
end = workingRange.text.length;
workingRange.setEndPoint("EndToStart", inputRange);
start = workingRange.text.length;
}
}
return {
start: start,
end: end,
length: end - start
};
}
document.getElementById("aTextBox").onkeydown = function(evt) {
evt = evt || window.event;
var keyCode = evt.keyCode;
var deleteKey = (keyCode == 46), backspaceKey = (keyCode == 8);
var sel, deletedText, val;
if (deleteKey || backspaceKey) {
val = this.value;
sel = getInputSelection(this);
if (sel.length) {
deletedText = val.slice(sel.start, sel.end);
} else {
deletedText = val.charAt(deleteKey ? sel.start : sel.start - 1);
}
alert("About to be deleted: " + deletedText);
}
};
No, there is no variable that stores the deleted char. Unless you have a history for Undo/Redo, but it would be difficult to get the information out of that component.
Easiest would be to compare the contents of the input field before and after delete/backspace have been pressed.
You could try something with the caret position:
function getCaretPosition(control){
var position = {};
if (control.selectionStart && control.selectionEnd){
position.start = control.selectionStart;
position.end = control.selectionEnd;
} else {
var range = document.selection.createRange();
position.start = (range.offsetLeft - 1) / 7;
position.end = position.start + (range.text.length);
}
position.length = position.end - position.start;
return position;
}
document.getElementById('test').​​​​onkeydown = function(e){
var selection = getCaretPosition(this);
var val = this.value;
if((e.keyCode==8 || e.keyCode==46) && selection.start!==selection.end){
alert(val.substr(selection.start, selection.length));
} else if(e.keyCode==8){
alert(val.substr(selection.start-1, 1));
} else if(e.keyCode==46){
alert(val.substr(selection.start, 1));
}
}​
Tested on Chrome 6. See jsFiddle for an example

Categories