Angularfire $firebaseArray extend dynamic count\sum - javascript

Am trying to achieve a dynamic count of certain node if defined:
This works but its not dynamic, you have to call sum().
app.factory("ArrayWithSum", function($firebaseArray) {
return $firebaseArray.$extend({
sum: function() {
var total = 0;
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
// the array data is located in this.$list
angular.forEach(this.$list, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
total++;
}
}
}
});
return total;
}
});
});
I tried $$update but can't access this_counter in array:
app.factory("counter", function($firebaseArray) {
return $firebaseArray.$extend({
sum: function() {
return this._counter;
},
$$updated: function(){
var changed = $firebaseArray.prototype.$$updated.apply(this, arguments);
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
if( !this._counter ) {
this._counter = 0;
}
// the array data is located in this.$list
angular.forEach(this.$list, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
this._counter++;
}
}
}
});
return changed;
}
});
});
Does anyone know how to make a dynamic variable that I can update and access?
Thanks

Got it working with $firebaseObject. Obviously you can add a property _counter to an object not an array. Any way this works and a good way to get a dynamic count.
app.factory("counter", function($firebaseObject) {
return $firebaseObject.$extend({
$$updated: function(){
var changed = $firebaseObject.prototype.$$updated.apply(this, arguments);
if( !this._counter ) { this._counter = 0; }
var total = 0;
var todayDate = new Date();
var start = todayDate.setHours(0,0,0,0);
var end = todayDate.setHours(23,59,59,999);
// the array data is located in this.$list
angular.forEach(this, function(rec) {
if (angular.isDefined(rec.qa)){
if (angular.isDefined(rec.qa.completed)) {
if (rec.qa.completed >= start && rec.qa.completed <= end){
total++;
}
}
}
});
this._counter = total;
return changed;
}
});
});
vm.panels = new counter(panelsRef);
{{vm.panels._counter}}
Am having issues with watches not firing after a long duration on IE11. So thought I'd try this approach.

Related

Stop execute ajax in for loop

I'm trying to do the following. Get number of pages from the API. Each page has multiple results. I check all the results with my condition. If the result fits the condition, then I need to finish the check, finish the page search and pass the result to another function. I don't understand how to end ajax (getData() execution in the checkPages() function) and exit the for loop in the same place. The break and return keywords do not help. Please tell me how to do it. Maybe I need to do to refactor my code. I don't really like to "throw" results from a function into a function. I do not use async/await because I need compatibility with old browsers.
getData("url-to-get-data").done(function (result) {
checkPages(result.total_pages);
});
function getData(url) {
return $.get({
url: "url-to-get-data"
})
}
function checkPages(pagesCount) {
for (var i = 2; i <= pagesCount; i++) {
getData("url-to-get-data", i).done(function(result) {
var today = checkToday(result);
if (today != null) {
//someMethod
//how to end the getData function and the for loop
}
});
}
}
function checkToday(response) {
var results = response.results;
var today = new Date();
var day = today.getDate();
var month = today.getMonth();
for (var i = 0; i < results.length; i++) {
var d = new Date(results[i].release_date);
if (d.getDate() === day && d.getMonth() === month) {
return results[i];
}
}
return null;
}
simplest change to your checkPages function
inner function that calls itself as required
function checkPages(pagesCount) {
function checkPage(i) {
if (i <= pagesCount) {
getData("url-to-get-data", i).done(function(result) {
var today = checkToday(result);
if (today == null) { // only get next page if today is null
checkPage(i+1);
}
});
}
}
checkPage(2);
}
If I understand correctly you are trying to do something like this?
UPDATE: implemented que to check if request is finsihed
getData("url-to-get-data").done(function (result) {
checkPages(result.total_pages);
});
function getData(url) {
return $.get({
url: "url-to-get-data"
})
}
function checkPages(pagesCount) {
let doContinue = true;
let loading = false;
let i = 2;
var checker = setTimeout(()=>{
if(i > pagesCount) clearTimeout(checker);
if(!loading){
loading = true;
getData("url-to-get-data", i).done(function(result) {
var today = checkToday(result);
if (today != null) {
clearTimeout(checker);
}
i++;
loading = false;
});
}
},100);
}
function checkToday(response) {
var results = response.results;
var today = new Date();
var day = today.getDate();
var month = today.getMonth();
for (var i = 0; i < results.length; i++) {
var d = new Date(results[i].release_date);
if (d.getDate() === day && d.getMonth() === month) {
return results[i];
}
}
return null;
}
Make your ajax call synchronous or use callback functions to keep getting more data until conditions are met.

