CKEditor Inline Editing on jQuery UI - php

I'm stuck on making CKEditor inline editing work on jQuery UI, especially on Tabs. Does anyone know how to make it work? Are there any plugins that will make CKEditor work on jQuery UI?

I had a similar issue and it turned out to be due to how the browsers were handling the "hidden" or "disabled" components which had yet to be rendered.
http://ckeditor.com/ticket/9814 gave a example of adding a listener to change the readOnly status when the instance becomes ready.
var ck = CKEDITOR.inline(element);
ck.on( 'instanceReady', function( ev ) {
var editor = ev.editor;
editor.setReadOnly( false );
});

I've been struggling with the same problem since this morning, but I found a fix.
var objCKeditor = new Object({
config: base_url + "library/applications/ckeditor/config.simple.js"
});
var objTab = new Object({
active: false
});
CKEDITOR.disableAutoInline = true;
// Activate your editors when the tabs themselves are activated.
$( ".navigation-tabs" ).on( "tabsactivate", function( event, ui ) {
// Find which tab has been chosen by the user.
objTab.chosen = $(this).tabs('option', 'active');
// Only initialize the editors once...
if ( (objTab.chosen == 3) && (objTab.active == false) ) {
// Loop through the editors.
$( 'div.link-bookmark-comment').each( function() {
// Find the ID for the editor.
objCKeditor.editor = $(this).attr('id');
// ... which is facilitated by this boolean.
objTab.active = true;
CKEDITOR.inline( objCKeditor.editor, { customConfig: objCKeditor.config } );
});
}
} );
So, it would appear that CKEditor does not like to be placed within tabs, or any object which is initially hidden.

Related

CKEDITOR how do i focus blur elements

Hello i'm new to CKEDTIOR , and I have some problems . I would like to focus when you click on the ckeditor element , and unfocus when you click outside of it . Can you please help ?
var challengeEd = undefined;
$('#thechallenge').focus(function() {
challengeEd = CKEDITOR.replace('thechallenge');
});
var solutionEd = undefined;
$('#thesolution').click(function() {
solutionEd = CKEDITOR.replace('thesolution');
});
var companyEd = undefined;
$('#thecompany').click(function() {
editor = CKEDITOR.replace('thecompany');
});
var customeruseEd = undefined;
$('#thecustomeruse').click(function() {
editor = CKEDITOR.replace('thecustomeruse');
});
$('body').click(function() {
if (challengeEd != undefined)
challengeEd.destroy();
if (solutionEd != undefined)
solutionEd.destroy();
if (companyEd != undefined)
companyEd.destroy();
if (customeruseEd != undefined)
customeruseEd.destroy();
})
Good start, but I see there is the problem with blur part. It is good to utilize component API and in case of CKEditor there is blur event:
Fired when the editor instance loses the input focus.
So I would go with the code like:
[ 'thesolution', 'thechallenge' ].forEach( function( selector ) {
// Attach focus listener.
document.querySelector( '#' + selector ).addEventListener( 'focus', function() {
// Create editor.
var editor = CKEDITOR.replace( selector );
// When instance is ready - focus it.
editor.on( 'instanceReady', function() {
editor.focus();
} );
// When editor losses focus - destroy it.
editor.on( 'blur', function() {
editor.destroy();
} );
} );
} );
for HTML like:
<textarea name="thechallenge" id="thechallenge" rows="10" cols="80">
<p>Foo Bar Baz</p>
</textarea>
<textarea name="thesolution" id="thesolution" rows="10" cols="80">
<p>Foo Bar Baz</p>
</textarea>
Live demo on codepen
So for each textfield there are 4 simple steps:
Attach focus listener (native or you can use jQuery).
Initialize editor instance on focus.
When editor is ready - focus it (it won't be focused be default after initialization).
On blur destroy editor instance.
Here is another solution :
for (instance in CKEDITOR.instances) {
var editor = CKEDITOR.instances[instance];
if (editor) {
// Call showToolBarDiv() when editor get the focus
editor.on('focus', function (event) {
showToolBarDiv(event);
});
// Call hideToolBarDiv() when editor loses the focus
editor.on('blur', function (event) {
hideToolBarDiv(event);
});
//Whenever CKEditor get focus. We will show the toolbar span.
function showToolBarDiv(event) {
//'event.editor.id' returns the id of the spans used in ckeditr.
$('#' + event.editor.id + '_top').show();
}
function hideToolBarDiv(event) {
//'event.editor.id' returns the id of the spans used in ckeditr.
$('#' + event.editor.id + '_top').hide()
}
}
}
});

PrestaShop, use tinymce directly from Smarty template

