एचटीएमएल टेक्स्ट-ओवरफ्लो इलिप्सिस डिटेक्शन


176

मेरे पास एक पृष्ठ पर ब्लॉक तत्वों का एक संग्रह है। वे सभी सीएसएस नियम सफेद-स्थान, अतिप्रवाह, पाठ-अतिप्रवाह सेट हैं ताकि अतिप्रवाहित पाठ को छंटनी की जाए और एक दीर्घवृत्त का उपयोग किया जाए।

हालांकि, सभी तत्व अतिप्रवाह नहीं करते हैं।

क्या वैसे भी मैं जावास्क्रिप्ट का उपयोग कर पता लगा सकता हूं कि कौन से तत्व अतिप्रवाहित हैं?

धन्यवाद।

जोड़ा गया: उदाहरण के लिए HTML संरचना जिसके साथ मैं काम कर रहा हूं।

<td><span>Normal text</span></td>
<td><span>Long text that will be trimmed text</span></td>

एसपीएएन तत्व हमेशा कोशिकाओं में फिट होते हैं, उनके पास एलिप्सिस नियम लागू होता है। मैं यह पता लगाना चाहता हूं कि जब स्प्लिस को स्पैन की पाठ्य सामग्री पर लागू किया जाता है।


डुप्लिकेट: stackoverflow.com/questions/143815/…
jantimon

10
डुप्लिकेट नहीं! यह प्रश्न एक तत्व के बारे में दूसरे, मूल तत्व पर है। मैं एक तत्व के भीतर पाठ के बारे में बात कर रहा हूँ। मेरे मामले में, टीडी में स्पैन कभी भी टीडी को ओवरफ्लो नहीं करता है, यह स्पैन के भीतर का पाठ है जो ओवरफ्लो होता है, और ट्रिम हो जाता है। यही मैं पता लगाने की कोशिश कर रहा हूँ! क्षमा करें - मैं इस प्रश्न को बेहतर ढंग से स्वीकार कर सकता था।
डीनोज

ओह, मैं जोड़ना भूल गया - यह केवल वेबकिट पर काम करने की आवश्यकता है अगर वह मदद करता है ...
deanoj

मैंने घोमे को सिर्फ यह देखने के लिए किया कि क्या यह काम करता है ... यह नहीं हुआ।
deanoj

दीर्घवृत्त पहलू अप्रासंगिक है; आपको यह पता लगाने की आवश्यकता है कि क्या यह अतिप्रवाहित है।
स्पडली

जवाबों:


114

एक बार मुझे ऐसा करने की आवश्यकता थी, और एकमात्र क्रॉस-ब्राउज़र विश्वसनीय समाधान जो मुझे आया था वह हैक था। मैं इस तरह के समाधानों का सबसे बड़ा प्रशंसक नहीं हूं, लेकिन यह निश्चित रूप से सही परिणाम समय और समय फिर से पैदा करता है।

विचार यह है कि आप तत्व को क्लोन करते हैं, किसी भी बाउंडिंग चौड़ाई को हटाते हैं, और परीक्षण करते हैं यदि क्लोन तत्व मूल से अधिक व्यापक है। यदि हां, तो आप जानते हैं कि यह समाप्त हो गया है।

उदाहरण के लिए, jQuery का उपयोग करना:

var $element = $('#element-to-test');
var $c = $element
           .clone()
           .css({display: 'inline', width: 'auto', visibility: 'hidden'})
           .appendTo('body');

if( $c.width() > $element.width() ) {
    // text was truncated. 
    // do what you need to do
}

$c.remove();

मैंने इसे प्रदर्शित करने के लिए एक jsField बनाया, http://jsfiddle.net/cgzW8/2/

तुम भी jQuery के लिए अपने खुद के कस्टम छद्म चयनकर्ता बना सकते हैं:

$.expr[':'].truncated = function(obj) {
  var $this = $(obj);
  var $c = $this
             .clone()
             .css({display: 'inline', width: 'auto', visibility: 'hidden'})
             .appendTo('body');

  var c_width = $c.width();
  $c.remove();

  if ( c_width > $this.width() )
    return true;
  else
    return false;
};

फिर इसका उपयोग तत्वों को खोजने के लिए करें

$truncated_elements = $('.my-selector:truncated');

