node.js call some methods using OOP way - node.js

I need to call some methods using OOP way e.g. this.method() but i get some errors, this my BingoCard.js help please.
var _ = require('underscore');
// ------------------------------------ ---------
// Constructor
// ---------------------------------------------
function BingoCard() {
if(false === (this instanceof BingoCard)) {
return new BingoCard();
}
this.firstRowSchema = [];
this.secondRowSchema = [];
this.thirdRowSchema = [];
this.firstRow = [];
this.secondRow = [];
this.thirdRow = [];
this.patterns = [
{
"1" : ['x','0','x','0','x','0','x','x','0'],
"2" : ['0','x','0','x','0','x','0','x','x'],
"3" : ['x','0','x','0','x','0','x','0','x']
},
{
"1" : ['x','x','0','x','0','x','0','x','0'],
"2" : ['0','x','x','0','x','0','x','0','x'],
"3" : ['x','0','x','x','0','x','0','x','0']
}
];
this.columns = {
"1": [1,2,3,4,5,6,7,8,9],
"2": [10,11,12,13,14,15,16,17,18,19],
"3": [20,21,22,23,24,25,26,27,28,29],
"4": [30,31,32,33,34,35,36,37,38,39],
"5": [40,41,42,43,44,45,46,47,48,49],
"6": [50,51,52,53,54,55,56,57,58,59],
"7": [60,61,62,63,64,65,66,67,68,69],
"8": [70,71,72,73,74,75,76,77,78,79],
"9": [80,81,82,83,84,85,86,87,88,89,90]
};
// Use Underscore to bind all of our methods
// to the proper context
_.bindAll(this);
}
// ---------------------------------------------
// Methods
// ---------------------------------------------
BingoCard.prototype = {
resetSchemas: function () {
this.firstRowSchema = [];
this.secondRowSchema = [];
this.thirdRowSchema = [];
},
generateRows: function () {
this.cardID = _.random(8888, 999999999); // generate a Card ID.
var pattern = _.shuffle(this.patterns);
this.firstRow = pattern[0][1];
this.secondRow = pattern[0][2];
this.thirdRow = pattern[0][3];
},
createColNumber: function (col,equalNumbers) {
console.log(this.patterns);
var colNumber = this.getColNumber(col);
if(typeof equalNumbers !== 'undefined' && equalNumbers.length > 0){
equalNumbers.forEach(function(val,key){
while(colNumber == val){
colNumber = this.getColNumber(col);
}
});
}
return colNumber;
},
getColNumber: function () {
var items = _.shuffle(this.columns[col]);
return items[0];
},
generateFirstRow: function () {
var col = 0;
this.firstRow.forEach(function(val,key){
col++;
if(val == 'x'){
this.firstRowSchema[key] = this.createColNumber(col);
} else {
this.firstRowSchema[key] = 0;
}
});
return this.firstRowSchema;
}
};
// ---------------------------------------------
// Export
// ---------------------------------------------
module.exports = BingoCard;
I call the bingocard class in app.js and this is my app.js contents.
var BingoCard = require('./bingocard');
var bingocard = new BingoCard();
bingocard.generateRows();
console.log(bingocard.generateFirstRow());
When in run "node app" from console i get this error:
TypeError: Object #<Object> has no method 'createColNumber'
at /var/www/bingo/bingocard.js:10:48
but createColNumber method defined .. :(?

On the fourth row in the code below, this is not referring to the prototype. this is pointing to something else.
this.firstRow.forEach(function(val,key){
col++;
if(val == 'x'){
this.firstRowSchema[key] = this.createColNumber(col);
} else {
this.firstRowSchema[key] = 0;
}
});
You can solve this by switching out this with self. and assign this to self in the beginning of the method definition. Like this:
generateFirstRow: function () {
var col = 0,
self = this;
this.firstRow.forEach(function(val,key){
col++;
if(val == 'x'){
self.firstRowSchema[key] = self.createColNumber(col);
} else {
self.firstRowSchema[key] = 0;
}
});
return this.firstRowSchema;
}

Related

Other product variant is disabled and I can not select it for 2 products (JS)

I am a coding beginner and I am building a store. My problem is that I have a product in different fabrics. Now I can only select one fabric type and the other is disabled and I can not select no matter what I do. Perfect would be if I select the fabric type, the associated products are displayed.
That what i mean
/*============================================================================
Dynamic variant availability
- To disable, set dynamicVariantsEnable to false in theme.liquid
==============================================================================*/
setCurrentVariantAvailability: function(variant) {
var valuesToEnable = {
option1: [],
option2: [],
option3: []
};
// Disable all options to start
this.disableVariantGroup($(selectors.formContainer, this.$container).find('.variant-input-wrap'));
// Combine all available variants
var availableVariants = this.variantsObject.filter(function(el) {
if (variant.id === el.id) {
return false;
}
// Option 1
if (variant.option2 === el.option2 && variant.option3 === el.option3) {
return true;
}
// Option 2
if (variant.option1 === el.option1 && variant.option3 === el.option3) {
return true;
}
// Option 3
if (variant.option1 === el.option1 && variant.option2 === el.option2) {
return true;
}
});
// IE11 can't handle shortform of {variant} so extra step is needed
var variantObject = {
variant: variant
};
availableVariants = Object.assign({}, variantObject, availableVariants);
// Loop through each available variant to gather variant values
for (var property in availableVariants) {
if (availableVariants.hasOwnProperty(property)) {
var item = availableVariants[property];
var option1 = item.option1;
var option2 = item.option2;
var option3 = item.option3;
if (option1) {
if (valuesToEnable.option1.indexOf(option1) === -1) {
valuesToEnable.option1.push(option1);
}
}
if (option2) {
if (valuesToEnable.option2.indexOf(option2) === -1) {
valuesToEnable.option2.push(option2);
}
}
if (option3) {
if (valuesToEnable.option3.indexOf(option3) === -1) {
valuesToEnable.option3.push(option3);
}
}
}
}
// Have values to enable, separated by option index
if (valuesToEnable.option1.length) {
this.enableVariantOptionByValue(valuesToEnable.option1, 'option1');
}
if (valuesToEnable.option2.length) {
this.enableVariantOptionByValue(valuesToEnable.option2, 'option2');
}
if (valuesToEnable.option3.length) {
this.enableVariantOptionByValue(valuesToEnable.option3, 'option3');
}
},
updateVariantAvailability: function(evt, value, index) {
if (value && index) {
var newVal = value;
var optionIndex = index;
} else {
var $el = $(evt.currentTarget);
var newVal = $el.val() ? $el.val() : evt.currentTarget.value;
var optionIndex = $el.data('index');
}
var variants = this.variantsObject.filter(function(el) {
return el[optionIndex] === newVal;
});
// Disable all buttons/dropdown options that aren't the current index
$(selectors.formContainer, this.$container).find('.variant-input-wrap').each(function(index, el) {
var $group = $(el);
var currentOptionIndex = $group.data('index');
if (currentOptionIndex !== optionIndex) {
// Disable all options as a starting point
this.disableVariantGroup($group);
// Loop through legit available options and enable
for (var i = 0; i < variants.length; i++) {
this.enableVariantOption($group, variants[i][currentOptionIndex]);
}
}
}.bind(this));
},
disableVariantGroup: function($group) {
if (this.settings.variantType === 'dropdown') {
$group.find('option').prop('disabled', true)
} else {
$group.find('input').prop('disabled', true);
$group.find('label').toggleClass('disabled', true);
}
},
enableVariantOptionByValue: function(array, index) {
var $group = $(selectors.formContainer, this.$container).find('.variant-input-wrap[data-index="'+ index +'"]');
for (var i = 0; i < array.length; i++) {
this.enableVariantOption($group, array[i]);
}
},
enableVariantOption: function($group, value) {
// Selecting by value so escape it
value = value.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g,'\\$1');
if (this.settings.variantType === 'dropdown') {
$group.find('option[value="'+ value +'"]').prop('disabled', false);
} else {
var $buttonGroup = $group.find('.variant-input[data-value="'+ value +'"]');
$buttonGroup.find('input').prop('disabled', false);
$buttonGroup.find('label').toggleClass('disabled', false);
}
},
Have already tried various things, but not come to the desired result, even disabling the function ensures that everything is displayed and also clickable.
I hope you can help me.
Best Regards

