BootstrapVue two tooltips appearing on the same element while having different targets? - html

I'm working in Vue with BootstrapVue and the bottom 2 tooltips I'm using are both appearing on the button which the click to mask this value button is targeted to. The tooltip which will contain the SSN is also appearing only on top of the button when it should be only where the span is.
I'm not sure why this is happening given that the IDs are seperated and I'd assume that it'd just place the SSN tooltip onto the span so it'd render there.
Markup:
<span class="app-titlebar__client-data-item non-draggable">
<div v-if="!hideSsn"
class="ssn-text"
#mouseenter="checkDataItem($event, 'ssn')"
#mouseleave="hideTooltips">
<button class="adv-btn adv-btn--naked app-titlebar__unmasked-btn"
id="titlebar-ssn-eye-hide"
#click="maskSsn(true)"
#mouseenter="hoverSsnMask(true)"
#mouseleave="hoverSsnMask(false)">
<svg class="us-icon-svg us-icon-svg--inline us-icon-svg--xs disable-pointer"
role="img"
focusable="false">
<use xlink:href="#adv-icons-svg_unmasked"></use>
</svg>
</button>
<span id="titlebar-ssn">
{{ssn}}
</span>
</div>
<div v-else
class="ssn-text">
<button class="adv-btn adv-btn--naked app-titlebar__mask-btn"
id="titlebar-ssn-eye-show"
#mouseenter="hoverSsnMask(true)"
#mouseleave="hoverSsnMask(false)"
#click="maskSsn(false)">
<svg class="us-icon-svg us-icon-svg--inline us-icon-svg--xs disable-pointer"
role="img"
focusable="false">
<use xlink:href="#adv-icons-svg_masked"></use>
</svg>
</button>
{{ssnMasked}}
</div>
</span>
Tooltips:
<b-tooltip v-if="clientInContext && ssn && hideSsn"
target="titlebar-ssn-eye-show"
:disabled.sync="disableSsnTooltip"
:show.sync="showSsnTooltip"
triggers="hover"
placement="bottom">
Click to temporarily display this value
</b-tooltip>
<b-tooltip v-if="clientInContext && ssn && !hideSsn"
target="titlebar-ssn-eye-hide"
:disabled.sync="disableSsnTooltip"
:show.sync="showSsnTooltip"
triggers="hover"
placement="bottom">
Click to mask this value
</b-tooltip>
<b-tooltip v-if="clientInContext && ssn && !hideSsn"
target="titlebar-ssn"
:disabled.sync="disableSsnTooltip"
:show.sync="showSsnTooltip"
triggers="hover"
placement="bottom">
{{ssn}}
</b-tooltip>

Since you are using v-if/v-else, make sure you place a unique keyeither on the button wrapper div or the button. What is most likely happening is that Vue is re-using the same element reference and just updating bits of it. b-tooltip caches the element reference when it is mounted.

Related

How to disable an svg tag based on any condition?

How can I disable an svg tag based on a condition in Angular?
Tried with [disabled]="true" but does not work for me. Adding a sample code down below.
<span>
<svg role="presentation" (click)="show = !show">
<use [attr.xlink:href]="show ? '#arrow-top' : '#arrow-bottom'"></use>
</svg>
</span>
Assuming you want to disable click based on showSVG variable.
In ts.
showSVG = true;
In template:
<span>
Show/hide
<svg [style.pointerEvents]="showSVG ? 'auto' : 'none'" role="presentation" (click)="show = !show">
<use [attr.xlink:href]="show ? '#arrow-top' : '#arrow-bottom'"></use>
</svg>
</span>

Click on an element in Selenium (ElementClickInterceptedException)