JavaScript: multiple instances wrong reference to private property

In the fiddle is a "class" I have written to manage navigation over the data model and a test which shows that multiple instances (starting from second) of this "class" are referencing something wrong.
https://jsfiddle.net/btvmnaxc/
(outputs to console)
Expected output would be
[{"name":"xx"}]
[{"name":"yy"}]
But after setting Elements via setElements, in other methods Elements is empty, strangely only after creating the second instance. I could think that setElements overwrites the reference, but why other methods keep this old reference instead of getting a new one from the var.
Could somebody explain this behavior?
P.S. I probably can think on a solution, as packing vars in a property which is an object.
function Pagination() {
var props = {Elements:[], ...}
}
P.S.S
function Pagination() {
var that = this;
var Elements = [0,1];
var Frame = [];
var FrameNumber = 0;
var EntitiesPerFrame = 25;
var FrameChangedCB = [];
this.subscribeFrameChange = function(cb) {
if (typeof cb === "function") {
FrameChangedCB.push(cb);
} else {
throw new Error("Not a function");
}
}
this.setEntitiesPerFrame = function(entities_per_frame) {
entities_per_frame = parseInt(entities_per_frame);
if (entities_per_frame > 0) {
EntitiesPerFrame = entities_per_frame;
while (!this.canDisplayFrame(FrameNumber) && FrameNumber > 0) {
FrameNumber--;
}
calculateFrame();
}
}
frameChanged = function() {
FrameChangedCB.forEach(function(cb) {
cb();
});
}
this.setElements = function(elements) {
if (Array.isArray(elements)) {
Elements = elements;
calculateFrame();
console.log("qq");
} else {
throw new Error("Can only work with arrays");
}
}
this.getStart = function() {
return FrameNumber * EntitiesPerFrame;
}
this.getEnd = function() {
var end = (FrameNumber + 1) * EntitiesPerFrame;
return end > Elements.length ? Elements.length : end;
}
this.getEntitiesPerFrame = function() {
return EntitiesPerFrame;
}
calculateFrame = function() {
var start = that.getStart();
var end = that.getEnd();
if (that.canDisplayFrame(FrameNumber)) {
Frame = Elements.slice(
start,
end
);
frameChanged();
} else {
throw new Error("Boundaries");
}
}
this.canDisplayFrame = function(nr) {
nr = parseInt(nr);
var can = false;
var start = nr * EntitiesPerFrame
var end = (nr + 1) * EntitiesPerFrame;
if (start <= Elements.length && nr >= 0) {
can = true;
}
return can;
}
this.getFrame = function() {
return Frame;
}
this.next = function() {
return this.goto(FrameNumber + 1);
}
this.prev = function() {
return this.goto(FrameNumber - 1);
}
this.goto = function(frame_nr) {
var changed = false;
if (that.canDisplayFrame(frame_nr)) {
FrameNumber = parseInt(frame_nr);
calculateFrame();
changed = true;
}
return changed;
}
this.getLength = function() {
return Elements.length;
}
}
var b = new Pagination();
var a = new Pagination();
a.setElements([{name: 'xx'}]);
b.setElements([{name: 'yy'}]);
console.log(JSON.stringify(a.getFrame()));
console.log(JSON.stringify(b.getFrame()));
This is happening because you are abusing implicit globals.
Your Pagination function contains two places where a function is assigned to an identifier without using var:
calculateFrame = function() {
var start = that.getStart();
var end = that.getEnd();
if (that.canDisplayFrame(FrameNumber)) {
Frame = Elements.slice(
start,
end
);
frameChanged();
} else {
throw new Error("Boundaries");
}
}
This will assign this function to a global variable named calculateFrame and any call to calculateFrame() will be calling whichever of those was assigned last (and therefore be using whatever scope it has access to).
To fix this, use var:
var calculateFrame = function() {
var start = that.getStart();
var end = that.getEnd();
if (that.canDisplayFrame(FrameNumber)) {
Frame = Elements.slice(
start,
end
);
frameChanged();
} else {
throw new Error("Boundaries");
}
}
Or better yet, use a named function declaration:
function calculateFrame() {
var start = that.getStart();
var end = that.getEnd();
if (that.canDisplayFrame(FrameNumber)) {
Frame = Elements.slice(
start,
end
);
frameChanged();
} else {
throw new Error("Boundaries");
}
}
After fixing the two places where you have this issue, the snippet outputs the expected result.
function Pagination() {
var that = this;
var Elements = [0, 1];
var Frame = [];
var FrameNumber = 0;
var EntitiesPerFrame = 25;
var FrameChangedCB = [];
this.subscribeFrameChange = function(cb) {
if (typeof cb === "function") {
FrameChangedCB.push(cb);
} else {
throw new Error("Not a function");
}
}
this.setEntitiesPerFrame = function(entities_per_frame) {
entities_per_frame = parseInt(entities_per_frame);
if (entities_per_frame > 0) {
EntitiesPerFrame = entities_per_frame;
while (!this.canDisplayFrame(FrameNumber) && FrameNumber > 0) {
FrameNumber--;
}
calculateFrame();
}
}
function frameChanged() {
FrameChangedCB.forEach(function(cb) {
cb();
});
}
this.setElements = function(elements) {
if (Array.isArray(elements)) {
Elements = elements;
calculateFrame();
console.log("qq");
} else {
throw new Error("Can only work with arrays");
}
}
this.getStart = function() {
return FrameNumber * EntitiesPerFrame;
}
this.getEnd = function() {
var end = (FrameNumber + 1) * EntitiesPerFrame;
return end > Elements.length ? Elements.length : end;
}
this.getEntitiesPerFrame = function() {
return EntitiesPerFrame;
}
function calculateFrame() {
var start = that.getStart();
var end = that.getEnd();
if (that.canDisplayFrame(FrameNumber)) {
Frame = Elements.slice(
start,
end
);
frameChanged();
} else {
throw new Error("Boundaries");
}
}
this.canDisplayFrame = function(nr) {
nr = parseInt(nr);
var can = false;
var start = nr * EntitiesPerFrame
var end = (nr + 1) * EntitiesPerFrame;
if (start <= Elements.length && nr >= 0) {
can = true;
}
return can;
}
this.getFrame = function() {
return Frame;
}
this.next = function() {
return this.goto(FrameNumber + 1);
}
this.prev = function() {
return this.goto(FrameNumber - 1);
}
this.goto = function(frame_nr) {
var changed = false;
if (that.canDisplayFrame(frame_nr)) {
FrameNumber = parseInt(frame_nr);
calculateFrame();
changed = true;
}
return changed;
}
this.getLength = function() {
return Elements.length;
}
}
var b = new Pagination();
var a = new Pagination();
a.setElements([{
name: 'xx'
}]);
b.setElements([{
name: 'yy'
}]);
console.log(a.getFrame());
console.log(b.getFrame());

