[jQuery] .on() mit :not

Rain

Lieutenant
Registriert
Mai 2003
Beiträge
704
Hallo zusammen,

ich steh aufm Schlauch :/

Ich erzeuge ein <div> dynamisch und will dass es verschwindet, wenn man überall draufklickt, nur auf das <div> nicht.

Also eine Liste wird erzeugt und diese soll verschwinden wenn man "daneben" klickt. Ich hab nun schon mehreres ausprobiert, mit :not erscheint es mir am logischsten, aber es geht nicht.

http://jsfiddle.net/Wbzgf/3/

Kann mich mal jemand vom Schlauch schubsen?
 
danke dir schonmal!

ein absolut positioniertes div "drunterlegen" wird leider nix, denn dadurch werden alle weiteren elemente auf der seite "nicht mehr klickbar". Es gibt noch ganz viele Navigations- und Aktions-Elemente, auf diese müsste der Benutzer dann 2 mal klicken bis sie reagieren.

Problematik mal hier veranschaulicht:

http://jsfiddle.net/Wbzgf/6/
 
@Picola: .live() ist veraltet, es wird geraten, es mittels .on() zu ersetzen.

@Rain: Wie wäre es mit einem zeitlichen Timer, der das eingeblendete div ausblendet, sobald der Mauszeiger sich nicht mehr über dem Button oder dem div selbst befindet? So lösen es quasi die meisten Mouseover-Menüs.

Code:
	// setup the buttons in the hover area
	$('#buttonarea, #hoverarea').hover(function() {
		clearInterval($('#hoverarea').data('timeoutId'));
		$('#hoverarea').slideDown(200);
	}, function() {
		$('#hoverarea').data('timeoutId', setTimeout(function() {
			$('#hoverarea').slideUp(200);
		}, 500));
	});

Ich verwende .data() um die timeoutid gut erreichbar an sinnvoller Stelle (dem hoverare-tag) zwischenzuspeichern. Wenn die Maus sich innerhalb der hoverarea befindet, wird das interval ausgesetzt. Verläßt es dies so wird es erneut mittlers SetTimeout() gestartet. Selbiges gilt auch für buttonarea, welches hoverarea bei betreten erst erscheinen läßt.
 
Danke dir DJND, interessanter Ansatz. Hover hilft mir in diesem Fall aber leider nicht weiter, es muss ein Click-Event sein. Es wird nämlich kein Hover-Menü, sondern zusätzliche Optionen, die beim Klick auf ein Listen-Element erscheinen.

Dieses Optionen-Menü wird an der Stelle, wo geklickt wird, absolut positioniert erzeugt. die lösung muss im zusammenspiel mit .on() und dem :not selector liegen.
 

Anhänge

  • menu.jpg
    menu.jpg
    20,1 KB · Aufrufe: 168
müsste es nicht so heißen?

$(document).on('click', ':not(div)', function() {
$(this).remove();
});
 
@ Mercsen:

probiers mal: http://jsfiddle.net/Wbzgf/7/
Wenn dann ':not('div')' , aber da doppelte ' -> ':not("div")', und auch 'body:not("div")' geht nicht
 
ich hab gerade einwenig probiert.

wenn du dem div eine klasse oder ud gibst klappt es wie folgt:

Code:
<html>
    <head>
        <script src="/javascript/jquery/jquery-1.7.2.js"></script>
        <script>
            $('#bla').click(function() {
                $('body').append('<div style="border: solid 1px red;">Überall solls verschwinden, aber nich bei dem Div</div>'); 
            });

            $(document).on('click', 'div:not(.noclick)', function(evt) {
                //$(evt.srcElement).remove(); 
                alert(evt.srcElement.id);
            });
            
            function test() {
                $('body').append('<div style=\"border: solid 1px red;\" class="noclick">Überall solls verschwinden, aber nich bei dem Div</div>');
            }
        </script>
    </head>
    <body>
        <button id="bla" onclick="test()">bla</button>
        <div id='blabla' style="width: 200px; height: 200px; border: 2px solid red"></div>
        <div id='blabla2' style="width: 200px; height: 200px; border: 2px solid green"></div>
    </body>
