How can I stop CKEditor replacing paragraphs with double <br> when pasting from Word - parsing

When I use the Paste from Word or Paste as plain text options in CKEditor double line returns get converted into double instances of <br>.
Whilst this is technically exactly what exists in the source file it would be fantastic if there were a way to have all double line returns be converted into paragraph tags when pasting from an external document. TinyMCE doesn’t seem to struggle with this.
Is this possible with CKEditor?
I'm using Pixel & Tonic's Wygwam version of CKEditor and the inference of this support thread is that it can't be done as exists :(

Since I spent hours searching for the same thing and found lots of posts asking but none answering I decided to work it out on my own.
Here is the solution, hope it saves you the time I wasted:
In config.js add:
CKEDITOR.on('instanceReady', function (ev) {
ev.editor.on('paste', function (ev) {
ev.data.html = ev.data.html.replace(/<br>\s*<br>/g, '</p><p>');
});
});

What really really fixed this issue for me was:
Put this line in config.js:
"config.enterMode = CKEDITOR.ENTER_BR;"
This will create a "br" instead of a "p" when you hit ENTER in the ckeditor.
Then put this script where you replace the
CKEDITOR.replace( 'descripcion', { enterMode : CKEDITOR.ENTER_BR, shiftEnterMode : CKEDITOR.ENTER_BR } );
CKEDITOR.on( 'instanceReady', function( ev )
{
ev.editor.dataProcessor.writer.setRules( 'br',
{
indent : false,
breakBeforeOpen : false,
breakAfterOpen : false,
breakBeforeClose : false,
breakAfterClose : false
});
});
</script>
That script prevented the double "br"
Hope it helps.

Here is my work-around for this in CKEditor 4 (where ck is an editor instance):
ck.on('afterPaste', function() {
var data = ck.getData();
data = data.replace(/<br \/>\s*<br \/>/g, '</p><p>');
ck.setData(data);
});

Related

best_in_place retains original values after update

I'm using best_in_place to do in-page editing of a table of data
in a ruby-on-rails app. The in-place editing works, but I have a
corner case that fails. A pair of items in the row (device_name,
generic_name) must be unique. If they are not unique, the server-side
code passes back a set of names with a changed generic_name to make
the pair unique. I use the following coffeescript to update the
display.
jQuery ->
$('.best_in_place[data-bip-object="full_dpoint"]').bind(
"ajax:success", (event, d) ->▫
return if ! d?
data = JSON.parse(d)
if ! data.dpoint?
return
else
item_to_edit = "#best_in_place_full_dpoint_" + data.dpoint.dpoint_id + "_generic_name"
$(item_to_edit).text(data.dpoint.generic_name)
)
This code works (IE it properly updates the page with the server-supplied
new generic name) , but if I then click back in the 'generic_name'
field, (to go into edit mode), the default edit text changes back
to what it was at the very beginning (page download time). I have
experimented with setting many different page elements to the new
generic name, including all of the following:
$(item_to_edit).attr('data-bip-original-content', data.dpoint.generic_name)
$(item_to_edit).attr('data-bip-value', data.dpoint.generic_name)
$(item_to_edit).attr('original-value', data.dpoint.generic_name)
$(item_to_edit).attr('bipValue', data.dpoint.generic_name)
$(item_to_edit).attr('bipvalue', data.dpoint.generic_name)
All to no avail. I have poked around in the dom trying to find where the original
value might be stored, but haven't found anything other than these.
Any ideas?
TIA.
Leonard
Try it
javascript:
$(document).ready(function () {
/* Activating Best In Place */
jQuery(".best_in_place").best_in_place();
var old_value;
$(document).on('change', '.not_abort', function (e) {
console.log(e.target.value);
old_value = e.target.value;
});
$(document).on('ajax:error', '.not_abort', function (e) {
console.log(e);
e.target.innerHTML = old_value;
$(e.target).data('bipOriginalContent', old_value);
});
})
view:
best_in_place #device_name, :email, class: 'not_abort'

How to prevent the <p> tag from wrapping around my input with tinymce in Rails?

