Javascript Hoisting - javascript

Quite an interesting thing was discovered by me as a JS learner, consider the following code.
this.init = function (e) {
var container = e.container;
// slider
var slider = $("#div1").slider({ orientation: "horizontal", step: 1,
slide: function () {
console.log(e.container); // not null
console.log(container); // null
}
});
};
here's how it's called:
lib.init({ container: $("#container") });
I know that I can use on("slide", {container: container}, function(event, args){...})) to bind slide event and pass external data into it. But - could anyone explain why values returned by two console.log are different? Also I wonder if the technique is a technically sound replacement for on approach?

First of all, I am amazed that you are getting a null for container. Would actually want to see your logs if you can post
Secondly, here's an explanation of why this won't work, but not of why you get a null:
This has nothing to do with hoisting
you are executing the init function with lib.init({ container: $("#container") });
At that time attached function this.init = function (e) { ... gets executed with some value of e, may be an Event, so e is defined and the variable container gets a value
Whereas, in the following code on 5th line,
var slider = $("#div1").slider( ... // u are calling slider
the slider function is being called with options, and one of the options is:
slide: function () { // anonymous and will execute later
console.log(e.container); // not null
console.log(container); // null
}
most important, you are in the scope of slider function of your library, as it is being executed
here, the function you are attaching to slide: ... has not been executed yet. It will, when slide event happens
when that happens, the present value of container will be used
If you are getting a null, something definitely is resetting container, as in the fiddle here by yckart its not null and is same as e.container

Can't see a difference... For me are both logs equal: http://fiddle.jshell.net/WJ2s8/

Related

JqueryUI access modify drag function

I am trying to get access and modify this function (second one) in jqueryUI. I have tried everything. What I want to do is to add something in the function. I know it is possible and I need to do something like this :
var snapIt = $.ui.draggable.prototype.drag;
$.ui.draggable.prototype.drag = function() {
console.log("hello"); // exemple of a thing I want to add
// Now go back to jQuery's original function()
return snapIt.apply(this, arguments);
};
On top it will get the function add in console "hello" and then continue normally with the rest of the jQuery function. But I just can't find this function. I know this doesn't work: $.ui.draggable.prototype.start and dozens of others I tried.
$.ui.plugin.add("draggable", "snap", {
start: function( event, ui, i ) {
click.x2 = event.clientX;
click.y2 = event.clientY;
var o = i.options;
i.snapElements = [];
$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
var $t = $(this),
$o = $t.offset();
if (this !== i.element[0]) {
//...........
I don't want the drag: function(event, ui) {..... I need to modify the function because I use ui.position = {left..... and it make the snap method not work. The only way was to change the drag method. I know it work because I tried manualy. But changing the library might be problematic for futur dev.
Don't know if I am clear but basically I want the path to $.ui.plugin.add("draggable", "snap", {//stuff}); in jqueryUI library
Thx in advance
There are 3 different sources of behaviors that are called on the different events in jquery-ui, each with its own structure.
First you have the "private" functions, that are defined on the prototype and that are called directly on native events. These are on $.ui.draggable.prototype and begin with a _ character. For example you have $.ui.draggable.prototype._mouseDrag function.
These are called directly and are the ones triggering the events. They are not directly accessible from the options.
Then you have the plugins functions. These are the ones that are added using add. Basically what add does is that it sets functions to be called on the events that are accessible via the options. And these plugins callbacks are called if their corresponding option is true. The structure goes like this:
Each plugin is an object that defines a callback for different
events. The events available are the same that are accessible in the options. For draggable, you have start, drag and stop.
These callbacks are pushed in arrays contained by
$.ui.draggable.plugins object, in which each property is one of the available event.
A function goes through the event array and validates if the plugin
should be ran based on the option set.
Once the plugins are done, the options callbacks are called. These are the ones that you set in the options.
So depending what ou want to modify, you can either change the prototype:
$.ui.draggable.prototype._mouseDrag
Or you can add a plugin. Like this:
$.ui.plugin.add( "draggable", "customPlugin", {
drag: function(event, ui, draggable){
console.log("I'm the custom plugin");
});
Or you can modify snap plugin. This one is a bit more complicated, and much less reliable since the functions are stored in arrays and not in an object, and they are added. The structure goes like this:
Each property key is an event, and every property is an array of
arrays.
Each of the array first element is the name of the option associated
with the callback, that is the second element of the array.
So the drag callback associated to snap is $.ui.draggable.prototype.plugins.drag[2], because it's the third callback that's been added to drag event. $.ui.draggable.prototype.plugins.drag[2][0] is the string "snap", which is used to check if the option was set to true. And the callback is $.ui.draggable.prototype.plugins.drag[2][1]. So you can modify it like this:
$.ui.draggable.prototype.plugins.drag[2][1] = function(){
console.log("I'm the modified plugin");
}
If you want a better control, you can iterate through $.ui.draggable.prototype.plugins.drag array and check the first element to make sure you modify the proper plugin.
Obviously, as you tried, you need to store the original callback if you want the behavior to work.
See here how this goes:
$.ui.plugin.add("draggable", "customPlugin", {
drag: function() {
console.log("%c I'm a custom plugin", 'color: blue');
}
});
var _temp = $.ui.draggable.prototype.plugins.drag[2][1];
$.ui.draggable.prototype.plugins.drag[2][1] = function() {
console.log("%c I'm the modified snap plugin drag callback", 'color: red');
_temp.apply(this, arguments);
}
$('div').draggable({
snap: true,
customPlugin: true,
drag: function() {
console.log("%c I'm the options callback", 'color: green');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<div>Drag me</div>
<div>Or me</div>

How to store original window.onscroll function in JavaScript

I have following code in my JavaScript library. My goal is to store the original onscroll function which is the first line of code snippet, and then point onscroll to a new function. However, what I am finding is that wind.origonscroll which is supposed to be the original scroll function is always pointing to the new function in second line.
Question: Is there a way to store the original function in code below, so window.origscroll always points to the function in first line of commented code? I am trying to keep track of what was the original window's onscroll event, which is not related to overriding a function. I do not need to override a function here.
//window.onscroll = function() {console.log('scrolling done');}
wind.origonscroll = window.onscroll;
window.onscroll = function () { window.scrollTo(wind.x, wind.y); };
If window.onscroll is not null ( if has been defined before) it can be saved away.
Try this:
window.onscroll=function() { console.log('asd') }
var old = window.onscroll
window.onscroll=function() { console.log('gggg') }
old()

Javascript variable is changing its value, reasons that can cause such?

I am debugging the weirdest error I ever seen. At this point my code look like this.
var counter = 0;
function setup() {
var count = ++counter;
var test = false;
function getSetter(arg?) {
if (typeof (arg) !== "undefined") {
console.log(["setting",count, arg]);
test = arg;
} else {
console.log(["getting",count, test]);
return test;
}
}
return getSetter;
}
var verticalScrollDisabled = setup();
this is in a closed scope and i have made sure that the variable test is not accessed outside the above code. I can change it to any name with same result. Updated such its clear that its not accessed outside of this scope. And updated with a counter to show its not written over.
Copy pasting result from the console.
["enter scroll area", div.fxs-blade-content, true, "3511>401 || 577>585"] HorizontalScrollBindingHandler.ts:12
["setting", 1,true] HorizontalScrollBindingHandler.ts:132
disable vert HorizontalScrollBindingHandler.ts:72
n.Event {originalEvent: WheelEvent, type: "mousewheel", isDefaultPrevented: function, timeStamp: 1422128039040, jQuery21104183536011260003: true…} HorizontalScrollBindingHandler.ts:15
["getting", 1,false] HorizontalScrollBindingHandler.ts:15
["getting", 1, false] HorizontalScrollBindingHandler.ts:75
[false, false]
Issue
As commented, my problem is that as seen in the trace. the variable get set to true, but when its being accessed again its false. I cant get why that can happen.
and the handler attached to mousescroll event.
var scrollHorizontally =(e) => {
// console.log([verticalScrollDisabled(), scrollInAction]);
console.log(e);
if (verticalScrollDisabled() && !scrollInAction)
return;
console.log([verticalScrollDisabled(), scrollInAction]);
This code has been working for ever and nothing changed to it other than we in some seperate code are opening a popup and closing it again. Is there anything that could cause events to be doing something out of the expected related to if the window loses focus or something? Again, the test variable is not altered outside the verticalcrollDisabled function, so I have no clue why it can go change itself to false, notice the ["setting", true].
Just verified that the popup is not the cause.
Heres the hole file. https://gist.github.com/s093294/e49ed46d2680c1403e3b
Answer is, validate your assumptions.
I assumed that the file was not loaded twice since it being a module defined with define and loaded with requirejs. This didnt hold up since there was some ID mapping that made two ids load this file and as one of the comments said, this is the thing that makes it possible.
I resolved the requirejs configuration and problem vent away.

Why is my method not seeing this.property?

In the code below, initializeBoard has access to the property, and the console returns 'white' when I start the script. But when I click inside the window, I get 'undefined'. What obvious thing am I missing? (Bonus: what's the search query that'd have led me to the answer without having to ask?)
var view = {
currentMove: 'white',
initializeBoard: function() {
console.log(this.currentMove);
},
click: function(e) {
console.log(this.currentMove);
}
}
window.onload = function() {
view.initializeBoard();
document.onclick = view.click;
}
The value of this is determined by how the function is called, not by where it is first assigned.
You are copying the (reference to the) function to document.onclick.
When the click event happens document.onclick is called. view.click is not called (even though it has the same value as document.onclick). This means that this is document not view.
Use bind if you want to create a wrapper function that calls the original function in the right context.
document.onclick = view.click.bind(view);

Using .bind (mootools) with onClick event

I have the code (inside one object)
onclick: this._addX.bind(this)
and then inside another object
onclick: this._addY.bind(this)
Now, _addX() and _addY are nearly identical, except they both end up calling (on the click event) a function with different argument values, say _addX calls foo('x') and _addY calls foo('y'). So I tried:
onclick: this._add.bind(this,'x') and
onclick: this._add.bind(this,'y') in the two objects. And of course I changed _add to accept an argument.
At runtime, when _add is called, it does not see any incoming arguments! I have fumbled around with different syntaxes but nothing works. Any ideas? The original syntax works fine (no arguments) but forces me to duplicate a large function with only one line different, which pains me. Thanks in advance.
_add: function(which) {
var me = this;
var checkFull = function(abk) {
if (abk.isFull) {
alert("full");
} else {
alert(which); // which is always undefined here!
}
};
getAddressBook(checkFull); //checkFull is a fn called by getAddressBook
},
this works and it keeps the scope within an element click event with the scope set to the class and not the element--there is no point in passing scope to the add method, it already has that:
var foo = new Class({
Implements: [Options],
add: function(what) {
alert(what);
},
initialize: function(options) {
this.setOptions(options);
this.options.element.addEvents({
click: function() {
this.add(this.options.what);
}.bind(this)
});
}
});
window.addEvent("domready", function() {
new foo({
element: $("foo"),
what: "nothin'"
});
});
just make an element with id=foo and click it to test (alerts nothin'). if your onclick is a function / event handler within your class as opposed to a normal element click event, then things are going to differ slightly - post a working skeleton of your work on http://mootools.net/shell/
If you read my previous answer, disregard it. The MooTools .bind method supports passing parameters. So something else isn't working as you expect:
onclick: this._add.bind(this, 'y');
Here is a simple setup on JSBin to show how bind truly does pass parameters.
The only purpose of bind is to "tell" the JS what object you mean when you say this. i.e. you pass as a parameter to bind an instance of the object you wish the this key word will refer to inside the function you used the bind on.

Categories