TinyMCE set content with html() after jqGrid is loaded - jqgrid

I have jqGrid and the TinyMCE editor inside my page.
After the grid is loaded I'm selecting the first row.
In the onSelectRow: function I set the editor value with $('#id').html(value_);. The value is a value inside one of the row cells.
My problem is when the page is loaded for the first row selection I can see the value inside the editor only for 1 second and then it disappears. (When I select the row onclick I can see the value, even if I refresh the page I can see it. It is not working, only for the first time.)
This is my code:
TinyMCE:
$('#tinymc_id.tinymce').tinymce({
theme : "advanced",
theme_advanced_buttons1 : "cut,copy,paste,|,bold,italic,underline,|,undo,redo,|,justifyleft,justifycenter,justifyright,justifyfull,|" ,
theme_advanced_buttons2 : "formatselect,fontselect,fontsizeselect,|,forecolor,backcolor,|",
theme_advanced_buttons3 : "",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
plugins : "paste"
init_instance_callback : myCustomInitInstance
});
function myCustomInitInstance(ed)
{
var s = ed.settings;
var realID = ed.id;
tinymce.dom.Event.add(ed.getWin(), 'focus', function(e) {
if($(realID)) {
}
});
tinymce.dom.Event.add(ed.getWin(), 'blur', function(e) {
if($(realID)) {
}
});
}
The jqGrid code:
onSelectRow: function(id)
{
save_row(lastSel);
grid.editRow(id,false,'','','','','','','');
jQuery ('#' + id + '_cell1').focus();
lastSel=id;
var _text = grid.getCell(id , "cell2");
$('#tinymc_id').html(_text);
},
loadComplete:function()
{
set_selected_row(1);
}
What is the problem? How can I solve it?

The problem here is that you probably set the textareas content using html(). But the editor is located inside an iframe (where the textareas content gets showed on init). To set the editor content better use
tinymce.get(editor_id).setContent(html_content);

$.each($('textarea'),function() {
if($(this).val() != "") {
var value = $(this).val();
$(this).html(value)
}
});
try this one if its working

Related

How to force CKEditor to process widgets when setting the HTML of an element

I have create a simple CKEditor widget that highlights the elements that have the class "pink".
I have also added a "Pinkify" button to the toolbar, which replaces the HTML of the selected element with some other elements that have the class "pink".
What I observe when I click the button is that widgets are not created for the freshly inserted elements. However, when I toggle between Source mode and WYSISYG mode, the widgets get created.
See the jsfiddle and its code:
CKEDITOR.replace('ck', {
allowedContent: true,
extraPlugins: 'pink'
});
CKEDITOR.plugins.add('pink', {
requires: 'widget',
init: function(editor) {
editor.widgets.add('pinkwidget', {
upcast: function(element) {
return element.hasClass('pink');
}
});
editor.addCommand('pinkify', {
editorFocus: 1,
exec: function(editor) {
var selection = editor.getSelection(),
selectedElement = selection.getStartElement();
if (selectedElement) {
selectedElement.setHtml("Let's have some <span class=\"pink\">pink</span> widget here!");
editor.widgets.checkWidgets(); // needed?
}
}
});
editor.ui.addButton('pinkify', {
label: 'Pinkify',
command: 'pinkify'
});
},
onLoad: function() {
CKEDITOR.addCss('.cke_widget_pinkwidget { background: pink; }');
}
});
I am aware of this question on Stackoverflow, but I can't get it to work with setHtml called on an element. Can you suggest how to modify the code so that widgets get created as soon as the HTML is updated?
According to the CKEditor team, it is normal that CKEDITOR.dom.element.setHtml does not instanciate widgets (see Widgets not initialised after calling setHtml on an element).
So the workaround they gave me was to rewrite the code that insert HTML in place of the selected element to:
if (selectedElement) {
selectedElement.setHtml("");
editor.insertHtml("Let's have some <span class=\"pink\">pink</span> widget here!");
}
For those like me who didn't know, editor.insertHTML inserts HTML code into the currently selected position in the editor in WYSIWYG mode.
Updated jsFiddle here.

CKEditor not editable in IE11 after ajax call

