วิธีที่ดีที่สุดในการตรวจจับอุปกรณ์ 'หน้าจอสัมผัส' โดยใช้ JavaScript คืออะไร


416

ฉันได้เขียนปลั๊กอิน jQuery ที่ใช้สำหรับทั้งบนเดสก์ท็อปและอุปกรณ์มือถือ ฉันสงสัยว่ามีวิธีการที่ JavaScript ตรวจสอบว่าอุปกรณ์มีความสามารถของหน้าจอสัมผัสหรือไม่ ฉันใช้ jquery-mobile.js เพื่อตรวจจับเหตุการณ์หน้าจอสัมผัสและใช้งานได้กับ iOS, Android เป็นต้น แต่ฉันต้องการเขียนคำสั่งแบบมีเงื่อนไขตามว่าอุปกรณ์ของผู้ใช้มีหน้าจอสัมผัสหรือไม่

เป็นไปได้ไหม


นี่เป็นวิธีที่ดีกว่า var x = 'touchstart' ใน document.documentElement; console.log (x) // คืนค่าจริงถ้าสนับสนุน // อื่นคืนค่าเท็จ
Risa__B

เหตุใดเธรดนี้จึงได้รับการปกป้องหากเทคนิคใหม่ยังคงปรากฏอยู่
Andy Hoffman

คำตอบ:


139

อัปเดต: โปรดอ่านคำตอบของ blmstrด้านล่างก่อนที่จะดึงไลบรารี่การตรวจจับคุณสมบัติทั้งหมดในโครงการของคุณ การตรวจจับการสนับสนุนการสัมผัสที่แท้จริงนั้นซับซ้อนกว่าและ Modernizr ครอบคลุมเฉพาะกรณีการใช้งานพื้นฐาน

Modernizrเป็นวิธีที่ยอดเยี่ยมและมีน้ำหนักเบาในการตรวจจับคุณสมบัติทุกชนิดในเว็บไซต์ใด ๆ

มันเพิ่มคลาสให้กับองค์ประกอบ html สำหรับแต่ละคุณสมบัติ

จากนั้นคุณสามารถกำหนดเป้าหมายคุณลักษณะเหล่านั้นได้อย่างง่ายดายใน CSS และ JS ตัวอย่างเช่น:

html.touch div {
    width: 480px;
}

html.no-touch div {
    width: auto;
}

และ Javascript (ตัวอย่าง jQuery):

$('html.touch #popup').hide();

88
Modernizr ไม่ได้ทดสอบหน้าจอสัมผัส มันทดสอบการมีอยู่ของเหตุการณ์การสัมผัสในเบราว์เซอร์ ดูส่วน "การทดสอบอื่น ๆ " ในเอกสาร: modernizr.com/docs/#features-misc
Harry Love

1
คุณยังสามารถทำการทดสอบ JS สำหรับการมีอยู่ของเหตุการณ์การสัมผัสถ้า (Modernizr.touch) {/ * ทำสิ่งที่สัมผัส/} อื่น {/ปรับไม่ * /}
Anatoly G

7
ถึงจุดของ @ harrylove ตั้งแต่ Windows 8 ออกมา Modernizr ได้ส่งคืนเบราว์เซอร์ของพีซีของฉันทั้งหมดว่าเข้ากันได้กับระบบสัมผัส
Anton

3
ปรับปรุง: คำตอบของ blmstr ดีกว่าและเป็นโซลูชัน Javascript ที่แท้จริง
Alan Christopher Thomas

1
หากModernizr.touchส่งคืนโดยไม่คาดคิดundefinedคุณอาจมี Modernizr ที่กำหนดเอง (คุณจะได้รับและเลือก) โดยไม่รองรับการตรวจจับเหตุการณ์แบบสัมผัส
Henrik N

679

คุณเคยลองใช้ฟังก์ชั่นนี้หรือไม่? (นี่เป็นเช่นเดียวกับ Modernizr ที่ใช้งาน)

function is_touch_device() {  
  try {  
    document.createEvent("TouchEvent");  
    return true;  
  } catch (e) {  
    return false;  
  }  
}

console.log(is_touch_device());

อัพเดท 1

document.createEvent("TouchEvent")ได้เริ่มกลับมาtrueเป็นโครเมียมล่าสุดแล้ว (ข้อ 17) Modernizr อัปเดตเมื่อครู่นี้ ตรวจสอบการทดสอบ Modernizr ออกจากที่นี่

อัปเดตฟังก์ชั่นของคุณเช่นนี้เพื่อให้มันทำงานได้:

function is_touch_device1() {
  return 'ontouchstart' in window;
}

console.log(is_touch_device1());

อัพเดท 2

ฉันพบว่าข้างต้นไม่ทำงานบน IE10 (คืนค่าเท็จบน MS Surface) นี่คือการแก้ไข:

function is_touch_device2() {
  return 'ontouchstart' in window        // works on most browsers 
  || 'onmsgesturechange' in window;  // works on IE10 with some false positives
};

console.log(is_touch_device2());

อัพเดท 3

'onmsgesturechange' in windowจะคืนค่าจริงในเดสก์ท็อป IE บางรุ่นดังนั้นจึงไม่น่าเชื่อถือ วิธีนี้ใช้ได้ผลมากกว่า:

function is_touch_device3() {
  return !!('ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints);       // works on IE10/11 and Surface
};

console.log(is_touch_device3());

อัพเดท 2018

เวลาผ่านไปและมีวิธีใหม่และดีกว่าในการทดสอบสิ่งนี้ ฉันได้แยกและเรียบง่ายวิธีการตรวจสอบของ Modernizr:

function is_touch_device4() {
    
    var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
    
    var mq = function (query) {
        return window.matchMedia(query).matches;
    }

    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
        return true;
    }

    // include the 'heartz' as a way to have a non matching MQ to help terminate the join
    // https://git.io/vznFH
    var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
    return mq(query);
}

