I am new to mootools. What I want is to create a new element span and inject an image to it.
I wrote the following code but doesn't work:
var newElementVar = new Element('span', {
'id': 'id_namekhan',
'text': 'I am a new div'
});
var my_img = new Element ('img' , {
'src' :'uploading/'+json.get('fpath')+'' ,
'style' : 'width:50px; text-align:left'
}).inject(id_namekhan, 'top');
Even the text 'I am a new div' is not showing.
Thanks
Your problem is that you are trying to inject the image into the span using its ID, but the span hasn't been added to the page (DOM tree) yet. Try this:
var my_span = new Element('span', {'id': 'id_namekhan','text': 'I am a new div'});
var my_img = new Element ('img' , {'src' :'uploading/'+json.get('fpath')+'' , 'style' : 'width:50px; text-align:left' }).inject(my_span, 'top');
my_span.inject($('element')); // replace element with the ID of the element you wish to inject the span inside
Related
How do i make this working?
var makePage = $('<div />').attr('data-role', 'page').attr('id', 'p'+item.id)
.append($('<div>').attr('data-role', 'header')
.append('')
.append('<img src="images/app/logo.png" id="navImg"/>')
.append('<div class="separatore"></div></div>'))
.append($('<div />').attr('data-role', 'main').attr('class', 'ui-content')
.append('<h2 class="hstyle">'+item.name+' '+item.surname+'</h2>')
.append($('<ul />').attr('data-role', 'listview').attr('data-inset', 'true')
if (item.cellulare != '') { .append('<li><img src="images/app/tel.png" class="ui-li-icon">'+item.cellulare+'</li>') }
) // data-role page
); // data-role main
makePage.appendTo($.mobile.pageContainer);
the condition i want is "if variable item is not empty, append this..".
Thanks
Store your new div into a variable if you want to later append new elements onto it. The way you were doing it you were telling the compiler to use the append method of a true value which doesn't exist.
var newDiv = $('<div />').attr('data-role', 'page')
.append($('<div>')
.attr('data-role', 'header');
if (item != '') {
newDiv.append('')
.append('<img src="images/app/logo.png" id="navImg"/>');
}
If you need to append into specific elements you need to append at that level then put that level into the parent. For instance if you were trying to append the image inside the anchor (note your code if it were to be proper code would append all into the first div you created):
$('').append('<img src="images/app/logo.png" id="navImg"/>').appendTo(newDiv);
In your first part it looks like you possibly were intending to create a div and then append another div with a specific data-role, but the way you were doing it would create a div with data-role page, append another div, and then update the parent div's data-role to header. To do it in order you should do:
var newDiv = $('<div />').attr('data-role', 'page');
$('<div>').attr('data-role', 'header').appendTo(newDiv);
Write like this.
if(item != '')
{
//write your code
}
you are mixing code
I'm currently creating a 'smartobject' widget. In the widgets dialog, the user can choose a 'smartobject', which simply put, generates some html, which should be added to the editor. Here comes the tricky part: the html sometimes div elements and sometimes simply span elements. In the case of the div variant, the widget should be wrapped in a div 'template'. In the case of a span variant, the widget should be wrapped in a span and the html should be added 'inline'.
In the widgets API I see the following way to define a template:
editor.widgets.add('smartobject', {
dialog: 'smartobject',
pathName: lang.pathName,
template: '<div class="cke_smartobject"></div>', // <------
upcast: function(element) {
return element.hasClass('smartObject');
},
init: function() {
this.setData('editorHtml', this.element.getOuterHtml());
},
data: function() {
var editorHtml = this.data.editorHtml;
var newElement = new CKEDITOR.dom.element.createFromHtml(editorHtml);
newElement.copyAttributes(this.element);
this.element.setText(newElement.getText());
}
});
But in my case, the template is more dynamic: sometimes a div and sometimes the span will do the correct thing..
How can I fix this without needing to create two widgets which will do the exact same thing, with only the wrapping element as difference?
I've already tried to replace the entire element in the 'data' method, like:
newElement.replace(this.element);
this.element = newElement;
But this seemed not supported: resulted in undefined errors after calling editor.getData().
I'm using ckeditor v4.5.9
Thanks for your help!
It seems I got it working (with a workaround).
The code:
CKEDITOR.dialog.add('smartobject', this.path + 'dialogs/smartobject.js');
editor.widgets.add('smartobject', {
pathName: lang.pathName,
// This template is needed, to activate the widget logic, but does nothing.
// The entire widgets html is defined and created in the dialog.
template: '<div class="cke_smartobject"></div>',
init: function() {
var widget = this;
widget.on('doubleclick', function(evt) {
editor.execCommand('smartobject');
}, null, null, 5);
},
upcast: function(element) {
return element.hasClass('smartObject');
}
});
// Add a custom command, instead of using the default widget command,
// otherwise multiple smartobject variants (div / span / img) are not supported.
editor.addCommand('smartobject', new CKEDITOR.dialogCommand('smartobject'));
editor.ui.addButton && editor.ui.addButton('CreateSmartobject', {
label: lang.toolbar,
command: 'smartobject',
toolbar: 'insert,5',
icon: 'smartobject'
});
And in the dialog, to insert code looks like:
return {
title: lang.title,
minWidth: 300,
minHeight: 80,
onOk: function() {
var element = CKEDITOR.dom.element.createFromHtml(smartobjectEditorHtml);
editor.insertElement(element);
// Trigge the setData method, so the widget html is transformed,
// to an actual widget!
editor.setData(editor.getData());
},
...etc.
UPDATE
I made the 'onOk' method a little bit better: the smartobject element is now selected after the insertion.
onOk: function() {
var element = CKEDITOR.dom.element.createFromHtml(smartobjectEditorHtml);
var elementId = "ckeditor-element-" + element.getUniqueId();
element.setAttribute("id", elementId);
editor.insertElement(element);
// Trigger the setData method, so the widget html is transformed,
// to an actual widget!
editor.setData(editor.getData());
// Get the element 'fresh' by it's ID, because the setData method,
// makes the element change into a widget, and thats the element which should be selected,
// after adding.
var refreshedElement = CKEDITOR.document.getById(elementId);
var widgetWrapperElement = CKEDITOR.document.getById(elementId).getParent();
// Better safe then sorry: if the fresh element doesn't have a parent, simply select the element itself.
var elementToSelect = widgetWrapperElement != null ? widgetWrapperElement : refreshedElement;
// Normally the 'insertElement' makes sure the inserted element is selected,
// but because we call the setData method (to ensure the element is transformed to a widget)
// the selection is cleared and the cursor points to the start of the editor.
editor.getSelection().selectElement(elementToSelect);
},
So in short, I partially used the widget API for the parts I wanted:
- Make the html of the widget not editable
- Make it moveable
But I created a custom dialog command, which simply bypasses the default widget insertion, so I can entirely decide my own html structure for the widget.
All seems to work like this.
Any suggestions, to make it better are appreciated:)!
As suggested in this ckeditor forum thread, the best approach would be to set the template to include all possible content elements. Then, in the data function, remove the unnecessary parts according to your specific logic.
I have tree view on a page which gets data from a ComboBox and a multiselect. The ComboBox contains the name of each ingredient and the multiselect contains the possible amount types which are then used as names for all their child nodes.
The tree looks something like that:
Ingredient 1
100mg
200mg
Ingredient 2
50mg
100mg
Everything works fine except I can add the same value twice because I am not able to validate if a node already exists.
Here is the function I am using to add new elements:
var addElement = function () {
var treeview = $("#ingredientTree").data("kendoTreeView");
var multiselect = $("#ingredientAmount").data("kendoMultiSelect");
var ingredientToAdd= $("#ingredient").val();
// I allways get an empty array at this point.
var exinstingIngredient= treeview.findByText(ingredientToAdd);
var children = new Array();
var amount = multiselect.value();
for (var j = 0; j < amount.length; j++) {
children.push({ text: amount[j] });
}
// it allways adds the items because the length is allways 0
if (exinstingIngredient.length === 0) {
treeview.append({
text: ingredientToAdd,
items: children
});
}
}
I don't understand why it can't find the existing element even I set its name as text and search for this text.
edit:
Here we have the treeview:
#(Html.Kendo().TreeView().TemplateId("treeview-template").Name("ingredientTree"))
That is the source of the ingredients, it handles just plain strings:
#(Html.Kendo().ComboBox()
.Name("ingredient")
.DataSource(source => source.Read(r => r.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "InternationalIngredients" }))))
.Events(events => events.Change("onIngredientChanged"))
)
Following you find the source for amounts, which handles strings to:
#(Html.Kendo().MultiSelect()
.Name("ingredientAmount")
.DataSource(source => source.Read(read => read.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "InternationalIngredientAmount" })).Data("getIngredient")).ServerFiltering(true)))
This is a function to determine the selected ingredient for the service call:
function getIngredient() {
return { ingredient: $("#ingredient").val() }
}
I've found the reason for my problem now. findByText seems to check the Content of the nodes span with class "k-in". Unfortunatly, this Content is modified when you add a template as described here. So if you want to find an element with template, you should use findById or you define your template in a way you can use jQuery.
How should I define observable object instead of {cases: records} in this code to update dom automatically once this observable is updated:
init : function( element , options ){
var el = this.element;debugger;
SObjectModelExt.findAll({sobject: new SObjectModel.Case()}).then(function(records){
el.html( can.view('casesView', {cases: records}));
});
}
Is this can.Map({case: []}) or can.List?
How use it in the mustache helper?
{{#each cases }} ?
I've tried to use like
this.records = new can.Map({case: []});
el.html( can.view('casesView', {cases: records}));
and later in the code to do
this.records.attr('cases', entries);
but it doesn't update dom.
You should be able to initialize an empty List and then replace it with the data you got back which should update the list. You can also assign that list for later reference:
init : function( element , options ){
var el = this.element;
var cases = this.cases = new can.List();
SObjectModelExt.findAll({sobject: new SObjectModel.Case()}).then(function(records){
cases.replace(records);
el.html( can.view('casesView', { cases: cases }));
});
}
Then you should just be able to reference it via this.cases later on and remove and add items to that list.
I'm using CKEditor 3.5 to provide WYSYWYG editing in a website. When inserting an image you can provide width and height of the image, which results in HTML like follows:
<img alt="" src="/Images/Sample.png" style="width: 62px; height: 30px; " />
Since this does the resizing in the browser and in other places on the same website I use Nathanael Jones' Image Resizing Module, I'd like to get the following output instead:
<img alt="" src="Images/Sample.png?width=62&height=30" />
Is there an easy way to control the generated HTML or have I really to write my own dialog/plugin for CKEditor?
EDIT:
Adding the following lines to config.js was the solution that eventually worked for me:
CKEDITOR.on('dialogDefinition', function (ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var dialog = dialogDefinition.dialog;
var editor = ev.editor;
if (dialogName == 'image') {
dialogDefinition.onOk = function (e) {
var imageSrcUrl = e.sender.originalElement.$.src;
var width = e.sender.originalElement.$.width;
var height = e.sender.originalElement.$.height;
var imgHtml = CKEDITOR.dom.element.createFromHtml('<img src=' + imageSrcUrl + '?width=' + width + '&height=' + height + ' alt="" />');
editor.insertElement(imgHtml);
};
}
});
The next problem is then, when editing an image, the width and height naturally are in the URL field and are missing in the dedicated fields for width and height. So I need to come up with a solution for the reverse... :-)
I kind of had the same problem, I needed to remove those attributes from the generated HTML for the image, so what I did was to override the onOK method of the uploader and insert the image element manually using the CKEditor's API, something like this:
CKEDITOR.on('dialogDefinition', function(ev) {
// Take the dialog name and its definition from the event data
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var editor = ev.editor;
if (dialogName == 'image') {
dialogDefinition.onOk = function(e) {
var imageSrcUrl = e.sender.originalElement.$.src;
var imgHtml = CKEDITOR.dom.element.createFromHtml("<img src=" + imageSrcUrl + " alt='' align='right'/>");
editor.insertElement(imgHtml);
};
}
}
This has worked for us so far.
Look at the "output html" sample, you can find there some code that changes the dimensions in images from styles to attributes, so you can adjust it to rewrite the URL.
I don't have enough points to comment on that previous answer. but in respect to your error: CKEDITOR.currentInstance returns undefined.
That is strange because CKEDITOR is global, but you shouldn't have to resort to that.
Within the OK function invocation, you have access to "editor", you shouldn't have to get the instance.
just a suggestion.
Best bet might be to "recreate" the src (and possibly the style) field's behavior. I've do something similar. (but not as complex)
Start with the original code (from plugins/dialog/image.js) and create setup and commit logic that produces (and parses) the markup you're looking for.
Then during dialog definition
Delete Originals
Add your "custom" fields
style field not sure, maybe just leave it in the dialog, but stub out it's commit logic.
I added my field to the dialog...
var infoTab = dialogDefinition.getContents( 'info' );
// Move the ID field from "advanced" to "info" tab.
infoTab.add( idField_config);
var idField_config = {
type : 'text',
label : 'Name',
id : 'linkId',
setup : function( type, element ) {
//if ( type == IMAGE )
this.setValue( element.getAttribute( 'id' ) );
},
commit : function( type, element ) {
//if ( type == IMAGE ) {
if ( this.getValue() || this.isChanged() )
element.setAttribute( 'id', this.getValue() );
//}
}
};
Issues I faced.
New fields get added to end of
dialog.
Pieces of the original code
( type == IMAGE ) isn't valid (Love to know why but felt comfortable it was safe to comment for my usage)
You might face problems with the markup rules undoing your hard work, but "output html" sample" suggestion should help you weed through that issue.