การเลือกข้อความที่โฟกัสโดยใช้ jQuery ไม่ทำงานใน Safari และ Chrome


85

ฉันมีรหัส jQuery ต่อไปนี้ (คล้ายกับคำถามนี้ ) ที่ใช้งานได้ใน Firefox และ IE แต่ล้มเหลว (ไม่มีข้อผิดพลาดเพียงแค่ใช้งานไม่ได้) ใน Chrome และ Safari มีแนวคิดสำหรับวิธีแก้ปัญหาหรือไม่?

$("#souper_fancy").focus(function() { $(this).select() });

ฉันต้องการพฤติกรรมที่แน่นอนใน Safari ของ iPad / iPhone สิ่งนี้ไม่ทำงานในเบราว์เซอร์ iPod / iPhone เบาะแสใด ๆ คำตอบที่ยอมรับด้านล่างนี้มีไว้สำหรับ Chrome / ซาฟารีบนเดสก์ท็อปเท่านั้น
Anand

5
หมายเหตุ: คำตอบที่ยอมรับในที่นี้จะช่วยแก้ปัญหาได้เพียงครึ่งเดียว ทำให้การเลือกใช้งานได้ แต่ทำให้ยากที่จะยกเลิกการเลือกด้วยการคลิกในภายหลัง พบทางออกที่ดีกว่าได้ที่นี่: stackoverflow.com/questions/3380458/…
SDC

คำตอบ:


188

เป็นเหตุการณ์ onmouseup ที่ทำให้การเลือกไม่ถูกเลือกดังนั้นคุณต้องเพิ่ม:

$("#souper_fancy").mouseup(function(e){
    e.preventDefault();
});

3
อ้างอิงเพิ่มเติมเกี่ยวกับข้อบกพร่องที่นี่: code.google.com/p/chromium/issues/detail?id=4505
Rajat

วิธีการบรรลุเดียวกันโดยใช้ Prototype?
tehfink

คุณยังสามารถลองเชื่อมโยงกับเหตุการณ์ 'คลิก' และหลีกเลี่ยงการผูกสองครั้ง
uglymunky

@uglymunky ขึ้นอยู่กับสิ่งที่คุณกำลังทำการเชื่อมโยงกับเหตุการณ์การคลิกจะไม่ได้ผลในทุกกรณีอย่างไรก็ตามมีวิธีการอื่นในการเลือกช่องป้อนข้อมูลนอกเหนือจากการคลิกและคุณต้องการให้สิ่งเหล่านั้นทำงานได้เช่นกัน (เช่น แท็บเข้าไป)
Tacroy

2
ฉันต้องการพฤติกรรมที่แน่นอนใน Safari ของ iPad / iPhone สิ่งนี้ไม่ทำงานในเบราว์เซอร์ iPod / iPhone เบาะแสใด ๆ
Anand

25
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});

3
นี่คือคำตอบที่ดีที่สุดหากคุณกำลังพยายามเลือกข้อความในช่องแบบฟอร์มสำหรับแอป PhoneGap ที่ทำงานบน Android สิ่งนี้ทำให้ผู้ใช้เห็นภาพว่าข้อความถูกเลือกในขณะที่คำตอบที่ยอมรับไม่ได้
BallisticPugh

4

ใช้งานได้ดีสำหรับองค์ประกอบอินพุต type = "text" #souper_fancy เป็นองค์ประกอบประเภทใด

$("#souper_fancy").focus(function() {
    $(this).select();
});

มันเป็นองค์ประกอบ type = "text" ฉันลอง $ ("input [type = text]") ด้วย ยังไม่ทำงานกับ jQuery 1.3.2 ใน Safari
user140550

3

เพียงแค่ป้องกันไม่ให้ค่าเริ่มต้นของการวางเมาส์ทำให้การเลือกข้อความเปิดอยู่ตลอดเวลา เหตุการณ์ MOUSEUP มีหน้าที่ล้างการเลือกข้อความ อย่างไรก็ตามด้วยการป้องกันพฤติกรรมเริ่มต้นคุณจะไม่สามารถยกเลิกการเลือกข้อความโดยใช้เมาส์ได้

เพื่อหลีกเลี่ยงสิ่งนั้นและทำให้การเลือกข้อความทำงานอีกครั้งคุณสามารถตั้งค่าสถานะบน FOCUS อ่านจาก MOUSEUP และรีเซ็ตเพื่อให้เหตุการณ์ MOUSEUP ในอนาคตทำงานได้ตามที่คาดไว้

$("#souper_fancy").focus(function() {
    $(this).select();

    //set flag for preventing MOUSEUP event....
    $this.data("preventMouseUp", true);
});