I am using Selenium to find information in Kaggle.
In order to do so, I am looking to scrape information on people solutions.
When I navigate to this url: https://www.kaggle.com/allen-institute-for-ai/CORD-19-research-challenge/tasks?taskId=882.
There are people solutions at the end of the task.
I would like to click on those elements.
From the page source, it doesn't look like pressing the solution should navigate to notebook of the solution (the < a href="/{usename} opens the user info tab, and not the notebook tab).
This is how the html of an element looks like:
<li class="sc-qQkIG hIKhtZ">
<a href="/moghazy" target="_blank" rel="noopener" class="sc-pZMVu kiTgMN">
<div class="sc-oTPjJ cCLmQH"><img src="https://storage.googleapis.com/kaggle-avatars/thumbnails/777390-kg.jpg" alt="Moghazy" class="sc-pckkE ljVeKr"><img src="/static/images/avatier/avatier-expert#2x.png" alt="expert" class="sc-pjIPr cvnVIi"></div>
</a>
<div class="sc-qYgLf hNZirj">
<div class="sc-pRStN jTbOhh">
<div class="sc-AxheI sc-fznWqX sc-qanuI frNLaF">COVID-19 Literature Ranking + Web Scraping</div>
</div>
<div class="sc-psdQm hrPHBT"><span class="sc-fzpkJw sc-fznzOf sc-oToFz dtnpxb">Moghazy · <span title="Sat May 16 2020 02:44:32 GMT+0300 (Israel Daylight Time)">6 days ago</span> · Notebook · Python · 4 Comments</span></div>
</div>
<div class="sc-pJsLC cBTgaO">
<div class="sc-pZzGt eDxwsZ sc-pkjoF iehzxN">
<button class="MuiButtonBase-root MuiButton-root sc-oTcWe sc-paYYD hlGLPZ MuiButton-outlined" tabindex="0" type="button" state="no-vote" data-testid="vote-button-icon">
<span class="MuiButton-label label">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="angle-up" class="svg-inline--fa fa-angle-up fa-w-10 " role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
<path fill="currentColor" d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"></path>
</svg>
</span>
<span class="MuiTouchRipple-root"></span>
</button>
<button class="MuiButtonBase-root MuiButton-root sc-oTcWe sc-pjUyM kZNtvl MuiButton-outlined Mui-disabled Mui-disabled" tabindex="-1" type="button" disabled="" state="no-vote"><span class="MuiButton-label label">14</span></button>
</div>
</div>
</li>
I find the elements using this code:
elements = driver.find_element_by_class_name("sc-oUaSW").find_elements_by_xpath(".//li")
for element in elements:
element.click()
but I am getting the error:
Message:
element click intercepted: Element ... is not clickable
but when I click on it in the server, it is clickable.
What am I doing wrong?
There are several issues to address:
Element is not clickable because it is not in focus. You need to move to it first.
The click opens a new tab. This requires its own handling.
Moving back to the original tab to click the next item.
This snippet should work:
main_window = driver.current_window_handle #this relates to issues 2, 3
elements = driver.find_element_by_class_name("sc-oUaSW").find_elements_by_xpath(".//li")
for element in elements:
ActionChains(driver).move_to_element(element).click().perform() #this addresses issue 1
#element.click()
driver.switch_to.window(driver.window_handles[1]) #this relates to issue 2
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//a[#class='KernelViewerContext_KernelTitle-sc-rdaqnd chqxNN']")))
#time.sleep(3)
#do whatever you wish with the tab/task here
driver.close()
driver.switch_to.window(main_window) # close tab and switch back to original browser tab (issue 3)
These imports are required for the above to work:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains

how to show the div when clicked on the link and how to get value from input?

i have a django template that uses for loop to print comments i want to show the input field and a button when the edit link is clicked how do i do that.
and also when the edit button is pressed i wanna get the value from that specific input field. how do i do that?
{% for comment in comments %}
<div class="comment mdl-color-text--grey-700">
<header class="comment__header">
<img src="images/co1.jpg" class="comment__avatar">
<div class="comment__author">
<strong>{{comment.User_name}}</strong>
<span>{{comment.date}}</span>
</div>
</header>
<div class="comment__text">
{{comment.text}}
</div>
<!-- FAB button , class "mdl-button--fab"-->
<a href="javascript:delete_comment('{{comment.text}}','{{comment.blogslug}}')">
<button class="mdl-button mdl-js-button mdl-button--fab">
<i class="material-icons">delete</i>
</button>
</a>
<!--when this link is clicked bellow edit_comment div should appear -->
<a href="">
<button class="mdl-button mdl-js-button mdl-button--fab">
<i class="material-icons">edit</i>
</button>
</a>
<!-- and also when i click the edit button how can i get value from the input -->
<div id="edit_comment" style="visibility: hidden;">
<input type="text" name="edit_comment">
<button>edit</button>
</div>
</div>
{% endfor %}
so the problem is there are going to many other comments of this type because they are printed using a loop.
Firstly, why are you wrapping your button in an <a> tag? Unnecessary.
Get rid of visibility: hidden. Use display: none or a class like Bootstrap's d-none.
I suggest d-none because it allows you to add the class and remove it without worrying about the inherited display property, i.e. display: flex or display: block.
https://getbootstrap.com/docs/4.0/utilities/display/
Write a custom function with an event listener.
Inside your template loop:
<button class="mdl-button mdl-js-button mdl-button--fab" onclick="handleClick(this)">
<i class="material-icons">edit</i>
</button>
ASSUMING YOU HAVE REMOVED THE <a> TAG
JavaScript:
let handleClick = function(param) {
let editCommentDiv = param.parentNode.lastChild;
editCommentDiv.style.display = "none"
};
This is by no means the best way to do it. I highly suggest you use BootStrap's d-none class. Also, what you should actually do is assign an ID based on the for loop to both the button and to the div, i.e. id=editcommentdiv_{{ forloop.counter }} this way you won't need to use DOM to navigate to the last element to get the edit div, and can just target the div directly via ID.

