tinymce 3.5.4.1 adding event handlers, lots of errors - tinymce

I'm adding a TinyMCE editor to one of our pages. For reasons above my pay-grade, we're using TinyMCE 3.5.4.1.
It's gone pretty well, except when I try to wire in an onFocus event handler. If I don't try to use the handler, the editors show up and work fine but on pages where I define a handler, there are boatloads of exceptions inside TinyMCE for the browser types I've tried (IE8,9,10 and Chrome).
I've been using templates from other posts I've seen on here but I haven't seen mention of all these TinyMCE exceptions. Of course, trying to unwind the minified script is a real pain.
The first example I found here had a setup function in the TinyMCE config like this:
, setup: function (ed) {
ed.onInit.add(function (ed, evt) {
if (!myFocus) return; // global for the handler to use
var dom = ed.dom;
var doc = ed.getDoc();
tinymce.dom.Event.add(doc, 'focus', myFocus);
});
}
When myFocus is defined, there are a number of exceptions TinyMCE throws starting with
if (j.isIE){l.attachEvent(...)} complaining that l.attachEvent doesn't exist. Then it moves on to all kinds of variable type mismatches.
Chrome developer tools are much more awkward fiddling with minified code, so I'm not sure what all it doesn't like.
Another post I found here suggested doing some minimal browser detection but this helped neither IE nor Chrome.
var doc = s.content_editable ? ed.getBody() : (tinymce.isGecko ? ed.getDoc() : ed.getWin())
Another post suggested a different approach, but I still had all the same errors in both browsers.
, setup: function (ed) {
ed.onInit.add(function (ed, evt) {
if (!myFocus) return;
ed.onFocus.add(myFocus);
});
}
I've also just tried (in vain)
, setup: function (ed) {
if (!myFocus) return;
ed.onFocus.add(myFocus);
}
Is event handling in TinyMCE just very fragile? Not well supported across browsers? Should I just steer clear of it and try using jQuery or something else?
Thanks
Mark

Turns out to be a pilot-error bug being deferred until the extend calls created the editor.

Related

How to specify event handlers when using lit-html?

The main documentation under [Writing Templates] the following example for binding an event handler with lit-html is provided.
html`<button #click=${(e) => console.log('clicked')}>Click Me</button>`
Adding this a simple page with the default render and html functions imported and calling render however doesn't seem to render the button. If you remove the #click event binding then the button is rendered. There must be something I'm missing or a serious bug in the library.
version: 0.10.2
The links below relate to how events handler bindings work in lit-html:
https://polymer.github.io/lit-html/guide/writing-templates.html
https://github.com/Polymer/lit-html/issues/399
https://github.com/Polymer/lit-html/issues/145
https://github.com/Polymer/lit-html/issues/273
https://github.com/Polymer/lit-html/issues/146
The previous accepted answer was wrong. lit-extended is deprecated and that workaround only worked for a period in 2018 while lit-html was switching over to the new syntax.
The correct way to consume an event is:
html`<button #click=${e => console.log('clicked')}>Click Me</button>`
You can configure the event by assigning an object with a handleEvent method too:
const clickHandler = {
// This fires when the handler is called
handleEvent(e) { console.log('clicked'); }
// You can specify event options same as addEventListener
capture: false;
passive: true;
}
html`<button #click=${clickHandler}>Click Me</button>`
There is also lit-element which gives you a base for building web components with Lit and TypeScript enhancements to move the boilerplate noise of creating event handlers into decorators:
#eventOptions({ capture: false, passive: true })
handleClick(e: Event) { console.log('clicked'); }
render() {
return html`<button #click=${this.handleClick}>Click Me</button>`
}
It appears that in order to use event handler bindings one must not use the standard lit-html API but instead lit-extended which appears to be distributed along with lit-html. Changing import statement to import lit-extended and changing the attribute syntax as shown below seems to work for me.
Before:
import { html, render } from "lit-html";
html`<button #click=${(e) => console.log('clicked')}>Click Me</button>`
After (working):
import { html, render } from "lit-html/lib/lit-extended";
html`<button on-click=${(e) => console.log('clicked')}>Click Me</button>`
Note that the #click syntax didn't seem to work for me at all regardless of what several examples show in the GitHub issues as well as the main documentation. I'm not sure if the above syntax is the preferred way or only way to do event binding but it seems to be one that is at least working.
To me it looks like this may be a good candidate for contributing improvements to the lit-html documentation.

PhantomJS : Modifiy dom before rendering page

