closethick button disappear liferay popup 6.2 - popup

I am migrating the AUI popup dialog window from liferay 6.1 to liferay 6.2. I see that there are some specific changes to be made. I had some problems with display of buttons but it is resolved now. But the problem is with the close icon (x) which should be on the top right corner. It disappeared suddenly as soon as I added a save button.
Here is my code:
myPopup = AUI().use('aui-base','liferay-util-window','aui-io-deprecated', 'event', 'event-custom', function(A) {
var buttons =[{
cssClass: 'button_close',
label: 'Save',
render:true,
id: 'myPopupButton',
on: {
click: function() {
myPopupSubmit();
}}
}];
myPopup = Liferay.Util.Window.getWindow(
{
dialog: {
title : a + ' mytitle',
centered : true,
height : 600,
width : 500,
draggable : true,
resizable : true,
modal : true,
toolbars: {
footer:buttons
},
}}).plug(A.Plugin.IO, {
uri : url
}).render();
myPopup.show();
});
}
Please let me know if you have any idea on it..
on myPopupSubmit I have also written code to close the popup as:
top.document.getElementById('closethick').click();
Since there is no closethick button it returns null.

Using the modal dialog example as a comparison, the X close button is removed when using the toolbars property.
Reviewing the source code for the toolbars property (line 309 at time of writing this) indicates that if you use this property directly, you'll need to include your own X close in the header.
An alternative would be to use the addToolbar function (as seen in the example) to include your buttons while preserving the default toolbars.
modal.addToolbar([{
cssClass: 'button_close',
label: 'Save',
render:true,
id: 'myPopupButton',
on: {
click: function() {
myPopupSubmit();
}
}
}]);
I would also consider making the instance of the dialog available to your myPopupSubmit function so that you would have direct access to perform dialog.hide() or calling dialog.hide() after myPopupSubmit versus using the X close approach.
If sticking with the current approach, the id being used will not work, you'll need to use a CSS selector as the YUI based id will change.

Related

How to simulate click event for tinyMCE v6x custom toolbar button programmatically

This is simple enough in earlier version of tinyMCE, but I can't find a way to make it work in v6x (suggested answers here only apply to earlier versions, that I can see)
Here's my button:
tinymce.PluginManager.add('newButton', (editor, url) => {
editor.ui.registry.addButton('newButton', {
text: 'Click me',
enabled: true,
onAction: () => {
alert('You clicked me')
}
})
return {
getMetadata: () => ({
name: 'newButton',
url: ''
})
}
});
tinymce.init({
selector: "textarea",
plugins: "newButton",
toolbar1: "newButton"
});
This works fine - click the button and you get an alert telling you you have. What I want to do now is call this click event from code (JaveScript) - I was hoping
tinymce.activeEditor.buttons['newButton'].onclick();
would work, as it does for - say - the "code" plugin; i.e. add this plugin (and button) to the editor and calling
tinymce.activeEditor.buttons['code'].onclick();
simulates clicking the toolbar button. So... how can I "click" my own custon toolbar button?
[edit] well.. that last line did work, I swear it did. Now it doesn't. wt.. :(
This may not be the "right" way (well, I know it isn't!) but I've found a way that works :)
First, I need a way to identify/find my custom button. I figured out tinymce renders them as div elements, and using
var divs = document.querySelectorAll('button');
divs.forEach((div) => {
console.log(div.innerHTML);
})
I am able to identify it and find the HTML used - it is not graced with an id, but we can use the innerHTML property (as identified) to get it and then simulate a click- viz:
var divs = document.querySelectorAll('button');
divs.forEach((div) => {
// NB 'DOC' is the text property of my custom button
if (div.innerHTML === '<span class="tox-tbtn__select-label">DOC</span>') {
// now we can simulate a click on it:
var evt = new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true
});
div.dispatchEvent(evt);
return;
}
})
(Thanks to the second answer, by Derek, here:
How to simulate a mouse click using JavaScript?
for the simulate click code)
[edit] better to use a for-loop rather than forEach as there's no sensible way to break out of the latter - that "return" doesn't actually do anything.

Make Upload tab the default in Insert/Edit Image dialog

