Add class to parent of <img> with certain class name or certain source - selector

My HTML looks like this, and I'm working with the YUI library:
<div>
<img class="smallimage" src="host/smallimage.jpg">
</div>
<div>
<img src="host/bigimage.jpg">
</div>
I would like to know how to (1) add a class to the container off all images with the class of .smallimage as well as (2) add a class to the container of all images with the string 'big' in the source tag. :)
So that the output is like this:
<div class = "small">
<img class="smallimage" src="host/smallimage.jpg">
</div>
<div class = "big">
<img src="host/bigimage.jpg">
</div>
Thanks very much fellas!
UPDATE:
Fellas I think I have figured this out now, but would still apprecate if someone could maybe just look if its solid:
1)
YUI().use('node', function(Y)
var node = Y.one(".smallimage")
Y.one(".smallimage").get('parentNode').addClass("small");
});
2)
YUI().use('node', function(Y)
var node = Y.one("img[src*='big']")
Y.one("img[src*='big']").get('parentNode').addClass("big");
});
Thanks!

Your solution is correct, but as the function says using Y.one will affect only one element. If you have multiple images you should use Y.all.
Also, keep in mind that you can do everything inside one YUI().use() call.

Related

Use GetElementsByClass to find all <div> elements by class name, nested inside a <p> element

I am creating a parser using Jsoup in Kotlin
I need to get a inner text of a tag with class "ptrack-content" inside the tag with class "titleCard-synopsis"
When I am trying to getElementsByClass in a element objects that created by a former getElementsByClass, I getting 0 elements
Code:
class NetlifxHtmlParser {
val html = """
<div class="titleCardList--metadataWrapper">
<div class="titleCardList-title"><span class="titleCard-title_text">Map Her</span><span><span class="duration ellipsized">50m</span></span></div>
<p class="titleCard-synopsis previewModal--small-text">
<div class="ptrack-content">A hidden map rocks Hartley High as the students' sexcapades are publicly exposed. Caught as the culprit, Amerie becomes an instant social pariah.</div>
</p>
</div>
<div class="titleCardList--metadataWrapper">
<div class="titleCardList-title"><span class="titleCard-title_text">Renaissance Titties</span><span><span class="duration ellipsized">50m</span></span></div>
<p class="titleCard-synopsis previewModal--small-text">
<div class="ptrack-content">Amerie, the new outcast, receives a party invitation that gives her butterflies. But when she manages to show up, a bitter surprise awaits.</div>
</p>
</div>
""".trimIndent()
fun parseEpisode() {
val doc = Jsoup.parseBodyFragment(html)
val titleCards = doc.getElementsByClass("titleCard-synopsis")
println("Episode: count titleCard = > ${titleCards.count()}") // 2
titleCards.forEachIndexed { index, element ->
val ptrack = element.getElementsByClass("ptrack-content")
println("Episode: count ptrack = > ${ptrack.count()}") // 0 !!
println("inner html = > ${ptrack.html()}") // null string !!
}
}
}
In the above code,
First, I am extracting tags with class name titleCard-synopsis.
For that , I using doc.getElementsByClass("titleCard-synopsis") which returns 2 element items.
Then, In the List of titleCard elements, I am extracting the elements that have ptrack-content as Class, by using the same getElementsByClass in each element,
which returns empty list.
Why this is happening ?
My goal is, I need to extract the description text for each title, the stored in the interior tags of p tag with class titleCard-synopsis.
If I try to get directly from "ptrack-content", it's working fine, but this a general class used in many places in the main HTML source. (this is snippet)
I need to get a inner text of a tag with class "ptrack-content" inside the tag with class "titleCard-synopsis"
But in the above method in the code, I am only getting emtpy list.
Why ?
Also note that, if I invoke the HTML() method in a element object of titleCards(ptrack.html()),
I am not getting the inner DIV tag, an empty string!!!
Please guide my to resolve the issue !
TL;DR
I need to get a inner text of a tag with class "ptrack-content" inside the tag with class "titleCard-synopsis"
I'm not really familiar with Kotlin, but this should produce the desired output:
val doc = Jsoup.parseBodyFragment(html)
val result = doc.select(".titleCard-synopsis + .ptrack-content")
result.forEachIndexed {index, element ->
println("${element.html()}")
}
Live example
This is an interesting problem!
You basically have an invalid HTML and jsoup is smart enough to auto-correct it for your. Your HTML structure gets altered and suddenly your query does not work.
This is the error:
<p class="titleCard-synopsis previewModal--small-text">
<div class="ptrack-content">A hidden map rocks Hartley High as the students' sexcapades are publicly exposed. Caught as the culprit, Amerie becomes an instant social pariah.</div>
</p>
You can't nest a <div> element inside a <p> element like that.
Paragraphs are block-level elements, and notably will automatically close if another block-level element is parsed before the closing </p> tag. [Source: <p>: The Paragraph element]
Also, look at Nesting block level elements inside the <p> tag... right or wrong?
This is how jsoup parses your tree:
<html>
<head></head>
<body>
<div class="titleCardList--metadataWrapper">
<div class="titleCardList-title">
<span class="titleCard-title_text">Map Her</span><span><span class="duration ellipsized">50m</span></span>
</div>
<p class="titleCard-synopsis previewModal--small-text"></p>
<div class="ptrack-content">
A hidden map rocks Hartley High as the students' sexcapades are publicly exposed. Caught as the culprit, Amerie becomes an instant social pariah.
</div>
<p></p>
</div>
<div class="titleCardList--metadataWrapper">
<div class="titleCardList-title">
<span class="titleCard-title_text">Renaissance Titties</span><span><span class="duration ellipsized">50m</span></span>
</div>
<p class="titleCard-synopsis previewModal--small-text"></p>
<div class="ptrack-content">
Amerie, the new outcast, receives a party invitation that gives her butterflies. But when she manages to show up, a bitter surprise awaits.
</div>
<p></p>
</div>
</body>
</html>
As you can see, elements with class titleCard-synopsis have no children with class ptrack-content.

