jQuery Extension accepting a String not just an Object - javascript

This might be a silly question, but I can't seem to find a solution...
I just wanted to make a isNullOrWhiteSpace extension (same name as the .NET one), to determine if a string is '', '0', 0, undefined, null. Nothing crazy.
Now doing it with a typical jQuery extension, it seems it is always looking for a jQuery Object to be passed in. But for in my extension, I need it to work with a simple string, but it doesn't work at all when I do.
$.fn.isNullOrWhiteSpace = function () {
if (['', '0', 0, undefined, null].indexOf($.trim(this)) > -1) {
return false;
}
return true;
};
'testing'.isNullOrWhiteSpace(); // doesn't work
// Uncaught TypeError: Object has no method 'isNullOrWhiteSpace'
What am I missing here??
-- from answers below, turns out it should be simply:
$.isNullOrWhiteSpace, the $.fn. part makes it a jQuery-Object extension as opposed to just a regular extension (like $.isArray(), $.trim() (which I use in my own question... sigh))

If you must hook this to jQuery — and there's really no reason to beyond namespace economy — you would do this:
$.nullOrWhitespace = function(s) {
return !s || !(s.replace(/\s*/, '')); // or something like this; just an example
};
Then call it with
if ( $.nullOrWhitespace( yourString ) ) {
... whatever ...
}

Try String.prototype.isNullOrWhiteSpace = function() {...

$.fn by default sets the context of this to an array of matched elements(when used with a selector). Which you clearly don't need in this case.
$.isNullOrWhiteSpace = function (str) {
return $.inArray($.trim(str), ['', '0', 0, undefined, null]) > -1;
};
This is what most other utility methods do eg: $.inArray, $.trim like we have already used! :)

As far as I know, $.fn.isNullOrWhiteSpace extends jQuery.
If you are extending jQuery you propably need to call the method on a jQuery object.
'testing' is a string but $('testing') would be a jQuery object.
This seems to work:
$.fn.isNullOrWhiteSpace = function () {
if (['', '0', 0, undefined, null].indexOf($.trim(this.selector)) > -1) {
return false;
}
return true;
};
alert($('').isNullOrWhiteSpace());
alert($('testing').isNullOrWhiteSpace());
DEMO

Related

Why use parentheses when returning in JavaScript?