</html>

das problem ist halt das man irgendwie nicht aus einem selector der ALLE elemente wählt, per not ein bestimmtes element wieder entfernen kann, nur wenn man es auf ein bestimmten typ zwingt!

Anscheinend ist die on methode nicht für soetwas geeignet, was ich mich nun frage ist folgendes:

Erstens könnte man bevor das Element ins DOM eingehängt wird auf alle Elemente ein Clickhandler machen, so hast du quasi alle Ausgewählt außer dem dialog.

zweitens: wenn der not selector nicht will, dann teste halt in dem clickhandler ob der gerade angeklickte element der dialog ist oder nicht.

der wird ja eine id haben, dann halt im handler prüfen ob die ID = der dialog id ist, wenn nicht dann blende ihn aus.

drittens:

du könntest auch auf den kompletten body einen click handler legen, der entfernt wird, sobald die maus den dialog betritt und wieder eingefügt wird wenn die maus den dialog verlässt,
bzw. einen flag setzen wie mouse_in_dialog und wenn der true ist, reagiert der click handler eben nicht

P.S.
man muss bei dem not selector keine ' und keine " angeben, aber er wird stets auf eine selection angewendet.

leider klappt auch body:not(.noclick) nicht, absolut keine Ahnung wieso.

Da du die elemente ja aber selber erstelltst, kannst du doch in diese funktione deine eigene version der on methode implementieren, da du ja immer weißt wann er erzeugt wird, kannst du da auch die handler verwalten

P.P.S.

mittlerweile glaube ich nicht das es an der o methode liegt.
Sondern an der art wie und wo die handler eingehängt werden, je nach selector wird der handler bei einem klick bis zu 4 mal ausgeführt, immer der selbe.
Das element was im :not steht aber einmal weniger. Sehr komisch!
Code:
<html>
    <head>
        <script src="/javascript/jquery/jquery-1.7.2.js"></script>
        <script>
            $('#bla').click(function() {
                $('body').append('<div style="border: solid 1px red;">Überall solls verschwinden, aber nich bei dem Div</div>'); 
            });

            $(document).on('click', ':not(#noclick)', function(evt) {
                //$(evt.srcElement).remove(); 
                alert(evt.srcElement.id);
            });
            
            function test() {
                $('body').append('<div style=\"border: solid 1px red;\" id="noclick">Überall solls verschwinden, aber nich bei dem Div</div>');
            }
        </script>
    </head>
    <body>
        <button id="bla" onclick="test()">bla</button>
        <div id='blabla' style="width: 200px; height: 200px; border: 2px solid red"></div>
        <div id='blabla2' style="width: 200px; height: 200px; border: 2px solid green"></div>
    </body>
</html>

Bei jedem element wird 3 mal die ID ausgegeben, außer wenn man auf das neu erstellte div klick, da nur 2 mal.

Meine Vermutung:
Weil man nur DIVs oder aber eine bestimtme ID ausschließt feuert der click handler 2 mal mehr weil er noch einen click auch body und document registriert, o.ä.

Edit: nimmt man den body auch in den :not befehl ist schonmal ein aufruf weniger!
Code:
     $(document).on('click', ':not(#noclick, body)', function(evt) {
                //$(evt.srcElement).remove(); 
                alert(evt.srcElement.id);
            });

edit2:
nimmst html auch noch mit rein passts!

Code:
     $(document).on('click', ':not(#noclick, body, html)', function(evt) {
                //$(evt.srcElement).remove(); 
                alert(evt.srcElement.id);
            });

#noclick kannst durch das ersetzen was du haben willst, auch nur div

feuert IMMER es sei denn man click auf das neu erstellte div ;)
 
