jQuery return multiple function - javascript

so, i have the following js:
function RHL(a,b,c)
{
return rx.removeClass(a).addClass(b);
return rhpfc.html(parseInt( rhpfc.html() ) -1 );
}
I am having a bit of difficult time with the formatting and syntax.
How do I combine both lines under one return. Also, I want to have two options: -1 or +1. So, I thought I would make - or + as c.
what kind of bracket do I need? (ie. 'c'1)

function RHL(a,b,c){
return [
rx.removeClass(a).addClass(b),
rhpfc.html(parseInt( rhpfc.html() ) -1 )
];
}
then you will need to use the index 0 or 1 to use the return value..
var rx = RHL(a,b,c)[0];
or
var rhpfc = RHL(a,b,c)[1];

Related

JQuery index() - Which way around?

In the following piece of code:
$('body').on('click', onClickSelector, function(e) {
console.log($(this).index(onClickSelector));
console.log($(onClickSelector).index(this));
}
Both logs seem to give the correct index value. That is, the index of this, within the onClickSelector collection.
But which is technically the correct way to get that value? Or are the two interchangeable? Also, are there any issues that could arise from using one over the other?
But which is technically the correct way to get that value?
They're interchangeable in that instance (since you don't already have the set of matches handy). If you look at the jQuery code under the covers, which looks like this:
index: function( elem ) {
// No argument, return index in parent
if ( !elem ) {
return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}
// Index in selector
if ( typeof elem === "string" ) {
return indexOf.call( jQuery( elem ), this[ 0 ] );
}
// Locate the position of the desired element
return indexOf.call( this,
// If it receives a jQuery object, the first element is used
elem.jquery ? elem[ 0 ] : elem
);
},
...they end up being the same thing: A call to the internal indexOf passing in a set and an element to find.

Javascript toFixed behaviour with substraction

I'm manipulating a lot of numbers in my application. For this particular case, here is what I do : I retrieve two lists of numbers, I do an average for each of these list, then I substract the two average. To avoid average like 3.333333333333 I use .toFixed(3) on my results.
Here is what it looks like :
// I found this function somewhere on Stackoverflow
Array.prototype.average = function() {
if(this.length == 0){
return 0;
}
else{
return this.reduce(function (p, c) {
return p + c;
}) / this.length;
}
};
sumHigh = [ 10.965, 10.889, 10.659, 10.69, 10.599 ]
sumLow = [ 4.807, 3.065, 2.668, 2.906, 3.606, 4.074, 4.153 ]
// Ok normal
console.log(sumHigh.average()) // 10.760399999999999
console.log(sumLow.average()) // 3.6112857142857138
// Ok normal
console.log(sumHigh.average().toFixed(3)) // "10.760" Does the ".." has anything to do with my problem ?
console.log(sumLow.average().toFixed(3)) // "3.611"
// So here I have my two average values with no more than 3 numbers after the comma but it is not taken into account when substracting these two numbers...
// Not Ok, why 10.760 - 3.611 = 7.148999999999999 ?
console.log(sumHigh.average().toFixed(3) - sumLow.average().toFixed(3)) // 7.148999999999999
console.log(parseFloat(sumHigh.average().toFixed(3)) - parseFloat(sumLow.average().toFixed(3))) // 7.148999999999999
// Just as an example, this is working
console.log(parseFloat(sumHigh.average().toFixed(3)) + parseFloat(sumLow.average().toFixed(3))) // 14.371
console.log(parseFloat(sumHigh.average()) + parseFloat(sumLow.average())) // 14.371685714285713
Can someone explain this behaviour?
Why substraction is not working while addition is?
Ok I know I can solve my problem with :
console.log((sumHigh.average() - sumLow.average()).toFixed(3)) // "7.149"
But that doesn't explain this behaviour.
Thanks

lack of identity between jQuery selector and jQuery variable?

