2011-01-18 14 views
13

Mam ciąg tekstu, który wyświetlam w polu tekstowym (orientacja od prawej do lewej). Użytkownik może dynamicznie zmieniać rozmiar textarea (do tego używam jquery), a tekst będzie zawijany w razie potrzeby.znajdowanie "podziałów wierszy" w tekstach, czyli zawijanie tekstu Tekst ARABIC

Kiedy użytkownik trafi do przesłania, wezmę ten tekst i utworzę obraz za pomocą PHP, ALE przed przesłaniem chciałbym wiedzieć, gdzie występuje "podział wiersza" lub raczej "zawijanie wyrazów".

Wszędzie, gdzie zajrzałem do tej pory, pokazuje mi tylko, jak przetwarzać podziały wiersza po stronie php. Chcę wyjaśnić, że NIE MA ŻADNYCH PRZERWY W LINII. To, co mam, to jeden LONG ciąg, który będzie zawijany na różne sposoby w oparciu o szerokość przestrzeni tekstowej ustawionej przez użytkownika.

Nie mogę użyć "kolumn" ani żadnej innej standardowej reprezentacji szerokości, ponieważ mam bardzo złożoną czcionkę arabską, która faktycznie składa się z glifów (znaków) o różnych szerokościach.

Jeśli ktoś wie, jak uzyskać dostęp do miejsca, w którym występuje słowo zawijanie (albo w polu tekstowym, albo w razie potrzeby div), naprawdę chciałbym to wiedzieć.

Moim jedynym innym rozwiązaniem jest faktyczne przechowywanie (w moim DB) szerokości każdego znaku (nieco nudnego, ponieważ istnieje ponad 200 znaków w 600 różnych czcionkach, w sumie ... kilka ogromnych liczb).

Moje nadzieje nie są wysokie, ale myślałem, że zapytam.

Dzięki

i. Jamal

+0

Jak generujesz obraz? Zwykle podczas rysowania tekstu na obrazie można zdefiniować prostokąt zawijający tekst, który zostanie zawinięty zgodnie z tym prostokątem. –

Odpowiedz

14

Cóż, zamiast znalezienie przerwy linii (co jest praktycznie niemożliwe) można siła je do pola tekstowego, za pomocą tej funkcji:

function ApplyLineBreaks(strTextAreaId) { 
    var oTextarea = document.getElementById(strTextAreaId); 
    if (oTextarea.wrap) { 
     oTextarea.setAttribute("wrap", "off"); 
    } 
    else { 
     oTextarea.setAttribute("wrap", "off"); 
     var newArea = oTextarea.cloneNode(true); 
     newArea.value = oTextarea.value; 
     oTextarea.parentNode.replaceChild(newArea, oTextarea); 
     oTextarea = newArea; 
    } 

    var strRawValue = oTextarea.value; 
    oTextarea.value = ""; 
    var nEmptyWidth = oTextarea.scrollWidth; 
    var nLastWrappingIndex = -1; 
    for (var i = 0; i < strRawValue.length; i++) { 
     var curChar = strRawValue.charAt(i); 
     if (curChar == ' ' || curChar == '-' || curChar == '+') 
      nLastWrappingIndex = i; 
     oTextarea.value += curChar; 
     if (oTextarea.scrollWidth > nEmptyWidth) { 
      var buffer = ""; 
      if (nLastWrappingIndex >= 0) { 
       for (var j = nLastWrappingIndex + 1; j < i; j++) 
        buffer += strRawValue.charAt(j); 
       nLastWrappingIndex = -1; 
      } 
      buffer += curChar; 
      oTextarea.value = oTextarea.value.substr(0, oTextarea.value.length - buffer.length); 
      oTextarea.value += "\n" + buffer; 
     } 
    } 
    oTextarea.setAttribute("wrap", ""); 
} 

