Тривале натискання JavaScript?


117

Чи можливо реалізувати "довге натискання" в JavaScript (або jQuery)? Як?

alt текст
(джерело: androinica.com )

HTML

<a href="" title="">Long press</a>

JavaScript

$("a").mouseup(function(){
  // Clear timeout
  return false;
}).mousedown(function(){
  // Set timeout
  return false; 
});

7
Я, мабуть, створив користувальницьку подію jQuery, використовуючи ваш код в якості основи, тож ви просто можете це зробитиjQuery(...).longclick(function() { ... });
Матті Вірккунен

1
Питання не позначене jQuery, хоча так і має бути. Питання задає спочатку чисте рішення Javascript, яке я віддаю перевагу, або необов'язково (в дужках), рішення jQuery. Більшість відповідей здаються типовими для jQuery як стандартного припущення. Я завжди зневажав jQuery і ні разу не використовував його, і не відчував жодної переконливої ​​потреби в ньому. Деяким із задоволенням користуватися ним, що чудово, кожен із своїх. Відповіді за допомогою будь-якої техніки нічого не зашкодили. Але оскільки питання прийме рішення jQuery, тег jQuery може отримати більше очних яблук і, сподіваємось, кращих відповідей. Відповіді jQuery тут здаються непосильними.

Відповіді:


159

Немає ніякої магії "jQuery", лише таймери JavaScript.

var pressTimer;

$("a").mouseup(function(){
  clearTimeout(pressTimer);
  // Clear timeout
  return false;
}).mousedown(function(){
  // Set timeout
  pressTimer = window.setTimeout(function() { ... Your Code ...},1000);
  return false; 
});

39
Не вдалося б і цього вогню перетягнути?
Галлал

11
@Gallal Імовірно це буде досить просто подивитися на що, зателефонувавши clearTimeout(pressTimer)на mousemove, якщо я що - то НЕ вистачає. Що, правда, навряд чи було б безпрецедентним.
Девід Джон Уельс

5
@DavidJohnWelsh Тільки те, що я дивився, ви не хочете просто рухатись мишкою - тримаючи палець мертвим стійко і не рухаючись 1px досить важко! Вам потрібно застосувати поріг (якщо миша не перемістилася 10 пікселів) тощо. Складається досить швидко!
Ян

6
Майте на увазі, що якщо ви очікуєте, що це працюватиме на телефонах, у них часто є власна поведінка за замовчуванням (наприклад, в хромірованому на андроїді, при натисканні посилання відображається модальне меню з різними параметрами). У мене не було великої кількості удачі заважати цьому, і якщо чесно втручатися у поведінку браузера за замовчуванням, все одно приховується.
Дартакус

4
Хоча це і є обрана відповідь, це питання насправді не відповідає. Це надмірно спрощено і наївно. Будь-яка тривала прес-подія повинна вирішувати кілька питань, на які ця відповідь ігнорується. 1) Розрізняйте довге натискання від перетягування від жесту від мультиконтактного (тобто прищипне збільшення або зменшення масштабу) 2) Скасувати, якщо переміщення за межами елемента чи області браузера 3) Визначте поведінку вибору тексту за замовчуванням на значній кількості платформ і пристроїв 4) Дозволити настроюваний поріг для чутливості і не покладатися на магічні числа. Особливо корисно для проблем, пов’язаних із доступністю, але не виключно для них.

34

Спираючись на відповідь Мейкоу Мура, я написав це. Це також гарантує, що користувач не здійснив клацання правою кнопкою миші, що призведе до тривалого натискання та роботи на мобільних пристроях. DEMO

var node = document.getElementsByTagName("p")[0];
var longpress = false;
var presstimer = null;
var longtarget = null;

var cancel = function(e) {
    if (presstimer !== null) {
        clearTimeout(presstimer);
        presstimer = null;
    }

    this.classList.remove("longpress");
};

var click = function(e) {
    if (presstimer !== null) {
        clearTimeout(presstimer);
        presstimer = null;
    }

    this.classList.remove("longpress");

    if (longpress) {
        return false;
    }

    alert("press");
};

