Trouver des «pauses de ligne» dans la zone de texte qui est un texte ARABIC en train de Word

J'ai une chaîne de texte que je montre dans une zone de texte (orientation de droite à gauche). L'utilisateur peut redimensionner la zone de texte de manière dynamique (j'utilise jquery pour cela) et le texte sera enroulé si nécessaire.

Lorsque les hits de l'utilisateur sont soumis, je vais prendre ce texte et créer une image à l'aide de PHP, MAIS avant de soumettre, j'aimerais savoir où se produisent les «interruptions de ligne» ou plutôt les «contournements de mots».

Partout où j'ai regardé jusqu'à présent, il me montre comment traiter les sauts de ligne sur le côté php. Je tiens à préciser qu'il n'y a pas de dérangement. Ce que j'ai, c'est une longue chaîne qui sera enroulée par mots de différentes façons en fonction de la largeur de la zone de texte définie par l'utilisateur.

Je ne peux pas utiliser des «colonnes» ou une autre représentation de largeur standard car j'ai une police arabique très complexe qui est en fait composée de glyphes (caractères) de nombreuses largeurs différentes.

Si quelqu'un connaît un moyen d'accéder à l'endroit où se déroulent les enveloppes de mots (soit dans une zone de texte, soit dans une div si besoin-être), j'aimerais vraiment savoir.

Ma seule autre solution consiste à stocker (dans ma base de données) la largeur de chaque caractère (un peu fastidieux car il y a plus de 200 caractères dans 600 polices différentes, pour un total de … un nombre énorme).

Mes espoirs ne sont pas élevés, mais j'ai pensé que je demanderais.

Merci

je. Jamal

Bien, au lieu de trouver les sauts de ligne (ce qui est pratiquement impossible), vous pouvez les forcer dans la zone de texte, en utilisant cette fonction:

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", ""); } 

Cette fonction obtient l'ID de la zone de texte et, chaque fois qu'il y a une enveloppe de mots, elle entraîne une nouvelle rupture de ligne dans la zone de texte. Exécutez la fonction dans le formulaire de soumission et vous obtiendrez le texte avec des pauses de ligne appropriées dans le code côté serveur.

Testé avec succès pour IE, Chrome et Firefox, n'hésitez pas à voir ici: http://jsfiddle.net/yahavbr/pH79a/1/ (L'aperçu affichera les nouvelles lignes)

Voici une implémentation fonctionnellement équivalente de la solution de l'Assistant Ombre qui est beaucoup plus rapide car elle utilise la recherche binaire au lieu de la recherche linéaire pour déterminer la longueur de chaque ligne:

 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", ""); } 

Violoncelle mise à jour .

Je pense que la manière la plus simple de le faire serait de configurer le mot «enveloppement» de votre zone de texte dans le code html sur «dur», comme ceci:

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

Cela signifie que, chaque fois que votre zone de texte vous interrompre, vous insérerez également un caractère \ n linebreak charachter dans la chaîne lors de la soumission. Si vous trouvez que cela passe par votre chaîne, il sera facile de déterminer où était la rupture à l'origine. Ou vous pouvez également transformer ces caractères en
Tags html avec la fonction nl2br () de PHP.

Pour une raison quelconque, je n'ai jamais été averti lorsque cette publication a été mise à jour … et la nuit dernière, j'ai eu cette idée BRILLANTE sur la façon de déterminer où les interruptions de ligne étaient … Je reconstruisais la chaîne et vérifiai la largeur à chaque fois, Et il a travaillé alors je suis venu ici pour le partager … et j'ai trouvé que j'avais 1 semaine de retard

Quoi qu'il en soit 2 choses importantes

  1. Le code que vous avez fourni utilise la même idée brillante que j'ai eu (bien fait) MAIS quand je le teste, il casse la première ligne correctement puis ajoute une pause de ligne après chaque caractère (testé sur le lien jsfiddle.net)

  2. J'ai ajouté mon code qui utilise jquery et utilise la largeur d'une portée pour déterminer quand se briser. Au début, j'ai essayé d'utiliser la largeur de la div, mais div.width () renvoie la largeur par défaut, et non la largeur du contenu.

Je suis conscient que cela ne peut pas TRAVAILLER TOUTES LES NAVIGATEURS , alors je demande avec gentillesse que si quelqu'un connaît une façon de rendre cela infaillible, ou près de lui, partagez.

Tout d'abord, les styles sont nécessaires pour synchroniser les polices (tous les attributs) entre la zone de texte et div, définir la taille et (pour IE) supprimer toutes les barres de défilement qui apparaissent automatiquement.

 .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; } 

Ensuite, j'inclus jquery et mes fonctions personnalisées:

 <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>

Et enfin, ma page d'essai 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> 

Voici mon exemple pour calculer le nombre réel de lignes (après l'emballage de ligne) pour chaque ligne de texte dans une zone de texte. Notez que la largeur du texte d'une zone de texte diminue légèrement lorsque la barre de défilement commence à apparaître . Cela peut provoquer un retrait supplémentaire du contenu précédent afin que la hauteur de ligne précédemment calculée ne soit pas correcte. Par conséquent, la zone de texte doit avoir un dépassement de style CSS-y configuré pour "défiler" pour forcer l'affichage de la barre de défilement tout le temps .

 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; } 

La fonction ci-dessus renvoie le nombre réel de lignes enroulées pour chaque ligne de texte (séparée par "\ n") dans une zone de texte. Le calcul est précis au moins pour Chrome et Firefox.

Code testé dans "Crome", "Firefox" et "IE". Obtenez des flux de ligne et le transport retourne un composant "textArea" ( côté client avec javascript ).

FONCTIONNE BIEN!. Je voudrais le partager avec vous

Important d'inclure le style

  <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>