มีตัวเลือก CSS สำหรับองค์ประกอบที่มีข้อความบางอย่างหรือไม่


511

ฉันกำลังมองหาตัวเลือก CSS สำหรับตารางต่อไปนี้:

Peter    | male    | 34
Susanne  | female  | 12

มีตัวเลือกใดที่จะตรงกับ TD ทั้งหมดที่มี "male" หรือไม่?


1
ปัญหาคือว่ามันจะยากมากที่จะใช้ในทางนักแสดง
Ms2ger

7
ตัวเลือก XPath สามารถทำได้ด้วยเมธอด. text () (หากคุณไม่ต้องการใช้ตัวเรียกใช้ JavaScript)
djangofan

11
นี่คือตัวอย่างวิธีการใช้ xpath: // h1 [text () = 'Session'] และคุณสามารถทดสอบ xpath ใน Chrome โดยพิมพ์ $ x ("// h1 [text () = 'Session']" ) ในคอนโซล
VinnyG

1
นี่จะสะดวกมาก ตัวอย่างเช่นเซลล์ตารางที่มีเครื่องหมายถูกหรือสตริง "ใช่", "ผ่าน", "ตกลง" เป็นต้นอาจเป็นสีเขียว
Andreas Rejbrand

$xตอบคำถาม สำหรับคำถามเดิม$x("//td[text()='male']")ทำเคล็ดลับ
เซี่ยว

คำตอบ:


393

ถ้าฉันอ่านข้อมูลจำเพาะอย่างถูกต้องไม่

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


227
:emptyมีกรณีหนึ่งขอบคือ:
Ciro Santilli 郝海东冠状病六四事件法轮功

34
เพื่อตอบคำถามของตัวเอง: ใช่มันยังคงเป็นจริงสำหรับวันนี้! ตัวเลือกเนื้อหาถูกคัดค้าน! ไม่มีตัวเลือกเนื้อหาอีกต่อไปตั้งแต่ CSS3 ( w3.org/TR/css3-selectors/#selectors )
Wlad

158

ใช้ jQuery:

$('td:contains("male")')

7
ลงเอยด้วยการต้องการสิ่งที่ตรงกันข้ามซึ่งก็คือ: jQuery (element) .not (": contain ('string')")
Jazzy

310
ยกเว้นว่าไม่ใช่ CSS นั่นคือ JavaScript
Synetech

9
เห็นด้วย - นั่นเป็นเหตุผลที่คำตอบของฉันบอกว่าฉันใช้ jQuery ไม่ใช่ CSS แต่คำตอบของฉันก็ถูกแก้ไข =)
moettinger

18
แต่คำว่า fe maleนั้นก็มีคำว่า 'male' ไม่เช่นกัน? มันทำงานได้แค่ 'cos male เป็นคนแรกหรือเปล่า? บั๊กที่รอจะเกิดขึ้นหากพวกเขาได้รับคำสั่งซื้อใหม่
Michael Durrant

5
@Michael Durrant: คุณตลก แต่การจับคู่สตริงข้ามองค์ประกอบ (ซึ่งเป็นปัญหาที่ยิ่งใหญ่กว่าการจับคู่สตริงย่อยปกติภายในองค์ประกอบเดียวกัน) ในความเป็นจริงหนึ่งในเหตุผลที่ยิ่งใหญ่ที่สุด: มี () ถูกทิ้ง
BoltClock

158

ดูเหมือนว่าพวกเขามีความคิดเกี่ยวกับเรื่องนี้สำหรับข้อมูลจำเพาะ CSS3 นี้แต่มันไม่ได้ทำให้ตัด

:contains()CSS3 selector http://www.w3.org/TR/css3-selectors/#content-selectors


9
Looks like they were thinking about it for the CSS3 spec but it didn't make the cut.และด้วยเหตุผลที่ดีมันจะเป็นการละเมิดหลักฐานทั้งหมดของการแยกสไตล์เนื้อหาโครงสร้างและพฤติกรรม
Synetech

