Save edited inline text from CKEditor 4 asp net - asp.net-mvc-3

I am trying to implement CKEditor 4 into an ASP NET website that I am working on, but I cannot figure out how I would save the edited material from the inline editor I know how to do it with the the old version, but I just don't understand the process for this.
I have looked in the forums... There is not v4 forum.
I looked in for the documentation.... Couldn't find it.
I have a feeling that this is a simple task, but I just don't know how.

You can get your data with CKEDITOR.instances.editor1.getData(). Then you can send it via AJAX or store it as a value of some input field. To do this periodically, follow this method:
CKEDITOR.disableAutoInline = true;
var editor = CKEDITOR.inline( 'editable' );
var savedData, newData;
function saveEditorData() {
setTimeout( function() {
newData = editor.getData();
if ( newData !== savedData ) {
savedData = newData;
// Send it with jQuery Ajax
$.ajax({
url: 'yourUrl',
data: savedData
});
// Or store it anywhere...
// ...
// ...
}
saveEditorData();
}, 500 );
};
// Start observing the data.
saveEditorData();
You can also observe the submit event and update some (hidden) form field with your data.
Have fun!

Are you trying to get it with AJAX or send with a form? The value of for example the top right inline editor area with Lorem Ipsum can be gotten like in the older version with simply
CKEDITOR.instances.editor1.getData().
In the XHTML output example they have a simple form that seems to work and I believe that using an (static) inline editor is just the same.
If you transform elements into editors inline dynamically, I would try to bind to the submit event and before submitting loop through all CKEDITOR.instances, get their data into hidden from fields. As for the hidden field naming or identifying which hidden field corresponds to which dynamic editor you'll have to figure out yourself :)

Related

jQuery - How to call/bind jquery events for elements added by ajax?

I'm working on an implementation of the jQuery plugin Tag-it! with a product entry form for assigning attributes to products of different type (laptops, tv's, gadgets etc).
The concept is the following:
When adding a new product, first, the user selects the product category from a dropdown for the product being added and a jQuery .change() event is triggered making an ajax call to get all the attributes that are related to that category. For example, if Im adding a TV i want my ajax call to populate 3 inputs for inches, panel type, hdmi whereas, if i'm adding a laptop I want those inputs to be cpu, ram, hdd, screen etc. Tag-it! works with a list of words (in my case, attributes) and an input field for choosing the set of words.
In my case, for each type of attributes I want to populate a separate input field and assign/bind it to/apply tagit plugin (sorry, I dont know how else to explain it).
Javascript:
<script src="../js/tag-it.js" type="text/javascript" charset="utf-8"></script>
<script>
$(function(){
// Sample1: var sampleTags1 = ["red", "green", "blue"];
// Sample2: var sampleTags2 = ["lcd", "plasma", "tft"];
var sampleTags1 = [<?=createTags('name', 'tags', 1)?>];
// createTags($name, $tags, $id) is a PHP function that returnss a list of tags for a given attribute
// Question 1: how do I place this here after a new input is added to the DOM?
$('#myTags').tagit();
//Question 2: for each input added to the DOM I need also to add this block in the javascript:
$('#allowSpacesTags1').tagit({itemName: 'item1', fieldName: 'tags1',
availableTags: sampleTags1, allowSpaces: true
});
$('#removeConfirmationTags').tagit({
availableTags: sampleTags,
removeConfirmation: true
});
});
$(document).ready(function() {
$('#cat_id').change(function(){
$.post('../includes/ajax.php', {
cat_id : $(this).find("option:selected").attr('value')}, function(data) {
$("#tagholder").html(data);
});
});
});
</script>
Ajax returns the following for each call:
<ul id="allowSpacesTags'.$row['ctid'].'"></ul> // $row['ctid'] is the ID for that attribute
which represents the input field for entering the tags/attributes.
Before there's any misunderstanding, I'm not asking how to do this in PHP.
My question is about the way I can dynamically add a var like sampleTags1 and also call the tagit() for each new input that is added to the DOM by ajax. I'll try to give any required information if my question isn't clear enough.
Please look at the questions in the code comments. Thanks!
http://api.jquery.com/live/
with .live( events, handler(eventObject) )
you don't need to attach or re-attach events when content is added dynamically
EDIT
i've just notticed that live is deprecated, instead you should use
.on()
http://api.jquery.com/on/