डेमो: http://jsfiddle.net/cgzW8/293/

उम्मीद है कि यह मदद करता है, के रूप में हैकी है।


1
@ गौरी नं; सीएसएस ट्रंकेशन बॉक्स में वास्तविक पाठ को नहीं बदलता है , इसलिए सामग्री हमेशा समान होती है, चाहे वह छोटा, दृश्यमान या छिपा हुआ हो। अभी भी प्रोग्राम को काट-छाँट करने का कोई तरीका नहीं है, अगर वहाँ था तो आपको पहली जगह में तत्व को क्लोन करने की आवश्यकता नहीं होगी!
क्रिश्चियन

1
लगता है कि यह उन स्थितियों में काम नहीं करेगा जहां कोई नहीं है white-space: nowrap
जकूब हैम्पल

2
मुझे कहना होगा कि इंटरनेट पर एक बहुत खोज के बाद और कई समाधानों को लागू करने की कोशिश की, यह अब तक का सबसे विश्वसनीय है जो मुझे मिला। यह समाधान ब्राउजरों के बीच अलग-अलग परिणाम नहीं देता है जैसे element.innerWidth या element.OffsetWidth, जिसमें मार्जिन या पैडिंग का उपयोग करते समय समस्या आती है .. महान समाधान, अच्छा किया।
14

1
मेरे लिए, यह कहीं भी काम नहीं आया। मुझे यकीन नहीं है, यह सीएसएस पर कैसे निर्भर करता है (मैंने इनपुट नियंत्रणों पर इसका उपयोग करने की कोशिश की है, नीचे दिए गए समाधान कम से कम क्रोम और फ़ायरफ़ॉक्स में काम करते हैं (लेकिन IE11 में नहीं)) ...
अलेक्जेंडर

3
महान समाधान, विशेष रूप से jQuery के छद्म चयनकर्ता का उपयोग कर। लेकिन कभी-कभी काम नहीं हो सकता है, क्योंकि चौड़ाई को गलत तरीके से गणना की जाती है यदि तत्व पाठ की अलग शैली (फ़ॉन्ट-आकार, पत्र-रिक्ति, आंतरिक तत्वों का मार्जिन) है। उस स्थिति में, मैं 'बॉडी' के बजाय क्लोन तत्व को $ this.parent () में जोड़ने की सलाह दूंगा। यह तत्व की सटीक प्रतिलिपि देगा और गणना सही होगी। वैसे भी धन्यवाद
एलेक्स

286

इस जेएस फ़ंक्शन को आज़माएं, अवधि तत्व को तर्क के रूप में पास कर रहा है:

function isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}

10
इसका उत्तर होना चाहिए - बहुत सुरुचिपूर्ण और क्रोम और IE (9) पर काम करता है
रॉय Truelove

14
यह उत्तर और एलेक्स का उत्तर IE8 में काम नहीं करेगा; कुछ विषम मामले हैं, जहां स्क्रॉल चौड़ाई और बाहरी उपलब्धता समान हैं ... लेकिन इसमें दीर्घवृत्त है, और फिर कुछ मामले जहां वे समान हैं ... और कोई दीर्घवृत्त नहीं है। दूसरे शब्दों में, पहला समाधान एकमात्र ऐसा है जो सभी ब्राउज़रों में काम करता है।

3
उन लोगों के लिए जिन्हें ऑफसेटविदथ, स्क्रॉलविद और क्लाइंटविथ को समझने की आवश्यकता है, यहां एक बहुत अच्छी व्याख्या है: stackoverflow.com/a/21064102/1815779
Linh Dam

4
इस पर text-overflow:ellipsisहोना चाहिएe.offsetWidth <= e.scrollWidth
oriadam

4
वे हमेशा फ्लेक्स बच्चों पर एक दूसरे के बराबर होते हैं, और इस प्रकार, उनके लिए काम नहीं करेंगे।
केविन बील

14

Italo के जवाब में जोड़कर, आप jQuery का उपयोग करके भी ऐसा कर सकते हैं।

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.width() < $jQueryObject[0].scrollWidth);
}

इसके अलावा, जैसा कि स्मोकी ने बताया, आप चौड़ाई के बजाय jQuery के आउटरविथ () का उपयोग करना चाह सकते हैं।