Using TinyMCE 5.7.0
Is there a way to make the "Upload" tab the default tab displayed in the Insert/Edit Image dialog?
I'm looking for a configuration option or programmatic way to do this so we can continue to easily update TinyMCE when new versions come out.
In TinyMCE (5.7.0 in my case, not the minified version), open plugins/image/plugin.js.
Search for these lines (1462 to 1466):
tabs: flatten([
[MainTab.makeTab(info)],
info.hasAdvTab ? [AdvTab.makeTab(info)] : [],
info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : []
])
Reorder the lines like this:
tabs: flatten([
info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : [],
[MainTab.makeTab(info)],
info.hasAdvTab ? [AdvTab.makeTab(info)] : []
])
We had the same requirement and this is how we did it.
Instead of adding the "Upload Image" option to toolbar, create a keyboard shortcut for opening the image upload modal using addShortcut method. Something like this in reactjs:
editor.addShortcut('ctrl+shift+i', 'Open image upload window', function () {
editor.execCommand('mceImage')
});
Now that we have a code block that runs when pressing the shortcut keys, we can add logic inside that block to initiate a click action on the "Upload" button within the modal like this:
setTimeout(() => {
let element = document.querySelectorAll('.tox-dialog__body-nav-item')[1];
if (element) { element.click() }
}, 0)
The setTimeout is added to make sure that the modal is added to DOM before run the querySelectorAll method on the document object is executed. Timeout even with 0 will make sure the code block only executes after all the synchronous tasks are done, which includes the DOM update.
In the end, the final codeblock will look like this:
editor.addShortcut('ctrl+shift+i', 'Open image upload window', function () {
editor.execCommand('mceImage')
setTimeout(() => {
let element = document.querySelectorAll('.tox-dialog__body-nav-item')[1];
if (element) { element.click() }
}, 0)
});
Edit:
If you notice other elements in the DOM with the same class as "tox-dialog__body-nav-item", you can change the querySelectorAll method to make it more well defined and make sure it only selects the class within image upload modal if found. I haven't yet ran into this issue, so this was enough for my case.

SAPUI5 using Popover as a tooltip

I'm trying to use the sap.m.Popover as a "rich tooltip" for some controls. This is as per recommendation from SAP because the sap.ui.commons library is now deprecated. We have too much text we want to add to the standard string tooltip. I haven't figured out a way to use the popover directly as a tooltip, which is why I've extended the TooltipBase control to handle the popover.
I've got the popover working fine, However when I interact with my control, I get the following error:
Uncaught Error: failed to load 'myNewToolTip/controls/TooltipBaseRenderer.js' from ../controls/TooltipBaseRenderer.js: 404 - Not Found
I see from these threads that it is because the TooltipBase class is an abstract class and therefore doesn't have a renderer. However, because I'm already using the popover, I don't need to render anything. I've tried to add the TooltipBaseRenderer.js and just have an empty render class. But UI5 really doesn't like that either.
My question is what should I do, I see two options:
There is probably a simple way to use the popover as a tooltip, which I'm just too stupid to figure out (Bear in mind, I'd prefer to bind it directly in the XML view).
Figure out a way to suppress the renderer call as I don't need it.
This is my current source code for the custom control:
sap.ui.define([
"sap/m/Popover"
], function (Popover) {
"use strict";
return sap.ui.core.TooltipBase.extend("myNewToolTip.TooltipBase", {
metadata: {
properties: {
title : {}
},
events: {
"onmouseover" : {},
"onmouseout" : {}
}
},
oView: null,
setView: function(view) {
this.oView = view;
},
onmouseover : function(oEvent) {
var that = this;
if (!this.delayedCall){
this.delayedCall = setTimeout(function() {
if (!that.oPopover){
that._createQuickView();
}
}, 500);
}
},
onmouseout: function(oEvent) {
if (this.oPopover){
this.closePopover();
this.delayedCall = undefined;
}
else{
clearTimeout(this.delayedCall);
this.delayedCall = undefined;
}
},
_createQuickView: function() {
var sTitle = this.getTitle();
this.oPopover = new Popover({
title: sTitle
});
this.oPopover.openBy(this.getParent());
},
closePopover: function(){
this.oPopover.close();
this.oPopover = undefined;
}
});
});
There is no need to create a custom control just to display a popover on mouseover. As you said, there is a simpler way: Adding event delegates.
One of the events that delegates can listen to is onmouseover which can be achieved like this:
this.byId("myTargetControl").addEventDelegate({
onmouseover: function () {
// Open popover here
}
});
Demo: https://embed.plnkr.co/jAFIHK
Extending sap.ui.core.TooltipBase
If you still consider extending TooltipBase (without Popover), take a look at this example: https://embed.plnkr.co/33zFqa?show=control/MyCustomTooltip.js,preview
Keep in mind, though, that tooltips in general shouldn't contain critical information due to its lack of discoverability as Fiori Design Guideline mentions
Tooltips (...) should never contain critical information. They should also not contain redundant information.
Just as a friendly reminder :) Don't make people hover to find things.