How to find xpath of an element which depends upon sibling class

I have below html code
<a class = sidetoolsdivider>
<div class = sideone > Test 1 </div>
<div class = sidetwo> </div>
</a>
<a class = sidetoolsdivider>
<div class = sideone > Test 2 </div>
<div class = sidetwo> </div>
</a>
...............
Here I need to find xpath locator of class sidetwo which has text Test1. There are many such similar classes hence you can differentiate between different only based on element text
The xpath would be something like below:
Since the element depends on the text, can make use of text attribute for the same.
//div[text()='Text1']/following-sibling::div
Or
//div[contains(text(),'Text1')]/following-sibling::div
Or
//div[contains(text(),'Text1')]/following-sibling::div[#class='sidetwo']
Link to refer - Link
This gets you the correct 'a'. Find an 'a' which contains the right div of sideone (note the .//, find a Child which is)
"//a[.//div[ #class='sideone" and text()='Test 1']"
Then just get the side two, complete xPath
"//a[.//div[ #class='sideone" and text()='Test 1']//div[#class='sidetwo']"
Works even if there is more text inside the entire 'a' and stuff gets complex with more elements inside.

Using dynamic IDs in a string in a VueJS

I'm using a UIKit library for a tab component that listens to a uk-tab property that targets an id. The problem with this, is that it creates the same ID for every tabbed component. I like the UI, but whoever thought of this, didn't think too far into it. I could fix it by making the id dynamic but I am having trouble calling it in the uk-tab property because it is rendering a string. Coming from a react background, I would do a string literal and some JSX, something like #item-${_id}to show #item-12, #item-13....and so on. But That's not working. How can I do this in Vue?
Here is an example of how it works
<div class="mytrigger">
<ul uk-tab="connect: #component-tab-left; animation: uk-animation-fade">
</div>
<div class="mytargetedtab">
<ul id="component-tab-left" class="uk-switcher">
</div>
Here is an example of how what I need
<div class="mytrigger">
<ul uk-tab="connect: #_uid+'switcher'; animation: uk-animation-fade">
</div>
<div class="mytargetedtab">
<ul :id="_uid+'switcher'" class="uk-switcher">
</div>
Check out the dev tools. It should be 810switcher, but instead is taking it as a string
Any ideas? Thanks
I believe what you need is:
<ul :uk-tab="`connect: #${_uid}switcher; animation: uk-animation-fade`">
Or if you prefer not to use backticks:
<ul :uk-tab="'connect: #' + _uid + 'switcher; animation: uk-animation-fade'">
The output will be:
<ul uk-tab="connect: #22switcher; animation: uk-animation-fade">
A few notes:
Using a : is short for v-bind: but don't let the name confuse you. v-bind doesn't necessarily bind anything, it just makes the attribute value a JavaScript expression.
I'd avoid using numbers at the start of element ids, I've seen that cause problems in the past. It'd be better to put the numbers at the end.
The underscore at the start of _uid indicates that it's private to Vue. There are no guarantees about what form it will take or whether it will even exist going forward.
Use data-uk-tab instead of uk-tab like below.
<div class="mytrigger">
<ul data-uk-tab="{connect: `#${_uid}switcher`, animation: 'uk-animation-fade'}">
</div>
<div class="mytargetedtab">
<ul :id="_uid+'switcher'" class="uk-switcher">
</div>
For more information => Switcher with tabs
You can use any javascript expression in a data binding in vue. So, if you bind a string template to the attribute, it'll populate what you expect.
<ul :uk-tab="`connect: #${uid}switcher`'; animation: uk-animation-fade">