When adding pills with horizontal orientation, div height doesn't increase correctly

I'm working on a web application, and I have a datatable where you can filter via an API call. Upon adding filters, Material Design chips get added in horizontal orientation. When I add too much chips, my text in my div goes over the text above it.
This is my code:
<!-- ABOVE IS ANOTHER MAT TOOLBAR ROW WITH 3 INPUTS AS SHOWN IN THE PICTURE BELOW -->
<mat-toolbar-row class="controls">
<div class="col-md-9">
<span>Filtering {{getTotalDataSize()}}
<span *ngIf="type === 'user'" i18n>users</span>
<span *ngIf="type === 'role'" i18n>roles</span>
<span *ngIf="type === 'entitlement'" i18n>entitlements</span>
<span *ngIf="type === 'application'" i18n>applications</span>:</span>
<span *ngIf="clusterConditions.length == 0"> no filters applied</span>
<div *ngIf="clusterConditions.length > 0 || isInGroupByMode()">
<mat-chip-list>
<mat-chip *ngFor="let condition of clusterConditions" [selectable]="false" [removable]="true" (removed)="removeCondition(condition)">
<span *ngIf="condition.attr.name">{{condition.attr.name | capitalize}} {{condition.match}} "{{condition.val}}"</span>
<span *ngIf="!condition.attr.name">Contains "{{condition.val}}"</span>
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<mat-chip *ngIf="isInGroupByMode()" [selectable]="false" [removable]="true" (removed)="changeGroupByMode(false)">
<span>Grouped by {{groupByAttribute.name}}</span>
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</div>
</div>
<div class="col-md-3">
<mat-paginator #paginator [length]="getDataSize()" [pageIndex]="0" [pageSize]="10"></mat-paginator>
</div>
</mat-toolbar-row>
I tried fiddling with some display: block/flex; and box-sizing: border-box;, but I can't seem to figure it out!
An example of what it looks like when adding too much chips:
I'd like the 'Filtering ...' to show beneath the input fields!
EDIT: Wanted behaviour:
Note: The row has two columns, the chips column and the navigator on the right. When there are to much pills, a next row has to start as shown in the picture above, in the column div of the pills, not of the paginator.
Either the pills start next to the 'Filtering ... :' or beneath it (doesn't really matter)
Thanks in advance!

How to show/hide in Angular2

I have a component that show/hide element by clicking a button.
This is my html
<div *ngFor="let history of histories | sortdate: '-dateModified'">
<p><b>{{ history.remarks }}</b> - <i>{{history.dateModified | date:'short'}}</i></p>
<a href="google.com"
[class.datatable-icon-right]="history.$$expanded"
[class.datatable-icon-down]="!history.$$expanded"
title="Expand/Collapse Row"
(click)="toggleExpandRow(history)"></a>
<!-- hide/show this by clicking the button above.-->
<div *ngFor="let step of history.steps; let i = index">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
<hr />
</div>
and my .ts
toggleExpandRow(row) {
console.log('Toggled Expand Row!', row);
//row
return false;
}
trying to search but, can't find any same sample.
On jquery, I can do this, but on Angular2, I am having hard time to figure this.
There are two options:
1- You can use the hidden directive to show or hide any element
<div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
2- You can use the ngIf control directive to add or remove the element. This is different of the hidden directive because it does not show / hide the element, but it add / remove from the DOM. You can loose unsaved data of the element. It can be the better choice for an edit component that is cancelled.
<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
Use the ngIf in your repeated rows. Create a boolean property called showStep to indicate whether the row should be expanded or not.
<div *ngFor="let step of history.steps; let i = index" ngIf="history.showStep">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
Then, in your .ts file:
toggleExpandRow(history) {
history.showStep = !history.showStep
//note the same porperty of showStep that is used in your html
}
Extra:
In fact, to save a few lines of codes, you don't even need the toggleExpandRow function at all. You can do it inline in your html:
//other attributes omitted for brevity
<a (click)="history.showStep = !history.showStep">