Div element is only loading correctly after clicks - javascript

I am having a bit of trouble when loading dynamic divs on Angular. I have made a button which adds new divs on each click on a specific area. But the problem happens once I have added them, as they are shown incorrectly:
The editor and the calendar (Both are made by PrimeNG) are not shown after I add such div, as it shows on the picture above. But after I click twice on the text box (marked as red in the picture below), the components load up.
Here is the HTML code I am using to show that.
<div class="ui-g-9" style="border: 2px solid #c8c8c8; border-radius: 5px;">
<section class="card" style="display: flex; overflow-x: auto; overflow-y: unset;">
<div *ngFor="let disparaEmail of disparaEmails" class="ui-g-4" style="margin-right: 10px; border: 1px solid #c8c8c8; border-radius: 5px; min-width: 466.828px;">
<p class="titulo-campo font1 fw700">Assunto:</p>
<textarea pInputTextarea [rows]="2" [(ngModel)]="disparaEmail.assuntoEmail" style="width: 100%; resize:unset; font-size: 18px;"></textarea>
<p class="titulo-campo font1 fw700">Tipo de Aviso:</p>
<p-editor [style]="{'height':'300px'}" [(ngModel)]="disparaEmail.msgEmail"></p-editor>
<p class="titulo-campo font1 fw700">Data:</p>
<p-calendar [(ngModel)]="disparaEmail.dataEmail" dateFormat="dd/mm/yy" showButtonBar="true" [locale]="br" [monthNavigator]="true"
[yearNavigator]="true" yearRange="2018:2050"></p-calendar>
</div>
</section>
</div>
<div style="display: inline-grid;">
<i class="fa fa-plus botoes-chamada" (click)="addAviso()" style="color: #819049; padding:30px; margin-bottom: 10px;" pTooltip="Adicionar um tipo de aviso."></i>
<i class="fa fa-minus botoes-chamada" (click)="deletaAviso()" style="color: #905149; padding:10px;" pTooltip="Remover o Ășltimo tipo de aviso inserido."></i>
</div>
Here is the TS part:
addAviso(){
this.disparaEmails.push(new EmailDispara());
}
deletaAviso(){
if (this.disparaEmails.length > 1){
this.disparaEmails.splice(this.disparaEmails.length - 1, 1);
}
}
Thanks for the help in advance!

This is probably the common problem of not properly detecting changes. Add ChangeDetectorRef injection into your component:
constructor (..., changeDetector: ChangeDetectorRef)
and invoke detectChanges after adding/removing:
addAviso(){
this.disparaEmails.push(new EmailDispara());
this.changeDetector.detectChanges(); // <- this line here
}

Related

JS: Adding style dependent on class exist in siblings child

I've had a look at related answers but none are what I am looking for... I think. Apologies if I am duplicating a question.
This HTML is used many times on a page, within a product box and is displayed on a product category page.
<div class"all-buttons-container">
<div class="button1-container">
<a class="button1">text</a>
</div>
<div class="button2-container">
<a class="button2 **hidden**">text</a>
</div>
</div>
In this (much simplified) HTML I have a container which houses 2 siblings.
- Each sibling contains an anchor.
The button containers are always visible.
Sometimes, the .button2 anchor also has the bootstrap class of hidden so the anchor is no longer displayed. This is done in each of the product boxes depending on the need to have the second button for that product. I am not in control of this.
When the .button2 anchor has the hidden class I need to add some margin-top to button1-container to vertically center it
I was going to use pure style (flexbox) but it wasn't achieving what I needed.
I would like to run a little jQuery or pure JS every time the page finishes loading which adds some the top margin, if required, on each instance of this HTML. I don't like having to do this but will need to if I cannot find another simple way of controlling it.
Any thoughts... solutions... perfect solutions etc?
Thanks in advance!
cheers
wayjo
I suppose I've fully understood your question.
You can achieve this without JS, in a cleaner any.
Why not make a custom class of button2-hidden and attach it to all-buttons-container?
<div class"all-buttons-container button2-hidden">
<div class="button1-container">
<a class="button1">text</a>
</div>
<div class="button2-container">
<a class="button2">text</a>
</div>
</div>
Then you have this CSS:
.button2-hidden .button2-container{
display: none; // or visibility -- whatever you want
}
.button2-hidden .button1-container{
margin-top: 1rem;
}
If you can add a div to contain the buttons, than you can use the snippet below:
.all-buttons-container{
display: flex; /* important part */
align-items: center; /* important part */
padding: 10px;
background-color: grey;
width: 200px;
border: 2px solid #fff;
height: 150px;
}
.hidden {
display: none!important;
}
.all-buttons-container > div a{
display: inline-block;
background-color: blue;
padding: 7px;
margin: 7px;
color: #fff;
}
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1">button1</a>
</div>
<div class="button2-container">
<a class="button2">button2</a>
</div>
</div>
</div>
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1">button1</a>
</div>
<div class="button2-container">
<a class="button2 hidden">button2</a>
</div>
</div>
</div>
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1 hidden">button1</a>
</div>
<div class="button2-container">
<a class="button2">button2</a>
</div>
</div>
</div>