56
@Synetech จริงๆแล้วมันสามารถช่วยแยกการจัดแต่งทรงผมออกจากเนื้อหาเพราะมันหมายความว่าเนื้อหาที่ไม่จำเป็นต้องรู้เกี่ยวกับไคลเอนต์ของพวกเขาจะต้องพิจารณาเป็นสิ่งสำคัญที่จะจัดแต่งทรงผมฐานบน ตอนนี้เนื้อหา HTML ของเรานั้นถูกจับคู่กับ CSS อย่างแน่นหนาโดยรวมคลาสที่เรารู้ว่า styler ให้ความสำคัญ พวกเขาขยับไปสู่การปล่อย CSS ที่เนื้อหาดังที่เห็นได้จากตัวเลือกค่าคุณลักษณะใน CSS3
DannyMeister

8
@Synetech และมันเป็นอย่างไร "พฤติกรรม" ใช่มั้ย สำหรับฉันมันเป็นเรื่องของการนำเสนอ มันไม่ได้ทำอะไรเลย - มันนำเสนอเนื้อหาบางประเภทในลักษณะที่แน่นอน
BarbaraKwarc

4
@ DannyMeister, โอ้คุณไม่ต้องโน้มน้าวฉัน สองสามปีที่ผ่านมาและฉันพบว่าตัวเองกลับมาที่นี่ในขณะที่พยายามมองหาฟังก์ชั่นนี้และไม่พอใจที่มันไม่ได้มีอยู่ แต่มันถูกปฏิเสธ 😒 eBay เพิ่งเปลี่ยน UI และทำให้ไซต์ใช้งานยากมาก ฉันกำลังพยายามแก้ไขด้วยสไตล์ชีทของผู้ใช้ แต่มาร์กอัปของพวกเขาไม่แยกความแตกต่างระหว่างการประมูลและรายชื่อ BIN ดังนั้นวิธีเดียวที่จะเน้นจำนวนการเสนอราคาในรายการคือการจับคู่องค์ประกอบตามเนื้อหาที่เป็นข้อความ ทั้งหมดที่ใช้ในการโน้มน้าวใจใครสักคนคือให้พวกเขาได้สัมผัสกับสถานการณ์กรณีใช้งานโดยตรง
Synetech

8
เพื่อให้แน่ใจว่ามีการแยกเนื้อหาและสไตล์ที่ดีเราไม่มีตัวเลือก: contain () ดังนั้นแทนที่จะใส่สไตล์ให้กับเซลล์ตามเนื้อหา (เช่นคอลัมน์ "สถานะ" ของ "เปิด" หรือ "แก้ไข") เราจะทำซ้ำเนื้อหาในทั้งการแสดงผลและแอตทริบิวต์ของชั้นเรียนแล้วเลือกที่ . ยอดเยี่ยม
Jon Kloske

122

คุณจะต้องเพิ่มแอตทริบิวต์ข้อมูลไปยังแถวที่เรียกdata-genderพร้อมกับmaleหรือfemaleค่าและใช้ตัวเลือกแอตทริบิวต์:

HTML:

<td data-gender="male">...</td>

CSS:

td[data-gender="male"] { ... }

10
การใช้แอตทริบิวต์ข้อมูลที่กำหนดเองกับ Javascript และ CSS นั้นไม่เป็นไร ดูMDN โดยใช้คุณสมบัติข้อมูล
Michael Benjamin

1
ฉันเห็นด้วยกับคุณลักษณะของข้อมูลว่าควรจัดการอย่างไร แต่กฎ CSS เช่น td.male มักจะง่ายต่อการตั้งค่าโดยเฉพาะกับเชิงมุมซึ่งอาจดูเหมือน: <td class = "{{person.gender}} ">
DJDaveMark

แน่นอนว่าเพศเป็นตัวอย่างที่ใช้ในการเรียน แต่ถ้าข้อมูลมีความหลากหลายมากกว่าmaleหรือfemale? ความจริงที่classเต็มไปด้วยชั้นเรียนอื่น ๆ ลำดับของพวกเขาไม่รับประกันอาจมีการปะทะกับชื่อชั้นอื่น ๆ ฯลฯ ทำให้classสถานที่เลวร้ายยิ่งสำหรับสิ่งประเภทนี้ data-*แอตทริบิวต์เฉพาะจะแยกข้อมูลของคุณออกจากทุกสิ่งนั้นและทำให้ง่ายขึ้นในการจับคู่บางส่วน ฯลฯ โดยใช้ตัวเลือกคุณลักษณะ
Stijn de Witt