Why await is not blocking the loop but executing before one task gets executed in nodejs?

I am trying to achieve the objective of performing tasks one after another means I want to wait for the one task until it gets completed and then following with the next task should execute. For that, I am using the async/await appropriately in order starting from loop to the functions which are being called.
But what I see is the forEach loop is still executing before the current task finishes execution.
So this is my flow of code with the series of functions which are being called one inside other as well and I want the execution on async/await basis, but the loop is executing before happening that.
var lines = [
"GET_RELATIONSHIP Jnki Maternal-Uncle",
"GET_RELATIONSHIP Jnki Paternal-Uncle",
"GET_RELATIONSHIP Yodhan Maternal-Uncle",
"GET_RELATIONSHIP Laki Paternal-Uncle"
]
for await (const line of lines) {
var str = line.trim().split(' ');
if (str[0] == 'ADD_CHILD') {
await addChild(family.familyHead);
} else if (str[0] == 'GET_RELATIONSHIP') {
var inputName = str[1];
var inputRelationship = str[2];
console.log("str = " + inputName, inputRelationship);
var result = await getRelationship(family.familyHead);
}
}
const getRelationship = async (person) => {
if (inputRelationship == "Paternal-Uncle" || inputRelationship == "Maternal-Uncle" || inputRelationship == "Paternal-Aunt" || inputRelationship == "Maternal-Aunt")
await filterAllPaternalAndMaternalFromFamily(person);
if (person.children) {
person.children.forEach(getRelationship)
}
return true;
}
async function filterAllPaternalAndMaternalFromFamily(person) {
if (person.name == inputName) {
var takeAllPaternalOrMaternal = await getAllPaternalOrMaternal(person);
l = takeAllPaternalOrMaternal.length;
if (inputRelationship == "Paternal-Uncle" || inputRelationship == "Paternal-Aunt")
takeAllPaternalOrMaternal = await removePerson(takeAllPaternalOrMaternal, person);
if (inputRelationship == "Maternal-Uncle" || inputRelationship == "Maternal-Aunt")
takeAllPaternalOrMaternal = await removePerson(takeAllPaternalOrMaternal, person);
const male = await filterMale(takeAllPaternalOrMaternal);
const female = await filterFemale(takeAllPaternalOrMaternal);
if (l == takeAllPaternalOrMaternal.length)
console.log("None");
else if (inputRelationship == "Maternal-Uncle" || inputRelationship == "Paternal-Uncle") {
await printPerson(male);
} else if (inputRelationship == "Maternal-Aunt" || inputRelationship == "Paternal-Aunt") {
await printPerson(female);
}
} else if (person.wife == inputName || person.husband == inputName)
console.log('None');
}
async function getAllPaternalOrMaternal(person) {
var getUncleAunt = [];
const display2 = async (person2) => {
if (person2.father == person.grandfather && person2.mother == person.grandmother)
getUncleAunt.push(person2);
if (person2.children)
person2.children.forEach(display2);
}
await display2(family.familyHead);
return getUncleAunt;
}
async function filterMale(males) {
const male = await males.filter(uncle => uncle.gender === 'Male');
return male;
}
async function filterFemale(females) {
const female = await females.filter(aunt => aunt.gender === 'Female');
return female;
}
async function printPerson(person) {
var str = "";
if (person.length) {
person.forEach(async (item) => {
str += item.name + " ";
})
console.log(str);
} else
console.log('None');
}
This is the output I am getting which shows that the for loop has been executed even before the first whole sequence of tasks been completed.
str = Jnki Maternal-Uncle
str = Jnki Paternal-Uncle
str = Yodhan Maternal-Uncle
None
str = Laki Paternal-Uncle
Chit Ish Vich Aras
Vritha
None
None

