Nhấn và giữ trong JavaScript?


117

Có thể thực hiện "báo chí dài" trong JavaScript (hoặc jQuery) không? Làm sao?

văn bản thay thế
(nguồn: androinica.com )

HTML

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

JavaScript

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

7
Tôi có lẽ muốn tạo tùy chỉnh sự kiện jQuery sử dụng mã của bạn như một cơ sở, vì vậy bạn chỉ có thể làm đượcjQuery(...).longclick(function() { ... });
Matti Virkkunen

1
Câu hỏi không được gắn thẻ jQuery, mặc dù nó phải như vậy. Câu hỏi trước tiên yêu cầu một giải pháp Javascript thuần túy, mà tôi thích hơn, hoặc tùy chọn (trong ngoặc đơn), một giải pháp jQuery. Hầu hết các câu trả lời dường như mặc định cho jQuery như một giả định tiêu chuẩn. Tôi luôn coi thường jQuery và chưa một lần sử dụng nó cũng như không cảm thấy có nhu cầu hấp dẫn nào đối với nó. Một số thích sử dụng nó, điều đó là tốt, cho riêng họ. Các câu trả lời bằng cách sử dụng một trong hai kỹ thuật không gây hại gì Nhưng vì câu hỏi sẽ chấp nhận các giải pháp jQuery, thẻ jQuery có thể nhận được nhiều nhãn cầu hơn và hy vọng câu trả lời tốt hơn. Các câu trả lời jQuery ở đây có vẻ mờ nhạt.

Câu trả lời:


159

Không có phép thuật 'jQuery', chỉ là bộ đếm thời gian 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
Điều này sẽ không cháy trên một lực kéo là tốt?
Gallal

11
@Gallal Có lẽ nó sẽ là khá đơn giản để xem đến đó bằng cách gọi clearTimeout(pressTimer)vào mousemove, trừ khi tôi đang thiếu một cái gì đó. Mà phải thừa nhận rằng sẽ khó mà không có tài.
David John Welsh

5
@DavidJohnWelsh Đúng như những gì tôi đang xem, bạn không chỉ muốn di chuyển chuột - giữ ngón tay của bạn cố định và không di chuyển 1px là khá khó! Bạn cần áp dụng một ngưỡng (nếu chuột chưa di chuyển 10px), v.v. Sẽ phức tạp khá nhanh!
Ian

6
Hãy nhớ rằng nếu bạn đang mong đợi điều này hoạt động trên điện thoại, chúng thường có hành vi nhấn lâu mặc định của riêng mình (ví dụ: chrome trên android hiển thị menu phương thức với nhiều tùy chọn khác nhau khi bạn nhấn và giữ một liên kết). Tôi đã không gặp nhiều may mắn trong việc ngăn chặn điều này và thành thật mà nói, việc can thiệp vào hành vi mặc định của trình duyệt dù sao cũng là một ẩn số.
dartacus

4
Mặc dù đây là câu trả lời được chọn, nhưng nó không thực sự trả lời câu hỏi. Nó quá đơn giản và ngây thơ. Bất kỳ sự kiện báo chí dài nào cũng phải giải quyết nhiều vấn đề mà câu trả lời này bỏ qua. 1) Phân biệt nhấn và giữ với kéo từ cử chỉ với chạm đa điểm (tức là chụm để phóng to hoặc thu nhỏ) 2) Hủy nếu chuyển động bên ngoài vùng phần tử hoặc trình duyệt 3) Giải quyết hành vi mặc định của lựa chọn văn bản trên một số nền tảng và thiết bị đáng kể 4) Cho phép một rào cản có thể định cấu hình cho độ nhạy và không dựa vào các con số ma thuật. Đặc biệt hữu ích cho - nhưng không dành riêng cho - mối quan tâm về khả năng tiếp cận.

34

Dựa trên câu trả lời của Maycow Moura, tôi đã viết điều này. Nó cũng đảm bảo rằng người dùng không thực hiện một cú nhấp chuột phải, điều này sẽ kích hoạt một lần nhấn và hoạt động trên thiết bị di động. BẢN GIỚI THIỆU

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);

Bạn cũng nên bao gồm một số chỉ báo bằng cách sử dụng hoạt ảnh 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; }
}

Tôi đã thực hiện phiên bản sửa đổi này, để làm điều gì đó liên tục trong khi nút được giữ jsfiddle nhưng vì một số lý do trên Android, nó vẫn chạy ngay cả sau khi bạn ngừng chạm vào nút + ...
Xander