var start = function(e) {
    console.log(e);

    if (e.type === "click" && e.button !== 0) {
        return;
    }

    longpress = false;

    this.classList.add("longpress");

    if (presstimer === null) {
        presstimer = setTimeout(function() {
            alert("long click");
            longpress = true;
        }, 1000);
    }

    return false;
};

node.addEventListener("mousedown", start);
node.addEventListener("touchstart", start);
node.addEventListener("click", click);
node.addEventListener("mouseout", cancel);
node.addEventListener("touchend", cancel);
node.addEventListener("touchleave", cancel);
node.addEventListener("touchcancel", cancel);

Ви також повинні включити деякий показник, використовуючи анімацію CSS:

p {
    background: red;
    padding: 100px;
}

.longpress {
    -webkit-animation: 1s longpress;
            animation: 1s longpress;
}

@-webkit-keyframes longpress {
    0%, 20% { background: red; }
    100% { background: yellow; }
}

@keyframes longpress {
    0%, 20% { background: red; }
    100% { background: yellow; }
}

Я зробив цю модифіковану версію, щоб робити щось постійно, поки натиснута кнопка jsfiddle, але чомусь на Android вона працює навіть після того, як ви перестанете торкатися кнопки + ...
Xander,

@Xander: Можливо, тому, що :hoverстан є сенситивним на сенсорних пристроях, можливо, це стосується і тут.
kelunik

Данг, мені цікаво, чи є якийсь спосіб отримати - / + збільшення номерів кнопок, що працюють на мобільному сайті, який підтримує довгі натискання Кожен метод, який я знаходжу, підтримує лише те, що потрібно клацати повторно, що болить за величезну кількість Дякую, хоча!
Ксандр

@Xander: Насправді, touchendякщо слід запустити IMO, немає причини, щоб він був липким, коли це спеціальний код для сенсорних пристроїв, можливо, я спробую щось завтра.
kelunik

1
Вияснили проблему на Android. Натискаючи на пожежі як у мусоні, так і в сенсорному старті, тож було запущено два таймери, але лише 1 скасовано, піднявши палець. Загорнуто престимер, якщо (presstimer === null), щоб переконатися, що таймер ще не був активним.
Xander


16

Я створив події для довгої преси (0,5 К чистого JavaScript), щоб вирішити цю проблему, вона додаєlong-press подію до DOM.

Прослуховуйте текст long-pressна будь-якому елементі:

// the event bubbles, so you can listen at the root level
document.addEventListener('long-press', function(e) {
  console.log(e.target);
});

Слухайте для long-pressна конкретного елемента:

// get the element
var el = document.getElementById('idOfElement');

// add a long-press event listener
el.addEventListener('long-press', function(e) {

    // stop the event from bubbling up
    e.preventDefault()

    console.log(e.target);
});

Працює в IE9 +, Chrome, Firefox, Safari та гібридних мобільних додатках (Cordova & Ionic для iOS / Android)

Демо


2
Приємний, друже !!
Джефф Т.

1
Це рішення мавпи виправляє вікно. Об'єкт CustomEvent дещо випадково, неповно і нестандартно. Він не належним чином створює властивості лише для читання, як лише для читання, але швидше читає-записує. Спеціально відсутній returnValue, type, timeStamp та isTrusted. Він не стосується перетягування, жестів, прискореного збільшення або зменшення масштабу або багаторазових помилок тривалого натискання, а також не вирішує питання великої кількості пристроїв та / або платформ, які за замовчуванням довго натискають на вибір тексту навіть за 500 мс. У бібліотеці відсутні будь-які тестові випадки для цих умов.

4
Це Open Source, не соромтеся брати участь у проекті :)
John Doherty

@JohnDoherty чудово! але чи можемо ми все ж використовувати "onClick" з тим самим елементом?
Девашиш

2
Ви все одно отримаєте подію "onclick" до тих пір, поки триватиме довге натискання, перш ніж починається таймер "тривалої затримки натискання"
Джон Догерті

15