how can i return the count from a function

hi iam new to javascript, i am trying to return a count from the function my code is like below
my code
function moredbCount(contentMoreArray2, ArrHeading) {
var sampleArr = [];
for (var a = 0; a < contentMoreArray2.length; a++) {
if (ArrHeading !== 'More') {
var fullHeading = ArrHeading + '-' + contentMoreArray2[a].name;
} else {
fullHeading = contentMoreArray2[a].name;
}
sampleArr.push(fullHeading);
}
var sampleCount = sampleHeadingCount(sampleArr);
return sampleCount.then(function (resultantCount) {
return resultantCount; //Here iam getting some count like 10 and returning it to the function;
});
}
var contentCount;
var totalCount = moredbCount(contentMoreArray2, ArrHeading);
totalCount.then(function (resultantTotalCount) {
return contentCount = resultantTotalCount
});
// Here i want to use contentCount 10, But iam getting undefined
Thanks In advance
return contentCount = resultantTotalCount won't return the count, but rather the response of assignment. In contentCount = resultantTotalCount, you are basically assigning the value of resultantTotalCount to contentCount.
You should use
function moredbCount(contentMoreArray2, ArrHeading) {
var sampleArr = [];
for (var a = 0; a < contentMoreArray2.length; a++) {
if (ArrHeading !== 'More') {
var fullHeading = ArrHeading + '-' + contentMoreArray2[a].name;
} else {
fullHeading = contentMoreArray2[a].name;
}
sampleArr.push(fullHeading);
}
var sampleCount = sampleHeadingCount(sampleArr);
return sampleCount.then(function (resultantCount) {
return resultantCount; //Here iam getting some count like 10 and returning it to the function;
});
}
var contentCount;
var totalCount = moredbCount(contentMoreArray2, ArrHeading);
totalCount.then(function (resultantTotalCount) {
return resultantTotalCount
});

Specified argument was out of the range of valid values. Parameter name: index

