I'm trying to implement hammer.js to swipe pages (like a book) and I did it. The problem is that this works
var idHammer1 = document.getElementById("pageHoja1")
//var hammertime = new Hammer(myElement, hammerOptionsPan);
var objHammer1 = new Hammer(idHammer1);
objHammer1.on('panleft panright', function(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
});
but this doesn't:
var fSwipe1 = function(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
}
var idHammer1 = document.getElementById("pageHoja1")
//var hammertime = new Hammer(myElement, hammerOptionsPan);
var objHammer1 = new Hammer(idHammer1);
objHammer1.on('panleft panright', fSwipe1(ev))
and this also don't work
function fSwipe1(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
}
and since I need to add this event to many pages (variable #) I cant hardcode it... How can I make it variable inside a cycle?
Thanks!
Ah, without knowing the extent of the errors, I do see:
objHammer1.on('panleft panright', fSwipe1(ev));
Here, you are rendering the function automatically, but what you actually want is to use a closure so that the function does not get rendered until the event gets hit. I'm not sure what ev represents, but if it is the event object, then this should work:
objHammer1.on('panleft panright', fSwipe1);
Where all you are doing is passing in the function that you want to be the callback and the even will automatically call this function and pass the event object as the first parameter.
A few other things that I notice:
make sure that you include the javascript library for Hammer
Make sure that gSceneActual is defined before it is evaluated at gSceneActual===2
Make sure that jQuery library is included
Related
I've been trying to get a smooth scroll animation for a while now, but mainly in JS..
This hasn't been working out that well so I decided to try in CSS3.
Now I want to make this animation responsive by calling a JS function which adds the CSS rules for the animation responsive to the object the animation is for. Here is the JS code I've got so far. I'll also leave a Fiddle, but I'm new to that so things might not work right away.
function getTexts() {
var element = document.getElementsByClassName('toplink');
for (x = 0, len = element.length; x < len; x++){
var ID = element[x].textContent.toLowerCase();
var object = document.getElementById(ID);
console.log(object);
addCSSAnimator(ID);
}
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = document.getElementById(el);
var Class = DOM.getAttribute("class");
var Parent = DOM.parentElement.getAttribute("id");
var rect = DOM.getBoundingClientRect();
var rule = ".toplink[ id= '"+el+"' ]:target - #"+Parent+" div."+Class+" {\n" +
"-webkit-transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"}";
console.log("Stylesheet: ",sheet," object: ",DOM," Class: ",Class," offset X&Y:",rect.x," ",rect.y);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
https://jsfiddle.net/dtj46c64/
You may try moving to jquery for this solution. Use document.ready and window.resize functions to handle the animation and also instead of for loop. use the jquery .each() function to get the elements. Try working around the following code i changed for you to go along with. Hope this puts you in the right direction to achieve your goal:
<script>
function getTexts() {
$(".toplink").each(function () {
let ID = $(this)
console.log(ID);
addCSSAnimator(ID);
});
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = el;
var Class = DOM.attr("class");
var Parent = DOM.parent().attr("id");
var rect = DOM[0].getBoundingClientRect();
var rule = ".toplink[ id= '" + el + "' ]:target - #" + Parent + " div." + Class + " {\n" +
"-webkit-transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"}";
console.log("Stylesheet: ", sheet, " object: ", DOM, " Class: ", Class, " offset X&Y:", rect.left, " ", rect.top);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
$(window).on('resize', function () {
getTexts();
});
$(document).ready(function () {
getTexts();
});
</script>
Notice i changed the rect.y to rect.top as on some browsers the getBoundingClientRect fucntion does not return x and y values but left and top are always filled.
Also dont know why you are getting id of the parent of the object as there is no id set to the parent of the anchor class="toplink" so it will always return as null or empty.
Sorry for not a 100% answer as got busy but i hope the solution so far i suggested will help you tweak and find what your looking for.
If you go to Google Alert website while you are not login with your Google Account you would have a chance of creating an alert send to your Yahoo account for example.
I am going create an alert using PhantomJS. Then I would need to click on the CREATE ALERT button. I need to do that using JavaScript. But it seems that PhantomJS cannot click on this button!
I have even tried to click on this button through Google Console but I could not.
I have used three different ways for clicking on the button which nothing works. Can someone help me to click on the CREATE ALERT button?
javascript:if(!window.jQuery||confirm('Overwrite\x20current\x20version?\x20v'+jQuery.fn.jquery))(function(d,s){s=d.createElement('script');s.src='https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.js';(d.head||d.documentElement).appendChild(s)})(document);
var inputOne = document.getElementsByTagName('input')[0];
inputOne.value = "testAlert";
var inputTwo = document.getElementsByTagName('input')[1];
inputTwo.value = "test#yahoo.com";
var button = document.getElementById('create_alert');
//1.
//button.click();
//2.
//$(button).trigger('click');
//$(button).trigger('change');
//3.
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
button.dispatchEvent(event);
And I am using following code in PhantomJS
phantom.injectJs("functions/jquery.js");
var page = require('webpage').create();
var load, contoroller;
var numOfActions = 1;
var clicked = false;
var initialURL = "https://www.google.com/alerts";
page.open(initialURL, function(status) {
load = true;
});
page.onLoadFinished = function(status)
{
clearInterval(contoroller);
if (clicked)
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}
else
{
contoroller = setInterval(function () {
if (load)
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
load = false;
enterQuery("test");
}
else
{
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
page.evaluate(function(){
var input = document.getElementsByTagName('input')[1];
input.value = "test#test.com";
})
click();
}
}, 5000);
}
}
function enterQuery(query)
{
page.injectJs("functions/jquery.js");
page.evaluate(function(query)
{
var box = document.getElementsByTagName('input')[0];
box.value = query;
//$(box).keypress();
}, query);
}
function click()
{
clicked = true;
clearInterval(contoroller);
var but = page.evaluate(function(){
var button = document.getElementById('create_alert');
//var event = document.createEvent("MouseEvents");
//event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
//button.dispatchEvent(event);
return button;
})
page.sendEvent('click', but);
window.setTimeout(function () {
console.log("The status of loading the page is " + status + "\n");
page.render("SCREENSHOTS/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}, 5000);
}
It seems that I need to first hover the mouse on the button. When you hover the mouse you will see that the class attribute of the element changes. I have tried $(button).trigger('mouseover') but after that the class attribute did not change. How can I trigger mouseover on this element?
There are two problems with your code: typing and clicking.
When you set the value of an input field directly, none of the input event handlers are called. You could use the native page.sendEvent("keypress", keys) which types keys as if a user would type them, so all event handlers will be triggered. Since the function doesn't know where to type to, you need to focus on the element first:
page.evaluate(function(selector){
document.querySelector(selector).focus();
}, selector);
page.sendEvent("keypress", query);
You can solve the clicking also with page.sendEvent("click", posx, posy). Now the challenge becomes to find out the position of the elements on the page. This answer provides a jQuery way of solving this:
page.injectJs("jquery.min.js");
var rect = page.evaluate(function(selector) {
return $(selector)[0].getBoundingClientRect();
}, selector);
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);
This is your full script that works as expected:
var page = require('webpage').create();
var load, contoroller;
var numOfActions = 1;
var clicked = false;
var initialURL = "https://www.google.com/alerts";
page.open(initialURL, function(status) {
load = true;
});
page.onLoadFinished = function(status)
{
clearInterval(contoroller);
if (clicked)
{
console.log("1| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}
else
{
contoroller = setInterval(function () {
if (load)
{
console.log("2| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
load = false;
enter("input", "test"); // very first input
}
else
{
console.log("3| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
enter("input.email_input", "test#test.com");
setTimeout(function(){
click("#create_alert");
}, 500);
}
}, 5000);
}
}
function enter(selector, query)
{
page.evaluate(function(selector){
document.querySelector(selector).focus();
}, selector);
page.sendEvent("keypress", query);
}
function click(selector)
{
clicked = true;
clearInterval(contoroller);
page.injectJs("functions/jquery.js");
var rect = page.evaluate(function(selector) {
return $(selector)[0].getBoundingClientRect();
}, selector);
page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);
window.setTimeout(function () {
console.log("4| The status of loading the page is " + status + "\n");
page.render("SCREENSHOT/page_" + numOfActions + ".png");
numOfActions += 1;
phantom.exit();
}, 5000);
}
I have the following bit of jQuery code that i want to reuse by calling it from other parts of my jQuery code. How would i do that?
$(document).ready(function() {
$('#share_mention').charcount({
maxLength: 140,
preventOverage: false
});
$('.countable').bind('update', function(evt, length, remaining) {
var message = 'id=' + $(evt.target).attr('id') + ', length=' + length + ', remaining=' + remaining;
});
});
There are many ways to skin this cat but here is an approach.
var yourNameSpace = {};
yourNameSpace.YourFunction = function(){
$('#share_mention').charcount({
maxLength: 140,
preventOverage: false
});
$('.countable').bind('update', function(evt, length, remaining) {
var message = 'id=' + $(evt.target).attr('id') + ', length=' + length + ', remaining=' + remaining;
});
}
$(document).ready(function() {
yourNameSpace.YourFunction()
});
First things first there is no such thing as a jQuery function. It's a javascript function.
The event is implicitly passed to the callback function.
function countCats (event) {}
$('.cats').on('click', countCats);
I'm struggling with managing dynamically built event handlers in javascript.
In several places, I build forms, or controls in which specific events (mainly mouseovers, mouse-outs, clicks) need to be handled.
The trick is that in a significant number of cases, the event handler itself needs to incorporate data that is either generated by, or is passed-into the function that is building the form or control.
As such, I've been using "eval()" to construct the events and incorporate the appropriate data, and this has worked somewhat well.
The problem is I keep seeing/hearing things like "You should never use eval()!" as well as a couple of increasingly ugly implementations where my dynamically-built event handler needs to dynamically build other event handlers and the nested evals are pretty obtuse (to put it mildly).
So I'm here, asking if someone can please show me the better way (native javascript only please, I'm not implementing any third-party libraries!).
Here's a crude example to illustrate what I'm talking about:
function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
var inp = document.createElement('input');
inp.id = controlName;
inp.type = type;
inp.style.cssText = dormantStyle;
eval("inp.onfocus = function() { this.style.cssText = '" + activeStyle + "'; }");
eval("inp.onblur = function() { this.style.cssText = '" + dormantStyle + "'; }");
eval("inp.onclick = function() { " + whenClicked + "; }");
return inp;
}
This function obviously would let me easily create lots of different INPUT tags and specify a number of unique attributes and event actions, with just a single function call for each. Again, this is an extremely simplified example, just to demonstrate what I'm talking about, in some cases with the project I'm on currently, the events can incorporate dozens of lines, they might even make dynamic ajax calls based on a passed parameter or other dynamically generated data. In more extreme cases I construct tables, whose individual rows/columns/cells may need to process events based on the dynamically generated contents of the handler, or the handler's handler.
Initially, I had built functions like the above as so:
function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
var inp = document.createElement('input');
inp.id = controlName;
inp.type = type;
inp.style.cssText = dormantStyle;
inp.onfocus = function() { this.style.cssText = activeStyle; };
inp.onblur = function() { this.style.cssText = dormantStyle; };
eval("inp.onclick = function() { " + whenClicked + "; }");
return inp;
}
...but I found that whatever the last assigned value had been for "activeStyle", and "dormantStyle" became the value used by all of the handlers thusly created (instead of each retaining its own unique set of styles, for example). That is what lead me to using eval() to "lock-in" the values of the variables when the function was created, but this has lead me into nightmares such as the following:
(This is a sample of one dynamically-built event-handler that I'm currently working on and which uses a nested eval() function):
eval("input.onkeyup = function() { " +
"InputParse(this,'ucwords'); " +
"var tId = '" + myName + This.nodeName + "SearchTable" + uidNo + "'; " +
"var table = document.getElementById(tId); " +
"if (this.value.length>2) { " +
"var val = (this.value.indexOf(',') >=0 ) ? this.value.substr(0,this.value.indexOf(',')) : this.value; " +
"var search = Global.LoadData('?fn=citySearch&limit=3&value=' + encodeURI(val)); " +
"if (table) { " +
"while (table.rows.length>0) { table.deleteRow(0); } " +
"table.style.display='block'; " +
"} else { " +
"table = document.createElement('table'); " +
"table.id = tId; " +
"ApplyStyleString('" + baseStyle + ";position=absolute;top=20px;left=0px;display=block;border=1px solid black;backgroundColor=rgba(224,224,224,0.90);zIndex=1000;',table); " +
"var div = document.getElementById('" + divName + "'); " +
"if (div) { div.appendChild(table); } " +
"} " +
"if (search.rowCount()>0) { " +
"for (var i=0; i<search.rowCount(); i++) { " +
"var tr = document.createElement('tr'); " +
"tr.id = 'SearchRow' + i + '" + uidNo + "'; " +
"tr.onmouseover = function() { ApplyStyleString('cursor=pointer;color=yellow;backgroundColor=rgba(40,40,40,0.90);',this); }; " +
"tr.onmouseout = function() { ApplyStyleString('cursor=default;color=black;backgroundColor=rgba(224,224,224,0.90);',this); }; " +
"eval(\"tr.onclick = function() { " +
"function set(id,value) { " +
"var o = document.getElementById(id); " +
"if (o && o.value) { o.value = value; } else { alert('Could not find ' + id); } " +
"} " +
"set('" + myName + This.nodeName + "CityId" + uidNo + "','\" + search.id(i)+ \"'); " +
"set('" + myName + This.nodeName + "ProvId" + uidNo + "','\" + search.provId(i)+ \"'); " +
"set('" + myName + This.nodeName + "CountryId" + uidNo + "','\" + search.countryId(i) + \"'); " +
"set('" + input.id + "','\" + search.name(i)+ \"'); " +
"}\"); " +
"var td = document.createElement('td'); " +
"var re = new RegExp('('+val+')', 'gi'); " +
"td.innerHTML = search.name(i).replace(re,'<span style=\"font-weight:bold;\">$1</span>') + ', ' + search.provinceName(i) + ', ' + search.countryName(i); " +
"tr.appendChild(td); " +
"table.appendChild(tr); " +
"} " +
"} else { " +
"var tr = document.createElement('tr'); " +
"var td = document.createElement('td'); " +
"td.innerHTML = 'No matches found...';" +
"tr.appendChild(td); " +
"table.appendChild(tr); " +
"} " +
"} else { " +
"if (table) table.style.display = 'none'; " +
"} " +
"} ");
Currently, I'm having problems getting the nested eval() to bind the ".onclick" event to the table-row, and, as you can see, figuring out the code is getting pretty hairy (debugging too, for all the known reasons)... So, I'd really appreciate it if someone could point me in the direction of being able to accomplish these same goals while avoiding the dreaded use of the "eval()" statement!
Thanks!
And this, among many other reasons, is why you should never use eval. (What if those values you're "baking" in contain quotes? Oops.) And more generally, try to figure out why the right way doesn't work instead of beating the wrong way into submission. :)
Also, it's not a good idea to assign to on* attributes; they don't scale particularly well. The new hotness is to use element.addEventListener, which allows multiple handlers for the same event. (For older IE, you need attachEvent. This kind of IE nonsense is the primary reason we started using libraries like jQuery in the first place.)
The code you pasted, which uses closures, should work just fine. The part you didn't include is that you must have been doing this in a loop.
JavaScript variables are function-scoped, not block-scoped, so when you do this:
var callbacks = [];
for (var i = 0; i < 10; i++) {
callbacks.push(function() { alert(i) });
}
for (var index in callbacks) {
callbacks[index]();
}
...you'll get 9 ten times. Each run of the loop creates a function that closes over the same variable i, and then on the next iteration, the value of i changes.
What you want is a factory function: either inline or independently.
for (var i = 0; i < 10; i++) {
(function(i) {
callbacks.push(function() { alert(i) });
})(i);
}
This creates a separate function and executes it immediately. The i inside the function is a different variable each time (because it's scoped to the function), so this effectively captures the value of the outer i and ignores any further changes to it.
You can break this out explicitly:
function make_function(i) {
return function() { alert(i) };
}
// ...
for (var i = 0; i < 10; i++) {
callbacks.push(make_function(i));
}
Exactly the same thing, but with the function defined independently rather than inline.
This has come up before, but it's a little tricky to spot what's causing the surprise.
Even your "right way" code still uses strings for the contents of functions or styles. I would pass that click behavior as a function, and I would use classes instead of embedding chunks of CSS in my JavaScript. (I doubt I'd add an ID to every single input, either.)
So I'd write something like this:
function create_input(id, type, active_class, onclick) {
var inp = document.createElement('input');
inp.id = id;
inp.type = type;
inp.addEventListener('focus', function() {
this.className = active_class;
});
inp.addEventListener('blur', function() {
this.className = '';
});
inp.addEventListener('click', onclick);
return inp;
}
// Called as:
var textbox = create_input('unique-id', 'text', 'focused', function() { alert("hi!") });
This has some problems still: it doesn't work in older IE, and it will remove any class names you try to add later. Which is why jQuery is popular:
function create_input(id, type, active_class, onclick) {
var inp = $('<input>', { id: id, type: type });
inp.on('focus', function() {
$(this).addClass(active_class);
});
inp.on('blur', function() {
$(this).removeClass(active_class);
});
inp.on('click', onclick);
return inp;
}
Of course, even most of this is unnecessary—you can just use the :focus CSS selector, and not bother with focus and blur events at all!
You don't need eval to "lock in" a value.
It's not clear from the posted code why you're seeing the values change after CreateInput returns. If CreateInput implemented a loop, then I would expect the last values assigned to activeStyle and dormantStyle to be used. But even calling CreateInput from a loop will not cause the misbehavior you describe, contrary to the commenter.
Anyway, the solution to this kind of stale data is to use a closure. JavaScript local variables are all bound to the function call scope, no matter if they're declared deep inside the function or in a loop. So you add a function call to force new variables to be created.
function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
while ( something ) {
activeStyle += "blah"; // modify local vars
function ( activeStyle, dormantStyle ) { // make copies of local vars
var inp = document.createElement('input');
inp.id = controlName;
inp.type = type;
inp.style.cssText = dormantStyle;
inp.onfocus = function() { this.style.cssText = activeStyle; };
inp.onblur = function() { this.style.cssText = dormantStyle; };
inp.onclick = whenClicked;
}( activeStyle, dormantStyle ); // specify values for copies
}
return inp;
}
What is the Google Closure's solution for resolving the issues with the this keyword in JavaScript callback functions. It would be so useful in OO style programming.
Is there any conventions or style for OOP in Google Closure???
update
How can I access this.darklayer in ViewportSizeMonitor handler???
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.math.Size');
goog.require('goog.style');
goog.require('goog.dom.ViewportSizeMonitor');
goog.provide('ehsun7b.ajax.AjaxBox');
ehsun7b.ajax.AjaxBox = function (url, containerClass) {
try {
this.url = url;
this.containerClass = containerClass;
var viwportSize = goog.dom.getViewportSize();
this.darklayer = goog.dom.createDom("div", {
"style": "width: " + viwportSize.width + "px;" + "height: " +
viwportSize.height + "px;" +
"background-image: url('css/img/50black.png');" +
"z-index: 1000;" +
"position: absolute;" +
"left: 0px; top: 0px;"
});
var vsm = new goog.dom.ViewportSizeMonitor();
goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
console.log("this: " + this.darklayer);
});
this.container = goog.dom.createDom("div", {
"class": this.containerClass
});
goog.dom.appendChild(this.darklayer, this.container);
goog.dom.setTextContent(this.container, "hello ajax box");
this.show = function() {
goog.dom.appendChild(document.body, this.darklayer);
},
this.hide = function() {
goog.dom.removeNode(this.darklayer);
}
} catch (e) {
console.log("error: " + e);
}
};
I changed my class according to the Closure's style this way:
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.math.Size');
goog.require('goog.style');
goog.require('goog.dom.ViewportSizeMonitor');
goog.provide('ehsun7b.ajax.AjaxBox');
ehsun7b.ajax.AjaxBox = function (url, containerClass) {
try {
this.url = url;
this.containerClass = containerClass;
var viwportSize = goog.dom.getViewportSize();
this.darklayer = goog.dom.createDom("div", {
"style": "width: " + viwportSize.width + "px;" + "height: " +
viwportSize.height + "px;" +
"background-image: url('css/img/50black.png');" +
"z-index: 1000;" +
"position: absolute;" +
"left: 0px; top: 0px;"
});
var vsm = new goog.dom.ViewportSizeMonitor();
goog.events.listen(vsm, goog.events.EventType.RESIZE, function(e) {
console.log("this: " + this.darklayer);
});
this.container = goog.dom.createDom("div", {
"class": this.containerClass
});
goog.dom.appendChild(this.darklayer, this.container);
goog.dom.setTextContent(this.container, "hello ajax box");
} catch (e) {
console.log("error: " + e);
}
};
ehsun7b.ajax.AjaxBox.prototype.show = function() {
goog.dom.appendChild(document.body, this.darklayer);
}
ehsun7b.ajax.AjaxBox.prototype.hide = function() {
goog.dom.removeNode(this.darklayer);
}
goog.bind is the general purpose solution. For example:
goog.bind(this.someFunction, this);
goog.bind(this.someFunction, this, arg1);
goog.bind(this.someFunction, this, arg1, arg2);
The framework is generally designed such that this can be avoided, so it's not common to have to explicitly call goog.bind.
For example, goog.events.EventHandler automatically binds callbacks to the handler you set in its constructor.
var handler = new goog.events.EventHandler(this);
handler.listen(something, 'something', this.someFunction); // no need to bind
The array functions also support a handler argument.
goog.array.forEach(elements, this.someFunction, this);
var items = goog.array.map(elements, this.someFunction, this);
And so on. Most parts of the framework make it pretty easy to do this, it's very well designed for "pseudo-classic" inheritance.
For more details, see http://www.bolinfest.com/javascript/inheritance.php