CKEditor how do I get a UIElement - javascript

I need to have two select menus in a CKEditor dialog, with the second select menu changing its options according to the selected option of the first menu. Simple enough you would think! But in CKEditor it seems really difficult to obtain the DOM equivalent of the CKEditor object. I can access the CKEditor Object but not its DOM equivalent(s).
The instance of the CKEditor select (UIElement) object has some useful DOM interactions i.e. getElement() but I can only access this object with the special this keyword within an event method within a CKEditor select "class" definition.
How can I access the instance of the CKEditor UIElement object (in this case the select)? I only have the id of the CKEditor object, CKEditor for some frustrating reason decides to apply random ids to its DOM object equivalents.
The instance object I am trying to access is documented here: (No mention of how to obtain this instance though!)
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.ui.dialog.select.html

In fact the CKEDITOR.dialog.getCurrent() method will allow you to access the Dialog instance from any function, and from there you can access the UIElement instance of any CKEditor object you're after.

Can you cache what you need in the setup callbacks during your dialog's initialization?
You can pass the setup functions an object and they could put what they need in there. So you'd pass an object into your setup stuff:
onShow: function() {
//...
this.cachedDomIds = { };
this.setupContent(this.cachedDomIds);
//...
}
And then in your setup:
setup: function(cache) {
//...
cache.some_dom_id = this.domId;
//...
}
Then at least you'd have access to all the real DOM id attributes and you could getElementById() as needed.

Thanks for the suggestion mu is too short,
I found I could access the other select menus by using this method:
this.getDialog().getContentElement([insert_dialog_name_here], this.getValue()).getElement()
this.getValue will have the same id of the CKEditor UI element I'm after

Related

.data() html5 cross window

I'm trying to put some data into a child windows html tag. But it doesn't seem to work. I tried putting it in with some jquery on that child window and that is working fine.
Here is the code implemented in the parent window to send the data to the child window:
$(".something", fullscreen.document).data("data1", "whatever");
Which will return "undefined" with the following jQuery code in the child window.
console.log($(".something").data("data1"));
But when I store the data with the child jQuery-script it works perfectly:
$(".something").data("data1", "whatever");
Is crosswindow data storing into tags not allowed?
jQuery uses its own data store for data you set with .data(). Each instance of jQuery (in each window) will have it's own separate data store so you won't get results from one when calling from another.
If your data is simply a string, then you will probably find it easier to not worry about multiple instance data stores and just use .attr() to store the string as an actual attribute on the DOM object. Then, there's zero question about where it's stored or how to access it because it's directly on the DOM object which you can easily get to from either jQuery instance.
// store data on the object
$(".something", fullscreen.document).attr("data-data1", "whatever");
// read data from within the target window
console.log($(".something").attr("data-data1"));
Note the use of the HTML5 "data-xxx" convention to avoid any attribute naming conflicts with standard attributes.
jQuery does not save the data with the DOMElement but with in the scope the used jQuery instance. As of that two instances of jQuery no matter if in the same document (e.g. two versions of jQuery) or in different documents, won't share the internal data, neither they can access it.
You will always need retrieve the data with the same jQuery that was used to set it.
If you want to access the data in the child for an element where the data was that way:
$(".something", fullscreen.document).data("data1", "whatever");
then you would need to do it that way:
parent.window.$(".something", docmuent).data('data1');

Detect "hooked" DOM elements

So I have a set of jQuery plugins, really basic stuff, but I split the code into plugins because I don't like having a huge jQuery(document).ready() function where I store the entire application logic.
Each plugin has a "destructor", which is basically a function that I defined in the plugin prototype object. This function unbinds events used by the plugin, removes DOM elements that were added by the plugin etc.
Plugins are initialized like this:
$('.element').plugin();
Is there any way I can get all the elements that have my plugins attached to them, from another plugin which is supposed to replace the body HTML, so I can call the destructor function?
I was thinking to store each plugin instance inside a global array, then I can access that array from any plugin. But maybe there is a better way that doesn't use the global state?
I don't think there is a ready made method for it... but as a hack you can add a class to the target elements in your plugin and then use that class to get all elements with the widget initialized lke
$.fn.plugin = function(){
this.addClass('my-plugin-class');
}
then to initialize
$(element).plugin()
to get all elements with the plugin
$('.my-plugin-class')....
But if it is a jQuery UI widget then you can use the selector $(':ui-widgetname'), see this answer
Arun P Johny wrote the rigth idea -- just delete 'footprint' of your job by marking the affected DOM elements with some specific class name.
I want just add an idea. Plugins are the methods of the library and nothing more. If you need the destroyer for constructor -- just make another plugin for it:
$.fn.overture = function (){...};// construct
$.fn.crescendo = function (){...};// more construct
$.fn.quietFarewell = function (){...};// destructor for everything above
$(...).overture().crescendo().quietFarewell();

add element before given javascript object in DOM

I have some function that recieves javascript object "element" (there is no id speicified for it like id=".."). This js object is already created in DOM and is seen on the page.
For different reasons I am not able to change the object "element" before it comes to the function.
I need to add a new element before given object. I know that this can be done using jquery, but in this case I do not know how to convert javascript to jQuery (if this is possible).
Are there other options how to add element before given js element in DOM?
You are looking for the insertBefore method:
https://developer.mozilla.org/en-US/docs/Web/API/Node.insertBefore
Usage:
function myInsert(element, before) {
before.parentNode.insertBefore(element,before);
}

What does this.$('.selector') do in jQuery?