มีคำตอบอีกข้อหนึ่งซึ่งเป็นข้อมูลโค้ดที่ใช้งานได้ซึ่งใช้คุณลักษณะของข้อมูลในลักษณะเดียวกัน
Josh Habdas

65

จริงๆแล้วมีพื้นฐานความคิดที่ชัดเจนว่าทำไมสิ่งนี้จึงไม่ถูกนำไปใช้ มันเป็นการรวมกันของ 3 ด้านโดยทั่วไป:

  1. เนื้อหาข้อความขององค์ประกอบเป็นองค์ประกอบย่อยขององค์ประกอบนั้น
  2. คุณไม่สามารถกำหนดเป้าหมายเนื้อหาข้อความโดยตรง
  3. CSS ไม่อนุญาตให้ขึ้นกับตัวเลือก

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


4
นี่เป็นเรื่องจริง นี่คือสิ่งที่ XPath มีไว้สำหรับ หากคุณสามารถเรียกใช้งานตัวเลือกใน JS / jQuery หรือห้องสมุดแยกวิเคราะห์ (ตรงข้ามกับ CSS-only) ก็จะสามารถใช้text()ฟังก์ชันของ XPath ได้
Mark Thomas

นั่นเป็นจุดที่ดีเกี่ยวกับเนื้อหา แต่ฉันหวังว่าคุณจะสามารถ:contains(<sub-selector>)เลือกองค์ประกอบที่มีองค์ประกอบเฉพาะอื่น ๆ ได้ ชอบdiv:contains(div[id~="bannerAd"])กำจัดโฆษณาและเป็นตู้คอนเทนเนอร์
Lawrence Dol

27

คุณสามารถตั้งค่าเนื้อหาเป็น data data จากนั้นใช้selector attributeดังที่แสดงไว้ที่นี่:

/* Select every cell containing word "male" */
td[data-content="male"] {
  color: red;
}

/* Select every cell starting on "p" case insensitive */
td[data-content^="p" i] {
  color: blue;
}

/* Select every cell containing "4" */
td[data-content*="4"] {
  color: green;
}
<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-conten="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>

คุณยังสามารถใช้ jQuery เพื่อตั้งค่าคุณสมบัติ data-content ได้อย่างง่ายดาย:

$(function(){
  $("td").each(function(){
    var $this = $(this);
    $this.attr("data-content", $this.text());
  });
});

3
ทราบว่า.text()และ.textContentค่อนข้างหนักพยายามหลีกเลี่ยงพวกเขาในรายการยาวหรือข้อความขนาดใหญ่เมื่อเป็นไปได้ .html()และ.innerHTMLรวดเร็ว
oriadam

@JoshHabdas คุณสามารถทำเป็นตัวอย่าง jsbin / jsfiddle ได้ไหม?
Buksy

1
หากคุณกำลังจะใช้ jQuery ให้ใช้ตัวเลือก$("td:contains(male)")
contain

หากเนื้อหานั้นสามารถแก้ไขได้โดยผู้ใช้ ( contenteditable='true'- กรณีของฉัน) มันไม่เพียงพอที่จะตั้งค่าของdata-contentแอตทริบิวต์ก่อนที่จะมีการแสดงหน้า มันจะต้องมีการปรับปรุงอย่างต่อเนื่อง นี่คือสิ่งที่ฉันใช้:<td onkeypress="event.target.setAttribute('data-content', event.target.textContent);">
Caram

13

เมื่อ CSS ขาดคุณสมบัตินี้คุณจะต้องใช้จาวาสคริปต์เพื่อจัดรูปแบบเซลล์ตามเนื้อหา ตัวอย่างเช่นกับ XPath's contains:

var elms = document.evaluate( "//td[contains(., 'male')]", node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null )

จากนั้นใช้ผลลัพธ์ดังนี้:

for ( var i=0 ; i < elms.snapshotLength; i++ ){
   elms.snapshotItem(i).style.background = "pink";
}

https://jsfiddle.net/gaby_de_wilde/o7bka7Ls/9/


นี่คือจาวาสคริปต์, สิ่งนี้เกี่ยวข้องกับคำถามอย่างไร?
rubo77

