2008-11-12 3 views
9

कभी-कभी आपके पास स्ट्रिंग्स होती हैं जो एक निश्चित पिक्सेल चौड़ाई के भीतर फिट होनी चाहिए। यह कार्य इतना कुशलता से करने का प्रयास करता है। :)किसी दिए गए पिक्सेल चौड़ाई के भीतर फिट करने के लिए अच्छी तरह से एक स्ट्रिंग को छिड़काएं

function fitStringToSize(str,len) { 
    var shortStr = str; 
    var f = document.createElement("span"); 
    f.style.display = 'hidden'; 
    f.style.padding = '0px'; 
    document.body.appendChild(f); 

    // on first run, check if string fits into the length already. 
    f.innerHTML = str; 
    diff = f.offsetWidth - len; 

    // if string is too long, shorten it by the approximate 
    // difference in characters (to make for fewer iterations). 
    while(diff > 0) 
    { 
     shortStr = substring(str,0,(str.length - Math.ceil(diff/5))) + '…'; 
     f.innerHTML = shortStr; 
     diff = f.offsetWidth - len; 
    } 

    while(f.lastChild) { 
     f.removeChild(f.lastChild); 
    } 
    document.body.removeChild(f); 

    // if the string was too long, put the original string 
    // in the title element of the abbr, and append an ellipsis 
    if(shortStr.length < str.length) 
    { 
     return '<abbr title="' + str + '">' + shortStr + '</abbr>'; 
    } 
    // if the string was short enough in the first place, just return it. 
    else 
    { 
     return str; 
    } 
} 

अद्यतन नीचे अपना सुझाव या refactorings पोस्ट करें: @ नीचे कुछ के समाधान में काफी बेहतर है, कृपया इसका इस्तेमाल करें।

अद्यतन 2: कोड अब gist के रूप में पोस्ट किया गया है; कांटे से मुक्त महसूस करें और पैच सबमिट करें :)

उत्तर

22