Хоча це виглядає досить просто, щоб самостійно реалізувати з таймаутом та кількома обробниками подій миші, це стає дещо складніше, коли ви розглядаєте випадки, такі як перетягування натискання, підтримуючи як натискання, так і довге натискання на один і той же елемент та робота з сенсорними пристроями, такими як iPad. Я в кінцевому рахунку використовував плагін longclick jQuery ( Github ), який піклується про ці речі для мене. Якщо вам потрібно підтримувати лише пристрої з сенсорним екраном, такі як мобільні телефони, ви можете також спробувати подію jQuery Mobile .


Посилання Github працює, але проект не оновлювався з 2010 року і не працює з поточними версіями jquery. Однак заміна handle.apply на dispatch.apply у вихідному коді виправляє це.
arlomedia

11

плагін jQuery. Просто кажу $(expression).longClick(function() { <your code here> });. Другий параметр - тривалість утримування; тайм-аут за замовчуванням - 500 мс.

(function($) {
    $.fn.longClick = function(callback, timeout) {
        var timer;
        timeout = timeout || 500;
        $(this).mousedown(function() {
            timer = setTimeout(function() { callback(); }, timeout);
            return false;
        });
        $(document).mouseup(function() {
            clearTimeout(timer);
            return false;
        });
    };

})(jQuery);

це не зберігається у виклику.
Чемпіль

Привіт, Бро, можемо ми використовувати його як основу події
user2075328

6

Для розробників крос-платформ (Примітка. Надані відповіді на даний момент не працюватимуть на iOS) :

Начебто миша / вниз працює нормально на Android - але не на всіх пристроях, тобто (samsung tab4). Зовсім не працював на iOS .

Подальше дослідження здається, що це пов'язано з елементом, що має вибір, і нативне збільшення збільшує слухача.

Цей слухач подій дозволяє відкрити мініатюрне зображення у режимі завантаження, якщо користувач утримує зображення протягом 500 мс.

Він використовує клас чуйних зображень, тому показує більшу версію зображення. Цей фрагмент коду було повністю перевірено (iPad / Tab4 / TabA / Galaxy4):

var pressTimer;  
$(".thumbnail").on('touchend', function (e) {
   clearTimeout(pressTimer);
}).on('touchstart', function (e) {
   var target = $(e.currentTarget);
   var imagePath = target.find('img').attr('src');
   var title = target.find('.myCaption:visible').first().text();
   $('#dds-modal-title').text(title);
   $('#dds-modal-img').attr('src', imagePath);
   // Set timeout
   pressTimer = window.setTimeout(function () {
      $('#dds-modal').modal('show');
   }, 500)
});

приємне рішення для iOS
eric xu

як би я не допустив дотиків, які починаються на ескізі, але скажімо, що це прокрутка. Іншими словами, не сенсорний запуск / кінець на місці, а дотик, який почався на елементі з обробника, але закінчується прокруткою
Акін Хван,

5
$(document).ready(function () {
    var longpress = false;

    $("button").on('click', function () {
        (longpress) ? alert("Long Press") : alert("Short Press");
    });

    var startTime, endTime;
    $("button").on('mousedown', function () {
        startTime = new Date().getTime();
    });

    $("button").on('mouseup', function () {
        endTime = new Date().getTime();
        longpress = (endTime - startTime < 500) ? false : true;
    });
});

DEMO


2
Хоча цей код, longclick не запускається в кінці 500 мс. Користувач може померти, натиснувши мишкою :). Довге натискання запускається, лише якщо користувач перестає натискати кнопку.
jedi

Чи охоплює це випадок, коли користувач почав прокручувати замість того, щоб закінчити свій longpress на тому ж місці?
Акін Хван

@AkinHwan Ні, це може спрацювати лише в тому випадку, якщо натискання миші буде випущено над тим самим елементом.
малина

4

Відповідь Діодея є приголомшливою, але це заважає вам додавати функцію onClick, вона ніколи не запустить функцію утримування, якщо ви поставите onclick. І відповідь Razzak майже досконала, але вона працює утримуючи функцію лише при натисканні миші, і, як правило, функція працює навіть у тому випадку, якщо користувач продовжує триматися.

Отже, я приєднався до обох і зробив це:

