How to check element does exist after mustache templating - javascript

I have this mustache setup:
$.getJSON('data/data.json', function(data) {
var template = "<ul>{{#"+elements+"}}<li class=\"selector {{.}}\"></li>{{/"+elements+"}}</ul>";
var html = Mustache.to_html(template, data);
panel.html(html);
});
After this I need to add some action on my <li> element with class selector. But there is a little problem with this element rendering to DOM. So I use small function to check this element does exist, but something is wrong and I have no results...
$.fn.doesExist = function(){
return $(this).length > 0;
};
var picker = $('li.selector');
if (picker.doesExist()) {
$(this).click(function(){
console.log('log');
})
}
and my html:
<div class="panel">
<ul>
<li class="selector 01"></li>
<li class="selector 02"></li>
<li class="selector 03"></li>
</ul>
</div>

Try this :
$.getJSON('data/data.json', function(data) {
var template = "<ul>{{#"+elements+"}}<li class=\"selector {{.}}\"></li>{{/"+elements+"}}</ul>";
var html = Mustache.to_html(template, data);
panel.html(html);
//*******************
// PERFORM TEST HERE
//*******************
});
//*******************
// $.getJSON() is asynchronous so
// performing test here is too early.
// The response from the server is guaranteed
// not to have arrived yet.
//*******************

try with
if($('li.selector').length>0){
$('li.selector').click(function(){
alert("wow")
})
}
jsFiddle

Related

I get object HTMLSpanElement printed using find() with ajax response

I have a file which has html code like :
<div>
<ul>
<li>
<span class='hour'>5pm</span>
<span class='temp' data-code='10'></span>
</li>
<li>
<span class='hour'> 7pm</span>
<span class='temp' data-code='8'></span>
</li>
<li>
<span class='hour'> 9pm</span>
<span class='temp' data-code='14'></span>
</li>
</ul>
</div>
The Jquery code:
var url = file;
$.get(
url,
function (data) {
var html = $(data),
hours = html.find('span.hour');
$('.container').html('<p id="hour">'+ hours[0]+'</p>');
}
});
The html that the JS file linked to:
<div class="container"></div>
I get this inserted into the .contaner div : [object HTMLSpanElement]
I want to get the text inside each of the spans with class hour
Also , How can I get the value inside the second div with class temp , Which is data-code?
Check if this is what you are looking for. (Check console)
https://codepen.io/anon/pen/EQQJQL
Code from it
$(function() {
var hourSpans = $('.hour')
hourSpans.each(function() {
console.log($( this ).html());
});
var tempSpans = $('.temp')
tempSpans.each(function() {
console.log($( this ).attr('data-code'));
});
});
You can iterate on span.hour. Use .append() to append <p>..</p> in .container
function(data) {
// Iterate on span.hour
$(data).find('span.hour').each(function() {
$('.container').append('<p id="hour">' + $(this).html() + '</p>');
});
}

How to prevent flickering on array updates in angular