Ta funkcja uzyskać identyfikator textarea i ilekroć jest zawijanie wyrazów, powoduje przesunięcie nowego podziału linii do obszaru tekstowego. Uruchom funkcję w formularzu submit, a otrzymasz tekst z odpowiednimi podziałami linii w kodzie strony serwera.

Testowane pomyślnie dla IE, Chrome i Firefox nie krępuj się przekonaj się tutaj: http://jsfiddle.net/yahavbr/pH79a/1/ (podgląd pokaże nowe linie)

+0

lol ...Podany kod używa tej samej genialnej idei, którą miałem (dobrze zrobione), ALE kiedy testuję, łamie pierwszą linię poprawnie, a następnie dodaje przerwę linii po każdej postaci (testowane pod linkiem jsfiddle.net) –

+0

@Irfan działa po prostu dla mnie dobrze ... wpisz "cześć, jak się masz dzisiaj?" Mam nadzieję, że wszystko w porządku! " i ładnie się rozdzieli na trzy linie. Czy możesz opublikować zrzut ekranu? –

+0

Niesamowita sztuczka, dzięki! –

1

Z jakiegoś powodu, nigdy nie został powiadomiony kiedy ten post został zaktualizowany ... i zeszłej nocy, miałem ten genialny pomysł, jak ustalić, gdzie podziały były ... Przebudowałem ciąg i sprawdzałem szerokość za każdym razem, i DZIAŁAłem , więc przyszedłem tu, aby się nim podzielić ... i Znaleziono 1 tydzień za

W każdym razie 2 ważne rzeczy

  1. Podany kod używa tej samej genialnej idei, którą miałem (dobrze zrobione), ALE kiedy testuję, łamie pierwszy wiersz poprawnie, a następnie dodaje przerwę linii po każdym znaku (testowane pod linkiem jsfiddle.net)

  2. Dodałem mój kod, który używa jquery i używa szerokości przęsła do określenia, kiedy złamać Najpierw próbowałem użyć szerokości div, ale div.width() zwraca domyślną szerokość, a nie szerokość treści.

Jestem świadomy, to może nie działać na wszystkich przeglądarkach tak, proszę uprzejmie, że jeśli ktoś zna sposób dokonywania to niezawodny, lub blisko niego, proszę podzielić.

Po pierwsze, style są niezbędne do synchronizacji czcionek (wszystkie atrybuty) między tekstem a elementem div, ustawiania rozmiaru i (w przypadku IE) usuwania pasków przewijania, które pojawiają się automatycznie.


    .inputArea { 
     width:200px; 
     height:100px; 
     font-family:Arial; 
     font-size:12px; 
     overflow: auto; 
     border: 1px solid #cccccc; 
     padding:0; 
     margin:0; 
    } 
    .divArea { 
     font-family:Arial; 
     font-size:12px; 
    } 

Następnie I obejmują jQuery i moje funkcje niestandardowe:


    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js 
