2009-04-28 11 views
72

Je dois tester si la valeur onsubmit d'une fiche est une fonction. Le format est généralement onsubmit="return valid();". Y at-il un moyen de dire si c'est une fonction, et si elle est appelable? Utiliser typeof renvoie juste que c'est une chaîne, ce qui ne m'aide pas beaucoup.Test si la valeur est une fonction

EDIT: Bien sûr, je comprends que "return valid();" est une chaîne. J'ai replace d jusqu'à "valide();", et même "valide()". Je veux savoir si l'une ou l'autre est une fonction.

EDIT: Voici un code, ce qui pourrait expliquer mon problème:

$("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: Voici le nouveau code. Il semble que je doive encore utiliser un eval, car l'appel à form.submit() ne déclenche pas d'onsubmits existants.

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; 
    } 
}); 

Suggestions sur éventuellement comment faire mieux?

Répondre

70

Je remplace un bouton d'envoi avec un lien d'ancrage . Depuis l'appel form.submit() n'active pas onsubmit, je le trouve, et eval() elle-même. Mais je voudrais vérifier si la fonction existe avant juste eval() ce qui est là. - 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: paramètre manquant f en fonction testOnsubmitAndSubmit

ci-dessus devrait fonctionner indépendamment du fait que vous attribuez l'attribut onsubmit HTML ou l'assigner en JavaScript:

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

d'où vient f f. – Art

+0

'f' est une instance de formulaire. Vous le passez à la fonction testOnsubmitAndSubmit en tant qu'argument. (Je sais que cette question est assez ancienne, mais peut-être que ma réponse sauvera quelqu'un d'un certain temps :)) – zeroos

-3

Une simple vérification comme celui-ci vous permettra de savoir si elle existe/définie:

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

Cela ne fonctionnera pas. Le if va s'affirmer à TRUE quand onsubmit est aussi une chaîne non vide. – Seb

+1

Une manière horrible de tester si quelque chose est une fonction - comme indiqué, et d'être plus clair: tout "véridique" ferait que ce code "fasse des choses" et ce pourrait ne pas être ce qui est attendu. Si this.onsubmit a la valeur 5 ou "hello" ou toute autre chose dans JavaScript qui donne true, vous allez avoir un comportement inattendu. –

+0

Le sujet de la question demande comment vérifier s'il existe quelque chose. C'est tout ce que je suggérais - pas plus, pas moins. – Kon

3

Assurez-vous que vous appelez typeof sur la fonction réelle, pas une chaîne littérale:

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

typeof "x"; // returns "string" 

typeof x; // returns "function" 
5

Qu'est-ce que navigateur utilisez-vous?

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

Cela me donne "function" dans IE7 et FireFox.

+0

Même si votre onsubmit est "return valid();"? –

+1

Oui - n'oubliez pas, vous ne pouvez pas avoir "retour" en dehors d'une fonction. – Greg

+0

form.onsubmit sera toujours une fonction tant qu'elle est définie en tant qu'attribut HTML. Vois ma réponse. –

3

Vous pouvez modifier this technique pour répondre à vos besoins:

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

Essayez

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

Ce "ceci" est dangereux. Où ce code devrait-il résider? –

+5

c'est juste un échantillon. Vous pouvez le changer en button.onsubmit instanceof Fonction – artemb

1

Eh bien, "return valid();"est une chaîne, de sorte que c'est exact.

Si vous voulez vérifier si elle a une fonction attachée à la place, vous pouvez essayer ceci:

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

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

Si c'est une chaîne, vous pouvez supposer/espérer qu'il est toujours de la forme

return SomeFunction(arguments); 

analyser le nom de la fonction, puis voir si cette fonction est définie à l'aide

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

J'étais sur le point d'ajouter cette résolution aussi ... rappelez-vous juste d'enregistrer la fonction au niveau du document/fenêtre – CrandellWS

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

Vous pouvez simplement utiliser l'opérateur typeof avec un opérateur ternaire pour faire court:

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