console.log(is_touch_device4());

ที่นี่พวกเขากำลังใช้touch-enabledฟีเจอร์การค้นหาสื่อที่ไม่ได้มาตรฐานซึ่งฉันคิดว่าเป็นวิธีที่แปลกและไม่ดี แต่เฮ้ในโลกแห่งความเป็นจริงฉันคิดว่ามันใช้งานได้จริง ในอนาคต (เมื่อพวกเขาได้รับการสนับสนุนโดยทั้งหมด) คุณลักษณะของสื่อเหล่านั้นแบบสอบถามอาจให้ผลลัพธ์เดียวกันและpointerhover

ตรวจสอบแหล่งที่มาของวิธีการที่ Modernizr กำลังทำอยู่

สำหรับบทความที่ดีที่อธิบายปัญหาเกี่ยวกับการตรวจจับการสัมผัสโปรดดู: Stu Cox: คุณไม่สามารถตรวจจับ Touchscreenได้


20
บางคู่ปลดเปลื้องมูลค่าให้กับบูลบังคับให้ฟังก์ชั่นที่จะกลับมาอย่างใดอย่างหนึ่งหรือtrue falseคุณสามารถอ่านเพิ่มเติมได้ที่นี่: stackoverflow.com/questions/4686583/…
Rob Flaherty

2
สิ่งนี้ไม่ทำงานกับ Opera Mobile 10 หรือ Internet Explorer Mobile 6 (Windows Mobile 6.5)
doubleJJ

17
NOT สองครั้ง (!!) ไม่มีความหมายมากนักเนื่องจากinโอเปอเรเตอร์ประเมินค่าเป็นบูลีนแล้ว
Steve

11
'onmsgesturechange'กำลังประเมินผลจริงแม้ในอุปกรณ์ที่ไม่ได้สัมผัส (PC) window.navigator.msMaxTouchPointsดูเหมือนว่าจะแม่นยำมากขึ้น พบได้ที่นี่
Steve

6
มันประเมินว่าเป็นจริงบน IE10 บน Windows 8 แม้ว่าหน้าจอของฉันจะไม่มีเซ็นเซอร์สัมผัส ฉันอัพเกรดแล็ปท็อปเครื่องเก่าจาก Windows 7 เป็น Windows 8
Pwner

120

เนื่องจาก Modernizr ตรวจไม่พบ IE10 บน Windows Phone 8 / WinRT โซลูชั่นข้ามเบราว์เซอร์ที่ง่ายคือ:

var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;

คุณจำเป็นต้องตรวจสอบเพียงครั้งเดียวเพราะอุปกรณ์ไม่รองรับการสัมผัสในทันทีทันใดหรือเพียงแค่สัมผัสดังนั้นเพียงเก็บไว้ในตัวแปรเพื่อให้คุณสามารถใช้งานได้อย่างมีประสิทธิภาพหลาย ๆ ครั้ง


3
'onmsgesturechange' ในหน้าต่างยังตรวจจับ "เดสก์ท็อป" IE10 บนอุปกรณ์ที่ไม่ใช่แบบสัมผัสดังนั้นนี่จึงไม่ใช่วิธีที่เชื่อถือได้ในการพิจารณาการสัมผัส
Matt Stow

6
คำตอบนี้ควรได้รับการยอมรับเนื่องจากเป็นคำตอบที่ดีที่สุดและง่ายที่สุดและทันสมัย ในฟังก์ชั่นฉันเชื่อว่าสิ่งนี้จะสอดคล้องกันมากขึ้น: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(เพื่อรวมคำตอบทั้งสอง) ทำงานได้ดีใน IE10 เช่นกัน!
Yeti

นี่ควรเป็นคำตอบที่ยอมรับได้ 'onmsgesturechange' in windowคืนค่าจริงบนเดสก์ท็อป IE10 แม้เป็นไปได้ที่จะสัมผัส
Sam Thornton

6
สิ่งที่คุณต้องการ:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83

1
แม้แต่ข้อเสนอแนะของ GFoleys เกี่ยวกับ 'ontouchstart' ในหน้าต่าง || !! (navigator.msMaxTouchPoints); ส่งคืนค่าบวกใน Chrome 30 dev ก.พ. 2014
Tom Andersen

37

ใช้ความคิดเห็นทั้งหมดข้างต้นฉันได้รวบรวมรหัสต่อไปนี้ที่ทำงานให้กับความต้องการของฉัน:

var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));

ฉันได้ทำการทดสอบบน iPad, Android (เบราว์เซอร์และ Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 พร้อม Touchscreen), Opera, Chrome และ Firefox

ขณะนี้มันล้มเหลวใน Windows Phone 7 และฉันยังไม่สามารถหาวิธีแก้ปัญหาสำหรับเบราว์เซอร์นั้นได้

หวังว่าบางคนพบว่ามีประโยชน์นี้


มีเหตุผลใดที่คุณไม่สามารถใช้ได้: function is_touch_device () {return !! ('ontouchstart' ในหน้าต่าง) || !! ('msmaxtouchpoints' ในระบบนำทาง); };
sidonaldson