In the Restify framework code I found this function:
function queryParser(options) {
function parseQueryString(req, res, next) {
// Some code goes there
return (next());
}
return (parseQueryString);
}
Why would the author write return (next()); and return (parseQueryString);? Does it need parentheses there and if so, why?
Using parentheses when returning is necessary if you want to write your return statement over several lines.
React.js offers a useful example. In the return statement of the render property in a component you usually want to spread the JSX you return over several lines for readability reasons, e.g.:
render: function() {
return (
<div className="foo">
<h1>Headline</h1>
<MyComponent data={this.state.data} />
</div>
);
}
Without parentheses it results in an error!
More generally, not using parentheses when spreading a return statement over several lines will result in an error. The following example will execute properly:
var foo = function() {
var x = 3;
return (
x
+
1
);
};
console.log(foo());
Whereas the following (without the parentheses) will throw errors:
var foo = function() {
var x = 3;
return
x
+
1
;
};
console.log(foo());
It doesn't need to be that way, but it's valid JavaScript code. Actually it's quite uncommon to see such syntax. I guess it's a personal preference of the author.
Parenthesis are used for two purposes in a return statement.
To support multi-line expression as mentioned in #Andru Answer.
To allow returning object in arrow function like the below:
() => ({ name: 'Amanda' }) // Shorthand to return an object
This is equivalent to
() => {
return { name : 'Amanda' }
}
For more information, please check this article.
https://medium.com/#leannezhang/curly-braces-versus-parenthesis-in-reactjs-4d3ffd33128f
// Create a component named MessageComponent
var MessageComponent = React.createClass({
render: function() {
return (
<div>{this.props.message}</div>
);
}
});
NOTE Why do we need the parentheses around the return statement (line
3)? This is because of JavaScript's automatic semicolon insertion.
Without the parentheses, JavaScript would ignore the following lines
and return without a value. If the JSX starts on the same line as the
return, then parentheses are not needed.
Taken from here.
Just to add to what others have said.
Using brackets around the return value is valid JavaScript, but mostly a bad thing to do.
Mostly bad because it doesn't add anything yet increases the size of the JavaScript which means that there is more to download to the browser. Yes most people have fast broadband connections, but don't lose sight of the fact that everything you put in the JavaScript file needs to be downloaded so avoid unnecessary code bloat. This probably doesn't matter if you use a tool to compact your code (minifier has already been mentioned), but not everyone does.
Sometimes it might aid readability. Hard pressed to think of an example in this case, but if the use of brackets makes your JavaScript clearer to you as the developer and thus easier to maintain then use them - even if it goes against what I said about code bloat.
Why would the author write return (next()); ... ?
Regarding next():
Probably because his function is something like this:
function next()
{
var i=0;
return function (){
// Do something with that closured i....
}
}
Regarding (xxx);:
It is unnecessary. Every minifier will remove it.
Example (uglifyJS):
becomes:
I tried:
var a = function() {
return true || true
}
console.log(a());
//return: true
var a = function() {
return
true || true
}
console.log(a());
//return: undefined
var a = function() {
return (
true || true
)
}
console.log(a());
//return: true
While Andru's answer is popular, it is wrong that parantheses are required for multiline return statement. Here, you can see an object of foo and bar is returned with no parantheses needed.
function foo () {
return {
foo: 'foo',
bar: 'bar',
}
}
console.log(foo())
As long as the return line is not just empty space or linebreak, you can have a multiline return just fine. Otherwise Automatic Semicolon Insertion takeover and break your return statement as demonstrated by Andru.
Regarding your question, I am onboard with Darin's answer.
This may be old but the return () can be used in this way:
function parseQueryString(req, res, next) {
var id = req.param('id');
return (id ? "Foo" : "Bar");
}
Less code, easy to read :)

Defining Javascript function with prototype property

What's wrong with this piece of code?
(function (){
'use strict';
// add hasClass function
String.prototype.hasClass = function (className) {
return this.className.search('(\\s|^)' + className + '(\\s|$)') != -1 ? true : false;
};
console.log(document.getElementById('link').hasClass('test'));
})();
I'd expect it to return true or false, but all I get is
TypeError: document.getElementById("link").hasClass is not a function**
UPD: Thanks guys. Now i get it. I should set method to Object or Element (What is more right?) not String!
document.getElementById('link') doesn't return a String, it returns a DOM element. You could try this instead:-
Element.prototype.hasClass = function (className) {
return this.className.search('(\\s|^)' + className + '(\\s|$)') != -1 ? true : false;
};
console.log(document.getElementById('link').hasClass('test'));
As far as I know, hasClass is not a method of Element, you're likely thinking of the jQuery method, as such you would have to use jQuery and select the element using a jQuery selector. Other frameworks may also have such methods, I believe YUI does as well.
The way to do this is to write a function that receives a DOM element, as the String object has nothing to do with it ;)
A simple example:
function hasClass(element, classcheck){
return element.className.indexOf(classcheck) !== -1;
}
So your code would look like:
(function (){
'use strict';
// add hasClass function
function hasClass(element, classcheck){
return element && element.className && element.className.indexOf(classcheck) !== -1;
}
console.log(hasClass(document.body,'test'));
})();
Obviously, you should be checking that the first argument is actually a DOM element too (quite a lot of different ways to achieve that), but this is the right way to go about it.

How do I override javascript's cloneNode?

