最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - An input in a form named 'action' overrides the form's action property. Is this a bug? - St

programmeradmin1浏览0评论

I have a form marked up as

<form class="form1" method="post" action="form1.php" style="width:405px">

Ordinarily, I could access the action of the form in javascript by referring to the .action of the form object, for example

document.forms[0].action

which would return the value

form1.php

However, if I have, as a ponent of the form, an item named "action", this "action" bees the content of the form's action. That is, if the form markup contains, for example,

<input name="action" type="hidden" value="check" />

Then

document.forms[0].action

returns the value

<input name="action" type="hidden" value="check" />

Now, I did work out how to get around this: by using

document.forms[0].getAttribute("action")

However, it's a nasty gotcha that confused me for too long. Is this a bug? A known gotcha of DOM management? Or should I just get into the habit of using .getAttribute()?

I have a form marked up as

<form class="form1" method="post" action="form1.php" style="width:405px">

Ordinarily, I could access the action of the form in javascript by referring to the .action of the form object, for example

document.forms[0].action

which would return the value

form1.php

However, if I have, as a ponent of the form, an item named "action", this "action" bees the content of the form's action. That is, if the form markup contains, for example,

<input name="action" type="hidden" value="check" />

Then

document.forms[0].action

returns the value

<input name="action" type="hidden" value="check" />

Now, I did work out how to get around this: by using

document.forms[0].getAttribute("action")

However, it's a nasty gotcha that confused me for too long. Is this a bug? A known gotcha of DOM management? Or should I just get into the habit of using .getAttribute()?

Share edited Aug 7, 2013 at 15:50 Charles 51.4k13 gold badges106 silver badges144 bronze badges asked Aug 7, 2013 at 10:12 bugmagnetbugmagnet 7,7798 gold badges72 silver badges140 bronze badges 1
  • 1 Not a bug, the browser is emulating IE behaviour which started form[elementname] style - correct would be form.elements[elementname]. However I had expected the attribute to shadow the input… – Bergi Commented Aug 7, 2013 at 10:24
Add a ment  | 

3 Answers 3

Reset to default 7

I would not call this a bug. This effect occurs, because attributes can be read by using element.attributename and named inputs inside a form can be accessed in the same way, formelement.inputname. If there is an attribute and an input with the same name, there is no guarantee which one will be used. It probably behaves differently in different browsers.

I personally use getAttribute if I am reading a known attribute that was included in the markup or added using setAttribute in JavaScript. For dynamic values like, for example, the checked attribute of a checkbox, I don't use getAttribute. But this is more a question of personal preference, I guess.

I am fighting this behaviour at the moment too (7 years later!)

It is very hacky, but you are able to access and call the action getter directly by using the following.

Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, 'action').get.call(document.forms[0]);

Having encountered this for a number of different form attrs, I finally worked up a general solution based on @threenplusone's answer.

The following code creates a safeForm() function that wraps any Forms in a Proxy object which transparently "unmasks" any form properties that have been hidden ("id", "name", "action", etc). All other values are returned as-is.


// get property descriptor from wherever in chain
function getPropertyDescriptor (obj, name) {
    let desc;
    while(obj && !(desc = Object.getOwnPropertyDescriptor(obj, name))) {
        obj = Object.getPrototypeOf(obj);
    }
    return desc;
}

// helpers for safeForm()
const isFormProxy = Symbol("isFormProxy"),
    formHandler = {
        get(form, prop) {
            if (prop === isFormProxy) return true;  // helper to detect proxy
            let value = form[prop];
            if (value instanceof HTMLElement && value.name === prop){
                let desc = getPropertyDescriptor(HTMLFormElement.prototype, prop);
                if(desc){
                    return desc.get.call(form);
                }
                // NOTE: ment out next line to include elements                 
                //       that aren't shadowing a form attribute.                 
                return;
            }
            return value;
        },
        set(form, prop, value){
            if(prop === isFormProxy) return;
            form[prop] = value;
        },
    };


// frontend function
function safeForm (elem){
     if(elem instanceof HTMLFormElement && !elem[isFormProxy]){
         return new Proxy(elem, formHandler);
     }
     return elem;
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论