I have tried following code for make the required field to notify the required field but its not working in safari browser.
Code:
<form action="" method="POST">
<input required />Your name:
<br />
<input type="submit" />
</form>
Above the code work in firefox. http://jsfiddle.net/X8UXQ/179/
Can you let me know the javascript code or any workarround? am new in javascript
Thanks
Safari, up to version 10.1 from Mar 26, 2017, doesn't support this attribute, you need to use JavaScript.
This page contains a hacky solution, that should add the desired functionality: http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/#toc-safari
HTML:
<form action="" method="post" id="formID">
<label>Your name: <input required></label><br>
<label>Your age: <input required></label><br>
<input type="submit">
</form>
JavaScript:
var form = document.getElementById('formID'); // form has to have ID: <form id="formID">
form.noValidate = true;
form.addEventListener('submit', function(event) { // listen for form submitting
if (!event.target.checkValidity()) {
event.preventDefault(); // dismiss the default functionality
alert('Please, fill the form'); // error message
}
}, false);
You can replace the alert with some kind of less ugly warning, like show a DIV with error message:
document.getElementById('errorMessageDiv').classList.remove("hidden");
and in CSS:
.hidden {
display: none;
}
and in HTML:
<div id="errorMessageDiv" class="hidden">Please, fill the form.</div>
The only drawback to this approach is it doesn't handle the exact input that needs to be filled. It would require a loop accross all inputs in the form and checking the value (and better, check for "required" attribute presence).
The loop may look like this:
var elems = form.querySelectorAll("input,textarea,select");
for (var i = 0; i < elems.length; i++) {
if (elems[i].required && elems[i].value.length === 0) {
alert('Please, fill the form'); // error message
break; // show error message only once
}
}
If you go with jQuery then below code is much better. Just put this code bottom of the jquery.min.js file and it works for each and every form.
Just put this code on your common .js file and embed after this file jquery.js or jquery.min.js
$("form").submit(function(e) {
var ref = $(this).find("[required]");
$(ref).each(function(){
if ( $(this).val() == '' )
{
alert("Required field should not be blank.");
$(this).focus();
e.preventDefault();
return false;
}
}); return true;
});
This code work with those browser which does not support required (html5) attribute
Have a nice coding day friends.
I had the same problem with Safari and I can only beg you all to take a look at Webshim!
I found the solutions for this question and for this one very very useful, but if you want to "simulate" the native HTML5 input validation for Safari, Webshim saves you a lot of time.
Webshim delivers some "upgrades" for Safari and helps it to handle things like the HMTL5 datepicker or the form validation. It's not just easy to implement but also looks good enough to just use it right away.
Also useful answer on SO for initial set up for webshim here! Copy of the linked post:
At this time, Safari doesn't support the "required" input attribute. http://caniuse.com/#search=required
To use the 'required' attribute on Safari, You can use 'webshim'
1 - Download webshim
2 - Put this code :
<head>
<script src="js/jquery.js"></script>
<script src="js-webshim/minified/polyfiller.js"></script>
<script>
webshim.activeLang('en');
webshims.polyfill('forms');
webshims.cfg.no$Switch = true;
</script>
</head>
I have built a solution on top of #Roni 's one.
It seems Webshim is deprecating as it won't be compatible with jquery 3.0.
It is important to understand that Safari does validate the required attribute. The difference is what it does with it. Instead of blocking the submission and show up an error message tooltip next to the input, it simply let the form flow continues.
That being said, the checkValidity() is implemented in Safari and does returns us false if a required filed is not fulfilled.
So, in order to "fix it" and also show an error message with minimal intervention (no extra Div's for holding error messages) and no extra library (except jQuery, but I am sure it can be done in plain javascript)., I got this little hack using the placeholder to show standard error messages.
$("form").submit(function(e) {
if (!e.target.checkValidity()) {
console.log("I am Safari"); // Safari continues with form regardless of checkValidity being false
e.preventDefault(); // dismiss the default functionality
$('#yourFormId :input:visible[required="required"]').each(function () {
if (!this.validity.valid) {
$(this).focus();
$(this).attr("placeholder", this.validationMessage).addClass('placeholderError');
$(this).val(''); // clear value so it shows error message on Placeholder.
return false;
}
});
return; // its invalid, don't continue with submission
}
e.preventDefault(); // have to add it again as Chrome, Firefox will never see above
}
I found a great blog entry with a solution to this problem. It solves it in a way that I am more comfortable with and gives a better user experience than the other suggestions here. It will change the background color of the fields to denote if the input is valid or not.
CSS:
/* .invalid class prevents CSS from automatically applying */
.invalid input:required:invalid {
background: #BE4C54;
}
.invalid textarea:required:invalid {
background: #BE4C54;
}
.invalid select:required:invalid {
background: #BE4C54;
}
/* Mark valid inputs during .invalid state */
.invalid input:required:valid {
background: #17D654 ;
}
.invalid textarea:required:valid {
background: #17D654 ;
}
.invalid select:required:valid {
background: #17D654 ;
}
JS:
$(function () {
if (hasHtml5Validation()) {
$('.validate-form').submit(function (e) {
if (!this.checkValidity()) {
// Prevent default stops form from firing
e.preventDefault();
$(this).addClass('invalid');
$('#status').html('invalid');
}
else {
$(this).removeClass('invalid');
$('#status').html('submitted');
}
});
}
});
function hasHtml5Validation () {
return typeof document.createElement('input').checkValidity === 'function';
}
Credit: http://blueashes.com/2013/web-development/html5-form-validation-fallback/
(Note: I did extend the CSS from the post to cover textarea and select fields)
I use this solution and works fine
$('#idForm').click(function(e) {
e.preventDefault();
var sendModalForm = true;
$('[required]').each(function() {
if ($(this).val() == '') {
sendModalForm = false;
alert("Required field should not be blank."); // or $('.error-message').show();
}
});
if (sendModalForm) {
$('#idForm').submit();
}
});
The new Safari 10.1 released Mar 26, 2017, now supports the "required" attribute.
http://caniuse.com/#search=required
You can add this event handler to your form:
// Chrome and Firefox will not submit invalid forms
// so this code is for other browsers only (e.g. Safari).
form.addEventListener('submit', function(event) {
if (!event.target.checkValidity()) {
event.preventDefault();
var inputFields = form.querySelectorAll('input');
for (i=0; i < inputFields.length; i++) {
if (!inputFields[i].validity.valid) {
inputFields[i].focus(); // set cursor to first invalid input field
return false;
}
}
}
}, false);
Within each() function I found all DOM element of text input in the old version of PC Safari, I think this code useful for newer versions on MAC using inputobj['prpertyname'] object to get all properties and values:
$('form').find("[required]").each(function(index, inputobj) {
if (inputobj['required'] == true) { // check all required fields within the form
currentValue = $(this).val();
if (currentValue.length == 0) {
// $.each((inputobj), function(input, obj) { alert(input + ' - ' + obj); }); // uncomment this row to alert names and values of DOM object
var currentName = inputobj['placeholder']; // use for alerts
return false // here is an empty input
}
}
});
function customValidate(){
var flag=true;
var fields = $('#frm-add').find('[required]'); //get required field by form_ID
for (var i=0; i< fields.length;i++){
debugger
if ($(fields[i]).val()==''){
flag = false;
$(fields[i]).focus();
}
}
return flag;
}
if (customValidate()){
// do yor work
}
Related
I have the following list of divs
<div id="multi-picker">
<div id="opt1">
<input type="checkbox"> Option 1
</div>
<div id="opt2">
<input type="checkbox"> Option 2
</div>
etc...
</div>
All working, but I'm not happy with the keyboard navigation. To navigate from opt1 to opt2 I need to press the tab key. Ideally I want to treat the options as a select and navigate with up/down arrow. Can this be done?
Alternatively...
Is there any way to have a multi-select with the options styled with checkboxes to reflect the selection state of each option?
I think you'll need javascript and using a plugin is an easier way to accomplish the task and maintain cross-browser functionality. However, here is a fiddle that, I think, kind of does what you want using just javascript. It defines additional attributes on your select elements and uses an onkeydown function to handle the navigation between the elements.
function keyPressed(e) {
var srcElement = e.target; // get the element that fired the onkeydown function
var dataset = false;
var selectList = false;
var next = "";
var prev = "";
if (srcElement.dataset) { // can we use HTML5 dataset?
dataset = true; // remember for later
// is this an element for which we care
if (srcElement.dataset.selectlist == 'true') {
selectList = true;
}
} else { // can't use HTML5 dataset, use getAttribute
if (srcElement.getAttribute('data-selectlist') == 'true') {
selectList = true;
}
}
// is it a select element and the user pressed either up arrow or down arrow
if (selectList && (e.keyCode == '38' || e.keyCode == '40')) {
// get the next and prev navigation options for this element
if (dataset) {
next = srcElement.dataset.next;
prev = srcElement.dataset.prev;
} else {
next = srcElement.getAttribute('data-next');
prev = srcElement.getAttribute('data-prev');
}
// up arrow was pressed and a prev element is defined
if (e.keyCode == '38' && prev != '') {
document.getElementById(prev).focus();
}
// down arrow was pressed and a next element is defined
if (e.keyCode == '40' && next != '') {
document.getElementById(next).focus();
}
// don't do native processing of the up or down arrow (page scrolling)
e.preventDefault;
}
}
document.onkeydown = keyPressed;
Here is the new html that contains the additional elements:
<div id="multi-picker">
<div id="opt1">
<input id="select1" type="checkbox" data-selectlist="true" data-prev="" data-next="select2"> Option 1
</div>
<div id="opt2">
<input id="select2" type="checkbox" data-selectlist="true" data-prev="select1" data-next=""> Option 2
</div>
</div>
This code is very specific to the problem presented and, though it may solve the problem, it would probably be better to use a general purpose plugin that would allow for more general application across your environment. You may also run into problems related to what your user expects the down and up arrow keys to do versus what you are doing by intercepting them.
In my experience I've run into problems where different browsers and even different end-user platforms present different behavior to the application making implementation consistency spotty. Many of the plugins are designed to eliminate that inconsistency and provide a cleaner, more intuitive interface.
Alternatively... Is there any way to have a multi-select with the options styled with checkboxes to reflect the selection state of each option?
That has multi-browser support? Not really. However, if you're a "It works in Chrome, it ships!" type dev, then you could totally fake a multi select to appear to have checkboxes that reflect the selection state of each option with good ol' CSS.
First our HTML:
<select multiple="multiple">
<option>Hello</option>
<option>World</option>
<option>Hello</option>
<option>World</option>
</select>
Next, dat CSS:
select {
border: none;
}
select:focus {
outline: none;
}
select option:before {
display: inline-block;
content: '';
width: 13px;
height: 13px;
position: relative;
margin-right: 3px;
background-image: url('http://i.imgur.com/5xszy3H.png');
background-position: -40px 0px;
top: 2px;
}
Using generated content, we've now applied our pseudo checkboxes. Let's add that last bit of CSS to give us a proper selected state!
select option:checked:before {
background-position: -40px -40px;
}
Woop.
Here's a fiddle to play around with: http://jsfiddle.net/9tLz6ugz/
In (limited) testing, this seemed to only work in Chrome and FireFox (both latest on OSX). Safari, IE, and Opera ignored the generated content all together. So, while not practical (at least not today), it's somewhat doable!
(Here's another fiddle without the background-image - requires a bit more work to get the look/feel consistent across browsers: http://jsfiddle.net/wpch98tg/ But does demonstrate use of unicode to fake a "checkbox" in a multi-select...)
I don't believe you'll find a way with plain HTML & CSS - this gets too far into customizing the core functionality so a bit of JavaScript should do the trick (I'm also using jQuery to make it slightly easier).
For my test, I used <label> instead of <div> to wrap the checkboxes, but this same idea holds true for divs. I just prefer labels so if JavaScript doesn't load, the checkboxes are still clickable.
<div class="fake-select">
<label for="fs1"><input type="checkbox" id="fs1" name="fs1" />Fake 1</label>
<label for="fs2"><input type="checkbox" id="fs2" name="fs2" />Fake 2</label>
[ ... ]
</div>
Basically, you need to track the user's keypresses and an "active" input. Look for up/down arrow key presses and change the active input based on that (scroll to it, add a class name for styling). I have it also allowing the space bar to check/uncheck the currently active box.
var fs = $(".fake-select"),
items = fs.find('input'),
divs = fs.find('label'),
active = 0;
// Hook keypresses
fs.keydown( function(e){
reCalculate(e);
rePosition();
return false;
});
// Click event for manual changes
items.unbind('click').click(function(e){
var thisInput = $(this),
thisLabel = $(this).parent();
window.active = thisLabel.index();
thisLabel.removeClass("checked");
if (thisInput.is(":checked"))
thisLabel.addClass("checked");
rePosition();
});
// Set new active element based on keypress
// Trigger click event if user hits space bar
function reCalculate(e){
var max = items.length -1,
cur = window.active,
charCode = (typeof e.which == "number" && e.which) ? e.which : e.keyCode;
if (charCode == 38) { // move up
cur--;
cur = (cur <= 0) ? 0 : cur;
}
if (charCode == 40) { // move down
cur++;
cur = (cur >= max) ? max : cur;
}
if (charCode == 32) { // space bar
items.eq(cur).focus().trigger('click');
}
window.active = cur;
}
// Add active class, call scroll function
function rePosition(){
divs.removeClass('active').eq(window.active).addClass('active');
scrollInView();
}
// Scroll the list so the active element is in view
function scrollInView(){
var target = divs.eq(window.active);
if (target.length) {
var top = fs.scrollTop() + target.position().top - fs.height()/2 + target.height()/2
fs.stop().animate({scrollTop: top}, 400);
}
return false;
}
jsFiddle example: http://jsfiddle.net/daCrosby/kqecngv0/13/
Can you use jQuery? This will activate the focus functionality via up/down arrow
function focusOnCheckboxes(locator){
var checkboxes = jQuery(locator).find(':checkbox');
var index = 0;
jQuery(locator).on('keydown', function(e){
if( e.keyCode == 38 ){
if(index > 0){
index = index - 1;
}
checkboxes[index].focus();
}
else if(e.keyCode == 40){
if(index < checkboxes.length - 1){
index = index + 1;
}
else{
index = checkboxes.length - 1;
}
checkboxes[index].focus();
}
else{
//console.log(e.keyCode);
}
});
}
// set the locator
focusOnCheckboxes('body');
I'm trying to find a way to make Safari 7 (tested with version 7.0.2, 7.0.3) respect the autocomplete="off" attributes. No matter what I try, it continues to auto-fill.
This is a problem for one of our admin pages where we set up new users. Our users keep saving over with their own username/password.
Here's an abbreviated version of the form we're using. I've tried renaming the fields to "xxu" and "xxp" but the autofill seems to read the label caption. I've fooled with various different labels but it still somehow triggers the auto-fill.
<form novalidate autocomplete="off">
<div class="control-group">
<label class="control-label">Username</label>
<div class="controls">
<input type="text" name="xxu" autocomplete="off" required="required">
</div>
</div>
<div class="control-group">
<label class="control-label">Username</label>
<div class="controls">
<input type="password" name="xxp" autocomplete="off" required="required">
</div>
</div>
</form>
I found this article on Apple's site that describes this problem. https://discussions.apple.com/message/25080203#25080203
Does anyone know of any other method for disabling auto-fill for a form in Safari 7? (Agh, this is the kind of thing we'd expect from IE)
Thanks for the help.
We had the same problem recently. On top of that, we had a AJAX validation of our form happening onBlur. For some strange reason, this would trigger safari to autofill our email input field again. So every time you fill in the email that you want, Safari would fill in an email that it preferred instead. Making it impossible to go through our form.
Our solution
was to pretty much break Safaris (and Chromes) autofill algorithm.
HTML:
<div class="douchebag_safari">
<input class="js-clear_field" tabindex="-1" name="e-mail" type="email">
<input class="js-clear_field" tabindex="-1" name="Ecom_User_Password" type="password">
</div>
CSS:
.douchebag_safari {
position: fixed;
width: 1px;
left: -50px;
}
.douchebag_safari input {
width: 1%;
}
JS:
$('#form').on('submit', function () {
"use strict";
$('.js-clear_field').attr('disabled', 'disabled');
}
The jist of it is: We put input fields of type email and password with names that will rank higher (or same?) in Safaris autofill algorithm and hide them outside the screen. OnSubmit, the fields will be disabled and will thus be excluded from the POST to our backend.
The downside is that users won't have autocomplete on our form, but we decided that it was worth it in our case.
NOTE (assuming you care): Users with Javascript disabled will still get these fields included in their POSTs. Depending on your setup, you will need to allow these two fields to come through to your backend to prevent errors. Just make sure you don't do anything with these fields for security reasons!
As a bonus, this solved a bug where Chrome (35) assumed the input field above the password field is the username. In our case, it was a number field, giving strange user experience and bugs.
I went with a simplified variation of the douchebag_safari approach that #Skurpi came up with. It's HTML only and goes at the bottom of my form.
<!-- http://stackoverflow.com/questions/22817801/how-to-disable-auto-fill-in-safari-7 -->
<div class="douchebag_safari" style="left: -9999px; position: fixed; width: 1px;">
<input type="password">
</div>
I found a quicker and simple way to avoid the form autocompleting. It works in FF 27, Chrome 36 and Safari 7.0.5 on a Mac. I still have not tested it in other OS.
I simply put a fake field as the first place in my form, no need for label or id and name attributes. I hid it for instance with an inline style and voilà!
<input type="password" style="display: none">
The email and password fields in my form are filled with the values from the database as expected and not getting autocompleted anymore.
To be honest, I don't like this solution either... I would love to find a compatible and standard solution but seems that autocomplete="off" is not working anymore.
Had the same issue and tried the first two HTML / CSS only solutions mentioned.
They did not work for me (or Safari 9.0.3 :) ) so I implemented a solution like this
<div style="overflow: hidden;width: 0px;height: 0px;">
<input id="password" type="password" name="password" />
</div>
on top of the actual form input fields.
Tested on Safari, Firefox (44.0.2) and Chrome (48.0.2564.109) running on OS X El Capitan.
The solutions given above did not work for me. After investigation I could evaluate that Safari's decision to enable autofill relies on the following factors:
Does the "id" attribute of the input contain "name"?
Does the "name" attribute of the input contain "name"?
Does the label of the input contain "name"?
I could then disable Safari's autofill with the following code, that I ended with wrapping it into a jQuery plugin, for convenience:
$(document).ready(function () {
$('input').disableAutoFill();
});
(function($) {
$.fn.disableAutoFill = function() {
"use strict";
var self = {
/**
* Disable autofill for one input
* #param {Object} $input jQuery element
*/
disableAutoFill: function($input) {
if (self.isBrowser('safari')) {
self.alterLabel($input);
self.alterName($input);
self.alterId($input);
}
$input.attr('autocomplete', 'off');
},
/**
* Change input's name
* Make sure Safari wont detect the word "name" in the name attribute
* otherwise Safari will enable autofill
* #param {Object} $input jQuery element
*/
alterName: function ($input) {
$input.attr('data-original-name', $input.attr('name'));
// Find unique name attribute value
var new_name = false;
var iteration = 0;
while (iteration < 10 && !new_name) {
new_name = self.random();
if (self.checkAttributeExists('name', new_name)) {
new_name = false;
}
}
if (new_name) {
$input.attr('name', new_name);
self.setFormSubmitHandler($input);
}
},
/**
* Change input's id
* Make sure Safari wont detect the word "name" in the id attribute
* otherwise Safari will enable autofill
* #param {Object} $input jQuery element
*/
alterId: function ($input) {
$input.attr('data-original-id', $input.attr('id'));
// Find unique id attribute value
var new_id = false;
var iteration = 0;
while (iteration < 10 && !new_id) {
new_id = self.random();
if (self.checkAttributeExists('id', new_id)) {
new_id = false;
}
}
if (new_id) {
$input.attr('id', new_id);
self.setFormSubmitHandler($input);
}
},
/**
* Reset input's name and id to its initial values before submitting the form
* #param {Object} $input jQuery element
*/
setFormSubmitHandler: function ($input) {
var $form = $input.closest('form');
if ($form.length > 0) {
$form.submit(function() {
var id = $input.attr('data-original-id');
if (id) {
$input.attr('id', id);
}
var name = $input.attr('data-original-name');
if (name) {
$input.attr('name', name);
}
});
}
},
/**
* Make sure Safari wont detect the word "name" in the label
* otherwise Safari will enable autofill
* #param {Object} $input jQuery element
*/
alterLabel: function ($input) {
var $label = self.findLabel($input);
if ($label && $label.length > 0) {
var text = $label.text();
var array = text.split('');
text = array.join('<span></span>');
$label.html(text);
}
},
/**
* Find label element of an input
* see http://stackoverflow.com/questions/4844594/jquery-select-the-associated-label-element-of-a-input-field
* #param $input
* #returns {*}
*/
findLabel: function ($input) {
var $label = $('label[for="'+$input.attr('id')+'"]');
if ($label.length > 0) {
return $label;
}
var $parentElem = $input.parent();
var $parentTagName = parentElem.get(0).tagName.toLowerCase();
if ($parentTagName == "label") {
return $parentElem;
}
return null;
},
/**
* Generate a random string
* #returns {string}
*/
random: function () {
var text = '';
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i=0; i < 5; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
},
/**
* Check if there is an existing DOM element with a given attribute matching a given value
* #param {string} attributeName
* #param {string} attributeValue
* #returns {boolean}
*/
checkAttributeExists: function (attributeName, attributeValue) {
return $('['+attributeName+'='+attributeValue+']').length > 0;
},
/**
* Detect current Web browser
* #param {string} browser
* #returns {boolean}
*/
isBrowser: function (browser) {
// http://stackoverflow.com/questions/5899783/detect-safari-using-jquery
var is_chrome = navigator.userAgent.indexOf('Chrome') > -1;
var is_explorer = navigator.userAgent.indexOf('MSIE') > -1;
var is_firefox = navigator.userAgent.indexOf('Firefox') > -1;
var is_safari = navigator.userAgent.indexOf("Safari") > -1;
var is_opera = navigator.userAgent.toLowerCase().indexOf("op") > -1;
if ((is_chrome)&&(is_safari)) {is_safari=false;}
if ((is_chrome)&&(is_opera)) {is_chrome=false;}
if (browser === 'chrome') {
return is_chrome;
}
if (browser === 'explorer') {
return is_explorer;
}
if (browser === 'firefox') {
return is_firefox;
}
if (browser === 'safari') {
return is_safari;
}
if (browser === 'opera') {
return is_opera;
}
return false;
}
};
self.disableAutoFill(this);
return this;
};
}(jQuery));
You can also download or check out the file here
I used a random number and incorporated it into each field name so that the browser never recognized the name of the field.
I've adopted a simpler solution which suits us where there are admins maintaining user accounts and occasionally setting their password, and that is simply to change the user's password input type to be:
<input type="text" name="password" />
Simple but effective.
You can try this:
If you're able to use JavaScript and jQuery, you can place this on load of the html (body onload):
$('#theform input').val('');
This question is similar like this: Is autocomplete="off" compatible with all modern browsers?
There are browsers that no longer supports autocomplete="off"
You can use this javascript code:
if (document.getElementsByTagName) {
var inputElements = document.getElementsByTagName(“input”);
for (i=0; inputElements[i]; i++) {
if (inputElements[i].className && (inputElements[i].className.indexOf(“disableAutoComplete”) != -1)) {
inputElements[i].setAttribute(“autocomplete”,”off”);
}
}
}
I tried everything, got it working, and then a later version of Safari broke my website again. I am about to try the extra form fields (thanks Skurpi). In the mean time, here is my new solution (in PHP)
if(strpos($_SERVER['HTTP_USER_AGENT'],'Safari') !== false)
{
?>
<div style="background:#ffff66;border:1px solid #ff9900;font-size:1.5em;padding:1em;">
The Safari browser has a known bug: autocomplete replaces required data in our form with incorrect values. Unfortunately this may prevent you from adding products to the shopping cart. <br /><br />Please try a different browser or go to your browser settings and turn off autocomplete and refresh the page.
</div>
<?php
}
If enough websites do this, maybe the Safari team will get a hint and fix their browser to obey the autocomplete="off" attribute.
<label for="input">Label</label><input type="file" id="input"/>
In Firefox 7 it is not possible to trigger the open file dialog by clicking on the label.
This SO question is very similar but that's green checked with it's a bug in FF. I'm looking for a workaround.
Any ideas?
thank you for this q&a... helped me out.
my variation of #marten-wikstrom's solution:
if($.browser.mozilla) {
$(document).on('click', 'label', function(e) {
if(e.currentTarget === this && e.target.nodeName !== 'INPUT') {
$(this.control).click();
}
});
}
notes
using document.ready ($(function() {...});) is unnecessary, in either solution. jQuery.fn.live takes care of that in #marten-wikstrom's case; explicitly binding to document does in my example.
using jQuery.fn.on... current recommended binding technique.
added the !== 'INPUT' check to ensure execution does not get caught in a loop here:
<label>
<input type="file">
</label>
(since the file field click will bubble back up to the label)
change event.target check to event.currentTarget, allowing for initial click on the <em> in:
<label for="field">click <em>here</em></label>
using the label element's control attribute for cleaner, simpler, spec-base form field association.
I came up with a feasible workaround:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("label").click(function () {
$("#input").click();
});
});
</script>
<label for="input">Label</label><input type="file" id="input"/>
Quite strange that FF allows you to simulate a click on a file input. I thought that was considered a security risk...
UPDATE: This is a generic workaround:
<script type="text/javascript">
$(function () {
if ($.browser.mozilla) {
$("label").live("click", function (event) {
if (event.target == this) {
$("#" + $(this).attr("for")).extend($("input", this)).first().click();
}
});
}
});
</script>
A couple problems arise when using the jQuery browser detection, most notably the anti-pattern of using browser detection rather than feature detection, in addition to the fact that 1.9+ doesn't provide that functionality.
Perhaps, then, the solution I arrived at is a bit hypocritical, but it worked well and seems to adhere to most best practices today.
First, ensure you're using Paul Irish's conditional classes. Then, use something like:
if($("html").hasClass("ie")) {
$("label").click();
} else {
$("input").click();
}
Otherwise, I found the event would be double-fired in browsers such as Chrome. This solution seemed elegant enough.
The file-selection dialog can be triggered in all browsers by the click() event. An unobtrusive solution to this problem could look like that:
$('label')
.attr('for', null)
.click(function() {
$('#input').click();
});
Removing the for attribute is important since other browsers (e.g. Chrome, IE) will still ratify it and show the dialog twice.
I tested it in Chrome 25, Firefox 19 and IE 9 and works like a charm.
It seems to be fixed in FF 23, so browser detection becomes hazardous and leads to double system dialogs ;(
You can add another test to restrict the fix to FF version prior to version 23:
if(parseInt(navigator.buildID,10) < 20130714000000){
//DO THE FIX
}
It's quite ugly, but this fix will be removed as soon as old the version of FF will have disappeared.
A work around when you don't need/want to have the input box (like image upload) is to use opacity: 0 in the element and use pointer-events: none; in the label.
The solution is really design specific but maybe should work for someone who comes to this. (until now the bug doesn't been fixed)
http://codepen.io/octavioamu/pen/ByOQBE
you can dispatch the event from any event to the type=file input if you want
make the input display:none and visibility:hidden, and then dispatch the event from,
say, the click|touch of an image ...
<img id="customImg" src="file.ext"/>
<input id="fileLoader" type="file" style="display:none;visibility:hidden"/>
<script>
customImg.addEventListener(customImg.ontouchstart?'touchstart':'click', function(e){
var evt = document.createEvent('HTMLEvents');
evt.initEvent('click',false,true);
fileLoader.dispatchEvent(evt);
},false);
</script>
Using the answer of Corey above in a React environment I had to do the following:
(Firefox check is based on: How to detect Safari, Chrome, IE, Firefox and Opera browser?)
const ReactFileInputButton = ({ onClick }) => {
const isFirefox = typeof InstallTrigger !== 'undefined';
const handleClick = isFirefox ? (e) => {
e.currentTarget.control.click();
} : undefined;
const handleFileSelect = (e) => {
if (e.target.files && e.target.files[0]) {
onClick({ file: e.target.files[0] });
}
}
return (
<>
<input type="file" id="file" onChange={handleFileSelect} />
<label htmlFor="file" onClick={handleClick}>
Select file
</label>
</>
);
};
Reverse the order of the label and input elements. iow, put the label element after the input element.
Try this code
<img id="uploadPreview" style="width: 100px; height: 100px;"
onclick="document.getElementById('uploadImage').click(event);" />
<input id="uploadImage" type="file" name="myPhoto" onchange="PreviewImage();" />
<script type="text/javascript">
function PreviewImage() {
var oFReader = new FileReader();
oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);
oFReader.onload = function (oFREvent) {
document.getElementById("uploadPreview").src = oFREvent.target.result;
};
};
</script>
I don't know if this is possible but I would like to have an input field where I would have a value that is not editable by the user.
However, I don't want the input field to be "readonly" because I still want the user to be able to add text after the value.
If you have any idea on how to do this, let me know please that would help me a lot.
EDIT: I use html forms.
You can position the text on top of the input field to make it look as if it is inside it. Something like this:
<input type="text" name="year" style="width:3.5em;padding-left:1.5em;font:inherit"><span style="margin-left:-3em;margin-right:10em;">19</span>
This way your input field will start with "19" which can not be edited, and the user can add information behind this.
Basically what you do is set the input field to a fixed width, so that you know how much negative margin-left to give the span with your text in it in order for it to be positioned exactly at the start of the input field.
You might need to fiddle with the margin-left of the span depending on the rest of your css.
Then also adding pedding-left to the input field, to make sure the user starts typing after your text and not under it.
font:inherit should make sure both your text and the text typed by the user are in the same font.
And if you want to put anything to the right of this input field, do add margin-right to the span with your text, as otherwise other content might start running over your input field as well.
seems a little weird to me ..why not just use a text output and afterwards the input field?
like sometimes used for the birthdate (although, maybe not anymore..)
birthyear: 19[input field]
edit:
with some javascript stuff you could realise something like that you asked for, though
an input field with text and catching keystrokes within that field while only allowing some after what you want to be always there - but, well, you would need to use js ..and if its just for that, Id rather say its not necessary
edit:
if you want to use a trick just for the viewer you could use a background-image/border-style that surrounds a text and the input field, thus making it look like text and input are the same input-box.
Sounds like you want placeholder text. In HTML5 you can set the placeholder attribute on any input element. This will work in modern browsers.
<input type="email" placeholder="jappleseed#appletree.com" name="reg_email" />
Now, for older browsers this won't work. You'll need a JavaScript alternative to provide the same UI value.
This can work for all browsers:
<input type="text" value="Search" onfocus="if (this.value == 'Search') {this.value = '';}" onblur="if (this.value == '') {this.value = 'Search';}">
but it's not recommended because there is a better way (really, it's a combination of the first two approaches): Use HTML5 markup for new browsers; jQuery and modernizr for old browsers. This way you can have only one set of code that will support all user cases.
Taken directly from webdesignerwall.com:
<script src="jquery.js"></script>
<script src="modernizr.js"></script>
<script>
$(document).ready(function(){
if(!Modernizr.input.placeholder){
$('[placeholder]').focus(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
input.removeClass('placeholder');
}
}).blur(function() {
var input = $(this);
if (input.val() == '' || input.val() == input.attr('placeholder')) {
input.addClass('placeholder');
input.val(input.attr('placeholder'));
}
}).blur();
$('[placeholder]').parents('form').submit(function() {
$(this).find('[placeholder]').each(function() {
var input = $(this);
if (input.val() == input.attr('placeholder')) {
input.val('');
}
})
});
}
</script>
[You'll need both jquery.js and modernizr.js installed in the same folder as your webpage.]
Note: I have a feeling that a little more research might reveal that modernizr isn't needed for this at all, though I could be wrong about that particular point.
Perhaps, then, you want a select menu?
<select name="mySelectMenu">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
Sorry if this isn't what you want either. I'm grasping at straws because what you are asking for is very vague. Maybe you should give an example of what one of these 'editable but not editable' inputs would be used for.
Also, you could use a select and a text input.
The main problem is to determine the position of the cursor. This can be done e.g. using the following function:
function getCaret(el) {
var pos = -1;
if (el.selectionStart) {
pos = el.selectionStart;
}
else if (document.selection) {
el.focus();
var r = document.selection.createRange();
if (r != null) {
var re = el.createTextRange();
var rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
pos = rc.text.length;
}
}
return pos;
}
Now you can install an event handler for the key press and check whether the pressed key was inside the immutable part of the value of the textarea. If it was there the event handler returns false, otherwise true. This behavior can be wrapped into a simple object:
function Input(id, immutableText) {
this.el = document.getElementById(id);
this.el.value = immutableText;
this.immutableText = immutableText;
this.el.onkeypress = keyPress(this);
}
function keyPress(el) {
return function() {
var self = el;
return getCaret(self.el) >= self.immutableText.length;
}
}
Input.prototype.getUserText = function() {
return this.el.value.substring(this.immutableText.length);
};
var input = new Input("ta", "Enter your name: ");
var userText = input.getUserText();
You can check it on jsFiddle (use Firefox or Chrome).
I came up with this:
```
if (e.target.value == '' || e.target.value.length <= 3) {
e.target.value = '+91-';
}
```
There is a common feature of modern browsers where a user can select some text and drag it to an input field. Within the same field it causes moving of text, between different fields it does copying.
How do I disable that? If there is no portable way, I am mostly interested in firefox. This is an intranet webapp, so I am also interested in modifying the browser/getting a plugin to do this. Maybe some system-level settings (I`m on windows XP)?
I need to keep the default select-copy-paste functionality.
The background is I have multiple-field data entry forms, and users often drag something by mistake.
For archival purposes:
<body ondragstart="return false" draggable="false"
ondragenter="event.dataTransfer.dropEffect='none'; event.stopPropagation(); event.preventDefault();"
ondragover="event.dataTransfer.dropEffect='none';event.stopPropagation(); event.preventDefault();"
ondrop="event.dataTransfer.dropEffect='none';event.stopPropagation(); event.preventDefault();"
>
does what I wanted. You can add the ondrag* handlers to form elements, too, like <input ondragenter=...>
reference url: https://developer.mozilla.org/En/DragDrop/Drag_Operations
This thing works.....Try it.
<BODY ondragstart="return false;" ondrop="return false;">
hope it helps. Thanks
This code will work in all versions of Mozilla and IE.
function preventDrag(event)
{
if(event.type=='dragenter' || event.type=='dragover' || //if drag over event -- allows for drop event to be captured, in case default for this is to not allow drag over target
event.type=='drop') //prevent text dragging -- IE and new Mozilla (like Firefox 3.5+)
{
if(event.stopPropagation) //(Mozilla)
{
event.preventDefault();
event.stopPropagation(); //prevent drag operation from bubbling up and causing text to be modified on old Mozilla (before Firefox 3.5, which doesn't have drop event -- this avoids having to capture old dragdrop event)
}
return false; //(IE)
}
}
//attach event listeners after page has loaded
window.onload=function()
{
var myTextInput = document.getElementById('textInput'); //target any DOM element here
if(myTextInput.addEventListener) //(Mozilla)
{
myTextInput.addEventListener('dragenter', handleEvents, true); //precursor for drop event
myTextInput.addEventListener('dragover', handleEvents, true); //precursor for drop event
myTextInput.addEventListener('drop', preventDrag, true);
}
else if (myTextInput.attachEvent) //(IE)
{
myTextInput.attachEvent('ondragenter', preventDrag);
myTextInput.attachEvent('ondragover', preventDrag);
myTextInput.attachEvent('ondrop', preventDrag);
}
}
add the following to your field tags:
#ondragstart is for IE, onmousedown is for firefox
ondragstart="return false" onmousedown="return false"
ondraggesture is supported by older versions of Firefox instead of ondragstart.
Use the following code
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
and:
<input type="text" ondrop="drop(event)" ondragover="allowDrop(event)">
See: http://jsfiddle.net/zLYGF/25/
You can use :focus attribute to recognize over what your mouse is:
if(document.activeElement.tagName == "INPUT"||document.activeElement.tagName == "TEXTAREA"){
event.preventDefault()
return
}