2009-04-28 18 views
72

Muszę sprawdzić, czy wartość funkcji onsubmit formularza jest funkcją. Format jest zwykle onsubmit="return valid();". Czy istnieje sposób sprawdzenia, czy jest to funkcja i czy można ją wywołać? Użycie typeof powoduje tylko, że jest to ciąg znaków, co nie pomaga mi zbytnio.Testowanie, czy wartość jest funkcją

EDYTOWANIE: Oczywiście, rozumiem, że "return valid();" jest ciągiem. Mam do "valid();", a nawet "valid()". Chcę wiedzieć, czy którykolwiek z nich jest funkcją.

EDIT: Oto niektóre kodu, które mogą pomóc w wyjaśnieniu mój problem:

$("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: Oto nowy kod. Wygląda na to, że nadal muszę używać eval, ponieważ wywołanie form.submit() nie uruchamia istniejących onsubmits.

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

Sugestie dotyczące tego, jak to zrobić lepiej?

Odpowiedz

70

Jestem wymieniając przesłać przycisk z linkiem zakotwiczenia . Ponieważ wywołanie form.submit() nie aktywuje onsubmit'S, ja znalezienie go i eval() ing to sam. Ale chciałbym sprawdzić, czy funkcja istnieje tylko przed eval() ing, co tam jest. - 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: brakujący parametr F w funkcji testOnsubmitAndSubmit

Powyższy powinien działać niezależnie od tego, czy można przypisać atrybut HTML z onsubmit lub przypisać go w JavaScript:

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

skąd pochodzi f in f.onsubmit? – Art

+0

'f' jest instancją formularza. Przekaż go do funkcji testOnsubmitAndSubmit jako argument. (Wiem, że to pytanie jest dość stare, ale może moja odpowiedź kiedyś kogoś uratuje :)) – zeroos

-3

Proste sprawdzenie jak to pozwoli Ci wiedzieć, czy istnieje/zdefiniowane:

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

To nie zadziała. Argument if wyświetli wartość TRUE, gdy onsubmit jest również niepustym łańcuchem. – Seb

+1

Straszny sposób sprawdzania, czy coś jest funkcją - jak wskazano, i aby być bardziej zrozumiałym: wszystko "prawda" spowodowałoby, że ten kod "zrobiłby coś", a to może nie być to, czego się oczekuje. Jeśli this.onsubmit zostanie ustawione na wartość 5 lub "hello" lub cokolwiek innego w JavaScript, który oceni na true, otrzymasz niespodziewane zachowanie. –

+0

Temat pytania pyta, jak sprawdzić, czy coś istnieje. To wszystko, co sugerowałem - nie więcej, nie mniej. – Kon

3

Upewnij dzwonisz typeof na rzeczywistej funkcji, a nie ciąg dosłowny:

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

typeof "x"; // returns "string" 

typeof x; // returns "function" 
5

Co Czy używasz przeglądarki?

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

Daje mi to "function" w IE7 i FireFox.

+0

Nawet jeśli twój onsubmit to "return valid();"? –

+1

Tak - nie zapominaj, że nie można "powrócić" poza funkcję. – Greg

+0

form.onsubmit będzie zawsze funkcją, o ile jest zdefiniowany jako atrybut HTML. Zobacz moją odpowiedź. –

3

Można spróbować modyfikacji this technique do własnych potrzeb:

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

Spróbuj

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

To "to" jest niebezpieczne. Gdzie powinien znajdować się ten kod? –

+5

to tylko próbka. Możesz zmienić go na button.onsubmit instanceof Function – artemb

1

dobrze, "return valid();"jest ciąg, więc to jest poprawne.

Jeśli chcesz sprawdzić, czy posiada ono funkcję dołączony zamiast, można spróbować to:

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

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

Jeśli jest ciągiem znaków, można założyć,/nadzieję, że to zawsze formularza

return SomeFunction(arguments); 

analizować za nazwą funkcji, a następnie sprawdzić, czy funkcja jest zdefiniowana

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

i chciałem dodać tę rozdzielczość również ... pamiętaj tylko, aby zarejestrować funkcję na poziomie dokumentu/okna – CrandellWS

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

Można po prostu użyć operatora typeof wraz z operatorem potrójnego w skrócie:

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