This is what I have so far: http://jsfiddle.net/beCVL/5/
This is how I'm trying to override the default cloneNode:
Object.defineProperty(Object.prototype, "cloneNode", {
get: cloneNode2,
set: cloneNode2
});
but it's not working, so, I think Object.prototype doesn't have cloneNode, but Element.prototype doesn't either.
So, which class do I need to use to override cloneNode, assuming my method is correct?
It's a property of Node.prototype https://developer.mozilla.org/En/DOM/Node.cloneNode
Node.prototype.cloneNode = function() {}
However, modifying built in objects may give you grief in the future. If possible, you should create a different function and use that instead, that way, existing code that uses cloneNode won't break.
Try using:
Node.prototype.cloneNode = cloneNode2;
Object.defineProperty is not used for this purpose. Here's an example of a use for it:
var o = {};
Object.defineProperty(o, 'blah', {
'get': function () { return 'asdf'; },
'set': function (x) { alert(x); }
});
alert(o.blah); // alerts 'asdf'
o.blah = 'fdsa'; // alerts 'fdsa'
Apparently, this only works in Chrome.
To solve the actual problem, it should be simple enough to just replace the RGB codes with its equivalent hex code.
function decToHex(a) {
return ('00' + (+a).toString(16)).substr(-2);
}
function replaceRGB(str) {
return str.replace(/rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/, function (_, r, g, b) {
return "#" + decToHex(r) + decToHex(g) + decToHex(b);
});
}
replaceRGB("color: rgb(255, 0, 0)") // "color: #ff0000"
This series of fiddles is a work in progress, but it reimplements cloneNode's functionality. http://jsfiddle.net/beCVL/19/
as of April 4th, 10:53am EST, it needs to work with IE, as IE doesn't have a Node object.
Note, that in IE, prototype functions can't be overridden. So, all instances of cloneNode have to be replaced by a function that determines which version of cloneNode to use.

Testing if value is a function