By default, the tinymce input gets passed to the DOM as a paragraph tag:
I would like to remove that element wrapper so that tinymce passes exactly what I entered in the text editor.
How do I do that ? Please if you provide a code, can you also let me know where that code gets added ?
Regards !!!
Actually I solved my problem. All I had to do was change the styling for paragraph tag :
p {margin: 0; padding: 0;}
You need to specify the forced_root_block to false. However the documentation states that not having your root block as a <p> tag can cripple the editors behaviour. Newlines will be spaced with <br> tags instead.
tinyMCE.init({
selector: 'textarea',
forced_root_block: false
});
See the documentation here
I strip out those pesky things with gsub and regex like this:
<%= #event.desc_long.gsub(/^\<p\>/,"").gsub(/\<\/p\>$/,"") %>
First .gsub removes the <p> at the start of the TinyMCE string, and the second one removes the </p> at the end. Working great for me. This would work for any language that uses regex (gsub is for rails). JavaScript example:
var str = "{TinyMCE HTML string}";
str = str.replace(/^\<p\>/,"").replace(/\<\/p\>$/,"");
Hope this helps!
EDIT:
Re: where to put it. You leave what TinyMCE puts in your database alone. Add the above only when you display it (in the view, e-mail whatever).
In case you just want to get rid of margins:
tinymce.init({
...
setup: function(ed) {
ed.on('init', function() {
var doc = this.getDoc().getElementById("tinymce");
doc.style.margin = 0;
});
},
});

Jquery UI Autocomplete not working after dom manipluation

I have been trying to implement the autocomplete and have come across a problem that has stumped me. The first time I call .autocomplete it all works fine and I have no problems. If, however, I call it after I have removed some (unrelated) elements from the DOM and added a new section to the DOM then autocomplete does nothing and reports no errors.
Code:-
$.ajax({
type : 'get',
dataType : 'json',
url : '/finance/occupations',
cache:true,
success:function(data){
occupationList = data;
$('.js-occupation').autocomplete({
source: occupationList,
messages: {
noResults: '',
results: function(){}
},
minLength : 2,
select:function(event, ui){
$('.js-occupationId').val(ui.item.id);
}
});
}
});
The background to this page is that it contains multiple sections that are manipulated as the user moves through them. Hide and show works fine and does not impact on the autocomplete. However, if I do the following:-
var section = $('.js-addressForm:last').clone();
clearForm(section);
$('div.addressDetails').append(section);
$('.js-addressForm:first').remove();
Which gives the user the bility to add multiple addresses on the previous section then the autocomplete stops working.
Any suggestions or pointers on something obvious I am missing?
I have tried to put the initialisation of the autocomplete on an event when the element gets focus and it still does not work.
You have to create the autocomplete after all other underlying objects. If you F12, you will see that the list is "visible", however it is below and hidden by all instances created after it.
If you created a div with inputs (one input being the autocomplete), then you create the automplete then the dialog instances, the autocomplete will never show. If you create the dialog then the autocomplete, no problem. The problem is the z-order
I have faced the same issue. For now to fix this, i'm creating widget on the input once input is in focus. It will help you solve the issue.
You can look for the help on
making sure some event bing only when needed
Sample code will look like this
$( "#target" ).focus(function() {
//I don't care if you manipulated the DOM or not. I'll be cautious. ;)
(function() {
$( "#combobox" ).combobox();
$( "#toggle" ).click(function() {
$( "#combobox" ).toggle();
});
})();
// use a flag variable if you want
});
This solved my problem. Hope its the solution you were looking f

autocomplete of words in the middle (jQuery UI)

