Archiv für die Kategorie "jQuery"

Tastenkombination / Tastaturkombination / Keyboard Shortcut abfangen und benutzerdefinierte Aktion ermöglichen

Vielleicht möchte man irgendwann einmal Tastenkombinationen / Shortcuts des Benutzers selbst verwerten und die Standardaktion des Browsers verhindern. Zum Beispiel wenn der Benutzer ein Dokument bearbeiten können soll: Beim Drücken der Tastenkombination STRG + S soll dieses direkt gespeichert und nicht der Speichern-Dialog des Browsers (Im Firefox sieht der so aus) geöffnet werden.

Ganz easy geht das mit jQuery und dem Javascript jQuery Hotkeys Plugin

(Für kompletten Code bitte die DEMO ansehen: http://files.philip-ehret.de/dev/examples/jquery/hotkeys_bind.php)

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery.hotkeys-0.7.9.min.js"></script>

Nach Einbinden der jQuery-Bibilothek und des Plugins fehlt nur noch wenig:

jQuery(document).ready(function($){
	$(this).bind('keydown', 'ctrl+s', function(e){
		e.preventDefault(); // Standardaktion verhindern
		$('#someform').submit();
	});
});

Eigentlich würde man jetzt wahrscheinlich noch erläuternde Worte erwarten, aber die gibt’s diesmal nicht, bei der Einfachheit sollte der Code des Beispiels selbsterklärend sein.

Share
Geschrieben von Philip Ehret am 27.11.2009 | Kommentare weiterlesen...

Tabs in einer Textarea ermöglichen oder Howto: Zeichen an aktueller Cursorposition in eine Textarea einfügen

Vielleicht kommt man irgendwann zu einem Punkt, an dem man gerne in einem Textfeld die Möglichkeit hätte, an der aktuellen Cursorposition ein oder mehrere Zeichen einzufügen.
Ein konkretes Beispiel wäre, dass beim Betätigen der Tab-Taste in einem Formularfeld auch wirklich ein Tab im Feld eingefügt werden und nicht – wie sonst üblich – der Fokus auf das nächste Formularelement springen soll.

Alex King hat sich die Mühe gemacht, dafür eine Javascript-Funktion zu schreiben. Da ich gerne mit jQuery arbeite, habe ich eine Implementierung gesucht und auch gefunden:

jQuery.fn.insertAtCaret = function (myValue) {
        return this.each(function(){
                //IE support
                if (document.selection) {
                        this.focus();
                        sel = document.selection.createRange();
                        sel.text = myValue;
                        this.focus();
                }
                //MOZILLA/NETSCAPE support
                else if (this.selectionStart || this.selectionStart == '0') {
                        var startPos = this.selectionStart;
                        var endPos = this.selectionEnd;
                        var scrollTop = this.scrollTop;
                        this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
                        this.focus();
                        this.selectionStart = startPos + myValue.length;
                        this.selectionEnd = startPos + myValue.length;
                        this.scrollTop = scrollTop;
                } else {
                        this.value += myValue;
                        this.focus();
                }
        });
};

In meinem Beispiel 1 wird – befindet sich der Fokus auf dem ersten Textfeld – beim Drücken der Backspace-Taste kein Inhalt gelöscht, sondern neuer hinzugefügt. Interessant für Menschen, denen der Konstruktivismus mehr liegt als der Destruktivismus ;-).

$('textarea#sometest').bind('keydown', function(e){
	if (e.keyCode == 8) { // Backspace
		e.preventDefault(); // Standard-Aktion verhindern
		$(this).insertAtCaret('Bitte nicht so destruktiv. Lieber ein paar mehr Zeichen!');
	}
});

Für den kompletten Code einfach den Quelltext der Beispiel-Seite betrachten.

Ein praktikableres Beispiel ist folgendes, wie oben angedeutet: Beim Drücken der Tab-Taste im zweiten Textfeld der Beispiel-Seite springt der Fokus nicht auf das nächste Textfeld, sondern ein Tab wird im Textfeld eingefügt. So etwas kann von Bedarf sein, möchte man dem Benutzer die Möglichkeit bieten, Quellcode / Text zu bearbeiten, dessen Formatierung von Bedeutung ist (in diesem Fall soll der CSS-Code möglichst lesbarsein).

$('textarea#someothertest').bind('keydown', function(e){
	if (e.keyCode == 9) { // Tab
		e.preventDefault(); // Standard-Aktion verhindern
		$(this).insertAtCaret('\t');
	}
});

