2009-04-28 16 views
72

Necesito comprobar si el valor de un formulario es onsubmit es una función. El formato es típicamente onsubmit="return valid();". ¿Hay alguna forma de saber si se trata de una función y si se puede llamar? Usar typeof solo devuelve que es una cadena, lo cual no me ayuda mucho.Comprobando si el valor es una función

EDIT: Por supuesto, entiendo que "return valid();" es una cadena He replace d hasta "valid();", e incluso "valid()". Quiero saber si alguno de ellos es una función.

EDITAR: Aquí hay un código, que puede ayudar a explicar mi problema:

$("a.button").parents("form").submit(function() { 
    var submit_function = $("a.button").parents("form").attr("onsubmit"); 
    if (submit_function && typeof(submit_function.replace(/return /,"")) == 'function') { 
     return eval(submit_function.replace(/return /,"")); 
    } else { 
     alert("onSubmit is not a function.\n\nIs the script included?"); return false; 
    } 
}); 

EDIT 2: Aquí está el código nuevo. Parece que todavía tengo que usar una evaluación, porque al llamar a form.submit() no se activan los envíos existentes.

var formObj = $("a.button").parents("form"); 
formObj.submit(function() { 
    if (formObj[0].onsubmit && typeof(formObj.onsubmit) == 'function') { 
     return eval(formObj.attr("onsubmit").replace(/return /,"")); 
    } else { 
     alert("onSubmit is not a function.\n\nIs the script included?"); 
     return false; 
    } 
}); 

Sugerencias sobre cómo hacerlo mejor?

Respuesta

70

estoy sustitución de una enviar botón con un enlace de anclaje . Dado que llamar al form.submit() no activa onsubmit's, lo estoy buscando, y eval() yo mismo. Pero me gustaría comprobar si la función existe antes de simplemente evaluar() lo que hay allí. - gms8994

<script type="text/javascript"> 
function onsubmitHandler() { 
    alert('running onsubmit handler'); 
    return true; 
} 
function testOnsubmitAndSubmit(f) { 
    if (typeof f.onsubmit === 'function') { 
     // onsubmit is executable, test the return value 
     if (f.onsubmit()) { 
      // onsubmit returns true, submit the form 
      f.submit(); 
     } 
    } 
} 
</script> 

<form name="theForm" onsubmit="return onsubmitHandler();"> 
<a href="#" onclick=" 
    testOnsubmitAndSubmit(document.forms['theForm']); 
    return false; 
"></a> 
</form> 

EDIT: Falta un parámetro f en función testOnsubmitAndSubmit

lo anterior debe funcionar independientemente de si se asigna el atributo HTML onsubmit o le asigne en JavaScript:

document.forms['theForm'].onsubmit = onsubmitHandler; 
+1

¿de dónde viene f en f.onsubmit? – Art

+0

'f' es una instancia de formulario. Lo pasa a la función testOnsubmitAndSubmit como argumento. (Sé que esta pregunta es bastante antigua, pero tal vez mi respuesta le ahorrará a alguien algo de tiempo :)) – zeroos

-3

Un cheque simple como esto le permitirá saber si existe/definida:

if (this.onsubmit) 
{ 
    // do stuff; 
} 
+5

Esto no funcionará. El if afirmará TRUE cuando onsubmit es una cadena no vacía también. – Seb

+1

Una manera horrible de probar si algo es una función, como se indica, y para ser más claro: cualquier "verdad" haría que este código "hiciera cosas" y que podría no ser lo que se esperaba. Si this.onsubmit se establece en el valor de 5 o "hola" o cualquier otra cosa en JavaScript que evalúe como verdadero, obtendrá un comportamiento inesperado. –

+0

El sujeto de la pregunta pregunta cómo verificar si algo existe. Eso es todo lo que sugerí, ni más ni menos. – Kon

3

Asegúrese de que está llamando typeof en la función real, no una cadena literal:

function x() { 
    console.log("hi"); 
} 

typeof "x"; // returns "string" 

typeof x; // returns "function" 
5