I'm running into a maddening problem where I set a variable to point to a jQuery selector, such as: var foobar=jQuery(this); I then pass this variable to a function to be worked on. Let's simplify a little and say the function looks like this:
function SetFieldValue (selector) {
selector.val('test');
console.log ( selector );
console.log ( jQuery('#' + selector.attr('id')) );
}
In this situation if you assume that:
the selector is always a form element (and therefore val() is a valid operation)
the selector does resolve to a single dom element which has an 'id' attribute
You would then expect the two console.log statements to output the same result, right? Well I'm running into a situation where this condition only happens about 90% of the time.
In order to give more context I've created a short screencast demonstrating the problem:
SCREENCAST LINK
For reference purposes, here's the actual SetFieldValue code that is shown in the screencast:
function SetFieldValue ( domObject, value ) {
// as a safety function, check if a string representation of the domObject was passed in and convert it to a jQuery object if it was
if ( jQuery.type(domObject) === "string") {
console.log ("Value passed into SetFieldValue was a string representation so converting to jQuery object");
domObject = jQuery(domObject);
}
if ( jQuery.inArray (domObject.prop('tagName').toLowerCase(),['input' , 'select' , 'textarea']) >= 0 ) {
console.log ("setting to value attribute: " + value);
if ( domObject.hasAttr('id') ) {
domObject.val(value);
//jQuery('#' + domObject.attr('id')).val(value);
} else {
domObject.attr('value',value);
}
console.log ("Using jQuery ID it is set to: " + jQuery('#' + domObject.attr('id')).val() );
console.log ("Using jQuery selector variable it is set to: " + domObject.val() );
} else {
console.log ("setting to html attribute");
domObject.html( value );
}
return domObject;
}
Lets examine the code a bit.
First assigning back to a parameter is not a good practice adding a var at the start of your function would be a lot better, as scope can be lost.
//Suggestion change parameter to domItem
var domObject
Your missing an error handler for when the parameter is not String.
when identifying the type use
<VARNAME>.constructor.toString().match(/function (\w*)/)[1] === "<TYPE>"
It's more efficient and handles custom types.
No need for all the logic in assignment of value attribute. Any dom Object can be made to have a value attribute. also not sure why you are setting the val versus the value.
domObject.attr('value',value);
It is at this point that I can see your code could really use some documentation to help explain purpose
If you are explicitly only wanting to set value on Input fields and set value as innerhtml on non input fields then yes the logic would be needed but could be simplified to ... as the value doesn't need to be detected to overwritten.
if (jQuery.inArray (domObject.prop('tagName').toLowerCase(), ['input' , 'select' , 'textarea']) >= 0) {
domObject.attr('value',value);
} else {
domObject.html( value );
}
No Idea why you are returning the domObject out.
So a quick rewrite without the return and keeping most of the logic adding error handling results in
/*jslint sloppy: true*/
/*global jQuery*/
function SetFieldValue(domString, value) {
// as a safety function, check if a string representation of the domObjects was passed in and convert it to a jQuery object if it was
var domObjects, index;
//errorhandling
if (domString === undefined || domString === null) {
throw {error : "domString must have a value."};
}
if (domString.constructor.toString().match(/function (\w*)/)[1] !== "string") {
if (domString.constructor.toString().match(/function (\w*)/)[1].match(/HTML[a-zA-Z]*Element/) === null) {
throw {error : "domString expected to be String or domObjects"};
}
} else {
if (jQuery(domString).length === 0) {
throw {error : "domString does not resolve to a detectable domObjects."};
}
}
//errorhandling
//action
if (domString.constructor.toString().match(/function (\w*)/)[1].match(/HTML[a-zA-Z]*Element/)) {
//made as an array to normalize as jQuery returns an array allows code to be simplified
domObjects = [domString];
} else {
domObjects = jQuery(domString);
}
//given that domObjects are an array need to step through the array
for (index = domObjects.length - 1; index >= 0; index -= 1) {
if (
jQuery.inArray(
domObjects[index].tagName.toLowerCase(),
['input', 'select', 'textarea']
) >= 0
) {
if (domObjects[index].hasAttr('id')) {
domObjects[index].val(value);
} else {
domObjects[index].attr('value', value);
}
} else {
domObjects[index].html(value);
}
}
}
The above passes JSLint
I know I didn't provide enough context for people to really dig into this problem but I have in the end solved it. What was the issue? Well it was #Kobi who first asked is the DOM element's ID unique ... to which I happily reported it was. And it had been but in fact that WAS the problem. Jesus. It's always the obvious things that you then go onto overlook that get you in trouble.
Anyway, thanks for your patience and help.