Für den gesamten Code ebenfalls den Quelltext der Beispiel-Seite ansehen.

Share
Geschrieben von Philip Ehret am 25.11.2009 | Kommentare weiterlesen...

Seite nach Absenden eines Formulars bzw. Klicken eines Links deaktivieren

Benutzer erwarten oft, dass sie sofort nach Absenden eines Formulars bzw. Klicken eines Links das Ergebnis mit der damit verbundenen Aktion auf ihrem Bildschirm sehen. Jedoch brauchen Skripte eben manchmal ein paar Sekunden, und so kommt es, dass oft mehrmals ein Absende-Button bzw. -Link betätigt wird, was unnötigen Traffic produziert.

Die hier präsentierte Lösung produziert unerwünschte Nebeneffekte, die mir erst später aufgefallen sind:

  • Hat der Benutzer beim Klicken eines Links z.B. die STRG-Taste (für Öffnen in einem neuen Tab), oder die SHIFT-Taste (für Öffnen in einem neuen Fenster) gedrückt, so wird die Aktion zwar ausgeführt, auf der aktuellen Seite bleibt jedoch der Lade-Hinweis. Wieso? Ich bin davon ausgegangen, dass beim Klicken eines Links eine neue Datei vom Browser im aktuellen Tab/Fenster geladen wird. Dadurch verschwindet der Ladehinweis, sobald die neue Seite angezeigt wird. Bei gleichzeitigem Drücken einer der eben genannten Tasten, wird die Seite jedoch nicht im aktuellen Tab/Fenster geladen. Der Lade-Hinweis wird trotzdem angezeigt.

Ich bin mir dessen bewusst geworden, bis zu einem Update sollte dieser Artikel mit Bedacht genossen werden.

Eine einfache Möglichkeit, dies vorzubeugen, lässt sich mit jQuery realisieren:
(DEMO: http://files.philip-ehret.de/dev/examples/jquery/deactivatecontent.html)

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript">
<!--
/**
 * Deaktiviert den Inhalt
 * bzw. blendet Overlay ein
 */
function deactivateControls() {
	var overlay = document.createElement('div');
	$(overlay).attr('id', 'overlay');
	$(overlay).css('filter', 'alpha(opacity=50)'); /*IE-Transparenz-Fix*/
	$(overlay).css('display', 'block');
	$(overlay).prependTo($(document.body));
}
/**
 * Aktiviert den Inhalt
 * bzw. blendet Overlay aus
 */
function activateControls() {
	$('#overlay').css('display', 'none');
	$('#overlay').remove();
}

/**
 * Erstellt einen Lade-Hinweis und zeigt diesen an
 */
function displayLoading() {
	var loading = document.createElement('div');
	$(loading).attr('id', 'loadingNotice');
	$(loading).text('Lade...');
	$(loading).prependTo($(document.body));
}

/**
 * Bindet an alle Submit-Buttons und Links
 * die deactivateControls-Funktion
 */
$(document).ready(function () {
	$('a, input[type="submit"]').bind('click', function(e) {
		/* Inhalt deaktivieren */
		deactivateControls();
		
		/* Ladestatus anzeigen */
		displayLoading();
	})
});
//-->
</script>

Sobald das Dokument für die Manipulation bereit ist ($(document).ready()) wird es nach Links und Submit-Buttons durchsucht. An deren Click-Event werden die Funktion deactivateControls(), welche den Seiteninhalt mit einem halbtransparenten Layer überblendet, und die Funktion displayLoading(), welche einen Lade-Hinweis einblendet, gebunden.

<style type="text/css">
body, html {
	margin: 0;
	padding: 0;
}

#overlay {
	opacity: .5;
	z-index: 10;
	position: fixed;
	display: none;
	width: 100%;
	height: 100%;
	background: #000;
}

#loadingNotice {
	z-index: 150;
	position: fixed;
	top: 35%;
	display: block;
	width: 100%;
	font: 20pt Arial, Helvetica, sans-serif;
	color: #f5f5f5;
	text-align: center;
}
</style>

Durch die Positionierung mit fixed und einen hohen z-index wird gewährleistet, dass die eingefügten Elemente vor dem restlichen Seiteninhalt liegen. Sollte im Projekt bei anderen Elementen der z-index zum Einsatz kommen, ist es wichtig, dass dieser kleiner als der von #overlay und #loadingNotice ist!

Share
Geschrieben von Philip Ehret am 21.09.2009 | Kommentare weiterlesen...