การใช้ฟังก์ชั่นจะใช้งานได้ แต่โดยทั่วไปฉันชอบใช้วิธีตัวแปรด้านบนเพื่อให้ได้รับการทดสอบเพียงครั้งเดียวและจะเร็วขึ้นเมื่อฉันตรวจสอบในภายหลังในรหัสของฉัน นอกจากนี้ฉันยังพบว่าฉันต้องทดสอบเพื่อดูว่า msMaxTouchPoints มากกว่า 0 เป็น IE 10 บน Windows 8 โดยไม่ต้องมีหน้าจอสัมผัสกลับเป็น 0 เป็น msMaxTouchPoints
เดวิด

ส่งคืนtrueบน Firefox 32 ของฉันบน windows 7 :(
vsync

Firefox 33 และ 33.1 บน Windows 8 ทั้งคู่แสดงเท็จในระบบของฉันอย่างถูกต้อง หากคุณอัพเกรด Firefox เป็นเวอร์ชันล่าสุดมันจะยังคงเป็นจริงหรือไม่? คุณอาจมีอุปกรณ์ที่ติดตั้งบนเครื่องของคุณที่สามารถทำให้ Firefox คิดอย่างไม่ถูกต้องว่าเครื่องของคุณมีการสัมผัสหรือไม่?
เดวิด

>>> 'ontouchstart' ในหน้าต่าง >>> true FF 51.0.1 บน Ubuntu
Ravi Gadhia

25

เนื่องจากการแนะนำคุณลักษณะสื่อแบบโต้ตอบคุณสามารถทำได้:

if(window.matchMedia("(pointer: coarse)").matches) {
    // touchscreen
}

https://www.w3.org/TR/mediaqueries-4/#descdef-media-any-pointer

อัปเดต (เนื่องจากความคิดเห็น): วิธีการแก้ปัญหาข้างต้นคือการตรวจสอบว่า "ตัวชี้หยาบ" ซึ่งมักจะเป็นหน้าจอสัมผัส - เป็นอุปกรณ์อินพุตหลัก ในกรณีที่คุณต้องการตัดหากอุปกรณ์ที่มีเช่นเมาส์มีหน้าจอสัมผัสที่คุณอาจใช้any-pointer: coarseแทน

สำหรับข้อมูลเพิ่มเติมดูได้ที่นี่: การตรวจจับว่าเบราว์เซอร์ไม่มีเมาส์และเป็นแบบสัมผัสเท่านั้น


3
นี่คือทางออกที่ดีที่สุดขอขอบคุณ! แม้ว่าฉันจะแนะนำให้ใช้(pointer: coarse)เนื่องจากคุณมักจะกำหนดเป้าหมายไปที่อินพุตหลักเท่านั้น สามารถใช้ในการผลิตได้เนื่องจากเบราว์เซอร์ที่ไม่รองรับบางตัวเป็นเดสก์ท็อปเท่านั้น มีบทความดี ๆ เกี่ยวกับเรื่องนี้ใน CSS
Fabian von Ellerts

2
นี่เป็นทางออกเดียวที่ฉันทดสอบว่าใช้ได้กับทุกสถานการณ์ ขอบคุณ!
kaiserkiwi

20

ฉันชอบอันนี้:

function isTouchDevice(){
    return typeof window.ontouchstart !== 'undefined';
}

alert(isTouchDevice());

12
ไม่จำเป็นต้องใช้นิพจน์ประกอบไปด้วยเพื่อส่งคืนบูลีน เพียงใช้นิพจน์เพื่อส่งคืนบูลีน function isTouchDevice(){ return (window.ontouchstart !== undefined); }
ทิม Vermaelen

1
คุณสามารถใช้: var isTouch = 'ontouchstart' in window;แต่สิ่งนี้ไม่สามารถใช้ได้กับ Chrome ล่าสุด (v31) แต่var isTouch = 'createTouch' in window.document;ก็ยังใช้งานได้
Olivier

2
ตามที่ได้กล่าวไปแล้วในความคิดเห็นของคำถามที่ยอมรับก่อนหน้านี้ "Modernizr ไม่ได้ทดสอบหน้าจอสัมผัสมันทดสอบการมีอยู่ของเหตุการณ์การสัมผัสในเบราว์เซอร์" ฟังก์ชั่นของคุณคือ hasTouchEvents () ไม่ใช่ isTouchDevice ()
hexalys

โปรดทราบว่าการทดสอบวิธีที่คล้ายกันtouchstartจะไม่สามารถจดจำ Surface เป็นอุปกรณ์สัมผัสได้เนื่องจาก IE ใช้pointerเหตุการณ์แทน
CookieMonster

1
อาจ @Nis ถูกต้อง แต่ใน Firefox 39 แสดงว่าส่งคืนเท็จอย่างถูกต้อง
Dan Dascalescu

17

หากคุณใช้Modernizrมันใช้งานง่ายมากModernizr.touchดังที่กล่าวไว้ก่อนหน้านี้

อย่างไรก็ตามฉันชอบใช้การรวมกันModernizr.touchและการทดสอบตัวแทนผู้ใช้เพียงเพื่อความปลอดภัย

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }

หากคุณไม่ได้ใช้ Modernizr คุณสามารถแทนที่Modernizr.touchฟังก์ชั่นด้านบนด้วย('ontouchstart' in document.documentElement)

นอกจากนี้โปรดทราบว่าการทดสอบตัวแทนผู้ใช้iemobileจะให้อุปกรณ์มือถือ Microsoft ที่ตรวจพบได้ในวงกว้างกว่าWindows Phoneคุณ

ดูคำถาม SO เช่นนี้ด้วย


8
คะแนนโบนัสจำนวนมากสำหรับ "ทำอะไรที่น่าประทับใจ" และ "ไม่สามารถแตะต้องสิ่งนี้ได้"
Lee Saxon

