Wicket AjaxFormUpdatingBehavior and Javascript - javascript

I have these two DropDownChoice (DDC) objects that work perfectly fine: when one element is chosen from the first DDC, the list for the second gets update with related choices. The first is strumListDDC, the latter is controlListDDC.
controlListDDC.setOutputMarkupId(true);
controlListDDC.setChoiceRenderer(new ChoiceRenderer<>("name"));
controlListDDC.add(new AjaxFormComponentUpdatingBehavior("change") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
QCControl qcc = controlListDDC.getModelObject();
lotList = QCLot.getLotsForCtrl(qcc.getId());
if (!lotList.isEmpty()) {
target.add(lotListDDC);
}
}
});
searchForm.addOrReplace(new Label("strumListLabel", "Strumento:"));
searchForm.addOrReplace(strumListDDC = new DropDownChoice<>("strumList", InstalledStrum.loadAllStrum(false)));
strumListDDC.setDefaultModel(new Model<>());
strumListDDC.add(new AjaxFormComponentUpdatingBehavior("change") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
InstalledStrum is = strumListDDC.getModelObject();
controlList = QCControl.loadQCControlPerStrumType(is.getStrumType());
lotList = new ArrayList<>();
if (!controlList.isEmpty()) {
target.add(controlListDDC);
target.add(lotListDDC);
}
}
});
For niceness reasons, I added this little bit of Javascript to the page template from which all my HTML pages are derived:
$(function filtersScroll() {
var $filters = $(".viewANfilters");
detailsPos = $filters.position().top;
$(window).on("scroll", function () {
if ($(window).scrollTop() > detailsPos)
$filters.css("position", "fixed").css("top", 0);
else
$filters.css("position", "fixed").css("top", detailsPos -$(window).scrollTop());
});
});
I add the javascript through using Wicket (but the problem is still there if I insert the code directly in the HTML, I just post it for completeness):
response.render(JavaScriptContentHeaderItem.forScript(Costants.JS_FILTERS_SCROLL, "filters_scroll"));
When I add the javascript, the onUpdate function of the first DDC never gets called (checked with debugger). As soon as I remove the javascript, the autoupdating behavior starts working fine again. Not that this javascript is fundamental to the page, I can still go on without it, but I fear the same thing will happen again when I will need to add some serious javascript.
Since I'm pretty new at javascript, can anybody give me a hint on what's stopping the AjaxFormComponentUpdatingBehavior from working? Can it be some sort of conflict between different script tags? There are others in the final page, added by Wicket itself, but since they have always been more than one I didn't think a new script would cause any trouble...

Check your selector ".viewANfilters" - if no element with that class is present, position() will be undefined, your JavaScript fails and Wicket won't be able to register any event handlers.

Related

Cannot reinitalize Sortable after ajax content update

