disable text drag and drop - html

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
}

Related

Sometimes links are not clickable [duplicate]

I have a link button inside a <td> which I have to disable. This works on IE but not working in Firefox and Chrome.
I tried all the following but not working on Firefox (using 1.4.2 js):
$(".myLink").attr('disabled', 'disabled');
$(".myLink").attr('disabled', true);
$(".myLink").attr('disabled', 'true');
Note - I cannot de-register the click function for the anchor tag as it is registered dynamically. AND I HAVE TO SHOW THE LINK IN DISABLED MODE.
You can't disable a link (in a portable way). You can use one of these techniques (each one with its own benefits and disadvantages).
CSS way
This should be the right way (but see later) to do it when most of browsers will support it:
a.disabled {
pointer-events: none;
}
It's what, for example, Bootstrap 3.x does. Currently (2016) it's well supported only by Chrome, FireFox and Opera (19+). Internet Explorer started to support this from version 11 but not for links however it's available in an outer element like:
span.disable-links {
pointer-events: none;
}
With:
<span class="disable-links">...</span>
Workaround
We, probably, need to define a CSS class for pointer-events: none but what if we reuse the disabled attribute instead of a CSS class? Strictly speaking disabled is not supported for <a> but browsers won't complain for unknown attributes. Using the disabled attribute IE will ignore pointer-events but it will honor IE specific disabled attribute; other CSS compliant browsers will ignore unknown disabled attribute and honor pointer-events. Easier to write than to explain:
a[disabled] {
pointer-events: none;
}
Another option for IE 11 is to set display of link elements to block or inline-block:
<a style="pointer-events: none; display: inline-block;" href="#">...</a>
Note that this may be a portable solution if you need to support IE (and you can change your HTML) but...
All this said please note that pointer-events disables only...pointer events. Links will still be navigable through keyboard then you also need to apply one of the other techniques described here.
Focus
In conjunction with above described CSS technique you may use tabindex in a non-standard way to prevent an element to be focused:
...
I never checked its compatibility with many browsers then you may want to test it by yourself before using this. It has the advantage to work without JavaScript. Unfortunately (but obviously) tabindex cannot be changed from CSS.
Intercept clicks
Use a href to a JavaScript function, check for the condition (or the disabled attribute itself) and do nothing in case.
$("td > a").on("click", function(event){
if ($(this).is("[disabled]")) {
event.preventDefault();
}
});
To disable links do this:
$("td > a").attr("disabled", "disabled");
To re-enable them:
$("td > a").removeAttr("disabled");
If you want instead of .is("[disabled]") you may use .attr("disabled") != undefined (jQuery 1.6+ will always return undefined when the attribute is not set) but is() is much more clear (thanks to Dave Stewart for this tip). Please note here I'm using the disabled attribute in a non-standard way, if you care about this then replace attribute with a class and replace .is("[disabled]") with .hasClass("disabled") (adding and removing with addClass() and removeClass()).
Zoltán Tamási noted in a comment that "in some cases the click event is already bound to some "real" function (for example using knockoutjs) In that case the event handler ordering can cause some troubles. Hence I implemented disabled links by binding a return false handler to the link's touchstart, mousedown and keydown events. It has some drawbacks (it will prevent touch scrolling started on the link)" but handling keyboard events also has the benefit to prevent keyboard navigation.
Note that if href isn't cleared it's possible for the user to manually visit that page.
Clear the link
Clear the href attribute. With this code you do not add an event handler but you change the link itself. Use this code to disable links:
$("td > a").each(function() {
this.data("href", this.attr("href"))
.attr("href", "javascript:void(0)")
.attr("disabled", "disabled");
});
And this one to re-enable them:
$("td > a").each(function() {
this.attr("href", this.data("href")).removeAttr("disabled");
});
Personally I do not like this solution very much (if you do not have to do more with disabled links) but it may be more compatible because of various way to follow a link.
Fake click handler
Add/remove an onclick function where you return false, link won't be followed. To disable links:
$("td > a").attr("disabled", "disabled").on("click", function() {
return false;
});
To re-enable them:
$("td > a").removeAttr("disabled").off("click");
I do not think there is a reason to prefer this solution instead of the first one.
Styling
Styling is even more simple, whatever solution you're using to disable the link we did add a disabled attribute so you can use following CSS rule:
a[disabled] {
color: gray;
}
If you're using a class instead of attribute:
a.disabled {
color: gray;
}
If you're using an UI framework you may see that disabled links aren't styled properly. Bootstrap 3.x, for example, handles this scenario and button is correctly styled both with disabled attribute and with .disabled class. If, instead, you're clearing the link (or using one of the others JavaScript techniques) you must also handle styling because an <a> without href is still painted as enabled.
Accessible Rich Internet Applications (ARIA)
Do not forget to also include an attribute aria-disabled="true" together with disabled attribute/class.
Got the fix in css.
td.disabledAnchor a{
pointer-events: none !important;
cursor: default;
color:Gray;
}
Above css when applied to the anchor tag will disable the click event.
For details checkout this link
Thanks to everyone that posted solutions (especially #AdrianoRepetti), I combined multiple approaches to provide some more advanced disabled functionality (and it works cross browser). The code is below (both ES2015 and coffeescript based on your preference).
This provides for multiple levels of defense so that Anchors marked as disable actually behave as such.
Using this approach, you get an anchor that you cannot:
click
tab to and hit return
tabbing to it will move focus to the next focusable element
it is aware if the anchor is subsequently enabled
How to
Include this css, as it is the first line of defense. This assumes the selector you use is a.disabled
a.disabled {
pointer-events: none;
cursor: default;
}
Next, instantiate this class on ready (with optional selector):
new AnchorDisabler()
ES2015 Class
npm install -S key.js
import {Key, Keycodes} from 'key.js'
export default class AnchorDisabler {
constructor (config = { selector: 'a.disabled' }) {
this.config = config
$(this.config.selector)
.click((ev) => this.onClick(ev))
.keyup((ev) => this.onKeyup(ev))
.focus((ev) => this.onFocus(ev))
}
isStillDisabled (ev) {
// since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event
let target = $(ev.target)
if (target.hasClass('disabled') || target.prop('disabled') == 'disabled') {
return true
}
else {
return false
}
}
onFocus (ev) {
// if an attempt is made to focus on a disabled element, just move it along to the next focusable one.
if (!this.isStillDisabled(ev)) {
return
}
let focusables = $(':focusable')
if (!focusables) {
return
}
let current = focusables.index(ev.target)
let next = null
if (focusables.eq(current + 1).length) {
next = focusables.eq(current + 1)
} else {
next = focusables.eq(0)
}
if (next) {
next.focus()
}
}
onClick (ev) {
// disabled could be dynamically removed
if (!this.isStillDisabled(ev)) {
return
}
ev.preventDefault()
return false
}
onKeyup (ev) {
// We are only interested in disabling Enter so get out fast
if (Key.isNot(ev, Keycodes.ENTER)) {
return
}
// disabled could be dynamically removed
if (!this.isStillDisabled(ev)) {
return
}
ev.preventDefault()
return false
}
}
Coffescript class:
class AnchorDisabler
constructor: (selector = 'a.disabled') ->
$(selector).click(#onClick).keyup(#onKeyup).focus(#onFocus)
isStillDisabled: (ev) =>
### since disabled can be a class or an attribute, and it can be dynamically removed, always recheck on a watched event ###
target = $(ev.target)
return true if target.hasClass('disabled')
return true if target.attr('disabled') is 'disabled'
return false
onFocus: (ev) =>
### if an attempt is made to focus on a disabled element, just move it along to the next focusable one. ###
return unless #isStillDisabled(ev)
focusables = $(':focusable')
return unless focusables
current = focusables.index(ev.target)
next = (if focusables.eq(current + 1).length then focusables.eq(current + 1) else focusables.eq(0))
next.focus() if next
onClick: (ev) =>
# disabled could be dynamically removed
return unless #isStillDisabled(ev)
ev.preventDefault()
return false
onKeyup: (ev) =>
# 13 is the js key code for Enter, we are only interested in disabling that so get out fast
code = ev.keyCode or ev.which
return unless code is 13
# disabled could be dynamically removed
return unless #isStillDisabled(ev)
ev.preventDefault()
return false
Try the element:
$(td).find('a').attr('disabled', 'disabled');
Disabling a link works for me in Chrome: http://jsfiddle.net/KeesCBakker/LGYpz/.
Firefox doesn't seem to play nice. This example works:
<a id="a1" href="http://www.google.com">Google 1</a>
<a id="a2" href="http://www.google.com">Google 2</a>
$('#a1').attr('disabled', 'disabled');
$(document).on('click', 'a', function(e) {
if ($(this).attr('disabled') == 'disabled') {
e.preventDefault();
}
});
Note: added a 'live' statement for future disabled / enabled links.
Note2: changed 'live' into 'on'.
Bootstrap 4.1 provides a class named disabled and aria-disabled="true" attribute.
example"
<a href="#"
class="btn btn-primary btn-lg disabled"
tabindex="-1"
role="button" aria-disabled="true"
>
Primary link
</a>
More is on getbootstrap.com
So if you want to make it dynamically, and you don't want to care if it is button or ancor than
in JS script you need something like that
let $btn=$('.myClass');
$btn.attr('disabled', true);
if ($btn[0].tagName == 'A'){
$btn.off();
$btn.addClass('disabled');
$btn.attr('aria-disabled', true);
}
But be carefull
The solution only works on links with classes btn btn-link.
Sometimes bootstrap recommends using card-link class, in this case solution will not work.
Just add a css property:
<style>
a {
pointer-events: none;
}
</style>
Doing so you can disable the anchor tag.
I've ended up with the solution below, which can work with either an attribute, <a href="..." disabled="disabled">, or a class <a href="..." class="disabled">:
CSS Styles:
a[disabled=disabled], a.disabled {
color: gray;
cursor: default;
}
a[disabled=disabled]:hover, a.disabled:hover {
text-decoration: none;
}
Javascript (in jQuery ready):
$("a[disabled], a.disabled").on("click", function(e){
var $this = $(this);
if ($this.is("[disabled=disabled]") || $this.hasClass("disabled"))
e.preventDefault();
})
In Razor (.cshtml) you can do:
#{
var isDisabled = true;
}
Home
You can disable the HTML link as given below:
<style>
.disabled-link {
pointer-events: none;
}
</style>
Google.com
You can use inline JavaScript:
Google.com
you cannot disable a link, if you want that click event should not fire then simply Remove the action from that link.
$(td).find('a').attr('href', '');
For More Info :- Elements that can be Disabled
I would do something like
$('td').find('a').each(function(){
$(this).addClass('disabled-link');
});
$('.disabled-link').on('click', false);
something like this should work. You add a class for links you want to have disabled and then you return false when someone click them. To enable them just remove the class.
To disable link to access another page on touch device:
if (control == false)
document.getElementById('id_link').setAttribute('href', '#');
else
document.getElementById('id_link').setAttribute('href', 'page/link.html');
end if;
I would suggest turning the link into a button and using the 'disabled' attribute. You can see this issue to check how to convert a link to a button: How to create an HTML button that acts like a link
You can use this to disabled the Hyperlink of asp.net or link buttons in html.
$("td > a").attr("disabled", "disabled").on("click", function() {
return false;
});
There is one other possible way, and the one that I like best. Basically it's the same way lightbox disables a whole page, by placing a div and fiddling with z-index. Here is relevant snippets from a project of mine. This works in all browsers!!!!!
Javascript (jQuery):
var windowResizer = function(){
var offset = $('#back').offset();
var buttontop = offset.top;
var buttonleft = offset.left;
$('#backdisabler').css({'top':buttontop,'left':buttonleft,'visibility':'visible'});
offset = $('#next').offset();
buttontop = offset.top;
buttonleft = offset.left;
$('#nextdisabler').css({'top':buttontop,'left':buttonleft,'visibility':'visible'});
}
$(document).ready(function() {
$(window).resize(function() {
setTimeout(function() {
windowResizer();
}, 5); //when the maximize/restore buttons are pressed, we have to wait or it will fire to fast
});
});
and in html
<img src="images/icons/back.png" style="height: 50px; width: 50px" />
<img src="images/icons/next.png" style="height: 50px; width: 50px" />
<img id="backdisabler" src="images/icons/disabled.png" style="visibility: hidden; position: absolute; padding: 5px; height: 62px; width: 62px; z-index: 9000"/>
<img id="nextdisabler" src="images/icons/disabled.png" style="visibility: hidden; position: absolute; padding: 5px; height: 62px; width: 62px; z-index: 9000"/>
So the resizer finds the anchor's (the images are just arrows) locations and places the disabler on top. The disabler's image is a translucent grey square (change the width/height of the disablers in the html to match your link) to show that it is disabled. The floating allows the page to resize dynamically, and the disablers will follow suit in windowResizer(). You can find suitable images through google. I have placed the relevant css inline for simplicity.
then based on some condition,
$('#backdisabler').css({'visibility':'hidden'});
$('#nextdisabler').css({'visibility':'visible'});
I think a lot of these are over thinking. Add a class of whatever you want, like disabled_link. Then make the css have .disabled_link { display: none }
Boom now the user can't see the link so you won't have to worry about them clicking it. If they do something to satisfy the link being clickable, simply remove the class with jQuery: $("a.disabled_link").removeClass("super_disabled"). Boom done!

How to disable and then re-enable onclick event in <img> using jquery

I have used an image instead of button, now I want to disable the onclick() event in some case as we disable a button. I tried many ways but doesn't work. Below is what I did:
<img title="Ok" class="mtbtn"id="upd_1" onclick="add_edited('1','MM');" src="/project/images/green_ok.gif" border="0">
The jQuery code is:
$("#upd_1").css('opacity','0.5');
$("#upd_1").unbind("click");
I also tried:
$("#upd_1").css('pointer-events','none'); and document.getElementById('upd_1').style.pointerEvents = 'none';.
Any solution?
Try this:
$("#upd_1").on('click',function(e){
e.preventDefault();
});
One hint is that you can give your click event a suffix so you can be sure it's the only event you are affecting. To bind:
$('#elementId').on('click.myevent', function () {
// your code
}
To unbind:
$('#elementId').off('click.myevent');
Not going into binding or unbinding the click event but how about creating a mask for the image. Hide the mask when you want the image to be clickable else show it.
img onclick="alert('clicked')" src="http://lh3.googleusercontent.com/mjejVTJKT4ABNKq2HGlkDs36f-QvzI2hKFER098vBIgiAoZ2H-SN5QPvFaZEVDZRxfujrS6pszZ_J-_di2F57w0IFE3KAciDwGAh-9RcCA=s660" alt="" />
<div id="mask"></div>
<script>
$('#mask').hide();
$('#disable').click(function() {
$('#mask').show();
});
$('#enable').click(function() {
$('#mask').hide();
});
</script>
Try the Plnkr: Plnkr
Try this way. Add your parameters in two attributes (data-a and data-b for example).
<img title="Ok" class="mtbtn"id="upd_1" data-a="1" data-b="MM" src="/project/images/green_ok.gif" border="0">
Then change your javascript in this way:
$(document).ready(function(){
$("#upd_1").bind("click", function(){
var a = $(this).data("a");
var b = $(this).data("b");
// Code here
$(this).unbind("click");
});
});
Here the result.
Alternative is this:
var semaphore = true;
function add_edited (a, b) {
if (semaphore) {
semaphore = false;
// Code here
}
}
Create a semaphore to manage the execution of the code to the click.
i understood you'r problem, there is no need to unbind() and re bind() the onclick event, you can simply remove and re-add onclick attribute using removeAttr() and attr()
<img title="Ok" class="mtbtn"id="upd_1" onclick="add_edited('1','MM');" src="/project/images/green_ok.gif" border="0">
JQuery:
$("#upd_1").css('opacity','0.5');
$("#upd_1").removeAttr('onclick');
to re add onclick event do the following:
$("#upd_1").css('opacity','1');
$("#upd_1").attr("onclick","add_edited('1','MM');");
that is all you need to do.

Disabled button is clickable on Edge browser

I have problem with Edge browser. In my web site I have buttons with span tags inside them. In this span tags I bind text and icons. So far I had no problem but on Edge browser it is possible to click on disabled buttons. After investigating problem I found out that, when button contains span tags inside, it is possible to click on button. Here is how it looks on my web site:
<button id="btnRefresh" type="button" class="btn btn-primary" ng-click="refresh()" ng-disabled="performingAction">
<span ng-class="performingAction && action == 'refresh' ? 'fa fa-cog fa-spin' :'fa fa-refresh'"></span>
<span>{{ refresh }}</span>
</button>
Here is example to testing:
<button type="button" disabled="disabled" onclick='alert("test");'>
<span>Click me!</span>
</button>
One option would be to hide buttons instead of disabling, but I prefer to disable them. Please suggest solution to over come this issue.
Just set
pointer-events: none;
for disabled buttons.
Here's CSS to disable all disabled elements everywhere:
*[disabled] {
pointer-events: none !important;
}
pointer-events documentation
This is a bug in Microsoft Edge. Disabled buttons accept clicks if they contain any HTML elements (i.e. if they contain anything else than just text).
Reported multiple times via Microsoft Connect:
Event bubbles from child element into element (by SO user Ryan Joy)
Bootstrap/Jquery disabled buttons generate click events and show tooltips even disabled
The bug was still present in Build 10565 (16 October 2015).
It was fixed in the November update, Build 10586.
A possible (but ugly) workaround is to call some Javascript in onclick for every button, which then checks if the button is disabled and returns false (thus suppressing the click event).
One work around I've come up with using angularjs is inspired by Ben Nadel's blog here
So for example:
angular.module('myModule').directive(
"span",
function spanDirective() {
return ({
link: function (scope, element, attributes) {
element.bind('click', function (e) {
if (e.target.parentNode.parentNode.disabled || e.target.parentNode.disabled) {
e.stopPropagation();
}
})
},
restrict: "E",
});
}
);
Since you're not always going to be using a span element and probably don't want to create a new directive for every element type, a more general workaround would be to decorate the ngClick directive to prevent the event from reaching the real ngClick's internal event handler when the event is fired on a disabled element.
var yourAppModule = angular.module('myApp');
// ...
yourAppModule.config(['$provide', function($provide) {
$provide.decorator('ngClickDirective', ['$delegate', '$window', function($delegate, $window) {
var isEdge = /windows.+edge\//i.test($window.navigator.userAgent);
if (isEdge) {
var directiveConfig = $delegate[0];
var originalCompileFn = directiveConfig.compile;
directiveConfig.compile = function() {
var origLinkFn = originalCompileFn.apply(directiveConfig, arguments);
// Register a click event handler that will execute before the one the original link
// function registers so we can stop the event.
return function linkFn(scope, element) {
element.on('click', function(event) {
if (event.currentTarget && event.currentTarget.disabled) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
}
});
return origLinkFn.apply(null, arguments);
};
};
}
return $delegate;
}]);
}]);

Required Attribute Not work in Safari Browser

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
}

Workaround for file input label click (Firefox)

<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>