Why is addClass not recognised as a function in this case? - javascript

I'm trying to add a class to a bunch of links whose suffix ends in .pdf as follows:
var pdfs = jQuery("a[href$='.pdf']"); //Choosing .pdf links
pdfs.each(addClass("pdf")); // Adding the class
This doesn't work, however, as the browser console prints this error when I try to reload the HTML file calling the .js file:
ReferenceError: addClass is not defined
Why is this happening?

jQuery allows you to perform it's API methods not only on single elements, but also on collections of elements (which is one of the nice advantages over the native DOM API).
The easiest way to achieve your goal is to capitalize on that:
var pdfs = jQuery("a[href$='.pdf']"); //Choosing .pdf links
pdfs.addClass("pdf"); // Adding the class
jQuery $.each() function is for those cases where you want to do something with each element in the collection that is not available as an API method in jQuery. It expects you pass it a function that gets passed the current element in each iteration as this:
var pdfs = jQuery("a[href$='.pdf']"); //Choosing .pdf links
pdfs.each(function() { console.log(this.href); }) // perform something jQuery doesn't offer as an API method
If you insist on using $.each(), the code is this:
var pdfs = jQuery("a[href$='.pdf']"); //Choosing .pdf links
pdfs.each(function() { $(this).addClass("pdf"); }); // Adding the class

https://api.jquery.com/addClass/
After choosing the pdf links you can directly call the addClass method on the variable pdfs because this is a jquery object and the class will be applied to all the links.
var pdfs = jQuery("a[href$='.pdf']"); //Choosing .pdf links
pdfs.addClass("pdf"); // Adding the class

So... in whole:
$("a[href$='.pdf']").each(function () {
$(this).addClass("pdf");
})

.each needs a function (delegate) for calling it for per item of jQuery result, but func() (in this case: addClass(..)) will call addClass function (that is not defined in current scope) and pass result of calling it to each function.
you can access to addClass function of per item, like this:
pdfs.each(function(index, pdf){
$(pdf).addClass(...);
});
or for all:
pdfs.addClass(...);

addClass(className) is a method of DOM element object. Must be called with element object. when we call addClass() without DOM object reference it look for local function, and thus throw the reference error.
var pdfs = jQuery("a[href$='.pdf']");
pdfs.each(function() {
$(this).addClass( "foo" );
});

Related

Javascript add function call with parameters to button

I would like to add a function call including parameters to a HTML button via javascript. I know there are plenty of questions to this subject but none of the answers i found did work for me.
Note: My HTML and JS are in separate files which are correctly linked (the JS code works)
Problem:
I can add the function call like this:
var $add = $("#add");
$add.click(myFunction);
However $add.click(myFunction(i)); does not work.(Did also try with specific integer)
I have also tried it the following way:
document.getElementById('add').onclick = function() {myFunction(i);};
But like that the function does not even get applied to the button.
My function is defined in the JS file like this:
function myFunction(length) {
//do stuff with length I would notice
}
You can use some thing like function bind or do it using handler:
$add.click(function(e){
myFunction(i);
});

Override javascript library function