Knockout-2.2.0, subscribe get value before change AND new value

jsfiddle link: http://jsfiddle.net/T8ee7/
When I call Knockout's subscribe method is there a way I can get both the previous and new value? Right now, I can only call get these values separately.
I want to trigger some code if the old and new value are different.
I suppose I could do the following, but it can get messy...
(http://jsfiddle.net/MV3fN/)
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
this.pageNumber = ko.observable(pageNumber || 1);
this.numberOfPages = ko.observable(1);
this.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
};
var _pagedRequest = new sv.PagedRequest();
var oldValue;
_pagedRequest.pageNumber.subscribe(function (previousValue) {
console.log("old: " + previousValue);
oldValue = previousValue;
}, _pagedRequest, "beforeChange");
_pagedRequest.pageNumber.subscribe(function (newValue) {
console.log("new: " + newValue);
if (oldValue != newValue) {
console.log("value changed!");
}
});
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
​
I prefer using an observable extender.
http://jsfiddle.net/neonms92/xybGG/
Extender:
ko.extenders.withPrevious = function (target) {
// Define new properties for previous value and whether it's changed
target.previous = ko.observable();
target.changed = ko.computed(function () { return target() !== target.previous(); });
// Subscribe to observable to update previous, before change.
target.subscribe(function (v) {
target.previous(v);
}, null, 'beforeChange');
// Return modified observable
return target;
}
Example Usage:
// Define observable using 'withPrevious' extension
self.hours = ko.observable().extend({ withPrevious: 1 });
// Subscribe to observable like normal
self.hours.subscribe(function () {
if (!self.hours.changed()) return; // Cancel if value hasn't changed
print('Hours changed from ' + self.hours.previous() + ' to ' + self.hours());
});
This seems to work for me
ko.observable.fn.beforeAndAfterSubscribe = function (callback, target) {
var _oldValue;
this.subscribe(function (oldValue) {
_oldValue = oldValue;
}, null, 'beforeChange');
this.subscribe(function (newValue) {
callback.call(target, _oldValue, newValue);
});
};
See more at: http://ideone.com/NPpNcB#sthash.wJn57567.dpuf
http://jsfiddle.net/MV3fN/3/
var sv = sv || {};
sv.PagedRequest = function (pageNumber, pageSize) {
var self = this;
self.pageNumber = ko.observable(pageNumber || 1);
self.numberOfPages = ko.observable(1);
self.pageSize = ko.observable(pageSize || sv.DefaultPageSize);
self.pageNumber.subscribe(function (previousValue) {
console.log(previousValue);
console.log(self.pageNumber.arguments[0]);
if (previousValue != _pagedRequest.pageNumber.arguments[0]) {
console.log('value changed');
}
else {
//This won't get executed because KO doesn't
//call the function if the value doesn't change
console.log('not changed');
}
}, _pagedRequest, "beforeChange");
};
var _pagedRequest = new sv.PagedRequest();
_pagedRequest.pageNumber(10);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(20);
_pagedRequest.pageNumber(5);
I don't know if you're really supposed to use arguments[0], but it seems to work.
You could also set up your own method to accomplish this in a much cleaner way:
http://jsfiddle.net/PXKgr/2/
...
self.setPageNumber = function(page) {
console.log(self.pageNumber());
console.log(page);
if (self.pageNumber() != page) {
console.log('value changed');
}
else {
console.log('not changed');
}
self.pageNumber(page);
};
...
_pagedRequest.setPageNumber(10);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(20);
_pagedRequest.setPageNumber(5);

