Devre dışı bırakılmış bir girdideki olay


234

Görünüşe göre bir engelli <input>herhangi bir olay tarafından ele alınmıyor

Bu soruna geçici bir çözüm bulmak için bir yol var mı?

<input type="text" disabled="disabled" name="test" value="test" />
$(':input').click(function () {
    $(this).removeAttr('disabled');
})

Burada, etkinleştirmek için girişe tıklamam gerekiyor. Ancak etkinleştirmezsem giriş gönderilmemelidir.



CSS-pretend-devre dışı bırakma özelliğini kullanabilir ve onSubmit işleyicisindeki girişler arasında geçiş yapabilir ve etkinleştirilmemiş olanları gerçekte devre dışı bırakabilirsiniz.
ptrk

Yanıtlar:


267

Devre dışı bırakılan öğeler fare olaylarını tetiklemez. Çoğu tarayıcı, devre dışı bırakılan öğeden kaynaklanan bir olayı DOM ağacına yayar, böylece olay işleyicileri kap öğelerine yerleştirilebilir. Ancak, Firefox bu davranışı sergilemez, devre dışı bırakılmış bir öğeye tıkladığınızda hiçbir şey yapmaz.

Daha iyi bir çözüm düşünemiyorum, ancak tam çapraz tarayıcı uyumluluğu için, bir öğeyi devre dışı girişin önüne yerleştirebilir ve o öğeye tıklayabilirsiniz. İşte ne demek istediğimin bir örneği:

<div style="display:inline-block; position:relative;">
  <input type="text" disabled />
  <div style="position:absolute; left:0; right:0; top:0; bottom:0;"></div>
</div>​

jq:

$("div > div").click(function (evt) {
    $(this).hide().prev("input[disabled]").prop("disabled", false).focus();
});​

Örnek: http://jsfiddle.net/RXqAm/170/ ( propyerine jQuery 1.7 kullanacak şekilde güncellendi attr).


2
Küçük şey: disabledözniteliği değersiz kullanıyorsanız, bu XHTML yerine HTML anlamına gelir, bu durumda kapatma eğik çizgisi gereksizdir.
Tim Down

11
@Tim: gerçekten gereksiz, ancak hala geçerli bir HTML. Bu gerçekten sadece bir alışkanlık gücü ve daha iyi görünüyor gibi hissediyorum.
Andy E

1
Teşekkürler Andy, bu oldukça akıllı. Daha basit değil mi? Devre dışı bırakılan girişlerin neden işlenemediğini biliyor musunuz?
Pierre de LESPINAY

2
Bu bir anlam ifade etmiyor: diğer html öğeleri fare olaylarını işliyor, neden devre dışı bırakılmamış bir öğe (örn. mouseenter, Vb.)
Augustin Riedinger

7
Devre dışı bırakılan öğenin input[disabled] {pointer-events:none}CSS'nizi koyarak tıklamalarınızı "atmasını" durdurabilirsiniz . Ardından tıklama, üst öğeyi tıklamış gibi davranır. IMHO bu en basit, en temiz çözümdür, ancak maalesef sadece pointer-eventsCSS özelliğini destekleyen tarayıcılar için çalışır : caniuse.com/#search=pointer-events
Doin

70

Belki de alanı salt okunur yapabilir ve gönderildiğinde tüm salt okunur alanları devre dışı bırakabilirsiniz

$(".myform").submit(function(e) {
    $("input[readonly]", this).attr("disabled", true);
});

ve girdi (+ script)

<input type="text" readonly="readonly" name="test" value="test" />

$('input[readonly]').click(function () {
    $(this).removeAttr('readonly');
})

5
+1, bu iyi bir alternatif öneri. Tek dezavantajı, giriş kutusunun tarayıcılar arasında değişen devre dışı bırakılmış stili almamasıdır;
Andy E

doğru. Belki de CSS ile bu sorunu çözebilir? Ama evet normal giriş alanları ile aynı görünmeyecek
Tokimon

Mükemmel alternatif çözüm. Bunu daha iyi seviyorum çünkü CSS ile gerekli herhangi bir stil yapabilirsiniz (yani LOOK devre dışı bırak) ama yine de mevcut olaylar var.
Joshua

62

