Why is my TinyMCE hidden textarea acting up? - javascript

I have about 7 textareas on a web page, all of them are rich text editors using TinyMCE. However at page load only 1 of them is visible and the rest of them hidden. The user can click a 'show' link which would display the remaining textareas one by one.
However, I have a weird problem. All the textareas are setup like this:
<textarea cols="40" rows="20"></textarea>
However, only the textarea displayed on page load is the full size I want it to be. The remaining textareas are really small when I show them. So I'm thinking that perhaps they aren't rendered because they are hidden on page load.
How can I remedy this?

Try adding some CSS to textareas that are hidden.
For example, use
<textarea cols="40" rows="20" style="width: 40em; height: 20em"></textarea>
I think I ran into this, where TinyMCE's CSS overrides some of the default CSS behaviour. I ended up having to "re-override" it, and eventually edited the TinyMCE's css pages.

I think this is an MCE bug, or at least a feature that MCE lacks.
Since I wanted to style my input box in CSS, not in HTML (yuck) I tried
visibility: hidden;
instead of
display: none;
and everything worked again.
I believe that the latter causes the element to take up no space, which trips up the MCE code which detects the width and height of the element.

When loading TinyMCE with jQuery, this problem can be solved as such:
1- On your textarea, specify a height in the inline style attribute:
<textarea style="height:200px;" class="tinymce" name="myfield"></textarea>
2- add a callback function when instantiating a TinyMCE editor. e.g. tinymceLoaded
$('textarea.tinymce').tinymce({
// Location of TinyMCE script
script_url : 'PATH_TO_TINYMCE.js',
// General options ...
// Theme options...
// callback function
init_instance_callback : "tinymceLoaded"
});
3- Set the height of your Editors in the tinymceLoaded function:
function tinymceLoaded(inst){
// get the desired height of the editor
var height = $('#' + inst.editorId).height();
// when the editor is hidden, the height calculated is 0
// Lets use the inline style text to solve this problem
if(height == 0){
height = $('#' + inst.editorId).css('height'); // 200px
height = height.replace(/[^0-9]/g, ""); // remove all non-numeric characters to isolate the '200'
}
// set the height of the hidden TinyMCE editor
$('#' + inst.editorId + '_ifr').css({height: height + 'px'});
}

Without having a few more specifics about your actual setup and how you're doing the vaious display/hide functionality it's hard to give a definitive answer.
I can throw a few general thoughts out though:
Do they render properly when you don't hide them on page load? That would give a definative answer for at what point the bug's occuring.
When you toggle the view of the textarea can you explicity set the row/col attributes at the same time?
Can you use css (maybe with !important) to set textarea width and height than to test if that has an effect?

From TinyMCE inside hidden div are not displayed as enabled when we put the div visible, user's slolife answer helped me:
Try calling tinyMCE.init(...) after you unhide the containing div.

I've been having the same issue where the height of the hidden textarea controls that were converted into TinyMCE editors were too small. Setting visibility to none worked but leaves a big empty space in its place.
The following solution worked well for me:
Do not hide your textarea controls initially on page load
Instead, set all of your TinyMCE's init config as follows:
tinyMCE.init({
...
init_instance_callback : "onInstanceInit"
});
In your onInstanceInit function, hide the initialized TinyMCE editor dynamically
If you show this editor afterwards, the height will be normal again just like it was never hidden

If you use production version of TinyMCE, you probably forgot to copy folders that tinymce.min.js needs. You need to have folders langs, plugins, skins and themes in the same folder as your tinymce.min.js file.

Another reason for the hidden thing is when you remove elements from the dom with tinymce initialized on them. You need to remove tinymce from this element first, so you will avoid weird behaviour when initialize new tinymce elements.
So for exemple :
removeElementWithTinymce = function(elementToRemove){
var parent = elementToRemove.parentNode;
tinymce.remove(elementToRemove.getAttribute('id'));
parent.removeChild(elementToRemove);
};
That's it.

Related

How to disable Evernote web view "max-width" with JavaScript?

Evernote places a max-width limit on web view content, and I have identified its location in Chrome developer tool(F12). Evidence: Unticking the checkbox beside "max-width" will stretch the table to full window width.
My question is, how can I remove that css statement with JavaScript code?
I have tried this:
document.getElementById("container").style.removeProperty("max-width")
but in vain.
The above web page can be reached at http://www.evernote.com/l/ABXYD6q6bM9MyaAfRs78hQnq6VMINfVJODg/
Given that this statement isn't set as inline style, you won't be able to remove it.
However, you could change its value and set it to none by adding an inline style declaration, which will override the current value.
Demo:
var elem = document.getElementById('container');
elem.style.maxWidth = 'none';
Not sure how webview works, but could you try using javascript to add a new class to it that added a max-width of 100%?
document.getElementById("container").classList.add('no-max-width');
then in the styles.css put
.no-max-width {
max-width: 100%; }
If that's not possible, then try
document.getElementById("container").style.maxWidth('100%');
Though I sometimes have trouble with .styles so not sure if that is exactly right, plus I've read it's better to add classes rather than play with css styles in JS, but also not sure how accurate that is.

