Как стать автором
Обновить
0

PHPLego: Горячие клавиши — атрибут hotkey

Время на прочтение6 мин
Количество просмотров8.2K
PHPLego: PHPLego: Горячие клавиши - атрибут hotkey

Дорогие друзья! Сегодня я хочу поделиться с Вами 138-мью строчками кода, которые позволяют ссылки <a> и кнопки <input type='submit'> расширить атрибутом hotkey.

Ведь иногда хочется, чтобы форма отправлялась по CTRL+Enter, а часто используемые пункты меню были доступны по какой-то своей хитрой комбинации клавиш.
А еще не хочется на эти мелкие удобства тратить время, ведь горячие клавиши — это далеко не для каждого. Хотя если к ним привыкнуть — отучиться просто невозможно.

Подключив файлик hotkeys.js, который будет описан ниже, появляется возможность задавать горячие клавиши любым ссылками и кнопкам отправки форм вот так:
<a href='...' hotkey="Ctrl + Shift + D">удалить</a>
или
<input type='submit' hotkey='Ctrl + Enter' value='Отправить'>




Дело в том, что описывать каждый раз обработчик на нажатие клавиши, когда появилось желание добавить на сайт горячих клавиш — не самый удобный вариант. Слишком много чести, для такой неглобальной задачи — потому то это и не очень распространено. Обычно решающим фактором оказывается банальная лень. А заказчики сами такого требовать не будут (пока, конечно, не прознают где-нибудь, что это типа модно). Поэтому я предлагаю вариант для ленивых — никаких обработчиков, кроме одного единственного. А горячая клавиша становится самодокументированной благодаря тексту из ссылки.

Вот эти строчки, содержимое файла hotkeys.js:
// ГОРЯЧИЕ КЛАВИШИ, файл hotkeys.js
// Для работы требуется JQuery. Автор: Олег Йожик Дубров

$(function(){
	// Задаем псевдоними для каждой кнопки, создав специальный ассоциативный массив:
	var keyCodes = {D:68, E:69, F:70, M:77, N:78, O:79, U:85, Esc:27, "/":220,
		"0":48, "1":49,  "2":50, "3":51, "4":52, "5":53, "6":54, "7":55, "8":56, "9":57,
		Left:37, Up:38, Right:39, Down:40, Enter:13, Ctrl:17, Alt:18, Space:32
		// прошу простить, тут не все коды клавиш
	};
	
	// заготовка всплыающей подсказки (оранжевый болончик над ссылками и инпутами)
	var prompt = $("<div class='hotprompt'>-</div>");
	prompt.css("position", "absolute");
	prompt.css("padding", "1px 3px");
	prompt.css("font-size", "8px");
	prompt.css("background-color", "orange");
	prompt.css("color", "black");
	prompt.css("opacity", "0.8"); // легкая полупрозрачность не повредит
	prompt.css("border", "1px solid black");
	// скруглим её особым образом, оставив один угл острым:
	prompt.css("border-radius", "7px 7px 0px 7px"); 
	prompt.css("-moz-border-radius", "7px 7px 0px 7px");
	
	// показать подсказки к клавишам
	var showHotPrompts = function(){
		if($(".hotprompt").length > 0) return ;
		// для каждого инпута или ссылки, с атрибутом hotkey
		$("a[hotkey], input[hotkey]").each(function(a){
			p = prompt.clone(); // клонируем заготовку, которую мы создали
			p.html($(this).attr("hotkey")); //помещаем в нее строку "Ctrl + .."
			p.insertAfter($(this)); //вставляем подсказку сразу после самой ссылки
			// располжим её так, чтобы острый уголок пришелся на левый верхний угол ссылки:
			p.css("left", $(this).position().left - p.width());
			p.css("top", $(this).position().top - p.height());
		});
	}
	
	// скрыть эти подсказки
	var hideHotPrompts = function(){
		// путем их тупого удаления:
		$("a[hotkey], input[hotkey]").each(function(a){
			$(".hotprompt").remove();
		});
	}
    
    // просто функция, проверяющая массив на предмет существования элемента
	var in_array = function(needle, haystack){
		for (key in haystack)
			if (haystack[key] == needle) return true;
		return false;
	}
	
	
	// Если нажата клавиша на странице
	$("html").keydown(function(e){
		var lastGood = false;
		// то перебираем все ссылки и инпуты, у которых есть атрибут hotkey
		$("a[hotkey], input[hotkey]").each(function(a){
			var hotkey = $(this).attr("hotkey"); // значение атрибута (например Ctrl + E)
			var words = hotkey.split("+"); //разделяем значению плюсом
			// Последний элемент в этом массиве - это сама клавиша:
			var key = words.pop().replace(/\s/,""); // вытаскиваем её и вырезаем все пробелы
			var syskeys = new Array();
			// Оставшиеся в массиве клавиши считаются системными (Ctrl, Alt, Shift)
			for(var i in words) syskeys.push(words[i].replace(/\s+/g,""));
			if(keyCodes[key] != e.keyCode) return; //код клавиши не подошел - прочь
			if(in_array('Ctrl', syskeys)    && !e.ctrlKey) return; //Ctrl не подошел - прочь
			if(in_array('Alt', syskeys)     && !e.altKey) return;  //Alt не подошел - прочь
			if(in_array('Shift', syskeys)   && !e.shiftKey) return;//Shift не подошел - прочь
			//если на странице несколько одинаковых клавиш, то сработает только последняя:
			lastGood = $(this); //переменная просто затрется последней подходящей клавишей
		});
		//если подходящая под нажатую комбинацию ссылка (или инпут) таки найдена:
		if(lastGood){ 
			// то если это форма, то субмитим:
			if(lastGood.attr("type") == 'submit')
				$(lastGood.context.form).submit();
			else{ // а если ссылка, то кликаем
				var href = lastGood.attr("href");
				lastGood.click();
			}
			return false; // и дефолтное поведение браузера отменяем
		}
		
		// А это для прочих случаев:
		// если нажата клавиша CTRL - то показываем оранжевую карту клавиш
		if(e.keyCode == keyCodes.Ctrl){ 
			showHotMap();
			showHotPrompts(); //и подсказки
		}
	});
	
	// на отпускание любой клавиши - скрываем подсказки и карту клавиш
	$("html").keyup(function(e){
		if(e.keyCode == keyCodes.Ctrl){ 
			hideHotPrompts();
			hideHotMap();
		}
	});

    // если куда-нибудь кликнули - скрываем все подсказки и карту клавиш
    $("html").click(function(e){
        hideHotPrompts();
        hideHotMap();
    });
    
    // показать оранжевую карту клавиш (тот самый большой квадрат со списком клавиш)
    var showHotMap = function(){
        if($(".hotsitemap").length > 0) return ;
        // создаем ораньжевый квадрат
        var hotmap = $("<div>");
        $("body").append(hotmap);
        hotmap.addClass("hotsitemap"); 
        hotmap.css('background-color', 'orange');
        hotmap.css('position', 'fixed'); //он будет не зависить от прокрутки
        hotmap.css('color', 'black');
        hotmap.css('top', '200px');      //свисая сверху на двухстах пикселях
        hotmap.css('padding', '20px');
        hotmap.css("border-radius", "10px"); //будучи скруглен, как я люблю
        hotmap.css("-moz-border-radius", "10px");//даже в мозилле
        hotmap.append("<h3>Горячие клавиши</h3>");
        // и наполняем его самими клавишами и пояснениями из ссылок
        $("a[hotkey]").each(function(){
            var hotkey = $(this).attr("hotkey");
            var value = $(this).html(); // текст ссылки <a href=...>вот этот</a>
            var title = $(this).attr("title"); // <a title='вот этот'>...
            // Возмем из этих двоих тот, что подлинне (скорее всего он более информативнее)
            var display_text = value.length > title.length ? value : title;
            // И дописываем этот текст и клавишу в квадрат:
            hotmap.append("<b>"+hotkey+"</b> "+display_text+"<br />"); 
        });
    }
    
    // скрыть эту карту
    var hideHotMap = function(){
        $(".hotsitemap").remove();
    }
});


