The idea here is to remove/disable certain items from the Actions Dropdown Menu from an Interactive Grid.
I've managed to disable the "Aggregate" option so far with the following code:
`function(config) {
config.initActions = function( actions ) {
actions.hide("show-aggregate-dialog");
}
return config;
}`
Now I'm trying to do the same with some other options, such as Refresh (shown as Aktualisieren), but the following line, which was added to the previous code, does nothing:
actions.hide("show-filter-dialog");
I've tried a couple things to attempt and remove the rest, such as the the none !important css function, without results:
#ig_id button[data-action="show-filter-dialog"] {
display: none !important;
}
I've attempted the Remove action as well, with no success:
actions.remove("show-filter-dialog");
Also with the use of the "Index menu removal" function, I managed to remove the whole Daten option, though I'd prefer only disabling certain items from it, not the whole thing:
var $ = apex.jQuery;
var toolbarData = $.apex.interactiveGrid.copyDefaultToolbar();
config.toolbarData = toolbarData;
toolbarData[3].controls[0].menu.items[3]['hide'] = true;
return config;
Is there something wrong with the methods I'm using? Are they capable of changing these items? Or I can only change these with plugins?
Also, I sometimes feel confused on where I should be putting some of these codes. Should javascript functions be put only in the Attributes section of the Interactive Grid or in the When Page Loaded section?
So, after a bit of experimenting and messing around with the code, I managed to solve everything here. I'm posting the solution in case someone else might want to use it as well. There might be better, easier and likely more unified ways of hiding it, rather than using so many different functions, but I suppose I have to learn more about Javascript first. This is the code and the properties that worked for me:
function(config) {
config.initActions = function( actions ) {
actions.hide("show-aggregate-dialog"); // hides Aggregate
actions.hide("refresh"); // Hides Refresh inside "Data"
actions.hide("chart-view"); // Hides Chart. Thanks to Alli Pierre Yotti in Apex Forums
actions.remove("show-columns-dialog"); // Hides Columns
actions.remove("show-filter-dialog"); // Hides Filter
actions.remove("show-help-dialog"); // Hides Help
}
var $ = apex.jQuery;
var toolbarData = $.apex.interactiveGrid.copyDefaultToolbar();
config.toolbarData = toolbarData;
toolbarData[3].controls[0].menu.items[4]['hide'] = true; // Hides Format
toolbarData[3].controls[0].menu.items[8]['hide'] = true; // Hides Report
config.features.flashback = false; // Hides Flashback
return config;
}
Related
I have a Virtualize table that does exactly what it needs to do and does it great. I now have the need to add a tooltip/popover to certain rows. This is not difficult, but I am noticing that it will not get the JavaScript portion of the setup for these tooltips to run. It seems like when I click in the table somewhere it realizes things have changed and calls the JS setup function. At that point it works great.
<Virtualize #ref="RowsVirtualizerLeft" ItemsProvider="RowsLoader" Context="row" ItemSize="RowHeight">
<ItemContent>
...
And the loader:
public async ValueTask<ItemsProviderResult<VirtualizedRow>> RowsLoader(ItemsProviderRequest request)
{
var result = BodyRows
.Where(x => x.IsVisible);
return new ItemsProviderResult<VirtualizedRow>(
result
.Skip(request.StartIndex)
.Take(request.Count),
result.Count()
);
}
The overridden OnAfterRender event:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("setupPopovers");
}
And lasty the JavaScript method:
function setupPopovers() {
const triggers = document.querySelectorAll("[id^='swift-trigger-']");
triggers.forEach((trig) => {
...
That is until I scroll down the dataset to a new area of data. These new rows also need to be "setup" and are not. It seems like any interaction on the table (like the click) will alert Blazor to call the OnAfterRenderAsyn which in turn calls me JS setup function and those tooltips now work.
So, my question is, is there a way to know when the UI is done rendering from the Virtualize component? I am not seeing an event I can catch from it? I suppose at worst, I could make a call that is paused for a second and then does the setup, but that does not seem to be a guarantee to always be enough time. Not like I would want to slow the app down either.
Is there a JavaScript page event I can catch that knows when things are done rendering? Perhaps whatever JavaScript Microsoft is doing has a way to catch an event from there?
More Info
I am not able to add any third party projects to the solution. So the suggestion by #Vikram-reddy will not work. We have the Bootstrap 5 (css only, not JS) and Popper.js. Plus whatever we write ourselves.
const triggers = document.querySelectorAll("[id^='swift-trigger-']");
The tooltip will not work in a virtualization scenario.
Please try the below component from BlazorBootstrap.
Demo: https://demos.getblazorbootstrap.com/tooltips
Github: https://github.com/vikramlearning/blazorbootstrap
Sample Code:
<Tooltip Title="Tooltip Left" Placement="TooltipPlacement.Left">Tooltip Left</Tooltip>
OR
Use the below approach on each row when it renders
var exampleTriggerEl = document.getElementById('example')
var tooltip = bootstrap.Tooltip.getOrCreateInstance(exampleTriggerEl)
tooltip.show();
Is anyone aware of a way to get access to the parent table of a selection in a version of Word that only has access to the 1.1 js api? We've been developing with 1.3 in mind, but must now also support the earlier version, rendering the following code broken:
async checkForInsideTable(ctx: Word.RequestContext, sel: Word.Range) {
let pt = sel.parentTable;
ctx.load(pt);
try {
await ctx.sync();
this.tableObject = pt;
return true;
} catch {
this.tableObject = null;
return false;
}
}
Over the past week we've tried a lot of different approaches, such as using bindings, wrapping table in content controls, or even relying on the styling tags. But nothing gets us to a position where we can get access to the parent or detect if the selection is within a specific element, and upgrading the version of Word is not an option.
I am afraid there is no direct way as 1.1 doesn't have table object/class.
You can first call getSelectedDataAsync(type: ooxml), then in the ooxml, you can analyze whether there is table out of the selection. But as mentioned above, you still can't get the table.
So basically I've started working with PageObjects and I'm having some issues.
I want to execute a command directly on some section. For example - I want to .waitForElementVisible directly on section (not on elements). Is it even possible? I've tried a lot of combinations, for example:
browser.page.topMenu().section.loginBox.section.unauthenticated.waitForElementVisible('#loginTooltip', 10000)
So it looks like this: topMenu() is my pageObject file, then there is loginBox section containing -> unauthenticated section containing -> loginTooltip section. I want to .waitForElementVisible on the last one section. How to do this? I know I can combine my sections without limitations, but how to work on them later on?
[would say this question is a bonus because it's not related with question in title]
I'm having problems when making an assertions on section in section. How to do this? I've tried a lot of ways, one of them is below:
browser.page.topMenu().expect.section('#loginBox').to.be.visible - this works - because it's only one section
browser.page.topMenu().expect.section('#loginBox').section('#unauthenticated').to.be.visible - doesn't work - I want to check if section unauthenticated which is inside loginBox section is visible. How to do this?
Thanks in advance for all answers, I've tried to figure this out myself without any success.
OK first let's break it down so it will be more readable:
var topMenu = browser.page.topMenu(); // Declare the page object.
var loginBox = topMenu.section.loginBox; // Declare the first section.
var unauthenticated = loginBox.section.unauthenticated // Declare the second section.
and so on...
Once you want to perform a command you can do:
loginBox.waitForElementVisible('#unauthenticated');
Note that the section selector should be declared:
sections: {
unauthenticated: {
selector: '.unauthenticated_title',
elements: {
sectionElements: '.selector_selector'
}
},
anotherSection: {
...
}
}
The second question is similar.
loginBox.expect.element('# unauthenticated').to.be.visible;
In one of our tests, we need to make sure that the tab keyboard navigation inside a form is performed in the correct order.
Question: What is the conventional way to check the tab navigation order with protractor?
Currently we are solving it by repeating the following step for as many input fields existing in a form (code below):
check the ID of the currently focused element (using getId())
send TAB key to the currently focused element
Here is the example spec:
it("should navigate with tab correctly", function () {
var regCodePage = new RegCodePage();
browser.wait(protractor.ExpectedConditions.visibilityOf(regCodePage.title), 10000);
// registration code field has focus by default
expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
// focus moved to Remember Registration Code
regCodePage.registrationCode.sendKeys(protractor.Key.TAB);
expect(regCodePage.rememberRegistrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
// focus moved to Request Code
regCodePage.rememberRegistrationCode.sendKeys(protractor.Key.TAB);
expect(regCodePage.requestCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
// focus moved to Cancel
regCodePage.requestCode.sendKeys(protractor.Key.TAB);
expect(regCodePage.cancelButton.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
// focus moved back to the input
regCodePage.cancelButton.sendKeys(protractor.Key.TAB);
expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
});
where regCodePage is a Page Object:
var RegCodePage = function () {
this.title = element(by.css("div.modal-header b.login-modal-title"));
this.registrationCode = element(by.id("regCode"));
this.rememberRegistrationCode = element(by.id("rememberRegCode"));
this.requestCode = element(by.id("forgotCode"));
this.errorMessage = element(by.css("div.auth-reg-code-block div#message"));
this.sendRegCode = element(by.id("sendRegCode"));
this.cancelButton = element(by.id("cancelButton"));
this.closeButton = element(by.css("div.modal-header button.close"));
};
module.exports = RegCodePage;
It is working, but it is not really explicit and readable which makes it difficult to maintain. Also, another "smell" in the current approach is a code duplication.
If the current approach is how you would also do it, I would appreciate any insights about making it reusable.
I think the PageObject should define a tab order list, since that is really a direct property of the page, and should be expressible as simple data. An array of items seems like a sufficient representation, so something like:
this.tabOrder = [ this.registrationCode, this.rememberRegistrationCode, this.requestCode, this.cancelButton ];
Then you need a bit of generic code that can check a tab order.
function testTabOrder(tabOrder) {
// Assumes TAB order hasn't been messed with and page is on default element
tabOrder.forEach(function(el) {
expect(el.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
el.sendKeys(protractor.Key.TAB);
});
}
Then your test would be something like:
it('has correct tab order', function() {
var regCodePage = new RegCodePage(); // this should probably be in the beforeEach
testTabOrder(regCodePage.tabOrder);
});
Of course, this assumes each element has a "getId()" method that works. (That seems like a reasonable assumption to me, but some environments may not support it.)
I think this keeps the tab-order nicely isolated on the PageObject (so its easy to keep in sync with the page content and doesn't get lost in the code that verifies the order). The testing code seem "optimistic" (I suspect the real world will introduce enough problems that you will end up expanding this code a bit).
I haven't tried any of this yet, so feel free to downvote if this doesn't work. :)
Also, I believe the forEach loop will work as-is, but I wouldn't be surprised if it needs some more explicit promise handling to make the dependencies explicit.
so I have been trying to change the highlight color in which documents show up in the "items" field within an Alfresco Share workflow form. Basically, given a starting form that looks like this...
You will notice that every other document that gets added to the items field is automatically highlighted light blue. I was wondering if it was possible to change that color, and furthermore if it was possible to set it so only the top item (or a single items) gets highlighted in that list of documents?
I thought this would be as simple as finding and changing a CSS file somewhere, but despite changing a number of different CSS files within Alfresco, I have had little luck changing that color. Just wondering if anyone had any experience with this and would be willing to help me out?
EDITED:
The class you're looking for is:
tr.yui-dt-highlighted
The problem here is that these classes are generated automatically by JavaScript injected in the page. So, I've searched and found this little info:
path share/res/js/yui-common.js you should use a tool like JavaScript Formatting to understand some code in there. There is a CLASS_HIGHLIGHTED that starts a function, and you should try to override this:
highlightRow: function (k) {
var i = this.getTrEl(k);
if (i) {
var j = this.getRecord(i);
c.addClass(i, d.CLASS_HIGHLIGHTED);
this.fireEvent("rowHighlightEvent", {
record: j,
el: i
});
return;
}
},
unhighlightRow: function (k) {
var i = this.getTrEl(k);
if (i) {
var j = this.getRecord(i);
c.removeClass(i, d.CLASS_HIGHLIGHTED);
this.fireEvent("rowUnhighlightEvent", {
record: j,
el: i
});
return;
}
},
There are highlightRow and highlightColumn to look into. It's always very difficult to override YAHOO yui functions..