overriding the jquery.param function

I have a problem with the jQuery.param function.
jQuery uses + instead of %20 to URL-encode spaces
var obje = {
'test': 'tester 2'
}
console.log($.param(obje));
returns "test=tester+2"
so I thought about overriding this core function:
(function($){
$.fn.param = function( a, traditional ) {
console.log('custom $.param');
var s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : value;
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
};
// Set traditional to true for jQuery <= 1.3.2 behavior.
if ( traditional === undefined ) {
traditional = jQuery.ajaxSettings.traditional;
}
// If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
// Serialize the form elements
jQuery.each( a, function() {
add( this.name, this.value );
} );
} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for ( var prefix in a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}
return s.join("&");
// Return the resulting serialization
//return s.join( "&" ).replace( r20, "+" );
};
})(jQuery);
var obje = {
'test': 'tester 2'
}
console.log($.param(obje));
This fails however.. The $.param isn't overridden.
Any idea what can be wrong?
Thanks!
Edit: my solution (because I'm a new user I appearently may not answer my own question in 8 hours (Why is that?))
With the solution of ThiefMaster I still had the problem that buildParams is undefined.
I solved this by calling the old function and then replacing the + back to %20
// modification of the jQuery.param function: spaces are encoded by jQuery.param with + instead of %20. replace these back to %20
(function($, oldFunction){
$.param = function( a, traditional ) {
var s = oldFunction.apply(oldFunction,[a,traditional]);
// Return the resulting serialization
return s.replace( '+', '%20' );
};
})(jQuery,jQuery.param);
You need to use $.param instead of $.fn.param (which would be a function to call on a jQuery object, e.g. $(...).param()).
Old post I know, but for the sake of recorded knowledge. To replace the '+' left behind when using $.param(), consider doing the following:
(Using the code you provided)
var obje = {
'test': 'tester 2'
}
console.log($.param(obje).replace(/\+/g, "%20"));
That will result in:
test = tester 2
Hope this helps someone.
The "re-replace" fix may also be implemented by using "beforeSend" in the ajax settings object:
{ beforeSend: function (request, settings) { settings.data = settings.data.replace(/\+/g, "%20"); } }
This approach is suitable for cases where you don't actually want to alter $.param()'s original behavior (for example, if you want "+" in URLs but "%20" for POST data).
[Edited because I remembered that string.replace() will only match once unless it's a regex object with the g flag.]

Shorter code for this JavaScript "if" statement

Is there a short way to write the following using either JavaScript or jQuery?
if (this.id==="a" || this.id==="b" || this.id==="c" || this.id==="d")
How about this?
if ( this.id in { "a":1, "b":1, "c":1, "d":1 } ) {
...
}
... or this?
if("abcd".indexOf(this.id) > -1) {
...
}
if ( ['a','b','c','d'].indexOf( this.id ) >= 0 ) { ... }
or
if ( this.id in {'a':0,'b':0,'c':0,'d':0} ) { ... }
One possibility is a switch statement.
switch(this.id){case"a":case"b":case"c":case"d":
//do something
}
You can try the following code. Especially when you have more than four test values.
if (/^[abcdef]$/.test(this.id)) {
...
}
The inline anonymous hash (d in o) performance was misrepresented in the tests as originally written, because the hash wasn't inline in the test.
Oddly enough, the true inline hash case, compared to the predefined hash case, is much slower in Firefox 4, but 50% faster in Chrome 12.
But a more important point is that d in o misses the point of a hash—that you don't have to iterate to find things.
Two lines, but still pretty short, and by far the fastest:
var o = {a:1,b:1,c:1,d:1};
if(o[this.id]){...}

Categories

Resources