I have a page with multiple TinyMCE editors (org.vaadin.tinymce.TinyMce), and I want to know which the user is 'in'. One approach would be to use the focus/blur events, but I've tried adding a class like this:
public class MyTinyMce extends TinyMce implements Focusable<TinyMce> { ... }
and then associating event handlers like this:
myTinyMce.addFocusListener(e -> {
System.out.println("focus!!");
});
myTinyMce.addBlurListener(e -> {
System.out.println("blurred!!");
});
but the events don't fire reliably. If I do the exact same thing with a Text component, it works as expected.
I say not "reliably" because they do fire if I click on the empty space in the TinyMCE toolbar (to the right of 'Tools' in the screenshot), but not if I click on the TinyMCE menu or into the editable body.
screenshot
Am I doing something wrong, or does the TinyMCE component simply not support this use-case? Is there another way to keep track of the user switching between different editors?
Related
I'm developing an MS Word add-in. In newer MS Word editions, there is the "FILE" option in the menu bar which opens an interface where you can select a recent document to open, open a new one, or an existing one. I am trying to find a way, through which I can know WHEN the user "leaves" the current document he is editing clicking on the FILE menu of Word. I cannot seem to find such an event. Is there a way to achieve this ?
The WindowDeactivate does not fulfill this purpose.
The reason I want to do this, is because for a custom spellchecker I'm writing, I'm highlighting the wrong words in an transparent (click through as well) form. So when the user in a recent version of Word clicks the FILE menu, the highlights are still there, as seen in the screenshot
TL:DR; is there a way to detect in MS Word when the user clicks the FILE option in the menu and the current document is not visible? I'm using add-in-express, so all the relevant word object model API is available.
I wonder how can I solve this, any help is appreciated.
edit: screenshot
Yes, you can detect and then execute code both when the File menu is clicked (displaying the Backstage View) and when the View's return arrow is clicked to remove the Backstage View and display the document. To do this use the onShow and onHide attributes with callbacks via a custom XML ribbon in your VSTO project (this will not work with a ribbon made with the Visual Designer).
Reference material can be found here:
Performing Actions When the Backstage View is First Displayed or Hidden
As this article uses VBA to expand on the concepts involved, I built a sample project demonstrating how onShow works using C# and Word 2016 (the documentation was written for Office 2010, but onShow and onHide will work in later versions of Word).
Solution Tree
Custom XML Ribbon (BackstageRibbon.xml)
Note that the <backstage> node, which activates the onShow attribute for the callback, follows the <ribbon> node in the XML.
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
onLoad="Ribbon_Load">
<ribbon>
<!--Ribbon XML goes here-->
</ribbon>
<backstage onShow="onShow">
</backstage>
</customUI>
Ribbon Code (BackstageRibbon.cs)
A bunch of this code is boilerplate, however public void onShow is the callback that executes your code based on the onShow attribute in the ribbon's custom XML. Also, public string GetCustomUI is where the C# is told to find the XML.
namespace Backstage_Events
{
[ComVisible(true)]
public class BackstageRibbon : Office.IRibbonExtensibility
{
private Office.IRibbonUI ribbon;
public BackstageRibbon()
{
}
#region IRibbonExtensibility Members
public string GetCustomUI(string ribbonID)
{
return GetResourceText("Backstage_Events.BackstageRibbon.xml");
}
#endregion
#region Ribbon Callbacks
//Create callback methods here. For more information about adding callback methods, visit https://go.microsoft.com/fwlink/?LinkID=271226
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
}
public void onShow(object contextObject)
{
//Code to be executed before Backstage View displays goes here
MessageBox.Show("Backstage Display Event Triggered!");
}
#endregion
Helpers //Region
}
}
ThisAddin.cs
You will also need to add:
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new BackstageRibbon();
}
after the ThisAddIn_Startup and ThisAddIn_Shutdown private voids in the ThisAddin.cs class to instantiate the custom ribbon.
Word will fire the Application.DocumentOpen event - you can see it live in OfficeSpy (I am its author - click Application button, go to the Events tab, look at the log at the bottom of the window).
I am adding menu buttons to a tinymce editor. In this interface there are multiple tinymce editors loaded on the page at once. The menu buttons I am adding all do some custom styling either using the formatter or by applying custom css classes to selected elements. As part of one of the items I need to also "remove all formatting" from the selection as well as add some text around the selection. There is already a built-in plugin that does this, so I would like to just call that function from my plugin.
I got this working by using jQuery to click the "remove all formatting" button, however since there are multiple editors on the page, this makes the page scroll from where the user is at, depending on which button actually gets clicked by jQuery.
I would rather not use this approach because i feel like it would be much cleaner and provide a better result to execute the remove formatting code from my plugin, but I am unsure how to access the function I need to call.
{
type: 'menuitem',
text: 'Sample Answer',
onAction: function() {
$('button[title|="Clear formatting"]').click(); //I would like to call this function here instead of jQuery clicking a button.
editor.formatter.apply('sample_answer');
}
},
So after some more digging, it appears that a certain amount of tinymce commands can be executed using editor.execCommand RemoveFormat is one of the commands you can use, so they made it easy on me for what I need to do.
It would still be nice to know if there was a way to execute other functions if I wanted to, but the execCommand function definitely solves this issue.
{
type: 'menuitem',
text: 'Sample Answer',
onAction: function() {
editor.execCommand('RemoveFormat');
editor.formatter.apply('sample_answer');
}
},
I want to set the focus to a certain field (org.gwtbootstrap3.client.ui.Input) in a dialog (org.gwtbootstrap3.client.ui.Modal) before the dialog shows up. The use case seem quite common, if you have a dialog with a single field like the Upload text or Add feed dialogs right here. However I could not figure out how to set the focus to this particular gwtbootstrap3 component.
The Input component does have a setFocus(true) method. I assumed that setting the focus before showing the dialog would not work, which it doesn't. So the logical solution is to put the method call inside a ScheduledCommand. Like this:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
textField.setFocus(true);
}
});
That usually works with GWT standard components, but does not seem to help in this case. I found a way to get notified once the dialog is shown through a ModalShowHandler. Like this:
modal.addShowHandler(new ModalShowHandler() {
#Override
public void onShow(ModalShowEvent evt) {
textField.setFocus(true);
}
});
I even tried to combine both, adding a deferred call to the handle. No luck. Any ideas?
You should be listening on the ModalShownEvent (note: Shown, not Show).
ModalShowEvent is fired when the modal is requested (for example, programmatically) to be shown.
ModalShownEvent is fired when the modal is actually shown.
This somewhat confusing naming is based on the events of the native Bootstrap Modal's events: show.bs.modal and shown.bs.modal.
ModalShownEvent combined with the usual Scheduler#scheduleDeferred should do the trick.
I am trying to open an email client just like using mail me tag.
But I want to use my custom widget, which is not hyperlink, anchor or so. I added a DOM handler to my widget to listen to clicks:
public class VContactWidget extends VHorizontalLayout implements ClickHandler {
private HandlerRegistration clickHandler;
public VContactWidget() {
// added some content here
clickHandler = addDomHandler(this, ClickEvent.getType());
}
#Override
public void onClick(ClickEvent event) {
Window.open("mailto:john.doe#mail.com", "_blank", "");
}
}
Everything is working fine except one detail: When the widget is clicked, new empty browser tab will open with url set to mailto:john.doe#mail.com. I don't want the new tab opened. Can I avoid it somehow?
Note I set _blank parameter, as used in many examples. I also tried to use empty string or some other values as well. I looked into documentation, but didn't find anything useful.
https://developer.mozilla.org/en-US/docs/Web/API/window.open
One solution may be to use Anchor, but my component is more complex, not just single <a> link.
Another detail to note may be application server - I am using Tomcat 7 now.
Trying to fire native event on hidden Anchor programatically did not work for me. (Which does not mean it cannot be done.)
This is, how I actually solved my problem: Instead of Window.open(), I used following call:
public void onClick(ClickEvent event) {
Window.Location.assign("mailto:john.doe#mail.com");
}
This is not something that you can control. Whether this link opens in a new tab or a new window depends on the browser settings and user preferences.
I don't think it will make a difference if you use an Anchor or Window.open. In either case, the behavior may be different in different browsers. Also remember that for some users a click on this link will open Outlook or Mail, while for other users it will open Gmail in a browser window.
UPDATE:
If you want an exact behavior of an <a> element, create a hidden anchor element and fire a click on it when a user clicks on your composite widget.
Firing click event from code in gwt
I have a ListView that displays a list of Panels, one below the other. Every panel features a button (implemented via AjaxLink) that closes the panel and removes it from the list.
This is how the ListView is initalized and how the panels are created:
panelsList = new ArrayList<MyPanel>();
pnlContainer = new WebMarkupContainer("pnlContainer");
ListView<MyPanel> pnlItems = new ListView<MyPanel>("pnlItems", panelsList) {
#Override
protected void populateItem(final ListItem<MyPanel> item) {
item.add(item.getModelObject());
item.add(new AjaxLink<Void>("pnlClose") {
#Override
public void onClick(AjaxRequestTarget target) {
panelsList.remove(item.getModelObject());
target.add(pnlContainer); // repaint panel container
}
});
}
};
pnlContainer.setOutputMarkupId(true);
pnlContainer.add(pnlItems);
add(pnlContainer);
This works so far - the actions that trigger adding new panels (usually also AjaxLinks) do what they should and the new panel is added and displayed correctly. But I have problems getting the close button to fully work.
Please see the following steps:
1) I start the server and navigate to the main page. The ListView is initially populated with one panel.
Close-button-code of this panel:
<a wicket:id="pnlClose" id="pnlClose7" href="javascript:;">Close</a>
Searching the page code for pnlClose7 finds the following javascript code that makes the button work as expected:
Wicket.Ajax.ajax({"u":"./?0-1.IBehaviorListener.0-pnlContainer-pnlItems-0-pnlClose","e":"click","c":"pnlClose7"});;
Note: I do not press the button now, if i would, it would work as expected (thoroughly tested).
2) I trigger an action that opens a second panel. The panel is displayed below the first one as expected.
Close-button of the first panel:
<a wicket:id="pnlClose" id="pnlClosef" href="javascript:;">X</i></a>
Close-button of the second panel:
<a wicket:id="pnlClose" id="pnlClose10" href="javascript:;">X</i></a>
But now, neither searching for pnlClosef nor pnlClose10 finds some javascript code. The buttons (both!) do not work. I can still find the javascript code for pnlClose7.
3) I reload the page via pressing F5.
The button IDs change to pnlClose1a and pnlClose1b. Both IDs have javascript counterparts and work.
4) I press the first button (upper panel, ID pnlClose1a). The panel is closed as expected.
The remaining button's ID changes to pnlClose1c, again without a javascript counterpart. Javascript code for pnlClose1a and pnlClose1b is still present.
To make a long story short, the javascript handlers for my AjaxLinks seem to have shyness issues and only appear after I press F5 or reload the whole page in any other manner. I guess thats because repainting the pnlContainer changes the IDs of the current panels - but why is the linked javascript not updated at the same time? Is there anything I can change in my code to update the whole page without completely reloading it?
Wierd thing is that I am pretty sure this worked before... But I checked the whole class history and can't find any major change that would have triggered that. The ListView-code is mainly static since I added it.
I was had similiar problem. if you have any hardcoded javascript code in your page or panels html file (using <script> tag) remove it and set that js code in renderHead of your panel.