Devre dışı bırakılan öğeler bazı tarayıcılarda tıklamaları "yerler" - ne bunlara yanıt verir ne de öğenin veya herhangi bir kapsayıcısının herhangi bir yerinde olay işleyicileri tarafından yakalanmasına izin vermezler.

IMHO bunu "düzeltmenin" en basit ve en temiz yolu (aslında OP'nin yaptığı gibi devre dışı bırakılmış öğelerin tıklamalarını yakalamanız gerekiyorsa) sayfanıza aşağıdaki CSS'yi eklemektir:

input[disabled] {pointer-events:none}

Bu, devre dışı bırakılan bir girişe yapılan tıklamaların üst öğeye düşmesini sağlar; burada bunları normal şekilde yakalayabilirsiniz. (Birkaç devre dışı girişiniz varsa, zaten bu şekilde yerleştirilmemişlerse, her birini kendi ayrı bir kaba koymak isteyebilirsiniz - ekstra <span>veya bir <div>, örneğin - sadece hangi engelli girişini ayırt etmeyi kolaylaştırmak için tıklandı).


Dezavantajı, bu hile ne yazık ki pointer-eventsCSS özelliğini desteklemeyen eski tarayıcılar için işe yaramaz . (IE 11, FF v3.6, Chrome v4'ten çalışmalıdır ): caniuse.com/#search=pointer-events

Eski tarayıcıları desteklemeniz gerekiyorsa, diğer yanıtlardan birini kullanmanız gerekir!


input[disabled]JavaScript ( element.disabled = true;) tarafından devre dışı bırakılan öğelerle de eşleşip eşleşmeyeceğinden emin değildim, ancak öyle görünüyor. Her neyse, input:disableddaha temiz buluyorum .
Martin

Bu iyi bir çözüm gibi görünüyor, IE11 olsa benim için çalışmıyor! Ayrıca FF 38+ ve Chrome 31+ diyorsunuz, ancak caniuse bağlantınız FF 3.6+ ve Chrome 4+ diyor?
user764754

@ user764754 ... benim hatam, önceki tarayıcı sürümlerini almak için caniuse sayfasında "Tümünü Göster" i tıklatmam gerektiğini fark etmedim! Bunu düzelttim. IE11 gelince, ben sadece test, ve iyi çalışır ( kod için jsfiddle.net/7kkszq1c/1 bakın, bazı nedenlerden dolayı jsFiddle sitesi IE11 benim için işe yaramadı, ben bir yapıştırmak zorunda kaldı. htm dosyası yerine)
Doin

Güncelleme için teşekkürler! Bu arada IE11'de bir web sitesinde çalıştığını ancak jsfiddle ile çalışmadığını da gözlemledim. Belki de jsfiddle iframe yüzünden ...
user764754

2
@Protectorone: devre dışı CSS 3'ten beri sözde bir sınıftır: w3.org/TR/css3-selectors/#UIstates
Martin

15

Ben alternatif - CSS kullanın öneririz:

input.disabled {
    user-select : none;
    -moz-user-select : none;
    -webkit-user-select : none;
    color: gray;
    cursor: pointer;
}

devre dışı bırakılmış öznitelik yerine. Ardından, devre dışı bırakılmış bir girişi simüle etmek için kendi CSS özniteliklerinizi ekleyebilirsiniz, ancak daha fazla kontrolle.


4
sadece ie10 ile çalışır, çok fazla kullanıcı ie9 / 8'e sahiptir. bu nedenle güvenilir bir alternatif değildir.
kodlar

Bu, form gönderildiğinde alanın gönderilmesine neden olur, bu da çoğu durumda istenmeyen bir durumdur.
cimmanon

7

$(function() {

  $("input:disabled").closest("div").click(function() {
    $(this).find("input:disabled").attr("disabled", false).focus();
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<div>
  <input type="text" disabled />
</div>


5
Ama bu FireFox üzerinde çalışmıyor - ve bütün mesele buydu!
GarethOwen

6

Bunun yerine disabledkullanmayı düşünebilirsiniz readonly. Bazı ekstra CSS ile girdiyi disabledalan gibi görünecek şekilde biçimlendirebilirsiniz.

Aslında başka bir sorun daha var. Olay, changeyalnızca öğe bir disabledalanı göz önünde bulunduran mantıksal olmayan odağı kaybettiğinde tetiklenir . Muhtemelen başka bir çağrıdan bu alana veri aktarıyorsunuzdur. Bu işi yapmak için 'bind' etkinliğini kullanabilirsiniz.

$('form').bind('change', 'input', function () {
    console.log('Do your thing.');
});

Eğer yanılmıyorsam formla birlikte salt okunur bir giriş gönderilecektir
Pierre de LESPINAY

Bu doğru. Daha sonra @ npth anwsner ile birleştirilmelidir.
Nykac

Teşekkürler, benim durumum için akıllı temiz ve iyimser.
Sultanos

4

VEYA bunu jQuery ve CSS ile yapın!

$('input.disabled').attr('ignore','true').css({
    'pointer-events':'none',
     'color': 'gray'
});

Bu şekilde öğeyi devre dışı bırakmış olursunuz ve hiçbir işaretçi olayı tetiklenmez, ancak yayılmaya izin verir ve gönderilirse yoksaymak için 'yoksay' özniteliğini kullanabilirsiniz.


@Precastic, bu doğru, ancak bu noktada neredeyse tüm diğer tarayıcılar için çalışıyor ve yani <11 için bir çoklu dolgu kullanabilirsiniz . sidonaldson, neden stil uygulamak için düz CSS kullanmıyorsunuz?
KyleMit

@KyleMit stilleri ayarlamak yerine bir sınıf ekleyebilirsiniz, ancak bu iş parçacığının konusu bu değil! Yalnızca, geliştirdiğiniz tarayıcı matrisine bağlı olarak hala iyi ve doğru bir cevap olan işaretçi olaylarını öneriyordum. Ve burada hiçbir şey yanlış olduğu gibi berbat bu cevabı işaretleyen herkes için teşekkürler: /
sidonaldson

1
@sidonaldson, İyi bir cevap, bu yüzden de daha üst sıralarda yer almasını diliyorum. Yoksay özniteliğinin ne yaptığından emin değilim . Ama CSS ile ilgili kastettiğim, CSS uygulamak için araç olarak jQuery'ye ihtiyacımız olduğunu düşünmüyordum. Sadece aynı seçiciyi hedefleyen ve ayrıca işaretçi olaylarını devre dışı bırakan bir CSS kuralı oluşturabilirsiniz. Bu kemanda , jQuery ve CSS aynı şeyi yapıyor olmalı, ancak CSS çok daha performanslı olacak.
KyleMit

@KyleMit ah, formun gönderildiğini varsayarsak, bir şekilde arka uca bir değer içeriyorsa bu alanı görmezden gelmesini söylemeniz gerekir (kimlik sahtekarlığını devre dışı bıraktığımız için).
sidonaldson

Bir özelliğe dayalı bir seçici kullanabileceğiniz için CSS'nin daha güçlü olabileceğini kabul ediyorum! Kendi devre dışı alanlarını eşleştirdiğim bu demoya göz atın: jsfiddle.net/KyleMit/pxx8pk6v
sidonaldson

0

Bugün böyle bir sorunumuz vardı, ancak HTML'yi değiştirmek istemedik. Bunun için mouseenter etkinliğini kullandık

var doThingsOnClick = function() {
    // your click function here
};

$(document).on({
    'mouseenter': function () {
        $(this).removeAttr('disabled').bind('click', doThingsOnClick);
    },
    'mouseleave': function () {
        $(this).unbind('click', doThingsOnClick).attr('disabled', 'disabled');
    },
}, 'input.disabled');

-1

Başka bir çözüm buldum:

<input type="text" class="disabled" name="test" value="test" />

"Engelli" sınıfı opaklıkla engelli elemanı taklit eder:

<style type="text/css">
    input.disabled {
        opacity: 0.5;
    }
</style>

Ardından, öğe devre dışı bırakılmışsa etkinliği iptal edin ve sınıfı kaldırın:

$(document).on('click','input.disabled',function(event) {
    event.preventDefault();
    $(this).removeClass('disabled');
});

JavaScript bölümü benim için çalışmıyor. Bunun dışında, engelli girişi etkinleştirmekle ilgili olduğu için soruyu cevaplamıyor. Ancak bu örnekte başlangıçta devre dışı bırakılmamıştır ve bu nedenle gönderimde gönderilir.
Raimund Krämer

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.