Si c'est une fonction que nous appelons et le retourner de la valeur de retour, sinon juste retour true

Edit:

Je ne suis pas sûr de ce que vous voulez vraiment faire, mais je vais essayer d'expliquer ce qui pourrait se passer.

Lorsque vous déclarez votre code onsubmit dans votre fichier html, il devient une fonction et donc son appel du "monde" JavaScript. Cela signifie que ces deux méthodes sont équivalentes:

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

Ces deux seront les deux fonctions et les deux seront appelables. Vous pouvez tester n'importe lequel de ceux utilisant l'opérateur typeof qui devrait afficher le même résultat: "function".

Maintenant, si vous affectez une chaîne à la propriété "onsubmit" via JavaScript, elle restera une chaîne, donc pas appelable. Notez que si vous appliquez l'opérateur typeof par rapport à cela, vous obtiendrez "string" au lieu de "function". J'espère que cela pourrait clarifier un certain nombre de choses. Là encore, si vous voulez savoir si une telle propriété (ou un identifiant) est une fonction appelable, l'opérateur typeof devrait faire l'affaire. Bien que je ne suis pas sûr si cela fonctionne correctement à travers plusieurs cadres.

Vive

+0

J'ai besoin de tester ceci en dehors de l'onsubmit cependant. –

2

form.onsubmit sera toujours une fonction lorsqu'elle est définie comme un attribut de l'élément HTML de formulaire. C'est une sorte de fonction anonyme attachée à un élément HTML, qui a le ce pointeur lié à cet élément FORM et a également un paramètre nommé event qui contiendra des données sur l'événement submit.

Dans ces circonstances, je ne comprends pas comment vous avez obtenu une chaîne à la suite d'une opération de typeof. Vous devriez donner plus de détails, mieux du code.

Modifier (en réponse à votre deuxième édition):

Je crois que le gestionnaire attaché à l'attribut HTML exécutera quel que soit le code ci-dessus.De plus, vous pouvez essayer de l'arrêter en quelque sorte, mais il semble que FF 3, IE 8, Chrome 2 et Opera 9 exécutent le gestionnaire d'attribut HTML en premier lieu, puis celui attaché (je n'ai pas testé avec jQuery cependant, mais avec addEventListener et attachEvent). Alors ... qu'est-ce que vous essayez d'accomplir exactement? D'ailleurs, votre code ne fonctionne pas parce que votre expression régulière va extraire la chaîne "valid();", ce qui n'est définitivement pas une fonction.

1

Je pense que la source de confusion est la distinction entre un attribut de noeud et correspondant propriété.

Vous utilisez:

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

Vous lisez directement la onsubmitla valeur d'attribut de (qui doit être une chaîne). Au lieu de cela, vous devez accéder au onsubmitpropriété du nœud:

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

Voici un test rapide:

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

Cela donne:

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

Vous peut toujours utiliser l'une des fonctions typeOf sur les blogs JavaScript tels que Chris West's. En utilisant une définition telle que la suivante pour la fonction typeOf() fonctionnerait:

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

Cette fonction (qui est déclarée dans l'espace de noms global, peut être utilisé comme ceci:

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

Si elle est une fonction , « fonction » sera retourné. Si c'est une chaîne, « string » sera retourné. Les autres valeurs possibles sont présentés 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

en utilisant une chaîne basée var iable comme exemple et en faisant usage instanceof Function Vous enregistrez la fonction..affecter la variable ... vérifier la variable est le nom de la fonction ... faire prétraiter ... affecter la fonction à la nouvelle var ... puis appeler le fonction.

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

Vous n'avez pas vraiment besoin de cette variable fn, vous pouvez simplement utiliser window [value](); –

+1

oui je sais mais je réalise aussi qu'il est généralement plus facile à comprendre dans un format long et comme c'est principalement un site pour apprendre votre contribution est en tout cas évalué @LajosMeszaros – CrandellWS

Questions connexes