Finding elements in nested repeater in Protractor - protractor

I'm trying to find an element in a nested repeater but I'm not sure how can I tackle it.
By default the HTML looks like following (editted it for easy understanding)
<div ng-repeat = "Repeater1">
<div ng-repeat = "Repeater2"> Text1 </div>
<div ng-repeat = "Repeater2"> Text2 </div>
<div ng-repeat = "Repeater2"> Text3 </div>
</div>
There is a button on the page view more, Which shows you three more items on the page. So after clicking the view more button the HTML looks like following
<div ng-repeat = "Repeater1">
<div ng-repeat = "Repeater2"> Text1 </div>
<div ng-repeat = "Repeater2"> Text2 </div>
<div ng-repeat = "Repeater2"> Text3 </div>
</div>
<div ng-repeat = "Repeater1">
<div ng-repeat = "Repeater2"> Text4 </div>
<div ng-repeat = "Repeater2"> Text5 </div>
<div ng-repeat = "Repeater2"> Text6 </div>
</div>
view more button gets disabled if there are no more items to be displayed on the page.
So my question is: from the default page (before clicking view more button) How can I find the element Text 6 ?
What the test should do:
Search the first three items for elementA
if not found, click on view more and search the next three items for elementA
if not found, click on view more again and search the next three items for elementA
The following code searches withing a repeater but I'm not sure how to search between nested repeater
let filteredList = this.Repeater2Elem.filter((item) => {
return item.getText().then((text) => {
return bundle === "text 2";
});
}).first().element(by.buttonText('Element Found')).click();

It depends if the elements which appear after the click "more" are present but not displayed or do not appear in the DOM at all.
Assuming the element is in DOM but isn't shown. (code shown below isn't tested)
function getAppearence(elem) {
return elem.isDispalyed().then(function (isDispalyed) {
if (isDispalyed)
return elem;//will return the element to continue working on it, otherwise return true
else {
return viewMoreButton.click().then(function () {
return getAppearence(elem);
});
}
});
}
this.Repeater2Elem.filter(function (item, index) {
return item.getText().then(function (text) {
return text === "textX";
});
}).then(function (elem) {
if (elem.length ==1)
return getAppearence(elem[0]).then(function (elem) {
return elem
})
})
First get the required element and then get it to be displayed by clicking recursive the 'view more' button.

Related

How to select the closest element with a specific tag in chai protractor

If the html looks as follow:
<form>
<div>
<field-component>
<div class='field'></div>
</field-component>
</div>
<div>
<div class='icon'></div>
</div>
</form>
I am able to get the field using fieldElement = element(by.css('.field')), but how can I get the closest element with the icon class?
try this:
var form = element(by.css('form'));
return form.element(by.css('.field')).isPresent().then((present) => {
if (present) {
return form.element(by.css('.icon')).click(); #click or whatever on this element
}
});

Show tags under their own specific tab

