I'm trying all day to set up a peristant style attribute to the body tag of the ckeditor instance. I could not find something like bodyStyle in ckeditor.config api (only bodyId and bodyClass).
So I was trying it myself, with the following solution (jQuery is used):
$(this).find('textarea.editor').ckeditor().ckeditorGet().on( 'instanceReady', function( e ){
var documentWrapper = e.editor.document,
documentNode = documentWrapper.$,
inh = $(documentNode.body);
inh.css('background', inheritParentBackground);
});
Wich is working quite well, but after I call .updateElement() or if i click the source button twice, it will removes all the styles again and 'instanceReady' is not called again.
I tried to fire it manually, but then it runs the style update first and gets directly overwritten from ckeditor.
What I'm actual trying to do: I want to edit a Div in an homepage, after klicking edit a ajax popup apears with the ckeditor and i want the Editor to have the same height, width and Background and i can not handle this over bodyId or bodyClass, so I guess I need a bodyStyle or somebody has a diffrent idea.
Is http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.html#.style what you're looking for?
I found out a dirty hack:
$(this).find('textarea.editor').ckeditor({
bodyId: Id+'" style="'+style,
});
not very nice but it works ;-)
You have two options. You can add an inline styleSheet in the instanceReady handler via:
var myStyleSheet = e.editor.document.appendStyleText("body {background:...}");
This appends an empty <style> element to the head of the editor's (iframed) document, containing the supplied text.
The return value is a CSSStyleSheet (a browser DOM object), so if you save it somewhere you can add, remove, or modify the style rules using DOM methods from javascript. I'm not sure if they persist through mode changes (i.e. after clicking "Source" twice), or calls to setData(), but you can capture these things using the 'mode' and 'contentDom' events, and reapply the styleSheet in the event handler. Note that (for the 'mode' handler at least) you need to check that editor.mode==='wysisyg', because editor.document is null in source mode.
On the other hand, if you really want to set your styles inline on the editor's <body> element, try defining a function:
function setEditorStyle(e)
{
var ed = e.editor;
if (ed.mode!=="wysiwyg") return; // don't set styles when in "Source" mode
// now change whatever styles you want, e.g.:
ed.document.getBody().setStyles({backgroundColor:"blue",color:"#FFFFFF",...});
// for setting just 1 style property, you can use .setStyle() instead
}
then within your editor config, you need to add:
..., on: { instanceReady: setEditorStyle, mode: setEditorStyle, ... }, ...
Which will set the style both after the editor iframe is first created, and after switching back to 'wysiwyg' mode (normal editing, not source mode).
I don't know why your styles are being reset by calls to updateElement(); I'm doing the same thing (using CKEditor v4) and updateElement() does not reset inline styles I've set on <body>. Perhaps it's something that's changed with CKeditor versions. In any case, if it's a problem you can simply manually reset the style again after calling updateElement(). (I'd say "just call setEditorStyle()", but as shown above that function is written to require an event parameter e. Instead you could rewrite it to use an externally defined "ed" variable (e.g. a global var) - i.e. change
var ed = e.editor;
to
if (!ed) ed = e.editor;
and then you can safely call setEditorStyle() from any point in your javascript after the editor has been created.)
Related
I'm testing out CKEditor
I'm trying to get the display in the editor, to match my sites css style for displaying the end result.
What I'm trying to do is style the "wrap code" button to match the css of my site, by adding in a class.
I've seen on this page of the manual, that you can do stuff like this:
config.format_pre = { element: 'pre', attributes: { 'class': 'editorCode' } };
However, doing the same for a code block like so:
config.format_code = { element: 'code', attributes: { 'class': 'someclass' } };
Doesn't actually do anything. Anyone got a pointer on what I might be missing?
I've tested it working on other elements, so I know the config file changes are being picked up.
The one important thing is that every tag which is formatted via config.format_tagname should be also included in config.format_tags. However, this two settings (config.format_tagname and config.format_tags) works only form Block-Level elements (as stated in the manual page you referenced ).
As code element is considered as an inline one by CKEditor (see DTD), it is not possible to use this config here.
However, the easiest way to modify the elements added via Style dropdown is to edit styles.js file which is present in CKEditor directory. The dropdown styles are based on this file, so you can easily modify code element there. You can also define your custom stylesSet.
As part of automation testing, we want to inspect the element in a website which is made of using the Zebkit UI framework.
We are unable to find the element using zebra.ui
examples can be found here
Can someone help us on inspecting the element
Zebkit UI components are rendered on HTML5 Canvas. So they are not part of browser DOM tree what can be a problem for a test tool that expects DOM as an input. But it doesn't mean you cannot go over zebkit UI stuff to perform test cases.
First of all keep in mind zebkit components are a hierarchy/tree like DOM is. Every rendered on a canvas zebkit UI component has a related JS instance of appropriate class. There are number of API methods you can use to travel over UI components tree. These methods expect path (XPath-like) since path (from my point of view) is less "encrypted" way than CSS selector.
The API methods you probably need:
byPath(path [,callback]) - traversing UI components tree by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// travel over all UI components in tree
zcanvas.byPath("//*", function(comp) {
// perform test cases here
...
});
properties([path,] properties) applies the specified properties set to component or number of components requested by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// set color property to black value for all labels
zcanvas.properties("//zebkit.ui.Label", { color: "black" });
on([eventName], [path], handler) add listener method(s) for the given event (or all events) of the given component or components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// register event listener for all found buttons
zcanvas.on("//zebkit.ui.Button", function (src) {
// handle button press event here
...
});
fire([eventName,] [path,] [argument]) fire the given event to the given component or to components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// fire button pressed event to button with id equals "testButton"
zcanvas.fire("//[#id='testButton']");
...
// or the same with a shortcut
zcanvas.fire("#testButton");
I'm not sure I understand correctly your issue, but assume you cannot click right button on canvas to open context menu and select "Inspect element" option.
You can
press F12 in browser
switch to "Elements"/"HTML" tab
in search field (CTRL + F) print "canvas"/"<canvas" and press Enter
Continue pressing Enter until required canvas found (current element should be highlighted)
These controls are implemented using an HTML5 CANVAS tag. Selenium cannot see "inside" this tag because it doesn't contain HTML. It's like an app inside the page. From the page you linked, it looks like you should be able to use JS to access elements inside the control. When I've done things with CANVAS tags in the past, I generally find JS that does or returns what I want and then wrap that code in a function that I can call. It will work but you will likely have to do some research on Zebkit to find out what JS you will need to validate, etc. all the different things you will want to validate... and it may end up that you won't be able to validate some things.
I want to Change the value assigned to a Document Property in spot fire. Lets say i have created a new document property called "Test1" as a string and assign it a value "a". Is there are way to change this value using Javascript every time i load the spotfire dashboard ?
I'm unaware of a way to use JavaScript for this, but you can assign a string document property via custom expression (if it's a List Box) or run an IronPython script each time the value changes. So, you could set the expression to the current date, datetimenow() and then every time it's loaded the IronPython script would fire. However, I don't see why you'd need the property control for this.
I suppose it really depends on what you want the document property to be set to. Is it data from your tables? Output from complex code? These are all things to consider.
1) Create an input type property control using the Document Property you want to change.
2) Edit Html to assign parent element an id say "testInput". And add the script as shown below in the Edit HTML window.
<span id="testInput"><SpotfireControl id="7db34e6c423240f59fc99e6b80fa23ec" /></span>
<script>
$("#testInput input").val("after");
$("#testInput input").focus();
$("#testInput input").blur();
</script>
3) This script will change the document property value to "after" whenever you open a file.
As you comment seemed to suggest, something you can do is write this code in Python and attach the script to an action control, e.i. a Link or a Button. Something simple like: Document.Properties["Test1"] = newValue
or even: Document.Properties[changingProperty] = newValue
allowing the code to be more reusable.
Then you insert Javascript into the Text Area as well to the effect of: $("#VeryLongSpotfireControlID").click();
Which should simulate clicking on action control, which in turn triggers the Python script to update the value. Just be careful not to use this approach when it would result in reloading the text area HTML, as this will re-trigger the Javascript, thus creating an endless loop.
I believe I have found a possible solution/work-around for the issue, entirely based on pure JavaScript (since TIBCO removed jQuery starting from Spotfire X). The solution is to force a simulated Enter Keystroke while focusing the input box to trigger updating the Document Property. (No data function and R needed)
HTML (SpotfireControl Element is an single line input-box for a Doc. Prop.):
<div id="container"><SpotfireControl id="b8534f13dc62416db6d4eaab16030f5e" /></div>
JS (focus and blur might no longer be needed for this solution, but I'm still keeping them just in case):
const inputConfirmationEvent = new KeyboardEvent("keypress", {
keyCode: 13,
bubbles: true,
cancelable: false
});
var elem = document.querySelector("#container input");
elem.value = "stringValue";
elem.blur();
elem.focus();
document.querySelector("#container input").dispatchEvent(inputConfirmationEvent);
Hope it helps someone.
Best,
Aaron
I'm trying to force CKE to stop modifying my HTML wildly, and trying to introduce our own rules.
For example, CKE will remove empty span and i tags, we can prevent it from doing it with
CKEDITOR.dtd.$removeEmpty.span = false
CKEDITOR.dtd.$removeEmpty.i = false
So far so good. Then we tried to make A tags to be able to support block level elements (HTML5), which we were able to do by manipulating the DTD as well.
But now it seems the DTD object is not enough for what we are trying to do.
For example, it's removing empty A tags, and I can't prevent it from doing it,
CKEDITOR.dtd.$removeEmpty.a = false
will not do the trick. It's doing the same thing with empty BR tags located at the end of the content.
I know CKE is using a filter, parser, processor or something that I need to hook onto and modify/alter it in order to stop it from doing those changes. Could you please give me any advise on how to achieve this ?
Cordially, Agustin.
UPDATE
I'm also looking forward in adding an extra supported children to SELECT tag. Select supports optgroup and option as children, I'm trying to add support for a custom_tag (inline), but I can't succeed in making it happen.
CKEDITOR.dtd.select.custom_tag = 1
Is not doing it. The custom tag is also declared on dtd.$inline
I guess there is some sort of external processing cleaning it up, and I can't control this from the DTD object. Any pointer on this regard ?
Unfortunately empty links are a special case and to stop removing them you will need to modify the source:
https://github.com/ckeditor/ckeditor-dev/blob/6f4c29002f4d6ecfa39308b641ae37c56bba1348/core/htmlparser/fragment.js#L59-L66
function isRemoveEmpty( node ) {
// Keep marked element event if it is empty.
if ( node.attributes[ 'data-cke-survive' ] )
return false;
// Empty link is to be removed when empty but not anchor. (#7894)
return node.name == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ node.name ];
}
BTW. CKEditor removes empty inline elements, because they are not editable (and some things may start working incorrectly). To ensure correct editability of these elements you can write widgets for them.
To disable filtering HTML (source) in CKEditor write in your config.js file this lines:
CKEDITOR.editorConfig = function( config ) {
config.allowedContent = true;
};
Source code here.
What's the best way to get usable DOM for an AJAX-requested page without loading any related images/scripts/etc?
Backstory:
I want to load a page in background, then perform a sort of data-mining on it (this is a browser extension, so I can't control the pages themselves). I do not want to spend time loading images and running scripts on the background page, since it is only page contents I need.
load data via ajax
strip all the tags containing src and href attributes, or simply change the value of those attributes with data:null. If data also contains inline style you should remove all statements containing a reference to external resources (e.g. background and border images, .htc components, xul bindings, .ico cursor)
append filtered data to the DOM and analyze it
step 2 could be achieved through a regular expression in javascript. e.g.
/* here we are in the ajax "success" callback */
...
data = data.replace(/(src|href|style)=['"]([^'"]+?)['"]/gi,
function(match, attribute) {
return (attribute.toLowerCase() === 'style')
? attribute + '=""' /* remove all inline style */
: attribute + '="data:null"'; /* href and src set to data:null */
})
/* append filtered data */
$(data).appendTo($('body_or_other_element'))
If possible, use jQuery, as I mentioned above. It makes it easy to select portions of the page DOM as needed.
Here are some examples:
You can grab tags href attribute like this: $("a", $(ajax_response)).attr("href");
Title's contents: $("title", $(ajax_response)).html();
You might have to test out the selectors to see which work best, but, I think this would be an easy way of going about this.