Protractor extract data from a repeater - javascript

Starting testing Angular JS application with protractor I would like to extract search results of my application.
To do so I need to iterate through a repeater "objects in objects" and extract the name coloumn :
I am using this code :
var result = element.all(by.repeater('object in objects').column('name'))
result.then(function(arr) {
//Traverse the repeater and extract data
for (var i = 0; i < arr.length; ++i) {
arr[i].getText().then(function(text) {
console.log( text);
console.log( arr.length);
});
}
This code displays only the first 6 elements even when my serach result is far more the 6.
Output :
TSK(AGR020J)(000)(AGR020JN00)(000)
40
40
TSK(ASA700J)(000)(ASA700JU00)(000)
40
40
TSK(AGR060J)(000)(AGR060JN00)(000)
40
40
TSK(AGT001H)(000)(AGT001HS20)(000)
40
40
TSK(ANF010J)(000)(ANF010JU00)(000)
40
40
TSK(AGT001H)(000)(AGT001HN20)(000)
40
40
40
40
....
6 is the number of elements in the first row of my results, I dont' know why the search doese not include remaining rows?
And here is the HTML temlate :
<div id="jobHolder" class="thumbJobs" style="height: 326px; overflow: hidden;" tabindex="5027">
<div id="job_1" class="job ng-scope" ng-click="showJobHoverInfo($index+1)" ng-repeat=
"object in objects" ng-class="object.jobStyle">
<div id="job_1_viewerEye" class="viewerEye" ng-click=
"viewerEye($event,$index+1, object)" ng-class="object.viewerEyeClass"></div>
<div id="job_1_jobBigPicto" class="jobBigPicto transition_2_opa">
<div id="job_1_jobsSmallPictos" class="jobsSmallPictos transition_2_opa">
<div id="job_1_jobDown" class="jobDown transition_2_opa">
<div id="job_1_jobHoverInfo" class="jobHoverInfo" ng-click=
"hideJobHoverInfo($event,$index+1)" style="left: -100%; top: 272px;"></div>
<div id="job_2" class="job ng-scope" ng-click="showJobHoverInfo($index+1)"
ng-repeat="object in objects" ng-class="object.jobStyle">
<div id="job_2_viewerEye" class="viewerEye" ng-click=
"viewerEye($event,$index+1, object)" ng-class="object.viewerEyeClass">
</div>
<div id="job_2_jobBigPicto" class="jobBigPicto transition_2_opa">
<div id="job_2_jobsSmallPictos" class="jobsSmallPictos transition_2_opa">
<div id="job_2_jobDown" class="jobDown transition_2_opa">
<div id="job_2_jobHoverInfo" class="jobHoverInfo" ng-click=
"hideJobHoverInfo($event,$index+1)" style="left: -100%; top: 272px;">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Sorry I think I have pasted the wrong HTML you can see it now after modification :
ng-repeat= "object in objects"

Related

How do I use a JavaScript code to several classes with the same name [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 1 year ago.
I am new to JavaScript, and to stack overflow, so excuse me if I am being oblivious. I was trying to built a progress bar for several classes with the same class name:
<div class="skill">
<h4>Javascript</h4>
<div class="progress-bar" data-label="Loading..." style="--width: 10">
</div>
</div>
<div class="skill">
<h4>Wordpress</h4>
<div class="progress-bar" data-label="Loading..." style="--width: 10">
</div>
<div class="skill">
<h4>Java</h4>
<div class="progress-bar" data-label="Loading..." style="--width: 10">
</div>
</div>
<div class="skill">
<h4>Bootstrap</h4>
<div class="progress-bar" data-label="Loading..." style="--width: 10">
</div>
but the JavaScript code:
const progressBar = document.getElementsByClassName
('progress-bar')[0]
setInterval(() => {
const computedStyle = getComputedStyle(progressBar)
const width = parseFloat(computedStyle.getPropertyValue
('--width')) || 0
progressBar.style.setProperty('--width', width + .1)
},5)
was applied only to the first class:
<h4>Javascript</h4>
<div class="progress-bar" data-label="Loading..." style="--width: 10">
</div>
Where did I go wrong?
Thank you for your time.
('progress-bar')[0]
this will select the first item that it finds..
try this..
const pb = document.getElementsByClassName('progress-bar');
for(var i; i<pb.length ; i++)
{
pb[i].//your codes for each item
}

How to check if all the input values are equal to my data?

I have 32 items in my array, all of them have these properties: id, word, image. User has to guess what's in all the images and write their guess in inputs (so 32 inputs in total). I need to check if the input equals my arrays property "word" and then when clicked a button (type submit, all my pic's and inputs are in a form) display some text for example "Oops! Guess again" if wrong and "Yay! You got it correctly" if right. The text should appear below every input. I displayed all the pictures and inputs with a forEach, and i'm using bulma framework for this page:
const wordBox = info.forEach((words) => {
mainColumns.innerHTML += `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" id="text" type="text" placeholder="Įvesk žodį">
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`;
});
Any ideas?
This is how it should look like (the result should appear in content place)
Something like this
I use change instead of a button click
const info = [
{word:"flower",image:"flower.gif"},
{word:"boat",image:"boat.gif"}
];
const mainColumns = document.getElementById("mainColumns");
mainColumns.innerHTML = info.map(({image,word}) =>
`<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${word}" type="text" placeholder="Įvesk žodį">
<span class="correct hide">Yay</span>
<span class="wrong hide">NOO</span>
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`).join("");
mainColumns.addEventListener("change",function(e) {
const correct = [...mainColumns.querySelectorAll("[data-word]")].map(input => {
if (input.value) {
const correct = input.value === input.dataset.word;
parent = input.closest("div");
parent.querySelector(".correct").classList.toggle("hide",!correct)
parent.querySelector(".wrong").classList.toggle("hide",correct);
return correct ? 1 : 0;
}
else return 0;
}).reduce((a,b)=>a+b);
document.getElementById("correct").innerText = correct;
})
#mainColumns { display:flex; }
.hide { display: none; }
<div id="mainColumns"></div>
Correct: <span id="correct"></span>
What you can do is to filter the word array with word from the input value. Then check if the length is equal zero, No match, if the length is greater than one, then there is a match.
const status = wordBox.filter(item => item.word === inputWord)
I'd move towards keeping the objects and the HTML separate, binding the HTML to the object and vice versa. This means including a couple more properties to your array elements.
let info = [{
image: 'flower.png',
word: 'flower',
content: '',
guess: ''
}];
function bindWords() {
info.forEach((words) => {
mainColumns.innerHTML = `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${words.word}" type="text" placeholder="Įvesk žodį" value="${words.guess}">
</div>
</div>
<div class="content">
${words.content}
</div>
</div>
</div>
</div>`;
});
}
bindWords();
check.addEventListener('click', () => {
info = Array.from(document.querySelectorAll('.card')).map(el => ({
image: el.querySelector('img').src,
word: el.querySelector('.input').dataset.word,
guess: el.querySelector('.input').value,
content: el.querySelector('.input').value === el.querySelector('.input').dataset.word ?
'Correct' : 'Incorrect'
}));
bindWords();
});
<div id="mainColumns"></div>
<button id="check">Check Answers</button>

Show contents of javascript arrays in buttons

I have the following code. How do I make the contents of the array appear on the button? The arrays have a content of 0,1,2,3,4,5. I want the the buttons which are aligned vertically to be as follows:
0
1
2
3
4
5
var family = [0, 1, 2, 3, 4, 5];
console.log(family);
for (var prop in family) {
document.getElementById('aaron-family').innerHTML += '<div class=col> <button type="button" class="list-group-item"' + prop + '</button></div>';
console.log(prop);
}
button {
width: 200px;
height: 200px;
}
<div class="container">
<div class="row">
<ul id="aaron-family">
<div class="list-group"></div>
</ul>
<div class="col">
1 of 3
</div>
<div class="col">
j 1 of 3
</div>
</div>
</div>
This is working fine now.
your code was working fine, you just forget to close the <button> tag on appending the HTML.
var family = [0, 1, 2, 3, 4, 5];
for (var prop in family) {
document.getElementById('aaron-family').innerHTML += '<div class=col> <button type="button" class="list-group-item">' + prop + '</button></div>';
}
button {
width: 200px;
height: 200px;
}
<html>
<body>
<div class="container">
<div class="row">
<ul id="aaron-family">
<div class="list-group">
</div>
</ul>
<div class="col">
1 of 3
</div>
<div class="col">j 1 of 3
</div>
</div>
</div>
</body>
</html>
I hope this was helpful to you. If there is anything else please feel free to ask.
Your loop is incorrect as well as the string html you are trying to append, you can change it to (I used string templates for better readability) :
family.forEach((value) => {
document.getElementById('aaron-family').innerHTML += `
<div class="col">
<button type="button" class="list-group-item">${value}</button>
</div>
`;
});

AngularJS, problems with $index variable in ng-repeat

I'm trying to fill out a 2 column table in AngularJS. I'm using ng-repeat directive to fill out the table, but it's not's working the way I'm planning. My $scope.items is: [Coors, Jameson, Bacardi, Corona]
I want the table to look like this:
| Coors (0) | Jameson (1) |
| Bacardi (2) | Corona (3) |
however, it looks like this:
| Coors (0) | Coors (1) |
| Bacardi (2) | Bacardi (3) |
I'm confused as to why the [$index+1] directive in the my script is only working in the actual text portion of the script (in parenthesis), while the <item-card> div does not seem to properly displaying items[$index+1], and instead is displaying items[$index]. Here is my script:
<div class=row ng-repeat="item in items" ng-if="$index %2 ==0">
<div class="col col-50" ng-if="$index < items.length">
<item-card item="{{item[$index]}}"></item-card>
({{$index}})
</div>
<div class="col col-50" ng-if="$index +1 < items.length">
<item-card item="{{items[$index+1]}}"></item-card>
({{$index+1}})
</div>
</div>
Does anyone know why this might not be working as intended?
Edit: Including is itemcard.html.
<div class = "card" >
<img id = "cardImage" ng-src= "data:image/jpeg;base64,{{item.image}}" width = "100%"/>
{{item.cartQuantity}}
<cardHeader>{{item.itemName}}</cardHeader><br>
<cardHeader ng-if= "item.paksize >1">{{item.paksize}} pack</cardHeader>
<button class="button" ng-click="addToCart(item)">+</button>
<button class="button" ng-click="decrementCart(item)">-</button>
</div>
What you're trying to do seems a little odd to me. Rather than trying to split the array of items into even chunks of 2 columns with Directive Fu, might you consider using lodash.chunk?
<script>
angular.module('example', [ ])
.run(function($scope){
$scope.items = _.chunk([ /* . . . */ ], 2);
});
</script>
<div ng-app="example">
<div class=row ng-repeat="chunk in items">
<div class="col col-50">
<item-card item="{{chunk[0]}}"></item-card>
({{$index}})
</div>
<div class="col col-50">
<item-card item="{{chunk[1]}}"></item-card>
({{$index+1}})
</div>
</div>
</div>
If you wanted to be really Angular about it (a pun!), you could register lodash.chunk as a custom Filter instead:
<script>
angular.module('example', [ ])
.run(function($scope){
$scope.items = [ /* . . . */ ];
})
.filter('chunk', function(){
return _.chunk;
});
</script>
<div ng-app="example">
<div class=row ng-repeat="chunk in items | chunk:2">
<div class="col col-50">
<item-card item="{{chunk[0]}}"></item-card>
({{$index}})
</div>
<div class="col col-50">
<item-card item="{{chunk[1]}}"></item-card>
({{$index+1}})
</div>
</div>
</div>

Close a bootstrap row and start new row after every nth containing div

I have a bootstrap row which will be populated by, let's say, blog post thumbnails.
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="navigation">navigation</div>
</section
I want to close a row, insert hr tag and open a new bootstrap row after every 4th post thumbnail.
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="row">
<div class="col-sm-3">content</div>
</div>
<hr class="divider" />
<div class="navigation">navigation</div>
</section>
Is there a way to do this with jquery?
Can do something like this:
var $mainElem = $('.row'),/* adjust selector to suit page*/
$parent = $mainElem.parent(),
/* remove children after 4th from existing row */
$items = $mainElem.children(':gt(3)').detach();
if ($items.length) {
/* create new row for every 4 items removed above */
for (var i = 0; i < $items.length; i = i + 4) {
var $row = $('<div class="row">').append($items.slice(i, i + 4));
$parent.append('<hr class="divider">').append($row);
}
}
DEMO
This worked best for me:
var $d = $('.thumbs');
var $p = $('.col-sm-3:gt(3)', $d);
if ($p.length) {
$('<div class="row thumbs">').insertAfter($d).append($p);
$('<hr class="divider">').insertAfter($d);
}
Depending on your motivation to wrap each set of columns in a new row, you can style every nth row with straight CSS.
In bootstrap, if you have extra columns that spillover past 12, they just wrap into a new line anyway, so having the new row is usually redundant, although you might have some external reason to keep it in your case.
Either way, here's a CSS solution that adds a page wide horizontal divider every 4 divs:
Demo in jsFiddle & Stack Snippets
.container .row.thumbs div:nth-child(4n) {
position: static;
}
.container .row.thumbs div:nth-child(4n):after {
content: ' ';
border-top: 1px solid black;
display: block;
position: absolute;
width: 95%;
margin-left: 2.5%;
left: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<section class="container">
<div class="row thumbs">
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
<div class="col-sm-3">content</div>
</div>
<div class="navigation">navigation</div>
</section>
Also, bear in mind that this won't be natively supported in < IE8

Categories