Change element type at runtime

Is it possible to dynamically define the type of an element inside a custom components template at runtime?
I'd like to avoid duplication of the inner contents of the button and a element in the following example:
<template>
<button if.bind="!isLinkBtn">
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</button>
<a if.bind="isLinkBtn">
<!--
The content is a 1:1 duplicate of the button above which should be prevented
somehow in order to keep the view DRY
-->
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</a>
</template>
Is it possible to write something like this:
<template>
<!--
The type of element should be defined at runtime and can be a standard HTML "button"
or an anchor "a"
-->
<element type.bind="${isLinkBtn ? 'a' : 'button'}">
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</element>
</template>
I'm aware of dynamic composition with <compose view="${widget.type}-view.html"></compose> but as far as I know, this won't allow me to create default HTML elements but only custom components, correct?
I've asked this question on the Aurelia Gitter where Erik Lieben suggested to use a #processContent(function) decorator, replace the content within the given function and return true to let Aurelia process it.
Unfortunately I don't know how to actually apply those instructions and am hoping for some alternative approaches here or some details about how to actually accomplish this.
Edit
I've created a corresponding feature request. Even though possible solutions have been provided, I'd love to see some simpler way to solve this ;)
When you want to reuse HTML snippets, use compose. Doing so does not create a new custom element. It simply includes the HTML at the location of each compose element. As such, the view-model for the included HTML is the same as for the element into which it is composed.
Take a look at this GistRun: https://gist.run/?id=36cf2435d39910ff709de05e5e1bedaf
custom-link.html
<template>
<button if.bind="!isLinkBtn">
<compose view="./custom-link-icon-and-text.html"></compose>
</button>
<a if.bind="isLinkBtn" href="#">
<compose view="./custom-link-icon-and-text.html"></compose>
</a>
</template>
custom-link.js
import {bindable} from 'aurelia-framework';
export class CustomLink {
#bindable() contentText;
#bindable() icon;
#bindable() isLinkBtn;
}
custom-link-icon-and-text.html
<template>
<span class="btn-icon">${icon}</span>
<span class="btn-text">${contentText}</span>
</template>
consumer.html
<template>
<require from="./custom-link"></require>
<custom-link content-text="Here is a button"></custom-link>
<custom-link is-link-btn.bind="true" content-text="Here is a link"></custom-link>
</template>
You may want to split these into separate elements, like <custom-button> and <custom-link> instead of controlling their presentation using an is-link-btn attribute. You can use the same technique to reuse common HTML parts and composition with decorators to reuse the common code.
See this GistRun: https://gist.run/?id=e9572ad27cb61f16c529fb9425107a10
Response to your "less verbose" comment
You can get it down to one file and avoid compose using the techniques in the above GistRun and the inlineView decorator:
See this GistRun: https://gist.run/?id=4e325771c63d752ef1712c6d949313ce
All you would need is this one file:
custom-links.js
import {bindable, inlineView} from 'aurelia-framework';
function customLinkElement() {
return function(target) {
bindable('contentText')(target);
bindable('icon')(target);
}
}
const tagTypes = {button: 'button', link: 'a'};
#inlineView(viewHtml(tagTypes.button))
#customLinkElement()
export class CustomButton {
}
#inlineView(viewHtml(tagTypes.link))
#customLinkElement()
export class CustomLink {
}
function viewHtml(tagType) {
let result = `
<template>
<${tagType}${tagType === tagTypes.link ? ' href="#"' : ''}>
<span class="btn-icon">\${icon}</span>
<span class="btn-text">\${contentText}</span>
</${tagType}>
</template>
`;
return result;
}
Sorry, I was doing 2 things at once while looking at gitter, which I am not good at apparently :-)
For the thing you wanted to accomplish in the end, could this also work?
I am not an a11y expert or have a lot of knowledge on that area, but from what I understand, this will accomplish what you want. The browser will look at the role attribute and handle it as a link or button and ignores the actual element type itself / won't care if it is button or anchor it will act as if it is of the type defined in role.
Then you can style it like a button or link tag with css.
<a role.bind="type"><span>x</span><span>y</span></a>
where type is either link or button, see this: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_link_role