I see this in someone's code: this.$('.selector') and am curious what that does. "this" is a Backbone view. So what does prefixing "this." onto a jQuery selector, in the given context, do?
From the doc:
$ (jQuery or Zepto)view.$(selector)
If jQuery or Zepto is included on
the page, each view has a $ function that runs queries scoped within
the view's element. If you use this scoped jQuery function, you don't
have to use model ids as part of your query to pull out specific
elements in a list, and can rely much more on HTML class attributes.
It's equivalent to running: view.$el.find(selector)
ui.Chapter = Backbone.View.extend({
serialize : function() {
return {
title: this.$(".title").text(),
start: this.$(".start-page").text(),
end: this.$(".end-page").text()
};
}
});
In short, it's used to access some elements of View with a familiar syntax.
It is basically limiting the search for elements with a class of selector to the element your View is based off of.
It's basically changing the scope of the search from document to this, which is obviously some element.

Wrapping a DOM element inside a JavaScript object

I've noticed a common pattern in the JavaScript I've been writing and was wondering if there is already a pattern out there that defines something similar as best practice? Essentially, it's how to get a DOM element and wrap it inside / associate it with a JavaScript object. Take this example, where you need a filter in your web app. Your page looks like this:
<html>
<head></head>
<body>
<div id="filter"></div>
</body>
</html>
You'd then wrap the element like so:
var myFilter = new Filter({
elem: document.getElementById('filter'),
prop: 'stacks-test',
someCallback: function() {
// specify a callback
}
});
And the JavaScript (where spec is an object passed to the constructor):
var Filter = function(spec) {
this.elem = spec.elem;
this.prop = spec.prop;
this.callback = spec.someCallback;
this.bindEvents();
};
Filter.prototype.bindEvents = function() {
var self = this;
$(this.elem).click(function(e) {
self.updateFeed();
};
};
Filter.prototype.updateFeed = function() {
this.prop; // 'stacks-test'
this.callback();
// ...
// code to interact with other JavaScript objects
// who in turn, update the document
};
What is this kind of approach called, and what are the best practices and caveats?
You might be interested in Dojo's widget library, Dijit - if I'm understanding your question correctly, it essentially does what you're asking, and a whole lot more.
In Dijit, a widget essentially encapsulates a DOM node, its contents, any JavaScript that defines its behavior, and (imported separately) CSS to style its appearance.
Widgets have their own lifecycle, registry, and events (including many which simply map to DOM events on a node within the widget, e.g. myWidget.onClick could effectively call myWidget.domNode.onclick).
Widgets can (but don't have to) have their initial contents defined in a separate HTML template file, through which it's also possible to bind events on nodes within the template to widget methods, as well as set properties on the widget that reference particular nodes in the template.
I'm barely scratching the surface here. If you want to read more on this, you can start with these reference pages:
http://dojotoolkit.org/reference-guide/dijit/info.html
http://dojotoolkit.org/reference-guide/dijit/_Widget.html (the base that all widgets extend)
http://dojotoolkit.org/reference-guide/dijit/_Templated.html (RE the HTML templating)
http://dojotoolkit.org/reference-guide/quickstart/writingWidgets.html (useful information when starting to write your own widgets)
http://dojotoolkit.org/reference-guide/dijit/ (for a bunch more info)
All said, I don't know what you're ultimately aiming for, and maybe this is all a bit much for your purposes (considering I'm throwing an entire other library at you), but figured it might pique your interest at least.
Continuing from my comment on the question, jQuery is a potential tool for the job, as it already provides some of the foundations for what you're after. However, having said that, it does introduce complexities of its own, and further, not all "jQuery ways" are equal. I'll suggest one way of using jQuery as your "object model", but it may or may not suit your needs.
First things first. The philosophy of jQuery is that you start everything by selecting the element first, using $(), or equivalently jQuery(). All operations conceptually begin with this. This is a slightly different way of thinking compared to creating an object that wraps an element and keeping a reference to that wrapper, but essentially this is what jQuery does for you. A call to $('#some-id') grabs the element with id of "some-id" and wraps it in a jQuery object.
One way: Write "Filter" plugins.
Replace your constructor with a initFilter() jQuery method. You can do this by modifying the jQuery prototype and using the jQuery object as your wrapper. jQuery's prototype is referenced by jQuery.fn, so:
jQuery.fn.initFilter = function (prop, callback) {
// Save prop and callback
this.data('filter-prop', prop);
this.data('filter-callback', callback);
// Bind events (makes sense to do this during init)
this.click(function () {
$(this).updateFeed();
});
};
Then do a similar thing for updateFeed():
jQuery.fn.updateFeed = function () {
this.data('filter-prop');
this.data('filter-callback')();
});
And use it like this:
$('#filter').initFilter(prop, callback);
Note that updateFeed can simply be in-lined into the click handler to prevent unnecessary pollution of the jQuery namespace. However, one advantage of using jQuery like this is that you do not need to keep a reference to the object if you need to invoke some function on it later, since jQuery ties all references to actual elements. If you'd like to call updateFeed programmatically, then:
$('#filter').updateFeed();
will then be invoked on the correct object.
Some things to consider
There are certainly downsides to this method. One is that all properties, which we've saved against the element using .data(), are shared between all jQuery functions that act on that element. I've attempted to alleviate this by prefixing the property names with "filter-", but depending on the complexity of your object(s), this may not be suitable.
Further, this exact method may not be so suitable for objects that require a lot of manipulation (i.e. objects with many functions) since all of these functions become common to all jQuery objects. There are ways to encapsulate all this which I won't go into here, but jQuery-ui does this with their widgets, and I'm experimenting with yet another alternative in a library I'm creating.
However, pulling back a bit, the only reason I suggested using jQuery in the first place is that your Filter object appears to be heavily tied to the DOM. It binds events to the DOM, it modifies the DOM based on user interaction, basically it appears to live in the DOM, so use something DOM-based, i.e. jQuery.

Categories