$("#souper_fancy").mouseup(function(e) {
    var preventEvent = $this.data("preventMouseUp");

    //only prevent default if the flag is TRUE
    if (preventEvent) {
        e.preventDefault();
    }

    //reset flag so MOUSEUP event deselect the text
    $this.data("preventMouseUp", false);
});

1

แม้ว่าจะใช้งานได้กับการเลือกใน IE, Firefox, Chrome, Safari และ Opera แต่จะไม่อนุญาตให้คุณแก้ไขโดยคลิกครั้งที่สองใน Firefox, Chrome และ Safari ไม่แน่ใจทั้งหมด แต่ฉันคิดว่านี่อาจเป็นเพราะเบราว์เซอร์ 3 ตัวนั้นออกเหตุการณ์โฟกัสอีกครั้งแม้ว่าฟิลด์นั้นจะมีโฟกัสอยู่แล้วจึงไม่อนุญาตให้คุณแทรกเคอร์เซอร์จริง ๆ (เนื่องจากคุณเลือกอีกครั้ง) ในขณะที่ใน IE และ Opera ดูเหมือนว่าจะไม่ทำเช่นนั้นดังนั้นเหตุการณ์โฟกัสจะไม่ถูกยิงอีกครั้งและทำให้เคอร์เซอร์ถูกแทรก

ฉันพบวิธีแก้ไขที่ดีกว่าในโพสต์ Stack นี้ซึ่งไม่มีปัญหานั้นและใช้ได้กับทุกเบราว์เซอร์


1

สิ่งนี้ควรใช้งานได้ใน chrome:

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});

โปรดพิจารณาเพิ่มข้อเสนอแนะเชิงสร้างสรรค์ว่าเหตุใด OP จึงเห็นปัญหาและโซลูชันของคุณแก้ไขได้
Mirko Adari

1

เนื่องจากมีการกะพริบเมื่อคุณใช้ setTimeout จึงมีโซลูชันตามเหตุการณ์อื่น วิธีนี้จะทำให้เหตุการณ์ 'โฟกัส' แนบเหตุการณ์ 'mouseup' และตัวจัดการเหตุการณ์จะแยกตัวเองอีกครั้ง

    function selectAllOnFocus(e) {
    if (e.type == "mouseup") { // Prevent default and detach the handler
        console.debug("Mouse is up. Preventing default.");
        e.preventDefault();
        $(e.target).off('mouseup', selectAllOnFocus);
        return;
    }
    $(e.target).select();
    console.debug("Selecting all text");
    $(e.target).on('mouseup', selectAllOnFocus);
}

จากนั้นวางสายเหตุการณ์แรก

    $('.varquantity').on('focus', selectAllOnFocus);

1

ใช้setSelectionRange()ภายในการโทรกลับไปที่requestAnimationFrame():

$(document).on('focus', '._selectTextOnFocus', (e) => {
    var input = e.currentTarget;
    var initialType = e.currentTarget.type;

    requestAnimationFrame(() => {
        // input.select() is not supported on iOS
        // If setSelectionRange is use on a number input in Chrome it throws an exception,
        // so here we switch to type text first.
        input.type = "text";
        input.setSelectionRange(0, Number.MAX_SAFE_INTEGER || 9999);
        input.type = initialType;
    });
});

ใช้setSelectionRange()แทนselect()ตั้งแต่select()นั้นไม่ทำงานใน Safari บนมือถือ (ดูการเลือกข้อความโดยทางโปรแกรมในช่องป้อนข้อมูลบนอุปกรณ์ iOS (Safari บนมือถือ) )

จำเป็นต้องรอrequestAnimationFrameก่อนที่จะเลือกข้อความมิฉะนั้นองค์ประกอบจะไม่ถูกเลื่อนเข้ามาในมุมมองอย่างถูกต้องหลังจากที่แป้นพิมพ์ปรากฏบน iOS

เมื่อใช้setSelectionRange()สิ่งสำคัญคือต้องตั้งค่าประเภทอินพุตเป็นtextมิฉะนั้นอาจทำให้เกิดข้อยกเว้นใน Chrome ได้ (ดูที่selectionStart / selectionEnd ในประเภทอินพุต = "number" ไม่อนุญาตอีกต่อไปใน Chrome )


0

หากใครก็ตามที่พบปัญหานี้อีกครั้งฉันได้รับโซลูชัน JS ที่แท้จริงซึ่ง (ในขณะนี้) ทำงานบนเบราว์เซอร์ทั้งหมดรวมถึง มือถือ

<input type="text" value="Hello world..." onFocus="window.setTimeout(() => this.select());">

(ไม่มี setTimeout () มันไม่ทำงานบน Safari, Safari บนมือถือและ MS Edge)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.