How to add a custom control to the TinyMce 4 toolbar

I want to introduce a new Control to TinyMce that I can use in the toolbar. In my case I want to add an icon control that can be placed at the start of the toolbar to differentiate between editors.
However there is almost no information about how to properly do this.
Finally I managed to come up with a way to properly do this.
First I introduce a new plugin icon (in icon/plugin.js) that registers a new control Icon. It uses a setting iconClass.
tinymce.PluginManager.add('icon', function() {
tinymce.ui.Icon = tinymce.ui.Widget.extend({
renderHtml: function () {
return '<span class="icon icon-' + this.settings.iconClass + '"> </span>';
}
});
});
Next I add a button facebook to the toolbar in the following way:
editor.addButton('facebook', {
type: 'icon',
iconClass: 'facebook-share'
});
Now I can add it to the toolbar specification:
tinymce.init({
toolbar: "facebook"
})
That's it! The new custom control should not render. The plugin code is only ran once; even if used multiple times.

Is there any event handler in EXTJS Paging Toolbar's Buttons?

I am new with EXTJS 4 and this forum. Sorry if it's already discussed in another thread, but I didn't found it.
My question is, I want my Grid Panel with Pagination to update it's store every 10 seconds. I have found a solution using userStore.loadPage(current_page), but it has a problem.
Some time, updating Grid Panel nearly in same time with user click "next" or "prev" in Pagination. This make Grid Panel to not working properly. What I want is, when I click "next" or "prev" or "refresh", the previous request (userStore.loadPage(current_page)) is aborted. So it will not interfere my current request.
But I didn't found event in EXTJS Paging Toolbar to handle "next", "prev", or "refresh" button. What is the solution for this issue? Is there any way?
This is my code just for reference:
// create User Store
var userStore = Ext.create('Ext.data.Store', {
model: 'EDC',
autoLoad: true,
pageSize: 10,
proxy: {
type: 'ajax',
url : 'Monitoring', // it is using Java servlet, so I write it this way
reader: {
type: 'json',
root: 'edc',
totalProperty: 'total'
}
}
});
// create Grid Panel
Ext.create('Ext.grid.Panel', {
store: userStore,
width: 800,
height: 400,
columns: [
{
text: "ID",
width: 50,
dataIndex: 'id'
},
{
text: 'Serial Number',
flex: 1,
dataIndex: 'sn'
}
// etc...
],
dockedItems: [{
xtype: 'pagingtoolbar',
store: userStore,
dock: 'bottom',
displayInfo: true
}]
});
It is how it is updated every 10 seconds
// after on Ready, reload every 10 seconds
Ext.onReady(function(){
self.setInterval("reloadCurrentEdc()", 10000);
});
// function for update
function reloadCurrentEdc(){
if(typeof userStore != 'undefined'){
userStore.loadPage(userStore.currentPage);
}
}
I think your problem is that your 'auto load' and your 'manual load' are so close together that your grid handles the result coming back from the first request as the second one.
I do agree with Alshten that the best way is to avoid requests that are so close together, you can do this by disabling the store load when there is already a store load in progress. but if you want your functionality I think you can do something like this:
listen to beforeload( Ext.data.Store store, Ext.data.Operation operation, Object eOpts ) event on the store, save the eOpts; listen to load( Ext.data.Store this, Ext.util.Grouper[] records, Boolean successful, Ext.data.Operation operation, Object eOpts ) compare the eOpts with the one you saved, if they are not the same, you know it's not the results you want.
You can have a look to the documentation about the paging toolbar component :
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.toolbar.Paging
There is a change which is fired every time the current page is changed, so it will be fired for "next" and "prev" click events. I haven't tried but I think it may be fired for "refresh" as well.
In my view, the best design would be to disable the buttons of the paging toobar (using the disable() function of this component) while the automatic reload is loading.
I use this selector: "gridpanel pagingtoolbar #refresh".
I'm able to use in my Controller classes in the init method mostly.
You can replace gridpanel with the alias or itemid of your grid.
.
.
.
init: function() {
this.control({
'gridpanel pagingtoolbar #refresh':{
click:function(){
console.log('grid panel', arguments);
}
}
});
},
.
.
.
Use
beforehange: function (tbar, pageData, eOpts) {
// here you can load data from server and load the data to store
return false // will avoid triggering store events
}
pageData is the page number
all button clicks like next/prev/refresh will trigger this function