"></script> 
    <script type="text/javascript"> 
    $(document).ready(function() { 
    $("#breakUp").click(function() { 
     showLineBreaks(); 
     addLineBreaks(); 
    }); 

    function showLineBreaks() { 
     content = $("#textEntered").val(); 
     //replace line breaks in content with "|" to allow for replacement below 
     content = content.replace("\r\n", "
"); content = content.replace("\r", "
"); content = content.replace("\n", "
"); $("#unedited").html(content); } function addLineBreaks() { content = $("#textEntered").val(); //replace line breaks in content with "|" to allow for replacement below content = content.replace("\r\n", "|"); content = content.replace("\r", "|"); content = content.replace("\n", "|"); tempContent = ""; $("#edited").html(""); for (var i = 0; i "); } else { tempContent = $("#edited").html(); $("#edited").html(tempContent + content.charAt(i)); if ($("#edited").width() > 200) { $("#edited").html(tempContent + "
" + content.charAt(i)); } } } } }); <script>

i wreszcie moją stronę testową HTML


    Enter text into the textarea below (Set to 200 px width, 100 px height)<br> 
    <textarea id="textEntered" class="inputArea"></textarea> 
    <br><br> 
    The div below will display that text WITHOUT wrapping, BUT replacing all existing line breaks with <br><br> 
    <div id="unedited"></div> 
    <br> 
    The following div will display that text with line breaks ADDED to fit the wrapping<br> 
    <div class="divArea"><span id="edited"></span></div> 
    <br> 
    <button id="breakUp">Click Here to Convert</button>
3

myślę najprostszy sposób robienia byłoby ustawić zawijanie tekstu w polu tekstowym w kodzie HTML na "twardy", na przykład:

<textarea id='yourTextArea' wrap='hard'></textarea> 

Oznacza to, że wszędzie tam, gdzie twoje pole tekstowe łamie linię, wstawisz także znak \ n wiersza linii podczas wysyłania. Jeśli znajdziesz to przechodząc przez twój ciąg znaków, ułatwi to ustalenie, gdzie początkowo była przerwa. Możesz też zamienić te znaki na
znaczników html za pomocą funkcji nl2br() w PHP.

+5

Jest to bardzo przydatne. Ale wydaje się niemożliwe, aby wykryć te przerwy w linii tylko z javascript bez umieszczania ich na serwerze. Jeśli ktokolwiek dowie się, jak to zrobić, opublikuj. – Mulhoon

13

Oto funkcjonalnie równoważne wdrożenie rozwiązania Cienia kreatora, który jest o wiele szybciej, ponieważ używa przeszukiwanie binarne zamiast przeszukiwanie liniowe, aby określić długość każdej linii:

function ApplyLineBreaks(strTextAreaId) { 
    var oTextarea = document.getElementById(strTextAreaId); 
    if (oTextarea.wrap) { 
     oTextarea.setAttribute("wrap", "off"); 
    } 
    else { 
     oTextarea.setAttribute("wrap", "off"); 
     var newArea = oTextarea.cloneNode(true); 
     newArea.value = oTextarea.value; 
     oTextarea.parentNode.replaceChild(newArea, oTextarea); 
     oTextarea = newArea; 
    } 

    var strRawValue = oTextarea.value; 
    oTextarea.value = ""; 
    var nEmptyWidth = oTextarea.scrollWidth; 

    function testBreak(strTest) { 
     oTextarea.value = strTest; 
     return oTextarea.scrollWidth > nEmptyWidth; 
    } 
    function findNextBreakLength(strSource, nLeft, nRight) { 
     var nCurrent; 
     if(typeof(nLeft) == 'undefined') { 
      nLeft = 0; 
      nRight = -1; 
      nCurrent = 64; 
     } 
     else { 
      if (nRight == -1) 
       nCurrent = nLeft * 2; 
      else if (nRight - nLeft <= 1) 
       return Math.max(2, nRight); 
      else 
       nCurrent = nLeft + (nRight - nLeft)/2; 
     } 
     var strTest = strSource.substr(0, nCurrent); 
     var bLonger = testBreak(strTest); 
     if(bLonger) 
      nRight = nCurrent; 
     else 
     { 
      if(nCurrent >= strSource.length) 
       return null; 
      nLeft = nCurrent; 
     } 
     return findNextBreakLength(strSource, nLeft, nRight); 
    } 

    var i = 0, j; 
    var strNewValue = ""; 
    while (i < strRawValue.length) { 
     var breakOffset = findNextBreakLength(strRawValue.substr(i)); 
     if (breakOffset === null) { 
      strNewValue += strRawValue.substr(i); 
      break; 
     } 
     var nLineLength = breakOffset - 1; 
     for (j = nLineLength - 1; j >= 0; j--) { 
      var curChar = strRawValue.charAt(i + j); 
      if (curChar == ' ' || curChar == '-' || curChar == '+') { 
       nLineLength = j + 1; 
       break; 
      } 
     } 
     strNewValue += strRawValue.substr(i, nLineLength) + "\n"; 
     i += nLineLength; 
    } 
    oTextarea.value = strNewValue; 
    oTextarea.setAttribute("wrap", ""); 
} 

Updated fiddle.

+0

Zdumiewające, skorzystałem z okazji, aby dodać przypadek testowy na żywo i przetestować z 10 akapitami [Lorem Ipsum] (http://generator.lorem-ipsum.info/), a zmiana jest naprawdę duża. Sława! –

+1

Pamiętaj, że to nie działa w niektórych przypadkach. Jeśli szerokość pola tekstowego jest tak duża jak koniec słowa, słowo pojawi się w następnym wierszu. – ben

0

Kod testowany w "Crome", "Firefox" i "IE". Pobierz wiersz i karetka zwraca komponent "textArea" (strona klienta z javascript).

DZIAŁA DOBRZE !. Chciałbym podzielić się z wami

ważne to styl

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
<%--//definimos un estilo--%> 
<STYLE type="text/css"> 
    #CadTemp 
    { 
     font-family: "Arial", serif; 
     font-size: 12pt; 
     visibility: hidden; 
     position: absolute; 
     top: -100; 
     left: 0px; 
    } 
</STYLE> 

    <script type="text/javascript"> 
     function mostrar() { 
      return 'ancho cadena: ' + document.getElementById('myTextarea').value.visualLength() + ' \n' + 'ancho textarea: ' + (document.getElementById('myTextarea').scrollWidth -4); 
     } 


     //sustituimos el espacio en blanco por el punto, tienen exactamente el mismo tamaño en 'pixeles' 
     function reemplazarEspacios(texto) { 
      var devolver = ""; 
      for (var i = 0; i < texto.length; i++) { 
       if (texto.charAt(i) == ' ') { 
        devolver += '.' 
       } else { 
        devolver += texto.charAt(i); 
       } 
      } 
      return devolver; 
     } 

     // Calcula los pixeles de ancho que ocupa un texto (la cadena debe tener el mismo tamaño y tipo de fuente) 
     String.prototype.visualLength = function() { 
      var ruler = document.getElementById("CadTemp");    
      ruler.innerHTML = reemplazarEspacios(this) 
      return ruler.offsetWidth; 
     } 

     //quitar espacios a la derecha de la cadena 
     String.prototype.rtrim = function() {return this.replace(/\s+$/,"");} 

     //devuelve el ultimo espacio de la cadena (que no sea espacio final) 
     function IndEspacio(cadena) { 
      //quito los espacios al final 
      var cadenaTemp = cadena.rtrim(); 
      return cadenaTemp.lastIndexOf(' '); 
     } 

     //insertar un salto de linea 
     function AplicarSaltosLinea(ID_elemento) { 
      //guardo el elemento web en una variable 
      var TextArea = document.getElementById(ID_elemento); 
      var cadenaTexto = ""; 
      var Cadenafinal = ""; 
      var buffer = ""; 

      //recorremos toda la cadena 
      for (var i = 0; i < TextArea.value.length; i++) { 
       //guardamos el caracater en la cadena 
       cadenaTexto += TextArea.value.charAt(i); 

       //si hay un retorno de carro, antes de llegar al final del textArea 
       if (TextArea.value.charAt(i) == '\n') { 
        Cadenafinal += cadenaTexto.substr(0, cadenaTexto.lastIndexOf('\n') + 1) ; 
        cadenaTexto = ""; 
       } 

       //si el ancho actual de la cadena es mayor o igual que el ancho del textarea (medida pixeles) 
       if (cadenaTexto.visualLength() > TextArea.scrollWidth - 4) { 
        //recuperamos el ultimo espacio en blanco antes de la ultima letra o palabra 
        var indiceEspacio = IndEspacio(cadenaTexto) 

        buffer = ""; 
        //ultimo espacio en blanco detectado, metemos el trozo de palabra desde el ultimo espacio 
        if (indiceEspacio >= 0) { 
         for (var j = indiceEspacio + 1; j <= i; j++) 
          buffer += cadenaTexto.charAt(j); 
         indiceEspacio = -1; 
        } else { 
         buffer += TextArea.value.charAt(i); 
        } 
        //coloca la cadena 
        Cadenafinal += cadenaTexto.substr(0, cadenaTexto.length - buffer.length) + "\n"; 
        cadenaTexto = buffer; 
       } 
      } 

      Cadenafinal += cadenaTexto; 

      document.getElementById("pnlPreview").innerHTML = Cadenafinal.replace(new RegExp("\\n", "g"), "<br />"); 
     } 


    </script> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <span id="CadTemp">hola</span> 
    </div> 
    <br /> 
    <div> 
     <textarea cols="20" rows="5" id="myTextarea" wrap="hard" 
      style="font-family: Arial, Helvetica, sans-serif; font-size: 12pt"></textarea> 
    </div> 
    <div id="pnlPreview"></div> 
    <div> 
     <button type="button" onclick="AplicarSaltosLinea('myTextarea');">Apply Line Breaks</button> 
     <button type="button" onclick="alert(document.getElementById('myTextarea').value)">mensaje</button> 
     <button type="button" onclick="alert(mostrar())">calcular Ancho Pixel</button> 
     <br /> 
     </div> 
    </form> 
</body> 
</html> 
1

Oto mój przykład do obliczania rzeczywistej liczby wierszy (po zawijania linii) dla każdego wiersza tekstu w textarea. Zauważ, że szerokość tekstu w polu tekstowym zmniejsza się nieznacznie, gdy pasek przewijania zaczyna się pojawiać. Może to spowodować dalsze zawijanie poprzedniej treści, aby obliczona wcześniej wysokość wiersza nie była poprawna. Dlatego też, tekst musi mieć przepełnienie stylu CSS-y ustawione na "przewijanie", aby wymusić wyświetlanie paska przewijania przez cały czas..

function get_row_wraps(txtArea){       
    if(wrap=="off"){          
     var out=[];          
     for(var i=txtArea.split_lines.length; i>=0; --i) 
      out[i]=1;         
     return out;          
    }             

    var its=txtArea.value.split("\n");       
    var newArea = txtArea.cloneNode(true);    
    newArea.hidden=true;         
    newArea.style.visibility = "hidden";     
    txtArea.parentNode.appendChild(newArea);    

    // get single row height        
    newArea.style.height="auto";       
    newArea.style.overflowY="scroll";     
    newArea.value="1\n2\n3";        
    var unit_height=newArea.scrollHeight;    
    newArea.value="1\n2\n3\n4";       
    var unit_height=newArea.scrollHeight-unit_height; 
    newArea.style.height=Math.round(unit_height*1.5)+"px"; // so that the scrollbar does not vanish 
    newArea.value="";         

    // obtain row height for every line of text   
    function comp_Nrow(scroll_height){     
     return Math.floor(scroll_height/unit_height); 
    }             
    function calc_rows(txt){        
     newArea.value+=txt;        
     return comp_Nrow(newArea.scrollHeight);   
    }             
    var out=[];           
    for(var i=0; i<its.length; i++)      
     out.push(calc_rows(i==0?its[i]:("\n"+its[i]))); 
    txtArea.parentNode.removeChild(newArea);    
    for(var i=out.length-1; i>0; i--)     
     out[i]-=out[i-1];        
// alert(out);           
    return out;           
}              

Powyższa funkcja zwraca rzeczywistą liczbę zawiniętych wierszy dla każdego wiersza tekstu (oddzielonych "\ n") w polu tekstowym. Obliczenia są dokładne co najmniej dla przeglądarki Chrome i Firefox.

Powiązane problemy