In angular, I am trying to keep my page realtime by polling a REST service(hosted locally) and update my array with the new retrieved content like this:
JS
angular.module("WIMT").controller('overviewController', function ($scope,$interval,$http){
var reg = this;
var promise;
reg.teacherInfoList = [];
reg.dayfilter = "";
$scope.start = function() {
$scope.stop();
promise = $interval( $scope.longPolling, 3000);
};
$scope.stop = function() {
$interval.cancel(promise);
};
$scope.longPolling = function(){
reg.teacherInfoList.length = 0;
$http({
method: 'GET',
url: 'api/schedules/' + "TPO01"
}).then(function onSuccessCallback(response) {
reg.teacherInfoList[0] = response.data;
console.log(reg.teacherInfoList[0]);
$scope.start();
}, function errorCallback(response) {
$scope.start();
});
}
$scope.start();
});
HTML
<div ng-controller="overviewController as oc">
<ul>
<li ng-repeat="teachInfo in oc.teacherInfoList ">
{{teachInfo.fullname}}
<div ng-repeat="day in teachInfo.days | filter: oc.dayfilter">
Today is: {{day.day}} {{day.date}}
<ul ng-repeat="roster in day.entries">
<li>
Name: {{roster.name}}
</li>
<li>
Start: {{roster.start}}
</li>
<li>
End: {{roster.end}}
</li>
<li>
Note: {{roster.note}}
</li>
</ul>
</div>
</li>
</ul>
The code used as above causes flickering:
reg.teacherInfoList[0] = response.data;
This code also causes flickering:
reg.teacherInfoList.splice(0,1);
reg.teacherInfoList.splice(0,0,response.data);
I have also tried to apply this to my ng-repeats:
ng-cloack
And applied this to my ng-repeats
track by $index
I have also read this:
How does the $resource `get` function work synchronously in AngularJS?
Now, I know that when I replace my array for a brief second the array is empty causing it to flicker, but I can't think of a solution to solve this problem. What would be the best way to solve this?
reg.teacherInfoList.length = 0;
Not sure if emptying the array is necessary here.
I believe the teacherInfoList array is empty for the entire duration of the request, causing it to render as blank.
You could try either removing (or commenting out) the line above or moving it into the top of the callback function of the GET request like
}).then(function onSuccessCallback(response) {
// applied here
reg.teacherInfoList.length = 0;
reg.teacherInfoList[0] = response.data;
console.log(reg.teacherInfoList[0]);
$scope.start();
}, function errorCallback(response) {
//and here
reg.teacherInfoList.length = 0;
$scope.start();
});

Get `li` elements and push it into object

I have a simple question!
I have this html and js:
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
var data = {
'language': 'fa',
'phrases': {},
};
I want to append all li in the phrases of data for have this output:
{"language":"fa","phrases":{"x":"foo","y":"bar"}}
I try this:
data.phrases.$(this).attr('id') = $(this).html();
And try push this:
data.phrases.push( {$(this).attr('id') : $(this).html()} );
And try extend this:
data.phrases.extend( {$(this).attr('id') : $(this).html()} );
But does not work!
Completed code:
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
<div id="result"></div>
var data = {
'language': 'fa',
'phrases': {},
};
//I want to append all `li` in the `phrases` of `data` for have this output:
//{"language":"fa","phrases":{"x":"foo","y":"bar"}}
$("li").each(function() {
//data.phrases.$(this).attr('id') = $(this).html();
//data.phrases.push( {$(this).attr('id') : $(this).html()} );
//data.phrases.extend( {$(this).attr('id') : $(this).html()} );
});
$("#result").html(JSON.stringify( data ));
See here online code: https://jsfiddle.net/NabiKAZ/fw63jd5k/
You cannot .push() into Object.
Use assignment to properties instead:
var data = {
'language': 'fa',
'phrases': {},
};
$("li").text(function(i, txt) {
data.phrases[this.id] = txt;
});
$("#result").html(JSON.stringify( data ));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
<div id="result"></div>
data.phrases is your object literal
[this.id] is your new object property, where this.id is the current li's ID
= txt; is where you assign to that property the value of the current li text
As you can figure out from above, if you need the entire HTML use .html() instead like:
$("li").html(function(i, html) {
data.phrases[this.id] = html;
});
You're quite close! The issue is that the dot operator in JavaScript cannot be used to evaluate a key then access it. You're looking for the [ ] operator, which can be used to evaluate whatever is in the brackets, then use the value as the key. So try this:
data.phrases[$(this).attr('id')] = $(this).html();
you have the right idea, but you aren't quite using your functions correctly. push is an array method, and extend just isn't a native method. so what we want to do is set the id to the key, and the value to the html
https://jsfiddle.net/fw63jd5k/2/
$("li").each(function(i, el) {
data.phrases[el.id] = $(el).html()
}

Protractor AngularJS count, copy, and verify a list span

I am new to automated testing, Protractor, and angularJS. I have a list that I would like to count, copy to an array maybe, and verify the list text is present. For example The list shows Attractions, Capacity, and Content to the user so they know what privileges they have.
Below is the .html
<div class="home-info">
<div class="home-top home-section">
<h3>User Information</h3>
<div class="home-box">
<div class="property-group wide">
<span>
Change Phillips<br />
</span>
</div>
</div>
<div class="home-box">
<div class="property-group wide">
<div>Editors:</div>
<span>
<ul class="property-stack">
<li><span>Attractions</span>
</li>
<li><span>Capacity</span>
</li>
<li><span>Content</span>
</li>
<li><span>Media</span>
</li>
<li><span>Options</span>
</li>
<li></li>
<li></li>
<li><span>Upload CADs</span>
</li>
</ul>
</span>
</div>
</div>
</div>
Below is the code I have written. I can get the first item on the list however using .all isn't working for me.
var text = "";
browser.driver.findElement.all(By.xpath("//li/span")).count().then(function(count) {
initialCount = count;
console.log(initialCount);
});
browser.driver.findElement(By.xpath("//li/span")).getText().then(function(text) {
console.log(text);
});
I'm trying to avoid using xpath as I was told to try and avoid. To be honest Im lost. Thanks for the help in advance.
Code used for matching:
expect(myLists).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);
I am not sure what version of protractor you're using but you should be able to just call element without the browser or driver prefix. Using element.all should get you the array of of elements you're looking for.
If you want to access specific indexes within that array you can use the .get(index) suffix to the element.all
So below:
1. you get the array of the elements
2. you get the count of the array
3. we call a for loop to iterate through all the indexes of the array
4. each index of the array we call the getText() and print it to the console
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
for(int i = 0; i < count; i++){
myLists.get(i).getText().then(function(text) {
textList[j++] = text;
console.log(text);
});
}
});
EDIT:
In researching I actually found another way to iterate through the array of elements by using the .each() suffix to the element.all.
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
myLists.each(function(element, index) {
element.getText().then(function (text) {
textList[j++] = text;
console.log(index, text);
});
});
});
you should be able to use the textList array to match things.
expect(textList).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);