No element found using locator: By(partial link text, Solid Community)

I'm trying to perform a Cucumber test that can click on the ng-select component (dropdown menu) and, after that, clicks on one of the options of the menu.
I've tried to use "element (by.partialLinkText('Solid Community')).click()", where "Solid Community" is the text that must be clicked. I also tried with "by.LinkedText" but it didn't work.
I can not use "by.id" or similar because the options of the menu don't have an id (the whole dropdown menu has one).
Here are some relevant parts of the code:
login.component.html:
...
<div style="margin-top: 10px;">
<ng-select class="login-select"
id="login-select-menu"
bindLabel="name"
bindValue="loginUrl"
placeholder="Select ID Provider"
dropdownPosition="bottom"
[items]="identityProviders"
[(ngModel)]="selectedProviderUrl"
style="width: 360px; height: 48px; margin-left: auto; margin-right: auto;">
<!-- DROPDOWN TEMPLATE -->
<ng-template ng-option-tmp let-item="item">
<div style="height:40px; padding-top:10px; position: relative;">
<img [src]="item.image" style="float: left; height: 32px; width: 32px; margin-top:-5px;" />
<span style="float: left; margin-left: 10px;">{{ item.name }}</span>
<div style="clear: both;"></div>
</div>
</ng-template>
</ng-select>
<input type="text"
class="wide-text"
*ngIf="selectedProviderUrl===null"
placeholder="Enter WebID"
style="margin-top:10px; padding: 12px 10px; width: 340px; height: 16px; display: block; margin-left: auto; margin-right: auto;"
[(ngModel)]="customProviderUrl" />
<button class="wide-button" (click)="onLogin()" *ngIf="selectedProviderUrl !== undefined || customProviderUrl !== undefined" [disabled]="selectedProviderUrl===null && !customProviderUrl" style="margin-top:10px;">Go</button>
</div>
...
loginSelectMenu.feature:
#loginSelectMenu-feature
Feature: Click on login select menu
Display anything
#loginSelectMenu-scenario
Scenario: Login Page
Given I am on the login page
When I click on the login select menu
Then It should happen anything
app.steps.ts (the error is in "When"):
When(/^I click on the login select menu$/, async () => {
await page.clickOnLoginSelectMenu();
await page.clickOnSolidCommunity();
});
app.po.ts:
clickOnLoginSelectMenu() {
return element(by.id('login-select-menu')).click();
}
clickOnSolidCommunity() {
this.sleep(3000);
return element(by.partialLinkText('Solid Community')).click();
}
When identifying elements it's important to look at the rendered HTML in the DOM instead of the angular HTML template. There are a number of transformations that occur when the templates are rendered.
Also partialLinkText will search for <a> tags which contain the provided string. It does not appear you are using any a tags within your code.
If your element is of another type you should be able to use the cssContainingText locator like so
element(by.cssContainingText('div','Solid Community')).click();

Show swatch-colors on category page in bigcommerce stencil framwork