$(element).on('click', function () {
    if(longpress) { // if detect hold, stop onclick function
        return false;
    };
});

$(element).on('mousedown', function () {
    longpress = false; //longpress is false initially
    pressTimer = window.setTimeout(function(){
    // your code here

    longpress = true; //if run hold function, longpress is true
    },1000)
});

$(element).on('mouseup', function () {
    clearTimeout(pressTimer); //clear time on mouseup
});

що робити, якщо користувач починає прокручувати після маунтаун, і не збирається робити давню клавішу
Акін Хван,


2

Ви можете встановити тайм-аут для цього елемента при натисканні миші та очистити його вгору:

$("a").mousedown(function() {
    // set timeout for this element
    var timeout = window.setTimeout(function() { /* … */ }, 1234);
    $(this).mouseup(function() {
        // clear timeout for this element
        window.clearTimeout(timeout);
        // reset mouse up event handler
        $(this).unbind("mouseup");
        return false;
    });
    return false;
});

З цим кожен елемент отримує свій тайм-аут.


1
$(this).mouseup(function(){});не видаляє обробник подій, він додає ще один. Використовуйте .unbindзамість цього.
Матті Вірккунен

слід використовувати off()зараз, а не відв'язувати.
dbinott

1

Ви можете скористатися jquery-mobile. Включіть jquery-mobile.js і наступний код буде добре працювати

$(document).on("pagecreate","#pagename",function(){
  $("p").on("taphold",function(){
   $(this).hide(); //your code
  });    
});

Це має бути прийнятою відповіддю, оскільки jquery-mobile забезпечує хороші стабільні рамки
pasx

1

Найелегантніший та чистіший плагін jQuery: https://github.com/untill/jquery.longclick/ , доступний також як packcke: https://www.npmjs.com/package/jquery.longclick .

Словом, ви використовуєте його так:

$( 'button').mayTriggerLongClicks().on( 'longClick', function() { your code here } );

Перевага цього плагіна полягає в тому, що, на відміну від деяких інших відповідей тут, події клацання все ще можливі. Зауважте також, що довге натискання відбувається, як і довгий натискання на пристрої, перед мишею. Отже, це особливість.


0

Для мене це робота з цим кодом (з jQuery):

var int       = null,
    fired     = false;

var longclickFilm = function($t) {
        $body.css('background', 'red');
    },
    clickFilm = function($t) {
        $t  = $t.clone(false, false);
        var $to = $('footer > div:first');
        $to.find('.empty').remove();
        $t.appendTo($to);
    },
    touchStartFilm = function(event) {
        event.preventDefault();
        fired     = false;
        int       = setTimeout(function($t) {
            longclickFilm($t);
            fired = true;
        }, 2000, $(this)); // 2 sec for long click ?
        return false;
    },
    touchEndFilm = function(event) {
        event.preventDefault();
        clearTimeout(int);
        if (fired) return false;
        else  clickFilm($(this));
        return false;
    };

$('ul#thelist .thumbBox')
    .live('mousedown touchstart', touchStartFilm)
    .live('mouseup touchend touchcancel', touchEndFilm);

0

Ви можете перевірити час для виявлення клацання або тривалого натискання [jQuery]

function AddButtonEventListener() {
try {
    var mousedowntime;
    var presstime;
    $("button[id$='" + buttonID + "']").mousedown(function() {
        var d = new Date();
        mousedowntime = d.getTime();
    });
    $("button[id$='" + buttonID + "']").mouseup(function() {
        var d = new Date();
        presstime = d.getTime() - mousedowntime;
        if (presstime > 999/*You can decide the time*/) {
            //Do_Action_Long_Press_Event();
        }
        else {
            //Do_Action_Click_Event();
        }
    });
}
catch (err) {
    alert(err.message);
}
} 

0

подобається це?

doc.addEeventListener("touchstart", function(){
    // your code ...
}, false);    

0

Ви можете використовувати jqueryподії Touch. ( див. тут )

  let holdBtn = $('#holdBtn')
  let holdDuration = 1000
  let holdTimer

  holdBtn.on('touchend', function () {
    // finish hold
  });
  holdBtn.on('touchstart', function () {
    // start hold
    holdTimer = setTimeout(function() {
      //action after certain time of hold
    }, holdDuration );
  });

