something inexplicable to me appears in the result of this code
var ctrl1 = {
func1: function(objct){
objct.options.b = "b";
}
}
var ctrl2 = {
myvar : {options:{a:"a"}},
func2: function(){
console.log(ctrl2.myvar);
ctrl1.func1(ctrl2.myvar);
},
}
ctrl2.func2();
I had as results
Object {a:"a", b:"b"}
while normally it should display
Object {a:"a"}
test in http://jsfiddle.net/akbach/6u0qnrc6/4/
Your coding is working fine. It's the options which gets updated before printing in console.
Try following steps open you console paste following code.
var ctrl1 = {
func1: function(objct){
objct.options.b = "b";
}
}
var ctrl2 = {
myvar : {options:{a:"a"}},
func2: function(){
console.log(ctrl2.myvar);
debugger;
ctrl1.func1(ctrl2.myvar);
},
}
ctrl2.func2();
Once the code stops at debugger you will see the required result in you console i.e a:"a"
Now resume script execution. After that write ctrl2.myvar on you console and then you will see the updated options with both a and b.
console.log may display a live reference (in chrome anyway), and not a snapshot. If it is "folded" (have to click on it to expand the details), it will continue to update.
You can see this by running your code, then modifying it again in the console and watching the previous output.
console.log() method receives a reference to the object. To open the object in console by clicking on "+" we need longer time, than the need for call func1 method. Try to replace console.log(ctrl2.myvar); with console.log(JSON.stringify(ctrl2.myvar));
Related
Edit: the code below was made up on the spot to show how I was going about what I was doing. It definietely won't run, it is missing a lot of things.
Here is a working example in codepen: https://codepen.io/goducks/pen/XvgpYW
much shorter example: https://codepen.io/goducks/pen/ymXMyB
When creating a function that is using call or apply, the this value stays null when using getPerson. however, when I use apply or call with getPerson it returns the correct person.
Please critique, I am really starting to learn more and more. I am in the middle of a project section so it might be hard to change all the code, but my next project could implement this better.
call and apply are setting to the window and not the object.
I will provide code that is much simpler with the same concept of what I am talking about.
function createPerson(){
this.manager = null;
this.teamManager = null;
this.setTeamManager = function(val){
this.teamManager = val;
}
this.setManager = function(val){
console.log('setting manager to',val);
this.teamManager = val;
}
this.getTeamManager = function(){
console.log('setting team manager to',val);
return this.teamManager ;
}
this.getManager = function(){
return this.manager;
}
this.appendSelect = function(elem){
var that = this;
createOtherSelects(that,elem);
}
//some functions that create selects with managers etc
//now assume there are other selects that will filter down the teams,
//so we might have a function that creates on change events
function createOtherSelects(that){
//code that creates locations, depending on location chosen will
//filter the managers
$('#location').on('change',function(){
//do some stuff
//... then call create management
createManagement(that,elem);
});
}
function createManagement(that,elem){
var currentLocation = that.location; //works
var area = that.area;//works ... assume these are set above
//code that returns a filter and unique set of managers back
that.teamManager = [...new Set(
data.map(person=>{
if(person.area==area &&
person.currentLocation==currentLocation
){
return person;
}
})
)].filter(d=>{if(d){return d}});
if(elem.length>0){
var selectNames = ['selectManager','selectTeamManager'];
var fcns = [that.setManager,that.setTeamManager];
for(var i = 0; i < selectNames.length;i++){
//do stuff
if(certainCriteriaMet){
// filter items
if(filteredManager == 1){
fcns[i].call(null,currentManager);//
}
}
}
}
}
}
var xx = new createPerson()
In console I see setting manager and setting team manager to with the correct values.
however when I call xx in console, I see everything else set except for
xx.teamManager and xx.manager
instead it is applying to the window, so if I type teamManager in the console, it will return with the correct person.
If I straight up say
that.setManager('Steve')
or even it works just fine.
xx.setManager('steve')
the this value in setManager is somehow changing from the current instance of the object to this window. I don't know why, and I would like to learn how to use apply and call using that for future reference.
I think the issue is with your following code
fcns[i].call(null,currentManager)
If you are not supplying "this" to call, it will be replaced with global object in non-strict mode.
fcns[i].call(that,currentManager)
See mdn article here
From your codepen example, you need to change that line
fcnset[0].apply(that,[randomName]);
The first argument of the apply method is the context, if you are not giving it the context of your method it's using the global context be default. That's why you end up mutating the window object, and not the one you want !
I'm trying to collect ratings for all products that have ratings on this page: https://www.theluxelens.com/pages/photoshop-overlays. While I can get the code below to work in my own browser (Chrome), it does not work on the page itself.
It is, however, able to get the elements that have the ratings, because the first console.log statement returns those elements.
var ratingsElements = document.getElementsByClassName("spr-badge");
console.log(ratingsElements);
var nonZeroRatings = [];
for(var i = 0; i < ratingsElements.length ; i++){
var rating = ratingsElements[i].getAttribute("data-rating");
console.log(rating);
if(rating != "0.0") {
nonZeroRatings.push(rating)
}
}
console.log("logging the ratings...");
console.log(nonZeroRatings);
There looks like a slight difference in what is returned when the code below is run in my own console vs from the page itself. When run from my browser console, the first console.log statement in my code returns an HTMLCollection that is slightly different - I believe this difference is why the code isn't working when run from the page itself, but I don't know why it is different. This code works, as you can see it delivers the ratings of products that have them (non-zero ratings) in an array:
VS. when the same code, run from the page, notice the HTMLCollection returned is slightly different:
This is the full script tag from the page:
<script type="text/javascript">
window.onload = function () {
var ratingsElements = document.getElementsByClassName("spr-badge");
console.log(ratingsElements);
var nonZeroRatings = [];
for(var i = 0; i < ratingsElements.length ; i++){
var rating = ratingsElements[i].getAttribute("data-rating");
console.log(rating);
if(rating != "0.0") {
nonZeroRatings.push(rating)
}
}
console.log("logging the ratings...");
console.log(nonZeroRatings);
};
</script>
Thanks for any insight here. This is a Shopify website, if that makes a difference.
When you log something from the page, it basically logs a reference which values are not filled in until the developer goes to look at the console entry. You may notice that little information icon beside it in the log entry, if you hover/click on that it should indicate this to you. Where, as when you're running this from the console it instead decides in this case to pull the collection data right away and log it.
That's the difference between runtime execution and developer intent in the console in some situations. This same concept applies at other times as well, I don't know all of them right off. That information icon showing up is a good indicator of the entry being a reference initially instead of a full data copy.
How can I check all Meteor helpers have run?
When I use this code, I get a new, empty div. When I remove the code from the rendered function and run it from my console, everything works fine.
Template.CasesShow.helpers({
value: function (n) {
if (this.data) {
var result = this.data.filter(function (obj) {
return obj.name == n;
});
if (result && result[0])
return result[0].value;
}
}
});
Template.CasesShow.rendered = function () {
$(document).ready(function () {
$textarea = $('[name=1]');
var content = $textarea.val().replace(/\n/g, '<br />');
$textarea.replaceWith($('<div class="box">' + content + '</div>'));
});
};
<template name="CasesShow">
<textarea class="w-input box" placeholder="{{_ 'laborauftrag.praxis'}}" name="1" data-name="1">{{value 1}}</textarea>
</template>
So I think, Meteor hasn't inserted the value yet, which is strange because it shouldn't run the rendered function then, right?
How can I make sure Meteor has run the helpers?
Template.rendered = func will run once before your template's helper (and long before your route provides you data). Your template isn't working when you have Template.rendered function because in your rendered function, you replace your textarea with div, and in helper you're returning value which is being set on the textarea which no longer exist (because Template.CaseShow.rendered has replaced it with <div>.
If you can provide more details about what you're actually trying to achieve here, we can solve that. What you have right now is intended behaviour of meteor.
If what you want to achieve is show your content in a div but after replacing /n with <br>, I believe you can do that by performing that regexp on your data in the template helper.
Put a console.log("FIRED VALUE HELPER"); and do the same for your .rendered console.log("TEMPLATE RENDERED"); The code will log in your client browser console. For chrome I right click on the browser and choose inspect element. Then choose console from the array of logs. Your client js code would look like this:
Template.CasesShow.helpers({
value: function (n) {
console.log("FIRED VALUE HELPER");
Template.CaseShow.rendered = function () {
console.log("FIRED RENDERED");
If you don't see the log in the client browser console, the helper/rendered function did not get called.
I have an array of hooks in jQuery that are executed before I load data into a grid. In one case, however, I want to remove the hook, then add it back for later. Whatever I'm doing is not working just right... it's probably a syntax error because I'm still somewhat new to jQuery. Any help would be appreciated, thanks!
Current code:
var preLoad = this.opts.hooks.preLoad.pop();
//stuff happens
//now I want to add the preLoad hook back
this.opts.hooks.preLoad.push(function(report) { preLoad(report); });
EDIT
It turns out the issue lies elsewhere in the code. However, I'd still like to know how best to accomplish this.
You access it the same way as any other variable stored in any other array.
this.opts.hooks.preLoad[0](myReport)
Can you not just add the function you removed like this?
var preLoad = this.opts.hooks.preLoad.pop();
//stuff happens
//now I want to add the preLoad hook back
this.opts.hooks.preLoad.push(preLoad);
And are you sure it's always the last one in the array that you want to remove?
It probably has to do with the fact that you are "canning" the argument "report" when you push the function back on the stack.
Try doing it like that:
var preLoad = this.opts.hooks.preLoad.pop();
//stuff happens
//now I want to add the preLoad hook back
this.opts.hooks.preLoad.push(preLoad);
I've tested it here http://jsfiddle.net/fWRez/
The example you gave has nothing to do with jQuery and is pure Javascript. Also, beware that what you are doing in your example is... not right. Consider this :
var ReportManager {
...
replace: function(report) {
var preLoad = this.opts.hooks.preLoad.pop();
//stuff happens
//now I want to add the preLoad hook back
this.opts.hooks.preLoad.push(function(report) { preLoad(report); });
}
}
If you execute this :
replace(null);
replace({foo:'bar'});
replace(null);
Your this.opts.hooks.preLoad array will look like this :
Array(
0: function(report) { return function(report) { return function(report) { ... } } }
)
Because you are pushing the function wrapped into itself every time you execute your code. I'm not sure why you need to pop and push it back in again, but this just look odd.
Also, Javascript is a very flexible language; which mean that you can do many weird stuff, like
"hello".concat(" world"); // -> 'hello world'
0.toString(); // -> '0'
(function(a) { return a; })("foo"); // -> 'foo'
(function() { return false; })() || (function() { return true; })(); // -> true (executes both functions)
(function(i) { return [i*2,i*3,i*4]; })(2)[1]; // -> 6
$('selector')[0]; // ...
// etc.
What I've got is an ASP.NET MasterPage/ContentPage, where the ContentPage utilizes an UpdatePanel with UpdateMode set to "Conditional". This ContentPage is basically a MultiView that has 3 views: Setup, Confirm, and Complete. I've got navigation buttons that when clicked, go to the server, do what they need to do and finally update the UpdatePanel so it can come back. My problem lies in my JavaScript.
I have the following Global object literal named PAGE:
PAGE = {
panel : undefined,
currentView: undefined,
buttons : {
all : undefined,
cont : undefined
},
views : {
setup : {},
confirm : {},
complete : {}
}
};
My PAGE.init() function looks like this:
PAGE.init = function() { console.log("PAGE.init() fired");
this.panel = $('div[id$="Panel_Page"]');
this.currentView = this.panel.find('input[id$="Hidden_CurrentView"]').val();
this.buttons.all = this.panel.find('input[type="submit"]');
this.buttons.cont = this.panel.find('input[id$="Button_Continue"]');
this.buttons.all.click(function() { PAGE.panel.hide(); });
switch (this.currentView) {
case "confirm" : this.views.confirm.init(); break;
case "complete" : this.views.complete.init(); break;
default : this.views.setup.init(); break;
}
};
And last, but not least, it all gets kicked off by:
// Fire events on initial page load.
PAGE.init();
// Fire events for partial postbacks.
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(PAGE.init);
My issue is that when it first fires Page.init() everything is great, however, when you click a button it immediately throws an error of: Uncaught TypeError: Cannot set property 'all' of undefined. Now I've tried to figure this out, but I'm at a loss. It seems as though this happens to ANY nested object literal off of the root of PAGE. The immediate properties like PAGE.panel work just fine, but as soon as you need access to PAGE.buttons.all or PAGE.views.setup, it throws this error. I have never seen this before.
Any ideas out there?
Use a getter for your panel property. Seeing as everything else appears to be a property of panel this should do it - you might be losing the reference to panel during the postback, so instead of getting the object once, get it every time:
get_panel: function() { return $get("Panel_Page"); }
Again, if I just have this.panel = $get(myElement) and then my partial page update destroys the node that was returned to this.panel when I created my object initially, this.panel will become undefined. Use a getter.
Hope that helps - happy coding.
EDIT:
Actually - now that I look at it again, you'll probably want to use getters for all of your properties instead of relying on get_panel().find(..) for currentView, for example, I'd do another getter there:
get_currentView: function() { return $get("Hidden_CurrentView", this.get_panel()); }
B
Instead of using this inside of the PAGE.init() function, I used PAGE and that corrected the issue. Apparently this was not referring to PAGE but rather PAGE.init. Still not sure why, as I do this elsewhere and it works.
For instance, the following use of this works and it's no different than how I use it in my OP:
PAGE.views.setup = {
buttons : {
all : undefined,
cont : undefined
},
init: function() {
var self = this,
buttons = self.buttons;
buttons.all = PAGE.panel.find('input[type="submit"]');
buttons.all.click(function() { alert(this.id + " clicked"); });
}
}