आपके कोड के साथ कुछ समस्याएं हैं।

  • / 5 क्यों? वर्णों की चौड़ाई font-family और font-size पर निर्भर करती है।
  • आप abbr title में str पलायन करना होगा (या किसी एक "कोड अमान्य कर देगा)।
  • diff घोषित नहीं किया गया है और वैश्विक क्षेत्र
  • substring इस तरह काम करने वाला नहीं है में समाप्त होता है। आप किस ब्राउज़र का उपयोग कर रहे हैं?
  • hiddenstyle.display की कोई मान्य मान नहीं है। इसे छिपाने के लिए आप मूल्य none का उपयोग करना चाहिए, लेकिन फिर ब्राउज़र offsetWidth गणना नहीं है। बजाय style.visibility="hidden" का प्रयोग करें।
  • सही के लिए खोज लंबाई ver है वाई अक्षम
  • बच चाहिए &lt;/abbr&gt; "

मैं इसे आप के लिए दुबारा लिखा और className जोड़ा ताकि आप स्थापित करने के लिए एक शैली का उपयोग कर सकते font-family और font-size। श्री Fooz सुझाव दिया है कि आप पूरी स्ट्रिंग को दिखाने के लिए माउसओवर का उपयोग करें। यही कारण है जबकि एक छोटे से अधिक परीक्षण मैं कीड़े की एक जोड़ी पाया: नहीं के बाद से आवश्यक आधुनिक ब्राउज़रों उसके लिए आपको

function fitStringToSize(str,len,className) { 
    var result = str; // set the result to the whole string as default 
    var span = document.createElement("span"); 
    span.className=className; //Allow a classname to be set to get the right font-size. 
    span.style.visibility = 'hidden'; 
    span.style.padding = '0px'; 
    document.body.appendChild(span); 


    // check if the string don't fit 
    span.innerHTML = result; 
    if (span.offsetWidth > len) { 
     var posStart = 0, posMid, posEnd = str.length; 
     while (true) { 
      // Calculate the middle position 
      posMid = posStart + Math.ceil((posEnd - posStart)/2); 
      // Break the loop if this is the last round 
      if (posMid==posEnd || posMid==posStart) break; 

      span.innerHTML = str.substring(0,posMid) + '&hellip;'; 

      // Test if the width at the middle position is 
      // too wide (set new end) or too narrow (set new start). 
      if (span.offsetWidth > len) posEnd = posMid; else posStart=posMid; 
     } 
     //Escape 
     var title = str.replace("\"","&#34;"); 
     //Escape <and> 
     var body = str.substring(0,posStart).replace("<","&lt;").replace(">","&gt;"); 
     result = '<abbr title="' + title + '">' + body + '&hellip;<\/abbr>'; 
    } 
    document.body.removeChild(span); 
    return result; 
    } 

संपादित करें (एफएफ, IE, ओपेरा और क्रोम के साथ परीक्षण) से करते हैं।

  • मैं बजाय Math.ceil इस्तेमाल किया इरादा Math.floor (मैं पर इस दोष है कि अंग्रेजी मेरी देशी भाषा नहीं है)

  • तो इनपुट स्ट्रिंग एचटीएमएल टैग था तो परिणाम होगा अपरिभाषित जा (यह मध्य में किसी टैग को काटना या खुले टैग को छोड़ने के लिए अच्छा नहीं है)

सुधार:

  • सभी स्थानों पर अवधि में कॉपी की गई स्ट्रिंग से बचें। तुम अब भी html-संस्थाओं का उपयोग कर सकते हैं, लेकिन कोई टैग की अनुमति है (< और > प्रदर्शित किया जाएगा)
  • दुबारा लिखा while -statement (यह एक थोड़ा तेजी से होता है, लेकिन मुख्य कारण बग से छुटकारा पाने के लिए किया गया था कि वजह से अतिरिक्त दौर और अलग होने के बयान से छुटकारा पाने के लिए )
  • को fitStringToWidth

संस्करण समारोह का नाम बदला 2:

function fitStringToWidth(str,width,className) { 
    // str A string where html-entities are allowed but no tags. 
    // width The maximum allowed width in pixels 
    // className A CSS class name with the desired font-name and font-size. (optional) 
    // ---- 
    // _escTag is a helper to escape 'less than' and 'greater than' 
    function _escTag(s){ return s.replace("<","&lt;").replace(">","&gt;");} 

    //Create a span element that will be used to get the width 
    var span = document.createElement("span"); 
    //Allow a classname to be set to get the right font-size. 
    if (className) span.className=className; 
    span.style.display='inline'; 
    span.style.visibility = 'hidden'; 
    span.style.padding = '0px'; 
    document.body.appendChild(span); 

    var result = _escTag(str); // default to the whole string 
    span.innerHTML = result; 
    // Check if the string will fit in the allowed width. NOTE: if the width 
    // can't be determined (offsetWidth==0) the whole string will be returned. 
    if (span.offsetWidth > width) { 
    var posStart = 0, posMid, posEnd = str.length, posLength; 
    // Calculate (posEnd - posStart) integer division by 2 and 
    // assign it to posLength. Repeat until posLength is zero. 
    while (posLength = (posEnd - posStart) >> 1) { 
     posMid = posStart + posLength; 
     //Get the string from the beginning up to posMid; 
     span.innerHTML = _escTag(str.substring(0,posMid)) + '&hellip;'; 

     // Check if the current width is too wide (set new end) 
     // or too narrow (set new start) 
     if (span.offsetWidth > width) posEnd = posMid; else posStart=posMid; 
    } 

    result = '<abbr title="' + 
     str.replace("\"","&quot;") + '">' + 
     _escTag(str.substring(0,posStart)) + 
     '&hellip;<\/abbr>'; 
    } 
    document.body.removeChild(span); 
    return result; 
} 
+0

बहुत अच्छा, धन्यवाद।/5 को मेरे आवेदन में नजरअंदाज करने के आधार पर चुना गया था (एम 10 पीएक्स है, एफ 3 पीएक्स है)। यह वास्तव में बकवास का प्रकार है क्योंकि स्ट्रिंग को रखा जाएगा कि div के स्टाइल के आधार पर फ़ॉन्ट का आकार बदल जाएगा, इसलिए आदर्श रूप से हम शरीर में शामिल नहीं होंगे, लेकिन उस div के लिए। – Aeon

+0

भागने: अच्छा बिंदु! उसे पकड़ नहीं लिया ... – Aeon

+0

सबस्ट्रिंग: गाह, मुझे लगता है कि एक टाइपो था, रेंज स्टार्ट ऑपरेटर भूल गया। – Aeon

3

एक त्वरित नज़र में, यह मेरे लिए अच्छा लग रहा है। यहां कुछ मामूली सुझाव दिए गए हैं:

  • रैखिक एक के बजाय इष्टतम आकार खोजने के लिए बाइनरी खोज का उपयोग करें।

  • (वैकल्पिक रूप से) माउसओवर जोड़ें ताकि एक टूलटिप पूर्ण स्ट्रिंग दे।

+0

शीर्षक संपत्ति सभी आधुनिक ब्राउज़रों में माउसओवर टूलटिप दे देंगे :) जब आप बाइनरी खोज कहते हैं, तो आपका क्या मतलब है? अभी यह स्ट्रिंग को कम से कम वर्णों की अनुमानित संख्या से कम करने की कोशिश करता है, इसलिए इसमें केवल 1-3 पुनरावृत्तियों होना चाहिए चाहे कितना समय स्ट्रिंग – Aeon