0

Мені потрібно було щось для подій на клавіатурі longpress, тому я написав це.

var longpressKeys = [13];
var longpressTimeout = 1500;
var longpressActive = false;
var longpressFunc = null;

document.addEventListener('keydown', function(e) {
    if (longpressFunc == null && longpressKeys.indexOf(e.keyCode) > -1) {
        longpressFunc = setTimeout(function() {
            console.log('longpress triggered');
            longpressActive = true;
        }, longpressTimeout);

    // any key not defined as a longpress
    } else if (longpressKeys.indexOf(e.keyCode) == -1) {
        console.log('shortpress triggered');
    }
});

document.addEventListener('keyup', function(e) {
    clearTimeout(longpressFunc);
    longpressFunc = null;

    // longpress key triggered as a shortpress
    if (!longpressActive && longpressKeys.indexOf(e.keyCode) > -1) {
        console.log('shortpress triggered');
    }
    longpressActive = false;
});

0

Я думаю, що це може допомогти вам:

var image_save_msg = 'You Can Not Save images!';
var no_menu_msg = 'Context Menu disabled!';
var smessage = "Content is protected !!";

function disableEnterKey(e) {
    if (e.ctrlKey) {
        var key;
        if (window.event)
            key = window.event.keyCode; //IE
        else
            key = e.which; //firefox (97)
        //if (key != 17) alert(key);
        if (key == 97 || key == 65 || key == 67 || key == 99 || key == 88 || key == 120 || key == 26 || key == 85 || key == 86 || key == 83 || key == 43) {
            show_wpcp_message('You are not allowed to copy content or view source');
            return false;
        } else
            return true;
    }
}

function disable_copy(e) {
    var elemtype = e.target.nodeName;
    var isSafari = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
    elemtype = elemtype.toUpperCase();
    var checker_IMG = '';
    if (elemtype == "IMG" && checker_IMG == 'checked' && e.detail >= 2) {
        show_wpcp_message(alertMsg_IMG);
        return false;
    }
    if (elemtype != "TEXT" && elemtype != "TEXTAREA" && elemtype != "INPUT" && elemtype != "PASSWORD" && elemtype != "SELECT" && elemtype != "OPTION" && elemtype != "EMBED") {
        if (smessage !== "" && e.detail == 2)
            show_wpcp_message(smessage);

        if (isSafari)
            return true;
        else
            return false;
    }
}

function disable_copy_ie() {
    var elemtype = window.event.srcElement.nodeName;
    elemtype = elemtype.toUpperCase();
    if (elemtype == "IMG") {
        show_wpcp_message(alertMsg_IMG);
        return false;
    }
    if (elemtype != "TEXT" && elemtype != "TEXTAREA" && elemtype != "INPUT" && elemtype != "PASSWORD" && elemtype != "SELECT" && elemtype != "OPTION" && elemtype != "EMBED") {
        //alert(navigator.userAgent.indexOf('MSIE'));
        //if (smessage !== "") show_wpcp_message(smessage);
        return false;
    }
}

function reEnable() {
    return true;
}
document.onkeydown = disableEnterKey;
document.onselectstart = disable_copy_ie;
if (navigator.userAgent.indexOf('MSIE') == -1) {
    document.onmousedown = disable_copy;
    document.onclick = reEnable;
}

function disableSelection(target) {
    //For IE This code will work
    if (typeof target.onselectstart != "undefined")
        target.onselectstart = disable_copy_ie;

    //For Firefox This code will work
    else if (typeof target.style.MozUserSelect != "undefined") {
        target.style.MozUserSelect = "none";
    }

    //All other  (ie: Opera) This code will work
    else
        target.onmousedown = function() {
            return false
        }
    target.style.cursor = "default";
}
// on_body_load

window.onload = function() {
    disableSelection(document.body);
};



// disable_Right_Click



document.ondragstart = function() {
    return false;
}

function nocontext(e) {
    return false;
}
document.oncontextmenu = nocontext;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.