Im trying to modify the behavior of the jquery UI spinner, and want to avoid hacking the original js file. Theres a function in the js file called _doSpin that if I modify I can achieve the effect I want (I want it to change the value by a percentage - not like the built in percentage method which presents a real percentage to the user, but I need normal ints to be incremented or decremented by a percentage without the bounds of 100% to 0%).
But I don't want to hack the original file, so I want to override the function from within my page (which uses ui.spinner.js). I cant work out how to get to the namespace of the library file, from within my html page. I've tried loads of tips from stackoverflow already but none seem to work in my case. The library file starts with (function($, undefined) but I can't understand how its defined a namespace for me to define in my html page, so I can 'break in' and override the function.
BTW the function is used internally in the library file, maybe its not possible to override it in this case? I don't want to use it locally in my html page, I call higher methods to do my business, I just need to change how the library works internally.
First off, are you entirely sure that you can't solve your problem by specifying options to the spinner object? It seems that with the min, max and step options you could make the step be any percentage of the range that you wanted at the time you created the spinner or set the range. Here's the doc for the step option.
If this is an internal function (not exposed in a public API or as a method on a public object), then it all depends upon how it is coded. If it is not put into a public namespace and it is defined within some other function, then you can't get at it to redefine it. The internals of a function are not something you can get to from outside the function in Javascript unless they are explicitly make accessible to the public somehow.
If it is in a public API somewhere, then you can just assign a new function to whatever symbol the API is on and that will replace the original function (usually you save the original function first so you can still use it if needed).
We can't really help you more specifically without you showing us the actual code you're wanting to override. FYI, I can't find a function called _doSpin in the jQueryUI source repository, so I don't really know which function in which code you're trying to override.
Edit: In a Google search, I found another version of a jQuery UI spinner that does have a _doSpin() method. In that version the _doSpin() method ends up as a method on the prototype for the spinner widget object (which is a jQuery UI object structure it uses for all its objects). I don't personally have much experience with jQueryUI, but from reading their doc on the widget factory, it sounds like you can inherit from an existing widget and replace methods on the prototype. Or, you could probably hack on the prototype directly - though it would take some doing to figure out how/where jQueryUI stores it or how to get to it.
This did a better job in the end.
<html>
<script type='text/javascript'>
var mainarray = [1,2,3,4,5];
function scrolltxtbox (e) {
var evt=window.event || e;
var delta=evt.detail ? evt.detail*(-120) : evt.wheelDelta;
var targ;
if (evt.target) targ = evt.target;
else if (evt.srcElement) targ = evt.srcElement;
(delta<=-120)?multiplier=0.95:multiplier=1.05;
changeweight(targ.id, multiplier);
if (evt.preventDefault)
evt.preventDefault()
else return false
}
function changeweight(targid, multiplier) {
var u = targid.match(/myspinner(.*)/);
mainarray[u[1]] = mainarray[u[1]]*multiplier;
document.getElementById(targid).value = mainarray[u[1]].toPrecision(3);
}
var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel"
var index;
for (index = 0; index < mainarray.length; ++index) {
document.write('<input type="text" size=6 id="myspinner'+index+'" value='+mainarray[index]+' autocomplete="off"><br>');
if (window['myspinner'+index].attachEvent) {
window['myspinner'+index].attachEvent("on"+mousewheelevt, scrolltxtbox);
} else if (window['myspinner'+index].addEventListener) {
window['myspinner'+index].addEventListener(mousewheelevt, scrolltxtbox, false);
}
}
</script>
</html>
Its probably (definitely!) oververbose, but it works nice.

Javascript retrieve absolute XPATH via ID of Node

Hello am trying to retrieve the XPATH of a document via the ID of the node, I saw this to be a simple matter when looking at the code a simple:
//iframe[#id=key];
But it won't work, I've tried every combination of syntax I can think of and not luck, the print out is "undefined". This is my code
function getNode(htmlURL, filename, xpath, callback){
var key = filename+xpath;
var frame = document.getElementById(key);
frame.addEventListener("load", function(evt){
var value= frame.contentDocument.evaluate(xpath, frame.contentDocument, null,9,null);
if(value!=null){
callback(value);
}
}, false);
frame.contentWindow.location.href = htmlURL;
}
function init(htmlURL, filename, xpath){
getNode(htmlURL, filename, xpath, function(node) { console.debug(node.outerHTML); });
}
Am trying to get the xpath inside the iframe, so I thought I'd have to point it to the xpath to the iframe first
If you want to find an element inside of an iframe then you need to use the evaluate method on the document in the iframe e.g.
frame.contentDocument.evaluate(xpath, frame.contentDocument, null,9,null)
But if you set the src to load an HTML document don't expect to be able to access nodes in the document in your code setting the src, instead set up an onload event handler to wait until the document has been loaded. In the event handler you can then access the nodes in the loaded document.
You are getting undefined because your xpath syntax translates to a code comment in JavaScript.
What you probably want is:
var finalxpath = "//iframe[#id=key]";
Note the quote characters which makes your xpath a string literal value.

extend a javascript option to add functionality

I need to call "MyOtherFunction" when "MyFunction"(which creates an element) completes, without MyFunction knowing what MyOtherFunction is.
The reason I need this is for extension of a jquery powered fileupload User Control that is used in several places with different functionality. A specific page shows a header and file count for it, and when the upload completes, I need to modify the file count according to how many files are displayed(by created elements) I thought :
$(UserControl).on(MyFunction, UploadElem, MyOtherFunction);
but this route is not accomplishing anything. The most I can alter the User Control is add in a function call, but without effecting the original user control functionality.
I'm not sure if because MyFunction isn't an event and doesn't bubble up or if it just isn't possible to use a defined function as a parameter of .on() is the reason I cannot get this code to work. Any suggestions?
Easiest way I can think of, is duck punching respectively hooking that method:
var _oldMyFunction = MyFunction;
MyFunction = function() {
_oldMyFunction.apply( this, arguments );
MyOtherFunction();
};
I managed to solve my own issue, but the context is important for the answer:
// Using a Global JavaScript object I created:
GlobalNameSpace.ExtensionFunction = function(oParam1, oParam2, oParam3)
{
/// <summary>All parameters are optional</summary>
return; // For instances when it is not being overwritten, simply return
}
//In the Code for the user control:
GlobalNameSpace.UploadControl.UploadComplete(oSender, oArgs)
{
///<summary>Handles the Upload process</summary>
// process the upload
GlobalNameSpace.ExtensionFunction(oSender, oArgs);
}
//and finally in the code to extend the functionality
GlobalNameSpace.Page.Init
{
///<summary>Initializes the page</summary>
// redefine the extension function
GlobalNameSpace.ExtensionFunction = function(oSender, oArgs)
{
GlobalNameSpace.Page.Function(oSender, oArgs);
}
}
This allows me to extend anything I need it to without polluting my objects, and having something generic already existing to call on to make my changes. This solution solves my problem of needing a onCreate function for the elements I create to represent my uploaded items to trigger the header displaying the number of files. Very useful

How to update multiple elements with one MooTools Request.HTML call

Does anyone know if, using one Request.HTML call from MooTools, it is possible to somehow update more than one element in a webpage? The current call I have is:
var req = new Request.HTML({update: $('content')}).get('../latest_events');
This updates the content div in my page with the "../latest_events" page. Is there a way to update other divs with the "../latest_events" page using this same call, or do I have to just use separate calls?
Yes, you can do whatever you want with the request data after you've obtained it. Just add a success event function to your Request.HTML options and handle the responseText by hand. Documentation about the events available to Request.HTML is available here:
http://mootools.net/docs/core/Request/Request
Always remember to check if a Mootools class extends another (it'll be noted at the top of the class). Typically you'll have to go all the way up the class tree to find the basic events associated with the class (as is the case with Request.HTML).
You should use the addRequests Method from Request.Queue Class from mootools :
var req = new Request.HTML({update: $('content')}).get('../latest_events');
var req2 = new Request.HTML({update: $('content2')}).get('../new_events');
myRequestQueue.addRequests({
req1: req,
req2: req2
});

Categories