Lo navegador estás usando?

alert(typeof document.getElementById('myform').onsubmit); 

Esto me da "function" en IE7 y Firefox.

+0

Incluso si su publicación es "return valid();"? –

+1

Sí, no lo olvide, no puede tener "retorno" fuera de una función. – Greg

+0

form.onsubmit siempre será una función siempre que se defina como un atributo HTML. Ver mi respuesta –

3

Usted puede intentar modificar this technique para satisfacer sus necesidades:

function isFunction() { 
    var functionName = window.prompt('Function name: '); 
    var isDefined = eval('(typeof ' + functionName + '==\'function\');'); 
    if (isDefined) 
    eval(functionName + '();'); 
    else 
    alert('Function ' + functionName + ' does not exist'); 
} 
function anotherFunction() { 
    alert('message from another function.'); 
} 
46

Trate

if (this.onsubmit instanceof Function) { 
    // do stuff; 
} 
+5

Que "esto" es peligroso. ¿Dónde debería residir ese código? –

+5

eso es solo una muestra. Puede cambiarlo a button.onsubmit instanceof Función – artemb

1

Bueno, "return valid();" es una cadena, por lo que es correcto.

Si desea comprobar si tiene una función de adjunto en lugar, puede probar esto:

formId.onsubmit = function(){ /* */ } 

if(typeof formId.onsubmit == "function"){ 
    alert("it's a function!"); 
} 
2

Si se trata de una cadena, que podría suponer/espero que sea siempre de la forma

return SomeFunction(arguments); 

analizar para el nombre de la función, y luego ver si esa función se define mediante

if (window[functionName]) { 
    // do stuff 
} 
+0

Estaba a punto de agregar esta resolución también ... simplemente recuerde registrar la función en el nivel de documento/ventana – CrandellWS

1
if (window.onsubmit) { 
    // 
    } else { 
    alert("Function does not exist."); 
    } 
12

simplemente puede usar el operador typeof junto con un operador ternario, para abreviar:

onsubmit="return typeof valid =='function' ? valid() : true;" 

Si se trata de una función que llamamos y lo devolverá de valor de retorno, de lo contrario sólo volver true

Edición:

No estoy muy seguro de lo que realmente quiere hacer, pero trataré de explicar lo que podría estar pasando.

Cuando declara su código onsubmit dentro de su html, se convierte en una función y, por lo tanto, se puede llamar desde el "mundo" de JavaScript. Eso significa que esos dos métodos son equivalentes:

HTML: <form onsubmit="return valid();" /> 
JavaScript: myForm.onsubmit = function() { return valid(); }; 

Estas dos funciones serán ambas y ambas serán habilitadas. Puede probar cualquiera de los que utilizan el operador typeof que debería arrojar el mismo resultado: "function".

Ahora, si asigna una cadena a la propiedad "onsubmit" a través de JavaScript, seguirá siendo una cadena, por lo tanto, no se puede llamar. Tenga en cuenta que si aplica el operador typeof en su contra, obtendrá "string" en lugar de "function".

Espero que esto pueda aclarar algunas cosas. Por otra parte, si desea saber si dicha propiedad (o cualquier identificador para el asunto) es una función y puede llamarse, el operador typeof debería hacer el truco. Aunque no estoy seguro de si funciona correctamente en varios marcos.

Saludos

+0

. Sin embargo, necesito probar esto fuera de la publicación. –

2

form.onsubmit siempre será una función cuando se define como un atributo de HTML la forma del elemento. Es una especie de función anónima asociada a un elemento HTML, que tiene el este puntero vinculado a ese elemento FORM y también tiene un parámetro llamado event que contendrá datos sobre el evento submit.

Bajo estas circunstancias, no entiendo cómo obtuvo una cuerda como resultado de un tipo de operación. Deberías dar más detalles, mejorar algún código.

Editar (como una respuesta a su segunda edición):