คุณกำลังตรวจสอบอุปกรณ์เดียวกันหลายครั้งและทำหลาย Regexes เมื่อคุณสามารถใช้เพียงครั้งเดียว นอกจากนี้คุณกำลังทำ regexes แบบไม่คำนึงถึงขนาดตัวพิมพ์ แต่สตริงนั้นลดระดับลงแล้ว
caesarsol

1
สิ่งนี้น่าจะเพียงพอ:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol

มีเหตุผลใดที่จะพิมพ์เล็กหรือพิมพ์ตัวพิมพ์เล็ก เมื่อใดที่ "iOS", "Android" หรือ "IEMobile" จะใช้ปลอกอื่น ๆ
Henrik N

14

เราพยายามใช้งาน modernizr แต่การตรวจสอบเหตุการณ์การสัมผัสนั้นไม่สอดคล้องกันอีกต่อไป (IE 10 มีเหตุการณ์การสัมผัสบนเดสก์ท็อป windows, IE 11 ทำงานเพราะเราได้ลดกิจกรรมการสัมผัสและเพิ่มตัวชี้ API)

ดังนั้นเราจึงตัดสินใจปรับปรุงเว็บไซต์ให้เป็นเว็บไซต์แบบสัมผัสตราบใดที่เราไม่ทราบว่าผู้ใช้ป้อนข้อมูลประเภทใด นี่น่าเชื่อถือกว่าโซลูชันอื่น ๆ

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

นี่เป็นโค้ดที่ง่ายของเรา:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});

คอมพิวเตอร์ทุกวันนี้มีทั้งระบบสัมผัสและเมาส์ ... คุณต้องแยกความแตกต่าง มันเป็นสิ่งที่ต้องรู้หากสัมผัสเพียงเมาส์หรือทั้งสองอย่าง 3 สถานะที่แตกต่าง
vsync

1
ใช่คุณพูดถูก แต่มันยากมาก ในกรณีที่ดีที่สุดแอปพลิเคชันของคุณได้รับการออกแบบให้ใช้งานโดยคอนโทรลเลอร์อินพุตและไม่สนใจว่าผู้ใช้มีหน้าจอสัมผัส, เมาส์, คีย์บอร์ดหรือทั้งหมดเข้าด้วยกัน
Martin Lantzsch

1
พฤติกรรมของผู้ใช้มีค่ามากกว่าข้อมูลจริงของอุปกรณ์ประเภทใดที่ผู้ใช้มี เมื่อคุณรู้ว่าผู้ใช้มีเมาส์หน้าจอสัมผัสและแป้นพิมพ์ - แล้วอะไรล่ะ จัดการกับพฤติกรรม (mousemove, touchmove, keydown, ฯลฯ ) ผู้ใช้สามารถเปลี่ยนประเภทการป้อนข้อมูลของพวกเขาที่ "runtime" นี่เป็นปัญหาที่น่ารังเกียจอย่างแท้จริงเมื่อคุณพัฒนาแอปพลิเคชันจริงซึ่งใช้งาน 8 ถึง 5 โดยไม่ต้องโหลดซ้ำ
Martin Lantzsch

2
+1 ในทางปฏิบัตินี่เป็นคำตอบที่ดีที่สุดสำหรับฉัน ตัวอย่างเช่นฉันมี datagrids Dataagrids เหล่านี้จะแสดง "ไอคอนแก้ไข" เพื่อแตะเพื่อแก้ไขหรือเมนูบริบทสำหรับตัวเลือกเพิ่มเติม หากตรวจพบการเลื่อนเมาส์ฉันจะลบไอคอน (ประหยัดพื้นที่ในตาราง) และผู้ใช้สามารถดับเบิลคลิกหรือคลิกขวา
prograhammer

3
โครเมี่ยมบนอุปกรณ์ระบบสัมผัสทำให้เกิด mousemove เป็นครั้งคราว
pstanton

9

Fiddle ทำงาน

ฉันประสบความสำเร็จเช่นนี้

function isTouchDevice(){
    return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}

if(isTouchDevice()===true) {
    alert('Touch Device'); //your logic for touch device
}
else {
    alert('Not a Touch Device'); //your logic for non touch device
}

ไม่พบแท็บเล็ตที่ใช้ Windows Surface
Dan Beaulieu

@ DanBeaulieu คุณช่วยกรุณาเจาะจงอุปกรณ์ได้เพราะฉันมี windows phone ที่ใช้งานได้ดีและฉันได้ใช้มันในแอปพลิเคชันของฉันซึ่งเป็น QA: ED ฉันจะตรวจสอบอีกครั้งและจะอัปเดตคำตอบอีกครั้ง ขออภัยในความไม่สะดวก
Aamir Shahzad

ไม่แน่ใจว่าปีใดมันเป็นโปรพื้นผิวหน้าต่างที่เป็นของเพื่อนร่วมงาน หลังจากเพิ่ม modernizr เราก็สามารถใช้งานได้
Dan Beaulieu

สิ่งนี้รายงานอย่างไม่ถูกต้องเกี่ยวกับการสัมผัสบนเครื่อง Windows 7 ของฉันและการสัมผัสบนแล็ปท็อป Windows 8 พร้อมหน้าจอสัมผัสและโทรศัพท์ Android 4.4 MotoX
Clay Nichols

ให้ค่าบวกปลอมใน Chrome (46) บน Mac ของฉัน
Patrick Fabrizius

9

มีบางอย่างที่ดีกว่าการตรวจสอบว่าพวกเขามีหน้าจอสัมผัสคือการตรวจสอบว่าพวกเขากำลังใช้มันรวมทั้งง่ายต่อการตรวจสอบ

