var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
var fs = require('fs');
var result;
nightmare
.goto('http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=')
.wait('select[name="selectTeam"]')
.evaluate(function () {
var options = document.querySelectorAll('option'),i;
var values =[]
for (i = 1; i < options.length; ++i) {
values.push(options[i].value)
}
return values;
})
.then(function (values) {
console.log(values)
values.reduce(function(accumulator, value) {
return accumulator.then(function(results) {
return nightmare.goto("http://football-system.jp/fss/pub_penaltylist.php?lid=eBVesRz5C54=")
.wait('select[name="selectTeam"]')
.select('select[name="selectTeam"]', value)
.wait('button[onClick="selectData();"]')
.click('button[onClick="selectData();"]')
.wait('table[class="tableOutputDate"]')
.evaluate(function () {
return document.querySelector('table[class="tableOutputDate"]').textContent;
})
.then(function(result){
console.log(result)
results.push(result);
return results;
});
});
}, Promise.resolve([])).then(function(results){
console.log(results)
});
})
.catch(function (error) {
console.error('Search failed:', error);
});
That is my code .I want to looping select all the selector in that page and get the all html data.I asked a question in here that how to loop in nightmare,but that result cant solve this problem.please help me. Thank you.
I solve my question.the problem is happened in the deal time,not in the loop logic.I add some more wait(time).I think wait(time)is better than the wait(selector).so is over. thank u attention.
var run = function * () {
//var values = ['http://www.yahoo.com', 'http://example.com', 'http://w3c.org'];
var titles = [];
for (var i = 0; i < values.length; i++) {
var title = yield nightmare.goto('.............')
//.wait('select[name="selectTeam"]')
.wait(2000)
.select('select[name="selectTeam"]', values[i])
.wait(2000)
.click('button[onClick="selectData();"]')
//.wait('table[class="tableOutputDate"]')
.wait(2000)
.evaluate(function () {
//return document.querySelector('table[class="tableOutputDate"]').textContent;
var divs = document.querySelectorAll('table[class="tableOutputDate"]'),i;
var tables = []
for (i = 0; i < divs.length; ++i) {
tables.push(divs[i].textContent)
//result += divs[i].href.toString()+"\n";
}
return tables;
})
titles.push(title);
}
return titles;
}
vo(run)(function(err, titles) {
console.dir(titles);
});
Related
I have an issue I have a "chat" and when I add a new text in my infinite scroll container,
I go back to the top of the page, i'm not stuck to the bottom.
How can I maintain the page in the bottom of my page while people chat
my service
tabs.factory('chat', function ($http, $timeout, $q) {
return {
default: {
delay: 100
},
data: [],
dataScroll: [],
init: function (data) {
if (this.data.length == 0) {
for (var i = 0; i < data.length; i++) {
this.data[i] = data[i]
}
} else {
var tailleDataSaved = this.data.length
var dataAAjouter = data.slice(tailleDataSaved)
for (var i = 0; i < dataAAjouter.length; i++) {
this.data.push(dataAAjouter[i])
}
}
},
request: function (showAll) {
var self = this;
var deferred = $q.defer();
var index = this.dataScroll.length
var ndDataVisible = 7
var start = index;
var end = index + ndDataVisible - 1;
$timeout(function () {
if (!showAll) {
var item = []
if (start < end) {
for (var i = start; i < end; i++) {
console.log(start)
console.log(end)
console.log(self.data[i])
if (item = self.data[i]) {
self.dataScroll.push(item);
}
}
}
} else {
self.dataScroll = self.data
}
deferred.resolve(self.dataScroll);
}, 0);
return deferred.promise;
}
}
})
my js file
$scope.listChat= function () {
$scope.isActionLoaded = false;
$http.get(apiurl).then(function (response) {
chat.init(response.data)
$scope.isActionLoaded = true
})
}
$scope.listChatInfiniteScroll = function () {
$scope.isScrollDataLoaded = false
ticketListeActionScroll.request(false).then(function (response) {
$scope.actionsInfiniteScroll = response
$scope.isScrollDataLoaded = true
})
}
html file
<div ng-if="isActionLoaded" infinite-scroll='listChatInfiniteScroll ()' infinite-scroll-distance='1'>
<div ng-repeat="chat in actionsInfiniteScroll">
{{chat.text}}
</div>
</div>
Each time I add a new message it calls listChat
I'm making an ionic application. I have a function called scope.win() that's supposed to fire when a quiz is finished, and then update the JSON file to add that quiz to the number of finished quizzes but it doesn't run properly.It doesn't give off any error. The function just stops running at a certain point and the app keeps going and nothing is happening.
This is the controller's file
angular.module('controllers', ['services'])
.controller('MainCtrl', function ($scope, $state, data) {
$scope.$on('$ionicView.enter', function () {
data.create();
});
$scope.chapter = data.chapterProgress();
})
.controller("BtnClick", function ($scope, lives, data, $cordovaFile, $ionicScrollDelegate) {
var live = 3;
var clickedOn = [];
var numQuestions;
$scope.part2Cred = false;
$scope.part3Cred = false;
$scope.part4Cred = false;
$scope.part5Cred = false;
$scope.part6Cred = false;
$scope.part7Cred = false;
$scope.part8Cred = false;
$scope.part9Cred = false;
$scope.part10Cred = false;
$scope.partQCred = false;
$scope.setNumQuestions = function(num){
numQuestions = num;
}
$scope.updatelives = function (){
//grabs the element that is called liv then updates it
var livesOnPage = document.getElementById('liv');
livesOnPage.innerHTML = live;
}
$scope.wrong = function (event){
var selec = document.getElementById(event.target.id);
if(clickedOn.includes(selec)){}
else{
selec.style.color = "grey";
clickedOn.push(selec);
live = live - 1;
if(live == 0){
$scope.gameover();
}
else{
$scope.updatelives();
}
}
}
$scope.right = function (event,chapter, section){
var selec = document.getElementById(event.target.id);
if(clickedOn.includes(selec)){}
else{
selec.style.color = "green";
clickedOn.push(selec);
numQuestions = numQuestions - 1;
if(numQuestions === 0){
$scope.win(chapter, section);
}
}
}
$scope.gameover = function(){
alert("game over please try again");
live = 3;
$ionicScrollDelegate.scrollTop();
$scope.partQCred = false;
$scope.part1Cred = !$scope.part1Cred;
for(i = 0; i< clickedOn.length;i++){
clickedOn[i].style.color = "rgb(68,68,68)";
}
}
$scope.win = function (chapter, section) {
alert("Well Done");
var data = data.chapterProgress(); // It is at this point that the //function stops running without giving off any error.
alert("Good Job");
var sectionsComplete = data[chapter].sectionsCompleted;
var totalsection = data[chapter].totalSections;
if (section === totalSection) {
window.location.href = "#/chapter1sections";
return;
}
if (section > sectionsComplete) {
data[chapter].sectionsCompleted += 1;
var url = "";
if (ionic.Platform.isAndroid()) {
url = "/android_asset/www/";
}
document.addEventListener('deviceready', function () {
$cordovaFile.writeFile(url + "js/", "chapters.json", data, true)
.then(function (success) {
// success
alert("Json file updated")
window.location.href = "#/chapter1sections";
}, function (error) {
// error
});
});
}
}
});
Here is the Services file. It seems to run fine but it is referenced a lot in the problematic sections of code in the controllers so I figured it was necessary to put it here.
angular.module('services', [])
.service('lives', function () {
var live = 3;
return {
getlives: function () {
return live;
},
setlives: function (value) {
live = value;
}
};
})
.service('data', function ($cordovaFile, $http) {
var url = "";
if (ionic.Platform.isAndroid()) {
url = "/android_asset/www/";
}
return {
//Run this function on startup to check if the chapters.json file exists, if not, then it will be created
create: function () {
var init = {
"one": {
"sectionsCompleted": 0,
"totalSections": 4
},
"two": {
"sectionsCompleted": 0,
"totalSections": 1
}
};
$cordovaFile.writeFile(url + "js/", "chapters.json", init, false)
.then(function (success) {
// success
}, function (error) {
// error
});
},
chapterProgress: function () {
return $http.get(url + "js/chapters.json").success(function (response) {
var json = JSON.parse(response);
return json;
}, function (error) {
alert(error);
});
}
}
});
Thank You so much for the help and time.
i recently needed some kinda customized repeater, which group data by their key, but not simply group them all together, so i read several references and things,... and at last i come up to copy
groupBy from this article which he seem to complete it at best, ...
http://sobrepere.com/blog/2014/10/14/creating-groupby-filter-angularjs/
And then i customized so it become like this:
the things my group by do... is:
Group Data Together Until It Reach Differences.
but the matter is that though it work, it still generate infdig, i know it's because the digest done call other one, but what i don't know is how to solve it in very easy and understandable manner, as i'm new to JavaScript...
app.filter('groupBy', function () {
var results = {};
return function (data, key) { //Data => My Objects Array - Key => Name Of Filtered Property
if (!(data && key)) return;
var result;
if (!this.$id) {
result = {};
} else {
var scopeId = this.$id;
if (!results[scopeId]) {
results[scopeId] = {};
this.$on("$destroy", function () {
delete results[scopeId];
});
}
result = results[scopeId];
}
for (var groupKey in result)
result[groupKey].splice(0, result[groupKey].length);
var grpKey = -1; //GroupKey
var lastUserId;
for (var i = 0; i < data.length; i++) {
if (!result[grpKey] || lastUserId && lastUserId != data[i][key]) // Ex.: result[data[0]["UserId"]]{ => return UserId
result[++ grpKey] = [];
result[grpKey].push(data[i]);
lastUserId = data[i][key];
}
var keys = Object.keys(result);
for (var k = 0; k < keys.length; k++) {
if (result[keys[k]].length === 0)
delete result[keys[k]];
}
return result;
};
});
In this url is working perfectly...
http://plnkr.co/edit/8jB4wSRtKfVmEsTGZtfV?p=preview
app.filter('groupBy', function ($timeout) {
return function (data, key) {
if (!key) return data;
var outputPropertyName = '__groupBy__' + key;
if(!data[outputPropertyName]){
var result = {};
for (var i=0;i<data.length;i++) {
if (!result[data[i][key]])
result[data[i][key]]=[];
result[data[i][key]].push(data[i]);
}
Object.defineProperty(result, 'length', {enumerable: false, value: Object.keys(result).length});
Object.defineProperty(data, outputPropertyName, {enumerable:false, configurable:true, writable: false, value:result});
$timeout(function(){delete data[outputPropertyName];},0,false);
}
return data[outputPropertyName];
};
});
I have an associative array date as key, the value in this case is an array of objects. Now in this object
while (tempDate < endDate) {
$scope.dates.push(tempDate.format("DD-MM-YYYY"));
var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
for (var i = 0; i < dailyTrips.length; i++) {
// console.log(moment(dailyTrips[i].trip.startTime).format("hh:mm a"));
// console.log(moment(dailyTrips[i].trip.endTime).format("hh:mm a"));
geocode(dailyTrips, i);
}
tempDate.add(1, 'days');
}
$scope.data = response.data;
var geocode = function(dailyTrips, i) {
(function() {
var latlng = {
lat: dailyTrips[i].trip.source.latitude,
lng: dailyTrips[i].trip.source.longitude
};
console.log(latlng);
var geocoder = new google.maps.Geocoder;
geocoder.geocode({
'location': latlng
}, function(result, status) {
if (result[1]) {
console.log(result[1].address_components[0].long_name+" "+result[1].address_components[2].long_name);
}
});
}(i));
};
Now This code is working but running at completely different times as it's a callback. I wanted to have this all at one time so that I can use it in ng-repeat and show everything nicely. How do I do that?
Expected output
Trip StartTime Trip from
Trip EndLine Trip To
EDIT 1: Still not working
while (tempDate < endDate) {
$scope.dates.push(tempDate.format("DD-MM-YYYY"));
var dailyTrips = response.data[tempDate.format("DD-MM-YYYY")];
var promises = [];
for (var i = 0; i < dailyTrips.length; i++) {
promises[i] = geocode(dailyTrips, i);
}
$q.all(promises).then(function(result) {
console.log(result); //line 39
});
tempDate.add(1, 'days');
}
$scope.data = response.data;
}, function(error) {
console.log(error.data);
});
var geocode = function(dailyTrips, i) {
var q = $q.defer();
var latlng = {
lat: dailyTrips[i].trip.source.latitude,
lng: dailyTrips[i].trip.source.longitude
};
console.log(latlng);
var geocoder = new google.maps.Geocoder;
geocoder.geocode({
'location': latlng
}, function(result, status) {
console.log(status);
if (status === google.maps.GeocoderStatus.OK) {
console.log(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
q.resolve(result[1].address_components[0].long_name + " " + result[1].address_components[2].long_name);
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function() {
geocode(dailyTrips, i);
}, 500);
} else {
q.reject();
}
});
return q.promise;
};
You cannot make an async call synchronous, except by blocking your code, which you do no NOT want to do. Instead, I suggest you convert geocode into a promise
var geocode = function(dailyTrips, i) {
return this.$q((resolve, reject) => {
....
and then wait for all the promises to complete
var promises = [];
for (var i = 0; i < dailyTrips.length; i++) {
promises[i] = geocode(dailyTrips, i);
}
$q.all(promises).then( function(results) {...} );
I always manage pagination with angular
retrieve all the data from the server
and cache it client side (simply put it in a service)
now I have to cope with quite lot of data
ie 10000/100000.
I'm wondering if can get into trouble
using the same method.
Imo passing parameter to server like
page search it's very annoying for a good
user experience.
UPDATE (for the point in the comment)
So a possible way to go
could be get from the server
like 1000 items at once if the user go too close
to the offset (ie it's on the 800 items)
retrieve the next 1000 items from the server
merge cache and so on
it's quite strange not even ng-grid manage pagination
sending parameters to the server
UPDATE
I ended up like:
(function(window, angular, undefined) {
'use strict';
angular.module('my.modal.stream',[])
.provider('Stream', function() {
var apiBaseUrl = null;
this.setBaseUrl = function(url) {
apiBaseUrl = url;
};
this.$get = function($http,$q) {
return {
get: function(id) {
if(apiBaseUrl===null){
throw new Error('You should set a base api url');
}
if(typeof id !== 'number'){
throw new Error('Only integer is allowed');
}
if(id < 1){
throw new Error('Only integer greater than 1 is allowed');
}
var url = apiBaseUrl + '/' + id;
var deferred = $q.defer();
$http.get(url)
.success(function (response) {
deferred.resolve(response);
})
.error(function(data, status, headers, config) {
deferred.reject([]);
});
return deferred.promise;
}
};
};
});
})(window, angular);
(function(window, angular, undefined) {
'use strict';
angular.module('my.mod.pagination',['my.mod.stream'])
.factory('Paginator', function(Stream) {
return function(pageSize) {
var cache =[];
var staticCache =[];
var hasNext = false;
var currentOffset= 0;
var numOfItemsXpage = pageSize;
var numOfItems = 0;
var totPages = 0;
var currentPage = 1;
var end = 0;
var start = 0;
var chunk = 0;
var currentChunk = 1;
var offSetLimit = 0;
var load = function() {
Stream.get(currentChunk).then(function(response){
staticCache = _.union(staticCache,response.data);
cache = _.union(cache,response.data);
chunk = response.chunk;
loadFromCache();
});
};
var loadFromCache= function() {
numOfItems = cache.length;
offSetLimit = (currentPage*numOfItemsXpage)+numOfItemsXpage;
if(offSetLimit > numOfItems){
currentChunk++;
load();
}
hasNext = numOfItems > numOfItemsXpage;
totPages = Math.ceil(numOfItems/numOfItemsXpage);
paginator.items = cache.slice(currentOffset, numOfItemsXpage*currentPage);
start = totPages + 1;
end = totPages+1;
hasNext = numOfItems > (currentPage * numOfItemsXpage);
};
var paginator = {
items : [],
notFilterLabel: '',
hasNext: function() {
return hasNext;
},
hasPrevious: function() {
return currentOffset !== 0;
},
hasFirst: function() {
return currentPage !== 1;
},
hasLast: function() {
return totPages > 2 && currentPage!==totPages;
},
next: function() {
if (this.hasNext()) {
currentPage++;
currentOffset += numOfItemsXpage;
loadFromCache();
}
},
previous: function() {
if(this.hasPrevious()) {
currentPage--;
currentOffset -= numOfItemsXpage;
loadFromCache();
}
},
toPageId:function(num){
currentPage=num;
currentOffset= (num-1) * numOfItemsXpage;
loadFromCache();
},
first:function(){
this.toPageId(1);
},
last:function(){
this.toPageId(totPages);
},
getNumOfItems : function(){
return numOfItems;
},
getCurrentPage: function() {
return currentPage;
},
getEnd: function() {
return end;
},
getStart: function() {
return start;
},
getTotPages: function() {
return totPages;
},
getNumOfItemsXpage:function(){
return numOfItemsXpage;
},
search:function(str){
if(str===this.notFilterLabel){
if(angular.equals(staticCache, cache)){
return;
}
cache = staticCache;
}
else{
cache = staticCache;
cache = _.filter(cache, function(item){ return item.type == str; });
}
currentPage = 1;
currentOffset= 0;
loadFromCache();
}
};
load();
return paginator;
}
});
})(window, angular);
server side with laravel (All the items are cached)
public function tag($page)
{
$service = new ApiTagService(new ApiTagModel());
$items = $service->all();
$numOfItems = count($items);
if($numOfItems > 0){
$length = self::CHUNK;
if($length > $numOfItems){
$length = $numOfItems;
}
$numOfPages = ceil($numOfItems/$length);
if($page > $numOfPages){
$page = $numOfPages;
}
$offSet = ($page - 1) * $length;
$chunk = array_slice($items, $offSet, $length);
return Response::json(array(
'status'=>200,
'pages'=>$numOfPages,
'chunk'=>$length,
'data'=> $chunk
),200);
}
return Response::json(array(
'status'=>200,
'data'=> array()
),200);
}
The only trouble by now is managing filter
I've no idea how to treat filtering :(