HTML : How to retain formatting in textarea? - html
I am using HTML textarea for user to input some data and save that to App Engine's model
The problem is that when I retrieve the content it is just text and all formatting is gone
The reason is because in textarea there is no formatting that we can make
Question:
is there any way to retain the format that user provides?
is there any other element(other than textarea), that i'll have to use?(which one?)
P.S I am very new to area of web development and working on my first project
Thank you
What you want is a Rich Text Editor. The standard HTML <textarea> tag only accepts plain text (even if the text is or includes HTML markup). There are a lot of example out there (including some listed on the page linked) but I would highly recommend using a prepackaged one for this. Coding your own is fairly complicated for people who are new, and even for a lot who have some experience. Both TinyMCE and CKEditor are very common ones, but there are many others as well.
A text box is like wordpad, you cant format it, if you paste in from word or any other formatted text it will wipe all the formatting and you will be left with just the text.
You need add an editor to the text areas, I use TinyMCE, but there are many other out there too.
To implement you need to have all the source (which you can get from TinyMCE) in your web directory.
Here's an example which you can try:
Add this the the head section of your page:
<script language="javascript" type="text/javascript" src="/js/tiny_mce/tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
theme : "advanced",
mode: "exact",
elements : "elm1",
theme_advanced_toolbar_location : "top",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,"
+ "justifyleft,justifycenter,justifyright,justifyfull,formatselect,"
+ "bullist,numlist,outdent,indent",
theme_advanced_buttons2 : "link,unlink,anchor,image,separator,"
+"undo,redo,cleanup,code,separator,sub,sup,charmap",
theme_advanced_buttons3 : "",
height:"350px",
width:"600px"
});
</script>
<script type="text/javascript">
tinyMCE.init({
// General options
mode : "textareas",
theme : "advanced",
plugins : "autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
// Theme options
theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertimage",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : true,
// Skin options
skin : "o2k7",
skin_variant : "silver",
// Example content CSS (should be your site CSS)
content_css : "css/example.css",
// Drop lists for link/image/media/template dialogs
template_external_list_url : "js/template_list.js",
external_link_list_url : "js/link_list.js",
external_image_list_url : "js/image_list.js",
media_external_list_url : "js/media_list.js",
// Replace values for the template plugin
template_replace_values : {
username : "Some User",
staffid : "991234"
}
});
</script>
Then to call the textarea:
<textarea name="content" style="width:100%">YOUR TEXT HERE</textarea>
NB: You need to download and have in your directory the js files for <script language="javascript" type="text/javascript" src="/js/tiny_mce/tiny_mce.js"></script>
Hope this helps!
This won't solve the case when you want somebody to be able to format their text (e.g. with WYSIWYG bold buttons etc.), but if you want to be able to accept pre-formatted HTML (e.g. copy and paste from other HTML source such as a webpage), then you can do this:
<form ...>
<label>Paste your HTML in the box below</label>
<textarea style='display:none' id='foo'></textarea>
<div id='htmlsource' contenteditable style='border:solid 1px black;padding:1em;width:100%;min-height:2em;' ></div>
<input type='submit' />
</form>
<script>
jQuery(function(){
jQuery('form').submit( function(e) {
jQuery('textarea').val( jQuery('#htmlsource').html() );
});
});
</script>
This uses a contenteditable div element which you can format to look like an input box and will accept pasted HTML, and a hidden textarea#foo which will be populated with the pasted HTML just before the form is submitted.
Note that this is not an accessible solution as it stands.
Depending on your goal for the programm it could already be sufficient to just add "pre" tags left and right to the input of your textarea. for example if your code submits to a form whatever is inside a textarea and than echos it in the target File this would already work.
> File 1:
>
> <form action="Output.php" methode=post>
> <textarea name="Input"></textarea>
> </form>
>
> File Output.php
>
> $UserInput = $_POST["Input"];
> $UserInput = "<pre>" . $UserInput . "</pre>"
> echo $UserInput
this already will retain all Enters for example that where used in the original user input and echo them correctly
If you retrieve the content from the App Engine Saving the Content with the pre tags added already in most cases does the trick
Related
TinyMCE 4 - allow AlpineJS attributes for all HTML tags
I want to allow all Alpine JS components (x-data, x-init, etc.) as attributes for all HTML tags in TinyMCE 4. I tried to add them via a rule for extended_valid_attributes in different ways, but everything fails. Either they are still stripped from the code or they become valid, but all other attributes are then stripped. Here are some examples of what I already tried, most of it I found in answers to other tinyMCE questions here (e.g. TinyMCE 4 - add custom styles/classes/attributes to any HTML tag) and read in the tinyMCE docs (https://www.tiny.cloud/docs-4x/configure/content-filtering/#extended_valid_elements, https://www.tiny.cloud/docs-4x/configure/content-filtering/#controlcharacters): $alpineAttributes = 'x-data|x-init|x-show|x-text|x-html|x-model|x-for|x-transition|x-effect|x-ignore|x-ref|x-cloak|x-teleport|x-if|x-id'; $settings['extended_valid_elements'] = '*['. $alpineAttributes .']'; -> select all elements via *: doesn't work, the alpine attributes still get stripped $settings['extended_valid_elements'] = '#['. $alpineAttributes .'],div,a,p'; -> here at least the attributes don't get stripped anymore for div, a and p tags, but all other attributes that would normally be allowed for each of those three now get stripped, because the list of allowed attributes doesn't get extended but overriden with my attributes. $settings['extended_valid_elements'] = '#['. $alpineAttributes .'],*'; -> doesn't work, the alpine attributes still get stripped $settings['extended_valid_elements'] = '#['. $alpineAttributes .']'; -> doesn't work, the alpine attributes still get stripped Is there really no way to just EXTEND the list of allowed attributes for each element instead of completely overriding it with my rules in extended_valid_elements?
We can solve this issue using different strategy. We can change Alpine prefix from x- to data-x-. As per the HTML standard x-data, x-init ... are not valid "custom attributes". The attributes need to have prefix data-. TinyMCE allows data-* custom data attributes by default, without having to specify them in any rules. So instead of forcing Alpine prefixes on TinyMce we can simply change the prefix on Alpine, using Alpine.prefix("data-x-"). Demo: on codepen <!DOCTYPE html> <html> <head> <style> #output { font-family: monospace; font-size: 0.9em; color: rgb(83, 23, 23); } </style> </head> <body> <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> <script src="https://unpkg.com/alpinejs#3.8.1/dist/cdn.min.js"></script> <script>Alpine.prefix("data-x-");</script> <p data-x-data="{date:'Date: '+ new Date().toISOString()}" data-x-text="date">date place holder</p> <textarea id=editor>Tiny!</textarea> <input type="button" id="btn" value="Show editor HTML content" /> <div id=output></div> <script type="text/javascript"> let content = `<br><p data-x-data="{date: 'Date: '+new Date().toISOString()}" data-x-text="date">date place holder</p>`; tinymce.init({ selector: '#editor', schema: 'html5', setup: function (editor) { editor.on('init', function (e) { editor.setContent(content); setTimeout(() => Alpine.initTree(editorDOM()), 200); }); } }); btn.onclick = function () { output.innerText = tinyMCE.activeEditor.getContent(); } function editorDOM() { return (editor_ifr.contentWindow ? editor_ifr.contentWindow.document : editor_ifr.contentDocument).body; } </script> </body> </html> The alpine x-text attribute works inside the editor as well, and it shows current date. This is because TinyMce allows our data-x-text attribute. Note: In the demo I've used TinyMce latest version 5. It works on version 4 as well. Tested using following CDN: <script src='https://cdn.tiny.cloud/1/no-api-key/tinymce/4/tinymce.min.js'></script> TinyMCE doesn't work on StackOverflow because of iframe restrictions that is why I've provided the codesandbox link.
multiple tinymce textareas
I use tinymce for a webpage that dynamically generates at least 5 texts. The configuration I use only works on the first textarea unfortunately. tinyMCE.init({ height : "300", mode : "exact", elements : "content", theme : "simple", editor_selector : "mceEditor", ... <textarea class="mceEditor" name="content" rows="15" cols="40">content</textarea> What's the configuration to enable tinymce editing in all textarea's.
If you're using "exact" mode you'll need to specify the ids of the elements you wish to convert to editors. function initMCEexact(e){ tinyMCE.init({ mode : "exact", elements : e, ... }); } // add textarea element with id="content" to document initMCEexact("content"); // add textarea element with id="content2" to document initMCEexact("content2"); // add textarea element with id="content3" to document initMCEexact("content3"); Or, you can use the "textarea" mode, which indiscriminately applies the editor to all textareas. function initMCEall(){ tinyMCE.init({ mode : "textareas", ... }); } // add all textarea elements to document initMCEall(); Just remember that if you're creating textareas dynamically, you will need to call tinyMCE.init() after creating the elements, because they need to be existing for tinyMCE to be able to convert them. Here is the documentation on modes.
For TinyMCE 4.0 you have to use a selector or defining a tinymce.init object/method for each desired configuration (https://www.tinymce.com/docs/get-started/multiple-editors/). For example, this is a page with 3 editors: <!DOCTYPE html> <html> <head> <script src="http://cdn.tinymce.com/4/tinymce.min.js"></script> <script type="text/javascript"> tinymce.init({ selector: '#myeditable-h1', toolbar: 'undo redo' }); tinymce.init({ selector: '.standard-editor' }); </script> </head> <body> <form method="post"> <h1 id="myeditable-h1">This Title Can Be Edited If You Click Here</h1> </form> <form method="post"> <div id="myeditable-div1" class="standard-editor"> <p>This section1 of content can be edited...</p> </div> <div id="myeditable-div2" class="standard-editor"> <p>This section2 of content can be edited...</p> </div> </form> </body> </html>
You should use different mode in your configuration. For example mode: "specific_textareas" to work for all textarea with a given class which is specified in the editor_selector parameter. In order to work on all textareas with class mceEditor you can use this: tinyMCE.init({ mode : "specific_textareas", editor_selector : "mceEditor", .....
use class in selector i have two or more textarea that i want init those with tiny int so <textarea class="mytextarea"></textarea> <textarea class="mytextarea"></textarea> . . . in init tinyint code: tinymce.init({ selector: 'textarea.mytextarea', plugins : 'advlist autolink link lists preview table code pagebreak', . . .
selector: 'textarea#new_f2f_feature_tech_notes,#new_f2f_feature_desc' We can add multiple tinymce textarea like above lo
According to tinymce.com/wiki.php/Configuration:selector, selector is the recommended way of selecting what elements should be editable. For all textarea elements, as requested: selector: "textarea", Or more elegantly, only those elements with a specific CSS tag: selector: "textarea.editme", <textarea class="editme">
Image tags returned by KCfinder are incomplete on CKeditor
Image tags returned by KCfinder are incomplete on CKeditor and not displayed/saved correctly. Note that i am using an inline CKEditor and KCFinder for image upload. Here are the integration codes: ckeditor/config.js config.filebrowserBrowseUrl = base_url+'/js/kcfinder/browse.php?type=files'; config.filebrowserImageBrowseUrl = base_url+'/js/kcfinder/browse.php?type=images'; config.filebrowserFlashBrowseUrl = base_url+'/js/kcfinder/browse.php?type=flash'; config.filebrowserUploadUrl = base_url+'/js/kcfinder/upload.php?type=files'; config.filebrowserImageUploadUrl = base_url+'/js/kcfinder/upload.php?type=images'; config.filebrowserFlashUploadUrl = base_url+'/js/kcfinder/upload.php?type=flash'; On page HTML <div id="page_body" contenteditable="true" class="full">...</div> On page JS <script type="text/javascript"> CKEDITOR.disableAutoInline = true; var editor = CKEDITOR.inline( 'page_body', { on: { focus: function(event){ var data = event.editor.getData(); alert(data); }, blur: function( event ) { var data = event.editor.getData(); var page_id = <?php echo $this->uri->segment(3) ?>; var page_link =$("#page_link").val(); $.ajax({ type: 'POST', url: '<?php echo site_url('admin/dashboard/ajaxChangePageData') ?>', data: { page_id: page_id, page_body: data,page_link:page_link }, beforeSend:function(){}, success:function(data){}, error:function(){ alert("Error"); } }); } } } ); </script> Strange is that i can browse the server/upload without any error with KCFinder i can even select an image from the server and the image is shown successfully in the content. but the code width height info are not present after a reload. I figured that the html created for the image was incomplete in source mode i see- <img alt="" src="/gchalk/content/images/333(1).jpg" 300px; height: 224px;" /> The situation just gets worse if for the second time i make some changes to the div say add some text. The image is lost and its treated as text, the above piece of code is shown as in source mode- <img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"=""> and it appears on browser/editor as - <img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"=""> I am tearing my hair for a day and cant find a way around. Please help me out to figure how to solve it. Oh, and for the record the text is saved in MySQL as "TEXT" through the ajax post i am pretty sure its not a problem but still just saying! I notice the image tag gets messed up in the default ckeditor(not inline) too.
Things that could effect the output of your code : 1- Magic Quotes when using PDO. if they are ON, turn them OFF in you php.ini! they are deprecated. Why am I telling you this? will because in your source mode you had 300px; height: 224px;" when you stored it and displayed it you had 300px;="" height:="" 224px;"="" 2- your CKeditor package. Try to download and reupload your Ckeditor (Update it to the last version if possible) other than that, I do not see anything wrong with the code you have provided. Good luck!
using color box in a wordpress plugin
I am developing a wordpress plugin in which i need to implement colorbox. I have the following code. Plugin works perfectly but the color box is not working. I have copied same colorbox code to an html file and its working. the only problem is in the wordpress plugin. Either i am not importing js and css exactly or any thing other is going wrong. Need help in urgent. <?php /* Plugin Name: my plugin Plugin URI: http://www.xxx.com/ Description: xxx Author: xxx Version: 1.0 Author URI: http://www.xxx.com */ wp_enqueue_style('colorbox.css', '\wordpress\wp- content\plugins\calc_plugin\colorbox.css'); wp_enqueue_script('jquery.js', '\wordpress\wp-content\plugins\calc_plugin\jquery.js', array('jquery1')); wp_enqueue_script('colorbox.js', '\wordpress\wp- content\plugins\calc_plugin\colorbox.js', array('jquery2')); function calc_form_markup() { $markup = <<<EOT <script> $(document).ready(function(){ $(".inline").colorbox({inline:true, width:"600", height:"450"}); }); </script> <div style='display:none' > <div id='inline_content1' style='padding:10px; background:#fff;'> <p><strong>This is inline content 1</strong></p> <image src = "http://wallpaper.goodfon.com/image/240138-1360x768.jpg" width = "175" height = " 150"> </div> </div> <p><a class='inline' href="#inline_content1">Inline HTML</a></p> EOT; return $markup; } add_shortcode('calc_form', 'calc_form_markup'); ?>
Your wp_enqueue_script is wrong. Here are the parameters: wp_enqueue_script( $handle ,$src ,$deps ,$ver ,$in_footer ); The $deps (dependency) being jQuery, which is included in WordPress already and called using jquery NOT 'jquery1'. Your JavaScript is wrong, Use a no conflict wrapper in WordPress, which is jQuery instead of $ $(document).ready(function() Should be jQuery(document).ready(function()
You are not loading the jQuery script that is required by Colorbox to function. Just enqueue it before you enqueue Colorbox.js. wp_enqueue_script("jquery");
Javascript Textarea Issue
I'm importing data from youtube into a textarea using Javascript. If you I simply place my Javascript code onto a blank area it displays the information fine, but for some reason it doesn't allow me to paste a same code into a textarea. Here is my code: <textarea rows="10" id="bandsvideodescription" name="bandsvideodescription"> <script type="text/javascript"> function youtubeFeedCallback( data ) { document.writeln( '' + data.entry[ "media$group" ][ "media$description" ].$t.replace( /\n/g, '' ) + '' ); } </script> </textarea> Any help would be great, Thanks.
Textareas are defined as: <!ELEMENT TEXTAREA - - (#PCDATA) -- multi-line text field --> They can only contain PCDATA, which means no elements (including <script> elements). Move the script to after the control, then get a reference to it (e.g. with document.getElementById) and set its value property instead of trying to write it out as the document loads.
Your script is interpreted as HTML code. You should escape angle brackets, like this: <textarea rows="10" id="bandsvideodescription" name="bandsvideodescription"> <script type="text/javascript"> function youtubeFeedCallback( data ) { document.writeln( '' + data.entry[ "media$group" ][ "media$description" ].$t.replace( /\n/g, '' ) + '' ); } </script> </textarea>
you can't put script tags <script> in a textarea you can't even put any html tag in a textarea. It will consider it as the default value ;) And escaping it with > our < will nt change anything because it's already escaped in the textarea to show it as simple text