AngularJS setting up a function to prevent duplication - javascript

At the moment I have duplicate code where I have the following examples:
if ($scope.user.window.title == 'true'){
if (this.title){
title = '<h2>'+this.title+'<h2>';
} else {
title = '';
}
} else {
title = '';
}
if ($scope.user.window.football == 'true'){
if (this.football){
football = '<p>'+this.football+'<p>';
} else {
football = '';
}
} else {
football = '';
}
I have tried the following but it doesn't work, it says that the $scope.user.window.football and $scope.user.window.title don't exist. I think it is down to the below function sending the value through as a string for my $scope.
function CheckWindow(element,tag) {
console.log(element);
if ($scope.user.window.element == 'true'){
if (this.element){
element = '<'+tag+'>'+this.element+'</'+tag+'>';
} else {
element = '';
}
} else {
element = '';
}
}
Usage
CheckWindow('title','h2')
CheckWindow('football','p')

$scope.user.window.element tries to access the property named element of $scope.user.window. You need $scope.user.window[element] instead.
this refers to the created function's scope. You could pass a new argument that for example.
that.element will have to be rewritten to that[element], for the same reason as in #1.
You can't assign a new value to a function's parameter (well, you can, but it won't be accessible outside the function's scope). Better return the value.
So:
function CheckWindow(that, element, tag) {
if ($scope.user.window[element] && that[element]){
return '<'+tag+'>'+that[element]+'</'+tag+'>';
}
return '';
}
title = CheckWindow(this, 'title', 'h2');
football = CheckWindow(this, 'football', 'p');

try
$scope.user.window[element]
When you need to reference a property as a sttring, you must use bracket notation.
Also, I doubt that 'this' will reference what you want. You may need to angular.bind this to the method.

Related

Target Variable from Variable Value

I am trying to target a variable from a variable value that has been passed in from function arguments. I don't know how to do this. P.S. the variables at the top are also used by other functions
let cardvalue0 = false;
let cardvalue1 = false;
function myfunction (card) {
if (card === false) {
card = true;
//ether cardValue 0 or 1 should now be true
return card;
}
}
// exturnal html
<button onclick="myfunction("cardValue0")"></button>
<button onclick="myfunction("cardValue1")"></button>
new try by me
//define cards
let card0State = false;
let card1State = false;
//toggle card status (read or not)
function cardToggle(card) {
console.log(card);
card = !card
console.log(card);
return card;
}
// external html
<button onclick="myfunction(cardValue0)"></button>
<button onclick="myfunction(cardValue1)"></button>
target a variable from a variable value? If I understood you right you want to access a variable cardvalue0 inside the function myfunction.
You can access it using, eval(card) but definitely not advised to do
function myfunction (card) {
if (eval(card) === false) { //this will work
card = true; //however you cannot change the original value
return card;
}
}
You can get this by using objects
let cardDict = { "cardvalue0" : false,
"cardvalue1" : false}
function myfunction (card) {
if (cardDict[card] === false) {
cardDict[card] = true;
return cardDict[card];
}
}
Would it be possible to store card0State and card1State in an object instead? Then you could reference them as keys to the object instead.
const cardvalues = {};
cardvalues.cardvalue0 = false;
cardvalues.cardvalue1 = false;
function myfunction (cardNumber) {
if (cardvalues[cardNumber] === false) {
cardvalues[cardNumber] = true;
//ether cardValue 0 or 1 should now be true
return cardvalues[cardNumber];
}
}
// exturnal html
<button onclick="myfunction('cardvalue0')"></button>
<button onclick="myfunction('cardvalue1')"></button>
Then you aren't declaring a new variable in the function scope and you are directly altering the key values on the object. This is usually better than a variable variable pattern.
"Variable" variables in Javascript?
the simpler would be moving the original variable (cardvalue0 and cardvalue1) in a Map or an object, so you could have :
cards = {
cardvalue0 : false,
cardvalue1 : false
}
function foo(cardName) {
cards[cardName] = !cards[cardName];
return cards[cardName]
}
}
if you can not move cardvalue0 and cardvalue1, you could simply hardcode them, but it will become ugly really fast.
function foo(cardName) {
if(cardName === "cardvalue0") {
cardValue0 = !cardValue0;
return cardValue0;
} else if(cardName === "cardvalue1")
cardValue1 = !cardValue1;
return !cardValue1;
}
eval would be the only way to get a variable from a string representation, but is not a good idea.

Pass property with dot notation(sometimes) to function

I've got a function that is looking through a specified collection and highlighting the checkboxes for the items that are present in that collection.
function highlightFiltersPresentInTransactions(collection, collectionproperty, child) {
var found = false;
angular.forEach(collection, function (filterType) {
if (scope.vm.transactions) {
found = scope.vm.transactions.filter(function (obj) {
if (child) {
return obj[collectionproperty][child] === filterType.name;
} else {
return obj[collectionproperty] === filterType.name;
}
});
}
if (found) {
filterType['has-transaction'] = (found.length > 0);
}
});
}
I'm able to call it and it correctly works like this
highlightFiltersPresentInTransactions(scope.filterTypes, 'target', 'type');
highlightFiltersPresentInTransactions(scope.actionTypes, 'transactionType');
What I would like to be able to avoid is the check whether there is a child element that needs to be checked.
I attempted to call the function as such:
highlightFiltersPresentInTransactions(scope.filterTypes, 'target.type');
Since this is a string it doesn't find the property. I also tried creating a blank target object then passing target.type without the quotes.
How can I dynamically pass in a property that might or might not have a child property to my function?
How about passing a function reference to the function?
highlightFiltersPresentInTransactions(scope.filterTypes, function(o) { return o.target.type; });
highlightFiltersPresentInTransactions(scope.filterTypes, function(o) { return o.transactionType; });
This can be implemented pretty easily:
function highlightFiltersPresentInTransactions(collection, readFn) {
var found = false;
angular.forEach(collection, function (filterType) {
if (scope.vm.transactions) {
found = scope.vm.transactions.filter(function (obj) {
return readFn(obj) === filterType.name;
});
}
if (found) {
filterType['has-transaction'] = (found.length > 0);
}
});
}
If you don't want to do that, one way or another you'll have to split your string target.type into separate properties, and do it your existing way (just without the explicit parameter for child).