$scope.apply not working in Angular

im trying to learn Angular.
Here is what im trying to do:
I am building an App that shows me citys. When i click on a city i want to see a list of all my favourite citys.
Using an "Show-List" Button with ng-click works but requires the button the be pushed.
Here is my approach for getting it done automatic:
I want a list in my DOM automatically updated on change of the list.
$scope.$watch('updatedList', function() {
// CHECK IF WORKS
console.log($scope.updatedList);
// APPLY TO DOM
$timeout(function(){
$scope.$apply(function () {
$scope.watchList = $scope.updatedList;
});
}, 1000)
});
The Console shows no error and gives out the correc values:
Object {city.3: "Herat", city.7: "Haag", city.10: "Tilburg" ......}
In my div is the following:
<ul>
<li ng-repeat="y in updatedList">{{ y }}</li>
</ul>
<ul>
<li ng-repeat="a in watchList">{{ a }}</li>
</ul>
First for the NG-Click-Version(which works on click) second for the $scope.$watch
Sorry for lots of questions but im really struggling with the Angular-Docs.
EDIT:
Function that Adds Citys to the List:
$scope.addToList = function(name,id) {
var cityToAdd = name;
var cityToAddID = id;
// ADD A CITY TO THE COOKIE -> WORKS
$cookies.put('city.' + cityToAddID, cityToAdd);
$scope.newList = $cookies.getAll();
$scope.addToListMessage = cityToAdd + " wurde hinzugefĆ¼gt";
// Show short INFONOTICE
window.setTimeout(function() {
$scope.$apply(function() {
$scope.addToListMessage = "";
});
}, 1000);
// Update the List
$scope.updateList();
};
Second Functions -> gets Values from Cookies and puts them to an Array:
$scope.updateList = function() {
var allCitys = $cookies.getAll();
// PUT ALL INTO AN ARRAY -> WORKS
var favouritesFromCookie = [];
$.each(allCitys, function(index, value) {
if (index.indexOf('city.') == 0) { favouritesFromCookie.push(value) }
});
// PUT THE ARRAY OF CITYS INTO A SCOPE_VARIABLE
$scope.updatedList = favouritesFromCookie;
};
Your $scope.updatedList needs to be an array to be used in ng-repeat.
You shouldn't directly write a list in expression. Try this
<ul>
<li ng-repeat="y in watchList">{{ y.city }}</li>
<li ng-repeat="y in watchList">{{ y.yourListItem}}</li>
</ul>

Categories

Resources