if (window.addEventListener) {
    var once = false;
    window.addEventListener('touchstart', function(){
        if (!once) {
            once = true;
            // Do what you need for touch-screens only
        }
    });
}

6

อันนี้ใช้ได้ดีแม้ในแท็บเล็ต Windows Surface !!!

function detectTouchSupport {
msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
touchSupport = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch &&     document instanceof DocumentTouch);
if(touchSupport) {
    $("html").addClass("ci_touch");
}
else {
    $("html").addClass("ci_no_touch");
}
}

4

ฉันใช้โค้ดด้านบนเพื่อตรวจสอบว่ามีการสัมผัสดังนั้น iframe fancybox ของฉันจะแสดงบนคอมพิวเตอร์เดสก์ท็อปและไม่ได้สัมผัส ฉันสังเกตเห็นว่า Opera Mini สำหรับ Android 4.0 ยังคงลงทะเบียนเป็นอุปกรณ์ที่ไม่ได้สัมผัสเมื่อใช้รหัสของ blmstr เพียงอย่างเดียว (ไม่มีใครรู้ว่าทำไม?)

ฉันสิ้นสุดการใช้:

<script>
$(document).ready(function() {
    var ua = navigator.userAgent;
    function is_touch_device() { 
        try {  
            document.createEvent("TouchEvent");  
            return true;  
        } catch (e) {  
            return false;  
        }  
    }

    if ((is_touch_device()) || ua.match(/(iPhone|iPod|iPad)/) 
    || ua.match(/BlackBerry/) || ua.match(/Android/)) {
        // Touch browser
    } else {
        // Lightbox code
    }
});
</script>

คุณช่วยอธิบายหน่อยได้ไหมว่าทำไมคุณไม่ใช้การโทรแบบจับคู่ครั้งเดียวกับ regexp เดี่ยว/iPhone|iPod|iPad|Android|BlackBerry/?
user907860

Opera Mini ดำเนินการเรนเดอร์บนเซิร์ฟเวอร์ของ Opera และไม่ใช่ในอุปกรณ์ดังนั้นจึงเป็นเรื่องที่แปลก
bluesmoon

4

"gotcha" ที่ใหญ่ที่สุดที่พยายามตรวจจับการสัมผัสอยู่ในอุปกรณ์ไฮบริดที่รองรับทั้งการสัมผัสและแทร็คแพด / เมาส์ แม้ว่าคุณจะสามารถตรวจสอบได้อย่างถูกต้องว่าอุปกรณ์ของผู้ใช้รองรับการสัมผัสสิ่งที่คุณต้องทำคือการตรวจสอบสิ่งที่อุปกรณ์ป้อนข้อมูลที่ผู้ใช้กำลังใช้งานอยู่ มีการเขียนรายละเอียดของความท้าทายนี้และเป็นวิธีการแก้ปัญหาที่เป็นไปได้ที่นี่

โดยทั่วไปวิธีการหาว่าผู้ใช้เพิ่งแตะหน้าจอหรือใช้เมาส์ / แทร็กแพดแทนการลงทะเบียนทั้งสองtouchstartและmouseoverเหตุการณ์บนหน้า:

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first
document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

การกระทำแบบสัมผัสจะทำให้ทั้งสองเหตุการณ์เกิดขึ้นก่อนหน้านี้ ( touchstart) ก่อนเสมอบนอุปกรณ์ส่วนใหญ่ ดังนั้นการนับลำดับเหตุการณ์ที่คาดการณ์ได้นี้คุณสามารถสร้างกลไกที่เพิ่มหรือลบcan-touchคลาสไปที่รูทเอกสารเพื่อสะท้อนประเภทอินพุตปัจจุบันของผู้ใช้ในขณะนี้บนเอกสาร:

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")
     
    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }
     
    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }
     
    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

รายละเอียดเพิ่มเติม ที่นี่


3

ลองดูโพสต์นี้มันให้ข้อมูลโค้ดที่ดีจริงๆสำหรับสิ่งที่ต้องทำเมื่อตรวจพบอุปกรณ์สัมผัสหรือจะทำอย่างไรถ้าเหตุการณ์ touchstart ถูกเรียกว่า:

