Beat: Eigenen Prompt entwickeln

hallo

Ich habe viele Funktionen, die etwas erzeugen/konvertieren etc...
Im Stile:

  • hole selektierten Text
  • Bearbeite ihn
  • Füge ihn am ursprünglichen Ort wieder ein

Einige diese Funktionen sollen nun eine zusätzlich prompt Routine aufrufen,
damit Anpassungen von Attributen etc möglich sind.
Ich möchte aber nicht den Standard prompt() verwenden, sondern denke an etwas, das flexibler ist.

myprompt("choice_and_text", "Wählen Sie eines der Attribute oder definieren Sie ein eigenes", "keines", "gelb", "rot", "blau")
myprompt("choice", "Wählen Sie eines der Attribute", "keines", "gelb", "rot", "blau")
myprompt("text", "Schreiben Sie Ihre Attributanagab")

Nun frage ich mich, an was ich da denken muss.

  • Ich stelle den prompt-dialog dar,
  • Ein OK Button würde den dialog beenden durch setzen einer variable
  • während( der prüfwert wert 0 ){
      //tu nichts !!!
      }
    Ich habe den Eindruck, dass dieses Design falsch ist.
    Aber wie mache ich es, dass die prompt routine nicht zu seinem caller zurückkehrt
  • solange eine Useraktion nicht gefallen ist
  • solange nicht eine maximale Zeit vergangen ist
  • solange der User nicht ausserhalb des prompt Elements geklickt hat?

mfg Beat
--