Anyone know good sample code using jQuery UI's autocomplete widget that can autocomplete words in the middle of a text box, not just autocomplete of the word at the end only?
I'm using the jquery UI autocomplete widget for a component that supports entry of multiple tags. It's like like stack overflow's tag editor, but simpler: no fancy formatting in the autocomplete dropdown, no "tag" background images in the edit box. I started with the jQuery UI Autocomplete Multiple sample and modified it.
It's working OK, except autocomplete doesn't work for tags in the middle of a multi-tag string. For example, if I type C Fortran and then put the caret right after C and type +, I'd expect to see C++ in the autocomplete list but instead I see Fortran again.
Here's the code so far: http://jsfiddle.net/WCfyB/4/
This is the same problem described by autocomplete in middle of text (like Google Plus), but the problem in that question was simpler because he could rely on an empty # in the text to signal when to show the autocomplete. In my case, I can't just rely on the text-- I actually need to find out where the caret is and autocomplete for the word where the caret is.
I could build this myself using caret or another plugin, but was wondering if there was already a jQuery-UI-based sample online that I could use without re-inventing another wheel, especially if there are browser-specific corner cases to worry about. Ideally, it'd behave like this: whenever the user places the caret inside or at the end of a tag (where tags are always separated by 1+ spaces), autocomplete is shown for that tag. Know a good sample?
I don't know of any examples like this, but here's something that you could start with:
var availableTags = [ ... ];
function split(val) {
return val.split(/ \s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
.bind("keydown", function(event) {
// don't navigate away from the field on tab when selecting an item
if (event.keyCode === $.ui.keyCode.TAB
&& $(this).data("autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function(request, response) {
var results = [],
selectionStart = this.element[0].selectionStart
term = extractLast(request.term.substring(0, selectionStart));
if (term.length > 0) {
results = $.ui.autocomplete.filter(availableTags, term);
}
response(results);
},
focus: function() {
return false; // prevent value inserted on focus
},
select: function(event, ui) {
var terms = split(this.value.substring(0, this.selectionStart));
terms.pop(); // remove the current input
terms.push(ui.item.value); // add the selected item
this.value =
$.trim(terms.join(" ") + this.value.substring(this.selectionStart)) + " ";
return false;
}
});
Example: http://jsfiddle.net/WCfyB/7/
The major caveat here is that the selectionStart method does not work in IE. You can replace those function calls with one of those plugins you mentioned in your question.

JQuery UI Multiselect how to get selected options values

wasted my day while searching how to get selected options values in JQuery UI widget by Michael Aufreiter. Here's the link to his demo site and github: http://quasipartikel.at/multiselect/
As a result I just need value fields of selected options without POST/GET sendings to PHP script.
I tried many methods and resultless.
Need your help and ideas
*Found many topics about jquery ui multiselect but useless because of Aufreiter :s *
That should work. Tested with Chrome console
$("#countries").val();
I went to the site you've got listed above, and was able to run this in my chrome console:
$('.ui-multiselect .selected li').each(function(idx,el){ console.log(el.title); });
It seems like the values you want are stored in the title attributes of the list items within the div.selected element.
Edit:
Doh! Well of course you want the values. Sorry mate. Completely missed that. The real goods are stored in the jQuery data() objects. In this case, the key you want is 'optionLink'. It maintains a reference to an option element. Each list item in the '.selected' div used the jQuery.data() method to add the underlying option to it.
So, you need to get the selected list items, iterate through, grab the 'optionLink' from the data jQuery data store, and then get the value.
The following code works on the example page:
$('.ui-multiselect .selected li').each(function(idx,el){
console.log(el);
var link = $(el).data('optionLink');
// link now points to a jQuery wrapped <option> tag
// I do a test on link first. not sure why, but one of them was undefined.
// however, I got all four values. So I'm not sure what the first <li>
// is. I'm thinking it's the header...
if(link){
// here's your value. add it to an array, or whatever you need to do.
console.log(link.val());
}
});
This is the first I've seen of the multiselect. It's slick. But I sympathize with your frustration trying to get something out. A 'getSelectedOptions()' method would be nice.
Cheers
Try accessing the selected values on the close event.
e.g.
$("#dropdown").multiselect({
header: false,
selectedList : 1,
height: "auto",
}).multiselectfilter().bind("multiselectclose", function(event, ui) {
var value = $("#dropdown").val();
});
Hope that helps.
Best solution
$('#select').multiselect({
selectAllValue: 'multiselect-all',
enableCaseInsensitiveFiltering: true,
enableFiltering: true,
height: "auto",
close: function() {
debugger;
var values = new Array();
$(this).multiselect("getChecked").each(function(index, item) {
values.push($(item).val());
});
$("input[id*=SelectedValues]").val(values.join(","));
}
});
You can try this:
$('#ListBoxId').multiselect({
isOpen: true,
keepOpen: true,
filter: true
});

Resources