I'm using PhantomJS 2.1.1
to be able to grab a webpage and generate a screenshot.
It's working... BUT I want do to some DOM manipulation (in javascript) before rendering the page into a png.
What I am doing is (in few step to summarize):
page.open(http://my_url.htm), function(status) {
if (status === 'sucess') {
waitFor(isPageLoaded, grabPage, 30000); //waitFor function is one provided by PhantomJS in example
}
};
function grabPage() {
page.render('screenshot_raw.png'); //this is working well
page.evaluate(function() {
document.querySelector('[id^="boardBackgroundImg-"]').style.filter = 'invert(1)';
}
page.render('screenshot_remodel.png'); //same screenshot as before
phantom.exit();
}
When doing myself in a firefox consol, the:
document.querySelector('[id^="boardBackgroundImg-"]').style.filter = 'invert(1)';
it's working weel!
But into my phantomjs script... it does nothing (but no error).
I've tried to put it in a external js file and use injectJS() or includeJS() but it does not help more.
Is someone having an idea?
Obviously I want to do some little bit more DOM transformation (removing some node).
Regards.
Update
I've updated my code to do at the end:
fs.write("test.htm", page.content, 'w');
phantom.exit()
The file content does not contains the DOM change I've provided.
So it seems that page.evaluate(...) is readonly. Just here to grab data from page content.
Is there a way to modify the DOM before rendering the page in PhantomJS?
Regards
PhantomJS v2.1.1's Webkit rendering engine is rather old now and it doesn't fully support modern CSS or Javascript. Try using puppeteer if you can.

Protractor element.click() throwing an exception

I was trying to figure out why .click() below was crashing protractor :
this.clickSecondPanel = function () {
element(by.css('div.panels-gs.panel-top-two-gs')).click();
}
until I changed the line to :
element(by.css('div.panels-gs.panel-top-two-gs')).click;
where my spec.js looks something like :
var DataCardPage = require('./pageObjects/dataCard.page.js');
var dataCardPage = new DataCardPage();
describe('Clicking on the 2nd panel', function () {
dataCardPage.clickSecondPanel();
it('Should select the 2nd test panel', function () {
expect(dataCardPage.getSecondPanelText()).toBe('TEST123');
});
In other places in my code, I use .click() (with parenths), so this is confusing to me.
The error is nasty:
Started
[17:44:23] E/launcher - Error while waiting for Protractor to sync with the page
: "window.angular is undefined. This could be either because this is a non-angu
lar page or because your test involves client-side navigation, which can interfe
re with Protractor's bootstrapping. See http://git.io/v4gXM for details"
Any advice appreciated...
Bob
Solved this in the comments above, posting as an answer.
My suggestion was to try moving the clickSecondPanel() inside the it block. It looked suspicious by itself just from a "best practice" perspective as I do not have any code that is outside of a jasmine function i.e. it, beforeAll, afterAll etc (don't even know where I learned that habit honestly).
It also seemed to effect the control flow and asynchronous execution so the click() event was triggering too soon. This can be explained in part by this documentation and/or this blog post
Try using browser.ignoreSynchronization=true at the begining of your test. May be the application that you are trying to automated does not contain angular in it.

Protractor + ionicPopup

Has anyone succeeded in using Protractor to detect an ionicPopup alert?
I've tried all the workarounds suggested here but no luck.
I need Protractor to detect the alert and check the text in the alert.
Here's the class I wrote to test that the popup exists and to ensure the text is correct in the header and body:
var TestUtilities = function(){
this.popup = element(by.css('.popup-container.popup-showing.active'));
//Tests to see if $ionicPopup.alert exists
this.popupShouldExist = function() {
expect(this.popup.isDisplayed()).toBeTruthy();
};
//Tests to see if $ionicPopup.alert contains the text provided in the argument exists in the header
this.popupContainsHeaderText = function (text) {
this.popupShouldExist();
expect(this.popup.element(by.css('.popup-head')).getText()).toMatch(text);
};
//Tests to see if $ionicPopup.alert contains the text provided in the argument exists in the body
this.popupContainsText = function (text) {
this.popupShouldExist();
expect(this.popup.element(by.css('.popup-body')).getText()).toMatch(text);
};
};
module.exports=TestUtilities;
Also check out this site for more on testing Ionic in protractor it talks about how to check to see if the popup exists: http://gonehybrid.com/how-to-write-automated-tests-for-your-ionic-app-part-3/
I've tested Ionic popups successfully by setting the popup variable as follows:
var popup = element(by.css('.popup-container.popup-showing.active'));
And in the test:
expect(popup.isDisplayed()).toBeTruthy();
Ionic Popups are just made of DOM elements, so you should be able to use normal locators to find/test them. Because they're not made of alerts, the workarounds in the issue you linked to are probably not useful.
I got it - I saw a lot of issues out there trying to do it in very complex ways, but in the end I tried this and it turns out to be this simple.
Inspect your element and find its ng-repeat value, then
var button = element(by.repeater('button in buttons')).getText()
You also need to have the browser sit out somehow for a couple seconds so it doesn't resolve to the tests while the ionic popup isn't actually there.
For that, browser.sleep(3000);
That's it! However, getting the other button in there is proving to be a little problem. var button = element(by.repeater('button in buttons')).get(0) or .get(1) return undefined is not a function.
Please accept the answer if you like it! If I figure out how to get the other button, I'll post it here.

IPython/Jupyter Installing Extensions

I'm having troubles installing extensions in IPython. The problem is that i can't get the extensions load automatically, i have followed the instructions in the github page but it just doesn't work. According the the homepage i need to modify the custom.js file by adding some lines. I want to install the codefolding, hide_input_all and runtools extensions. This is how my custom.js file looks:
// activate extensions only after Notebook is initialized
require(["base/js/events"], function (events) {
$([IPython.events]).on("app_initialized.NotebookApp", function () {
/* load your extension here */
IPython.load_extensions('usability/codefolding/codefolding')
IPython.load_extensions('usability/runtools/runtools')
require(['/static/custom/hide_input_all.js'])
});
});
The extensions work well if i call them manually, for example, if i type
%%javascript
IPython.load_extensions('usability/runtools/runtools/main');
the runtools appear and works perfectly, but i want the extensions to be loaded automatically and not to have to call them manually every time. Could someone tell me where is my mistake?
There's been a little change to the syntax. Nowadays, $ might not be defined by the time your custom.js loads, so instead of something like
$([IPython.events]).on("app_initialized.NotebookApp", function () {
IPython.load_extensions("whatever");
});
you should do something like
require(['base/js/namespace', 'base/js/events'], function(IPython, events) {
events.on('app_initialized.NotebookApp', function(){
IPython.load_extensions("whatever");
})
});
with the appropriate changes to braces and parentheses. For me, the former will work more often than not, but certainly not always; it fails maybe ~1/3 of the time.
If that doesn't do it for you, open up Developer Tools (or whatever is relevant for your browser) and look at the javascript console for errors. That'll help figure out what's going wrong.