How can I stop jQuery UI dialogs from getting squashed?

I have a fairly simple div element which I want to turn into a popup via jQuery UI. The HTML is basically
<div id="login_form">
<table> ... </table>
</div>
Without any jQuery involvement, it renders fairly naturally like this (the green background comes from the div and fits around its contents):
When I make it into a popup with this code:
$(document).ready(function()
{
$("#login_form") .dialog (
{
autoOpen: false
});
$("#login_or_sign_up") .click (function()
{
$("#login_form") .dialog ("open");
});
});
It renders like this.
Yuck.
I'm fairly sure the reason is simply that I haven't included the jQuery UI CSS files. I don't want to include the jQuery UI CSS files.
By inspecting the popup I notice that jQuery has created another div which surrounds the one I provided, and this is styled to have a width of 300px. I expect this is the problem -- jQuery UI has picked a size which is too small and the inner elements are not reducing themselves to fit.
Can I make jQuery dialog-ify my div without shrinking it?
If not, I can probably work around this by adding width:100% styles to the inner elements individually. In that case, is there a general workaround which will not require me to alter any of the inner elements?
.dialog({ width: 'auto' }) works.

add style's to the textarea 's specific line

I have html textarea dynamically it's content changing line by line. I want to add some styles to the updated or modified line content. Is there any windows selection, like properties, to do it??
What I want is make user feel, that the change has happen. Or any other way to achieve it?
There is no simple way to achieve it just by CSS with textarea, but the problem is solvable for sure :)
you can replace textarea with <div contenteditable><p></p></div>
you can set textarea CSS: background: transparent and manipulate some element below the textarea
you can modify this jQuery plugin: https://github.com/cotenoni/jquery-linedtextarea to manipulate specific lines (some CSS work required, cause by default you can manipulate just left column)
you can set custom background for textarea and move it up and down to specific line by background-position: 0 X

Using jqTransform on hidden contact form, select box value not showing

Sorry if this is a pain the ass, but I could really use some help here:
http://dev.rjlacount.com/treinaAronson-form/
The contact form can be seen by clicking the "Contact" button on the top left. I'm using the jqTransform jQuery plugin to style it. It's hidden initially with display:none; applied to the div with the ID "panel", and slid in with the following:
$("#flip").click(function(e){
e.preventDefault();
$("#panel").slideToggle("3000");
});
With this setup, the contact form isn't displaying the current value of the select box inside its field. If I instead remove the display:none; rule for the panel div from my CSS, and hide the form after the page has loaded with:
$("#panel").hide();
The form display correctly. Does anybody know how I can make this work and avoid the flash of an open panel I get if I hide it with jQuery after the page loads?
Thanks so much for any advice. Please let me know if I can provide any more information.
The problem is, jqtransform is setting width for a label (currently visible value in a transformed select) to match the width of original select.
If the original select (or its parent) has display:none set, and it doesn't have any css width specified, the result of .width() on that element is zero.
You can in fact check (using firebug or google chrome dev tools), that it's not that contact form isn't displaying the current value of the select element, but rather displaying it with a width equal to zero.
The easiest solution in your case, is to set (in your css file) fixed width for the selects that are part of a contact form. That way, even though they will be hidden at first, the jqtransform will set correct width for label. For example:
/* css declaration */
#change-form select {
width: 390px;
}
Side note: there are of course other ways to make it work, including tweaking the jqtransform script to fit your specific use case. Part of the script related to setting mentioned width of a label starts on line 289.

TinyMCE limit text on scrollerActived