creo que el controlador asociado al atributo HTML ejecutará sin importar el código de seguridad.Además, podría intentar detenerlo de alguna manera, pero parece que FF 3, IE 8, Chrome 2 y Opera 9 están ejecutando el controlador de atributos HTML en primer lugar y luego el adjunto (no probé con jQuery sin embargo, pero con addEventListener y attachEvent). Entonces ... ¿qué estás tratando de lograr exactamente?

Por cierto, su código no funciona porque su expresión regular extraerá la cadena "valid();", que definitivamente no es una función.

1

creo que la fuente de confusión es la distinción entre atributo de un nodo y la propiedad correspondiente.

Estás usando:

$("a.button").parents("form").attr("onsubmit") 

Estás leyendo directamente el 's valor onsubmitatributo (que debe ser una cadena). En su lugar, usted debe tener acceso a la onsubmitpropiedad del nodo:

$("a.button").parents("form").prop("onsubmit") 

Aquí es una prueba rápida:

<form id="form1" action="foo1.htm" onsubmit="return valid()"></form> 
<script> 
window.onload = function() { 
    var form1 = document.getElementById("form1"); 

    function log(s) { 
     document.write("<div>" + s + "</div>"); 
    } 

    function info(v) { 
     return "(" + typeof v + ") " + v; 
    } 

    log("form1 onsubmit property: " + info(form1.onsubmit)); 
    log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit"))); 
}; 
</script> 

Esto produce:

 
form1 onsubmit property: (function) function onsubmit(event) { return valid(); } 
form1 onsubmit attribute: (string) return valid() 
0

Usted siempre puede usar una de las funciones typeOf en blogs de JavaScript como Chris West's. Usando una definición como la siguiente para la función typeOf() funcionaría:

function typeOf(o){return {}.toString.call(o).slice(8,-1)} 

Esta función (que se declara en el espacio de nombres global, se puede utilizar la siguiente manera:

alert("onsubmit is a " + typeOf(elem.onsubmit)); 

si se trata de una función "Función" será devuelto. Si se trata de una cadena, "cadena" será devuelto. Otros valores posibles se muestran here.

0
// This should be a function, because in certain JavaScript engines (V8, for 
// example, try block kills many optimizations). 
function isFunction(func) { 
    // For some reason, function constructor doesn't accept anonymous functions. 
    // Also, this check finds callable objects that aren't function (such as, 
    // regular expressions in old WebKit versions), as according to EcmaScript 
    // specification, any callable object should have typeof set to function. 
    if (typeof func === 'function') 
     return true 

    // If the function isn't a string, it's probably good idea to return false, 
    // as eval cannot process values that aren't strings. 
    if (typeof func !== 'string') 
     return false 

    // So, the value is a string. Try creating a function, in order to detect 
    // syntax error. 
    try { 
     // Create a function with string func, in order to detect whatever it's 
     // an actual function. Unlike examples with eval, it should be actually 
     // safe to use with any string (provided you don't call returned value). 
     Function(func) 
     return true 
    } 
    catch (e) { 
     // While usually only SyntaxError could be thrown (unless somebody 
     // modified definition of something used in this function, like 
     // SyntaxError or Function, it's better to prepare for unexpected. 
     if (!(e instanceof SyntaxError)) { 
      throw e 
     } 

     return false 
    } 
} 
3

utilizando una cadena basada var como ejemplo y haciendo uso instanceof Function Registra la función ... asigne la variable ... verifique que la variable es el nombre de la función ... haga el pre-procesamiento ... asigne la función a la nueva var ... luego llame al función.

function callMe(){ 
    alert('You rang?'); 
} 

var value = 'callMe'; 

if (window[value] instanceof Function) { 
    // do pre-process stuff 
    // FYI the function has not actually been called yet 
    console.log('callable function'); 
    //now call function 
    var fn = window[value]; 
    fn(); 
} 
+2

Realmente no necesitas esa variable fn, solo puedes usar window [value](); –

+1

Sí, lo sé, pero también me doy cuenta de que, en general, es más fácil de entender en un formato largo y, como este es principalmente un sitio para aprender, su aporte se valora en cualquier caso @LajosMeszaros – CrandellWS

Cuestiones relacionadas