How to bind events to element generated by ajax

I am using RenderPartial to generate CListView and all the contents generated properly and good pagination is working fine too. But when I added my custom JS to elements generated by the CListview it works fine for the the fist page content but when i use pagination and click to page 2 then the JS binding fails.
Is there any other way to bind custom event to elements generated in YII CListview I had tried using live, and on nothing work for me here is my js file.
I think I have to call my function on every ajax load in but how can I achieve in yii
This is the script I am using to update ratings on server with button click and this the element for which these forms and buttons are defined are generated by CListview in yii
$(document).ready(function(){
$('form[id^="rating_formup_"]').each(function() {
$(this).live('click', function() {
alert("hi");
var profileid= $(this).find('#profile_id').attr('value');
var userid= $(this).find('#user_id').attr('value');
console.log(userid);
var data = new Object();
data.profile_id=profileid;
data.user_id=userid;
data.liked="Liked";
$.post('profile_rating_ajax.php', data, handleAjaxResponse);
return false;
});
});
});
You can also try CGridView.afterAjaxUpdate:
'afterAjaxUpdate' => 'js:applyEventHandlers'
The $.each method will loop only on existing elements, so the live binder will never see the ajax-generated content.
Why don't you try it like this:
$(document).ready(function(){
$('form[id^="rating_formup_"]').live('click', function() {
alert("hi");
var profileid= $(this).find('#profile_id').attr('value');
var userid= $(this).find('#user_id').attr('value');
console.log(userid);
var data = new Object();
data.profile_id=profileid;
data.user_id=userid;
data.liked="Liked";
$.post('profile_rating_ajax.php', data, handleAjaxResponse);
return false;
});
});
This problem can be solved by two ways:
Use 'onclick' html definitions for every item that is going to receive that event, and when generating the element, pass the id of the $data to the js function. For example, inside the 'view' page:
echo CHtml::htmlButton('click me', array('onclick'=>'myFunction('.$data->id.')');
Bind event handlers to 'body' as the framework does. They'll survive after ajax updates:
$('body').on('click','#myUniqueId',funcion(){...});

Auto Complete for Generic list MVC 3

I have a Generic list in my Model class. I want to have a textbox with autocomplete in my view which fills data from the generic list. How can I do this?.
For this you will need
Function on server side which will return list of matching data and will accept string entered by the user.
Something like this
public JsonResult AutoComplete(string input)
{
//Your code goes here
}
In the View, for the text box you need to bind KeyDown event. You can take help of jQuery for this. On key down handler you will make an Ajax call to the function you have defined in the Controller. Some thing like this:
$.ajax({
url: '#Url.Action("AutoComplete", "ControllerName")',
data: 'input=' + sampleInput,
success: function (data) {
//Show the UL drop down
},
error: function (data) {
// Show Error
}
});
In response you will get list of strings, which you will need to bind to some html element like "UI". Once done, display this UI with proper CSS below the text box. Using jQuery, you can retrieve the pixel location of text box too.
You can not use Asp.Net Auto Complete box in your project as you are developing app in MVC (no viewstate). I hope you get the idea.
You can use JQuery Autocomplate.
To fill the list, you can populate the data from you object.
I can't remember the exact Razor syntax, but you can refer to this:
//data is your Model object of type List<String>
var listString = [#foreach(x in data) { '#x',}];
$( "#dataList" ).autocomplete({
source: listString
});
<input id="dataList">
JQuery Autocomplte
http://jqueryui.com/demos/autocomplete/
This is client side auto complete, I can provide server side if you need.

Loading dynamic "chosen" select elements

I am using the jQuery plugin chosen (by Harvest). It is working fine on (document).ready, but I have a button that, when clicked, uses ajax to dynamically create more select objects that I want to use the "chosen" feature. However, only the original select elements have the "chosen" features, and the new (dynamically created) do not work. I am using jQuery.get to append the new elements. Here is a sample of the code:
jQuery(".select").chosen();//this one loads correctly
jQuery("#add-stage").click(function() {
jQuery.get('/myurl',{},function(response) {
//response contains html with 2 more select elements with 'select' class
jQuery('#stages').append(response);
jQuery(".select").chosen();//this one doesn't seem to do anything :-(
});
});
I was thinking that I need a .live() function somewhere, but I haven't been able to figure that out yet. Any help is much appreciated!
Note - I am not trying to dynamically load new options, as specified in the documentation using trigger("liszt:updated");
Ensure that the response elements have the select class.
console.log( response ); // to verify
May also be a good idea to only apply the plugin to the new element(s).
jQuery(".select").chosen();
jQuery("#add-stage").click(function() {
jQuery.get('/myurl',{},function(response) {
console.log( response ); // verify the response
var $response = $(response); // create the elements
$response.filter('.select').chosen(); // apply to top level elems
$response.find('.select').chosen(); // apply to nested elems
$response.appendTo('#stages');
});
});
Also, if /myurl is returning an entire HTML document, you may get unpredictable results.
after you code (fill the select) .write this
$(".select").trigger("chosen:updated");
I had a similar problem with Chosen. I was trying to dynamically add a new select after the user clicks on a link. I cloned the previous select and then added the clone, but Chosen options would not work. The solution was to strip the Chosen class and added elements, put the clone in the DOM and then run chosen again:
clonedSelect.find('select').removeClass('chzndone').css({'display':'block'}).removeAttr('id').next('div').remove();
mySelect.after(clonedSelect);
clonedSelect.find('select').chosen();
one way you can use chosen with ajax:
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
cache: false,
data: search
}).done(function(data){
$.each(data, function(){
$('<option />', {value: this.value, text: this.text}).appendTo(selectObj);
});
chosenObj.trigger('liszt:updated');
});
where selectObj is particular select object
But ...
Chosen is implemented very bad.
It has several visual bugs, like: select some option, then start searching new one, then remove selected and the keep typing - you will get 'Select some options' extended like 'Select some options search value'.
It doesn't support JQuery chaining.
If you will try to implement AJAX you will notice, that when you loose focus of chosen, entered text disappears, now when you will click again it will show some values.
You could try to remove those values, but it will be a hard time, because you cannot use 'blur' event, because it fires as well when selecting some values.
I suggest not using chosen at all, especially with AJAX.
1.- Download Livequery plugin and call it from your page.
2.- Release the Kraken: $(".select").livequery(function() { $(this).chosen({}); });
This is an example of Chosen dynamically loading new options form database using ajax every time Chosen is clicked.
$('.my_chonsen_active').chosen({
search_contains:true
});
$('.my_chonsen_active').on('chosen:showing_dropdown', function(evt, params){
id_tosend=$(this).attr("id").toString();
$.get("ajax/correspondance/file.php",function(data){
$('#'+id_tosend).empty();
$('#'+id_tosend).append(data);
$('#'+id_tosend).trigger("chosen:updated");
});
});

