I am getting some strange behaviour within IE which I was hoping someone might be able to explain. I have a simple form with an address lookup input
<form action="http://localhost:8000/processForm" method="post">
<label for="input_1" class="form-control-label col-xs-12">
Postcode
</label>
<div class="col-xs-12">
<div class="input-group">
<input type="text" name="questions[1]" autocomplete="off" id="input_1" class="form-control address" value="" >
<a class="btn btn-xs input-group-addon address-button" id="input_address_addon" role="button" tabindex="0">
<img src="http://localhost:8000/images/glyphicons-243-map-marker.png">
Search
</a>
</div>
<div class="col-xs-12 col-sm-8 col-sm-offset-4 col-md-7">
<select class="form-control selectpicker addSelect" id="input_address_select" style="display: none;">
<option value="">Enter above</option>
</select>
</div>
</div>
<button type="submit" class="btn submit btn-navigation">
Continue
</button>
</form>
The address is entered into the input, then the search button is clicked. This makes a call to an API to return addresses and populate the a select input with them. This all works fine in all browsers, but noticed something strange with IE. This is the Javascript that handles the API call and populating of the select.
!function ($, window) {
$(function () {
init();
});
var getAddresses = function (postcode, callback) {
var $xhr = $.getJSON('/lookupPostcode/' + postcode);
$xhr.done(function (data) {
callback(data);
});
$xhr.error(function () {
callback([]);
})
};
var init = function () {
$("input.address").each(function () {
var $input = $(this);
var $icon = $input.next('.address-button');
var $select = $input.parents('.row').eq(0).find("select");
$select.css("display", "none");
var onKeyUp = function (e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
$icon.trigger("click");
}
};
var onKeyDown = function(e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
}
};
$input.on("keyup", onKeyUp);
$input.on("keydown", onKeyDown);
$icon.on("keyup", onKeyUp);
$icon.on("keydown", onKeyDown);
$select.on("keyup", onKeyUp);
$icon.on("click", function () {
getAddresses($input.val(), function (addresses) {
//populate select options with addresses
});
});
$select.on('change', function (event) {
var ua = window.navigator.userAgent;
var is_ie = /MSIE|Trident/.test(ua);
if ( !is_ie ) {
$select.css("display", "none");
}
/*$select.css("display", "none");*/
});
});
};
}(jQuery, window);
So when an address is selected from the select input, I hide the select input. On IE, this hiding of this element seems to make the form submit. You can see above that I have added some code to check that it is not IE and only hide on these devices, and keeping the select in place on IE works fine. Also, if I put an alert at the top of the change event, this also seems to stop the form submitting in IE.
So I was wondering what may be causing this to submit in IE if I hide the select? I have read that IE does not like buttons to be used as form submits, but not sure if this is the issue?
Is there any way to get the select hiding in IE?
Thanks
So I was wondering what may be causing this to submit in IE if I hide
the select? I have read that IE does not like buttons to be used as
form submits, but not sure if this is the issue?
I can't reproduce your problem, everything works well on my side (IE 11.1.17340.0 version).
Please try to use the following code: (based on your code, please note the part of code with comment)
<head runat="server">
<title></title>
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
!function ($, window) {
$(function () {
init();
});
var getAddresses = function (postcode, callback) {
//var $xhr = $.getJSON('/lookupPostcode/' + postcode);
//$xhr.done(function (data) {
// callback(data);
//});
//$xhr.error(function () {
// callback([]);
//})
//using the following array to populate the select.
var datalist = [{ "ID": "1", "ParentID": "0", "Name": "Parent1" }, { "ID": "2", "ParentID": "0", "Name": "Parent2" },
{ "ID": "3", "ParentID": "1", "Name": "Child 1.1" }, { "ID": "4", "ParentID": "1", "Name": "Child 1.2" },
{ "ID": "5", "ParentID": "3", "Name": "SubChild 1.1.1" }, { "ID": "6", "ParentID": "2", "Name": "Child 2.1" }];
callback(datalist);
};
var init = function () {
$("input.address").each(function () {
var $input = $(this);
var $icon = $input.next('.address-button');
//you are using the .row class to find the select control, but from your form, I can't find this class.
var $select = $input.parents('.row').eq(0).find("select");
//debugger;
$select.css("display", "none");
var onKeyUp = function (e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
$icon.trigger("click");
}
};
var onKeyDown = function (e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
}
};
$input.on("keyup", onKeyUp);
$input.on("keydown", onKeyDown);
$icon.on("keyup", onKeyUp);
$icon.on("keydown", onKeyDown);
$select.on("keyup", onKeyUp);
$icon.on("click", function () {
$select.empty();
$select.append("<option value=''>Enter above</option>");
getAddresses($input.val(), function (addresses) {
//populate select options with addresses
$.each(addresses, function (index, item) {
//debugger;
$select.append("<option value='" + item.ID + "'>" + item.Name + "</option>");
});
$select.css("display", "block");
});
});
$select.on('change', function (event) {
var ua = window.navigator.userAgent;
var is_ie = /MSIE|Trident/.test(ua);
//get the selected text and populate the input text.
$input.val($(this).find("option:selected").text());
//hide the select control
if (!is_ie) {
$select.css("display", "none");
}
$select.css("display", "none");
});
});
};
}(jQuery, window);
</script>
</head>
<body>
<form action="http://localhost:8000/processForm" method="post">
<label for="input_1" class="form-control-label col-xs-12">
Postcode
</label>
<div class="col-xs-12 row">
<div class="input-group">
<input type="text" name="questions[1]" autocomplete="off" id="input_1" class="form-control address" value="" />
<a class="btn btn-xs input-group-addon address-button" id="input_address_addon" role="button" tabindex="0">
<img src="http://i.imgur.com/H9FIags.jpg" style="height:10px;width:10px" />
Search
</a>
</div>
<div class="col-xs-12 col-sm-8 col-sm-offset-4 col-md-7">
<select class="form-control selectpicker addSelect" id="input_address_select" >
<option value="">Enter above</option>
</select>
</div>
</div>
<button type="submit" class="btn submit btn-navigation">
Continue
</button>
</form>
</body>
The output as below:
The reason why your form submits is the fact that you have a button of type "submit" in your form.
<button type="submit"...>
Whenever you press enter, this will cause your form to submit.
You need to change your submit button to another type like "button" and add a Javascript event handler to it (for example onClick="submit()").
<button type="button" class="btn submit btn-navigation" onClick="submit(this.form)">
Continue
</button>
function submit(form){
form.submit();
}
Related
<html>
<form class="form" id="helpForm" enctype='multipart/form-data' novalidate>
<div id="file_div" class="form-group">
<div class="controls">
<input type="file" id="file_upload" class="form-control square" accept="application/pdf" name="file_upload" onchange="return fileValidation()">
<div class="help-block" id="file_error"></div>
</div>
</div>
<button type="submit" class="btn btn-primary" id="form-submit">submit</button>
</form>
</html>
I have written some jquery code to work with it
function fileValidation() {
var fileInput = document.getElementById('file_upload');
var filePath = fileInput.value;
// Allowing file type
var allowedExtensions = /(\.pdf)$/i;
if(fileInput.files[0] == undefined) {
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>Pdf File is required field !</li></ul>');
return false;
} else if (!allowedExtensions.exec(filePath)) {
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>File type is not allowed !</li></ul>');
return false;
} else if (fileInput.files[0].size > 2097152) { //26214400 -25MB
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>File size must under 2MB !</li></ul>');
return false;
} else {
if (event == undefined) {
uploadFile();
}
return true;
}
}
if I do console.log() inside fileValidation() it print everything here.
but why my this code not doing its work?
$('#file_div').removeClass('validate');
$("#file_div").addClass('error');
$('#file_error').css('display','block');
$('#file_error').append('<ul role="alert"><li>Pdf File is required field !</li></ul>');
It work if I call fileValidation() on submit button.
Things to I am using for other validation. and inside this
(function(window, document, $) {
'use strict';
// Input, Select, Textarea validations except submit button
$("input,select,textarea,file").not("[type=submit]").jqBootstrapValidation({
filter: function () {
return $(this).is(":visible");
},
sniffHtml: false,
submitSuccess: function ($form, event) {
event.preventDefault();
fileValidation(); // this is working and doing all
}
});
})(window, document, jQuery);
Can anyone suggest , how I can achieve this on OnChange event?
Thanks
The issue here is $("input,select,textarea,file").not("[type=submit]").jqBootstrapValidation({}); function.
So if anyone help to find why it blocking that onchange function to work?
I am trying to create a javscript method that will allow moving to the next field by hitting the enter key. This mostly works fine, except that when you hit enter to click a button, it creates a new row identical to the previous one (which is normal), but then it doesn't move to the next field straight away. You need to hit tab to go to the next one.
I would really appreciate some help on this, as I cannot get it to move to the next box and go straight to it.
quickAddViewModel.prototype.addItemLine = function() {
var self = this;
var itemLine = {
ItemNumber: ko.observable(''),
ItemQuantity: ko.observable(0),
Error: ko.observable(false)
};
self.itemsToAdd.push(itemLine);
}
ko.bindingHandlers.nextFieldOnEnter = {
init: function(element, valueAccessor, allBindingsAccessor) {
$(element).on('keydown', 'input, select', function(e) {
var self = $(this),
form = $(element),
focusable, next;
if (e.keyCode == 13) {
focusable = form.find('input,a,select,button,textarea').filter(':visible');
var nextIndex = focusable.index(this) == focusable.length - 1 ? 0 : focusable.index(this) + 1;
next = focusable.eq(nextIndex);
next.focus();
this.addItemLine();
return true;
}
});
}
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="row form-group" data-bind="css: { 'has-error': Error() }, nextFieldOnEnter:true">
<div class="col-xs-7">
<input type="text" class="form-control" placeholder="Eg K000_ASAHI" data-bind="itemCodes: ItemNumber, value: ItemNumber, valueUpdate: 'input'">
</div>
<div class="col-xs-3">
<input type="number" class="form-control" placeholder="0" data-bind="numericInput: ItemQuantity, value: ItemQuantity">
</div>
<div class="col-xs-2">
<button type="button" class="icon-circle-minus" data-bind="visible: $index() + 1 < $parent.itemsToAdd().length, click: function() { $parent.removeItemLine($index()) }, clickBubble: false"></button>
<button type="button" class="icon-circle-plus" data-bind="visible: $index() + 1 == $parent.itemsToAdd().length, click: function() { $parent.addItemLine() }"></button>
</div>
</div>
I'm busy with David Turnbull's - Your first Meteor Application. Everything works up to the point where I try and add a new player to the list via a form. My problem is that preventDefault is not preventing the form from trying to submit and reloading the page. return false doesn't work either.
Any ideas why this will be happening?
Thanks
PlayersList = new Mongo.Collection('players');
if (Meteor.isClient) {
//Helpers
Template.leaderboard.helpers({
'player': function() {
return PlayersList.find({}, {sort: {score: -1, name: 1}});
},
'playerCount': function() {
return PlayersList.find().count();
},
'selectedClass': function() {
var playerId = this._id;
var selectedPlayer = Session.get('selectedPlayer');
if(playerId == selectedPlayer) {
return 'selected'
}
},
'showSelectedPlayer': function() {
var selectedPlayer = Session.get('selectedPlayer');
return PlayersList.findOne(selectedPlayer);
}
});
//Events
Template.leaderboard.events({
'click .player': function() {
var playerId = this._id;
Session.set('selectedPlayer', playerId);
},
'click .increment': function() {
var selectedPlayer = Session.get('selectedPlayer');
var increaseBy = document.getElementById('increase-by').value;
var isNumber = /^\d+$/.test(increaseBy);
if(increaseBy != '' && isNumber) {
PlayersList.update(selectedPlayer, {$inc: {score: +increaseBy}});
}
},
'click .decrement': function() {
var selectedPlayer = Session.get('selectedPlayer');
var decreaseBy = document.getElementById('decrease-by').value;
PlayersList.update(selectedPlayer, {$inc: {score: -decreaseBy}});
},
'submit #new-player': function(event) {
event.preventDefault();
var playerNameVar = event.target.playerName.value;
if(playerNameVar != '') {
PlayersList.insert({
name: playerNameVar,
score:0
});
}
}
});
}
Template
<template name="addPlayerForm">
<div id="add-player" class="reveal-modal" data-reveal>
<a class="close-reveal-modal">×</a>
<h2>Add a player</h2>
<p class="lead">Add another player to the leaderboard</p>
<div class="row">
<div class="small-8 column small-centered">
<form id="new-player">
<div class="row collapse">
<div class="small-8 column">
<input type="text" placeholder="Player name" name="playerName">
</div>
<div class="small-4 column">
<input type="submit" class="button postfix" value="add player">
</div>
</div>
</form>
</div>
</div>
</div>
</template>
I've never read the book, and I don't know what your template looks like, but the problem is likely due to a selector issue.
Maybe try assigning an id to your form and mapping the submit event to that id:
// html file
<Template name="leaderboard">
<form id="new-player">
<input type="text" name="playerName">
<input type="submit" value="Submit">
</form>
</Template>
// js file
Template.leaderboard.events({
'submit #new-player': function(event) {
event.preventDefault();
...
}
});
Edit
Maybe try changing Template.leaderboard.events to Template.addPlayerForm.events.
Ok, I made the same mistake as the poster and I am putting the correct code here:
In html file:
<template name="addPlayerForm">
<form>
<input type="text" name="playerName">
<input type="submit" value="Add Player">
</form>
</template>
In js file:
Template.addPlayerForm.events({
'submit form': function(event){
event.preventDefault();
console.log("Form submitted");
console.log(event.type);
}
});
Trying to clear the error messages when the disabled fields are toggled on and off on my form using jquery.validate. Right now I have it working where on change or on click fields are showing and changing the prop from disabled. So it works for what I need which is hiding the fields that are not necessary and not validating them when they are in a disabled state. However, when I toggle these fields back to their disabled state ad hide them, the error messages are still showing until I click submit again. I tried adding the .valid() call to the toggleDisabled function and it does not make the messages disappear when they go back to a hidden/disabled state. Anyone see what can be added to make the messages disappear when the fields do?
Here is the working fiddle with what I have so far:
JS Fiddle
And I am using jquery.validate from :
jQuery.Validate
HTML:
<form id="myform">
<input type="text" name="field1" />
<br/>
<br />
<input type="text" id="toggleInput" name="toggleInputName" disabled style="display:none" />
<input type="button" id="toggleButton" value="Toggle Disabled" />
<div id="tickets">
<label for="group1">Number of Tickets: <span class="req">*</span></label>
<select class="group1_dropdown" id="group1" name="group1">
<option value="0">-- Please select --</option>
<option value="1">Member</option>
<option value="2">Member + 1 Guest</option>
<option value="3">Member + 2 Guests</option>
<option value="4">Member + 3 Guests</option>
</select>
</div>
<input type="text" id="payMethod" name="payMethodName" disabled style="display:none" />
<input type="submit" />
</form>
JS:
$(document).ready(function () {
$('#myform').validate({
onblur: true,
onkeyup: false,
ignore: ":disabled",
rules: {
field1: {
required: true,
minlength: 5
},
payMethodName: {
required: true,
minlength: 5
},
toggleInputName: {
required: true,
minlength: 5
}
},
submitHandler: function (form) { // for demo
alert('valid form');
return false;
}
});
});
//used for toggling/showing disabled fields - will display and make not disabled on same click event
(function ($) {
$.fn.toggleDisabled = function () {
return this.each(function () {
var $this = $(this);
if ($this.prop('disabled')) {
$this.prop('disabled', false).show();
} else {
$this.prop('disabled', true).hide();
}
});
};
})(jQuery);
$(function () {
$('#toggleButton').click(function () {
$('#toggleInput').toggleDisabled();
});
});
$(function () {
$("#group1").change(function () {
var str = "";
str = parseInt($(this).val());
if(str == 2)
$("#payMethod").toggleDisabled();
else
$("#payMethod").toggleDisabled();
});
});
I have changed your plugin a little to do what you want.
Fiddle Demo
(function ($) {
$.fn.toggleDisabled = function () {
return this.each(function () {
var $this = $(this),
id = $this.attr('id'), //get the id of input
label = $this.next('label[for="' + id + '"]'); //find the next label which is added by jQuery Validator
if ($this.prop('disabled')) {
label.show(); //show the label
$this.prop('disabled', false).show();
} else {
label.hide();//hide the label
$this.prop('disabled', true).hide();
}
});
};
})(jQuery);
Update
Another way without changing your plugin
Fiddle Demo
$(document).ready(function () { //place your all DOM ready code in one DOM ready handler
var validator = $('#myform').validate({ //assign validate to a variable
//validator code here
});
$('#toggleButton').click(function () {
validator.resetForm();//reset Form validation
$('#toggleInput').toggleDisabled();
});
});
I have page when I have input and a button.
<div>
<div class="input-group">
<span class="input-group-addon">Enter test</span>
<input type="Text" class="form-control" data-bind="value:Test, event: { keypress: searchKeyboardCmd}" required />
</div>
</div>
<button data-bind=' event:{click:foo}' class="btn btn-default">Submit</button>
and my code:
var ViewModel = function () {
var self = this;
self.Test = ko.observable();
self.data = ko.observableArray([]);
self.DeviceId = ko.observable();
self.number = ko.observable(1);
self.MeUser = ko.observable(true);
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13)
alert("Znalazlem enter " + ko.toJSON(self));
return true;
};
self.foo = function () {
alert("foo");
}
};
ko.applyBindings(new ViewModel());
});
And I have problems with my code. I catch enter with this code:
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13)
alert("Znalazlem enter " + ko.toJSON(self));
return true;
};
It's catches perfectly but binded object is updated after calling alert. So in the first enter I null in value Test. After second enter I have first value and so on. Can anyone suggest me how to modify this code?
The problem is that the event is executed before the blur event (which is when the value is updated. You can make sure the update gets updated after every keystroke by adding valueupdate: 'afterkeydown' to the input:
<div>
<div class="input-group">
<span class="input-group-addon">Enter test</span>
<input type="Text" class="form-control"
data-bind="valueUpdate: 'afterkeydown', value:Test, event: { keypress: searchKeyboardCmd}" required />
</div>
</div>
<button data-bind=' event:{click:foo}' class="btn btn-default">Submit</button>