In chrome console, I have set some breakpoints in code of the sources. Those are set in a class for which an instance of this class was instantiated at loadtime. :
var SearcherBlock = function(n) {
function t() {
n.apply(this, arguments);
this.CurrentData = null;
this.onInput = null;
this.SearchInput = document.getElementById(this.BlockUniqueID + "_SearchInput");
this.SearchResults = document.getElementById(this.BlockUniqueID + "_Search_Results");
this.SearchResultsTitle = document.getElementById(this.BlockUniqueID + "_ResultsTitle");
this.onDocumentClick = this.onDocumentClickHandler.bind(this);
this.MinSearchStringLength = SearchController.getMinSearchStringLength(this.Configuration.LanguagesFor2SymbolSearch)
}
var i = {
destroyed: !0
};
return $.extend(t.prototype, n.prototype),
t.prototype.activate = function() {
n.prototype.activate.call(this);
this.onInput = this.textChange.bind(this);
this.SearchInput && this.SearchInput.addEventListener("input", this.onInput, !1);
this.tooltipsInit()
}
t.prototype.textChange = function(n) {
var t = n.srcElement || n.target;
if (this.SearchResultsTitle.innerHTML) {
... }
}
}
So now when I am at a breakpoint in this class whose instance I would like to achieve is triggered in this class. I would like to figure out a way to access this instance, like window.something.something - how can I do this if possible?
The reason is that when I call the function hasText() by window.hasText(), it complains because all properties of the this that is being used in the function are undefined. Therefore, I would like to have a way of accessing the instantiated object.
Related
Im struggling to find a way to get the properties Override & Justification available outside of the function. The code is:
self.CasOverridesViewModel = ko.observable(self.CasOverridesViewModel);
var hasOverrides = typeof self.CasOverridesViewModel === typeof(Function);
if (hasOverrides) {
self.setupOverrides = function() {
var extendViewModel = function(obj, extend) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
extend(obj[property]);
}
}
};
extendViewModel(self.CasOverridesViewModel(), function(item) {
item.isOverrideFilledIn = ko.computed( function() {
var result = false;
if (!!item.Override()) {
result = true;
}
return result;
});
if (item) {
item.isJustificationMissing = ko.computed(function() {
var override = item.Override();
var result = false;
if (!!override) {
result = !item.hasAtleastNineWords();
}
return result;
});
item.hasAtleastNineWords = ko.computed(function() {
var justification = item.Justification(),
moreThanNineWords = false;
if (justification != null) {
moreThanNineWords = justification.trim().split(/\s+/).length > 9;
}
return moreThanNineWords;
});
item.isValid = ko.computed(function() {
return (!item.isJustificationMissing());
});
}
});
}();
}
I've tried it by setting up a global variable like:
var item;
or
var obj;
if(hasOverrides) {...
So the thing that gets me the most that im not able to grasp how the connection is made
between the underlying model CasOverridesviewModel. As i assumed that self.CasOverridesViewModel.Override() would be able to fetch the data that is written on the screen.
Another try i did was var override = ko.observable(self.CasOverridesViewModel.Override()), which led to js typeError as you cannot read from an undefined object.
So if anyone is able to give me some guidance on how to get the fields from an input field available outside of this function. It would be deeply appreciated.
If I need to clarify some aspects do not hesitate to ask.
The upmost gratitude!
not sure how far outside you wanted to go with your variable but if you just define your global var at root level but only add to it at the moment your inner variable gets a value, you won't get the error of setting undefined.
var root = {
override: ko.observable()
};
root.override.subscribe((val) => console.log(val));
var ViewModel = function () {
var self = this;
self.override = ko.observable();
self.override.subscribe((val) => root.override(val));
self.load = function () {
self.override(true);
};
self.load();
};
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
I have this class like so :
https://jsfiddle.net/0sh7fLtp/
When I create a new object of this class, my local variable can't be seen even when I assign to window in the class:
function Hilitor() {
var excat;
this.setMatchType = function(type) {
if (type == "exact"){
window.excat = true;
}
};
this.setRegex = function(input) {
alert(excat);
};
this.apply = function(input) {
this.setRegex();
};
}
and this is how i call it :
var myHilitor = new Hilitor();
myHilitor.apply();
myHilitor.setMatchType("exact");
Not sure I completely understand your question but you are trying to compare a variable "excat" to string "excat"... See this fiddle to how you can make your var a string and then get desired output..
https://jsfiddle.net/shemdani/0sh7fLtp/5/
var myHilitor = new Hilitor();
myHilitor.setMatchType("excat");
myHilitor.apply();
function Hilitor()
{
var excat;
this.setMatchType = function(type)
{
if(type == "excat"){window.excat = true;}
};
this.setRegex = function(input)
{
alert(window.excat);
};
this.apply = function(input)
{
this.setRegex();
};
}
Two main problems
1) Your var exact inside the function is not a global variable and so not accessible on the window object. (But that's a good thing).
Your code will work if you remove window.exact for just exact
this.setMatchType = function(type)
{
if(type == "exact"){excat = true;}
};
2) You are also calling apply before you call setMatchType. Switching them like this works:
var myHilitor = new Hilitor();
myHilitor.setMatchType("excat");
myHilitor.apply();
Working example
In my Javascript there is a parent Base class that will be extended by others.
I'd like to:
define in it a method getSubject() that could be common to all children, when it is not overridden.
make getSubject() rely on a Base property, that eventually could be overridden as well.
always call the getSubject() method in the context of the caller (the children classes or the Base class)
To clarify (hopefully) what I want to do..
I wrote (non-valid) PHP code as an example.
<?php
class Base
{
const SUBJ_SELECTOR = 'input';
public function init()
{
$this->wrapper = ....;
$this->subject = $this->getSubj();
if ($this->subject.attr('data-active')) {
// ... do stuff
}
}
public function getSubj() // One definition in parent
{
return $this->wrapper.find(self::SUBJ_SELECTOR);
}
}
class Select extends Base
{
const SUBJ_SELECTOR = 'select' // Override just the selector
}
class Textarea extends Base
{
const SUBJ_SELECTOR = 'textarea[name=foo]';
public function getSubj() // Eventual overriding
{
$subjs = $this->wrapper.find(self::SUBJ_SELECTOR);
foreach ($subjs as $subj) {
if ($subj.attr('multiline')) {
return $subj;
}
}
return $subjs;
}
}
I'd like to achieve the same result with Javascript (and JQuery eventually).
Actually I wrote some code (that I still didn't test) as a sketch:
var Base = function() {
this.options = {};
this.subject_selector = 'input';
this.wrapper = $('.container');
};
Base.prototype.getSubject = function() {
return this.wrapper.find(this.subject_selector);
}
Base.prototype.init = function() {
subj = this.getSubject();
if(subj.attr('data-active')) {
// ... do stuff
}
}
var Select = function() {
this.subject_selector = 'select';
}
Select.prototype = new Base();
Select.prototype.constructor = Select;
var Textarea = function() {
this.subject_selector = 'textarea';
}
Textarea.prototype.getSubject = function() {
subjs = this.wrapper.find(this.subject_selector);
for (var i = subjs.length - 1; i >= 0; i--) {
if(subjs[i].attr('multiline')) {
return subjs[i];
}
};
return subjs;
}
Textarea.prototype = new Base();
Textarea.prototype.constructor = Textarea;
Would it work correctly? Is this a proper use of the inheritance model?
Am I callling the method in the right way and will I get the expected result when executing the init() method?
I'm trying to call a method cardSelection() from a function game() but instead I'm getting an error report which throws back to me the whole function with a "has no method cardSelection()" The idea is to access the method through the click of a button, which HTML tag is as follows:
<img id="PlayerCard0" class="card" src="images/Cards/Mario.png" alt="Mario" title="Mario" onclick="game.cardSelection('PlayerCard0')">
I'm not posting the whole Javascript as I believe this to be the case of a mere declaration error, anyhow, game() and cardSelection() were declared as follows:
function game()
{
...
this.cardSelection = function(card)
{
var cardElem = document.getElementById(card);
var id = cardElem.getAttribute("id");
var call = document.getElementById("call");
var select = function(card)
{
var found = 0;
for (var card = 0, totalCards = 5; card < totalCards; card++)
{
if (document.getElementById("PlayerCard" + card + "selected"))
{found++}
}
if (found == 0)
{
call.setAttribute("onclick", "changeHand()");
call.childNodes[0].nodeValue = "Change";
}
if (found < 3)
{
id += "selected"
setAttributes(cardElem,
{
"id" : id,
"style": "position: relative; top: 1em;",
"onclick" : "cardSelection('" + id + "')"
});
}
else { return; }
}
var unselect = function (card)
{
cardElem.removeAttribute("style");
id = id.replace("selected","");
setAttributes(cardElem,
{
"id" : id,
"onclick" : "cardSelection('" + id + "')"
});
var cardNumber = 0;
var found = false;
while (cardNumber < 5 && !found)
{
if (document.getElementById("playerCard" + cardNumber + "selected"))
{found = true;}
cardNumber++;
}
if (!found)
{
call.setAttribute("onclick", "compareHands()");
call.childNodes[0].nodeValue = "Hold";
}
}
if (id.indexOf("selected") >= 0){unselect(card);}
else {select(card);}
}
...
}
How game() is called:
window.onload = function openingScreen()
{
var startGame = document.createElement("a");
startGame.setAttribute("onclick", "game()");
startGame.appendChild(document.createTextNode("Play"));
window.table = document.getElementById("table");
table.appendChild(startGame);
}
The problem you are experiencing is the result of confusion about Objects/Classes/Instances in javascript.
The critical point for you on this issue is the difference between new game() and game();
var foo = new game()
tells the JS engine to create a new object
point that object's Prototype (not prototype) at game's prototype
and then invoke the function game, but for the sake of the body of that function this will refer to the created object.
If the function doesn't return an object, assign our created object to foo (otherwise assign the function's return value to foo
Inside the body of your game function, you have this.cardSelection = function (....
If you simply invoke game as a function, so just game(), without the new keyword, this inside the body of the function will be the window object! So you'll add cardSelection to the window object.
Also importantly: game.cardSelection() is looking for a function named cardSelection as a property on the function game.
Here's an example of using that style that would work:
var foo = function () {
//do interesting stuff
}
foo.bar = function () {
//do interesting stuff related to foo
}
foo.bar();
What you seem to be expecting would need to be written this way:
var game = function () {
this.cardSelection = function () {
//perform card selection!
}
}
var aGame = new game();
aGame.cardSelection();
Or, if cardSelection does not need access to any private properties of the game, it could be written more efficiently as
var game = function () {
//setup the game
};
game.prototype.cardSelection = function () {
//perform card selection
};
var aGame = new game();
aGame.cardSelection();
I cannot find an proper example for the love of my life on how to do this or even if this is possible. Based on my pieced together understanding from fragments of exmaples, I have come up with the following structure
var t = function()
{
this.nestedOne = function()
{
this.nest = function()
{
alert("here");
}
}
}
t.nestedOne.nest();
However this is not working (obviously). I would greatly appreciate if someone could point me in the right direction!
That is simply done with:
var t = {
nestedOne: {
nest: function() {
alert('here');
}
}
};
Your code otherwise doesn't make sense. this inside function doesn't refer to the function itself, it refers to the object context that the function is invoked in. And you are not even invoking the functions in your code.
If I say obj.func() then this inside func will be obj for that call. So assigning this.asd = true will assign true to that object's "asd" property.
If you wanted to do a nested class, it looks very different:
ClassA = (function() {
function ClassA() {
}
ClassA.prototype.method1 = function() {
};
function ClassB() {
}
ClassB.prototype.method1 = function() {
};
return ClassA;
}())
only ClassA can now make instances of ClassB. This should achieve same goals as nested classes in java.
See http://jsfiddle.net/CstUH/
function t(){
function f(){
this.nest = function()
{
alert("here");
}
}
this.nestedOne = new f();
}
var myt=new t();
myt.nestedOne.nest()
Edit 1:
You can also use
new t().nestedOne.nest()
instead of
var myt=new t();
myt.nestedOne.nest()
(http://jsfiddle.net/CstUH/1/)
Edit 2:
Or even more condensed:
function t(){
this.nestedOne = new function(){
this.nest = function(){
alert("here");
}
}
}
new t().nestedOne.nest()
http://jsfiddle.net/CstUH/2/
In JS functions are prime class objects, and you can access them directly in the code [i.e. without using reflection or so].
The code you put inside t body would be performed when actually executing t:
t();
You wrote t.nestedOne,nest(), but t has no nestedOne property - you should do like this:
var t = {
nestedOne : {
nest : function()
{
alert("here");
}
}
};
t.nestedOne.nest();
I advice you to have a trip on John Resig's Learning Advanced JavaScript tutorial, it was very enlightening for me.
A simple callback handler I wrote today as an example of how I do deep nesting. I apologize if it's not the bees knees when it comes to code style, it made the concept a little clearer for me.
function test () {
this.that = this;
this.root = this;
this.jCallback = new Array(new Array()); // 2d
this.jCallbackCount = -1;
this.str = "hello";
// Callback handler...
this.command = {
that : this, // let's keep a reference to who's above us on the food chain
root : this.root, // takes us back to the main object
// add : function() { var that = this; console.log(that.that.str); },
add : function(targetFnc, newFunc) {
var that = this;
var home = that.that; // pretty much root but left in as an example of chain traversal.
var root = this.root; // useful for climbing back up the function chain
// console.log(that.that.str);
home.jCallbackCount++;
// target, addon, active
home.jCallback[home.jCallback.length] = { 'targetFunc' : targetFnc, 'newFunc' : newFunc, 'active' : true, 'id': home.jCallbackCount};
console.log('cbacklength: ' + home.jCallback.length);
console.log('added callback targetFunction:[' + targetFnc + ']');
return home.jCallbackCount; // if we want to delete this later...
},
run : function(targetFnc) {
var that = this;
var home = that.that;
console.log('running callback check for: ' + targetFnc + ' There is : ' + (home.jCallbackCount + 1) + 'in queue.');
console.log('length of callbacks is ' + home.jCallback.length);
for(i=0;i < home.jCallback.length - 1;i++)
{
console.log('checking array for a matching callback [' + targetFnc + ']...');
console.log('current item: ' + home.jCallback[i]['targetFunc'] );
if( home.jCallback[i]['targetFunc'] == targetFnc )
{
// matched!
home.jCallback[i]['newFunc']();
}
// console.log(that.that.jCallback[i].targetFunction);
}
}
};
}
test.prototype = {
say : function () {
var that = this;
console.log('inside');
// that.command('doSay');
that.command.run('doSay');
console.log(that.str);
}
} // end proto
// BEGIN TESTING **************************************************************************
// BEGIN TESTING **************************************************************************
// BEGIN TESTING **************************************************************************
var testing = new test();
testing.command.add('doSay', function () { console.log('213123123'); } );
testing.command.add('doSay', function () { console.log('12sad31'); } );
testing.command.add('doSay', function () { console.log('asdascccc'); } );
testing.say();
live:
http://jsfiddle.net/Ps5Uf/
note: to view console output, just open inspector in chrome and click on the "console" tab.