I have the following javascript code which must load a termset from sharepoint managed metadata store.
The code was working fine until monday and suddenly stopped working with the error on the title.
I changed the contents of the executequeryasync with just a console.log and I still have the error.
I already debugged line by line the execGetTermIds, and none of the lines there throwed the exception
function GetTermsDataFromTaxonomy(){
//Current Context
var context = SP.ClientContext.get_current();
//Current Taxonomy Session
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
//Term Stores
var termStores = taxSession.get_termStores();
//Name of the Term Store from which to get the Terms.
var termStore = termStores.getByName("Taxonomy_kl5tZjInn7STsFTzIE7n3Q==");
//GUID of Term Set from which to get the Terms.
var termSet = termStore.getTermSet("31da4bc1-6429-499a-9d5e-be5e18b13c87");
var terms = termSet.getAllTerms();
var list;
var p = execGetTermIDs();
p.done(function(result) {
context.load(terms);
context.executeQueryAsync(function(){
console.log("hola");
},
function(sender,args){
console.log(args.get_message());
});
});
p.fail(function(result) {
// result is a string because that is what we passed to reject()!
var error = result;
console.log(error);
});
}
function sortTermsFromTree (tree) {
if (tree.children.length && tree.term.get_customSortOrder) {
var sortOrder = null;
if (tree.term.get_customSortOrder()) {
sortOrder = tree.term.get_customSortOrder();
}
// If not null, the custom sort order is a string of GUIDs, delimited by a :
if (sortOrder) {
sortOrder = sortOrder.split(':');
tree.children.sort(function (a, b) {
var indexA = sortOrder.indexOf(a.guid);
var indexB = sortOrder.indexOf(b.guid);
if (indexA > indexB) {
return 1;
} else if (indexA < indexB) {
return -1;
}
return 0;
});
}
// If null, terms are just sorted alphabetically
else {
tree.children.sort(function (a, b) {
if (a.title > b.title) {
return 1;
} else if (a.title < b.title) {
return -1;
}
return 0;
});
}
}
for (var i = 0; i < tree.children.length; i++) {
tree.children[i] = sortTermsFromTree(tree.children[i]);
}
return tree;
}
function execGetTermIDs(){
var d = $.Deferred();
var q = "<View><Query><Where></Where></Query></View>";
var context = new SP.ClientContext(siteUrl);
var oList = context.get_web().get_lists().getByTitle('TaxonomyHiddenList');
var camlQuery = SP.CamlQuery.createAllItemsQuery();
var collTermListItem = oList.getItems(camlQuery);
context.load(collTermListItem);
var o = {d: d, collTermListItem:collTermListItem};
context.executeQueryAsync(
Function.createDelegate(o, getTermIDsComplete),
Function.createDelegate(o, failCallback)
);
return d.promise();
}
function getTermIDsComplete()
{
var listItemEnumerator = this.collTermListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
termIDs[oListItem.get_fieldValues().Title] = oListItem.get_id();
}
this.d.resolve(termIDs);
}
function failCallback() {
this.d.reject("something bad happened");
}
omg, I found the error, and I cant find an explanation on this, hopefully somebody at Microsoft can tell me.
this line:
var termStore = termStores.getByName("Taxonomy_kl5tZjInn7STsFTzIE7n3Q==");
We noticed the name is now different, it has a different guid, but we as customers cant change that name, so the only reason is Microsoft changed it for us because it was working on monday.
Update: I changed that line with:
termStore = session.getDefaultSiteCollectionTermStore();
to avoid that it happens in the future.

update list property in listTicker function every X seconds

I am attempting to create a ticker that fades in and out the objects in an array using the jQuery fadeIn/fadeOut function. I referenced someone else's code and was able to get it working for the most part. What I would like to do now is get the list property of listTicker to update every X number of seconds and move to the next array. I assume I must use a for loop somehow but I just cant seem to figure out how to implement it.
Below is what I was able to get working:
var listTicker = function(options) {
var defaults = {
list: [],
startIndex:0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value= options.list[index];
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
};
var textlist = new Array("Saab", "Volvo", "BMW");
var textlist2 = new Array("Dell", "HP", "Toshiba");
var textlist3 = new Array("John", "Dave", "Greg");
var currentlist = new Array(textlist, textlist2, textlist3);
$(function() {
listTicker({
list: currentlist[0] ,
startIndex:0,
trickerPanel: $('#expression'),
interval: 3 * 1000,
});
});
Not 100% happy with the organization/separation of this code, but it achieves the objective:
http://jsfiddle.net/49Y8s/
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
var nextItemIndex = (index+1) < currentList.length ? (index+1) : 0;
var nextListIndex = (function(){
var val = listIndex;
if(nextItemIndex==0){
val = listIndex+1;
}
if(val >= options.lists.length){
val = 0;
}
return val;
})();
setTimeout(function() {
listTickerInner(nextListIndex,nextItemIndex);
}, options.interval);
});

Categories

Resources