I'm doing a PrestaShop module. This module will be anchored to the hook called "hookDisplayAdminProductsExtra".
I need to use the TEXTAREA field tinymce using the library, you can do so by creating the textarea directly from Smarty and not as a controller? Maybe using jQuery function or adding a class to the field?
My code in tpl file is:
{foreach $row_list as $row}
<textarea id="description_1" name="description_1" class="autoload_rte" aria-hidden="true">
{$row['desc']}
</textarea>
{/foreach}
My module function is:
$this->context->smarty->assign(
array(
'row_list' => $this->getField($id)
)
);
return $this->display(__FILE__, 'admin-view.tpl');
The autoload_rte is "used" when tab Informations is loaded by Prestashop using:
$(document).ready(function(){
// Execute when tab Informations has finished loading
tabs_manager.onLoad('Informations', function(){
tinySetup({
editor_selector :"autoload_rte",
setup : function(ed) {
ed.on('init', function(ed)
{
if (typeof ProductMultishop.load_tinymce[ed.target.id] != 'undefined')
{
if (typeof ProductMultishop.load_tinymce[ed.target.id])
tinyMCE.get(ed.target.id).hide();
else
tinyMCE.get(ed.target.id).show();
}
});
ed.on('keydown', function(ed, e) {
tinyMCE.triggerSave();
textarea = $('#'+tinymce.activeEditor.id);
var max = textarea.parent('div').find('span.counter').data('max');
if (max != 'none')
{
count = tinyMCE.activeEditor.getBody().textContent.length;
rest = max - count;
if (rest < 0)
textarea.parent('div').find('span.counter').html('<span style="color:red;">Maximum '+ max +' characters : '+rest+'</span>');
else
textarea.parent('div').find('span.counter').html(' ');
}
});
}
});
});
});
In addition to this, the other tabs are also loaded later than the Informations tab. To solve this, you need to initialized the tinymce for the field you want. Choose another selector (not sure it's needed but at least there is 100% no chance to mess with the current ones), for example the class mytextarea, then use:
<script>$(document).ready(function(){tinymce.init({mode : "textareas", editor_selector : "mytextarea", plugins: "textcolor paste code"});})</script>
This can be in your tpl.
In my tests, if there is no plugins setup there would be an error in console log. But you can adjust the tinymce settings as you wish.

issue including wp_enqueue_media - WordPress

I am building a custom interface that is utilizing WordPress functions and a specific area I am trying to utilize is the media section of WordPress. I am first including the core files of WordPress:
$location = $_SERVER['DOCUMENT_ROOT'] . "/wordpress";
include($location.'/wp-config.php');
include($location.'/wp-load.php');
include($location.'/wp-includes/pluggable.php');
global $wpdb;
if( !isset($wpdb) )
{
include($location.'/wp-config.php');
include($location.'/wp-includes/wp-db.php');
}
Than within my media file I am using: wp_enqueue_media() to allow me to access the media viewer for when a user is uploading media from their account.
My JS script I am using to run the media request is as follows:
$('.add-media').on('click', function( event ){
var file_frame;
var wp_media_post_id = wp.media.model.settings.post.id; // Store the old id
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frames.file_frame = wp.media({
title: jQuery( this ).data( 'uploader_title' ),
button: {
text: jQuery( this ).data( 'uploader_button_text' ),
},
multiple: true // Set to true to allow multiple files to be selected
});
// When an image is selected, run a callback.
file_frame.on( 'select', function() {
var selection = file_frame.state().get('selection');
selection.map( function( attachment ) {
attachment = attachment.toJSON();
// Do something with attachment.id and/or attachment.url here
$(".load-attachments").append('<div class="singleImg"><img src="'+attachment.url+'" width="100px" height="100px"/><input type="hidden" class="fileURL load-single-attachment" value="'+attachment.id+'"/><span class="removeImg remove"> X </span></div>');
$(".removeImg").bind('click', function(){
$(this).parent().remove();
});
});
});
// Finally, open the modal
file_frame.open();
});
The issue here is, when running the add-media event, wp is undefined. Now I am not sure as to why this is. Any thoughts or suggestions?
After looking through documentation, I couldn't really figure out why this was happening. But I found the solution. Some final files are called when using wp_footer(). And without this, none of your JavaScript files will run.
So In the future if your developing an application and want to use WordPress core functionalities, make sure to include wp_footer() at the end of your application to make sure you won't run into wp not being defined in js.

how to remember scroll position of page

I am submitting some data to my database then reloading the same page as the user was just on, I was wondering if there is a way to remember the scroll position the user was just on?
I realized that I had missed the important part of submitting, so, I decided to tweak the code to store the cookie on click event instead of the original way of storing it while scrolling.
Here's a jquery way of doing it:
jsfiddle ( Just add /show at the end of the url if you want to view it outside the frames )
Very importantly, you'll need the jquery cookie plugin.
jQuery:
// When document is ready...
$(document).ready(function() {
// If cookie is set, scroll to the position saved in the cookie.
if ( $.cookie("scroll") !== null ) {
$(document).scrollTop( $.cookie("scroll") );
}
// When a button is clicked...
$('#submit').on("click", function() {
// Set a cookie that holds the scroll position.
$.cookie("scroll", $(document).scrollTop() );
});
});
Here's still the code from the original answer:
jsfiddle
jQuery:
// When document is ready...
$(document).ready(function() {
// If cookie is set, scroll to the position saved in the cookie.
if ( $.cookie("scroll") !== null ) {
$(document).scrollTop( $.cookie("scroll") );
}
// When scrolling happens....
$(window).on("scroll", function() {
// Set a cookie that holds the scroll position.
$.cookie("scroll", $(document).scrollTop() );
});
});
#Cody's answer reminded me of something important.
I only made it to check and scroll to the position vertically.
(1) Solution 1:
First, get the scroll position by JavaScript when clicking the submit button.
Second, include this scroll position value in the data submitted to PHP page.
Third, PHP code should write back this value into generated HTML as a JS variable:
<script>
var Scroll_Pos = <?php echo $Scroll_Pos; ?>;
</script>
Fourth, use JS to scroll to position specified by the JS variable 'Scroll_Pos'
(2) Solution 2:
Save the position in cookie, then use JS to scroll to the saved position when page reloaded.
Store the position in an hidden field.
<form id="myform">
<!--Bunch of inputs-->
</form>
than with jQuery store the scrollTop and scrollLeft
$("form#myform").submit(function(){
$(this).append("<input type='hidden' name='scrollTop' value='"+$(document).scrollTop()+"'>");
$(this).append("<input type='hidden' name='scrollLeft' value='"+$(document).scrollLeft()+"'>");
});
Than on next reload do a redirect or print them with PHP
$(document).ready(function(){
<?php
if(isset($_REQUEST["scrollTop"]) && isset($_REQUEST["scrollLeft"]))
echo "window.scrollTo(".$_REQUEST["scrollLeft"].",".$_REQUEST["scrollTop"].")";
?>
});
Well, if you use _targets in your code you can save that.
Or, you can do an ajax request to get the window.height.
document.body.offsetHeight;
Then drop them back, give the variable to javascript and move the page for them.
To Remember Scroll all pages Use this code
$(document).ready(function (e) {
let UrlsObj = localStorage.getItem('rememberScroll');
let ParseUrlsObj = JSON.parse(UrlsObj);
let windowUrl = window.location.href;
if (ParseUrlsObj == null) {
return false;
}
ParseUrlsObj.forEach(function (el) {
if (el.url === windowUrl) {
let getPos = el.scroll;
$(window).scrollTop(getPos);
}
});
});
function RememberScrollPage(scrollPos) {
let UrlsObj = localStorage.getItem('rememberScroll');
let urlsArr = JSON.parse(UrlsObj);
if (urlsArr == null) {
urlsArr = [];
}
if (urlsArr.length == 0) {
urlsArr = [];
}
let urlWindow = window.location.href;
let urlScroll = scrollPos;
let urlObj = {url: urlWindow, scroll: scrollPos};
let matchedUrl = false;
let matchedIndex = 0;
if (urlsArr.length != 0) {
urlsArr.forEach(function (el, index) {
if (el.url === urlWindow) {
matchedUrl = true;
matchedIndex = index;
}
});
if (matchedUrl === true) {
urlsArr[matchedIndex].scroll = urlScroll;
} else {
urlsArr.push(urlObj);
}
} else {
urlsArr.push(urlObj);
}
localStorage.setItem('rememberScroll', JSON.stringify(urlsArr));
}
$(window).scroll(function (event) {
let topScroll = $(window).scrollTop();
console.log('Scrolling', topScroll);
RememberScrollPage(topScroll);
});
I had major problems with cookie javascript libraries, most cookie libraries could not load fast enough before i needed to scroll in the onload event. so I went for the modern html5 browser way of handling this. it stores the last scroll position in the client web browser itself, and then on reload of the page reads the setting from the browser back to the last scroll position.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
if (localStorage.getItem("my_app_name_here-quote-scroll") != null) {
$(window).scrollTop(localStorage.getItem("my_app_name_here-quote-scroll"));
}
$(window).on("scroll", function() {
localStorage.setItem("my_app_name_here-quote-scroll", $(window).scrollTop());
});
});
</script>
I tackle this via using window.pageYOffset . I saved value using event listener or you can directly call window.pageYOffset. In my case I required listener so it is something like this:
window.addEventListener('scroll', function() {
document.getElementById('showScroll').innerHTML = window.pageYOffset + 'px';
})
And I save latest scroll position in localstorage. So when next time user comes I just check if any scroll value available via localstorage if yes then scroll via window.scrollTo(0,myScrollPos)
sessionStorage.setItem("VScroll", $(document).scrollTop());
var scroll_y = sessionStorage.getItem("VScroll");
setTimeout(function() {
$(document).scrollTop(scroll_y);
}, 300);