Here is my website http://evisionshop.com/
I need suggestion related to the swatch color. How I can show the products attribute color into category page with each product below price.
below is the code of category page
<h3 class="product-item-name">{{name}}</h3>
<!---swatch--->
<div class="cat_item"></div>
<!---swatch--->
<div class="product-item-price">
{{#if price}}
{{> components/product/price price=price show_savings=false schema_org=false}}
{{/if}}
</div>
and here is the code with the help the swatch colors showing on products details page
<div class="form-field form-field-options form-field-swatch{{#if required}} form-required{{/if}}"
data-swatch-selector
data-product-attribute="swatch">
<div class="form-field-title">
{{display_name}}
<span class="swatch-value" data-swatch-value>{{lang 'forms.swatches_none_selected'}}</span>
{{#if required}}<span class="required-text">{{lang 'common.required'}}</span>{{/if}}
</div>
<div class="form-field-control">
{{#each values}}
<label class="swatch-wrap" data-swatch-value="{{label}}" data-product-attribute-value="{{id}}">
<span class="form-label-text">{{label}}</span>
<input
class="form-input swatch-radio"
id="attribute-{{id}}"
type="radio"
name="attribute[{{../id}}]"
value="{{id}}"
{{#if selected}}checked{{/if}}
{{#if ../required}}required{{/if}}
aria-required="{{required}}">
<span class="swatch {{#if data.[1]}}two-colors{{/if}}{{#if data.[2]}} three-colors{{/if}}">
{{#if pattern}}
<span class="swatch-color swatch-pattern" style="background-image: url('{{getImage image 'core-swatch'}}');"></span>
{{/if}}
{{#if data.[0]}}
<span class="swatch-color" style="background-color: #{{data.[0]}}"></span>
{{/if}}
{{#if data.[1]}}
<span class="swatch-color secondary" style="background-color: #{{data.[1]}}"></span>
{{/if}}
{{#if data.[2]}}
<span class="swatch-color tertiary" style="background-color: #{{data.[2]}}"></span>
{{/if}}
</span>
{{#if pattern}}
<span class="swatch-pattern-expanded">
<img class="swatch-pattern-image" src="{{getImage image 'core-swatch'}}">
</span>
{{/if}}
</label>
{{/each}}
</div>
</div>
I have jquery code which was working on simple theme and here is the code of jquery
<script>
$(document).ready(function(){
$(".ProductDetails").each(function(){
var mcurl = $("strong a",this).attr("href");
$(this).after("<div class='mccolors'></div>");
$(".mccolors").load(mcurl + " .productOptionPickListSwatch");
});
});
</script>
but it's not working on big commerce stencil framework I have changed classes but not working.
If you click on the first products on the website home page it will show colors of products into details page here is the link
http://evisionshop.com/blackview-e7s/
and I am trying to call this color on category page please check the screenshot http://prntscr.com/fk0p1r
how I can achieve this with jquery or javascript with the help the <div class="cat_items"></div> I have called into the sections automatically show the swatch colors dynamically on the category page.
Thanks in advance for help.
I had the exact same problem.
The way to solve it is like this. It's not pretty but it worked.
Go to Storefront > Footer Scripts
You might have to play around a bit with the '190px' I removed the 'Required' field earlier from the swatch.html file.
Include this at the end:
<style>
#media screen and (max-width: 770px) {
.productView-options .form-radio:checked+.form-option span.form-option-variant.form-option-variant--color:after{ left:190px!important; }
}
.productView-options [data-product-attribute='swatch']{
position:relative !important;
}
.productView-options [data-product-attribute] .form-option{
overflow:visible !important;
position: initial !important;
}
.productView-options .form-option span.form-option-variant.form-option-variant--color:after {
content: attr(title);
display: none;
}
.productView-options .form-radio:checked+.form-option span.form-option-variant.form-option-variant--color:after{
display: inline-block;
color: #000;
padding: 0;
position:absolute;
top: -2px;
left: 50px;
border-radius:4px;
width: 250px;
text-align: left;
font-size: 15px;
font-weight: 100;
}
</style>

Problems with popover tooltip in table td tag

Here is what I have and it works fine:
<div style="padding:5px; border:solid 1px gray; width: 30px; height: 20px;" role="button" data-toggle="popover" data-content="test">
<div class="tv-button"></div>
</div>
But If I do this:
<td>
<div style="padding:5px; border:solid 1px gray; width: 30px; height: 20px;" role="button" data-toggle="popover" data-content="test">
<div class="tv-button"></div>
</div>
</td>
it stopped working.
This is what I have in script:
$("[data-toggle=popover]")
.popover({
placement: "top",
trigger: "hover",
html: true
});
Does anyone know what is the problem?
Thanks in advance.
I realized that it does not work if i do the ng-repeat on the "tr" tag and repeat many of "td" tags, in that case it does not work, without ng-repeat it does, i would create JSfiddle but since i have quite a lot of html, i dont want to bother you to read that...did any of you have conclusions about that?

Moving html element containing contentEditable to another branch in dom without losing focus

I hope you can help with this problem.
I have the following html structure (simplified) which represents two fixed-height pages in a document with headers, footers, a body and a number of "DataItems" (3 readonly, 1 editable) within that body. There are also a "Summary" and "Add New" DataItems.
I need to be able to move a DataItem's block of html (that may contain a contentEditable element) into another position in the document. However, I need to do so without losing focus to the contentEditable element if it is that which is being moved.
This action is triggered whilst the user is typing into the contentEditable HTML Editor and the DataItem that they are typing into gets taller. As it does so, when the bottom DataItem starts to overlap the footer, it gets pushed down to the next page. A bit like typing into a table cell in MS Word that isn't allowed to break across pages.
I can get a partial solution working with jQuery. This moves next sibling DataItems from the first page to the second page as a previous sibling grows in height, but the problem with this is that when I then go to move the DataItem which has focus, it loses focus and breaks the user's flow of typing. I have tried putting focus back to the contentEditable div after moving it, but issues with selection and range and not being able to find the cursor position plus issues with the scrollbars jumping despite them being reset back have proved that solution to be too unreliable.
I therefore tried a different approach which was to move all html content between the last DataItem of the first page and the first DataItem (if any) of the next page to a position before the last data item, in the hope that doing so would prevent the html content editor from losing focus, but still give the impression that the DataItem has moved down to the second page.
The functionality I've tried (and failed) to achieve is to cut the html between the "start-here" and "end-here" divs and move it to the "paste-here" div. The divs are just there as placeholders to show what should be moved.
However, despite trying various methods using jQuery dom manipulation and RegEx string replacement I can't seem to come up with a solution that doesn't involve replacing the common ancestor - which is the "Pages" div - and hence having to replace the current contentEditable - and hence losing focus.
Does anyone have an idea of how I could do this and retain focus so the user can continue typing uninterrupted?
Regards,
Jeremy :)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
.Document
{
text-align:left;
margin: 0px auto;
display:inline-block;
position:relative;
/*border: 1px solid blue;*/
}
.Pages
{
margin: 0px auto;
position:relative;
display:inline-block;
/*border: 1px solid yellow;*/
}
.PortraitPage
{
height:29.7cm;
width:21cm;
background: #ffffff;
position:relative;
}
.FirstPage
{
border: 1px dotted black;
}
.ExtraPage
{
margin-top:10px;
margin-bottom:10px;
border: 1px dotted black;
}
.PageHeader
{
border: 0px dotted #e2e2e2;
position:absolute;
top:0px;
width: 18cm;
left:0cm;
}
.PageBody
{
border: 1px dotted #c2c2c2;
position:absolute;
top:4.5cm; /* this needs to be whatever the height of the header is */
width: 18cm;
left:1.5cm;
/*min-height:22cm;*/
}
.PageFooter
{
border: 1px dotted #e2e2e2;
position:absolute;
bottom:0px;
width: 18cm;
left:1.5cm;
}
.PageSeparator
{
background: #999999;
height: 1cm;
width: 21cm;
}
.InvoiceItemsForm
{
position: relative;
/*top: 2.5cm;*/
}
/* This prevents the space added in contentcell divs in the html entry cell just for the PageEditor */
.InvoiceItemsForm div
{
margin-bottom: 0px;
}
.LineItem_Panel_ReadOnly
{
position:relative;
border: 1px solid transparent;
}
.LineItem_Panel_ReadOnly_Hover
{
position:relative;
border: 1px solid #C2C2C2;
background-color:#ffffff;
}
.LineItem_Panel_Edit
{
position:relative;
border: 1px solid #C2C2C2;
}
.LineItem_Panel_Insert
{
position:relative;
border: 1px solid green;
}
</style>
</head>
<body>
<div id="ctl00_phContent_pnlInvoicePage" class="Page FirstPage PortraitPage">
<div class="FirstHeader PageHeader">
First Page Header
</div>
<div class="ExtraHeader HiddenExtraPageSection">
Hidden ExtraPage Header that is copied when a new page is created
</div>
<div id="ctl00_phContent_pnlInvoicePageBody" class="PageSection Body PageBody">
<div id="ctl00_phContent_pnlInvoiceItemsForm" class="InvoiceItemsForm DataSection">
<div id="ctl00_phContent_lvLineItems_ctrl0_pnlLineItemReadOnly" class="DataItem LineItem_Panel_ReadOnly InvoiceLineItem">
<div class="LineItem_Panel_HTMLContent">
<span id="ctl00_phContent_lvLineItems_ctrl0_lblHTMLContent">
<p>
aaaaaaaaaaaaaaa</p>
<p>
aaaaaaaaaaaaaa</p>
</span>
</div>
</div>
<div id="ctl00_phContent_lvLineItems_ctrl1_pnlLineItemReadOnly" class="DataItem LineItem_Panel_ReadOnly InvoiceLineItem">
<div class="LineItem_Panel_HTMLContent">
<span id="ctl00_phContent_lvLineItems_ctrl1_lblHTMLContent">
<p>
bbbbbbbbbbbbbbb</p>
<p>
bbbbbbbbbb</p>
</span>
</div>
</div>
<div id="ctl00_phContent_lvLineItems_ctrl2_pnlLineItemReadOnly" class="DataItem LineItem_Panel_ReadOnly InvoiceLineItem">
<div class="LineItem_Panel_HTMLContent">
<span id="ctl00_phContent_lvLineItems_ctrl2_lblHTMLContent">cccccccccccccc</span>
</div>
</div>
<div id="ctl00_phContent_lvLineItems_ctrl3_pnlLineItemEdit" class="DataItem LineItem_Panel_Edit InvoiceLineItem">
<div id="ctl00_phContent_lvLineItems_ctrl3_pnlHTMLEditor" class="HTMLEditorPanel">
<div style="width: 126px; height: 20px;" id="ctl00_phContent_lvLineItems_ctrl3_txtHTMLContent$HtmlEditorExtenderBehavior_ExtenderContainer"
class="unselectable ajax__html_editor_extender_container">
<input style="display: none; visibility: hidden;" id="ctl00_phContent_lvLineItems_ctrl3_txtHTMLContent"
name="ctl00$phContent$lvLineItems$ctrl3$txtHTMLContent" value="ddddddddddddd"
type="text" autocomplete="off">
<div style="height: 21px; overflow: auto; clear: both;" id="ctl00_phContent_lvLineItems_ctrl3_heeHTMLContent_ExtenderContentEditable"
class="ajax__html_editor_extender_texteditor" contenteditable="true">
<p>
ddddddddddddd</p>
<p>
</p>
</div>
</div>
</div>
</div>
<div class="DataItem">
<p>
Click <a id="ctl00_phContent_lvLineItems_lbAddLineItem" href='javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$phContent$lvLineItems$lbAddLineItem", "", true, "", "", false, true))'>
here</a> to add a new Data Item</p>
</div>
<div id="paste-here"></div>
<div class="DataItem InvoiceTotals">
<div class="InvoiceSubTotal">
Sub Total: <span id="ctl00_phContent_lvLineItems_lblInvoiceSubTotal">18,110.00</span></div>
<div class="InvoiceVATTotal">
VAT Total: <span id="ctl00_phContent_lvLineItems_lblInvoiceVATTotal">3,111.00</span></div>
<div class="InvoiceTotal">
Invoice Total: <span id="ctl00_phContent_lvLineItems_lblInvoiceTotal">21,221.00</span></div>
</div>
<div id="start-cut"></div>
</div>
</div>
<div class="FirstFooter PageFooter">
First Page Footer
</div>
<div class="ExtraFooter HiddenExtraPageSection">
Hidden ExtraPage Footer that is copied when a new page is created
</div>
</div>
<div id="ctl00_phContent_pnlInvoicePage" class="Page ExtraPage PortraitPage">
<div class="ExtraHeader PageHeader">
Extra Page Header
</div>
<div id="ctl00_phContent_pnlInvoicePageBody" class="PageSection Body PageBody">
<div id="ctl00_phContent_pnlInvoiceItemsForm" class="InvoiceItemsForm DataSection">
<div id="end-cut"></div>
</div>
</div>
<div class="ExtraFooter PageFooter">
Extra Page Footer
</div>
</div>
</body>
</html>
I don't see any reason you have to reparent anything to achieve the effect you want. Instead of trying to rely on the browser being smart enough to render things where you want them, which will prove to be inconsistent between browsers and possibly different versions of the same browser, I would suggest using CSS and javascript to explicitly position the items. When the text the user enters gets too long to fit in the space provided, you can use node.style.top=newY; node.style.left=newX; to reposition it, and node.style.height=newHeight; node.style.width=newWidth; to resize it however large it needs to be. These methods don't require the browser to remove and re-insert the element, so focus is not lost, nor is text selection or cursor position.

Categories