Get classname from tag in LESS - less

I want to use a classname to set a background on a element, but i'm not sure if it's possible with LESS js at the moment.
The case is:
I have a table with a list of athletes, on these lists i want to show a country flag as a background of a p tag.
In HTML it looks like:
<table>
<tr>
<td class="athlete"><p class="us">Athlete 1</p></td>
</tr>
</table>
I want to set the background image through a mixin, if i can get the classname from the P tag i would be there.
.athlete {
p {
.setBackgroundImage(#ClassName);
}
}
is there anyway in LESS to achieve this?

The problem is that i need a whole new rule for every possible country. My loop implementation didn't cut it either.
I went for the javascript implementation, i add a background image to a iso coded classname in a certain parent class.
<div class="nationality">
<p class="athlete">Athlete X<span class="nl"></span></p>
</div>
jQuery(".nationality span").css('background-image', 'url(../img/flags/60/'+jQuery(".nationality span").attr("class")+'.png);
Thanks guys.

Related

Improvement With Xpath Search?

I am a student learning selenium and trying to set a checkbox(by placing a tick) that resides on the same row as a target document. Here is how the row looks:
<span><input>Checkbox</input></span> - <span>_lblDocumentCategoryDescription</span> - <span>_lblDocumentdescription</span>
Each row consists of a checkbox for that row, a category and a description. I am provided the description and need to set the corresponding checkbox at the beginning of the row.
Although I have a solution that works I am looking for a better method as my method is very slow and I can call it multiple times, compounding the slowness. The page in question has 315 fixed different documents that might possibly be added (to a merge and print feature). I usually add at least 3 rows so need to run the search
I am currently using xpath to search since my knowledge of CSS is limited and it seems like traversing up the DOM (no :parent?) is not easy unless using some javascript, which I am trying to avoid. I have read that executing JS doesn't emulate the user correctly so I guess xpath is the solution?
As I know there must be a quicker/better/more efficient solution I am hoping others might have found better?
Here is what I am currently using:
Method Call
CPTools,setStupidCheckbox("Sublease Addendum", true);
Method:
public CPTools setStupidCheckbox(String documentToPrint, Boolean onIfTrue) {
this.log.trace("Starting: setStupidCheckbox; parameter: documentToPrint " + documentToPrint);
String xpathForCheckboxes = "/ancestor::tr//input";
try {
String xpathForDocumentDescriptions = String.format("//span[contains(text(), '%s')]", documentToPrint);
tools.waitForElement(By.xpath(xpathForDocumentDescriptions), 2);
if (driver.findElement(By.xpath(xpathForDocumentDescriptions)).isDisplayed()) {
driver.findElementByXPath(xpathForDocumentDescriptions + xpathForCheckboxes).click();
}
} catch (org.openqa.selenium.NoSuchElementException | ElementNotVisibleException e) {
}
this.log.trace("Ending: setStupidCheckbox");
return this;
}
Here is the full xpath for a table row (the dynamic part of the id is the _ctl316):
<tr class="DataGridCellData">
<td class="DataGridCellDataCenterAligned">
<span class="DataLabel"><input id="ctl01_PageBody_grdDocument_ctl316_chkSelect" name="ctl01$PageBody$grdDocument$ctl316$chkSelect" onclick="javascript:uiHelper.GridCellCheck(this, 'chkAllSelect');" type="checkbox"></span>
</td><td>
<span id="ctl01_PageBody_grdDocument_ctl316_lblDocumentCategoryDescription">Approval Form</span>
</td><td align="left">
<span id="ctl01_PageBody_grdDocument_ctl316_lblDocumentdescription">Sublease Addendum</span>
</td><td align="center">
</td>
</tr>
Thanks in advance for any possible help.
Try below XPath if span text (Sublease Addendum) is unique:
//td[.= 'Sublease Addendum']

Best way to get a specific descendant relative to a Navigator Object

Here is an example of the HTML I am working with:
<div //this is the Navigator I have
<div
<div class = 'myClass'
<div
<sort-table
<table
<thead </thead>
<tbody </tbody> //this is the Navigator I want
</table>
</sort-table>
</div>
</div>
... (you get the idea)
I have a method that is supposed to grab the table relative to a specific Navigator. The Navigator in question is linked up to the div I have marked in the HTML above. and I want it to return the tbody.
I am surprised there is no getAllDecendents method for Navigator.
right now my method looks like this:
Navigator getTable(Navigator config){
return config.children($(By.xpath("//div[#class='myClass']"))).children().children().children().children($(By.xpath("//tbody")))
}
It works fine, but I don't like that I have to do the children() chain. I have to imagine there is simply a way to grab a descendant based on a particular selector but I can not find anything like that in the API
I should add there is a very good reason I don't just use xpath to grab that table. This is just a small snippet of the HTML. This same structure is duplicated many times on the page which is why I have the getTable method.
Maybe you want to use .find() instead of .children()?
$("div.myClass").find("tbody")

Aurelia customAttribute to toggle input edit

I need some help in figuring out the best way to create a customAttribute that will allow for an easy edit-toggle. Here is what I'm looking for:
<tr toggle-edit>
<td edit-hide>${model.name}</td>
<td edit-show><input type="text" value.bind="model.name"></td>
<td><button edit-trigger>Edit</button></td>
</tr>
So basically I want a customAttribute named toggleEdit that will look for edit-trigger attribute and add an event listener to it that will toogle a variable true/false and depending on it will either show or hide the elements that have edit-hide / edit-show.
I'd prefer to not travers the DOM inside the element to find these attributes as it feels jQuerish, is this achievable?
I want to have a customAttribute like this because I have at least 10 elements that will use an edit button and having a variable for each one of them and then use if.bind seems like a bad idea. I could always do inside of the template itself through click.delegate="myShowVar = !myShowVar" but as far as I know puting logic inside html is a bad practice (coming from an angular background).
I would add a plunker/codepen but because of the whole compilation and libraries dependencies this does not seem like an easy task.
Many thanks for any ideas.
Use the contenteditable attribute
I recommend against trying to have a custom attribute automagically handling this for you. You'll probably run into more problems than you'll solve this way. Instead, I recommend that you create an editable property in your view model and bind to it.
The contenteditable attribute is a standard HTML attribute that allows for editing the content of HTML elements, such as DIVs, and is supported out of the box with Aurelia. I recommend leveraging it if it will meet your needs. Here's how:
table.html
<td contenteditable.bind="editable"></td>
<td><button click.delegate="editable = !editable"></td>
Full running gist here: https://gist.run/?id=c4e716f21f4f9c15a9346cfacbdae74b
Since my <tr></tr> turned out to be a 14 line code (with some animation on toggling) I decided it was best to create a customElement out of it. The problem I ran on was that customElements don't really work as table elements (similar as in other frameworks). The soultion to this is to use a as-element attribute.
Inside of the customElement I used contenteditable which is actually a better solution than using if.bind since swapping between input and a div produces a jumping effect because of the difference in styles (which of course could be circumnavigated by applying certain style to them but contenteditable works out-of-the-box).
This is more or less what I created (parent.html):
<tr as-element="my-custom-row"
title="My first row"
is-editable="true"
model.two-way="myModel.name"
value-changed-callback.call="updateModel(myModel)">
</tr>
And inside my-custom-row.html:
<template>
<td>${title & oneTime}</td>
<td>
<div contenteditable.one-way="editingEnabled ? 'true' : 'false'"
blur.trigger="valueChanged(model)"
textcontent.two-way="model">
</div>
<div class="my-class" class.one-way="editingEnabled ? 'my-class--active' : ''"></div>
</td>
<td>
<span class="edit-icon"
click.delegate="editingEnabled = !editingEnabled"
if.one-time="isEditable">
</span>
</td>
</template>
This way I don't have to create a variable for each edit since editingEnabled is unique to each customElement.
As I side note, I think it's better to be more explicit and to use one-way/two-way/one-time instead of bind since it's clear what is happening.
I will also provide the corresponding js for a full answer(my-custom-row.js):
import { bindable } from 'aurelia-framework';
export class MyCustomRow {
#bindable model;
#bindable title;
#bindable isEditable;
#bindable valueChangedCallback;
constructor() {}
valueChanged(modelValue) {
this.valueChangedCallback({ modelValue })
}
}

How to check if there is a strikethrough on some text in selenium webdriver?

There are many planbox, which are having same class and ids, inside them there are a number of <p> tags and decorated text.
<div class="planbox">
<p class="baseprice">
<span>
<strike> $70 </strike>
</span>
</p>
<p> New discount price is etc. </p>
</div>
<div class="planbox">
<p class="baseprice">
<span> $70 </span>
</p>
</div>
Now, My test case is - if the base price is strikethrough, only then <p> 'New discount price .. </p> will show, otherwise not.
How to check whether a text is strikethrough or not? And even if we get this how will I check that <p> New discount.. </p> should not show if the text is not striked.
As there is no class in <p> tag on which I can check whether it displayed or not.
One solution in my mind was - add one dummy class in <span> tag and using findChildren('span.dummyCLass') it will result all the webelements having dummyClass.
Now I will check whether web-elements have strike tag or not, and this is the place where I got stuck.
Initially, i was thinking of a Jquery solution, but is it possible to do without adding new class and jquery?
You don't need to add a class to any element to accomplish this task. In general, you don't want to edit the HTML. Another issue is... if you can find the element to add a class, then you don't need to add the class to find the element. :)
The way I approach tasks like these is to find the outermost element that contains all the elements that you are interested in. I refer to this as a "container". What you want to do in this case is to find the containers and loop through them looking for the strikethrough price and for the "New discount price..." text.
The containers are DIVs with the planbox class. The strikethrough price is indicated by the STRIKE tag. The "New discount price..." text is in a P tag. With this info we can write some code. This is Java because I don't know what language you want and I'm not familiar with the Galen framework.
// gets the collection of containers using a CSS selector
List<WebElement> containers = driver.findElements(By.cssSelector("div.planbox"));
// loops through the containers
for (WebElement container : containers)
{
// determine if the STRIKE tag exists
boolean strikeExists = !container.findElements(By.tagName("strike")).isEmpty();
// determine if the "New discount price is..." text exists in the 2nd P tag
boolean discountPriceExists = container.findElements(By.tagName("p")).get(1).getText().trim().contains("New discount price is");
// if both are true log a pass, otherwise log a fail
if (strikeExists && discountPriceExists)
{
// log a pass
}
else
{
// log a fail
}
}
I haven't used much of selenium. But you can port this jquery code to selenium,
//if there is a strike element
if($(".baseprice span strike").length > 0){
//next() will select the sibling of the p tag with baseprice class
$("p.baseprice).next() != undefined){
return true
}else{
return false
}
}
you can use Galen for this. There you can verify certain CSS properties.

Foreach property in item from list

I'm revamping a small helpdesk application (moving from ASP classic to MVC4). This is my first full MVC application. I've opted to go with Razor, and I feel like it's pretty intuitive. But I've hit a wall on this part.
I get a list of tickets from the database to display to the user. What I would like is to dynamically create a table. Right now I have put the headers in place manually, which is fine. If there's a way to do that dynamically, though, I'm open to suggestions.
But the crucial piece is to get each property from the ticket. I have a Ticket class that has over 20 properties. I'll be working on whittling those down to the minimum we want to display, but as a starting point, I'm trying to throw them all up on the screen.
I have the following:
#model IList<Helpdesk4.Models.Ticket>
...
#foreach (var ticket in Model)
{
<tr>
#foreach (var item in ticket)
{
<td>item</td>
}
</tr>
}
But I can't run that foreach on ticket. I'm enough of a noob that I don't totally understand why, but I think that the properties have to be loaded and so can't be enumerated by default. So without pulling up each property name, how do I just get each property's value from ticket?
I am using NHibernate for the queries to the db if that makes any difference.
The absolutely clearest and easiest way to do this if to manually add each of the properties values to the row. This does require a small amount of "extra" work, but it is a one time thing, and 20 properties is not that much. It also gives you much finer control over exactly how each property is displayed, if it is aligned right or left, etc.
What you end up with is something like this
#foreach (var ticket in Model)
{
<tr>
<td>
#ticket.FirstProperty
</td>
<td class="align-right">
#ticket.SecondProperty
</td>
<td class="align-center bold">
#Html.DisplayFor(m => ticket.ThirdProperty)
</td>
<td>
<i>#ticket.FourthProperty</i>
</td>
...
</tr>
}
Stylings and such added for emphasis of customizability.
Good luck with your first MVC project!
Foreach only works with an enumerable item, and general classes don't implement IEnumerable. You need to put each item on there yourself. The best way would be to use something like Html.TextBoxFor(m => m.Property) for each property.
edit:
The best way would be to just use Html.LabelFor on the object itself.
#for(int index = 0; index < Model.Count; ++index)
{
<tr>
#Html.LabelFor(m => m[index])
<tr>
}