@Xander: Có thể do :hovertrạng thái dính trên thiết bị cảm ứng, có thể điều đó cũng áp dụng ở đây.
kelunik

Dang, tôi tự hỏi liệu có cách nào để các nút tăng số - / + hoạt động trên một trang web dành cho thiết bị di động hỗ trợ nhấn lâu không. Mọi phương pháp tôi tìm thấy chỉ hỗ trợ việc phải nhấp chuột nhiều lần, điều này gây khó khăn cho những con số khổng lồ. Xin cảm ơn!
Xander

@Xander: Thực ra thì touchendnên kích hoạt IMO, không có lý do gì để nó dính khi nó là mã đặc biệt cho thiết bị cảm ứng, có lẽ ngày mai tôi sẽ thử cái gì đó.
kelunik

1
Đã tìm ra sự cố trên Android. Việc nhấn sẽ kích hoạt cả thời gian dừng lại và khởi động lại, vì vậy nó có 2 bộ hẹn giờ chạy nhưng chỉ 1 bộ bị hủy bằng cách nhấc ngón tay của bạn. Bao quanh bộ bấm giờ với if (bấmtimer === null) để đảm bảo bộ đếm thời gian chưa hoạt động.
Xander


16

Tôi đã tạo long-press-event (0.5k JavaScript thuần túy) để giải quyết vấn đề này, nó thêm một long-presssự kiện vào DOM.

Nghe một long-presstrên bất kỳ yếu tố:

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

Lắng nghe long-pressmột yếu tố cụ thể :

// 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);
});

Hoạt động trong IE9 +, Chrome, Firefox, Safari và các ứng dụng di động kết hợp (Cordova & Ionic trên iOS / Android)

Bản giới thiệu


2
Tuyệt vời, anh bạn !!
Jeff T.

1
Giải pháp này khỉ vá đối tượng window.CustomEvent theo cách hơi lộn xộn, không đầy đủ và không chuẩn. Nó không tạo đúng cách các thuộc tính chỉ đọc như chỉ đọc mà là đọc-ghi. Nó đặc biệt thiếu returnValue, type, timeStamp và isTrusted. Nó không giải quyết các thao tác kéo, cử chỉ, chụm để phóng to hoặc thu nhỏ, hoặc các lỗi chạm nhiều lần khi nhấn lâu, cũng như không giải quyết vấn đề của một số lượng lớn thiết bị và / hoặc nền tảng mặc định nhấn lâu để chọn văn bản ngay cả ở 500ms. Thư viện thiếu bất kỳ và tất cả các trường hợp thử nghiệm cho các điều kiện này.

4
Open Source của nó, cảm thấy tự do để đóng góp cho dự án :)
John Doherty

@JohnDoherty tuyệt vời! nhưng chúng ta vẫn có thể sử dụng "onClick" với cùng một phần tử chứ?
Devashish

2
Bạn vẫn sẽ nhận được sự kiện 'onclick' chừng nào báo chí dài được phát hành trước khi đá 'dài thao tác bấm chậm trễ' đếm thời gian trong
John Doherty

15

Mặc dù nó trông đủ đơn giản để tự thực hiện với thời gian chờ và một vài trình xử lý sự kiện chuột, nhưng nó sẽ phức tạp hơn một chút khi bạn xem xét các trường hợp như nhấp-kéo-thả, hỗ trợ cả nhấn và nhấn giữ trên cùng một phần tử và làm việc với các thiết bị cảm ứng như iPad. Tôi đã kết thúc bằng cách sử dụng plugin longclick jQuery ( Github ), plugin này sẽ chăm sóc những thứ đó cho tôi. Nếu bạn chỉ cần hỗ trợ các thiết bị có màn hình cảm ứng như điện thoại di động, bạn cũng có thể thử sự kiện jQuery Mobile taphold .


Liên kết Github hoạt động, nhưng dự án đã không được cập nhật kể từ năm 2010 và không hoạt động với các phiên bản jquery hiện tại. Tuy nhiên, việc thay thế handle.apply bằng dict.apply trong mã nguồn sẽ khắc phục được điều đó.
arlomedia

11

plugin jQuery. Chỉ cần đặt $(expression).longClick(function() { <your code here> });. Tham số thứ hai là thời lượng giữ; thời gian chờ mặc định là 500 ms.

(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);

điều này không được giữ lại trong cuộc gọi.
Champ

hi Bro chúng ta có thể sử dụng nó như một sự kiện xương sống
user2075328

6

