This is one of the first time's I'm looking at javascript, so please excuse the newbish question.
I'm trying to read the code for a specific function on a website that is of interest to me. I didn't write anything for the website, so cannot really comment on the general structure. This is almost like reverse engineering. Where it's called (in a js/main.js) looks like:
$(document).ready(function() {
$('#search').funcA();
From what I understand this is saying from the file/class or whatever that comesf rom the id search, call funcA. My questions is: how do I see the file that is called with #search?
funcA is almost certainly a jQuery plugin (or part of jQuery itself). The first thing I would try in your situation is searching for "jQuery funcA" on Google.
Whether or not it is actually part of jQuery, you can see the source for that function by running:
$('#search').funcA
in a REPL, such as your browser's console, or:
console.log( $('#search').funcA );
as long as the toString function for that function hasn't been overwritten and it is not a reference to a native function.
funcA appears to be defined as a jQuery method; try
console.log($.fn.funcA)
Open javascript console in the same browser window (I used chrome) that is displaying the page that contains that code. Then just execute this line:
> $('#search').funcA
You should see the body of funcA. Random example output when I did $("#myownid").show:
function funcA (a,b,c){var d,e;if(a||a===0)return
this.animate(cu("show",3),a,b,c);for(var
g=0,h=this.length;g
...
If you manage to see the body of the function, you should be able to infer likely sources (or post them here and we should be able to point you further)
The console.log suggestions here are nice use of Function.prototype.toString (and in some browsers some console magic), but I'd use debugger instead. Chrome has quite nice debugging tools for stuff like this and the debugger statement will get you there with ease.
var test = $('#search').funcA;
debugger;
Open the console and start investigating. When the execution of your code hits that breakpoint, you'll see handy tools like this
Right-clicking test there should also give you the option to "Show function definition" which will show you where the function was actually defined as source code.
And if you want to investigate even further from there, you can always set similar breakpoints right from the Chrome dev console.
Short version: Open the console and run $("#search") it will return a jquery object containing the dom node that has an id of search.
Long version:
$("something")
Is jquery (a java script library) for select elements by css selector returning a jquery object.
https://learn.jquery.com/using-jquery-core/selecting-elements/
$(document).ready(function() {
Is jquery for when my document (basically the page) is ready for me to muck with run this anonymous function.
https://learn.jquery.com/using-jquery-core/document-ready/
$('#search').funcA();
Selects a set of elements, in this case the single element with id "search" and then run funcA on each of them using the element as the scope. So it would run funcA on the element with ID "search" with the search node being the value of the special scope variable (scope is referenced through the key word "this", it can get rather complex).
So in essence what your seeing is:
When my document is ready find the search element and run my function funcA on it.
Related
I want to modify the output of the functions (just say RANDOM examples, apologies for any code mistakes):
ng-if=!pfile.isgame
ng-if=! pfile.examplefile
-from false to true before it even has the page has any chance to drop any code on the page. How can I make it so I can append code to the page to the very beginning of the page to force every output of these particular functions to go true, on a live page?
This is definitely possible, I'm not sure where the function would be however the elements you can actually see the arguments on the page and it doesn't not look server sided at all, its just how its done. I read many articles but it many of them have not really helped me.
I am aware of Event Listener Breakpoints, its just the problem if I'm choosing the right one.
Thank you and I really appreciate it just if you can please dum down the explanation for me as even though I do understand HTML and JavaScript to an OK standard, I am still a massive beginner. This is something I always wanted to try out.
Hopefully I have understood your question correctly. There are a couple of options and the answer will depend on whether the functions are declarations or expressions.
If they are declarations, they get hoisted to the top on first pass, so that by the time your code begins execution, the function already exists and you can overwrite it early on.
If it's a function expression, you have to wait until the function expression has been created.
Example 1 (Function Declaration):
I have a function declaration on my page, which returns true if there is a remainder in the calculation, otherwise false. I execute it on page load. The output is false here:
function hasRemainder(first, second) {
return (first % second != 0);
}
console.log(hasRemainder(10, 5));
false
I have now added the Script First Statement breakpoint in DevTools, so that the debugger breaks before any script is run:
I re-open the page and the execution pauses. I now run the following code in the Console tab to override the hasRemainder function so that it always returns true:
hasRemainder = function() {
return true;
}
Finally, I click Play to continue execution. You can long click to select Long Resume, which skips breakpoints for 500ms so that you don't get caught for very single breakpoint thereafter.
true
The output this time is true as you would expect.
Example 2 (Function Expression):
We can't rely on the early breakpoint this time because the function won't exist yet. We need to add the breakpoint just after the function expression has been created.
Search for the functions using Cmd+Opt+F (Mac) or Ctrl+Shift+F (Windows).
When you are in the file with the function expression, put a breakpoint at the end of the function. When the debugger pauses, run the overriding function into the Console, and then press play to continue execution.
I am trying to make sense of the onchange event of bootstrap-multiselect. In particular, I am trying to understand the function syntax and parameters.
$('#example-onChange').multiselect({
onChange: function(option, checked, select) {
alert('Changed option ' + $(option).val() + '.');
}
});
How to know what does the three parameters in the function mean? Where will I get these three parameters? I also tried looking at the code https://github.com/davidstutz/bootstrap-multiselect/blob/master/dist/js/bootstrap-multiselect.js#L263 but couldn't make much sense of it.
I know using alerts that in this function option refers to the selected option, checked shows whether the option was checked or unchecked. I keep getting undefined when doing console.log(select) inside the function, so not sure what does that mean.
Question: How to understand function parameters and syntax like these? This is just an example but knowing a generic procedure will help me decode other similar functions in future.
In short, it seems the library doesn't actually provide the select option.
In general, in situations where the documentation isn't very precise, the technique I often apply is to console.log the arguments, then inspecting what each of them look like.
In this situation, when doing:
$('#example-onChange').multiselect({
onChange: function(option, checked, select) {
console.log(arguments);
}
});
... I got the following output:
... from this you can see two arguments are provided. The first is the jQuery object of the option that was clicked. The second (you can assume) is a boolean as to whether the option is selected or not.
You can also see no select (3rd argument) was provided.
Another approach you can take is to search the source code, like you did; but I'd recommend finding where the function was called, rather than where it was defined. By searching for onChange in the source code, you can see onChange is called at least 3 times.
this.options.onChange($option, checked);
this.options.onChange($option, true);
this.options.onChange($option, false);
... none of which provide a 3rd argument. I say at least 3 times here, because it can be hard sometimes (particularly in large libraries) to find all call sites, since developers can mask them in all sorts of weird and wonderful ways
Other techniques you can use:
Setting a breakpoint within your handler function (either using the "breakpoint" functionality of your dev. tools, or via the debugger statement), triggering the handler, then following the callstack (again, using developer tools) to examine the call site, and to see what variables are provided.
Opening an issue on the respective GitHub project. You'll find plenty of library owners are more than happy to help.
Unfortunatly, all Javascript libraries must have a very robust documentation.
Moreover, Javascript is a dynamically typed language, so there is no informations about the required types for the formal parameters. It make libraries more difficult to understand without good documentation.
In order to quickly understanding, with experience, there is some thinking mecanisms which can be used. For example, the parameters of an event's delegate provide informations on the elements on which it occurs. It's like these parameters are values returned to you.
In your example, there is chance that option, checked and select are concerned by the option's element in the multiselect defined in #example-onChange which was changed (onChange).
Example 1 :
onClose:function(success)
{
//TODO
}
In this case, "success" should mean : this parameter is true if closing on my element has succeeded else "success" is false.
Example 2 :
afterSave:function(success, filename)
{
}
In this case, "filename" should be the filename of the saved element after perform save's action.
I doing my best for writting correct english, I hope it's understandable.
The reason I want to do this is kind of complicated, but long story short, you can do window[myString]=function hello(){}. Is there a way to do var hello=function [myString](){}?
The reason I want to do this is because I am creating a class generator in javascript. The problem is, I can only name the variable that I assign the constructor to, I can't actually name the class itself. So if instantiate a bunch of instances of my generated class, chrome dev tools doesn't know what the instance is, so it calls the object (anonymous function) instead of its class name. This really grinds my gears.
Here's an example of what I'm trying to do. Copy and paste into Chrome's dev tools:
function Person(name){this.name=name;};
Person.initChildClass=function(className,talkMethod){
window[className]=function(){Person.apply(this,arguments)}
window[className].prototype.talk=talkMethod;
}
Person.initChildClass("PoliceMan",function(){alert("I am a police man")});
Person.initChildClass("LittleBoy",function(){alert("googoogaagaa");});
var cop=new PoliceMan("Bob");
cop;
Copy and paste my code into the dev tools (Chrome) and you will see that it says window.(anonymous function) rather than "Cop" for the cop. How do I make it say "Cop"?
Try
func.displayName = "whatever";
but it may not work in all browsers. See Function.displayName : and same thing in Chromium
I have what looks like to me to be a simple variable assignment not working.
This code is in jQuery, for the context see here.
I'm calling:
$('#foo').on('someEvent', eventHandlerFn);
And I get this issue within the jQuery on function. Here's the starting point:
As you can see from the console below the code, selector is set the my eventHandlerFn and the fn variable is undefined. This is as expected.
On line 3509, the value of selector is assinged to fn. So, the value of fn should be same as the value of selector, no??
See below - selector is defined, as expected, but fn is still undefined. Why?
The end result is that my event handler is never registered.
The code runs well as shown in the following two screens (the issue is on how chrome sets the context to the console)
It looks like console has access to the variable at definition time (in this case the passed parameters) and not the live values as you run the code
Before the swap
After the swap
I'm not seeing any problem with this jsFiddle. Feel free to edit the jsFiddle to get it to look more like your code.
Can you try putting in console.log(fn); after line 3510 and rerunning? Maybe it's just a problem with the debugger?
This seems to be an issue with the debugger in Chrome - either a material problem or just a nuance of the debugger that I don't understand. fn does have a value toward the end of the call, but not where the breakpoint is.
I'm updating an existing website running on Expression Engine. So far, I've stayed away from any code I didn't write or couldn't understand. I recently must have altered some bit of code someplace (helpful, I know) and now a block of JS I didn't write is causing an error that seems to bypass the document.ready() event. The window.load() event however is still taking place.
In the Chrome DevTools Console, the error "Uncought TypeError: Cannot call method 'replace' of UNDEFINED" points to the definition of a function "fixedEncodeURIComponent" pasted below.
$("#MessageContainer.Counted").counter({
type: 'char',
goal: 250,
count: 'down'
}).change(function(){
var TEMP = fixedEncodeURIComponent($(this).val());
$("#Message").val(TEMP);
});
var TEMP = fixedEncodeURIComponent($("#MessageContainer.Test").val());
$("#Message").val(TEMP);
function fixedEncodeURIComponent (str) {
str=str.replace(/"/g, '');
return encodeURIComponent(str).replace(/[!'()*]/g, escape);
}
As I interpret the error, this function is being passed a variable that is not a string. I added an alert(str) to the function definition and the result was UNDEFINED as I expected. The first of several unknowns for me is which call to the function 'fixedEncodeURIComponent' is being passed a bad variable. I assume that it's the first call, but that's just a guess. It so happens that this first call contains a syntax I have never encountered before. I don't know how to interpret what happens when $(this) is passed as a function argument.
Any insights would be greatly appreciated. Also, if there's more information you need please let me know. The client's site is password protected but I can include any code you request.
Thank you.
I'm taking a guess that the }); on line 3 is exiting a document.ready context. If that's the case then your second call to fixedEncodeURIComponent may be getting called before the DOM is even loaded.
Start by wrapping
var TEMP = fixedEncodeURIComponent($("#MessageContainer.Test").val());
$("#Message").val(TEMP);
in a
$(function() {
// code
});
block. If that doesn't work, check that #MessageContainer.Test actually matches an element. Since this is code you inherited, the class name "Test" clues me in that the block in question might be a remnant of someone trying to debug an issue and maybe it should have been removed.
I suspect $("#MessageContainer.Test") since it looks like its supposed to be an ID selector instead of what it actually is when jQUery parses it(which is an ID selector combined with a class selector). $("MessageContainer\\.Test") allows you to select an element with ID MessageContainer.Test