3
ในขณะที่คุณไม่สามารถเลือกเนื้อหาใน css คุณจะต้องใช้ js เพื่อทำเช่นนั้น ในขณะที่คุณอยู่ในจุดที่คุณชี้ให้เห็นว่านี่ไม่ใช่ css การใช้แอตทริบิวต์ data ไม่ได้เลือกตามเนื้อหา เราสามารถเดาได้ว่าเหตุใดผู้อ่านจึงต้องการเลือกเซลล์ตามเนื้อหาการเข้าถึงแบบใดที่เธอมีต่อ html จำนวนการจับคู่ตารางขนาดใหญ่ ฯลฯ เป็นต้น
user40521

7

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


4

สำหรับผู้ที่ต้องการเลือกข้อความซีลีเนียม CSS สคริปต์นี้อาจมีประโยชน์สำหรับคุณ

เคล็ดลับคือการเลือกพาเรนต์ขององค์ประกอบที่คุณกำลังมองหาแล้วค้นหาเด็กที่มีข้อความ:

public static IWebElement FindByText(this IWebDriver driver, string text)
{
    var list = driver.FindElement(By.CssSelector("#RiskAddressList"));
    var element = ((IJavaScriptExecutor)driver).ExecuteScript(string.Format(" var x = $(arguments[0]).find(\":contains('{0}')\"); return x;", text), list);
    return ((System.Collections.ObjectModel.ReadOnlyCollection<IWebElement>)element)[0];
}

นี่จะคืนค่าองค์ประกอบแรกหากมีมากกว่าหนึ่งรายการเนื่องจากเป็นองค์ประกอบเดียวเสมอในกรณีของฉัน


คุณสามารถใช้TD:contains('male')ถ้าคุณใช้ซีลีเนียม: imho ใช้ได้เฉพาะเมื่อคุณไม่สามารถอัปเดตแหล่งที่มาเพื่อเพิ่มคลาสได้ เช่นถ้าคุณทดสอบรหัสดั้งเดิมหรือ บริษัท ของคุณจะไม่ยอมให้คุณพูดกับ devs (eurgh!) เพราะการทดสอบของคุณจะมีความเปราะและจะแตกหากใครบางคนเปลี่ยนข้อความในภายหลังmasculineหรือเปลี่ยนภาษา เอกสาร SauceLabs แสดงการใช้containsที่นี่ ( saucelabs.com/resources/articles/selenium-tips-css-selectors ) + cc @matas vaitkevicius ฉันพลาดอะไรไปแล้วหรือ
snowcode

3

ฉันเห็นด้วยกับ data data (คำตอบของผู้เดินทางรอบโลก) คือวิธีการจัดการ แต่กฎ CSS เช่น:

td.male { color: blue; }
td.female { color: pink; }

มักจะง่ายต่อการตั้งค่าโดยเฉพาะอย่างยิ่งกับ libs ฝั่งไคลเอ็นต์เช่น angularjs ซึ่งอาจง่ายเหมือน:

<td class="{{person.gender}}">

ตรวจสอบให้แน่ใจว่าเนื้อหามีเพียงคำเดียว! หรือคุณสามารถแมปกับชื่อคลาส CSS ที่แตกต่างกันด้วย:

<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}">

เพื่อความสมบูรณ์นี่คือแนวทางของ data data:

<td data-gender="{{person.gender}}">

การโยงเทมเพลตเป็นทางออกที่ดี แต่มันรู้สึก ick บิตเพื่อสร้าง classnames ตามโครงสร้างมาร์กอัป ( แต่ที่สวยมากสิ่งที่BEMไม่ในทางปฏิบัติ)
Josh Habdas

2

@ คำตอบของ voyager เกี่ยวกับการใช้data-*คุณลักษณะ (เช่นdata-gender="female|male"เป็นวิธีที่มีประสิทธิภาพและได้มาตรฐานที่สุด ณ ปี 2560:

[data-gender='male'] {background-color: #000; color: #ccc;}

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

จนกว่าการสนับสนุนดังกล่าวจะประสบความสำเร็จและดำเนินการในสิ่งที่ดีที่สุดถัดไปที่ฉันสามารถแนะนำได้เมื่อมีการใช้งานคือการใช้คำexplode/ splitตัวเว้นวรรคส่งคำแต่ละคำภายในspanองค์ประกอบและถ้าคำ / เป้าหมายการออกแบบจัดแต่งทรงผมสามารถใช้ร่วมกันได้ :

$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
 echo '<span>'.$value1.'</span>;
}

อื่นถ้าไม่สามารถคาดเดาไปอีกครั้งคำตอบที่ใช้ voyager เกี่ยวกับการใช้data-*แอตทริบิวต์ ตัวอย่างการใช้ PHP:

$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
 echo '<span data-word="'.$value1.'">'.$value1.'</span>;
}