<o(((°>           ><o(((°>

<°)))o><                     ><o(((°>o
Der Valigator leibt diese Fische

  1. Aber wie mache ich es, dass die prompt routine nicht zu seinem caller zurückkehrt

    Das geht nicht, du kannst das nur Eventbasiert umsetzen. Wenn der prompt geöffnet wird, dann wird nichts weiter getan, erst wenn dieses beendet oder abgebrochen wird, geht's weiter.

    Struppi.

  2. Lieber Beat,

    die "originale" propmpt-Methode hält die Ausführung von JavaScript komplett an. Während das Eingabefenster geöffnet ist, tut sich in JS-Land garnichts.

    Du willst nun auch eine Benutzerabfrage tätigen. Dazu musst Du eine Funktion schreiben, die "zweigleisig" fährt. Entweder deshalb, weil Du sie aufrufst, um zu fragen, oder deshalb, weil Du sie zur Auswertung der Antwort aufrufst.

    Du brauchst also eine Eigenschaft, die prüft, ob der Aufruf die Frage, oder die Antwort ist.

    Ich habe soetwas schonmal in Verbindung mit meinen Inline Popups gemacht. Das Ergebnis findest Du in meiner Dateiverwaltung.

    Hier der Code, den ich dafür benutze:

    // erstellt ein Popup mit einer Ja/Nein-Frage  
    // @parameter "frage": String  
    // @parameter "werte": Array mit zwei Strings (das sind die Werte von und für die Funktion "DateiVerwaltung.abschicken", die nach diesem Popup bei "ja" erneut aufgerufen wird!)  
    confirm : function (frage, werte) {  
        if (typeof(InlinePopup) == "undefined")  
            return window.confirm(frage);  
      
        var votum = DateiVerwaltung.confirmation.confirm;  
        DateiVerwaltung.confirmation.confirm = false;  
        DateiVerwaltung.confirmation.values = werte;  
      
        if (!DateiVerwaltung.confirmation.win) {  
            frage = frage.replace(/\n/gi, "</p>\r\n<p>");  
            var fenster = InlinePopup.open("", "confirm", "resizeable=no,statusbar=no,width=400,height=350");  
            fenster.document.open();  
            fenster.document.writeln('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">');  
            fenster.document.writeln('<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">');  
            fenster.document.writeln('<head>');  
            fenster.document.writeln('<title>Best&auml;tigen</title>');  
            fenster.document.writeln('<link rel="stylesheet" type="text/css" href="' + DateiVerwaltung.cmsRoot + 'css/dateiverwaltung.css" />');  
            fenster.document.writeln('<script type="text/javascript" src="' + DateiVerwaltung.cmsRoot + 'js/inlinepopup/inlinepopup_close.js"></script>');  
            fenster.document.writeln('<script type="text/javascript">');  
            fenster.document.writeln('function ergebnis(str) {');  
            fenster.document.writeln('    parent.DateiVerwaltung.confirmation.confirm = (str == "ja");');  
            fenster.document.writeln('    if (str == "ja") {');  
            fenster.document.writeln('        parent.DateiVerwaltung.xmlhttp.toDo = function () {');  
            fenster.document.writeln('            var win = self.parent.DateiVerwaltung.confirmation.win;');  
            fenster.document.writeln('            self.parent.DateiVerwaltung.confirmation.win = null;');  
            fenster.document.writeln('            win.close();');  
            fenster.document.writeln('        };');  
            fenster.document.writeln('        parent.DateiVerwaltung.abschicken(parent.DateiVerwaltung.confirmation.values);');  
            fenster.document.writeln('    } else {');  
            fenster.document.writeln('        self.parent.DateiVerwaltung.confirmation.win = null;');  
            fenster.document.writeln('        self.close();');  
            fenster.document.writeln('    }');  
            fenster.document.writeln('}');  
            fenster.document.writeln('</script>');  
            fenster.document.writeln('</head><body id="bestaetigungs-fenster">');  
            fenster.document.writeln('<h1>Sicherheits-R&uuml;ckfrage</h1>');  
            fenster.document.writeln('<p><img src="' + DateiVerwaltung.cmsRoot + 'images/cms/warn-frage.gif" alt="" class="linksbuendig" /></p>');  
            fenster.document.writeln('<p>' + frage + '</p>');  
            fenster.document.write('<p class="neue-zeile"><button id="ja" type="button" onclick="ergebnis(\'ja\')"><img src="' + DateiVerwaltung.cmsRoot + 'images/cms/haken16x16.gif" alt="" /> Ja</button>');  
            fenster.document.writeln('<button id="nein" type="button" onclick="ergebnis(\'nein\')"><img src="' + DateiVerwaltung.cmsRoot + 'images/cms/x16x16.gif" alt="" /> Nein</button></p>');  
            fenster.document.writeln('</body></html>');  
            fenster.document.close();  
      
            DateiVerwaltung.confirmation.win = fenster;  
        }  
      
        return votum;  
    },  
    
    

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  3. Seufz
    Danke mal euch beiden.

    Felix hat natürlich die Sache auf den springenden Punkt gebracht.
    Es wird mir also nichts anderes übrig bleiben, als die Funktionen, welche einen Dialog haben sollen, nach dem Prinzip des Affenformulars zu ändern.

    @Felix.
    Dein Beispiel ist klar. ich werden das mal eher ohne extra Fenster , aber mit einem absolut platzierten Element im Doc versuchen.
    Schliesslich habe ich eh schon alles für die GUI vorhanden.

    Das Prinzip wäre demnach:

    // User wendet einen Funktionslink an

    function somefunc( need ){
      // Wenn need=setdialog
         Rufe Dialog(caller) mit Werten
         return
      // wenn need=getdialog
         hole die aktuellen Werte im Dialog-Formular
         Setze/überschreibe Optionswerten für die Textbehandlung

    {---Dies ist mein bisheriger Funktionscode----)
      Erledige deine übliche Aufgabe
     (--------------------------------------------)
    }

    function dialog(Werteliste){
         Erstelle Formular nach übergebenen Werten
         Gib dem Formular den namen der aufzurufenden Function mit
         = mein eigener Caller
    }

    Das Formular dann hat im OK Button den Auslöser-Event.

    Hinweis:
    Obiger Pseudocode habe ich mal so skizziert, dass der zusätzliche Block für den Dialog (den ich ja nicht für alle Funktionen brauche) geschlossen erscheint.
    Das lässt es mir offen, immer noch mit einer einfachen Funktionsschnittstelle zu arbeiten für User-definierte Funktionen.

    mfg Beat

    <o(((°>           ><o(((°>

    <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische

    1. Felix hat natürlich die Sache auf den springenden Punkt gebracht.
      Es wird mir also nichts anderes übrig bleiben, als die Funktionen, welche einen Dialog haben sollen, nach dem Prinzip des Affenformulars zu ändern.

      wieso Affenformular? Du willst doch keine neue Seite aufbauen.

      Das Formular dann hat im OK Button den Auslöser-Event.

      Eben, Eventbasiert. Du musst eine Umgebung aufbauen, die events auslösen, erzeigen und fangen kann. Das ist exakt das was ich mit Eventbasiert meinte.

      Struppi.

  4. Aktuelle Problembeschreibung

    Ich habe eine Funktion in einem Array gespeichert:

      _ehf.ef[x][++y] = ['Test',  
        function(mode, opt ){  
           alert ("MODE"+mode);  
           if( mode != 1 ){  
              _ehf.dialog(_ehf.ef[x][y][1], 'Hi test', ['bla','bla']);  
              return;  
           else{  
              alert ("hi"+opt);  
              var class = ' class="' + opt + '"' ;  
              _ehf.f.insert('set',  
                   '<p'+class+'>' + _ehf.f.insert('get') + '</p>');  
          }  
      ) ];  
    
    

    Solche Funktionen arbeiten tadellos. Aber diese hat nun den Aufruf
    zu einer Dialog_Funktion.
    Der ELSE Zweig wird nicht ausgeführt.
    Das Problem liegt hier:

    ehf_dialog_collect = function(fx){  
      var opt = _ehf.dialog_options.getElementsByTagName('input');  
      var ret = '';  
      for ( var i=0; i < opt.length; i++){  
        if( opt[i].checked == true){ ret += opt[i].value + ' '; }  
      }  
      //alert(fx + ' \n'+ret); // Funktion wird bis hierher korrekt ausgeführt.  
      fx( 1, ret );  
    }
    

    alert( fx ...) gibt mir die Funktion wie oben geschrieben plus den angesammelten Return Wert.
    Aber
      fx( 1, ret );
    führt die Funktion nicht aus. das heisst, ich bekomme den oben geschilderten ELSE Zweig nicht.

    Mit diversen alerts schon alles abgescheckt. Wo ist das Problem?

    Hinweis: mit fx gebe gebe ich eigentlich jenes Array-Element weiter,
    indem die Funktion gespeichert ist.
    Die Funktion selbst gibt im IF Zweig sein eigenes Array-Element korrekt an.

    Danke für Hilfe

    mfg Beat

    1. Ich habe den Fehler herausgefunden.
      Die Werte x und y zeigten auf eine falsche Funktion.

      Ich verwenden nun in der dialog Function die Methode .caller

      Das einzige, was mich etwas beunruhigt:
      .caller gehört nicht zum ECMA Standard laut MozDev

      mfg Beat

      --
      Woran ich arbeite:
      X-Torah
      ><o(((°>           ><o(((°>
         <°)))o><                     ><o(((°>o
      Der Valigator leibt diese Fische
      1. Das einzige, was mich etwas beunruhigt:
        .caller gehört nicht zum ECMA Standard laut MozDev

        Deshalb würde ich sie auch nicht verwenden. Besser für deinen Zweck eignet sich arguments.callee.

        Dei Ansatz ist aber nicht schön. Eine Funktion die eine Eventfunktion auf sich selbst übergibt.

        Üblicher in JS ist sowas:

         _ehf.ef[x][++y] = ['Test',  
            function(mode, opt ){  
               alert ("MODE"+mode);  
               if( mode != 1 ){  
                  _ehf.dialog.onok = function() {  
                     alert(arguments);  
                  };  
                  _ehf.dialog.onabort = function() {  
                     alert(arguments);  
                  };  
                  _ehf.dialog('Hi test', ['bla','bla']);  
                  return;  
               else{  
                  alert ("hi"+opt);  
                  var class = ' class="' + opt + '"' ;  
                  _ehf.f.insert('set',  
                       '<p'+class+'>' + _ehf.f.insert('get') + '</p>');  
              }  
          ) ];  
        
        

        Struppi.

        1. Das einzige, was mich etwas beunruhigt:
          .caller gehört nicht zum ECMA Standard laut MozDev

          Deshalb würde ich sie auch nicht verwenden. Besser für deinen Zweck eignet sich arguments.callee.

          Ich habe das jetzt so geändert:

          _ehf.dialog = function( mode, text,opt){
              var fx = _ehf.dialog.arguments.callee.caller;
              //...
          }

          Dein Ansatz ist aber nicht schön. Eine Funktion die eine Eventfunktion auf sich selbst übergibt.

          Was ist die Alternative?
          Dass ich jede Funktion spalten muss.
          Das gibt mir dann nicht mehr wartbaren Code.

          Üblicher in JS ist sowas:
          [code lang=javascript] _ehf.ef[x][++y] = ['Test',
              function(mode, opt ){
                 alert ("MODE"+mode);
                 if( mode != 1 ){
                    _ehf.dialog.onok = function() {
                       alert(arguments);
                    };

          Ich arbeite nicht mit dem Standard prompt. Da ist kein onok
          Da ist onclick die übergabe der Variable "1"

          mfg Beat

          --
          ><o(((°>           ><o(((°>
             <°)))o><                     ><o(((°>o
          Der Valigator leibt diese Fische
          1. Ich habe das jetzt so geändert:

            _ehf.dialog = function( mode, text,opt){
                var fx = _ehf.dialog.arguments.callee.caller;
                //...
            }

            in callee steckt die Funktion, nicht in caller.

            » Dein Ansatz ist aber nicht schön. Eine Funktion die eine Eventfunktion auf sich selbst übergibt.

            Was ist die Alternative?
            Dass ich jede Funktion spalten muss.
            Das gibt mir dann nicht mehr wartbaren Code.

            Wieso? So wie du es jetzt machst halte ich es für nicht wartbar.

            » Üblicher in JS ist sowas:
            » [code lang=javascript] _ehf.ef[x][++y] = ['Test',
            »     function(mode, opt ){
            »        alert ("MODE"+mode);
            »        if( mode != 1 ){
            »           _ehf.dialog.onok = function() {
            »              alert(arguments);
            »           };

            Ich arbeite nicht mit dem Standard prompt. Da ist kein onok
            Da ist onclick die übergabe der Variable "1"

            Ich weiß und der Standardprompt bietet ja auch keine Events an, da dieser Modal arbeitet. Diese events musst du in deinem prompt einbauen. D.h. wenn in deinem prompt auf ok gedrückt wird ruft dieser die Funktion onok() auf. Bei cancel oder abbrechen, eben den Event, den du für's abbrechen definieren möchtest. Wie gesagt, das ist so wie du es von anderen Events in JS kennst, onclick, onload, onscroll, .... usw.

            Struppi.

        2. Üblicher in JS ist sowas:

          _ehf.ef[x][++y] = ['Test',

          function(mode, opt ){
                 alert ("MODE"+mode);
                 if( mode != 1 ){
                    _ehf.dialog.onok = function() {
                       alert(arguments);
                    };
                    _ehf.dialog.onabort = function() {
                       alert(arguments);
                    };
                    _ehf.dialog('Hi test', ['bla','bla']);
                    return;
                 else{
                    alert ("hi"+opt);
                    var class = ' class="' + opt + '"' ;
                    _ehf.f.insert('set',
                         '<p'+class+'>' + _ehf.f.insert('get') + '</p>');
                }
            ) ];

            
          Wobei ich hier übersehen habe, dass du hier ja auch noch eine Flag eingebaut hast. Dieser ist unnötig, wenn du mit Events arbeitest.  
            
          Der code müßte in etwa so aussehen  
          ~~~javascript
          _ehf.ef[x][++y] = ['Test',  
              function(opt ){  
                    _ehf.dialog.onok = function() {  
                       var opt = arguments[0];  
                    var class = ' class="' + opt + '"' ;  
                    _ehf.f.insert('set',  
                         '<p'+class+'>' + _ehf.f.insert('get') + '</p>');  
                    };  
                    _ehf.dialog.onabort = function() {  
                       alert(arguments);  
                    };  
                    _ehf.dialog('Hi test', ['bla','bla']);  
                    return;  
                }  
            ) ];  
          
          

          Struppi.