Jeśli jest to funkcja nazywamy go i powrót jego wartości zwracanej, inaczej po prostu wrócić true

Edycja:

Nie jestem do końca pewien, co tak naprawdę chcesz zrobić, ale spróbuję wyjaśnić, co może się wydarzyć.

Po zadeklarowaniu swojego kodu onsubmit w swoim html, zostaje on przekształcony w funkcję, a tym samym jest wywoływalny z JavaScript "świata". Oznacza to, że te dwie metody są równoważne:

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

Te dwa będą obie funkcje i oba będą wymagalne. Możesz przetestować dowolne z nich za pomocą operatora typeof, który powinien przydzielić ten sam wynik: "function".

Teraz, jeśli przypiszesz ciąg do właściwości "onsubmit" przez JavaScript, pozostanie ciągiem, a więc nie będzie można go wywołać. Zauważ, że jeśli zastosujesz do tego operatora typeof, otrzymasz "string" zamiast "function".

Mam nadzieję, że to może wyjaśnić kilka rzeczy. Z drugiej strony, jeśli chcesz się dowiedzieć, czy taka właściwość (lub jakikolwiek identyfikator dla danej sprawy) jest funkcją i można ją wywołać, operator typeof powinien załatwić sprawę. Chociaż nie jestem pewien, czy działa poprawnie w wielu klatkach.

zdrowie

+0

Muszę to przetestować poza onsubmit. –

2

form.onsubmit zawsze będzie to funkcja, gdy określona jako atrybut języka HTML na formę elementu. Jest to anonimowa funkcja dołączona do elementu HTML, który ma wskaźnik, który jest przypisany do tego elementu FORM i ma również parametr o nazwie event, który będzie zawierał dane o zdarzeniu przesyłania.

W tych okolicznościach nie rozumiem, w jaki sposób otrzymałeś ciąg znaków w wyniku operacji typeof. Powinieneś podać więcej szczegółów, lepiej trochę kodu.

Edit (jako reakcja na swojej drugiej edycji):

wierzę obsługi dołączone do atrybutu HTML zostanie wykonany niezależnie od powyższego kodu.Co więcej, można spróbować go jakoś zatrzymać, ale wydaje się, że FF 3, IE 8, Chrome 2 i Opera 9 realizują procedurę obsługi atrybutów HTML w pierwszej kolejności, a następnie jednej dołączone (nie testowane z jQuery ale z dodatkiem addEventListener i attachEvent). Więc ... co dokładnie chcesz osiągnąć?

Nawiasem mówiąc, Twój kod nie działa, ponieważ wyrażenie regularne będzie wyodrębnić ciąg „poprawny();”, który na pewno nie jest funkcją.

1

Myślę, że źródłem nieporozumień jest rozróżnienie między węzłem w atrybutu i odpowiedni własność.

Używasz:

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

pan bezpośrednio czytając „s wartość onsubmitatrybutu (który musi być ciągiem). Zamiast tego, należy uzyskać dostęp do onsubmitwłasność węzła:

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

Oto szybki test:

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

Daje:

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

You zawsze może używać jednej z funkcji typeOf na blogach JavaScript, takich jak Chris West's. Stosując definicję takich jak poniżej dla funkcji typeOf() będzie działać:

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

Funkcja ta (która jest zadeklarowana w globalnej przestrzeni nazw, mogą być używane tak:

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

Jeśli jest to funkcja , zostaną zwrócone "Function". Jeśli jest ciągiem znaków, zostanie zwrócony "String". Inne możliwe wartości są pokazane 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

użyciu ciąg oparciu var a iable jako przykład i wykorzystanie instanceof Function zarejestrować się function..assign zmienny ... sprawdź zmienna to nazwa funkcji ... zrobić wstępny proces ... przypisać funkcję do nowego var ... to nazwać funkcjonować.

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

Tak naprawdę nie potrzebujesz tej zmiennej fn, możesz po prostu użyć window [value](); –

+1

Tak, wiem, ale zdaję sobie również sprawę, że generalnie jest to łatwiejsze do zrozumienia w długim formacie i ponieważ jest to przede wszystkim strona, w której można się dowiedzieć, że Twój wkład jest ceniony w każdym przypadku @LajosMeszaros – CrandellWS