Inline CKEditor adds <br> to empty div on startup - javascript

CKEditor in Inline mode adds a <br> in the source of the document to an empty div when it is initialized. When you check the source in CKEditor it shows completely empty. I guess this is done to stop collapsing the div or whatever element it is editing on, but for me this is causing issues since I target the empty div with CSS to display a placeholder.
I have searched about everywhere on how to disable this and have seen some issues with FireFox many years ago, but that seems to be unrelated.
<div id="editarea" placeholder="Title"></div>
CKEDITOR.inline('editarea, {});
<style>
div:empty:after {
content: attr(placeholder);
}
</style>
When you look in the Developer Tools the source of the document looks like:
<div id="editarea" placeholder="Title">
<br>
</div>
Adding the following to the config does not seem to be doing anything:
config.fillEmptyBlocks = false;

Can help someone else, the solution I found, pass by the editor event listener:
// Ckeditor 4
editor.on('key', function (evt) {
var selection = editor.getSelection();
var element = selection.getStartElement();
var html = element.getHtml();
var id = element.getId();
if (evt.data.keyCode !== 13
&& id === 'editarea')) {
if (html.match(/( )?<br>$/)) {
element.setHtml('');
}
}
})

That <br> is a "filler" and is always placed at input (editor initialization) into empty block elements by function createBogusAndFillerRules to give an height to the element so the user can click on it to edit it.
Actually there is not a CKeditor configuration to avoid this behaviour but, using jQuery, we can remove the <br> on instanceReady.ckeditor event with:
if($(this).html().trim() === '<br>'){
$(this).html('');
}

Please try this code it is working for me:
For removing br on load
$('your_id').ckeditor();
CKEDITOR.on('instanceReady', function() {
$('div.application').find('br').remove(); // remove br tag added on empty divs
});
for removing &nbsp use this in destroy function:
for(CKname in CKEDITOR.instances) // delete multiple instances of ckeditor
{
CKEDITOR.instances[CKname].destroy(function(){
$("your_id").html(function (i, html) {
return html.replace(/ /g, ''); // remove
});
})
}

Related

Hide DIV when input field is blank