I'm using Sortable to organise lists inside of parent groupings, which themselves are also sortable, similar to the multi example on their demo page, but with text. This works fine and uses code along the lines of:
var globObj = {};
function prepSortCats() {
globObj.subCatsGroup = [];
// Changing parent group order
globObj.sortyMainCats = Sortable.create(catscontainer, {
// options here omitted from example
onUpdate: function( /**Event*/ evt) {
// Send order to database. Works fine.
}
});
// Changing sub list order
globObj.subCatsGroup.forEach.call(document.getElementById('catscontainer').getElementsByClassName('subcatlist'), function(el) {
var sortySubCats = Sortable.create(el, {
// options here from example
onUpdate: function( /**Event*/ evt) {
// Send order to database. Works fine.
}
});
});
}
Which is called when the page loads using:
$(document).ready(function () {
// Sortable
prepSortCats();
});
All good so far. However, the user can introduce new elements into any of the lists (sub or parent). In brief, any new elements added by the user are first added to the database, then the relevant section of the page is refreshed using ajax to pull the updated content from the database and display that. The user sees their newly added items added to one of the existing lists. Ajax call is as follows:
function refreshCategories() {
var loadUrl = "page that pulls lists from database and formats it";
$("#catscontainer")
.html(ajax_load)
.load(loadUrl);
return false;
};
This works fine too. Except, Sortable no longer works. I can't drag any lists. My first thought was to destroy the existing Sortable instances and reinitialize them. Right after I called refreshCategories() I call the following:
if(globObj.sortyMainCats.length !== 0) {
globObj.sortyMainCats.destroy();
}
if(globObj.subCatsGroup.length !== 0) {
var i;
for (i = globObj.subCatsGroup.length - 1; i >= 0; i -= 1) {
globObj.subCatsGroup[i].destroy();
globObj.subCatsGroup.splice(i, 1);
}
}
prepSortCats();
But Sortable still has no effect. I introduced the global object (although controversial) so that I could target the Sortable instances outside their scope but I appear to have overlooked something. Any ideas? Apologies for not providing a working example. As I make various ajax calls to a server, I don't think this is possible here.
Update
I'm clearly misunderstanding some action that's taking place. Well, I should preface that by saying I missed that I could still organise the group/parent lists after reloading a section of the page by ajax with refreshCategories(). This is very much a secondary action to being able to sort the sub lists, which is what I noticed was broken and remains so.
But it did point out that although the entirety of $("#catscontainer") was being replaced with a refreshed version of the lists (and that's all it contains, list elements), Sortable still had some sort of instance running on it. I was under the understanding that it was somehow tied to the elements that were removed. Now I'm a bit more lost on how to get Sortable to either: (a) just start from scratch on the page, performing prepSortCats() as if it was a fresh page load and removing any previous Sortable instance, or (b) getting the remaining Sortable instance, after the ajax call to recognise the added elements.
Update 2
Making some progress.
Through trial and error I've found that right after calling refreshCategories(), calling globObj.sortyMainCats.destroy() is preventing even the group lists from being ordered. Then if I call prepSortCats() after this, I can move them again. But not the sub lists.
This isn't conclusive but it looks like I'm successfully destroying and reinitializing Sortable, which was my goal, but something about the ajax loaded elements isn't working with Sortable.
I was looking for the answer in the wrong place, being sure it was an issue with ajax loaded content and the dom having some inconsistencies with what Sortable expected.
Turns out it was an asynchronous problem. Or, to put it simpler, the section of the page being loaded by ajax wasn't quite ready when Sortable was being asked to be reinitalized.
For anyone having the same trouble, I changed:
$("#catscontainer")
.html(ajax_load)
.load(loadUrl);
to
$("#catscontainer")
.html(ajax_load)
.load(loadUrl, function() {
reinitSortable();
});
where reinitSortable() is just a function that fires off the destroy and prepSortCats() functions similar to how they're displayed above.

Spotfire - javascript to trigger IronPython script to be executed on report load

I have the follwing javascript code that it triggers an IronPython script when I load the report.
The only issue I have is that for a reason I don't know it does it (it triggers the script) a couple of times.
Can some one help me? below is the script:
var n=0;
$(function () {
function executeScript() {
if (n==0){
n=n+1;
now = new Date();
if (now.getTime()-$('#hiddenBtn input').val()>10000){
$('#hiddenBtn input').val(now.getTime());
$('#hiddenBtn input').focus();
$('#hiddenBtn input').blur();
}
}
}
$(document).ready(function(){executeScript()});
strong text});
Please, let me know if you need more information.
Thanks in advance!!!
I have had similar issues with Javascript executing multiple times. Spotfire seems to instance the JS more than once, and it can cause some interesting behavior...
the best solution, in my opinion, only works if users are accessing the document via a link (as opposed to browsing the library). pass a configuration block to set a document property with a current timestamp, which would execute your IP script. this is the most solid implementation.
otherwise, you can try something like this:
// get a reference to a container on the page with an ID "hidden"
var $hidden = $("#hiddenBtn input");
// only continue if the container is empty
if !($hidden.text()) {
var now = Date.now();
$hidden.text(now)
.focus()
.blur();
|}
this is essentially the same as the code you posted, but instead of relying on the var n, you're counting on the input #hiddenBtn > input being empty. there is a caveat that you'll have to ensure this field is empty before you save the document
one addtional solution is using a Data Function to update the document property, like #user1247722 shows in his answer here: https://stackoverflow.com/a/40712635/4419423

CefSharp Wait For Element to Appear Javascript Not Triggering Raise Event

I've been at this quite a while, have dug everywhere and I'm about at my wits end. The solution seems simple: Inject some javascript code into the chromium browser to wait for an element to appear (the browser has already finished loading and without waiting for the element, my .net code races past the automation parts I want to do on the page), then proceed.
I'm following the examples set here and here (see the constructor).
However, the raise event isn't firing like I figured it should be. It's probably due to my javascript code - or it's possible I've missed something somewhere else.
Here is the js code:
private void InjectJsWait(string eventName, string selector, int time, string eventStage)
{
string script = #"function waitForElementToDisplay(##SELECTOR##, ##TIME##) {
if(document.querySelector(##SELECTOR##)!=null) {
window.boundEvent.raiseEvent('##EVENTNAME##', {eventStage: ##STAGE##});
return;
}
else {
setTimeout(function() {
waitForElementToDisplay(##SELECTOR##, ##TIME##);
}, ##TIME##);
}
}";
script = Regex.Replace(script, "##SELECTOR##", selector);
script = Regex.Replace(script, "##TIME##", time.ToString());
script = Regex.Replace(script, "##EVENTNAME##", eventName);
script = Regex.Replace(script, "##STAGE##", eventStage);
browser.ExecuteScriptAsync(script);
}
Any help would be greatly appreciated.
Using a MutationObserver should be able to do this.
You would simply have to check the observed change and filter out the one you need; no guessing whether or not an event has fired or element has been added.
Keep in mind that this needs Chrome 18+ or 26+ to work

CKEditor instance already exists

I am using jquery dialogs to present forms (fetched via AJAX). On some forms I am using a CKEditor for the textareas. The editor displays fine on the first load.
When the user cancels the dialog, I am removing the contents so that they are loaded fresh on a later request. The issue is, once the dialog is reloaded, the CKEditor claims the editor already exists.
uncaught exception: [CKEDITOR.editor] The instance "textarea_name" already exists.
The API includes a method for destroying existing editors, and I have seen people claiming this is a solution:
if (CKEDITOR.instances['textarea_name']) {
CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name');
This is not working for me, as I receive a new error instead:
TypeError: Result of expression 'i.contentWindow' [null] is not an object.
This error seems to occur on the "destroy()" rather than the "replace()". Has anyone experienced this and found a different solution?
Is is possible to 're-render' the existing editor, rather than destroying and replacing it?
UPDATED
Here is another question dealing with the same problem, but he has provided a downloadable test case.
For this to work you need to pass boolean parameter true when destroying instance:
var editor = CKEDITOR.instances[name];
if (editor) { editor.destroy(true); }
CKEDITOR.replace(name);
function loadEditor(id)
{
var instance = CKEDITOR.instances[id];
if(instance)
{
CKEDITOR.remove(instance);
}
CKEDITOR.replace(id);
}
I had this problem too, but I solved it in a much simpler way...
I was using the class "ckeditor" in my jQuery script as the selector for which textareas I wanted use for CKEditor. The default ckeditor JS script also uses this class to identify which textareas to use for CKEditor.
This meant there is a conflict between my jQuery script and the default ckeditor script.
I simply changed the class of the textarea and my jQuery script to 'do_ckeditor'(you could use anything except "ckeditor") and it worked.
This is the simplest (and only) solution that worked for me:
if(CKEDITOR.instances[editorName])
delete CKEDITOR.instances[editorName];
CKEDITOR.replace(editorName);
Deleting this entry in the array prevents this form safety check from destroying your application.
destroy() and remove() did not work for me.
Perhaps this will help you out - I've done something similar using jquery, except I'm loading up an unknown number of ckeditor objects. It took my a while to stumble onto this - it's not clear in the documentation.
function loadEditors() {
var $editors = $("textarea.ckeditor");
if ($editors.length) {
$editors.each(function() {
var editorID = $(this).attr("id");
var instance = CKEDITOR.instances[editorID];
if (instance) { instance.destroy(true); }
CKEDITOR.replace(editorID);
});
}
}
And here is what I run to get the content from the editors:
var $editors = $("textarea.ckeditor");
if ($editors.length) {
$editors.each(function() {
var instance = CKEDITOR.instances[$(this).attr("id")];
if (instance) { $(this).val(instance.getData()); }
});
}
UPDATE: I've changed my answer to use the correct method - which is .destroy(). .remove() is meant to be internal, and was improperly documented at one point.
var e= CKEDITOR.instances['sample'];
e.destroy();
e= null;
I've had similar issue where we were making several instances of CKeditor for the content loaded via ajax.
CKEDITOR.remove()
Kept the DOM in the memory and didn't remove all the bindings.
CKEDITOR.instance[instance_id].destroy()
Gave the error i.contentWindow error whenever I create new instance with new data from ajax. But this was only until I figured out that I was destroying the instance after clearing the DOM.
Use destroy() while the instance & it's DOM is present on the page, then it works perfectly fine.
For ajax requests,
for(k in CKEDITOR.instances){
var instance = CKEDITOR.instances[k];
instance.destroy()
}
CKEDITOR.replaceAll();
this snipped removes all instances from document.
Then creates new instances.
The i.contentWindow is null error seems to occur when calling destroy on an editor instance that was tied to a textarea no longer in the DOM.
CKEDITORY.destroy takes a parameter noUpdate.
The APIdoc states:
If the instance is replacing a DOM element, this parameter indicates whether or not to update the element with the instance contents.
So, to avoid the error, either call destroy before removing the textarea element from the DOM, or call destory(true) to avoid trying to update the non-existent DOM element.
if (CKEDITOR.instances['textarea_name']) {
CKEDITOR.instances['textarea_name'].destroy(true);
}
(using version 3.6.2 with jQuery adapter)
This is what worked for me:
for(name in CKEDITOR.instances)
{
CKEDITOR.instances[name].destroy()
}
CKEDITOR.instances = new Array();
I am using this before my calls to create an instance (ones per page load). Not sure how this affects memory handling and what not. This would only work if you wanted to replace all of the instances on a page.
I've prepared my own solution based on all above codes.
$("textarea.ckeditor")
.each(function () {
var editorId = $(this).attr("id");
try {
var instance = CKEDITOR.instances[editorId];
if (instance) { instance.destroy(true); }
}
catch(e) {}
finally {
CKEDITOR.replace(editorId);
}
});
It works perfectly for me.
Sometimes after AJAX request there is wrong DOM structure.
For instace:
<div id="result">
<div id="result>
//CONTENT
</div>
</div>
This will cause issue as well, and ckEditor will not work. So make sure that you have correct DOM structure.
i had the same problem with instances, i was looking everywhere and finally this implementation works for me:
//set my instance id on a variable
myinstance = CKEDITOR.instances['info'];
//check if my instance already exist
if (myinstance) {
CKEDITOR.remove(info)
}
//call ckeditor again
$('#info').ckeditor({
toolbar: 'Basic',
entities: false,
basicEntities: false
});
You can remove any ckeditor instance by remove method of ckeditor. Instance will be id or name of the textarea.
if (CKEDITOR.instances[instance_name]) {
CKEDITOR.remove(CKEDITOR.instances[instance_name]);
}
Indeed, removing the ".ckeditor" class from your code solves the issue. Most of us followed the jQuery integration example from the ckeditor's documentation:
$('.jquery_ckeditor')
.ckeditor( function() { /* callback code */ }, { skin : 'office2003' } );
and thought "... maybe I can just get rid or the '.jquery_' part".
I've been wasting my time tweaking the callback function (because the {skin:'office2003'} actually worked), while the problem was coming from elsewhere.
I think the documentation should mention that the use of "ckeditor" as a class name is not recommended, because it is a reserved keyword.
Cheers.
I learned that
delete CKEDITOR.instances[editorName];
by itself, actually removed the instance. ALL other methods i have read and seen, including what was found here at stackoverflow from its users, did not work for me.
In my situation, im using an ajax call to pull a copy of the content wrapped around the and 's. The problem happens to be because i am using a jQuery .live event to bind a "Edit this document" link and then applying the ckeditor instance after success of the ajax load. This means, that when i click another link a link with another .live event, i must use the delete CKEDITOR.instances[editorName] as part of my task of clearing the content window (holding the form), then re-fetching content held in the database or other resource.
I hade the same problem with a jQuery Dialog.
Why destroy the instance if you just want to remove previous data ?
function clearEditor(id)
{
var instance = CKEDITOR.instances[id];
if(instance)
{
instance.setData( '' );
}
}
I chose to rename all instances instead of destroy/replace - since sometimes the AJAX loaded instance doesn't really replace the one on the core of the page... keeps more in RAM, but less conflict this way.
if (CKEDITOR && CKEDITOR.instances) {
for (var oldName in CKEDITOR.instances) {
var newName = "ajax"+oldName;
CKEDITOR.instances[newName] = CKEDITOR.instances[oldName];
CKEDITOR.instances[newName].name = newName;
delete CKEDITOR.instances[oldName];
}
}
I am in the situation where I have to controls that spawn dialogs, each of them need to have a ckeditor embedded inside these dialogs. And it just so happens the text areas share the same id. (normally this is very bad practice, but I have 2 jqGrids, one of assigned items and another of unassigned items.) They share almost identical configuration. Thus, I am using common code to configure both.
So, when I load a dialog, for adding rows, or for editing them, from either jqGrid; I must remove all instances of CKEDITOR in all textareas.
$('textarea').each(function()
{
try
{
if(CKEDITOR.instances[$(this)[0].id] != null)
{
CKEDITOR.instances[$(this)[0].id].destroy();
}
}
catch(e)
{
}
});
This will loop over all textareas, and if there is a CKEDITOR instance, then destroy it.
Alternatively if you use pure jQuery:
$('textarea').each(function()
{
try
{
$(this).ckeditorGet().destroy();
}
catch(e)
{
}
});
remove class="ckeditor" , it might have triggered ckeditor initialization
I had the same problem where I was receiving a null reference exception and the word "null" would be displayed in the editor. I tried a handful of solutions, including upgrading the editor to 3.4.1 to no avail.
I ended up having to edit the source. At about line 416 to 426 in _source\plugins\wysiwygarea\plugin.js, there's a snippet like this:
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
In FF at least, the iframe isn't completely instantiated by the time it's needed. I surrounded the rest of the function after that line with a setTimeout function:
iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
setTimeout(function()
{
// Running inside of Firefox chrome the load event doesn't bubble like in a normal page (#5689)
...
}, 1000);
};
// The script that launches the bootstrap logic on 'domReady', so the document
...
The text renders consistently now in the modal dialogs.
To support dynamic (Ajax) loading of forms (without page refreshes between) which contain textareas with the same (same form is called again) or different ID's (previously unloaded form) and convert them to CKEditor elements I did the following (using the JQuery adapter):
After the page has finished every Ajax call that delivers a textarea to be converted, I make a call to the following function:
setupCKeditor()
This looks like this (it assumes your textareas to be converted to RTE's have class="yourCKClass"):
/* Turns textAreas into TinyMCE Rich Text Editors where
* class: tinymce applied to textarea.
*/
function setupCKeditor(){
// define editor configuration
var config = {skin : 'kama'};
// Remove and recreate any existing CKEditor instances
var count = 0;
if (CKEDITOR.instances !== 'undefined') {
for(var i in CKEDITOR.instances) {
var oEditor = CKEDITOR.instances[i];
var editorName = oEditor.name;
// Get the editor data.
var data = $('#'+editorName).val();
// Check if current instance in loop is the same as the textarea on current page
if ($('textarea.yourCKClass').attr('id') == editorName) {
if(CKEDITOR.instances[editorName]) {
// delete and recreate the editor
delete CKEDITOR.instances[editorName];
$('#'+editorName).ckeditor(function() { },config);
count++;
}
}
}
}
// If no editor's exist in the DOM, create any that are needed.
if (count == 0){
$('textarea.yourCKClass').each( function(index) {
var editorName = $(this).attr('id');
$('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);
});
}
}
I should mention that the line:
$('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);
could (and should) be simply:
$('#'+editorName).ckeditor(function() { },config);
however I found that the editor would often show the correct content for a second after loading and them empty the editor of the desired content. So that line with the callback code forces the CKEditor content to be the same as the originating textarea content. Causes a flicker when used. If you can avoid using it, do so..
I had exactly the same problem like jackboberg. I was using dynamic form loading into jquery dialogs then attaching various widgets (datepickers, ckeditors etc...).
And I tried all solutions noted above, none of them worked for me.
For some reason ckeditor only attached the first time I loaded form, the second time I got exactly the same error message jackboberg did.
I've analyzed my code and discovered that if you attach ckeditor in "mid-air" that is while form content is still not placed into dialog, ckeditor won't properly attach its bindings. That is since ckeditor is attached in "mid-air", second time you attach it in "mid-air"... poof ... an error is thrown since the first instance was not properly removed from DOM.
This was my code that ptoduced the error:
var $content = $(r.content); // jQuery can create DOM nodes from html text gotten from <xhr response> - so called "mid-air" DOM creation
$('.rte-field',$content).ckeditor(function(){});
$content.dialog();
This is the fix that worked:
var $content = $(r.content).dialog(); // first create dialog
$('.rte-field',$content).ckeditor(function(){}); // then attach ckeditor widget
I ran into this exact same thing and the problem was that the wordcount plugin was taking too long to initialize. 30+ seconds. The user would click into the view displaying the ckeditor, then cancel, thereby ajax-loading a new page into the dom. The plugin was complaining because the iframe or whatever contentWindow is pointing to was no longer visible by the time it was ready to add itself to the contentWindow. You can verify this by clicking into your view and then waiting for the Word Count to appear in the bottom right of the editor. If you cancel now, you won't have a problem. If you don't wait for it, you'll get the i.contentWindow is null error. To fix it, just scrap the plugin:
if (CKEDITOR.instances['textarea_name'])
{
CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name', { removePlugins: "wordcount" } );
If you need a word counter, register for the paste and keyup events on the editor with a function that counts the words.
For those using the jquery "adapter" and having trouble (as I was), as super hackish yet working solution is to do something like this:
// content editor plugin
(function($){
$.fn.contentEditor = function( params ) {
var xParams = $.extend({}, $.fn.contentEditor.defaultParams, params);
return this.each( function() {
var $editor = $(this);
var $params = $.extend({}, xParams, $editor.data());
// if identifier is set, detect type based on identifier in $editor
if( $params.identifier.type ) {
$params.type = $editor.find($params.identifier.type).val();
}
$editor.data('type', $params.type);
// edit functionality
editButton = $('<button>Edit Content</button>').on('click',function(){
// content container
var $cc = $('#' + $editor.data('type'));
// editor window
var $ew = $('<form class="editorWindow" />');
$ew.appendTo('body');
// editor content
$ec = $('<textarea name="editorContent" />').val($cc.html());
$ec.appendTo($ew);
$ec.ckeditor();
//$ec.ckeditorGet().setMode('source');
$ew.dialog({
"autoOpen": true,
"modal": true,
"draggable": false,
"resizable": false,
"width": 850,
"height": 'auto',
"title": "Content Editor",
"buttons": {
'Save': function() {
$cc.html( $ec.val() );
$ec.ckeditorGet().destroy();
$ew.remove();
},
'Cancel / Close': function() {
$ec.ckeditorGet().destroy();
$ew.remove();
}
},
'close': function() {
$ec.ckeditorGet().destroy();
},
'open': function() {
$ew.find('a.cke_button_source').click();
setTimeout(function(){
$ew.find('a.cke_button_source.cke_on').click();
}, 500);
}
});
return false;
});
editButton.appendTo( $editor );
});
}
// set default option values
$.fn.contentEditor.defaultParams = {
'identifier': {
'type': 'input[name="type"]'
}
};
})(jQuery);
$(function(){
$('form.contentEditor').contentEditor();
});
The key point being this part:
'open': function() {
$ew.find('a.cke_button_source').click();
setTimeout(function(){
$ew.find('a.cke_button_source.cke_on').click();
}, 500);
}
This fixes the problem with the editor text not being visible the next time you open the dialog. I realise this is very hackish, but considering that most of these are going to be used for admin tools, I don't think that's as big a concern as it normally would be.. and this works, so hopefully it will save someone some time ;)
This is the fully working code for jquery .load() api and ckeditor, in my case I am loading a page with ckeditor into div with some jquery effects. I hope it will help you.
$(function() {
runEffect = function(fileload,lessonid,act) {
var selectedEffect = 'drop';
var options = {};
$( "#effect" ).effect( selectedEffect, options, 200, callback(fileload,lessonid,act) );
};
function callback(fileload,lessonid,act) {
setTimeout(function() {//load the page in effect div
$( "#effect" ).load(fileload,{lessonid:lessonid,act:act});
$("#effect").show( "drop",
{direction: "right"}, 200 );
$("#effect").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) {
loadCKeditor(); //call the function after loading page
});
}, 100 );
};
function loadCKeditor()
{//you need to destroy the instance if already exist
if (CKEDITOR.instances['introduction'])
{
CKEDITOR.instances['introduction'].destroy();
}
CKEDITOR.replace('introduction').getSelection().getSelectedText();
}
});
===================== button for call the function ================================
<input type="button" name="button" id="button" onclick="runEffect('lesson.php','','add')" >
Its pretty simple. In my case, I ran the below jquery method that will destroy ckeditor instances during a page load. This did the trick and resolved the issue -
JQuery method -
function resetCkEditorsOnLoad(){
for(var i in CKEDITOR.instances) {
editor = CKEDITOR.instances[i];
editor.destroy();
editor = null;
}
}
$(function() {
$(".form-button").button();
$(".button").button();
resetCkEditorsOnLoad(); // CALLING THE METHOD DURING THE PAGE LOAD
.... blah.. blah.. blah.... // REST OF YOUR BUSINESS LOGIC GOES HERE
});
That's it. I hope it helps you.
Cheers,
Sirish.
This functions works for me in CKEditor version 4.4.5, it does not have any memory leaks
function CKEditor_Render(CkEditor_id) {
var instance = CKEDITOR.instances[CkEditor_id];
if (CKEDITOR.instances.instance) {
CKEDITOR.instances.instance.destroy();
}
CKEDITOR.replace(CkEditor_id);
}
// call this function as below
var id = 'ckeditor'; // Id of your textarea
CKEditor_Render(id);
CKeditor 4.2.1
There is a lot of answers here but for me I needed something more (bit dirty too so if anyone can improve please do). For me MODALs where my issue.
I was rendering the CKEditor in a modal, using Foundation. Ideally I would have destoryed the editor upon closing, however I didn't want to mess with Foundation.
I called delete, I tried remove and another method but this was what I finally settled with.
I was using textarea's to populate not DIVs.
My Solution
//hard code the DIV removal (due to duplication of CKeditors on page however they didn't work)
$("#cke_myckeditorname").remove();
if (CKEDITOR.instances['myckeditorname']) {
delete CKEDITOR.instances['myckeditorname'];
CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
} else {
CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
}
this was my method to return my specific formatting, which you might not want.
function GetCKEditorSettings()
{
return {
linkShowAdvancedTab: false,
linkShowTargetTab: false,
removePlugins: 'elementspath,magicline',
extraAllowedContent: 'hr blockquote div',
fontSize_sizes: 'small/8px;normal/12px;large/16px;larger/24px;huge/36px;',
toolbar: [
['FontSize'],
['Bold', 'Italic', 'Underline', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink'],
['Smiley']
]
};
}
Try this:
for (name in CKEDITOR.instances)
{
CKEDITOR.instances[name].destroy(true);
}

How to have a javascript callback executed after an update panel postback?

I'm using a jQuery tip plugin to show help tips when the user hovers certain elements of the page.
I need to register the plugin events after the page is loaded using css selectors.
The problem is I'm using an ASP.NET Update Panel and after the first postback, the tips stop working because the update panel replaces the page content but doesn't rebind the javascript events.
I need a way to execute a javascript callback after the Update Panel refreshes its content, so I can rebind the javascript events to have the tips working again.
Is there any way to do this?
Instead of putting your jQuery code inside of $(document).ready(), put it inside
function pageLoad(sender, args) {
...
}
pageLoad is executed after every postback, synchronous or asynchronous. pageLoad is a reserved function name in ASP.NET AJAX that is for this purpose. $(document).ready() on the other hand, is executed only once, when the DOM is initially ready/loaded.
See this Overview of ASP.NET AJAX client lifecycle events
The pageLoad didn't work. I used this instead:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);
function pageLoaded() {
}
This is probably far from the most elegant solution, but its a solution nonetheless:
public class UpdatePanel : System.Web.UI.UpdatePanel
{
/// <summary>
/// Javascript to be run when the updatepanel has completed updating
/// </summary>
[Description("Javascript to be run when the updatepanel has completed updating"),
Category("Values"),
DefaultValue(null),
Browsable(true)]
public string OnUpdateCompleteClientScript
{
get
{
return (string)ViewState["OnUpdateCompleteClientScript"];
}
set
{
ViewState["OnUpdateCompleteClientScript"] = value;
}
}
protected override void OnPreRender(System.EventArgs e)
{
base.OnPreRender(e);
if(!string.IsNullOrEmpty(this.OnUpdateCompleteClientScript))
Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID, string.Concat("Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args){for(var panelId in sender._updatePanelClientIDs){if(sender._updatePanelClientIDs[panelId] == '", this.ClientID, "'){", this.OnUpdateCompleteClientScript, "}}});"), true);
}
}
Use it like this:
<uc:UpdatePanel OnUpdateCompleteClientScript="alert('update complete');">
<!-- stuff in here -->
</uc:UpdatePanel>
Of course you'll need to register the custom control in youre webconfig or page to use it like this.
Edit: also, have you looked at jquery.live?
If you want to do specific operations before and after the UpdatePanel has loaded, you can override BeginPostbackRequest and EndPostbackRequest like so:
var postbackControl = null;
var updatePanels = null;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginPostbackRequest);
prm.add_endRequest(EndPostbackRequest);
function BeginPostbackRequest(sender, args) {
prm._scrollPosition = null;
postbackControl = args.get_postBackElement();
postbackControl.disabled = true;
updatePanels = args._updatePanelsToUpdate;
// do your stuff
}
function EndPostbackRequest(sender, args) {
// do your stuff
postbackControl.disabled = false;
postbackControl = null;
updatePanels = null;
}
This is very handy if you want to process only HTML that was delivered by the update panel. Some operations require more resources and it would be overkill to process the whole DOM tree on pageLoad.
Use pageLoaded event and check whether callback or postback:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(function (sender, args) {
if (args._panelsUpdated && args._panelsUpdated.length > 0) {
//callback;
}
else {
//postback;
}
});

Categories

Resources