Example:
Jsfiddle
If the page is loaded the first time, the CKEditor is working right and the value of the editor can be edited. After hitting the button "ajax" which is calling the following function (cursor must be in the editor field):
function ajax_call() {
var html = "<textarea id=\"textarea\"><p>test 1</p><p>test 2</p><p>test 3</p></textarea><script type='text/javascript'>jQuery(document).ready(function() { ckEditor('textarea'); });<\/script>";
$.post("/echo/html/", { html: html }, function(data){
jQuery('#target').html(data);
});
}
it isn't possible to click on the text in IE11 to edit the value. Clicking beyond the text or left of it enabels the editor again.
Looks like creation of new textarea after CKEDITOR is initiated brakes editor in IE. Though i just tried to set data directly on instance of CKEDITOR and it worked fine,rather than creating new textarea tag.
function ajax_call() {
var html = "<p>test 4</p><p>test 5</p><p>test 6</p>";
$.post("/echo/html/", { html: html }, function(data){
//jQuery('#target').html(data); <-- Removed from original
CKEDITOR.instances['textarea'].setData(data)// <-- Added
});
}
function ckEditor(id) {
CKEDITOR.replace(id, {
language : 'de',
});
}
jQuery(document).ready(function() {
ckEditor('textarea');
});
Here is working example:
http://jsfiddle.net/2wq86gqs/15/

OpenLayers events issue, featureover and onselect

I have a strange problem with the use of vector layers events.
Here is snipped of my code:
var options = {
projection : "EPSG:3857",
displayProjection : "EPSG:4326",
numZoomLevels : 18,
//after delete this part below of option everything works good
eventListeners: {
featureover: function(e) {
document.getElementById("output").innerHTML="ok';
}}};
map = new OpenLayers.Map('map', options);
w_parcels = new OpenLayers.Layer.Vector("PARCELS", {
styleMap : style_parcels,
projection : "EPSG:3857",
strategies : [ new OpenLayers.Strategy.Fixed() ],
protocol : new OpenLayers.Protocol.HTTP({
url : "parcels.php",
format : new OpenLayers.Format.GeoJSON()})
});
map.addLayers([osm,w_parcels]);
selectControl = new OpenLayers.Control.SelectFeature(w_parcels, {
clickout: false,
multiple: true,
onSelect : onFeatureSelect,
onUnselect : onFeatureUnselect,
toggleKey: "ctrlKey" // ctrl key removes from selection
});
selectControl.handlers.feature.stopDown = false;
map.addControl(selectControl);
selectControl.activate();
map.addControl(new OpenLayers.Control.ScaleLine());
function onFeatureSelect(feature) {
console.log('it works');
}
In this code event onselect dosen't work always when I click on feature on the layer(sometimes I have to do double click).
If I delete eventListeners from options , the onselect works perfect, I mean always when I click feature on the layer.
What is wrong in my code? Is the possibility to resolve this conflict betwween eventListeners an onselect?
Seems like, Event featureover masks the select control as that function will executes first while you select, as you must mouse over the Vector Layer for clicking it. But if the functionality is limited to select and mouse-over vector layer. Then you can use something like-
eventListeners: {
featureover: function(e) {
//behavior for hover events
},
featureout: function(e) {
//behavior for mouse out events
},
featureclick: function(e) {
//behavior for click events
}
}
Hope this helps.

AngularJS directive toggle menu preventing default for other directive

