Сохранение по Ctrl+S в браузере

    Могу ошибаться, но решения данной проблемы на Хабре еще не приводилось, так что позвольте поделиться с вами полезным куском кода. Задача: по нажатию Ctrl+S заблокировать браузерный диалог о сохранении страницы и запустить пользовательскую функцию.

    Проблема

    При редактировании данных в формах вместо прилагающейся кнопки «Сохранить» иногда так и хочется нажать привычное Ctrl+S. Это неизменно приводит к появлению стандартного браузерного диалога, который предложит вам сохранить текущую html-страницу.

    С помощью JavaScript попытаемся:
    * заблокировать появление диалога о сохранении;
    * отловить нажатие клавиш и запустить клиентскую функцию, которая, к примеру, может запустить ajax-submit ваших данных;

    Для блокирования стандартной обработки событий в браузере используются:
    * Метод preventDefault() объекта event. Поддерживается в Gecko и Opera.
    * Свойство returnValue объекта event, поддерживаемое в IE.

    Обработчики вешаем с помощью специальной функции addHandler, чтобы не менять лишний раз HTML-код.В зависисмости от браузера блокирование производится для события keydown или keypress. После того, как диалог о сохранении будет убит, можно вызвать угодную нам функцию.

    Код


    // Функция для добавления обработчиков событий
    function addHandler(object, event, handler, useCapture) {
    if (object.addEventListener) {
    object.addEventListener(event, handler, useCapture ? useCapture : false);
    } else if (object.attachEvent) {
    object.attachEvent('on' + event, handler);
    } else alert("Add handler is not supported");
    }

    // Определяем браузеры
    var ua = navigator.userAgent.toLowerCase();
    var isIE = (ua.indexOf("msie") != -1 && ua.indexOf("opera") == -1);
    var isGecko = (ua.indexOf("gecko") != -1);

    // Добавляем обработчики
    if (isIE) addHandler (document, "keydown", hotSave);
    else addHandler (document, "keypress", hotSave);

    function hotSave(evt) {
    // Получаем объект event
    evt = evt || window.event;
    var key = evt.keyCode || evt.which;
    // Определяем нажатие Ctrl+S
    key = String.fromCharCode(key).toLowerCase() == "s";
    if (evt.ctrlKey && key) {
    // Блокируем появление диалога о сохранении
    if(evt.preventDefault) evt.preventDefault();
    evt.returnValue = false;
    // Запускаем любую функцию, по желанию
    clientFunction();
    // Возвращаем фокус в окно
    window.focus();
    return false;
    }
    }
    function clientFunction() {
    // И тут что-то происходит...
    }


    Плагин для jQuery, размещенный на Google Code

    Использование

    Работоспособность проверена в:
    * WIN: IE6, IE7;
    * WIN: FF 1.5, NN 7.1, NN 8.0, Mozilla 1.7;
    * WIN: Opera 7.1, 7.5, 8.0, 9.01, 9.2;
    * MAC: Пишут, что по Mac OS X + FF3b5 работает (но имеено Ctrl+S, а не Command+S);

    Не работает:
    * в Лисе под Linux и Mac OS X при сохранении по Ctrl+Ы. Для фикса нужен патч браузера.

    Приведенный выше скрипт успешно протестирован в системе редактирования баз данных Flede. Привычное нажатие Ctrl+S, и база на вашем хосте получила новые данные, а вы остались на нужной странице и пишите дальше :-)

    Если скрипт не работатет в других браузерах или платформах, пишите в комментах!

    Кросспост Сохранение по Ctrl+S в браузере c webew.ru

    Комментарии 91

      +1
      В системе Flede это сейчас работает в версии 0.73rc, которая доступна с svn. Есть одно пожелание - в firefox под линукс нажатие Ctrl-Ы не срабатывает как Ctrl-S. Это бага firefox, но можно ли пофиксить средствами JS?
        0
        Это особенность Лисы именно под Линукс, под вин — всё ОК.
        Да, надо потестить. Как только доберусь до Линукса — обязательно починю :-)
          +2
          Это бага именно фаера именно под линукс, лечится вот этим https://addons.mozilla.org/ru/firefox/addon/3529 =)
            0
            Это бага линукса и именно хоткеев. В Мозиллу костыли вставить можно, а вот в остальные приложения - проблемно.

            Решения вменяемого я так и не нашел. Может поделится кто?
              0
              мне кажется, это баг только gtk, разве нет ? и вроде бы где то я видел решение на эту тему) но может я ошибаюсь, скорей всего так и есть =)
                0
                линукса - это вы уж слишком )
                скорее GTK, в QT приложениях такого не наблюдается
                  +1
                  Это _не_ баг GTK. Если не обрабатывать сырое событие "key-press-event", а делать акселераторы, то никаких проблем нет. Сам исправлял подобный баг в gajim.
                  Большая часть GTK приложений прекрасно понимают шорткаты в любой раскладке.

                  И, кстати, в Firefox3 баг был исправлен. Но, к сожалению, костылём, который, впрочем, работает лучше, чем вышеупомянутое расширение.
                0
                Don't try it with other languages/layouts, the result will be unpredictable.

                я пользуюсь раскладкой typewriter, у меня этот плагин не будет работать?
                  0
                  Огромное спасибо, оч долго мучался с хоткеями
                  0
                  Поп поводу этого бага в блоге "огненый лис" был топик, где сказано что проблема решена...

                  Можете почтитаь топик про решение проблемы.
                    +1
                    Эта проблема решена в ff3. А вот 1 и 2 версии останутся без этого фикса :(
                    Так что, на мой взгляд, при создании хоткеев надо учитывать и это.
                      0
                      извините что дабл пост, но я не нашел как отредактировать сообщение =(

                      я тут новый...

                      Вот ссылка на решение проблемы с Лисом в Линуксе:

                      http://habrahabr.ru/blog/firefox/28589.html
                    0
                    +1
                    Хороший пост, пишите еще.
                      +1
                      осталось внедрить на хабр (а лучше - повсеместно, где есть формы) :)
                      большое спасибо за статью! буду адаптировать код под jQuery и юзать в проектах :)
                        0
                        Как сделаете решение для jQuery, если Вас не затруднит, отпишите его мне или в комментах. С удовольствием добавлю его в статью.
                          +1
                          Прошу простить, не тестировал совсем :) Просто переложил (с некоторыми неточностями, т.к. jQuery, судя по примерам из документации, не знает gecko, но знает msie, opera, safari & firefox). В общем, предлагаю уважаемому сообществу принять участие в разработке :)

                          var e = "keypress";
                          if($.browser.msie || $.browser.opera) e = "keydown";
                          $(document).bind(e, function(evt){
                          var evt = evt || window.event;
                          var key = evt.keyCode || evt.which;

                          var isIE = $.browser.msie || $.browser.opera;
                          var isGecko = !isIE;
                          key = !isGecko ? (key == 83 ? 1 : 0) : (key == 115 ? 1 : 0);
                          if (evt.ctrlKey && key) {
                          if(evt.preventDefault) evt.preventDefault();
                          evt.returnValue = false;
                          clientFunction();
                          window.focus();
                          return false;
                          })

                          ЗЫ: ногами не бить, с jQuery знаком второй день :)
                            +1
                              0
                              :) за ссылку спасибо, пошёл искать ритуальную стену для самоубийств.
                                0
                                Спасибо!
                                0
                                Работает, только у Вас одной фигурной скобки не хватает закрывающей для ифа в конце.
                                Статья обновлена, спасибо!
                                  +1
                                  Лучше положить в статью ссылку rold. Моё решение кривое (у меня оно под IE7 не заработало, а под FF заработало со второго нажатия).
                                    0
                                    Да, ссылка на гугл будет актуальнее.
                                    А у Вас всё работает, видимость неработоспособности из-за того, что дебажите алертом. Лучше обновите какую-нибудь ноду на страницу, сразу всё станет на свои места ;-)
                                      0
                                      Во всём есть плюсы и минусы :) В ИЕ у меня не заработало так: http://www.href.kz/save
                                      А решение по ссылке исполняет код параллельно с вызовом сохранительного окошка (по крайней мере в опере) :)
                                      Нет в жизни счастья :)
                                        0
                                        Но, попытаться стоило )
                            0
                            Немного не в тему: встречал однажды интересную реализацию отлова CTRL+S на сайте. При нажатии на данную комбинацию открывался DIV, визуально копирующий окно сохранения файла в MSIE. При нажатии кнопки Save страница якобы сохранялась в MyDocuments и div-чик закрывался.
                            Разумеется позже, когда пользователь хотел посмотреть сохранённую страницу и искал её в папке с документами, он там её не обнаруживал.
                              0
                              На локальную машину без использования хаков или activeX яваскрипт никого не пустить. А вот сделать такую вещь с привлечением сервера никто не мешает.
                              Например, Вы жмете Ctrl+S, открывается тот самый ДИВ, похожий на браузерный диалог и предлагает выбрать папку на хосте, для сохранения HTML-документа (при участии БД или еще как, не суть). Вы выбираете и сохраняете.
                              Или в почте — выбрать папку куда положить черновик письма.
                              Возможностей для реализации можно придумать много.
                                0
                                Вы не совсем меня поняли. Данный функционал явно сделан был чтобы ввести пользователя в заблуждение. Пользователь считал, что страница сохранена, чего по сути не происходило. Видимо, таким образом пытались защитить авторский контент. Хотя не уверен: не было защиты от selection, да и "File -> Save As" работало прекрасно. Имхо - просто разработчику не фиг делать было, вот он и реализовал такую "фичу".
                                К сожалению не могу дать ссылку, видел это несколько лет назад и сейчас уже адрес ресурса не помню.
                                  0
                                  Я всё прекрасно понял, и предложил вместо бестолкового решения вариант полезного (более-менее) применения :-)
                                    0
                                    Ну, собственно, в таком случае, простите, Вы изобрели велосипед :)
                                    Схожий функционал реализован у некоторых служб Google (например, GoogleDocs)
                                      0
                                      В таком случае я изобрел 2 велосипеда, сама статья тоже неактуальна в виду того, что Ctrl+S уже реализован у Гугла :-)
                                        0
                                        Боюсь расстроить: http://jshotkeys.googlepages.com/test-st… :)
                                        Другое дело, далеко не всегда желательно подключать большие либы в проекте.
                                          0
                                          Видел уже. Да и когда гмэйлом пользуешься такая реализация сохранения выделяется своим удобством. А вот отдельный скрипт для сохранения нигде не встречал, вот и результат в виде статьи :-)
                                            0
                                            блин... опять эта страница... люблю я её... какое-то неповторимое ощущение зарождается, когда по нажатию Ctrl+W - ничего не происходит :)
                                              0
                                              В Опере очень даже происходит :)
                                                +1
                                                именно поэтому я пока использую решение из статьи, за неимением лучшего :)
                                –3
                                Подкинули бы кармы мне, пост хочу по javascript написать. А то у меня 0 - зарегился неделю назад :)
                                  +1
                                  Совет: не просите карму. Её нужно заслужить, а после таких просьб у кармы имеется тенденция уменьшаться :)
                                    +1
                                    Ну ваше дело :) Если никому неинтересно про то как красиво вписать понятия процесса и потоков и как следствие динамическую подгрузку модулей на javascript.

                                    //
                                    // Dynamic script example.
                                    //

                                    // Load script.
                                    var pLib = new HDynamicScript("Lib\\MapAppTest.js", "Map" ]);
                                    var Map = pLib.GetExport("Map");

                                    var pMap = new Map;

                                    alert(pMap.PrivateData());

                                    Хотел реально полезную штуку осветить, походу тут это не нужно...
                                      0
                                      Почему же не нужно?
                                      Считаете полезным другим - пишите, в этом ограничений нет. А если то, что напишите будет действительно полезным, то проблема кармы и переноса из персонального блога в коллективный очень быстро решится :)
                                      Хинт: для записи в персональный блог карма должна быть >= 0
                                        0
                                        Тут Вы ошибаетесь. В персональный блог нельзя писать с нулевой кармой, только комменты.
                                          0
                                          "опубликовать новый хабратопик в персональный блог — карма >0"
                                          http://habrahabr.ru/info/help/karma/
                                            +1
                                            именно это и сказал bur :)
                                              0
                                              Согласен, мой косяк в операторе.
                                              Но суть осталась: m007 вполне иеет возможность писать в блог.
                                                0
                                                Нет, не осталось.
                                                При регистрации карма = 0.
                                                А писать можно при карме > 0.
                                                Вывод?
                                                  0
                                                  при добавлении коммента карма уже была положительная. А сейчас даже увеличилась. Так что утверждение "m007 вполне иеет возможность писать в блог" верно :)
                                                    0
                                                    При добавлении комментария карма была нулевая (я сам лично это видел), а потом её плюсанули. Поверьте, я сам только пару недель на Хабре. Пока не плюсанут в карму - живешь полностью в комментах.
                                                      0
                                                      Я тоже посмотрел практически сразу. Карма была меньше единицы, но больше нуля.
                                                        0
                                                        Кстати, считаю верным тот момент, что с нулевой кармой писать блог нельзя. Хорошо, если чловек некоторое время будет только читателем. Блоггин на Хабре довольно специфичен :)
                                                0
                                                карма >0
                                                а вы утверждаете, что карма >= 0
                                                ;-)
                                        0
                                        пиши в личный блог. там тебе скажут что надо было писать в блог о яваскриптах, скажешь что кармы не хватает и будет тебе кармы) перенесёшь пост в нужный блог.
                                        +2
                                        Классная штука, мне понравилось. Mac OS X + FF3b5 работает, но в макосях вместо Ctrl+S принято нажимать Command+S, посему диалог появляется, но с Ctrl все работает. На виндовой клаве у меня оно равняется клавише Win.
                                          0
                                          Спасибо! Допишу в топик.
                                          +1
                                          Дополнение про Mac OS X: Ctrl+Ы на Маке не работает.
                                            0
                                            Спасибо, учёл в статье.
                                            +1
                                            Решение для jQuery от Google
                                            Не совсем корректная фраза, скорее «Плагин для jQuery, размещенный на Google Code» :)
                                              0
                                              Спасибо, изменил.
                                              0
                                              Наверняка, многие попробовали нажать ctrl + S после прочтения заголовка :D
                                                +1
                                                чисто ради интереса, зачем блокировать горячие клавиши?
                                                  0
                                                  Если вам нужен интерфейс для сохранения ваших данных, а не HTML-кода страницы, то логично воспользоваться уже существующими хоткеями.
                                                  И их никто не блокирует, их переопределяют для сохранения других данных.
                                                    0
                                                    ничего не понял из вашего ответа :(
                                                    если я нажимаю ctrl+s то должна сохраниться страница. для каких целей блокировать это?
                                                      +1
                                                      Объясню проще.
                                                      Ctrl+S — это горячая клавиша для сохранения.
                                                      А что сохранять, HTML-страницу или введенные пользователем данные решает уже конкретное приложение.
                                                      Есть такой почтовик - Gmail. Так вот, когда я пишу письмо, мне очень удобно по нажатию Ctrl+S сохранять письмо, а не видеть диалог о сохранении страницы.
                                                      Здесь речь идет не просто о блокировании Ctrl+S, а о возможности привязать к этому хоткею другое событие.
                                                        0
                                                        в таком случае, следует предупреждать большими буквами, что ctrl+s сохраняет письмо, а не страницу. иначе такая юзабильность будет только со знаком "−". В том же GMail'e я вовсе не ожидаю сохранения письма по ctrl+s, хоть это и логично было бы.
                                                        Извините за придирство, но это всё равно что взять чью-либо машину и перекрасить в другой цвет.
                                                        А за скрипт респектище!
                                                  +1
                                                  s/Gekko/Gecko
                                                    0
                                                    fixed
                                                    0
                                                    спасибо, интересно. но лично я считаю, что функция сохранения документа должна лежать на браузере. а для сайта следует определить уровень доступности, что-то вроде предупреждения перед сохранением и служебной информацией для браузера как, что и в каком варианте сохранять. так, думаю, будет грамотней и логичней.

                                                    может подкинуть как идейку W3C?:)
                                                      0
                                                      Что и куда сохранять должно определяться приложением исходя из удобства пользователей. Иначе мы получим враждебный по отношению к юзеру интерфейс. Здесь речь идет исключительно о перехвате хоткея. Никакая служебная информация никуда не уходит, а сохранять можно не только документ.
                                                        0
                                                        перехватка хоткея по своей идее вещь не правильная. я говорю о том, что сайт дне должен определять функцию сохранения, в лучшем случае должен указывать браузеру что и как сохранять. отсюда будет и удобство для пользователя и стандарт для сайтостроителя, а для браузера это новая встроенная функция и отсутствие избыточной загрузки яваскрипт кодом.
                                                          0
                                                          1) Под сохранения в данном случае подразумевается отправка HTTP-запросов на хост. Это для юзера выглядит сохранением, а для браузера - ничем не примечательный запрос с данными формы.
                                                          2) В мозгу пользователя хоткей привязан к событию, а не конкретному действию, и это правильно. Неправильно на Ctrl+S привязывать выделение всего документа или закрытие страницы. А сохранение данных, если есть что сохранять и оно часто требуется - очень правильно повесить на этот хоткей.
                                                            0
                                                            1) я рассуждал о том как можно было бы реализовать эту функцию в будущем;)
                                                            2) я согласен с тем, что в голове у пользователя на хоткей Ctrl+S записана одна постоянная функция, не правильным я считаю сокрытие от него факта переделки этой функции и невозможность перенастройки этого хоткея. у браузера есть свой вариант выполнения функции, у авторов сайта свой - получается насильственный запрет функции браузера. а если браузерная функция мне была удобней?
                                                              0
                                                              1) Зачем? Нет, действительно, чем запрос отправленный по хоткею отличается своего обычного собрата?
                                                              2) Ответственность за такие случаи ложится на разработчика приложения. Если разработчик перехватил хоткей там, где все пользуются браузерным — значит он мудак и юзеры быстро забьют на эту страницу.
                                                      0
                                                      Как по мне, неудачная идея переопределять стандартное поведение программы. Один сайт будет реагировать на Ctrl-S стандартно, другой иначе, третий вообще непредсказуемо. Будет каша в головах юзеров и разрыв привычных шаблонов.
                                                        0
                                                        Предполагаю, что Вы не работали с web-приложениями где это реализовано и не представляете насколько это удобно и естественно :-)
                                                        К тому же не стоит втыкать перехват хоткеев по поводу и без повода.

                                                        И еще информация для размышления. Часто ли Вы на страницах ежедневно используемых сайтов (почта, поиск) жмете Ctrl+S для сохранения html-кода? :-)
                                                          –1
                                                          Я, например, работал с приложениями, где это реализовано. И отлично представляю, насколько это неудобно.
                                                          Я привык что броузер по ctrl+s/cmd+s сохраняет страничку, а не делает какую-то там другую фигню. Мне не нужную тем более.

                                                          Моментально проникаюсь отвращением к сайтам, которые пытаются переназначить хоткеи моего браузера.
                                                        +1
                                                        Фича очень полезная, знаю по себе, отработана уже привычка если пишешь "долго" некий текст автоматом жмешь ктрл+Ы, от этого зачастую получаю диалог сохранения страницы =) Так что когда в свое время увидел подобную фишку в редакторе tinymce принял на вооружение и использую в некоторых местах.

                                                        Полностью согласен, что подобную функциональность веб приложение в праве изменять.
                                                        Будем надеяться что данный топик сподвигнет народ использовать подобную функциональность.

                                                        ЗЫ и вообще стандартные хоткеев много ) главное не переборщить.
                                                          0
                                                          Винградовцам, привет! :-)
                                                          Ловите плюс.
                                                          0

                                                          key = !isGecko ? (key == 83 ? 1 : 0) : (key == 115 ? 1 : 0);
                                                          ???
                                                            0
                                                            По кейпрессу разные кейкоды в Гекко и Опере.
                                                              0
                                                              :)
                                                              Я думал, что достаточно будет обратить внимание программиста на строку...
                                                              Что ж, еще раз (конкретнее): key == 83 ? 1 : 0
                                                                0
                                                                key == 83 ? 1 : 0
                                                                Если на клавиатуре нажата клавиша с виртуальным кодом 83 ("S"), то присваиваем флагу истинное значение, если нет - ложное.
                                                                :-)
                                                                Кстати, есть более элегантное решение для всей строки:
                                                                key = String.fromCharCode(key).toLowerCase() == "s" ? 1 : 0;
                                                                  +1
                                                                  key = key == 83;
                                                                  То же самое и для "более элегантного решения", т.к. булева значения, которое возвращает оператор сравнения, вполне достаточно, чтобы не "городить огород".
                                                                    0
                                                                    +1
                                                                    Глаз замылен, не увидел (
                                                            0
                                                            Те, кто используют PrototypeJS, могут поставить просто evt.stop(). Он сам определяет, что использовать: evt.preventDefault() или evt.stopPropogation().

                                                            Если надо делать в iframe, то для IE строчка определения event выглядеть будет так:
                                                            evt = iframe.contentWindow.document.parentWindow.event;
                                                              0
                                                              Имхо, пытаться изменить действие браузера по умолчанию - моветон.
                                                                0
                                                                А что, если вы хотите сделать какой-нибудь тул типа wysiwyg-редактора?
                                                                  –1
                                                                  Стараться не использовать "браузерные" комбинации. Я привык к тому, что Ctrl+S сохраняет страницу и если кому-то вздумается, что на его сайте будет по-другому, то я больше никогда этот сайт не посещу.
                                                                    0
                                                                    Согласен с вами... но не полностью. Обычно такие вещи делаются там, где нужен именно функционал (привычный для большинства пользователей), а не там, где располагается контент.
                                                                0
                                                                Сколько людей - столько мнений. Лично я привык сабмитить данные по Ctrl-Enter, Ctrl-S - сохранение страницы на диск. Веб-приложение ни под каким предлогом не вправе переназначать пользовательские хоткеи, до тех пора пока это явно не указано юзером в настройках.
                                                                  0
                                                                  Вот и я о том же!
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                    0
                                                                    "который повесил на Ctrl-Home переход на главную страницу"
                                                                    а почему просто не нажать home, чтобы попасть наверх страницы?
                                                                    0
                                                                    Привык на маке сохранять cmd+s. почему бы и тут не сделать такой обработчик?

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                    Самое читаемое