1

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

      cells = document.querySelectorAll('td');
    	console.log(cells);
      [].forEach.call(cells, function (el) {
    	if(el.innerText.indexOf("male") !== -1){
    	//el.click(); click or any other option
    	console.log(el)
    	}
    });
 <table>
      <tr>
        <td>Peter</td>
        <td>male</td>
        <td>34</td>
      </tr>
      <tr>
        <td>Susanne</td>
        <td>female</td>
        <td>14</td>
      </tr>
    </table>

<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-conten="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>

1

ฉันพบว่าตัวเลือกคุณลักษณะเป็นทางออกที่ดีที่สุดของคุณหากคุณไม่ต้องการใช้ javascript หรือ jquery

เช่นเพื่อจัดเรียงเซลล์ตารางทั้งหมดด้วยคำว่าพร้อมใน HTML ให้ทำดังนี้

 <td status*="ready">Ready</td>

จากนั้นใน css:

td[status*="ready"] {
        color: red;
    }

0

คุณสามารถใช้contentกับattr()และเซลล์ตารางสไตล์ที่::not :empty

th::after { content: attr(data-value) }
td::after { content: attr(data-value) }
td[data-value]:not(:empty) {
  color: fuchsia;
}
<table>
  <tr>
    <th data-value="Peter"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="34"></td>
  </tr>
  <tr>
    <th data-value="Susanne"></th>
    <td data-value="female"></td>
    <td data-value="12"></td>
  </tr>
  <tr>
    <th data-value="Lucas"></th>
    <td data-value="male">&#x0200B;</td>
    <td data-value="41"></td>
  </tr>
</table>

A ZeroWidthSpaceใช้เพื่อเปลี่ยนสีและอาจถูกเพิ่มโดยใช้ vanilla JavaScript:

const hombres = document.querySelectorAll('td[data-value="male"]');
hombres.forEach(hombre => hombre.innerHTML = '&#x0200B;');

แม้ว่า<td>แท็กปิดท้ายนั้นอาจถูกตัดออกไปซึ่งอาจทำให้แท็กนั้นไม่ได้ว่างเปล่า


0

หากคุณไม่ได้สร้าง DOM ด้วยตัวเอง (เช่นใน userscript) คุณสามารถทำสิ่งต่อไปนี้ด้วย pure JS:

for ( td of document.querySelectorAll('td') ) {
  console.debug("text:", td, td.innerText)
  td.setAttribute('text', td.innerText)
}
for ( td of document.querySelectorAll('td[text="male"]') )
  console.debug("male:", td, td.innerText)
<table>
  <tr>
    <td>Peter</td>
    <td>male</td>
    <td>34</td>
  </tr>
  <tr>
    <td>Susanne</td>
    <td>female</td>
    <td>12</td>
  </tr>
</table>

เอาต์พุตคอนโซล

text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male

-2

ทำเครื่องมือตัวกรองขนาดเล็กเช่นนี้:

    var searchField = document.querySelector('HOWEVER_YOU_MAY_FIND_IT')
    var faqEntries = document.querySelectorAll('WRAPPING_ELEMENT .entry')

    searchField.addEventListener('keyup', function (evt) {
        var testValue = evt.target.value.toLocaleLowerCase();
        var regExp = RegExp(testValue);

        faqEntries.forEach(function (entry) {
            var text = entry.textContent.toLocaleLowerCase();

            entry.classList.remove('show', 'hide');

            if (regExp.test(text)) {
                entry.classList.add('show')
            } else {
                entry.classList.add('hide')
            }
        })
    })

-2

ไวยากรณ์ของคำถามนี้ดูเหมือนว่าไวยากรณ์ของ Robot Framework ในกรณีนี้แม้ว่าจะไม่มีตัวเลือก css ที่คุณสามารถใช้สำหรับการบรรจุได้ แต่มีคำสำคัญ SeleniumLibrary ที่คุณสามารถใช้แทนได้ รอจนกว่าธาตุประกอบด้วย

ตัวอย่าง:

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