Foundation equalizer plug + BS 3.2?

Trying to use equalizer plug, but id doesn't work, and no errors. It`s look like http://goo.gl/OvKy1g. Here is a page http://goo.gl/INMqUL. Do i need include some css for it.
You can use the Foundation Equalize plugin along with Twitter Bootstrap, but you need to do a couple of things to make it work.
DEMO
First, your principle issue is that foundation.js is looking for the corresponding foundation.css. Since you're using Twitter Bootstrap as your base styles, you probably don't want to have to deal with all of the potential style conflicts or having your users download another large css file. Really all that is needed is a reference to the Foundation version and namespace, so just add the following to your css:
meta.foundation-version {
font-family: "/5.4.5/";
}
meta.foundation-data-attribute-namespace {
font-family: false;
}
The second issue is with your markup. You have the data-equalizer-watch attribute applied to the containing .col-sm-4 element, but you have your border on the child element with the class latest-news-item. So change your markup to be:
<div class="row" data-equalizer>
<div class="col-sm-4" >
<div class="latest-news-item" data-equalizer-watch>
<!--Your content here-->
</div>
</div>
<div class="col-sm-4" >
<div class="latest-news-item" data-equalizer-watch>
<!--Your content here-->
</div>
</div>
<div class="col-sm-4" >
<div class="latest-news-item" data-equalizer-watch>
<!--Your content here-->
</div>
</div>
</div>
As you can see in the demo, I was able to get your test page to work with these changes, but I was also able to dramatically reduce the foundation.js file size by using the Custom option on the Foundation Download page and just building a js version with the equalize plugin only. The minified version was 31K. If you're not planning to use any of the other foundation plugins, you might consider using a custom file.
That said, for folks that are looking for an alternative lighter-weight approach, it might be just as easy to write your own jQuery such as by adding a class to the row you want to equalize (I called it 'equalize') and then add:
var row=$('.equalize');
$.each(row, function() {
var maxh=0;
$.each($(this).find('div[class^="col-"]'), function() {
if($(this).height() > maxh)
maxh=$(this).height();
});
$.each($(this).find('div[class^="col-"]'), function() {
$(this).height(maxh);
});
});
Wrap it in a function and you can call it on resize as well if that is important to you.