I have two template files: one for the form (loginFormTemplate) and one for the dialog (dialogTemplate). When I put them togheter I only get the i18n on my form (like ${i18n.username}, etc.), but not my dialog html it's says ${undefined}. I have clearly defined it in my nls file. Why? Here's my code when I construct my dialog.
var template = lang.replace(dialogTemplate, {
form: loginFormTemplate
});
var contentWidget = new (declare(
[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],
{
templateString: template,
i18n: i18n
}
));
I could create "variables" just like my form within the dialoTemplate and pass my i18n value, but I don't find it quite elegant. I just want to do it once. So, instead it would be like this.
var template = lang.replace(dialogTemplate, {
form: loginFormTemplate,
_ok: i18n.okLabel,
_cancel: i18n.cancelLabel
});
var contentWidget = new (declare(
[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin],
{
templateString: template,
i18n: i18n
}
));
Here's my solution with with phusick answer (my form is notated %[]):
var template = lang.replace(
dialogTemplate,
{form: loginFormTemplate},
/\%\[([^\]]+)\]/g
);
I'm not by my computer, but I guess calling 'lang.replace' replaces not only {form}, but also your ${i18n.*} with undefined since only 'form' is defined when calling 'lang.replace'.
Edit: You can use 'lang.replace' with a custom pattern to avoid conflicts between i18n and string concatenation: http://livedocs.dojotoolkit.org/dojo/_base/lang#advanced-usage
Related
I am trying to apply translations to a jquery dataTable. ie.
myTable.DataTable({
language: {
paginate: {
next: (I18n.t('filters.paginate.next')),
previous: (I18n.t('filters.paginate.previous'))
}
}
});
When I run:
I18n.locale //=>en (even when the locale is changed)
Below, you see the I18n json shows two different locales for the same value, only is picking up one in brackets, even though they are the same attribute ?
After some time I have found the reason for the issue was that the function I was using to initialize my dataTables was IIFE (function() { })();, and was being processed before $(document).ready, and the correct I18n locale would not update for my translations in time. So I used a regex on the URL query string with a function called in the IIFE, and set the I18n.locale to the found value:
function QueryString(item){
var svalue = location.search.match(new RegExp("[\?\&]" + item + "=([^\&]*)
(\&?)","i"));
return svalue ? svalue[1] : svalue;
}
(function() {
I18n.locale = QueryString('locale');
//initialized tables and added translations
.... })();
I'm trying to create a CKEditor5 custom element plugin - mainly for custom format/styles -- nested divs etc. Managed to be able to inject/format the elements, and I can type in them. But if I try to copy and paste text into a custom element I get a too much recursion error.
MyWidget plugin:
export default class MyWidgetPlugin extends Plugin {
init() {
const editor = this.editor;
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
isLimit: true,
});
editor.conversion.elementToElement({ model: 'my-widget', view: 'my-widget' });
editor.commands.add('myWidget', new MyWidgetCommand(editor));
}
}
MyWidget command:
class MyWidgetCommand extends Command {
execute() {
const editor = this.editor;
const block = first(this.editor.model.document.selection.getSelectedBlocks());
this.editor.model.change(writer => {
const myWidget = writer.createElement('my-widget')
writer.insert ( myWidget, block, 'after');
writer.appendElement( 'paragraph', myWidget );
});
}
}
Inserting a widget injects this into the editor:
<my-widget>
<p></p>
</my-widget>
And I can type fine, but I can't paste. I'm guessing I got the schema wrong... have played around with quite a few different options.. but to no avail.
I didn't check it but I think that the issue is here:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
isLimit: true,
});
This schema rule says that <my-widget> will allow e.g. a <paragraph> inside it. But it doesn't say anything about where <my-widget> may be used. That's because $root is not allowed in any other element (cause it's a root :)).
I think that the following should work fine:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
allowIn: '$root',
isLimit: true,
});
Alternatively, a more generic solution should work too:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
allowWhere: '$block',
isLimit: true,
});
Still, the editor should not crash with an infinite loop, so I reported https://github.com/ckeditor/ckeditor5-engine/issues/1441.
I'm using Dojo and would like to create a tree like structure. However, I'd like to be able to display content within the tree once the end node in a particular branch has been expanded. e.g.
top
- a branch
-- last item in this branch
[some content such as a div, span, image etc]
-- another item in this branch
[some more content]
etc
Does anyone know if this can be achieved using dijit Tree and if so, any pointers?
After digging around in the docs I've found a way to do this. It's not simple so thought I'd share. This page has an example of how to display a tree node with a rich text label rather than just text. This involves declaring your own class that inherits from Tree._TreeNode, allowing you to control it's creation. This same technique can be used.
When creating a Tree, I override the _createTreeNode function as follows:
_createTreeNode: function (args) {
if (args.item.type === "content") {
return new LayerManagerContentNode(args);
} else {
return new Tree._TreeNode(args);
}
}
In my store I add an object to represent the content that I want to display inline and give it a type of 'content'.
I create a class that inherits from Tree._TreeNode as follows:
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom",
"dojo/dom-construct",
"dojo/on",
"dijit/form/Button",
"dijit/Tree"
], function (declare, lang, dom, domConstruct, on, Button, Tree) {
return declare("my/ui/platforms/desktop/parts/LayerManagerContentNode", [Tree._TreeNode], {
// summary:
// ...
constructor: function () {
},
postCreate: function () {
var button = new Button({
label: "Test"
});
this.domNode.innerHTML = "<div></div>";
this.domNode.innterText = "";
button.placeAt(this.domNode, "first");
}
});
});
in the postCreate, I create a button (this was just for testing, I'll probable create a content pane or something to further populate) to be displayed in place of the usual tree node. I then replace the tree nodes innerHTML and innerText to hide what would normally be displayed, en voila, it works!
I dare say there are better ways to do this so if anyone comes along and has one, please add it.
I have a DOJO Editor that I add in JS using the method createEditor
require(["dijit/Editor"],
function(Editor){
this.createEditor = function(idToReplace){
var myEditorA = new Editor({
height: '50px',
plugins:['bold','italic']
}, document.getElementById(idToReplace));
myEditorA.startup();
}
});
I need the text inside the Editor after it has been changed.
I hooked up the method getEditorText but it is failing to do as I want it to do.
require(["dijit/Editor"], "dojo/dom",
function(Editor, dom){
this.getEditorText = function(idofEditor){
//Editor myEditor =Editor(null, dom.byId(idofEditor)); does not work either
var myEditor = dom.byId(idofEditor);
var content = myEditor.get("value");
});
The value that I need is stored in the attribute "value" in the Editor.
If I store myEditorA in a global variable I can get the content but I need the correct syntax to avoid working with unnecessary global variables
In Dojo widgets (dijit) and DOM nodes are treated seperately. For DOM nodes you indeed need to use the dojo/dom module and the function byId(). For widgets however, you need the dijit/registry module and then you can get the widget by its DOM node like this:
require(["dijit/registry", "dojo/dom"], function(registry, dom) {
var myEditor = registry.byNode(dom.byId(idofEditor));
});
But because the registry also saves your editor with the same ID as your DOM node, you can also access it directly (without using the DOM node) like this:
require(["dijit/registry"], function(registry) {
var myEditor = registry.byId(idofEditor);
});
I made an example JSFiddle which you can find here.
<div dojoType="dojo.Dialog" id="alarmCatDialog" bgColor="#FFFFFF" bgOpacity="0.4" toggle="standard">
<div class='dijitInline'>
<input type='input' class='dateWidgetInput' dojoAttachPoint='numberOfDateNode' selected="true">
</div>
how to show this dialog I tried dijit.byId('alarmCatDialog').show();
The above code is a template and I called dijit.byId('alarmCatDialog').show() from the .js file .
dojo.attr(this.numberOfDateNode) this code works and I got the data .but if I change dojoattachpoint to id then I try dijit.byId('numberOfDateNode') will not work;
Your numberOfDateNode is a plain DOM node, not a widget/dijit, i.e. javascript object extending dijit/_Widget, which is the reason you cannot get a reference to it via dijit.byId("numberOfDateNode"). Use dojo.byId("numberOfDateNode") instead and you are all set.
dojoAttachPoint or its HTML5 valid version data-dojo-attach-point is being used inside a dijit template to attach a reference to DOM node or child dijit to dijit javascript object, which is the reason dijit.byId('alarmCatDialog').numberOfDateNode has a reference to your <input type='input' class='dateWidgetInput' .../>.
The main reason to use data-dojo-attach-point is that:
you can create multiple instances of dijit and therefore your template cannot identify nodes/dijits by IDs as you will have multiple nodes/dijits with the same ID
it's an elegant declarative way, so your code won't be full of dijit.byId/dojo.byId.
It is important to keep track of what is the contents and which is the template of the dijit.Dialog. Once you set contents of a dialog, its markup is parsed - but not in a manner, such that the TemplatedMixin is applied to the content-markup-declared-widgets.
To successfully implement a template, you would need something similar to the following code, note that I've commented where attachPoints kicks in.
This SitePen blog renders nice info on the subject
define(
[
"dojo/declare",
"dojo/_base/lang",
"dijit/_Templated",
"dijit/_Widget",
"dijit/Dialog"
], function(
declare,
lang,
_Templated,
_Widget,
Dialog
) {
return declare("my.Dialog", [Dialog, _Templated], {
// set any widget (Dialog construct) default parameters here
toggle: 'standard',
// render the dijit over a specific template
// you should be aware, that once this templateString is overloaded,
// then the one within Dialog is not rendered
templateString: '<div bgColor="#FFFFFF" bgOpacity="0.4">' +// our domNode reference
'<div class="dijitInline">' +
// setting a dojoAttachPoint makes it referencable from within widget by this attribute's value
' <input type="input" class="dateWidgetInput" dojoAttachPoint="numberOfDateNode" selected="true">' +
'</div>' +
'</div>',
constructor: function(args, srcNodeRef) {
args = args || {} // assert, we must mixin minimum an empty object
lang.mixin(this, args);
},
postCreate: function() {
// with most overrides, preferred way is to call super functionality first
this.inherited(arguments);
// here we can manipulate the contents of our widget,
// template parser _has run from this point forward
var input = this.numberOfDateNode;
// say we want to perform something on the numberOfDateNode, do so
},
// say we want to use dojo.Stateful pattern such that a call like
// myDialogInstance.set("dateValue", 1234)
// will automatically set the input.value, do as follows
_setDateValueAttr: function(val) {
// NB: USING dojoAttachPoint REFERENCE
this.numberOfDateNode.value = val;
},
// and in turn we must set up the getter
_getDateValueAttr: function() {
// NB: USING dojoAttachPoint REFERENCE
return this.numberOfDateNode.value;
}
});
});