2

क्या आप एक ही समारोह लिख सकते हैं लेकिन एक div की चौड़ाई और ऊंचाई फिट करने के लिए? मेरे पास निश्चित चौड़ाई और ऊंचाई वाला एक div है, जहां मुझे डेटाबेस से टेक्स्ट डालना होगा। यदि पाठ div के लिए बहुत बड़ा है, तो मैं इसे अंत में और विज्ञापन काटना चाहता हूं ... अंत में? मुमकिन? धन्यवाद

संपादित करें: मेरे प्रयोजन के लिए

<p id="truncateMe">Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean consectetuer. Etiam venenatis. Sed ultricies, pede sit 
amet aliquet lobortis, nisi ante sagittis sapien, in rhoncus lectus 
mauris quis massa. Integer porttitor, mi sit amet viverra faucibus, 
urna libero viverra nibh, sed dictum nisi mi et diam. Nulla nunc eros, 
convallis sed, varius ac, commodo et, magna. Proin vel 
risus. Vestibulum eu urna. Maecenas lobortis, pede ac dictum pulvinar, 
nibh ante vestibulum tortor, eget fermentum urna ipsum ac neque. Nam 
urna nulla, mollis blandit, pretium id, tristique vitae, neque. Etiam 
id tellus. Sed pharetra enim non nisl.</p> 

<script type="text/javascript"> 

var len = 100; 
var p = document.getElementById('truncateMe'); 
if (p) { 

    var trunc = p.innerHTML; 
    if (trunc.length > len) { 

    /* Truncate the content of the P, then go back to the end of the 
     previous word to ensure that we don't truncate in the middle of 
     a word */ 
    trunc = trunc.substring(0, len); 
    trunc = trunc.replace(/\w+$/, ''); 

    /* Add an ellipses to the end and make it a link that expands 
     the paragraph back to its original size */ 
    trunc += '<a href="#" ' + 
     'onclick="this.parentNode.innerHTML=' + 
     'unescape(\''+escape(p.innerHTML)+'\');return false;">' + 
     '...<\/a>'; 
    p.innerHTML = trunc; 
    } 
} 

</script> 

मैं से ... लिंक हटा दिया, के रूप में मैं अपने पन्ने पर अन्य टैब कि पूरा पाठ रखती है: मैं अपने प्रश्न के लिए जे एस समाधान मिल गया।

संबंधित मुद्दे