button variable scope - how to update variable in parent scope? jQuery - javascript

Updated jsFiddle: http://jsfiddle.net/leongaban/NmH97/
Inside my main function is a button state modifier function and several click functions.
Having a bit of trouble updating the boolean values in the parent function. I could solve this by using global variables, but I know I shouldn't need to do that here.
In the function below, when #toggle_company is clicked I pass the bool company (which is set to true by default) into the setupToggleButtons function. The current state is then switched, but the original company bool value is unchanged, how would you write this to target and update the variable company in the parent function wireSearchIcons?
var wireSearchIcons = function() {
// Boolean Flags
var company = true;
var phone = true;
var orange_on = '#F37B21'; var orange_off = '#f3cdb1';
var green_on = '#3DB54A'; var green_off = '#d8e0c3';
// Other code...
$("#toggle_company").unbind('click').bind('click', function () {
setupToggleButtons(company, '#toggle_company path', orange_on, orange_off);
});
function setupToggleButtons(bool, path, on, off) {
var path = $(path);
if (bool) {
path.css('fill', off);
bool = false;
return bool;
} else {
path.css('fill', on);
bool = true;
return bool;
}
console.log(bool);
}
}

When you use the variable in the function call, you will be sending the value that the variable contains, not the variable itself. Changing the parameter has no effect on the variable where the value came from.
Javascript doesn't support sending parameter by reference, so just return the value from the function, and assign it back to the variable:
$("#toggle_company").unbind('click').bind('click', function () {
company = setupToggleButtons(company, '#toggle_company path', orange_on, orange_off);
});
function setupToggleButtons(bool, path, on, off) {
var path = $(path);
if (bool) {
path.css('fill', off);
bool = false;
} else {
path.css('fill', on);
bool = true;
}
return bool;
}

It doesn't make sense to write a setupToggleButtons function that does so little. You should inline the code into the click handlers, or create the click handlers within the setup function.
var wireSearchIcons = function() {
// Flags
var company = true;
var phone = true;
var orange_on = '#F37B21'; var orange_off = '#f3cdb1';
var green_on = '#3DB54A'; var green_off = '#d8e0c3';
// Toggle Button States
$("#toggle_company").unbind('click').bind('click', function () {
company = !company;
$('#div_company').css('background', company ? orange_on : orange_off);
});
$("#toggle_phone").unbind('click').bind('click', function () {
phone = !phone;
$('#div_phone').css('background', phone ? green_on : green_off);
});
}
wireSearchIcons();

Related

Validate breeze complex-type without validate the entire entity

When you want to validate breeze-entity you write:
this.entityAspect.validateEntity()
But what about if I want to fire validations only for complex-type, without fire the entire-entity validations?
complexType.complexAspect not have method validateEntity.
So, what should I do?
Edit after I saw Jay answer:
I tried to use method validateProperty.
But the result was that it always returns true, becouse it not check each one of the properties.
So, I tried to call method validateProperty several-times, each time for other field of the complexType. It give me boolian-result of valid/not valid, but not update the validation-errors.
Here is the code that I tried after I saw Jay answer, but it is not help:
validateSingleField(myComplexProertyName);
first version of validateSingleField function: (the result was that it always returns true, becouse it not check each one of the properties)
function validateSingleField(object, fieldName) {
var entityAspect = object.entityAspect;
var objectType = object.entityType;
var prop = objectType.getProperty(fieldName);
var value = object.getProperty(fieldName);
if (prop.validators.length > 0) {
var context = { entity: entityAspect.entity, property: prop, propertyName: fieldName };
if (entityAspect._validateProperty(value, context)) {
return true;
}
return false;
}
}
second version:(It give me boolian-result of valid/not valid, but not update the validation-errors.)
function validateSingleField(object, fieldName) {
var aspect = object.entityAspect || object.complexAspect;
var entityAspect = object.entityAspect || object.complexAspect.getEntityAspect();
var objectType = object.entityType || object.complexType;
var prop = objectType.getProperty(fieldName);
if (prop.isComplexProperty) {
var isOk;
objectType.getProperties().forEach(function (p) {
isOk = isOk && validateSingleField(object[fieldName](), p.name)//writing 'object[fieldName]()' - is for send the entire complexType of the entity
});
return isOk;
}
else {
{
var value = object.getProperty(fieldName);
if (prop.validators.length > 0) {
var context = { entity: entityAspect.entity, property: prop, propertyName: fieldName };
if (entityAspect._validateProperty(value, context)) {
return true;
}
return false;
}
}
}
}
There is no separate method to validate a complex type because the validation results are all part of the 'parent' entity. Complex type properties are considered part of the entity, not independent entities.
What you can do is call validateProperty on the 'complex' property of the parent entity.