TinyMCE not working in http request xhr ajax generated page

So i I have a page that contains links that call an httpRequest. The request calls a php file that grabs data from mysql and pre populates a form which is then returned to the browser/webpage. My problem is that when the page is returned to the browser via the httpRequest/ajax the text area does not display the tinymce editor, it just displays a normal text area. It looks like my request and ajax is working fine the text area just doesn't have the tinycme editor on it.
When i don't use ajax it works fine but when i put it in a separate file and call it via ajax it doesn't bring in the tinymce editor.
Does anyone know how to fix this problem so that my ajax generated page displays the text area with the tinymce editor. Thank you.
Lets presume that your thinyMCE instance is initialized with code below
// initialize tinyMCE in page
tinyMCE.init({
mode: "textareas",
theme: "advanced"
});
and you have some kind of button somewhere in the page. For purpose of this tip, i will not give it any ID but you may. Now, using jQuery you can easily attach event handler to that button which will call through AJAX your server and take content which you want to put tinyMCE editor. Code which will do such job would look somehow like below.
$(function() {
$("button").bind("click", function() {
var ed = tinyMCE.get('content');
ed.setProgressState(1); // Show progress
$.getJSON('/page/12.json', { /* your data */
}, function(data) {
ed.setProgressState(0); // Hide progress
ed.setContent(data["body"]);
}
});
});
});
You can see that on button.click ajax will call url /page/12.json which will return JSON as response. bare minimum of that response could be:
{
title: "Page title",
body: "<html><head><title>Page title</title>......</html>"
}
I attached anonymous function as callback which will handle response from server. and hide progress indicator which is shown before ajax call.
About JSON
JSON is shorten of JavaScript Object Notation. It is JavaScript code!!! So don't be confused about it. Using JSON you can make javascript object which can have attributes you can use later in your code to access particular peace of data which that object "holds". You can look at it as some kind of data structure if it is easier to you.
Anyway, to show you how this JSON can be created by hand look at examples below
var data = new Object();
data.title = "Page title";
data.body = "<html....";
or
var data = {
title: "page title",
body: "<html...."
};
it is very same thing.
If you want to learn more about JSON point your browser to http://json.org.
===== alternative =====
Alternative to json solution could be just plane ajax call to server and response can be plain HTML (from your question I can assume that you have something like this already). So instad of calling $.getJSON you can use $.get(url, callback); to do same thing. The code at the top of my answer will not dramatically change. Instead of geting JSON in response you will get string which is HTML.
----------- BOTTOM LINE -------
I prefer JSON since it can be easily extended later with other attributes, so there is no painful code changes later ;)
Problem here will be that when you return the full page and render it using the ajax response, your tinymce instance has not been shut down before.
In order to do this you can call this small piece of code before you render the ajax response:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
In this case the editor should initialize correctly. You are not allowed to initialize a tinymce editor with the same id before shutting the first one down.
Strangely i ran into this problem yesterday. Following code should work, but YMMV. Trick is to use the correct steps in ajax events. I used the Regular TinyMCE and made use of the jQuery library already included.
Following goes into your tinyMCE initialization tinyMCE.init() . All of the below block should be outside the document.ready.
myTinyInit = {
//.......All essential keys/values ...........
setup : function(ed) {
ed.onChange.add(function( ed ) {
tinyMCE.triggerSave();
}) }
//.....................
};
// Init the tinyMCE
tinyMCE.init(myTinyInit);
This ensures the content is being saved regularly onto the textarea that holds the value. Next step is setting up the request events.
Normally tinyMCE mceAddControl before the ajax post and mceRemoveControl after the ajax success should do the trick. But I found that often does not work.
I used the form as the jQuery selector in my case.
jQuery( '.myForm' )
.find( 'textarea#myTextArea' )
.ajaxStart(function() {
// If you need to copy over the values, you can do it here.
// If you are using jQuery form plugin you can bind to form-pre-serialize event instead.
// jQuery( this ).val( tinyMCE.get( jQuery( this ).attr( 'id' )).getContent() );
}).ajaxSend( function() {
// ! - step 2
// My case was multiple editors.
myEds = tinyMCE.editors;
for( edd in myEds ) {
myEds[ eds ].remove();
}
// tinyMCE.get( 'myTextarea' ).remove();
// strangely mceRemoveControl didnt work for me.
// tinyMCE.execCommand( 'mceRemoveControl', false, jQuery( this ).attr('id'));
}).ajaxSuccess(function() {
// Now we got the form again, Let's put up tinyMCE again.
txtID = jQuery( this ).attr( 'id' );
// ! - step 3
tinyMCE.execCommand( 'mceAddControl', false, txtID );
// Restore the contents into TinyMCE.
tinyMCE.get( txtID ).setContent( jQuery( this ).val());
});
Problems i came across :
Using mceRemoveControl always gave me r is undefined error persistently.
If you get a blank tinyMCE editor, check the DOM whether the ID of the textarea is replaced with something like mce_02, this means that TinyMCE is being initialized again or something is wrong with the order. If so, the tinyMCE is duplicated with each save.
if you are new to JS, I recommend using jQuery with the form plugin, it might be easier for you. But do use the regular non-jquery tinyMCE, as it is well documented.
I fixed this problem by recalling the function after the ajax call. In this part of my ajax:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("Content").innerHTML=xmlhttp.responseText;
tinymce();
Now it works fine.

Resources