function isEllipsisActive($jQueryObject) {
    return ($jQueryObject.outerWidth() < $jQueryObject[0].scrollWidth);
}

9

क्रिस्चियन वर्गा से स्वीकृत उत्तर का उपयोग करने वाले (या उपयोग करने की योजना) करने वालों के लिए, कृपया प्रदर्शन के मुद्दों से अवगत रहें।

इस तरह से DOM को क्लोन करना / हेरफेर करना DOM Reflow का कारण बनता है ( DOM reflow पर एक स्पष्टीकरण देखें) यहाँ देखें) जो बेहद संसाधन गहन है।

एक पृष्ठ पर 100+ तत्वों पर क्रिस्चियन वर्गा के समाधान का उपयोग करने से 4 सेकंड का रिफ्लो विलंब होता है, जिसके दौरान JS थ्रेड लॉक होता है। जेएस को सिंगल-थ्रेडेड माना जाता है, इसका मतलब अंतिम उपयोगकर्ता के लिए एक महत्वपूर्ण UX देरी है।

इटालो बोरसैटो का उत्तर स्वीकार किया जाना चाहिए, यह मेरे प्रोफाइलिंग के दौरान लगभग 10 गुना तेज था।


2
दुर्भाग्य से यह हर परिदृश्य में काम नहीं करता (काश यह होता)। और आपके द्वारा यहां उल्लेखित प्रदर्शन हिट हो सकता है, केवल उस स्थिति के लिए इसे चालू करके ऑफसेट किया जा सकता है जिसमें आपको जांचने की आवश्यकता है - जैसे कि केवल mouseenterयह देखने के लिए कि क्या टूलटिप को दिखाने की आवश्यकता है।
याकूब

5

इटालो से उत्तर बहुत अच्छा है! हालाँकि मुझे इसे थोड़ा परिष्कृत करने दें:

function isEllipsisActive(e) {
   var tolerance = 2; // In px. Depends on the font you are using
   return e.offsetWidth + tolerance < e.scrollWidth;
}

क्रॉस ब्राउज़र संगतता

तो, वास्तव में, यदि आप उपरोक्त कोड और उपयोग की कोशिश console.logके मूल्यों बाहर मुद्रित करने के लिए e.offsetWidthऔर e.scrollWidth, आप देखेंगे IE पर, कि, भले ही आप कोई पाठ काट-छांट होते, के एक मूल्य के अंतर 1pxया 2pxअनुभवी है।

इसलिए, आपके द्वारा उपयोग किए जाने वाले फ़ॉन्ट आकार के आधार पर, एक निश्चित सहिष्णुता की अनुमति दें!


यह IE10 पर काम नहीं करता है - ऑफसेटविंडथ स्क्रॉलविद के समान है, दोनों मुझे छंटनी की चौड़ाई दे रहे हैं।
SsjCosty

1
मुझे Chrome 60 (नवीनतम) पर भी इस सहिष्णुता की आवश्यकता है।
Jan 29ankowski

5

elem.offsetWdith VS ele.scrollWidth मेरे लिए यह काम! https://jsfiddle.net/gustavojuan/210to9p1/

$(function() {
  $('.endtext').each(function(index, elem) {
    debugger;
    if(elem.offsetWidth !== elem.scrollWidth){
      $(this).css({color: '#FF0000'})
    }
  });
});

न तो वर्तमान क्रोम में और न ही फ़ायरफ़ॉक्स में काम करता है। दोनों तत्व लाल हो जाते हैं।
xehpuk

4

यह नमूना पाठ तालिका के साथ सेल तालिका पर टूलटिप दिखाता है। तालिका की चौड़ाई के आधार पर गतिशील है:

$.expr[':'].truncated = function (obj) {
    var element = $(obj);

    return (element[0].scrollHeight > (element.innerHeight() + 1)) || (element[0].scrollWidth > (element.innerWidth() + 1));
};

$(document).ready(function () {
    $("td").mouseenter(function () {
        var cella = $(this);
        var isTruncated = cella.filter(":truncated").length > 0;
        if (isTruncated) 
            cella.attr("title", cella.text());
        else 
            cella.attr("title", null);
    });
});

डेमो: https://jsfiddle.net/t4qs3tqs/

यह jQuery के सभी संस्करण पर काम करता है


1