$(function(){
  if(window.Touch) {
    touch_detect.auto_detected();
  } else {
    document.ontouchstart = touch_detect.surface;
  }
}); // End loaded jQuery
var touch_detect = {
  auto_detected: function(event){
    /* add everything you want to do onLoad here (eg. activating hover controls) */
    alert('this was auto detected');
    activateTouchArea();
  },
  surface: function(event){
    /* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
    alert('this was detected by touching');
    activateTouchArea();
  }
}; // touch_detect
function activateTouchArea(){
  /* make sure our screen doesn't scroll when we move the "touchable area" */
  var element = document.getElementById('element_id');
  element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
  /* modularize preventing the default behavior so we can use it again */
  event.preventDefault();
}

3

ฉันจะหลีกเลี่ยงการใช้ความกว้างหน้าจอเพื่อตรวจสอบว่าอุปกรณ์เป็นอุปกรณ์แบบสัมผัสหรือไม่ มีหน้าจอสัมผัสที่มีขนาดใหญ่กว่า 699px ลองนึกถึง Windows 8 Navigatior.userAgent อาจดีที่จะแทนที่การโพสต์ผิด ๆ

ฉันอยากจะแนะนำตรวจสอบปัญหานี้ใน Modernizr

คุณต้องการที่จะทดสอบว่าอุปกรณ์รองรับกิจกรรมการสัมผัสหรือเป็นอุปกรณ์สัมผัส น่าเสียดายที่นั่นไม่ใช่สิ่งเดียวกัน


3

ไม่เป็นไปไม่ได้ คำตอบที่ยอดเยี่ยมให้เป็นเพียงบางส่วนเพราะวิธีการใดก็ตามที่จะก่อให้เกิดผลบวกปลอมและเชิงลบเท็จ แม้แต่เบราว์เซอร์ก็ไม่ทราบว่ามีหน้าจอสัมผัสอยู่หรือไม่เนื่องจาก API ของระบบปฏิบัติการและความจริงสามารถเปลี่ยนแปลงได้ในระหว่างเซสชันเบราว์เซอร์โดยเฉพาะอย่างยิ่งกับการจัดเรียงประเภท KVM

ดูรายละเอียดเพิ่มเติมในบทความที่ยอดเยี่ยมนี้:

http://www.stucox.com/blog/you-cant-detect-a-touchscreen/

บทความแนะนำให้คุณพิจารณาสมมติฐานที่ทำให้คุณต้องการตรวจจับหน้าจอสัมผัสพวกเขาอาจผิด (ฉันตรวจสอบของฉันเองสำหรับแอปของฉันและข้อสันนิษฐานของฉันผิดจริง!)

บทความสรุป:

สำหรับเลย์เอาต์สมมติว่าทุกคนมีหน้าจอสัมผัส ผู้ใช้เมาส์สามารถใช้การควบคุม UI ขนาดใหญ่ได้ง่ายกว่าผู้ใช้ระบบสัมผัสที่สามารถใช้ตัวควบคุมขนาดเล็กได้ เช่นเดียวกันสำหรับสถานะโฮเวอร์

สำหรับกิจกรรมและการโต้ตอบสมมติว่าทุกคนอาจมีหน้าจอสัมผัส ใช้การโต้ตอบของแป้นพิมพ์เมาส์และสัมผัสร่วมกันเพื่อให้แน่ใจว่าไม่มีการบล็อกกัน


3

งานเหล่านี้หลายงาน แต่ต้องการ jQuery หรือ javascript linters บ่นเกี่ยวกับไวยากรณ์ เมื่อพิจารณาคำถามเริ่มต้นของคุณขอให้มีวิธี "JavaScript" (ไม่ใช่ jQuery ไม่ใช่ Modernizr) ในการแก้ปัญหานี่เป็นฟังก์ชั่นง่าย ๆ ที่ใช้งานได้ทุกครั้ง นอกจากนี้ยังเป็นเรื่องเล็กน้อยที่คุณจะได้รับ

function isTouchDevice() {
    return !!window.ontouchstart;
}

console.log(isTouchDevice());

ประโยชน์สุดท้ายที่ฉันจะพูดถึงคือรหัสนี้เป็นกรอบและอุปกรณ์ไม่เชื่อเรื่องพระเจ้า สนุก!


function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}สิ่งนี้ได้ผลกับฉันดังนั้นฉันจึงเพิ่มการสนับสนุนให้กับคำตอบนี้เนื่องจากฉันยังคาดหวังว่าจะมีเธรดวานิลลา JS เมื่อ Google นำฉันมาที่นี่
Daniel Lavedonio de Lima

2

ดูเหมือนว่าตอนนี้ Chrome 24 จะรองรับกิจกรรมแบบสัมผัสอาจเป็นสำหรับ Windows 8 ดังนั้นโค้ดที่โพสต์ที่นี่จึงใช้งานไม่ได้อีกต่อไป แทนที่จะพยายามตรวจสอบว่าเบราว์เซอร์รองรับการสัมผัสตอนนี้ฉันเชื่อมเหตุการณ์ทั้งการแตะและคลิกและทำให้แน่ใจว่ามีการเรียกเพียงหนึ่งเดียว:

myCustomBind = function(controlName, callback) {

  $(controlName).bind('touchend click', function(e) {
    e.stopPropagation();
    e.preventDefault();

    callback.call();
  });
};

แล้วเรียกมันว่า:

myCustomBind('#mnuRealtime', function () { ... });

หวังว่านี่จะช่วยได้!


1
หัวข้อที่เกี่ยวข้องstackoverflow.com/questions/12566306/...
อากาศ

2

เบราว์เซอร์ทั้งหมดรองรับยกเว้น Firefox สำหรับเดสก์ท็อปเสมอTRUEเนื่องจาก Firefox สำหรับเดสก์ท็อปรองรับการออกแบบที่ตอบสนองสำหรับนักพัฒนาแม้คุณคลิกปุ่มสัมผัสหรือไม่!

ฉันหวังว่า Mozilla จะแก้ไขปัญหานี้ในรุ่นถัดไป

ฉันใช้เดสก์ท็อป Firefox 28

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}

