I have created a control using RadEditor and image manager (follow link: http://www.sitefinity.com/developer-network/forums/developing-with-sitefinity/radeditor-image-manager).
When user click button "Insert an image" it show "ImageLibraryDialog" and user can select an image as image-1.
http://www.sitefinity.com/clientsfiles/e12f501e-37c1-6deb-a958-ff0000446526_image-1.png?sfvrsn=0
My problem is: How to append selected image to radEditor control when click button save in "ImageLibraryDialog".
Here is my code in .ascx designer:
<telerik:RadEditor ID="HtmlSocial" runat="server" Width="600px" ClientIDMode="Static" OnClientLoad="OnClientLoad"
ToolsFile="~/Extensions/RadEditor/ToolsFile.xml"
ContentFilters="EncodeScripts,FixUlBoldItalic,FixEnclosingP,IECleanAnchors,MozEmStrong,ConvertFontToSpan,ConvertToXhtml,IndentHTMLContent"
>
<ImageManager ViewPaths="~/Images" UploadPaths="~/Images" DeletePaths="~/Images" />
<MediaManager ViewPaths="~/Files" UploadPaths="~/Files" DeletePaths="~/Files" />
<FlashManager ViewPaths="~/Files" UploadPaths="~/Files" DeletePaths="~/Files" />
<DocumentManager ViewPaths="~/Files" UploadPaths="~/Files" DeletePaths="~/Files" />
<Content>
</Content>
</telerik:RadEditor>
And here is the script to open image library dialog:
<script type="text/javascript">
Telerik.Web.UI.Editor.CommandList["LibraryImageManager"] = function (commandName, editor, args) {
var editorArgs = editor.getSelectedElement();
//if (!editorArgs || !editorArgs.nodeName || typeof (editorArgs.nodeName) == "undefined" || editorArgs.nodeName != "A")
// editorArgs = editor.getSelection();
var myCallbackFunction = function (sender, args) {
alert(1);
debugger;
if (typeof(editorArgs.nodeName) != "undefined" && editorArgs.nodeName == "IMG")
args.parentNode.replaceChild(editorArgs, args);
else {
// InsertTextArea();
var cloned = args.cloneNode(true);
var div = args.ownerDocument.createElement("DIV");
div.appendChild(cloned);
editorArgs.pasteHtml(div.innerHTML);
}
};
editor.showExternalDialog(
'<%= ResolveUrl("~/Sitefinity/Dialog/MediaContentManagerDialog/?mode=Image")%>',
editorArgs,
750,
600,
myCallbackFunction,
null,
'ImageLibraryDialog',
true,
Telerik.Web.UI.WindowBehaviors.Close + Telerik.Web.UI.WindowBehaviors.Move,
false,
true);
};
function InsertTextArea() {
var editor = $find('<%=HtmlSocial.ClientID%>');
editor.set_html('<textarea id="myTableToFind" style="overflow:hidden; height: 300px; width: 500px;" border="none"></textarea>');
}
</script>
Please tell me how to append selected image to radEditor control when click button save in "ImageLibraryDialog".
Thanks you very much.
Related
I would like to prevent the pressing of ENTER if the kendo editor body has a certain height (to limit the max height of the editor field). But none of my tries worked.
<textarea data-role="editor"
data-bind="events: { keydown: onEditorKeyDown }">
</textarea>
viewModel.onEditorKeyDown = function (e) {
var key = e.keyCode;
if (key == 13) {
var editor = e.sender;
var body = editor.body;
var height = body.scrollHeight;
if (height > 195) {
?? //tried e.preventDefault(), return false etc.
}
}
};
I've managed to find two solutions. One is dirty hack and other doesn't match your requirements 100%. But both perform what is needed more or less.
New paragraph is added via embedded editor insertParagraph command which overrides default keydown logic. So the first solution is to temporary override this command using keydown and keyup events like this:
<textarea data-role="editor"
data-bind="events: { keydown: onEditorKeyDown, keyup: onEditorKeyUp }">
</textarea>
// this should probably be moved to viewModel, it's here for demo puproses only
var savedCommand;
var viewModel = kendo.observable({
html: null,
isVisible: true,
onChange: function() {
kendoConsole.log("event :: change (" + kendo.htmlEncode(this.get("html")) + ")");
}
});
viewModel.onEditorKeyDown = function (e) {
var key = e.keyCode;
if (key == 13) {
var editor = e.sender;
var body = editor.body;
var height = body.scrollHeight;
if (height > 195) {
savedCommand = editor.toolbar.tools.insertParagraph.command;
editor.toolbar.tools.insertParagraph.command = function() {};
}
}
};
viewModel.onEditorKeyUp = function (e) {
var key = e.keyCode;
if (key == 13) {
if (savedCommand) {
var editor = e.sender;
editor.toolbar.tools.insertParagraph.command = savedCommand;
savedCommand = undefined;
}
}
};
kendo.bind($("#example"), viewModel);
This works fine, but looks a bit ugly.
Other solution is to execute editor undo command if needed. It works too, but empty line always flickers for a moment:
<textarea data-role="editor"
data-bind="events: { keyup: onEditorKeyUp }"></textarea>
var viewModel = kendo.observable({
html: null,
isVisible: true,
onChange: function() {
kendoConsole.log("event :: change (" + kendo.htmlEncode(this.get("html")) + ")");
}
});
viewModel.onEditorKeyUp = function (e) {
var key = e.keyCode;
if (key == 13) {
var editor = e.sender;
var body = editor.body;
while (body.scrollHeight > 195) {
editor.exec('undo');
}
}
};
kendo.bind($("#example"), viewModel);
UPD: I've found event better solution. You can use execute event, see http://docs.telerik.com/kendo-ui/api/javascript/ui/editor#events-execute
Then check conditions and filter by command name to cancel insert of new paragraph:
execute: function(e) {
alert(e.name);
e.preventDefault();
}
I'm creating a firefox extension using Add-on SDK, which will display all the tab details including memory, title and url. I have tried to get the tab title using require("sdk/tabs"); tab package.
Below is the sample code:
popup.js
<body>
<ul>
<li>
Settings
</li>
</ul>
<script type="text/javascript" src="popup.js"></script>
</body>
popup.js
var tab_button = document.getElementById("tab_list");
tab_button.addEventListener("click", function() {
addon.port.emit("GET_TABS");
});
main file: index.js
const buttons = require("sdk/ui/button/action");
const { TogglePanel } = require("popupPanel");
var button = buttons.ActionButton({
id: "mem-tools",
label: "tabs info listing",
icon: {
"16": "./tab.png",
},
onClick: handleClick
});
let togglePanel = new TogglePanel();
function handleClick(state) {
togglePanel.panel.show({position:button});
}
Panel file: popupPanel.js
var Panel = require('sdk/panel');
var self = require('sdk/self');
var { MemoryHandler } = require('memory-handler');
var memoryHandler = new MemoryHandler();
function TogglePanel() {
this.panel = new Panel.Panel({
width: 150,
height: 200,
contentURL: self.data.url("popup.html")
});
this.panel.port.on("GET_TABS", function() {
memoryHandler.getAllTabs();
});
}
exports.TogglePanel = TogglePanel;
memory-handler.js
var tabs = require('sdk/tabs');
function MemoryHandler() {
return {
getAllTabs: () => {
for(let tab of tabs) {
console.log(tab.title);
}
}
}
}
exports.MemoryHandler = MemoryHandler;
This code only fetching all tab titles from the main window and child window, but not from all other new window's tabs which is opening using _blank attribute.
Note: we can easily recreate the issue just create an html page and use the below code:
Visit me
The page open using the "_blank" attribute is not coming under the tabs array.
Any help is appreciated.
Thanks in advance!!
We can get all the titles from all the window tabs by creating a custom array.
index.js
var memoryHandler = new MemoryHandler();
tabs.on('ready', function(tab) {
memoryHandler.addTabDetails({id: tab.id ,title: tab.title, url: tab.url});
});
If you want to get the title which is setting by using javascript after page load, you can inject a mutation observer code in the content script of tab
memory-handler.js
var presentTabs = []
function MemoryHandler() {
return {
addTabDetails: (tab_array) => {
presentTabs.push(tab_array);
}
}
}
exports.MemoryHandler = MemoryHandler;
I have this code:
function getArea (){
var area1 = document.getElementById('first');
var area2 = document.getElementById('adart');
if (area1.style.display.match("none") && area2.style.display.match("none"))
{
area1.style.display = 'block';
}
else
{
area1.style.display = 'none';
}
}
function getArea1 (){
var addArticle = document.getElementById('adart');
var area1 = document.getElementById('first');
if (addArticle.style.display.match("none") && area1.style.display.match("none"))
{
addArticle.style.display = 'block';
}
else
{
addArticle.style.display = 'none';
}
}
Now, in my html page:
I have two text areas and two buttons.
Each button "activates" a different text area.
All that my code does is to make the property 'display' in each text area to be "block" or "none", also, to make sure that if one text is already visible, the others will not.
The problem is that the first button "edit article" is not working until I click on the second button "add article". The second button works properly.
Any thoughts?
I want to write a ckeditor plugin that adds a checkbox to the toolbar.
When an img element is selected, the checkbox should reflect whether the image has a certain class or not.
When something else than an image is selected, the checkbox should be
disabled, or maybe invisible.
When I check or uncheck the checkbox, the class should be added/removed to/from the img.
In other words, I want to add something else than a button to the toolbar (those that are added with editor.ui.addButton), and that something should be a checkbox.
How do I do that?
I managed to do it anyway, using editor.ui.add and editor.ui.addHandler. Here is a screenshot:
plugin.js:
CKEDITOR.plugins.add('add_zoomable_to_image',
{
init: function( editor )
{
var disabled_span_color = "#cccccc";
var enabled_span_color = "#000000";
var cb;
var span;
var html =
"<div style='height: 25px; display: inline-block'>" +
"<div style='margin: 5px'><input class='add_zoomable_cb' type='checkbox' disabled='disabled'>" +
"<span class='add_zoomable_span' style='color: " + disabled_span_color + "'> Add zoomable to image</span>" +
"</div>" +
"</div>";
editor.ui.add('add_zoomable_to_image', "zoomable_button", {});
editor.ui.addHandler("zoomable_button",
{
create: function ()
{
return {
render: function (editor, output)
{
output.push(html);
return {};
}
};
}
});
editor.on("selectionChange", function()
{
var sel = editor.getSelection();
var ranges = sel.getRanges();
if (ranges.length == 1)
{
var el = sel.getStartElement();
if (el.is('img'))
{
enable_input();
if (el.hasClass('zoomable'))
check_cb();
else
uncheck_cb();
}
else
disable_input();
}
else
disable_input();
});
editor.on("instanceReady", function ()
{
cb = $('.add_zoomable_cb');
span = $('.add_zoomable_span');
cb.change(function()
{
var element = editor.getSelection().getStartElement();
if (cb.is(':checked'))
element.addClass('zoomable');
else
element.removeClass('zoomable');
});
});
function enable_input()
{
cb.removeAttr('disabled');
span.css('color', enabled_span_color);
}
function disable_input()
{
uncheck_cb();
cb.attr('disabled', 'disabled');
span.css('color', disabled_span_color);
}
function check_cb()
{
cb.attr('checked', 'checked');
}
function uncheck_cb()
{
cb.removeAttr('checked');
}
}
});
CKEditor doesn't include the option to add a checkbox to the toolbar, so your first step is to look at their code and extend it to add the checkbox.
Then look at how other buttons work to modify the content and detect when the selection in the editor changes to reflect its new state, and apply those ideas to your checkbox.
Toggle button in jqgrid top toolbar is defined using Oleg answer as
var autoedit;
$("#grid_toppager_left table.navtable tbody tr").append(
'<td class="ui-pg-button ui-corner-all" >' +
'<div class="ui-pg-div my-nav-checkbox">' +
'<input tabindex="-1" type="checkbox" id="AutoEdit" '+(autoedit ? 'checked ' : '')+'/>' +
'<label title="Toggle autoedit" for="AutoEdit">this text is ignored in toolbar</label></div></td>'
);
$("#AutoEdit").button({
text: false,
icons: {primary: "ui-icon-star"}
}).click(function () {
autoedit = $(this).is(':checked');
});
Answer from how to add standard textbox command to jqgrid context menu is used to autogenerate context menu for grid from toolbar.
In generated context menu for this item only text "this text is ignored in toolbar" appears and selecting it does nothing.
How to make it work or remove this item from context menu?
Look at the demo or the same demo with another themes: this and this.
First of all I modified the code of the jquery.contextmenu.js to support jQuery UI Themes. Then I modified the code more, to be able to create context menu more dynamically. In the modified version of jquery.contextmenu.js one can crate menu and the bindings not only in the onContextMenu, but also in onShowMenu. Inside of onContextMenu one can create just the empty menu
<div id="myMenu"><ul></ul></div>
It is important only if one use dynamically switching of the icons of the text of buttons from the navigator bar.
You can download the modified version of the file here.
In the demo I used the last modification of the code from the answer, so the standard context menu can be still used in the grid on selected text or in the enabled input/textarea fields. The context menu of the browser will be displayed in the case:
I modified the code of createContexMenuFromNavigatorButtons function from the answer to the following:
var getSelectedText = function () {
var text = '';
if (window.getSelection) {
text = window.getSelection();
} else if (document.getSelection) {
text = document.getSelection();
} else if (document.selection) {
text = document.selection.createRange().text;
}
return typeof (text) === 'string' ? text : text.toString();
},
createContexMenuFromNavigatorButtons = function (grid, pager) {
var menuId = 'menu_' + grid[0].id, menuUl = $('<ul>'),
menuDiv = $('<div>').attr('id', menuId);
menuUl.appendTo(menuDiv);
menuDiv.appendTo('body');
grid.contextMenu(menuId, {
bindings: {}, // the bindings will be created in the onShowMenu
onContextMenu: function (e) {
var p = grid[0].p, i, lastSelId, $target = $(e.target),
rowId = $target.closest("tr.jqgrow").attr("id"),
isInput = $target.is(':text:enabled') ||
$target.is('input[type=textarea]:enabled') ||
$target.is('textarea:enabled');
if (rowId && !isInput && getSelectedText() === '') {
i = $.inArray(rowId, p.selarrrow);
if (p.selrow !== rowId && i < 0) {
// prevent the row from be unselected
// the implementation is for "multiselect:false" which we use,
// but one can easy modify the code for "multiselect:true"
grid.jqGrid('setSelection', rowId);
} else if (p.multiselect) {
// Edit will edit FIRST selected row.
// rowId is allready selected, but can be not the last selected.
// Se we swap rowId with the first element of the array p.selarrrow
lastSelId = p.selarrrow[p.selarrrow.length - 1];
if (i !== p.selarrrow.length - 1) {
p.selarrrow[p.selarrrow.length - 1] = rowId;
p.selarrrow[i] = lastSelId;
p.selrow = rowId;
}
}
return true;
} else {
return false; // no contex menu
}
},
onShowMenu: function (e, $menu) {
var options = this, $menuUl = $menu.find('ul:first').empty();
$('table.navtable .ui-pg-button', pager).each(function () {
var $spanIcon, text, $td, id, $li, $a, button,
$div = $(this).children('div.ui-pg-div:first'),
gridId = grid[0].id;
if ($div.length === 1) {
text = $div.text();
$td = $div.parent();
if (text === '') {
text = $td.attr('title');
}
if (this.id !== '' && text !== '') {
id = 'menuitem_' + this.id;
if (id.length > gridId.length + 2) {
id = id.substr(0, id.length - gridId.length - 1);
}
} else {
// for custom buttons
id = $.jgrid.randId();
}
$li = $('<li>').attr('id', id);
$spanIcon = $div.children('span.ui-icon');
if ($spanIcon.length > 0) {
// standard navGrid button or button added by navButtonAdd
$li.append($('<a>')
.text(text)
.prepend($spanIcon.clone().css({
float: 'left',
marginRight: '0.5em'
})));
$menuUl.append($li);
options.bindings[id] = (function ($button) {
return function () { $button.click(); };
}($div));
} else {
button = $div.children("input").data("button");
if (button !== undefined) {
$a = $('<a>')
.text(button.options.label)
.prepend(
$('<label>').addClass("ui-corner-all").css({
float: 'left',
width: '16px',
borderWidth: '0px',
marginRight: '0.5em'//'4px'
}).append(
$('<span>').addClass("ui-button-icon-primary ui-icon " +
button.options.icons.primary)
.css({
float: 'left',
marginRight: '0.5em'
})
)
);
$li.append($a);
if (button.type === "checkbox" && button.element.is(':checked')) {
$a.find('label:first').addClass("ui-state-active");
}
$menuUl.append($li);
options.bindings[id] = (function ($button, isCheckbox) {
if (isCheckbox) {
return function () {
if ($button.is(':checked')) {
$button.siblings('label').removeClass("ui-state-active");
} else {
$button.siblings('label').addClass("ui-state-active");
}
$button.click();
$button.button("refresh"); // needed for IE7-IE8
};
} else {
return function () { $button.click(); };
}
}(button.element, button.type === "checkbox"));
}
}
}
});
return $menu;
}
});
},
autoedit = false;
and fill the check-button in the navigator bar with the code which is changed only a little:
$("#pager_left table.navtable tbody tr").append(
'<td class="ui-pg-button ui-corner-all">' +
'<div class="ui-pg-div my-nav-checkbox">' +
'<input tabindex="-1" type="checkbox" id="AutoEdit" />' +
'<label title="Checkx caption which should appear as button tooltip"' +
' for="AutoEdit">Autoedit</label></div></td>'
);
$("#AutoEdit").button({
text: false,
icons: {primary: "ui-icon-mail-closed"}
}).click(function () {
var iconClass, $this = $(this);
if (!autoedit) { // $this.is(':checked')) {
autoedit = true;
iconClass = "ui-icon-mail-open";
} else {
autoedit = false;
iconClass = "ui-icon-mail-closed";
}
$this.button("option", {icons: {primary: iconClass}});
});
createContexMenuFromNavigatorButtons($grid, '#pager');
UPDATED: One more demo which support buttons added by new inlineNav method you can find here. Additionally I included in the demo the function normalizePagers which I use to improve the look of the pager:
How you can see the contextmenu includes only enabled buttons from the navigator bar.