I'm creating a tag system on my website. So far it's all working great. But now I wish to create a page that shows all my tags under their own tab like you have with a portfolio page.
Example: http://www.don-zalmrol.be/tags?tag=Electronics
My page already displays the tags for a specific tag under it's own tab (i.e. electronics), but as you might guess I wish to populate the other tags in their respective tab as well.
So in short you land a view that displays the tag you've selected, but on the same page you can see the others as well.
Anybody has any idea how I can do this? I don't think I'm far away from the solution as I can already load the projects for specific tags under it's own tab. Now I only need to populate the remaining tabs with the tags!
Thanks!
This is my code so far:
http://pastebin.com/jwGW0NKZ
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
var portfolio = Umbraco.TagQuery.GetAllContentTags().OrderBy(t => t.Text);
var tagList = Umbraco.TagQuery.GetAllContentTags().OrderBy(t => t.Text);
string tag = Request.QueryString["tag"];
if (!tag.IsNullOrWhiteSpace())
{
var publishedContent = Umbraco.TagQuery.GetContentByTag(tag);
if (publishedContent.Count() > 0)
{
#* Show title *#
<div class="media contact-info wow fadeInDown" data-wow-duration="1000ms" data-wow-delay="600ms">
<center>
<div>
<i class="fa fa-tags"></i>
</div>
<br />
<div class="media-body">
<h2>Tags</h2>
<p>Browse content by tag</p>
</div>
</center>
<br />
</div>
#* Show tag titles in tabs *#
<ul class="portfolio-filter text-center">
<li><a class="btn btn-default" href="#" data-filter="*">All tags</a></li>
#foreach (var tags in tagList)
{
<!-- Create a selected tag -->
if(#tags.Text == #tag)
{
<li><a class="btn btn-default active" href="#" data-filter=".#tag">#tag</a></li>
}
#* Show all other tags *#
else
{
<li><a class="btn btn-default" href="#" data-filter=".#tags.Text">#tags.Text</a></li>
}
}
</ul>
<div class="row">
<div class="portfolio-items">
#* Start picture content *#
#foreach (var tags in tagList)
{
#* Put selected tag in the right tag tab *#
if(#tags.Text == #tag)
{
#* Show tag content *#
foreach (var item in publishedContent.OrderByDescending(i => i.CreateDate))
{
<div class='portfolio-item #tag col-xs-12 col-sm-4 col-md-3'>
<div class="recent-work-wrap">
#* IF the project has a picture *#
#if(item.HasValue("pictureOfTheProject"))
{
var featureImage = Umbraco.TypedMedia((int)item.GetPropertyValue("pictureOfTheProject"));
<img class="img-responsive" src="#featureImage.GetCropUrl(250, 250)" alt='#item.GetPropertyValue("titleOfTheProject")' />
<div class="overlay">
<div class="recent-work-inner">
<h3>#item.GetPropertyValue("titleOfTheProject")</h3>
<a class="preview" href="#featureImage.GetCropUrl(250, 250)" rel="prettyPhoto">
<i class="fa fa-eye"></i> View
</a>
</div>
</div>
}
#* Else when the project doesnt have a picture, show default one *#
else
{
var noImage = "http://www.don-zalmrol.be/media/1440/no_image_available.png";
<img class="img-responsive" src="#noImage.GetCropUrl(250, 250)" alt="No image" />
<div class="overlay">
<div class="recent-work-inner">
<h3>#item.GetPropertyValue("titleOfTheProject")</h3>
<a class="preview" href="#noImage.GetCropUrl(250, 250)" rel="prettyPhoto">
<i class="fa fa-eye"></i> View
</a>
</div>
</div>
}
</div>
</div>
}
}
#* Put the other tags under there own tab *#
else
{
}
}
#* End dynamic tags *#
</div>
</div>
}
#* No content matching the tag? *#
else
{
<p>There isn't any content matching that tag.</p>
#Html.Partial("TagList")
}
}
#* Show the tag list with amount *#
else
{
#Html.Partial("TagList")
}
}
EDIT 27-03-2016
Ok so I now know that I need to play around with my tag query or use the IEnumerable. But I can't seem to find it out how I can do this without breaking the code...
#* Get all tags and order them by name *#
var tagList = Umbraco.TagQuery.GetAllContentTags().OrderBy(t => t.Text);
#* Get requested tag *#
string tag = Request.QueryString["tag"];
#* Show all content by requested tag *#
var publishedContent = Umbraco.TagQuery.GetContentByTag(tag);
Above are the pieces of code that list all the tags I have in a var, gets the name from the URL (i.e. Electronics) and one that then displays all content that matches said queried tag.
So in short I need to change the last part of the TagQuery to list all content that has a tag and then filter it out by the querystring to display them in their own category.
But how can list all tagcontent?
Cheers,
Don
Your issue is on line 76 of the pastebin where you loop through the published content, which is already filtered by the selected tag. Because of this, only content with the selected tag ever gets written to the template.
What you need to do is use the loop on line 70 where you're looping through all tags. The jQuery plugin you're using will handle the filtering by using the CSS class you add on line 78. You can get rid of the loop on line 76.
For clarity, I would also change the
#foreach (var tags in tagList)
to
#foreach (var item in tagList)
since the foreach is producing a single tag rather than plural "tags" as your code insinuates. This has the added bonus of allowing you to keep the rest of your code the same once you remove the loop on line 76.

Dynamically added elements - using $(this)

When adding a element to the dom dynamically like this:
row = """
<div class="ipad-row">
<h3>Sample Row</h3>
<div id="wrapper-placeholder">
<div class="scrollView" style="">
<a class="btn btn-primary add-row-item">Add an item</a>
</div>
</div>
</div>
"""
$(".add-row").live "click", ->
$(".ipad .body").append row
false
How come when I try and get this from the a link inside that row element, I get window:
$(".add-row-item").live "click", =>
f = $ this
console.log f // this logs window object, not the link element?
f.parent().append row_item
Can someone please explain this behavior and how i can use $(this) like you would if the element did exist when the dom loaded?
Thanks
=> changes this to the this in the parent context:
$(".add-row-item").live "click", =>
f = $(this)
compiles to
var _this = this;
$(".add-row-item").live("click", function() {
var f = $(_this);
Use -> instead, which won't modify this.

jQuery Isotope Filtering Reset

I'm using JQuery Isotope with a combination, three-level filter. In all the examples I've come across, the only way to "reset" the filters is by clicking a "Show All" option.
Is it possible to "un-filter" results by clicking on a selected filter to un-select it?
Here is an example: http://jsfiddle.net/RevConcept/suagb/
Here is my code...
HTML
<div id="options" class="combo-filters">
<div class="option-combo location">
<ul class="filter option-set group level-one" data-filter-group="location">
<li class="hidden">any
<li>exterior
<li>interior
</ul>
</div>
<div class="option-combo illumination">
<ul class="filter option-set group level-two" data-filter-group="illumination">
<li class="hidden">any
<li>illuminated
<li>non-illuminated
</ul>
</div>
<div class="option-combo mount">
<ul class="filter option-set group level-three" data-filter-group="mount">
<li class="hidden">any
<li>wall
<li>ground
</ul>
</div>
</div><!--end options-->
CSS
header nav a {
color:#666666;
}
header nav a.selected {
color:#000000;
}
JAVASCRIPT
$(function(){
var $container = $('#container'),
filters = {};
$container.isotope({
itemSelector : '.project',
masonry: {
columnWidth: 80
}
});
// filter buttons
$('.filter a').click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return;
}
var $optionSet = $this.parents('.option-set');
// change selected class
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// store filter value in object
// i.e. filters.location = 'exterior'
var group = $optionSet.attr('data-filter-group');
filters[ group ] = $this.attr('data-filter-value');
// convert object into array
var isoFilters = [];
for ( var prop in filters ) {
isoFilters.push( filters[ prop ] )
}
var selector = isoFilters.join('');
$container.isotope({ filter: selector });
return false;
});
});
You could add a "Reload Page" button...
Here are 3 examples for you...
<input type="button" value="Reload Page" onClick="window.location.href=window.location.href">
<input type="button" value="Reload Page" onClick="window.location.reload()">
<input type="button" value="Reload Page" onClick="history.go(0)">
isoSelective provides combining and toggling filters. Try using my updated version: https://github.com/simmerdesign/jquery-isoselective