มันยังคงเป็นเวอร์ชั่น 32.0 และพวกเขายังไม่ได้แก้ไข! บ้า. ทำไมจึงไม่สามารถเปิดใช้งานได้ สิ่งนี้จะส่งคืนเสมอtrue:(
vsync

2

jQuery v1.11.3

มีข้อมูลที่ดีมากมายในคำตอบที่ให้ไว้ แต่เมื่อเร็ว ๆ นี้ฉันใช้เวลามากมายพยายามผูกทุกอย่างเข้าด้วยกันเป็นโซลูชั่นการทำงานเพื่อให้บรรลุสองสิ่ง:

  1. ตรวจสอบว่าอุปกรณ์ที่ใช้อยู่เป็นอุปกรณ์ประเภทหน้าจอสัมผัส
  2. ตรวจสอบว่าอุปกรณ์ถูกแตะ

นอกจากโพสต์นี้และการตรวจจับอุปกรณ์หน้าจอสัมผัสด้วย Javascriptฉันพบว่าบทความนี้โดย Patrick Lauke มีประโยชน์อย่างยิ่ง: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

นี่คือรหัส ...

$(document).ready(function() {
//The page is "ready" and the document can be manipulated.

    if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
    {
      //If the device is a touch capable device, then...
      $(document).on("touchstart", "a", function() {

        //Do something on tap.

      });
    }
    else
    {
      null;
    }
});

สิ่งสำคัญ! *.on( events [, selector ] [, data ], handler )วิธีการตอบสนองความต้องการที่จะมีตัวเลือกมักจะเป็นองค์ประกอบที่สามารถจัดการกับ "touchstart" เหตุการณ์หรือการอื่น ๆ เช่นเหตุการณ์ที่เกี่ยวข้องกับการสัมผัส ในกรณีนี้มันคือองค์ประกอบเชื่อมโยงหลายมิติ "a"

ตอนนี้คุณไม่จำเป็นต้องจัดการกับการคลิกเมาส์ปกติใน JavaScript เนื่องจากคุณสามารถใช้ CSS เพื่อจัดการกิจกรรมเหล่านี้โดยใช้ตัวเลือกสำหรับองค์ประกอบไฮเปอร์ลิงก์ "a" เช่น:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

หมายเหตุ: มีตัวเลือกอื่น ๆ เช่นกัน ...


1
var isTouchScreen = 'createTouch' in document;

หรือ

var isTouchScreen = 'createTouch' in document || screen.width <= 699 || 
    ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) || 
    ua.match(/Android/);

จะเป็นการตรวจสอบอย่างละเอียดมากขึ้นฉันคิดว่า


3
มันจะดีที่จะทราบว่าหมายถึงua navigator.userAgentการตรวจจับโดยความกว้างของหน้าจอสามารถให้ผลลัพธ์ที่ผิดถ้ามีคนเปิดเบราว์เซอร์ในโหมดเต็มหน้าจอไม่ได้
HoLyVieR


1

ฉันพยายามอย่างมากด้วยตัวเลือกที่แตกต่างกันเกี่ยวกับวิธีการตรวจจับใน Javascript ว่าหน้านั้นจะแสดงบนอุปกรณ์หน้าจอสัมผัสหรือไม่ IMO ณ ขณะนี้ไม่มีตัวเลือกจริงในการตรวจสอบตัวเลือกอย่างถูกต้อง เบราว์เซอร์อาจรายงานเหตุการณ์การสัมผัสบนเครื่องเดสก์ท็อป (เนื่องจากระบบปฏิบัติการอาจจะพร้อมใช้งานด้วยระบบสัมผัส) หรือโซลูชันบางอย่างอาจไม่ทำงานในอุปกรณ์มือถือทั้งหมด

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

วิธีการแก้ปัญหาของฉันคือการrefactorมุมมองเพื่อให้ไม่มีคำแนะนำเครื่องมือที่จำเป็นมากกว่าปุ่มและในที่สุดฉันไม่จำเป็นต้องตรวจสอบอุปกรณ์สัมผัสจากจาวาสคริปต์ด้วยวิธีการที่ทุกคนมีข้อบกพร่องของพวกเขา


1

คุณสามารถติดตั้งเครื่องมือที่ทันสมัยและใช้เหตุการณ์สัมผัสง่าย มันมีประสิทธิภาพมากและใช้งานได้กับทุกอุปกรณ์ที่ฉันทดสอบบนรวมถึงพื้นผิวหน้าต่างด้วย!

ฉันสร้างjsFiddle แล้ว

function isTouchDevice(){
    if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
         alert("is touch");
            return true;
         }else{
            alert("is not touch");
            return false;
    }
}

3
ยินดีต้อนรับสู่ SO! รหัสด้วยตัวเอง (เช่นรหัสที่ไม่ใส่เครื่องหมายข้อคิดเห็น) ไม่ค่อยถือว่าคำตอบ คุณสามารถปรับปรุงคำตอบนี้ได้โดยเพิ่มคำอธิบายของตัวอย่าง
ebarr

1

คำตอบที่ดูเหมือนจะเป็นคำตอบที่คำนึงถึงบริบท:

1) ไซต์สาธารณะ (ไม่มีการเข้าสู่ระบบ)
รหัส UI เพื่อทำงานกับทั้งสองตัวเลือกพร้อมกัน

2) ไซต์เข้าสู่ระบบ
จับภาพว่ามีการเลื่อนเมาส์เกิดขึ้นบนแบบฟอร์มการเข้าสู่ระบบหรือไม่และบันทึกสิ่งนี้ลงในอินพุตที่ซ่อนอยู่ ค่าจะถูกส่งผ่านกับข้อมูลรับรองการเข้าสู่ระบบและเพิ่มลงในเซสชันของผู้ใช้ดังนั้นจึงสามารถใช้ในช่วงเวลาของเซสชันได้

Jquery เพื่อเพิ่มไปยังหน้าเข้าสู่ระบบเท่านั้น:

$('#istouch').val(1); // <-- value will be submitted with login form

if (window.addEventListener) {
    window.addEventListener('mousemove', function mouseMoveListener(){
        // Update hidden input value to false, and stop listening
        $('#istouch').val(0); 
        window.removeEventListener('mousemove', mouseMoveListener);
    });
} 

(+1 ถึง @Dave Burt และ +1 ถึง @Martin Lantzsch ตามคำตอบ)


1

ปัญหา

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