Script wont call function in Google Chrome

I have a script that pops up a div element when a anchor tag is clicked
echo '<h2>' . $row['placename'] . '</h2>';
It's echoed from a PHP script, and is working fine in FF and IE(9).
But chrome won't run it, atleast on ver. 18.0.1025.168 m
The popup(divid); event fires when I click it, but it doesent complete the function calling inside the script the function is in.
var width_ratio = 0.4; // If width of the element is 80%, this should be 0.2 so that the element can be centered
function toggle(div_id) {
var el = document.getElementById(div_id);
if ( el.style.display == 'none' ) { el.style.display = 'block';}
else {el.style.display = 'none';}
}
function blanket_size(popUpDivVar) {
alert(popUpDivVar);
if (typeof window.innerWidth != 'undefined') {
viewportheight = window.innerHeight;
} else {
viewportheight = document.documentElement.clientHeight;
}
if ((viewportheight > document.body.parentNode.scrollHeight) && (viewportheight > document.body.parentNode.clientHeight)) {
blanket_height = viewportheight;
} else {
if (document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight) {
blanket_height = document.body.parentNode.clientHeight;
} else {
blanket_height = document.body.parentNode.scrollHeight;
}
}
var blanket = document.getElementById('blanket');
blanket.style.height = blanket_height + 'px';
var popUpDiv = document.getElementById(popUpDivVar);
popUpDiv_height=0;
popUpDiv.style.top = popUpDiv_height + 'px';
}
function window_pos(popUpDivVar) {
if (typeof window.innerWidth != 'undefined') {
viewportwidth = window.innerHeight;
} else {
viewportwidth = document.documentElement.clientHeight;
}
if ((viewportwidth > document.body.parentNode.scrollWidth) && (viewportwidth > document.body.parentNode.clientWidth)) {
window_width = viewportwidth;
} else {
if (document.body.parentNode.clientWidth > document.body.parentNode.scrollWidth) {
window_width = document.body.parentNode.clientWidth;
} else {
window_width = document.body.parentNode.scrollWidth;
}
}
var popUpDiv = document.getElementById(popUpDivVar);
window_width=window_width/2;
window_width = window_width * width_ratio;
popUpDiv.style.left = window_width + 'px';
}
function popup(windowname) {
alert(windowname); // THIS WORKS
blanket_size(windowname);
window_pos(windowname);
toggle('blanket');
toggle(windowname);
}
The last function in that script is the one that is called first. I put an alert box in it to verify that it was fired. BUT, I put an alert box in the next function that it calls (blanket_size), and it did not fire, as I had the alert box on the first line in the function. It did not fire.
I simply have no clue why. The weird thing is that this stuff works in other browsers, but not chrome. Any ideas?
Thanks!
Edit: And I also verified that the parameter value passed into the popup() function (the 'windowname' param) is valid/has a value. It contains the ID of a DIV that is in the HTML document, and it's not dynamically created.
Edit 2: Ok, I got the script running when and ONLY when I add an alert box with the parameter value in it (windowname) to the popup(windowname) function. But if I remove that box, it stops working again.
Edit 3:
Got no errors on the debugger at all. But now I'm even more confused. After a great deal of tries, it seems like it's working with the alert box at random! Sometimes works, and sometimes not.
Final Edit
Changed logic to jQuery. Should have done this long ago!
// Open property
$(".property-open-link", ".yme-propertyitem").live('click', function() {
$("#yme-property-pop").css({'display': 'block', 'z-index': '9999' });
$("#blanket").css({'display': 'block', 'height', getBlanketHeight(), 'z-index': '1000' });
loadproperties('open', $(this).closest(".yme-propertyitem").attr("id"));
});
// Close property button
$("#yme-property-close").live('click', function() {
$("#yme-property-pop").css('display', 'none');
$("#blanket").css('display', 'none');
});
Couple of things to clear up first:
It really helps if you create a way for us to interact with your
code, especially as you've pasted PHP code here, instead of plain
HTML
Is there a reason why you're not using a library to handle your DOM
interactions? It will make your code more concise and take away some
possible failure points when it comes to cross-browser code.
Right,
I'm a little unsure why your code isn't working in Chrome. I set up a demo in jsfiddle and it seems to work fine.
You'll notice I'm not attaching the events in onclick attributes on the <a/> element, and neither should you. This could be where the problem lies.
Currently, the code in the jsfiddle alerts as expected and only fails when it fails to find a relevent DOM node in toggle.
Note:
addEventListener in the example is not cross-browser, which is another reason to use a DOM library.

Categories