Fieldset and disabling all child inputs - Work aro

2019-03-24 18:41发布

问题:

I have a fieldset that has a ui-view under it.
Each view had lots of fields(a field is a directive that wraps an input) under it.

It looks something like this:

<fieldset ng-disabled='myCondition'>
   <div ui-view></div> // this changes with lot's of fields that look like <div field='text-box'></div>
</fieldset>

Now, this worked great, the fields get disabled on all browsers except IE.
I've done some google and seen that ie doesn't support fieldset + disabled and I'm looking for a quick workaround.

I've tried some things that were close but not perfect and I assume I'm not the first one that needs a solution(even though I didn't find anything on google).

回答1:

Seems like related to IE issues, see this and related (sorry, can't post more than 2 links yet). The first one will be fixed in next major IE release (Edge?). The second one is still opened.

As I suspect, the problem is that user still can click into inputs inside disabled fieldset an edit them.

If so, there is "css only" workaround for IE 8+ that creates transparent overlay above disabled fieldset that prevents fieldset from being clicked.

The workaround is described in Microsoft Connect issues.

There is fiddle, that demonstrates workaround in action.

fieldset {
    /* to set absolute position for :after content */
    position: relative;
}
/* this will 'screen' all fieldset content from clicks */
fieldset[disabled]:after {

    content: ' ';
    position: absolute;
    z-index: 1;
    top: 0; right: 0; bottom: 0; left: 0;
    /* i don't know... it was necessary to set background */
    background: url( data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==);
}

The workaround has some limitations, see code for details.

There are some options with JavaScript.

Seems like for IE9+ you can catch mousedown events on fieldset and call e.preventDefault() if fieldset is disabled.

fieldset.onmousedown = function(e) {

    if (!e) e = window.event;

    if (fieldset.disabled) {

        // for IE9+
        if (e.preventDefault) {

            e.preventDefault();
        }
        // for IE8-
        else {

            // actualy does not work
            //e.returnValue = false;
        }

        return false;
    }
}

For IE8 and below it is imposible to catch bubbling mousedown events on disabled fieldset, event handlers does not even gets called. But it is possible to catch them on fieldset ancestors, on documetn.body for exampe. But again, for IE8- you can't prevent element from being focused by preventing default action of mousedown event. See jQuery ticket #10345 for details (sorry, can't post more than 2 links). You can try to use UNSELECTABLE attribute to temporary forbid element to get focus. Something like this:

document.body.onmousedown = function(e) {

    if (!e) e = window.event;

    var target = e.target || e.srcElement;

    if (fieldset.contains(target) && fieldset.disabled) {

        // no need to do this on body!!! do it on fieldset itself
        /*if (e.preventDefault) {

            e.preventDefault();
        }
        else {*/

            // this is useless
            //e.returnValue = false;

            // but this works
            fieldset.setAttribute("UNSELECTABLE", "on");

            window.setTimeout(function() { target.setAttribute("UNSELECTABLE", ""); },4);
        /*}*/

        return false;
    }
}


回答2:

It has 1 line solution now.

.

Though status is fixed in Microsoft documentation Issue still not resolved!

But, Now we can also use pointer-events: none;. It will disable all input elements

fieldset[disabled] {
    pointer-events: none;
}


回答3:

I had the exact same problem, and i came up with this directive:

angular.module('module').directive('fieldset', function () {
    return {
        restrict: 'E',
        link: function (scope, element, attrs) {

            if (angular.isUndefined(element.prop('disabled'))) { //only watch if the browser doesn't support disabled on fieldsets
                scope.$watch(function () { return element.attr('disabled'); }, function (disabled) {
                    element.find('input, select, textarea').prop('disabled', disabled)
                });
            }
        }
    }
});

The feature detect is flawed though. On IEs it appears that the fieldset element (all elements it seems actually) have a 'disabled' property that is just set to false.

Edit: i just realised that it is inside an 'ng-view'. You may have to mess around with $timeouts to get it to apply the changes after the view has loaded. Or, even easier, place the fieldset inside the view.



回答4:

This is a fix to disable fieldsets in IE11: https://connect.microsoft.com/IE/feedbackdetail/view/962368/can-still-edit-input-type-text-within-fieldset-disabled

Detect IE: Detecting IE11 using CSS Capability/Feature Detection

_:-ms-lang(x), fieldset[disabled].ie10up 
        {
            pointer-events: none;
            opacity: .65;
        }