อุปกรณ์สัมผัสยังทำงานด้วย mousemoveเปิดใช้งานการแตะ

สารละลาย

  1. ถือว่าการสัมผัสเป็นเท็จในการโหลด
  2. รอจนกว่าtouchstartเหตุการณ์จะเริ่มขึ้นจากนั้นตั้งค่าเป็นจริง
  3. หาก touchstart ถูกไล่ออกให้เพิ่มตัวจัดการ mousemove
  4. หากเวลาระหว่างเหตุการณ์ mousemove สองเหตุการณ์ที่เกิดขึ้นน้อยกว่า 20ms ให้ถือว่าพวกเขากำลังใช้เมาส์เป็นอินพุต ลบกิจกรรมตามที่ไม่ต้องการอีกต่อไปและ mousemove เป็นกิจกรรมราคาแพงสำหรับอุปกรณ์เมาส์
  5. ทันทีที่ระบบเริ่มทำงาน touchstart อีกครั้ง (ผู้ใช้กลับไปใช้ touch) ตัวแปรจะถูกตั้งค่ากลับเป็นจริง และทำซ้ำกระบวนการดังนั้นมันจึงถูกกำหนดในแบบไดนามิก ถ้าโดย mousemove บางครั้งปาฏิหาริย์โดนไล่ออกสองครั้งอย่างรวดเร็วอย่างไร้เหตุผล (ในการทดสอบของฉันมันเป็นไปไม่ได้เลยที่จะทำได้ภายใน 20ms) การเริ่มต้นครั้งต่อไปจะทำให้มันกลับเป็นจริง

ทดสอบบน Safari iOS และ Chrome สำหรับ Android

หมายเหตุ: ไม่แน่ใจ 100% สำหรับตัวชี้เหตุการณ์สำหรับ MS Surface ฯลฯ

การสาธิต Codepen


const supportsTouch = 'ontouchstart' in window;
let isUsingTouch = false;

// `touchstart`, `pointerdown`
const touchHandler = () => {
  isUsingTouch = true;
  document.addEventListener('mousemove', mousemoveHandler);
};

// use a simple closure to store previous time as internal state
const mousemoveHandler = (() => {
  let time;

  return () => {
    const now = performance.now();

    if (now - time < 20) {
      isUsingTouch = false;
      document.removeEventListener('mousemove', mousemoveHandler);
    }

    time = now;
  }
})();

// add listeners
if (supportsTouch) {
  document.addEventListener('touchstart', touchHandler);
} else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
  document.addEventListener('pointerdown', touchHandler);
}

1

จริงๆแล้วฉันค้นคว้าคำถามนี้และพิจารณาทุกสถานการณ์ เพราะมันเป็นปัญหาใหญ่ในโครงการของฉันด้วย ดังนั้นฉันถึงฟังก์ชั่นด้านล่างมันทำงานได้กับเบราว์เซอร์ทุกรุ่นในทุกอุปกรณ์:

const isTouchDevice = () => {
  const prefixes = ['', '-webkit-', '-moz-', '-o-', '-ms-', ''];
  const mq = query => window.matchMedia(query).matches;

  if (
    'ontouchstart' in window ||
    (window.DocumentTouch && document instanceof DocumentTouch)
  ) {
    return true;
  }
  return mq(['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''));
};

คำแนะนำ : แน่นอนisTouchDeviceแค่คืนbooleanค่า


0

ขอบเขตsupportวัตถุjQuery :

jQuery.support.touch = 'ontouchend' in document;

และตอนนี้คุณสามารถตรวจสอบได้ทุกที่เช่นนี้

if( jQuery.support.touch )
   // do touch stuff

0

ดูเหมือนว่าจะทำงานได้ดีสำหรับฉันจนถึงตอนนี้:

//Checks if a touch screen
is_touch_screen = 'ontouchstart' in document.documentElement;

if (is_touch_screen) {
  // Do something if a touch screen
}
else {
  // Not a touch screen (i.e. desktop)
}

0

เมื่อติดเมาส์มันสามารถสันนิษฐานได้ว่ามี Hitrate ค่อนข้างสูง (ฉันจะบอกว่าใช้งานได้จริง 100%) ว่าผู้ใช้เลื่อนเมาส์อย่างน้อยระยะทางเล็กน้อยหลังจากหน้าพร้อม - โดยไม่ต้องคลิกใด ๆ กลไกด้านล่างตรวจจับสิ่งนี้ หากตรวจพบฉันถือว่านี่เป็นสัญญาณของการสนับสนุนการสัมผัสที่ขาดหายไปหรือมีความสำคัญเล็กน้อยหากได้รับการสนับสนุนเมื่อใช้งานเมาส์ อุปกรณ์สัมผัสจะถือว่าหากตรวจไม่พบ

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

โดยประมาณจะเป็นเช่นนี้ (ขออภัยสำหรับ jQuery แต่คล้ายกันใน Javascript บริสุทธิ์):

var mousedown, first, second = false;
var ticks = 10;
$(document).on('mousemove', (function(e) {
    if(UI.mousechecked) return;
    if(!first) {
        first = e.pageX;
        return;
        }
    if(!second && ticks-- === 0) {
        second = e.pageX;
        $(document).off('mousemove'); // or bind it to somewhat else
        }
    if(first  && second  && first !== second && !mousedown){
        // set whatever flags you want
        UI.hasmouse = true;
        UI.touch = false;
        UI.mousechecked = true;
    }

    return;
}));
$(document).one('mousedown', (function(e) {
    mousedown = true;
    return;
}));
$(document).one('mouseup', (function(e) {
    mousedown = false;
    return;
}));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.