Zuletzt bearbeitet:
Danke für deine Mühen, Mercsen! Bei deinem Beispiel klappts, ich bekomms bei mir nicht eingebaut :(

Vereinfachter Code:

HTML:
<html>
<head>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">

function smalloptions(e, headline, script, vars) {

$('#smalloptions').remove();

$('body').append('\
<div id="smalloptions">\
<div id="smalloptions_headline">'+headline+'</div>\
<div id="smalloptions_content"></div>\
<div id="smalloptions_close">Schließen</div>\
</div>');

$('#smalloptions').css({
'position': 'absolute',
'z-index': '10000',
'left': (e.pageX-5)+'px',
'top': (e.pageY-5)+'px',
'border': 'solid 1px #000',
'background-color': '#fff',
'text-align': 'center'
});

}

$(document).on('click', 'div:not(#smalloptions, body, html)', function() {
// $('#smalloptions').remove();
alert('123');
});
</script>
</head>



<body style="width: 100%; height: 100%;">

<div style="width: 100%; height: 100%; background-color: blue;">
<div id="click" style="width: 100px; height: 50px; background-color: red;"></div>
</div>

<script type="text/javascript">
$('#click').click(function(e) {
smalloptions(e, 'bla', '');
});
</script>

</body>
</html>

Egal ob ich html und body rein-/rausnehme div:not(..) oder nur :not(..), NIX. Vielmehr feuert das click-event zum ausblenden der generierten box sobald man den klick zum generieren macht. Gibts doch nich :(
 
das gleiche problem wie vorher, der :not selector schließt zu viele elemente aus:
du musst ihm sagen das der click handler auch nicht auf die elemente des smalloptions div angewendetw werden soll:

Code:
  $(document).on('click', ':not(#smalloptions, #smalloptions_headline, #smalloptions_content, #smalloptions_close, body, html)', function() {
                // $('#smalloptions').remove();
                alert('123');
            });
am besten allen elementen des dialogs eine klasse geben und diese in dem not selector schreiben, z.b.

Code:
  $(document).on('click', ':not(.smalloptions, body, html)', 
                alert('123');
            });

das problem hierbei ist dann wieder das der handelr öfter aufgerufen wird, wenn z.b. ein children nen click bekommt.

indem fall wird er 2 mal aufgerufen wenn man im roten klickt, weil einmal das rote div und dann der parent (das blaue) ein event feuern. Quasi egal, aber unschön, jedenfalls sollte es so klappen

ich würde immernoch sagen das es leichter wäre im clickhandler zu prüfen von welchem element der klick kam und wenn es nicht im dialog war soll er verschwinden, wenn der click aus dem dialog kam, dann wird an den dialog handler deligiert, oder auf die on methode verzichten und beim erstellen des dialogs die handler selber einfügen / entfernen
 
Zuletzt bearbeitet:
keine chance,
bei alle id's einzeln aufzuzählen: reagiert das Schließen nicht mehr,
allen Elementen eine Klasse zu geben: Schließen feuert sobald generiert wird.

Ich glaube auch dass ich den Ansatz ändere und prüfe, auf was geklickt wurde und das dann auswerte. Ich danke dir für deine Mühe und Zeit, Mercsen


EDIT:

Die Lösung ist Folgende:

HTML:
$(document).click(function(e) {

if ($('#smalloptions').length > 0 && e.target.id != 'smalloptions' && $(e.target).parent().attr('id') != "smalloptions" && $(e.target).parent().parent().attr('id') != "smalloptions") {
... 
}

});

Prüfen ob das generierte Element überhaupt exisitiert, dann entsprechend sovieler Ebenen, wie es in der generierten Box gibt das Elternelement auf die Bezeichnung (klasse, id) prüfen (!=). Mit Sicherheit gehts schöner, aber mittlerweile hab ich genug Stunden mit diesem verhältnismässig kleinen Problem verbracht. Danke an die Helfer.

EDIT 2:

Hier die Lösung für unendlich viele Ebenen innerhalb des erzeugten Elements:

HTML:
$(document).click(function(e) {
if ($('#smalloptions').length > 0 && $(e.target).closest('#smalloptions').length == 0) {
$('#smalloptions').remove();
}
});

Beim geklickten Object wird geprüft, ob in den nachfolgenden DOM Ebenen des Objects das Element exisitiert. Hat es eine Länge von 0, so wurde auf ein Object geklickt, dass #smalloptions nicht in seiner übergeordneten DOM-Hierachie besitzt und es kann ausgeblendet werden
 
Zuletzt bearbeitet:
Zurück
Oben