I need to test whether the value of a form's onsubmit is a function. The format is typically onsubmit="return valid();". Is there a way to tell if this is a function, and if it's callable? Using typeof just returns that it's a string, which doesn't help me much.
EDIT: Of course, I understand that "return valid();" is a string. I've replaced it down to "valid();", and even "valid()". I want to know if either of those is a function.
EDIT: Here's some code, which may help explain my problem:
$("a.button").parents("form").submit(function() {
var submit_function = $("a.button").parents("form").attr("onsubmit");
if ( submit_function && typeof( submit_function.replace(/return /,"") ) == 'function' ) {
return eval(submit_function.replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?"); return false;
}
} );
EDIT 2: Here's the new code. It seems that I still have to use an eval, because calling form.submit() doesn't fire existing onsubmits.
var formObj = $("a.button").parents("form");
formObj.submit(function() {
if ( formObj[0].onsubmit && typeof( formObj.onsubmit ) == 'function' ) {
return eval(formObj.attr("onsubmit").replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?");
return false;
}
} );
Suggestions on possibly how to do this better?
I'm replacing a submit button with an
anchor link. Since calling
form.submit() does not activate
onsubmit's, I'm finding it, and
eval()ing it myself. But I'd like to
check if the function exists before
just eval()ing what's there. – gms8994
<script type="text/javascript">
function onsubmitHandler() {
alert('running onsubmit handler');
return true;
}
function testOnsubmitAndSubmit(f) {
if (typeof f.onsubmit === 'function') {
// onsubmit is executable, test the return value
if (f.onsubmit()) {
// onsubmit returns true, submit the form
f.submit();
}
}
}
</script>
<form name="theForm" onsubmit="return onsubmitHandler();">
<a href="#" onclick="
testOnsubmitAndSubmit(document.forms['theForm']);
return false;
"></a>
</form>
EDIT : missing parameter f in function testOnsubmitAndSubmit
The above should work regardless of whether you assign the onsubmit HTML attribute or assign it in JavaScript:
document.forms['theForm'].onsubmit = onsubmitHandler;
Try
if (this.onsubmit instanceof Function) {
// do stuff;
}
You could simply use the typeof operator along with a ternary operator for short:
onsubmit="return typeof valid =='function' ? valid() : true;"
If it is a function we call it and return it's return value, otherwise just return true
Edit:
I'm not quite sure what you really want to do, but I'll try to explain what might be happening.
When you declare your onsubmit code within your html, it gets turned into a function and thus its callable from the JavaScript "world". That means that those two methods are equivalent:
HTML: <form onsubmit="return valid();" />
JavaScript: myForm.onsubmit = function() { return valid(); };
These two will be both functions and both will be callable. You can test any of those using the typeof operator which should yeld the same result: "function".
Now if you assign a string to the "onsubmit" property via JavaScript, it will remain a string, hence not callable. Notice that if you apply the typeof operator against it, you'll get "string" instead of "function".
I hope this might clarify a few things. Then again, if you want to know if such property (or any identifier for the matter) is a function and callable, the typeof operator should do the trick. Although I'm not sure if it works properly across multiple frames.
Cheers
What browser are you using?
alert(typeof document.getElementById('myform').onsubmit);
This gives me "function" in IE7 and FireFox.
using a string based variable as example and making use instanceof Function
You register the function..assign the variable...check the variable is the name of function...do pre-process... assign the function to new var...then call the function.
function callMe(){
alert('You rang?');
}
var value = 'callMe';
if (window[value] instanceof Function) {
// do pre-process stuff
// FYI the function has not actually been called yet
console.log('callable function');
//now call function
var fn = window[value];
fn();
}
Make sure you are calling typeof on the actual function, not a string literal:
function x() {
console.log("hi");
}
typeof "x"; // returns "string"
typeof x; // returns "function"
You can try modifying this technique to suit your needs:
function isFunction() {
var functionName = window.prompt('Function name: ');
var isDefined = eval('(typeof ' + functionName + '==\'function\');');
if (isDefined)
eval(functionName + '();');
else
alert('Function ' + functionName + ' does not exist');
}
function anotherFunction() {
alert('message from another function.');
}
form.onsubmit will always be a function when defined as an attribute of HTML the form element. It's some sort of anonymous function attached to an HTML element, which has the this pointer bound to that FORM element and also has a parameter named event which will contain data about the submit event.
Under these circumstances I don't understand how you got a string as a result of a typeof operation. You should give more details, better some code.
Edit (as a response to your second edit):
I believe the handler attached to the HTML attribute will execute regardless of the above code. Further more, you could try to stop it somehow, but, it appears that FF 3, IE 8, Chrome 2 and Opera 9 are executing the HTML attribute handler in the first place and then the one attached (I didn't tested with jQuery though, but with addEventListener and attachEvent). So... what are you trying to accomplish exactly?
By the way, your code isn't working because your regular expression will extract the string "valid();", which is definitely not a function.
If it's a string, you could assume / hope it's always of the form
return SomeFunction(arguments);
parse for the function name, and then see if that function is defined using
if (window[functionName]) {
// do stuff
}
Isn't typeof xxx === 'function' the best and the fastest?
I made an bench in wich you can try it out, compared to instanceof and _underscore
Its just seems to be faster than instanceof (using chrome)
It won't trow an error if the variable is not defined
Here a bench: https://jsbench.me/qnkf076cqb/1
Checking the call method on the value seems to be a good enough test. e.g., val.call && val()
> a = () => {}
[Function: a]
> function b() {}
undefined
> c = function(){}
[Function: c]
> d = 2
2
> e = []
[]
> f = {}
{}
> a.call
[Function: call]
> b.call
[Function: call]
> c.call
[Function: call]
> d.call
undefined
> e.call
undefined
> f.call
undefined
Note: Except when it's a class.
Well, "return valid();" is a string, so that's correct.
If you want to check if it has a function attached instead, you could try this:
formId.onsubmit = function (){ /* */ }
if(typeof formId.onsubmit == "function"){
alert("it's a function!");
}
You can always use one of the typeOf functions on JavaScript blogs such as Chris West's. Using a definition such as the following for the typeOf() function would work:
function typeOf(o){return {}.toString.call(o).slice(8,-1)}
This function (which is declared in the global namespace, can be used like this:
alert("onsubmit is a " + typeOf(elem.onsubmit));
If it is a function, "Function" will be returned. If it is a string, "String" will be returned. Other possible values are shown here.
I think the source of confusion is the distinction between a node's attribute and the corresponding property.
You're using:
$("a.button").parents("form").attr("onsubmit")
You're directly reading the onsubmit attribute's value (which must be a string). Instead, you should access the onsubmit property of the node:
$("a.button").parents("form").prop("onsubmit")
Here's a quick test:
<form id="form1" action="foo1.htm" onsubmit="return valid()"></form>
<script>
window.onload = function () {
var form1 = document.getElementById("form1");
function log(s) {
document.write("<div>" + s + "</div>");
}
function info(v) {
return "(" + typeof v + ") " + v;
}
log("form1 onsubmit property: " + info(form1.onsubmit));
log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit")));
};
</script>
This yields:
form1 onsubmit property: (function) function onsubmit(event) { return valid(); }
form1 onsubmit attribute: (string) return valid()
// This should be a function, because in certain JavaScript engines (V8, for
// example, try block kills many optimizations).
function isFunction(func) {
// For some reason, function constructor doesn't accept anonymous functions.
// Also, this check finds callable objects that aren't function (such as,
// regular expressions in old WebKit versions), as according to EcmaScript
// specification, any callable object should have typeof set to function.
if (typeof func === 'function')
return true
// If the function isn't a string, it's probably good idea to return false,
// as eval cannot process values that aren't strings.
if (typeof func !== 'string')
return false
// So, the value is a string. Try creating a function, in order to detect
// syntax error.
try {
// Create a function with string func, in order to detect whatever it's
// an actual function. Unlike examples with eval, it should be actually
// safe to use with any string (provided you don't call returned value).
Function(func)
return true
}
catch (e) {
// While usually only SyntaxError could be thrown (unless somebody
// modified definition of something used in this function, like
// SyntaxError or Function, it's better to prepare for unexpected.
if (!(e instanceof SyntaxError)) {
throw e
}
return false
}
}
if ( window.onsubmit ) {
//
} else {
alert("Function does not exist.");
}
Beware that es6 class is also a function but not callable
class C {}
typeof C === "function" // true
C instanceof Function // true
C() // error
C.call() // error
new C() // okay
new C // okay
A simple check like this will let you know if it exists/defined:
if (this.onsubmit)
{
// do stuff;
}

How do I create methods for an HTML element?

I'm trying to create a simple, small and basic javascript framework just for learning purposes.
But the thing is that i'm allready stuck at the very basics.
I'm trying to do something like this:
$('testdiv').testFunction();
And the code i've written for that:
var elementID;
var smallFramework = {
$:function(id) {
this.elementID = id;
},
testFunction:function() {
alert(this.elementID);
}
};
window.$ = smallFramework.$;
But in return I get:
$('testdiv) is undefined
Can anyone help me with this small and hopefully easy question?
To get the behavior you're expecting, you need the $ function to return an object with a method named testFunction.
Try:
var smallFramework = // an object for namespacing
{
$:function(id) // the core function - returns an object wrapping the id
{
return { // return an object literal
elementID: id, // holding the id passed in
testFunction: function() // and a simple method
{
alert(this.elementID);
}
};
}
};
Of course, there are many other ways to achieve the behavior you desire.
If you're trying to add methods to an HTML element you could do something along these lines.
$ = function( elementId ) {
var element = document.getElementById( elementId );
element.testFunction = function(){
alert( this.id );
return this; // for chaining
}
return element;
}
$('test').testFunction();
Try
smallFramework.$('testdiv');
instead. According to the code you posted, that's where your $ function ended up.
Or alternatively, it looks like you're trying to replicate something like jQuery. You might want to try something like this.
var $ = smallFramework = (function () {
var f =
{
find:function(id) {
f.elementID = id;
return f; //every function should return f, for chaining to work
},
testFunction:function() {
alert(f.elementID);
return f;
}
}
return f.find //the find function will be assigned to $.
//and also assigned to smallFramework.
//the find function returns f, so you get access to testFunction via chaining
// like $("blah").testFunction()
})() //note this function gets called immediately.
this code may look confusing to someone new to JavaScript because it depends heavily on the concept of closures. I suggest that if this doesn't make sense, spend some time at Douglas Crockford's JavaScript website. This is important because the code above will bite if you happen to use this in the find function because this won't be bound to f, as you may expect it to be when you use it from $ or smallFramework.

Categories

Resources