I wonder if you could help me with an issue.
I am building a content template for an events page, that pulls data through using Advanced Custom Fields.
I have a field in the admin side which will be filled out when adding a new event. The field is called show_info with the ID #acf-editor-46.
On some events however this will be left blank, but the DIV that wraps around the content on the frontend will still show on the template, the DIV has the class .show-info-wrapper.
I would like it so when the show_info field is blank, the DIV .show-info-wrapper does not display on the front end.
I have made some progress from browsing around, you can see the code I have so far here:
HTML (Just a quick testing set up):
<textarea id="acf-editor-46" class="wp-editor-area" aria-hidden="true">1111</textarea>
<div class="show-info-wrapper">CONTENT</div>
JavaScript + jQuery:
$(document).ready(function() {
if($('#acf-editor-46').val() == '' ){$('.show-info-wrapper').hide();}
$('#acf-editor-46').on('change' , function() {
if( this.value != ''){
$('.show-info-wrapper').show();
}
else{
$('.show-info-wrapper').hide();
}
});
});
It works on JSFiddle (http://jsfiddle.net/ha2nedfb/), however, it seems that on my WordPress site as the input and the DIV are not on the same DOM, it does not work.
Could anyone help me with this?
Thank you!
Just change the event of #acf-editor-46 to input.
$(document).ready(function() {
if($('#acf-editor-46').val() == '' ){$('.show-info-wrapper').hide();}
$('#acf-editor-46').on('input' , function() { // Just change event to input
if( this.value != ''){
$('.show-info-wrapper').show();
}
else{
$('.show-info-wrapper').hide();
}
});
});
if (!$("#acf-editor-46").val()) {
// textarea is empty
}
try this to check textarea is empty or not
You can delegate event if textarea is rendered later.
$(document).on('change', '#acf-editor-46', callback);
Links:
https://api.jquery.com/on/
https://learn.jquery.com/events/event-delegation/
Assuming the <textarea> and <div> are really siblings in this very order (your text contradicts the example) & if you're OK with adding a placeholder to the textarea & you only need new-ish browsers, there is a pure CSS solution:
<textarea ... placeholder=" "> </textarea>
.show-info-wrapper {
display: block;
}
.wp-editor-area:placeholder-shown + .show-info-wrapper {
display: none;
}
Here's a pen.

Moving inline javascript function to external file and convert to jQuery

I am trying to optimize my "spoiler" bbcode on phpBB3.
Right now, I have a working solution, but the inline javascript is injected by phpBB every time the "spoiler" bbcode tag is used. I want to call a common function instead of adding it inline every time the bbcode is used.
Here is that working inline javascript:
<div class="spoiler">
<div class="spoiler-title">
<span onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.parentNode.getElementsByTagName('a')[0].innerText = 'hide'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.parentNode.getElementsByTagName('a')[0].innerText = 'show'; }">
<strong>{TEXT1}</strong> (show)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
For ease of reading, the inline onclick function is repeated here:
if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = '';
this.parentNode.getElementsByTagName('a')[0].innerText = 'hide';
} else {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none';
this.parentNode.getElementsByTagName('a')[0].innerText = 'show';
}
Clicking the anchor with the class of "spoiler-btn" has a preventDefaults on it, to prevent the click from taking you to the top of the page:
$(document).ready(function(){
$(".spoiler-btn").click(
function(e) {
e.preventDefault();
}
);
});
I was trying to replace the span onclick inline javascript with a function call that passes 'this' to an external javascript file. I couldn't seem to get that working, so I tried using jQuery to capture 'this' to traverse up the DOM to find the "div" contained within the "spoiler-text" div and manipulate the display:none. There can be multiple of these spoiler tags on the page, so I cannot give the div inside of the "spoiler-text" div an id.
Here I changed the onclick of the span to the external function:
onclick="spoilerToggle(this);"
I then have the following in my external file:
var spoilerToggle = function(param) {
if ($(this).parent('div').parent('div').hasClass('spoiler-text').css('style') == 'none') {
($(this).parent('div').parent('div').hasClass('spoiler-text').removeAttr('style'));
($(this).parent('div').$('a').text('hide'));
} else {
($(this).parent('div').parent('div').hasClass('spoiler-text').css('display', 'none'));
($(this).parent('div').$('a').text('show'));
}
}
The console then gives the following error:
bbcode.js:22 Uncaught TypeError: $(...).parent(...).parent(...).hasClass(...).css is not a function
Line 22 is the line with the "if" check.
jQuery is loaded on the site, and I've made sure to call my external javascript file right before the close of the body tag.
I feel like I've gone down the rabbit hole and cannot see the light. I'm sure this is much easier than I am making it out to be.
Any help is greatly appreciated. Thank you!
.hasClass() returns a boolean, so you can't chain other methods after it. That's why you get the error you quote.
I would implement it a different way though:
$(document).on("click", ".spoiler-title", function(e) {
e.preventDefault();
var container = $(this).closest(".spoiler");
container.find(".spoiler-btn").text(function(i, currentText) {
return currentText === "show" ? "hide" : "show"
});
container.find(".spoiler-text div").toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="spoiler">
<div class="spoiler-title">
<span>
<strong>{TEXT1}</strong> (show)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
The above uses a single, delegated click handler bound to the document to handle clicks on all spoiler elements on the page (you could instead bind it to a lower-level container element, at whatever the lowest level is that contains all the spoilers).
Within the handler, this will refer to the clicked element, so with DOM navigation methods such as .closest() and .find() you can go up to the containing div and then down to the elements you want to manipulate. .closest() is more flexible than trying to chain .parent().parent(), because it will automatically go up until it finds an element matching the specified selector, so if you later change your HTML structure the JS probably won't need to change.
If the .text() call looks confusing, what happens there is jQuery calls the function I passed to .text() as an argument, passing it the current value of the element's text and then whatever value is returned becomes the new text.

Global function not executing [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have script that creates a div and adds a function that would remove this div on click, but it's not working.
function del(el) {
$("#"+el).remove();
}
function create() {
var element = document.createElement("div");
var att = document.createAttribute("onclick");
att.value = "del(this.id)";
element.setAttributeNode(att);
$(element).attr('id', "someID");
document.getElementById("someContainer").appendChild(element);
}
Yes, yes, I KNOW this is not the best way to add a function, but I want to do it this way.
Just FYI - after executing create() the DIV appears fine. I checked and it does have proper ID and onclick="del(this.id)" attribute, but after clicking on it nothing happens. I double checked and added alert("I'm working") to the onclick attribute later and that worked. I'm not getting any errors. In the past .remove() was working fine but now it doesn't (Maybe that's because of the way I'm adding a function this time)
EDIT: It appears that del() is not executed when clicking on div.
You have this posted with jQuery, but you're showing mostly Vanilla. As to your initial problem,
function del(el) {
$("#"+el).remove();
}
function create() {
var element = document.createElement("div");
var att = document.createAttribute("onclick");
att.value = "del(this.id)";
element.setAttributeNode(att);
$(element).attr('id', "someID");
document.getElementById("someContainer").appendChild(element);
$(element).html('<h1>DIV CREATED!</h1>').css('background-color', String.randColorHex());
}
create();
#someContainer > div { height: 10em; width: 100%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/JDMcKinstry/String.randColorHex/0c9bb2ff/String.randColorHex.js"></script>
<div id="someContainer"></div>
Seems to work fine.
My guess would be that you have an issue with creating multiple divs by with the same ID, or possibly a scope issue.
Here's a couple steps you might take to double check the issue if using Google Chrome Dev Tools:
Open Console
Double Check function 'del' is globally available and the method you expect it to be by simply typing del. If you get an error, then your method may be displaced.
Another way you could check would be put the following in your onClick: try{console.debug(del);}catch(err){console.error('DEL DOES NOT EXIST!')}
Once you've established the method is within scope, if still not working, try the following:
Replace $("#"+el).remove(); with console.debug(el, $('#'+el))
This does a couple of things: It shows you that the Function is working, as well as gives you information of what's going on within.
If the first part of the console message (el) is the ID you expect, then check the 2nd part ($('#'+el)).
It should look something like: [div:#someID]
Open it and check it's length'. If0`, then it did not find that element.
If 1, then remove should be working fine. Put remove back in just above this console call, and ensure you now get a length of 0
Just FYI, this is how to do what you're trying to do using jQuery.
function create() {
var container = $('#someContainer'), // get container
// create div, everything in {} is an ATTR, then append it TO the container
div = $('<div />', { id: 'someID' + container.children('div').length+1 }).appendTo(container);
// just for visual, i use my own plugin to set a random background color
div.css('background-color', String.randColorHex());
}
$(function() {
$(document) // your click methods
.on('click', '#btnCreate', create)
.on('click', '#someContainer > div', function(e) { $(this).remove(); })
// trigger button once on load
$('#btnCreate').trigger('click');
})
#someContainer > div { height: 2em; width: 100%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/JDMcKinstry/String.randColorHex/0c9bb2ff/String.randColorHex.js"></script>
<button id="btnCreate">Create</button>
<hr />
<div id="someContainer"></div>

.removeClass not functioning within .replaceWith

I'm trying to make a button that will hide a specific -- and then replace it with another hidden . However, when I test the code, everything fires correctly except for the .removeClass which contains the "display: none."
Here is the code:
<script type="text/javascript">
$(document).ready(function(){
var webform = document.getElementById('block-webform-client-block-18');
var unmarriedbutton = document.getElementById('unmarried');
var buyingblock = document.getElementById('block-block-10');
$(unmarriedbutton).click(function () {
$(buyingblock).fadeOut('slow', function() {
$(this).replaceWith(function () {
$(webform).removeClass('hiddenbox')
});
});
});
});
</script>
The CSS on 'hiddenbox' is nothing more than "display: none.'
There is a with the id of unmarried, which when clicked fades out a div and replaces it with a hidden div that removes the class to reveal it. However, the last part doesn't fire -- everything else does and functions properly. When I look at in the console too, it shows no errors.
Can someone please tell me where the error is? Thanks!
Edit: I may be using the wrong function to replace the div with, so here's the site: http://drjohncurtis.com/happily-un-married. If you click the "download the book" button, the the div disappears and is replaced correctly with the div#block-webform-client-block-18. However, it remains hidden.
The function you pass to replaceWith has to return the content you want to replace it with. You have to actually return the content.
I don't know exactly what you're trying to accomplish, but you could use this if the goal is to replace it with the webform object:
$(this).replaceWith(function () {
return($(webform).removeClass('hiddenbox'));
});
NB, use jquery !
var webform = $('#block-webform-client-block-18');
var unmarriedbutton = $('#unmarried');
var buyingblock =$('#block-block-10');
unmarriedbutton.click(function () {
buyingblock.fadeOut('slow', function() {
$(this).replaceWith( webform.removeClass('hiddenbox'));
});
});
Was too fast, i believe it's the way you select your object (getelementbyid) then you create a jquery object from it... -> use jquery API

Jquery UI Dialog Remove Issue

Back from this issue
Multiple Dialog
I was able to solve the issue but now problem is that it removes the div so when I access that Div it give error. It gives error because when I open dialog it works fine after removing on close it gives e.rror
I don't want to removed jQuery('#divPopup') If there is only one div present. If multiple jQuery('#divPopup') are there remove() should be working fine.
jQuery('.register_button_class').live('click',function () {
var iFrameobj = createIframe('',iframeUrl);
jQuery('#divPopup').html(iFrameobj);
createDialogWithClose(url,'#bodyId');
return false;
});
Dummy Div for Dialog Popup, This get removed, when Click on Close Jquery Ui Popup.
So when I say
jQuery('#divPopup').html(iFrameobj);
It gives error.
<div id="divPopup"></div>
I'm assuming that your function:
createDialogWithClose(url, '#bodyId');
removes the div id="divPopup" each from the DOM when you close it.
I would suggest not initially including that div in your markup and change your function to create the div and append it to the DOM when it runs. Then remove like you're already doing.
jQuery('.register_button_class').live('click',function () {
var iFrameobj = createIframe('',iframeUrl);
jQuery("body").append("<div id='divPopup' />").html(iFrameobj);
createDialogWithClose(url,'#bodyId');
return false;
});
It's hard to tell what other issues you may be running into with this bit of code that you posted, however, jQuery("body").append("<div id='divPopup' />").html(iFrameobj); will create the divPopup each time the function runs. So, when you close it and it gets removed it will just get created again the next time that button is clicked.
EDIT: How to check if a Div exists -
if ($("#divPopup").length > 0){
// do something here
}
I solved like this
var length = jQuery('#divPopup').length;
if(length>1)
{
jQuery('#divPopup').dialog('destroy').remove();
}else
{
jQuery('#divPopup').dialog('destroy');
}

Categories