In my project, the Ckeditor is part of a webpage, which is coded using GWT. So the interface to CKeditor is using Java.
Whenever the webpage is displayed, the CKeditor will be passed a HTML via setData(), which the CKeditor is supposed to show.
The problem is: CKeditor sometimes won't show the HTML. Its content was just empty, although I am very sure the html had been passed to setData().
I had tried several approaches to solve this problem, but none would work.
My approach
Create a TextArea using DOM.createTextArea()
Call myEditor=CKEDITOR.replace(textArea, config) to initialize the CKeditor
call myEditor.setData(html) to set the content.
It was good and showed the content at the first time.
But after the webpage got hidden and shown again, I called myEditor.setData(html2) to show another html, but this time the CKeditor showed nothing.
First solution (did not work)
I changed the code to call myEditor.destroy() before the webpage was hidden, and call CKEDITOR.replace(textArea, config) again when the webpage was visible again, after that I called myEditor.setData(newHtml).
This time it worked in IE and FF, but not in Chrome and Edge, it kept showing the content of the first load time, instead of showing the new HTML.
Second solution (did not work)
I changed it to call CKEDITOR.inline(textArea, config) instead of CKEDITOR.replace(textArea, config) when the webpage was visible again, while the destroy() and setData() was still called in the same order. This time the CKeditor again didn't show anything from the second time.
Last attempt
My last approach was to not calling destroy(), but creating a new TextArea each time before showing CKeditor, and called CKEDITOR.replace(textArea, config) and setData(html). This seems to work well, but occasionally the CKeditor still showed empty content.
Could anyone please help me to solve this problem?
I am using CKeditor 4.5.8.
Finally I figured out the solution:
Before hiding the ckeditor, call editor.destroy(true), and delete editor. (Before this, I only called editor.destroy() [note: no 'true'], which didn't work well).
Here is the code:
if (editor) {
editor.destroy(true);
delete editor;
}
Use this java script code that is very simple and effective.Note editor1 is my textarea id
<script>
$(function () {
CKEDITOR.timestamp= new Date();
CKEDITOR.replace('editor1');
});
</script>
second way ! In controller ,when your query is fetch data from database then use this code after .success(function().
$http.get(url).success(function(){
CKEDITOR.replace('editor1');
});
Related
I have javascript files defined in the <head> of both my layout decorator template and my individual pages which are decorated. When I update a thymeleaf fragment in one of my pages the javascript defined in the head of the parent page no longer works. Is there a standard way to 'refresh' these js files?
Thanks.
Additional clarification :
I have a form submitted by an ajax call which updates a table in the page. I have a Jquery onClick function targeting a button in the updated table. The javascript doesn't seem able to bind to the returned elements in the updated part of the page. I select by element class and can see that the selection works prior to the partial fragment render.
For me it is unclear what you mean by
javascript defined in the head of the parent page no longer works.
The page is created on the server. Normally it contains urls of the javascript files
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
In this case 'refreshing' the javascript files can happen only in the client.
Check the html of the page in the client.
Are the tags as expected ?
Are there tags for all expected javascript files ?
With the browser tools (for example Google Chrom developer tools ) check that all script files are actually loaded.
If this doesnt help, it could be that the order of the script tags has changed between the first and second load. This could cause a different behaviour of the javascript executed in the browser.
EDIT :
With the initial load you bind javascript callbacks to dom elements.
You do this directly or through Jquery or other libraries.
When a new dom element is loaded, it has no callbacks bound to it, even if it has the same id as a replaced dom element.
So after the load you have to bind your callbacks again.
If you bound them 'by hand', just bind it again.
If you are using a JQuery plugin, that made the bindings, look into the code or documentation, many of them have a function for that or you can call initialization again.
Once you added new content to the DOM you need to bind again the new content.
Let's say I have a button with some class, the event in binded to the class:
<button class="someclass">Button 1</button>
<script>
var something = function() {
// do something
};
$(".someclass").on("click", something);
</script>
If I add more buttons from the same class to the DOM, they will have not have the click event binded. So once you load the new content via ajax, also remove all binding and add again (you need to remove or you will have buttons with 2 events).
$(".someclass").off("click");
$(".someclass").on("click" , something);
I am using the following directive to create a ckEditor view. There are other lines to the directive to save the data but these are not included as saving always works for me.
app.directive('ckEditor', [function () {
return {
require: '?ngModel',
link: function ($scope, elm, attr, ngModel) {
var ck = ck = CKEDITOR.replace(elm[0]);
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
setTimeout(function () {
ck.setData(ngModel.$modelValue);
}, 1000);
}; }
};
}])
The window appears but almost always the first time around it is empty. Then after clicking the [SOURCE] button to show the source and clicking it again the window is populated with data.
I'm very sure that the ck.setData works as I tried a ck.getData and then logged the output to the console. However it seems like ck.setData does not make the data visible at the start.
Is there some way to force the view window contents to appear?
You can call render on the model at any time and it will simply do whatever you've told it to do. In your case, calling ngModel.$render() will grab the $modelValue and pass it to ck.setData(). Angular will automatically call $render whenever it needs to during its digest cycle (i.e. whenever it notices that the model has been updated). However, I have noticed that there are times when Angular doesn't update properly, especially in instances where the $modelValue is set prior to the directive being compiled.
So, you can simply call ngModel.$render() when your modal object is set. The only problem with that is you have to have access to the ngModel object to do that, which you don't have in your controller. My suggestion would be to do the following:
In your controller:
$scope.editRow = function (row, entityType) {
$scope.modal.data = row;
$scope.modal.visible = true;
...
...
// trigger event after $scope.modal is set
$scope.$emit('modalObjectSet', $scope.modal); //passing $scope.modal is optional
}
In your directive:
ngModel.$render = function (value) {
ck.setData(ngModel.$modelValue);
};
scope.$on('modalObjectSet', function(e, modalData){
// force a call to render
ngModel.$render();
});
Its not a particularly clean solution, but it should allow you to call $render whenever you need to. I hope that helps.
UPDATE: (after your update)
I wasn't aware that your controllers were nested. This can get really icky in Angular, but I'll try to provide a few possible solutions (given that I'm not able to see all your code and project layout). Scope events (as noted here) are specific to the nesting of the scope and only emit events to child scopes. Because of that, I would suggest trying one of the three following solutions (listed in order of my personal preference):
1) Reorganize your code to have a cleaner layout (less nesting of controllers) so that your scopes are direct decendants (rather than sibling controllers).
2) I'm going to assume that 1) wasn't possible. Next I would try to use the $scope.$broadcast() function. The specs for that are listed here as well. The difference between $emit and $broadcast is that $emit only sends event to child $scopes, while $broadcast will send events to both parent and child scopes.
3) Forget using $scope events in angular and just use generic javascript events (using a framework such as jQuery or even just roll your own as in the example here)
There's a fairly simple answer to the question. I checked the DOM and found out the data was getting loaded in fact all of the time. However it was not displaying in the Chrome browser. So the problem is more of a display issue with ckEditor. Strange solution seems to be to do a resize of the ckEditor window which then makes the text visible.
This is a strange issue with ckeditor when your ckeditor is hidden by default. Trying to show the editor has a 30% chance of the editor being uneditable and the editor data is cleared. If you are trying to hide/show your editor, use a css trick like position:absolute;left-9999px; to hide the editor and just return it back by css. This way, the ckeditor is not being removed in the DOM but is just positioned elsewhere.
Use this java script code that is very simple and effective.Note editor1 is my textarea id
<script>
$(function () {
CKEDITOR.timestamp= new Date();
CKEDITOR.replace('editor1');
});
</script>
Second way In controller ,when your query is fetch data from database then use th
is code after .success(function().
$http.get(url).success(function(){
CKEDITOR.replace('editor1');
});
I know, that this thread is dead for a year, but I got the same problem and I found another (still ugly) solution to this problem:
instance.setData(html, function(){
instance.setData(html);
});
There is a problem when I put Kendo Dropdown List info Fancybox - Popup.
For detail:
I have page A :this page contains Kendo Dropdown list (with id = #myDropdown).
I have page B : I put my Fancybox caller here- I mean I use Fancybox to load page A (by ajax)
Everything look well , but I got a problem here:
You know, when I initialize a Dropdown List, Kendo-UI will create an "anchor" Tag for UI-effect purpose.
Ex:
DropdownList has id = #myDropdown
Kendo will create one more Tag with id = #myDropdown-list.
After closing the Fancybox-popup , The "#myDropdown" was removed from DOM, but "#myDropdown-list". It still on the DOM overtime, and it willing to be double after I call the popup again(ofcourse if dont refresh current page).
And The Kendo-DateTimePicker as the same too.
p/s: and so sorry about by english if it was too bad :D. I hope you get my question.
im going to put my "popup" in iframe.But I dont know if it is good when using iframe in this case...
Using IFrame or not is not the cause of the error. I tried with a container and without it to load the fancybox via ajax, but it didn't make a difference.
What I found is sort of a hack, however it solves the problem. Let's suppose we have a code which creates the popup and the popup's content is located in the href 'popupFrame':
$.fancybox({
'href': 'popupFrame',
'type': 'ajax',
beforeClose: removeKendoHelpers
});
The other part is the function which is called before closing the popup:
function removeKendoHelpers() {
$("#myDropdown-list").remove();
}
Of course you can create the removeKendoHelpers as an inline function and if there are more parts to remove then put that code into the removeKendoHelpers function as well.
One interesting remark: in the fancybox API onCleanup and onClosed are listed as options but they do not work, instead use beforeClose or afterClose.
UPDATE:
Actually a lot of problem is solved with calling the kendo widget's destroy() method. It solves the removing problems for the widgets except for one of the three helper divs of the DateTimePicker, so the close looks like the following:
function removeKendoHelpers() {
$("#myDropdown-list").data("kendoDropDownList").destroy();
$("#datetimepicker").data("kendoDateTimePicker").destroy();
}
And to resolve the date time picker's actual problem which is I think a bug in the kendop framework (I will report this and hopefully get some feedback) the last function only needs to be extended with:
$(".k-widget.k-calendar").remove();
OTHER solution:
This one is more crude but works like a charm for me even if the page has multiple kendo controls and even if you open another fancybox from your fancybox.
Wrap the fancybox creation in a function, like:
function openFancyBox() {
$("body").append("<div class='fancybox-marker'></div>");
$.fancybox({
'href': 'popupFrame',
'type': 'ajax',
beforeClose: removeKendoHelpers
});
}
This will create a new div at the very end of the body tag, and the function at the closing of the fancybox uses this:
function removeKendoHelpers() {
$(".fancybox-marker").last().nextAll().remove();
$(".fancybox-marker").last().remove();
}
I hope these solves all your problem!
I am trying to fetch data from a site by simulating events using CasperJS with phantomJS 1.7.0.
I am able to simulate normal click events and select events. But my code fails in following scenario:
When I click on button / anchor etc on remote page, the click on remote page initiates an AJAX call / JS call(depending on how that page is implemented by programmer.).
In case of JS call, my code works and I get changed data. But for clicks where is AJAX call is initiated, I do not get updated data.
For debugging, I tried to get the page source of the element container(before and after), but I see no change in code.
I tried to set wait time from 10 sec to 1 ms range, but that to does not reflect any changes in behavior.
Below is my piece of code for clicking. I am using an array of CSS Paths, which represents which element(s) to click.
/*Click on array of clickable elements using CSS Paths.*/
fn_click = function(){
casper.each(G_TAGS,function(casper, cssPath, count1)
{
casper.then ( function() {
casper.click(cssPath);
this.echo('DEBUG AFTER CLICKING -START HTML ');
//this.echo(this.getHTML("CONTAINER WHERE DETAILS CHANGE"));
this.echo('DEBUG AFTER CLICKING -START HTML');
casper.wait(5000, function()
{
casper.then(fn_getData);
}
);
});
});
};
UPDATE:
I tried to use remote-debug option from phantomJS, to debug above script.
It is not working. I am on windows. I will try to run remote debugging on Ubuntu as well.
Please help me. I would appreciate any help on this.
UPDATE:
Please have a look at following code as a sample.
https://gist.github.com/4441570
Content before click and after click are same.
I am clicking on sorting options provided under tag (votes / activity etc.).
I had the same problem today. I found this post, which put me in the direction of jQuery.
After some testing I found out that there was already a jQuery loaded on that webpage. (A pretty old version though)
Loading another jQuery on top of that broke any js calls made, so also the link that does an Ajax call.
To solve this I found http://api.jquery.com/jQuery.noConflict/
and I added the following to my code:
this.evaluate(function () { jq = $.noConflict(true) } );
Anything that was formerly assigned to $ will be restored that way. And the jQuery that you injected is now available under 'jq'.
Hope this helps you guys.
I am currently loading several forms into a webpage with:
$(document).ready(function () {
$('#content').load('php_script.php', function() {
$(this).find('#someForm').ajaxForm(function() {
alert('Success!');
});
$(this).find('.someOtherForm').ajaxForm(function() {
alert('Success!');
});
});
});
This works in Chrome, Chromium and IE who loads the forms and everything works as it should (Clicking submit sends a request to the php-script defined in the form's action, which adds stuff to a db, and shows the alert dialog). In Firefox (v10.0.2) this code loads the forms into the DOM and displays them, but when clicking submit on any of the forms nothing happens.
At first I suspected ajaxForm, but changing the above code to:
$(document).ready(function () {
$('#content').load('php_script.php');
});
yields almost the same result, the difference being that the user is sent to the script defined as the action (Except for Firefox, where nothing happens).
How do I make Firefox not kill the submit button?
I solved it, bad HTML from my side:
<table><form ...>
<tr>...</tr>
</form></table>
Instead it should look like:
<form ...><table>
<tr>...</tr>
</table></form>
The validator did not catch this since it was loaded via jQuery (and I forgot to validate the page serving the forms), and Firefox buggered out.
The code above looks ok to me...
Have you had a look in firebug if there are any errors? Maybe there is a conflicting Id or something.
Maybe the form isnt completely loaded into the dom yet, might be worth giving live binding a try
Found this in the docs:
...jQuery uses the browser's .innerHTML property to parse the retrieved document and insert it into the current document. During this process, browsers often filter elements from the document such as , , or elements. As a result, the elements retrieved by .load() may not be exactly the same as if the document were retrieved directly by the browser...
If you inspect the form is it the same as in other browsers?