Говоря русским языком, этот скрипт по нажатию на комбинацию клавиш пробегает по всем элементам, содержащим атрибут hotkey и, если нашел элемент с такой комбинацией — кликает по нему. Если же элементов с такой комбинацией несколько — то кликает по последнему из них.

Также, по нажатию на Ctrl он отображает над каждым горячим элементом всплывающую подсказку о возможности воспользоваться горячей клавишей. Еще, в этот же момент, он отображает блок, в котором списком перечислены все горячие клавиши страницы.

Этот блок хорош тем, что он отображает все, даже скрытые горячие клавиши (т.е. клавиши на ссылках, у которых стоит стиль display:none). Таким образом можно на страницу поместить список скрытых ссылок на всякие разделы, для которых нет соответствующего пункта меню, и породить тем самым еще один короткий путь в эти разделы.

Пользуясь случаем, хочу обратиться к создателям браузеров


Уважаемые разработчики! Пожалуйста, включите вы эти 138 строчек кода в сам браузер, неужели это так сложно? Обещаем, мы будем этим пользоваться. Вот читатели Хабра не дадут соврать. И скажем вам за это огромное спасибо! Сжальтесь над нами, теми кто терпит ваши расхождения в стандартах, замысловатости и различия подходов к яваскрипту и атрибутов HTML. Над простыми программистами и верстальщикамии, теми кто с почтением ждет каждый новый атрибут CSS и трудятся как рабы на галерах, на базе возможностей, которые создаете вы, ради того чтобы создать то, что требуют от нас клиенты. Вы стоите у истоков этой пирамиды, и я надеюсь вы осознаете всю важность ответственности, которая ложится на ваши кончики пальцев. Мы ценим и уважаем работу, проделанную вами за все эти годы и я надеюсь вы прислушаетесь к нам и нашим советам.

Дорогие Хаброчитатели, вчера я распрощался со своей старой работой, из-за того, что писал статьи на Хабре. Друзья, я рассчитываю на вас. Если вам не безразлично будущее и развитее браузеров, если вы чувствуете дискомфорт от сложившийся ситуации — действуйте. Вы можете повлиять на существующую несправедливось! Нас читают десятки тысяч людей из сферы IT. Мы можем и должны активно участвовать в формировании необходимых нам тегов, атрибутов, параметров и прочих полезных нововведений. Многое еще не сделано, и если мы будем молчать — неизвестно сколько понадобится времени, чтобы их наконец осенило. Поэтому я прошу отписаться всех тех, кто за то чтобы включить атрибут hotkey в кликабельные элементы HTML.

Я ЗА! Олег Йожик
Теги:
Хабы:
Всего голосов 60: ↑50 и ↓10+40
Комментарии66

Публикации

Информация

Сайт
xn--e1afggmlij4g.xn--p1ai
Дата регистрации
Дата основания
Численность
1 человек (только я)
Местоположение
Россия

Истории