मुझे लगता है कि इसका उपयोग करने का बेहतर तरीका यह है getClientRects()कि ऐसा लगता है कि प्रत्येक आयत की ऊंचाई समान है, इसलिए हम अलग-अलग topमूल्य की संख्या के साथ लाइनों की संख्या को कैच कर सकते हैं ।

getClientRectsइस तरह काम करो

function getRowRects(element) {
    var rects = [],
        clientRects = element.getClientRects(),
        len = clientRects.length,
        clientRect, top, rectsLen, rect, i;

    for(i=0; i<len; i++) {
        has = false;
        rectsLen = rects.length;
        clientRect = clientRects[i];
        top = clientRect.top;
        while(rectsLen--) {
            rect = rects[rectsLen];
            if (rect.top == top) {
                has = true;
                break;
            }
        }
        if(has) {
            rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
            rect.width = rect.right - rect.left;
        }
        else {
            rects.push({
                top: clientRect.top,
                right: clientRect.right,
                bottom: clientRect.bottom,
                left: clientRect.left,
                width: clientRect.width,
                height: clientRect.height
            });
        }
    }
    return rects;
}

getRowRectsइस तरह काम करो

आप इस तरह का पता लगा सकते हैं


1

सभी समाधान वास्तव में, मेरे लिए काम नहीं किया क्या किया था काम तत्वों की तुलना की गई थी scrollWidthकरने के लिएscrollWidth (जो तत्व ट्रिगर है पर निर्भर करता है, या बच्चे) ने अपने माता-पिता की।

जब बच्चा scrollWidthअपने माता-पिता से अधिक होता है, तो इसका मतलब .text-ellipsisसक्रिय है।


eventमूल तत्व कब है

function isEllipsisActive(event) {
    let el          = event.currentTarget;
    let width       = el.offsetWidth;
    let widthChild  = el.firstChild.offsetWidth;
    return (widthChild >= width);
}

eventबाल तत्व कब है

function isEllipsisActive(event) {
    let el          = event.currentTarget;
    let width       = el.offsetWidth;
    let widthParent = el.parentElement.scrollWidth;
    return (width >= widthParent);
}

0

e.offsetWidth < e.scrollWidthसमाधान हमेशा काम नहीं कर रहा।

और यदि आप शुद्ध जावास्क्रिप्ट का उपयोग करना चाहते हैं, तो मैं इसका उपयोग करने की सलाह देता हूं:

(टाइपप्रति)

public isEllipsisActive(element: HTMLElement): boolean {
    element.style.overflow = 'initial';
    const noEllipsisWidth = element.offsetWidth;
    element.style.overflow = 'hidden';
    const ellipsisWidth = element.offsetWidth;

    if (ellipsisWidth < noEllipsisWidth) {
      return true;
    } else {
      return false;
    }
}

0

समाधान @ItaloBorssatto एकदम सही है। लेकिन एसओ को देखने से पहले - मैंने अपना निर्णय लिया। यह रहा :)

const elems = document.querySelectorAll('span');
elems.forEach(elem => {
  checkEllipsis(elem);
});

function checkEllipsis(elem){
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const styles = getComputedStyle(elem);
  ctx.font = `${styles.fontWeight} ${styles.fontSize} ${styles.fontFamily}`;
  const widthTxt = ctx.measureText(elem.innerText).width;
  if (widthTxt > parseFloat(styles.width)){
    elem.style.color = 'red'
  }
}
span.cat {
    display: block;
    border: 1px solid black;
    white-space: nowrap;
    width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
}
 <span class="cat">Small Cat</span>
      <span class="cat">Looooooooooooooong Cat</span>


0

मेरा कार्यान्वयन)

const items = Array.from(document.querySelectorAll('.item'));
items.forEach(item =>{
    item.style.color = checkEllipsis(item) ? 'red': 'black'
})

function checkEllipsis(el){
  const styles = getComputedStyle(el);
  const widthEl = parseFloat(styles.width);
  const ctx = document.createElement('canvas').getContext('2d');
  ctx.font = `${styles.fontSize} ${styles.fontFamily}`;
  const text = ctx.measureText(el.innerText);
  return text.width > widthEl;
}
.item{
  width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
}
      <div class="item">Short</div>
      <div class="item">Loooooooooooong</div>


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.