I have a textarea in my rails application to collect content from user in a database. The rails application is further feeding that text to an XML-driven flex application.
The flex application has number of fixed sized containers which wraps the text inside (from the XML created by Rails app on-the-fly), but truncates the text if it exceeds the container's height. Problem is; there is no way to present the large text in XML, so it gets adjusted automatically in the compiled flex application. And the fact is; the web-based rails app and front-tier flex app are entirely disconnected in terms of having awareness of their internal events. (like in this case; rails app has no knowledge of the overflow event for flex internal containers and relying on font-size and character/line count doesn't work in this scenario!)
Therefore, I wrote a JS function to watch and rescue the textarea's overflow situation and while setting its attributes (viz; line-height, font-size, font-family, width, height... yada yada) matching that of the flex control. The complex form in rails did the trick to have dynamic number of such textarea's control being observed by the JS function.
Here is the Prototype code to handle the overflow event with the corresponding rescue code for cleanup:
var timeout;
document.observe('dom:loaded', attach_obr);
function attach_obr() {
$$('.active_text').each (function(text_element){
text_element.observe('keyup', function(e){
check_limits(text_element.id);
});
text_element.observe('change', function(e){
check_limits(text_element.id);
});
});
}
function check_limits(eyeD) {
if($(eyeD).scrollHeight > $(eyeD).offsetHeight){
// overflow occured, now the rescue code here
timeout = window.setTimeout(function() {
$("error_notice").hide();
}, 4000);
$("error_notice").show().update('There is no space left in this box, please use a new box to continue adding content');
// truncate text till the scrollbar disappears
while($(eyeD).scrollHeight > $(eyeD).offsetHeight){
$(eyeD).value = $(eyeD).value.slice(0, -1);
}
}
else {
if($("error_notice").innerHTML!=""){
$("error_notice").hide().update("");
clearTime(timeout);
}
}
}
[Note: It works with a minor flaw of truncating few more characters than expected in the last line. User can retype these letters till the end of that line. I guess this is because somehow the change in width of textarea due to the appearance of scroll-bar is effecting either the scrollHeight or offsetHeight during the process & there should be something more to the loop's condition ($(eyeD).scrollHeight > $(eyeD).offsetHeight)]
The while loop makes things bit slower, but at least it is serving the purpose. WYSIWYG is achieved. (I would love to hear any suggestion from the viewers to improve that inelegant code :O )
WYSIWYG is not achieved, in terms of rich/formatted text..
Incorporating Rich Text:
Rather than expecting from user to place tags inside the area , in the next phase, I am planning to deploy tinyMCE in my app. Now, to make the above function work with tinyMCE, I have the following code:
tinyMCE.init({
theme_advanced_buttons1 : "bold, italic, underline, strikethrough, separator, justifyleft, justifycenter, justifyright, justifyfull, separator, forecolor, backcolor",
theme:"advanced",
mode:"textareas",
plugins : "safari",
width: '360px',
height: '198px',
setup : function(ed) {
ed.onChange.add(function(ed, i) {
check_limits(ed.id);
});
}
});
The binding and firing of events is working alright. Unfortunately, the aim to control the text overflow is not working. Reason being;
a) ed.id is the id of my textarea not the interactive panel created by tinyMCE. So, the attributes like scrollHeight are offsetHeight are not getting changed for the hidden textarea control.
b) The value of textarea in this case also contains HTML code rather than the actual text. So, it is very implicit to tell what is the actual text without markup (which in our case is required when truncating the overflowed text).
My questions:
Is there a way to get the scrollHeight and offsetHeight of the control created by tinyMCE?
Is there a way to get the only-text version (without markup) of inner content of tinyMCE control?
(So, when I truncate the text in check_limits function, it doesn't effect/breaks the markup/DOM created by tinyMCE for the formatted text. In other words, I would be simulating the user action of pressing backspace on tinyMCE control in the while loop.)
Elegant way to do this whole exercise with & without tinyMCE?
Any suggestions are greatly appreciated!
First you need to know that tinymce creates a contenteditable iframe to let users edit html contents; contents from that iframe get written back to the textarea onSave. The textarea gets hidden in the rtinymce intiatilization process. The editor id is equal to the textarea id.
Here some suggestions:
1. Relevant code
var frameid = editor.id+'_ifr';
var currentiframe = document.getElementById(frameid);
var offsetHeight = currentiframe .contentDocument.body.offsetHeight;
var scrollHeight = currentfr.Document.body.scrollHeight
2. code for this (using jQuery)
var plain_text = $(editor.getBody()).text();
3. The only more efficient way to handle the while loop in the "without tinymce" case will be to slice off some more characters and follow a logarithmic approach. You slice off a bigger part of the string and then get to the final value in half-part paces. Example: You slice of 20 characters, but it fits. Then you slice off 10 characters of the original string. If it does not fit you try 15 characters and so on... this is more effectife then the while approach, but more complicated to develop.
EDIT:
It seems almost impossible to get the line number from the caret position. Problem here is that you do not know where the a text line breaks. Though it is easy to find out in which paragraph the cursor is located at (tinymce uses paragraphs to wrap text nodes).
There is a way to limit insertion in tinymce based on characters (i.e. limit can be set to 100 characters), but i guess this won't work for your use case unless you use a monospace font.
Another approach could be to set the tinymce css to set the editor window to the exact same width as your flex boxes (set the widht to the iframes body element should be sufficient). In this case it sould be easier to use the scrollHeigth approach - you would only need to find out if the heigth did change after insertion of text and then you could divied the heigth with the lineheigth to egt the line number. I suggest you write an own plugin to implement this. This is not that difficult. Here is a link to a tutorial for this.

Categories