storing a value in a variable in conjunction with if

I'm trying to create a talk page link that changes based on what namespace you might be in. For instance if you're in mainspace you'll be directed to Talk: if in category to Category_talk:. I have this so far:
var namespace = if (wgNamespaceNumber == '0') {
return ('Talk');
} else {
return (mw.config.get( 'wgCanonicalNamespace' ) + '_talk');
}
But it's just returning a syntax error, unexpected token if. I'm guessing you can't use if in this way?
return is for passing a value or object out of a function, not blocks like if/else.
var namespace;
if (wgNamespaceNumber == '0') {
namespace = 'Talk';
} else {
namespace = mw.config.get( 'wgCanonicalNamespace' ) + '_talk';
}
You guessed right. You can't assign an IF like that.
Change your code into
var namespace = null;
if (wgNamespaceNumber == '0') {
namespace = 'Talk';
} else {
namespace = (mw.config.get( 'wgCanonicalNamespace' ) + '_talk');
}
And it'll work.
You don't need to return anything. You can just set the value of the variable based on the condition. The function will however need to return a value.
var namespace = (wgNamespaceNumber == '0')
? 'Talk'
: mw.config.get( 'wgCanonicalNamespace' );
The condition above is called a ternary (MDN explains it better)

how to create a function to set or get style property value?

i write a function want to set or get style property value:
function $(ID){return document.getElementById(ID);}
Object.prototype.css=function(style,value){
if(value==undefined){
return eval("this.style."+style);
}
else{
if(isNaN(value)){
return eval("this.style."+style+"=\""+value+"\"");
}
else{
return eval("this.style."+style+"="+value);
}
}
}
function ad(){
$("ad_ol").css("top","-170px");
}
it can work well in FireFox 、 Chrome and IE9,but not work in IE7 and IE8,error message is:Object does not support the "css" property or method
who can help me? is the "this" problem? is have better function can do this?
No need for eval, and there are other flaws in you code.
Try using something like:
function css(prop,value){
value = value || '';
if(prop) {
this.style[prop] = value;
return this.style[prop];
}
return true;
}
function $(ID){
var element = document.getElementById(ID || 'nodId');
if(element) {
element.css = css; // create css method for this element
}
return element; // Note: element is null if no ID was provided
}
$("ad_ol").css("top","-170px"); //=> should work now

Defining prototype property for JavaScript for XML prototype functions

I am using custom javascript functions provided at this link (http://km0.la/js/mozXPath/) to implement particular XML functionality in FireFox.
Here is the code:
// mozXPath
// Code licensed under Creative Commons Attribution-ShareAlike License
// http://creativecommons.org/licenses/by-sa/2.5/
if( document.implementation.hasFeature("XPath", "3.0") ) {
if( typeof XMLDocument == "undefined" ) { XMLDocument = Document; }
XMLDocument.prototype.selectNodes = function(cXPathString, xNode) {
if( !xNode ) { xNode = this; }
var oNSResolver = this.createNSResolver(this.documentElement);
var aItems = this.evaluate(cXPathString, xNode, oNSResolver,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var aResult = [];
for( var i = 0; i < aItems.snapshotLength; i++) {
aResult[i] = aItems.snapshotItem(i);
}
return aResult;
}
XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode) {
if( !xNode ) { xNode = this; }
var xItems = this.selectNodes(cXPathString, xNode);
if( xItems.length > 0 ){ return xItems[0]; }
else{ return null; }
}
Element.prototype.selectNodes = function(cXPathString) {
if(this.ownerDocument.selectNodes) {
return this.ownerDocument.selectNodes(cXPathString, this);
}
else { throw "For XML Elements Only"; }
}
Element.prototype.selectSingleNode = function(cXPathString) {
if(this.ownerDocument.selectSingleNode) {
return this.ownerDocument.selectSingleNode(cXPathString, this);
}
else { throw "For XML Elements Only"; }
}
}
Assuming the XML object has been defined and loaded with XML content, here is an example of how one would access a an XML tag named "cd_rank":
var cd_rank_XMLObj = XMLObj.selectSingleNode("cd_rank");
What I want to do is add the property "nodeTypedValue" to the selectSingleNode() function, but I'm not sure how to do this. In the Element.prototype.selectSingleNode function, I tried adding:
this.prototype.nodeTypedValue = this.textContent;
However, it's giving me an error saying it's undefined. I even tried adding it outside of the function, just to dumb it down and get the concept, and it also says it's undefined:
var XMLObj.selectSingleNode.prototype.nodeTypedValue = XMLObj.textContent;
alert(XMLObj.selectSingleNode("cd_rank").nodeTypedValue);
Essentially what I'm trying to do, I suppose, is add a prototype property to a prototype function. But I need some help with this. How can i add "nodeTypedValue" such that I write "XMLObj.selectSingleNode(Path).nodeTypedValue"?
Okay, I think I figured out how to add it inside the function, probably due more to luck than logic:
Element.prototype.selectSingleNode = function(cXPathString){
if(this.ownerDocument.selectSingleNode) {
var result = this.ownerDocument.selectSingleNode(cXPathString, this);
if (result != null) {
result.nodeTypedValue = result.textContent;
}
return result;
}
else{throw "For XML Elements Only";}
}

Categories

Resources