So I made a directive for a toggle (drop down) menu in AngularJS. I used the directive for multiple items within the page but I have a small problem. When one item is open and I click another one I want the previous one to close. The event.preventDefault and event.stopPropagation stops the event for the previous item and doesn't close it. Any ideas on how to fix this? Is there a way to perhaps only stop the event within the scope?
app.directive('toggleMenu', function ($document) {
return {
restrict: 'CA',
link: function (scope, element, attrs) {
var opened = false;
var button = (attrs.menuButton ? angular.element(document.getElementById(attrs.menuButton)) : element.parent());
var closeButton = (attrs.closeButton ? angular.element(document.getElementById(attrs.closeButton)) : false);
var toggleMenu = function(){
(opened ? element.fadeOut('fast') : element.fadeIn('fast'));
};
button.bind('click', function(event){
event.preventDefault();
event.stopPropagation();
toggleMenu();
opened = ! opened;
});
element.bind('click', function(event){
if(attrs.stayOpen && event.target != closeButton[0]){
event.preventDefault();
event.stopPropagation();
}
});
$document.bind('click', function(){
if(opened){
toggleMenu();
opened = false;
}
});
}
};
And here's a Fiddle: http://jsfiddle.net/JknUJ/5/
Button opens content and content should close when clicked outside the div. When clicked on button 2 however content 1 doesn't close.
Basic idea is that you need to share the state between all your dropdown submenus, so when one of them is shown, all others are hidden. The simpliest way of storing state (such as opened or closed) are... CSS classes!
We'll create a pair of directives - one for menu, and another for sumbenu. It is more expressive that just divs.
Here is out markup.
<menu>
<submenu data-caption="Button 1">
Content 1
</submenu>
<submenu data-caption="Button 2">
Content 2
</submenu>
</menu>
Look how readable is it! Say thanks to directives:
plunker.directive("menu", function(){
return {
restrict : "E",
scope : {},
transclude : true,
replace : true,
template : "<div class='menu' data-ng-transclude></div>",
controller : function ($scope, $element, $attrs, $transclude){
$scope.submenus = [];
this.addSubmenu = function (submenu) {
$scope.submenus.push(submenu);
}
this.closeAllSubmenus = function (doNotTouch){
angular.forEach($scope.submenus, function(submenu){
if(submenu != doNotTouch){
submenu.close();
}
})
}
}
}
});
plunker.directive("submenu", function(){
return {
restrict : "E",
require : "^menu",
scope : {
caption : "#"
},
transclude : true,
replace : true,
template : "<div class='submenu'><label>{{caption}}</label><div class='submenu-content' data-ng-transclude></div></div>",
link : function ($scope, $iElement, $iAttrs, menuController) {
menuController.addSubmenu($scope);
$iElement.bind("click", function(event){
menuController.closeAllSubmenus($scope);
$iElement.toggleClass("active");
});
$scope.close = function (){
$iElement.removeClass("active");
}
}
}
});
Look thar we restricted them to HTML elements (restrict : "E"). submenu requires to be nested in menu (require : "^menu"), this allows us to inject menu controller to submenu's link function. transclude and replace controls the position of original markup in compiled HTML output (replace=true means that original markup will be replaced with compiled, transclude inserts parts of original markup to compiled output).
When we've done with this, we just say to menu close all your child menus! and menu iterates over submenus, forcing them to close.
We are adding childs to menu controller in addSubmenu function. It is called in submenus link function, thus every compiled instance of submenu adds itself to menu. Now, closing all submenus is as easy as iterating over all children, this is done by closeAllSubmenus in menu controller.
Here is a full Plunker to play with.

Add a hyperlink in one of the columns in JQGrid and clicking on Hyperlink should open a new window

I have a jqgrid with certain columns and I need hyperlink in one of the columns, clicking on the hyperlink should open a new window, basically call a window.open().
Also when I call the window.open(), I need the hyperlink column value.
Please provide me with some sample code.Anyhelp would be highly appreciated.
Thanks
Oleg, I tried the below code and it is throwing error "object expected" in load().
{name:'FileName', FileName:'price', width:60, align:"center", formatter:returnMyLink}
function returnMyLink(cellValue, options, rowdata)
{
return "<a href='javascript:load();'>Open Window</a>";
}
function load()
{
var guid = 'CEF9C407-2500-4619-95E3-8E6227B65954';
window.open ('/irj/servlet/prt/portal/prtroot/com.medline.medpack.ExcelViewerPL.ExcelViewer?report=CustomerBenefit&reportId='+guid );
}
I did try the document.delegate to capture the a href event.
$(document).delegate('#CustomerSavingsView .jqgrow td a[href="#"]', 'click',function()
{
alert('test');
}
I was not able to capture this event either.
Sorry Im new to Jquery. Please correct me if Im wrong.
Thanks
This is how I solved it. In the grid complete event added the following code.
hl = "<a href='#Test' target='_blank' id='hlink"+cl+"'>Test</a>";
And then added a event handler for it.
$(document).delegate('#CustomerSavingsView .jqgrow td a[href*="#Test"]', 'click', function ()
{
var guid = 'CEF9C407-2500-4619-95E3-8E6227B65954';
window.open('/irj/servlet/prt/portal/prtroot/com.medline.medpack.ExcelViewerPL.ExcelViewer?report=CustomerBenefit&reportId='+guid );
}
This solved the purpose. Thanks again Oleg and Walter.
maybe this will be help:
in colModel,define a col: {name:'test',formatter:linkformatter}
and in javascript create a function named linkformatter which returns a link;
like:
function linkformatter( cellvalue, options, rowObject){
return '<a href='xxxxxx' />';
}
The predefined formatter 'showlink' can be used to create the link in the grid column. You can use target property of the formatoptions options to define target of the link.
First declare the Jquery JQGrid column definition as follows
colModel: [{ name: 'Notes/Memos', width: "5", sortable: true, classes: 'ellip', resizable: false, formatter: MethodFormatter }]
The formatter property takes the method name which is invoked with the three parameters which internally having the cells value and its id and the following method returns the hyperlink.
function MethodFormatter(cellValue, options, rowObject) {
var selectedRowId = options.rowId;
return '<a href="javascript:MethodJS(' + selectedRowId + ')" style="color: #3366ff" id="' + selectedRowId + '" >' + cellValue + '</a>';}
The following JS Function is invoked after clicking the hyperlink which opens up another page in a window.
function MethodJS(selectedRowId) {
document.location.href = "ViewContact.aspx?NoteID=" + selectedRowId;
}
My approach involves fewer lines of code and gives the solution asked for. In my grid, a column called Project Number is formatted as a hyper link. It opens a new page and passes the project number as a parameter.
colNames: ["Project #", ...],
colModel: [
{ name: 'Project Number', index: 'Project Number', width: 80, key: true, formatter: 'showlink', formatoptions: { baseLinkUrl: 'Details.aspx', target: '_new' } },
Note where I have key: true. Without this, the url returns the row number. The url returned is http://localhost:57631/Details.aspx?id=2103
I'm using jqGrid version 5.0.1
This is my pattern. As I said, it is much more code than Oleg's suggestion of using the showlink formatter, but it is more customizable.
// bind a live event handler to any elements matching the selector 'a.linkWindowOpener'
$('a.linkWindowOpener').live('click', linkWindowOpener);
// colModel settings
{ name: 'ItemDescription', index: 'ItemDescription', formatter: itemDescription_formatter, unformat: itemDescription_unformatter },
// custom formatter to create the hyperlink
function itemDescription_formatter(cellvalue, options, rowObject) {
var html = '';
var itemID = rowObject.itemID;
var itemDescription = cellvalue;
var a = $('<a>')
.attr('href', '/Forms/WorkOrder/ViewItem.aspx?ItemID=' + itemID)
.attr('data-itemDescription', itemDescription )
.html(itemDescription)
.addClass('linkWindowOpener');
html = a.getHtml();
return html;
}
// unformatter to return the raw value
function itemDescription_unformatter( cellvalue, options, cell) {
return $('a', cell).attr('data-itemDescription');
}
// event handler to call when clicking the hyperlink
function linkWindowOpener(event) {
event.preventDefault();
event.stopPropagation();
var o = $(event.currentTarget);
var url = o.attr('href');
window.open(url);
return false;
}
// jQuery extenision function I wrote to get the HTML of an element
// returns the HTML of an element. It works by wrapping the element
// inside a DIV and calling DIV.html(). It then returns the element back to
// it's original DOM location
jQuery.fn.getHtml = function () {
var elm = $(this[0]);
// create a div
var div = $('<div>');
// append it to the parent of the target element
elm.parent().append(div);
// append the element to the div
div.append(elm);
// get the html of the div
var html = div.html();
// move element back to its parent
div.parent().append(elm);
div.remove();
return html;
}

Resources