How to use "this" and not "this" selectors in jQuery

I have 4 divs with content like below:
<div class="prodNav-Info-Panel">content</div>
<div class="prodNav-Usage-Panel">content</div>
<div class="prodNav-Guarantee-Panel">content</div>
<div class="prodNav-FAQ-Panel">content</div>
And a navigation list like this:
<div id="nav">
<ul id="navigation">
<li><a class="prodNav-Info" ></a></li>
<li><a class="prodNav-Usage" ></a></li>
<li><a class="prodNav-Guarantee"></a></li>
<li><a class="prodNav-FAQ" ></a></li>
</ul>
</div>
When the page is first displayed I show all the content by executing this:
$('div.prodNav-Usage-Panel').fadeIn('slow');
$('div.prodNav-Guarantee-Panel').fadeIn('slow');
$('div.prodNav-FAQ-Panel').fadeIn('slow');
$('div.prodNav-Info-Panel').fadeIn('slow');
Now, when you click the navigation list item it reveals the clicked content and hides the others, like this:
$('.prodNav-Info').click( function() {
$('div.prodNav-Info-Panel').fadeIn('slow');
$('div.prodNav-Usage-Panel').fadeOut('slow');
$('div.prodNav-Guarantee-Panel').fadeOut('slow');
$('div.prodNav-FAQ-Panel').fadeOut('slow');
});
So what I have is 4 separate functions because I do not know which content is currently displayed. I know this is inefficient and can be done with a couple of lines of code. It seems like there is a way of saying: when this is clicked, hide the rest.
Can I do this with something like $(this) and $(not this)?
Thanks,
Erik
In your particular case you maybe able to use the .sibilings() method something like this:
$(this).fadeIn().sibilings().fadeOut()
Otherwise, lets say that you have a set of elements stored somewhere that points to all of your elements:
// contains 5 elements:
var $hiders = $(".prodNavPanel");
// somewhere later:
$hiders.not("#someElement").fadeOut();
$("#someElement").fadeIn();
Also, I would suggest changing the classes for your <div> and <a> to something more like:
<div class="prodNavPanel" id="panel-Info">content</div>
....
<a class="prodNavLink" href="#panel-Info">info</a>
This gives you a few advantages over your HTML. First: the links will have useful hrefs. Second: You can easily select all your <div>/<a> tags. Then you can do this with jQuery:
$(function() {
var $panels = $(".prodNavPanel");
$(".prodNavLink").click(function() {
var m = this.href.match(/(#panel.*)$/);
if (m) {
var panelId = m[1];
$panels.not(panelId).fadeOut();
$(panelId).fadeIn();
return false; // prevents browser from "moving" the page
}
});
});