Đối với các nhà phát triển nền tảng chéo (Lưu ý Tất cả các câu trả lời được đưa ra cho đến nay sẽ không hoạt động trên iOS) :

Di chuột lên / xuống dường như hoạt động ổn trên Android - nhưng không phải tất cả các thiết bị tức là (samsung tab4). Hoàn toàn không hoạt động trên iOS .

Nghiên cứu sâu hơn có vẻ như điều này là do phần tử có sự lựa chọn và độ phóng đại bản địa xen kẽ người nghe.

Trình xử lý sự kiện này cho phép mở hình ảnh thu nhỏ theo phương thức bootstrap, nếu người dùng giữ hình ảnh trong 500 mili giây.

Nó sử dụng một lớp hình ảnh đáp ứng để hiển thị một phiên bản hình ảnh lớn hơn. Đoạn mã này đã được kiểm tra đầy đủ trên (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)
});

giải pháp tốt đẹp cho iOS
eric xu

làm cách nào để ngăn các chạm bắt đầu trên hình thu nhỏ, nhưng giả sử kết thúc là một cuộn. nói cách khác, không phải là một touchstart / kết thúc tại chỗ, nhưng một cảm ứng bắt đầu vào phần tử với xử lý, nhưng cuối cùng lại trở thành một cuộn
Akin Hwan

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;
    });
});

BẢN GIỚI THIỆU


2
Đánh dấu mã này, longclick không được kích hoạt khi kết thúc 500ms. Người dùng có thể chết khi nhấp vào chuột :). Nhấp chuột dài chỉ được kích hoạt khi người dùng dừng nhấp vào nút.
jedi

Điều này có giải quyết được trường hợp khi người dùng bắt đầu cuộn thay vì hoàn thành thao tác nhấn phím dài của họ ở cùng một vị trí không?
Akin Hwan

@AkinHwan Không, nó sẽ chỉ được kích hoạt nếu nhấp chuột được thả trên cùng một phần tử.
razz

4

Câu trả lời của Diodeus thật tuyệt vời, nhưng nó ngăn bạn thêm chức năng onClick, nó sẽ không bao giờ chạy chức năng giữ nếu bạn đặt onclick. Và câu trả lời của Razzak là gần như hoàn hảo, nhưng nó chỉ chạy chức năng giữ khi di chuột lên và nói chung, chức năng này sẽ chạy ngay cả khi người dùng tiếp tục giữ.

Vì vậy, tôi đã tham gia cả hai và thực hiện điều này:

$(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
});

những gì nếu người dùng bắt đầu di chuyển sau khi mousedown, và không có ý định làm một nhấn và giữ
Akin Hwan


2

Bạn có thể đặt thời gian chờ cho phần tử đó khi di chuột xuống và xóa nó khi di chuột lên:

$("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;
});

Với điều này, mỗi phần tử sẽ có thời gian chờ riêng.


1
$(this).mouseup(function(){});không loại bỏ trình xử lý sự kiện, nó thêm một trình xử lý khác. Sử dụng .unbindthay thế.
Matti Virkkunen

nên sử dụng off()ngay bây giờ thay vì hủy liên kết.
dbinott

1

Bạn có thể sử dụng taphold của jquery-mobile. Bao gồm jquery-mobile.js và mã sau sẽ hoạt động tốt

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

Điều này sẽ là câu trả lời được chấp nhận kể từ jquery-mobile cung cấp một khuôn khổ tốt ổn định
pasx

1

Thanh lịch và sạch sẽ nhất là một plugin jQuery: https://github.com/untill/jquery.longclick/ , cũng có sẵn dưới dạng packacke: https://www.npmjs.com/package/jquery.longclick .

Tóm lại, bạn sử dụng nó như vậy:

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

Ưu điểm của plugin này là, trái ngược với một số câu trả lời khác ở đây, các sự kiện nhấp chuột vẫn có thể xảy ra. Cũng lưu ý rằng một lần nhấp dài xảy ra, giống như một lần nhấn dài trên thiết bị, trước khi di chuột lên. Vì vậy, đó là một tính năng.


0

Đối với tôi, nó hoạt động với mã đó (với 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

Bạn có thể kiểm tra thời gian để xác định Nhấp chuột hoặc Nhấn lâu [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

như thế này?

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

0

Bạn có thể sử dụng jquerysự kiện Chạm. ( xem tại đây )

  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

Tôi cần một cái gì đó cho các sự kiện bàn phím longpress, vì vậy tôi đã viết cái này.

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

Tôi nghĩ Điều này có thể giúp bạn:

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;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.