JavaScript: Not Calling Constructor Function

Can someone shed some light as to why this doesn't work the way I think it should (or what I'm overlooking).
function Pane(data) {
var state = {
show: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
So I can console log Pane(arg).show/hide and it'll log it as a function, so why is it when I call Pane(arg).show it doesn't do anything? The functions in the object work (outside of the constructor function in their own functions).
The function is returning the state object, so it will never return the constructed object, even when used with new. Since state contains those methods, you can just call the function and immediately invoke one of the methods on the returned object.
Now, if you're expecting show and hide to automatically have access to data via closure, it's not working because you're shadowing the variable by declaring the method parameters. You can do this instead:
function Pane(data) {
var state = {
show: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
Then you can use it like this:
Pane({}).show();
Or like this:
var p = Pane();
p.show();
Or force a new argument when needed:
p.show({foo:'bar'});
You are overriding the original argument in each function.
So what you are doing is to find elements with the attribute data-content='undefined'
This obviously doesn't work.
So to fix this you should just remove the data argument in the show/hide function.
Here is a plnkr showing the problem and fix.

How to call a Javascript function when value of a variable changes?

Usually we call a Javascript function, when a button is click.
<button onclick=function1();>Post message</button>
Or sometimes, we may call a Javascript function at a particular time.
window.onload = myFunction();
function myFunction()
{
setInterval(function1,t);
}
where function1() is any Javascript function. I want to call this function only if value of a variable changes in the script.
For instance: Lets say I have a variable abc. Now value of that variable changes when I select something on the page using the function below.
var abc = function getSelectionHTML() {
var userSelection;
if (window.getSelection) {
// W3C Ranges
userSelection = window.getSelection ();
// Get the range:
if (userSelection.getRangeAt) {
if (userSelection.rangeCount > 0)
var range = userSelection.getRangeAt(0);
else
return '';
} else {
var range = document.createRange ();
range.setStart (userSelection.anchorNode, userSelection.anchorOffset);
range.setEnd (userSelection.focusNode, userSelection.focusOffset);
}
// And the HTML:
var clonedSelection = range.cloneContents ();
var div = document.createElement ('div');
div.appendChild (clonedSelection);
return div.innerHTML;
} else if (document.selection) {
// Explorer selection, return the HTML
try {
userSelection = document.selection.createRange ();
return userSelection.htmlText;
} catch (err) {
return '';
}
} else {
return '';
}
}
How to alert(abc) only when the value of variable changes? Please help!
If you are targeting "modern" browsers, you can use Object.defineProperty to define a setter function, i.e. a function that get's called every time you set the value of the corresponding field.
Since "global" variables in JS are simply members of the window object jou should be able to do something like
Object.defineProperty(window, "abc", { set: function(v) {
/* this is run every time abc is assigned a value:
the value being assigned can be found in v */
} } );
Firstly, you need to define your variable abc with Custom Setters and Getters:
var value_of_abc;
Object.defineProperty(window, 'abc', {
get: function() {
console.log('get!');
return value_of_abc;
},
set: function(value) {
console.log('set!');
value_of_abc = value;
}
});
Then whenever you call or change variable abc, the thing down here will occur.
window.abc //get!
window.abc = 1 //set!

Javascript creating function to share variables between other functions

I have a couple click functions with jQuery that share the same variables, so I created a function to return those variables.
While this works, I'm wondering whether programmatically speaking this is the right or most efficient way to do this:
function clickVars($me){
var $curStep = $('.cust-step-cur'),
$nextStep = $curStep.next('.cust-step'),
nextStepLen = $nextStep.length,
$list = $('.cust-list'),
$btnCheck = $('.cust-btn.checklist'),
hasChecklist = $me.hasClass('checklist');
return {
curStep: $curStep,
nextStep: $nextStep,
nextStepLen: nextStepLen,
list: $list,
btnCheck: $btnCheck,
hasChecklist: hasChecklist
};
}
// Checklist Click
$('.option-list a').on('click',function(){
var $me = $(this),
myVars = clickVars($me);
currentStepOut(myVars.curStep);
myVars.curStep.removeClass('cust-step-cur');
currentStepIn(myVars.nextStep, myVars.list, myVars.btnCheck);
});
// Navigation
$('.cust-btn').on('click',function(){
if(animReady === false)
return false;
var $me = $(this),
myVars = clickVars($me);
if(myVars.hasChecklist && myVars.list.hasClass('cust-step-cur'))
return false;
currentStepOut(myVars.curStep);
myVars.curStep.removeClass('cust-step-cur');
if(myVars.nextStepLen === 0 || $me.hasClass('checklist')) {
myVars.nextStep = myVars.list;
}
animReady = false;
currentStepIn(myVars.nextStep, myVars.list, myVars.btnCheck);
});
Is this a standard way of generated shared variables between multiple functions?
In AS3 it's good practice to do:
// Variable definitions
var enabled:Boolean = false;
public function myFunction(){
enabled = true;
}
So in JavaScript I've been doing:
// Variable defintions
var a,b,c,d,e = 0;
function alterVariables(){
a = 1;
b = 2;
}
You have to understand you are not sharing variables between functions. Moreover, each time you click those elements, clickVars function is called again and again, even if you click only one element multiple times. So this code is very bad expirience. Check this:
// Defined ones
var nodes = {
$elements : $('.elements'),
$otherElements : $('.otherElements'),
}
// In case you have multiple .selector elements in your DOM
$('.selector').each(function() {
// Defined ones for each element
var $element = $(this), isList = $element.hasClass('.list');
$element.bind('click', function(){
nodes.$elements.addClass('clicked');
});
});
$('.anotherSelector').each(function() {
// Yep, here is some duplicate code. But there won't be any
// performance improvement if you create special method for
// such small piece of code
var $element = $(this), isList = $element.hasClass('.list');
$element.bind('click', function(){
nodes.$elements.addClass('clicked');
});
});

Problem with Event Handling via YUI

When users click "search" input element, the search text inside the input will disappear and since I have several controls like that, I thought I could make the code reusable. Here is my code formerly done and working with jQuery but now in YUI I cannot make it work.
var subscriptionBoxTarget = "div.main div.main-content div.side-right div.subscription-box input";
var ssbNode = YAHOO.util.Selector.query(subscriptionBoxTarget);
var ssbValue = YAHOO.util.DOM.getAttribute(ssbNode,"value");
var subscriptionBox = new RemovableText(ssbNode,ssbValue,null);
subscriptionBox.bind();
////////////////////////////////
//target : the target of the element which dispatches the event
// defaultText : the default for input[type=text] elements
// callBack : is a function which is run after everthing is completed
function RemovableText(target,defaultText,callBack)
{
var target = target; //private members
var defaultText = defaultText;
var callBack = callBack;
//instance method
this.bind = function()
{
mouseClick(target,defaultText);
mouseOff(target,defaultText);
if(callBack != null)
callBack();
}
//private methods
var mouseClick = function(eventTarget,defaultValue)
{
var _eventTarget = eventTarget;
var _defaultValue = defaultValue;
/*$(eventTarget).bind("click",function(){
var currentValue = $(this).val();
if(currentValue == defaultValue)
$(this).val("");
});*/
YAHOO.util.Event.addListener(_eventTarget,"click",function(e){
alert(e);
});
}
var mouseOff = function(eventTarget,defaultValue)
{
var _eventTarget = eventTarget;
var _defaultValue = defaultValue;
/*$(eventTarget).bind("blur",function(){
var currentValue = $(this).val();
if(currentValue == "")
$(this).val(_defaultValue);
});*/
YAHOO.util.Event.addListener(_eventTarget,"blur",function(e){
alert(e);
});
}
}
You have a lot of unnecessary code here.
The input parameters passed to the RemovableText constructor are available by closure to all the methods defined inside. You don't need to, and shouldn't redefine named params as vars.
function RemovableText(target, defaultText, callback) {
this.bind = function () {
YAHOO.util.Event.on(target, 'click', function (e) {
/* You can reference target, defaultText, and callback in here as well */
});
YAHOO.util.Event.on(target, 'blur', function (e) { /* and here */ });
if (callback) {
callback();
}
};
}
The definition of an instance method from within the constructor seems dubious, as is the requirement that the values passed to the constructor must be kept private. Just assign them to instance properties (this._target = target; etc) and add instance methods to the prototype. If the functionality you're after is just this simple, then why bother with methods at all?
Using the click event does not support keyboard navigation. You should use the focus event.
I'm not sure why you would have a callback passed at construction that fires immediately after attaching the event subscribers.

Categories

Resources