Rickshaw.Graph.RangeSlider TypeError: $(element).slider is not a function

I have this error:
TypeError: $(element).slider is not a function
with the following script:
Rickshaw.namespace('Rickshaw.Graph.RangeSlider');
Rickshaw.Graph.RangeSlider = function(args) {
var element = this.element = args.element;
var graph = this.graph = args.graph;
$( function() {
$(element).slider( {
range: true,
min: graph.dataDomain()[0],
max: graph.dataDomain()[1],
values: [
graph.dataDomain()[0],
graph.dataDomain()[1]
],
slide: function( event, ui ) {
graph.window.xMin = ui.values[0];
graph.window.xMax = ui.values[1];
graph.update();
// if we're at an extreme, stick there
if (graph.dataDomain()[0] == ui.values[0]) {
graph.window.xMin = undefined;
}
if (graph.dataDomain()[1] == ui.values[1]) {
graph.window.xMax = undefined;
}
}
} );
} );
$(element)[0].style.width = graph.width + 'px';
graph.onUpdate( function() {
var values = $(element).slider('option', 'values');
$(element).slider('option', 'min', graph.dataDomain()[0]);
$(element).slider('option', 'max', graph.dataDomain()[1]);
if (graph.window.xMin == undefined) {
values[0] = graph.dataDomain()[0];
}
if (graph.window.xMax == undefined) {
values[1] = graph.dataDomain()[1];
}
$(element).slider('option', 'values', values);
} );
};
From the following page:
https://github.com/shutterstock/rickshaw/blob/master/src/js/Rickshaw.Graph.RangeSlider.js
The javascript debugger show me this line: slide: function( event, ui ) {
Can you show me a way to resolve my problem. Thanks you!
You should import jqueryui before using the slider.
http://jqueryui.com/slider/

JQuery Dynatree - search node by name

I would like to start using Dynatree on my page, however I will probably need searching my tree by name. Do you know maybe how to do this?
I needed to have not only matching nodes, but also the whole paths to these nodes. I wrote this functionality and it works for me.
Modifications for library:
var clear = true;
DynaTreeNode.prototype.search = function(pattern){
if(pattern.length < 1 && !clear){
clear = true;
this.visit(function(node){
node.expand(true);
node.li.hidden = false;
node.expand(false);
});
} else if (pattern.length >= 1) {
clear = false;
this.visit(function(node){
node.expand(true);
node.li.hidden = false;
});
for (var i = 0; i < this.childList.length; i++){
var hide = {hide: false};
this.childList[i]._searchNode(pattern, hide);
}
}
},
DynaTreeNode.prototype._searchNode = function(pattern, hide){
if (this.childList){
// parent node
var hideNode = true;
for(var i = 0; i < this.childList.length; i++){
var hideChild = {hide: false};
this.childList[i]._searchNode(pattern, hideChild);
hideNode = hideNode && hideChild.hide;
}
if(hideNode && !this._isRightWithPattern(pattern)){
this._hideNode();
hide.hide = true;
} else {
hide.hide = false;
}
} else {
// leaf
if (!this._isRightWithPattern(pattern)){
this._hideNode();
hide.hide = true;
} else {
hide.hide = false;
}
}
},
DynaTreeNode.prototype._isRightWithPattern = function(pattern){
if((this.data.title.toLowerCase()).indexOf(pattern.toLowerCase()) >= 0){
return true;
}
return false;
},
DynaTreeNode.prototype._hideNode = function(){
if(this.li) {
this.li.hidden = true;
}
}
Use:
$("tree").dynatree("getRoot").search(pattern);
There is currently no search function, but you could use something like this (not tested)
var match = null;
tree.visit(function(node){
if(node.data.title === "foo"){
match = node;
return false; // stop traversal (if we are only interested in first match)
}
});
alert("Found " + match);
I've done it this way
<style>
span.occurance a.dynatree-title{background-color:#3AFF22;}
</style>
DynaTreeNode.prototype.find = function (needle) {
needle = (needle || '');
if (needle.length >= 1) {
var occurs = [];
this.visit(function (node) {
$(node.span).removeClass('occurance'); //remove pervious findings
if (node.data.title.indexOf(needle) != -1) {
occurs.push(node);
node._expandPath();
}
});
for (indx in occurs) { // mark findings
$(occurs[indx].span).addClass('occurance');
}
} else {
$('span.dynatree-node.occurance').removeClass('occurance');
}
},
DynaTreeNode.prototype._expandPath = function () {
var path = [],
node = this;
while (node = node.getParent()) {
path.push(node);
}
for (indx in path) {
path[indx].expand(true)
}
}
usage:
[your selector].dynatree("getRoot").find('needle');
Thanks to #mar10 i made a small, simple function to search a node with title:
// If searchFrom is null, root is used
function seachFolderNodeWithName(name, searchFrom) {
if (name == null) {
return undefined;
}
if (searchFrom == null) {
searchFrom = jQuery('#tree').dynatree("getRoot");
}
var match = undefined;
searchFrom.visit(function (node) {
if (node.data.title === name) {
match = node;
return false; // Break if found
}
});
return match;
};

Resources