Writing sections of javascript dynamically - javascript

When the input gets blurred, I want to get the value of the input and replace the word "action" in the script, with the value of the input. So for example, if I type "hide" in the input, the word "action" would be replaced with "hide". Or something to that effect.
I'll then be using this logic to define the trigger (#elementA) and target (#elementB) also.
HTML
<input type="text" id="define-action">
<script id="interactions">
$('#elementA').click(function() {
$('#elementB').action();
)};
</script>
JS
$('#define-action').blur(function() {
var action = $(this).val();
// Replace "action" with action
)};

Use object [] notation
$(selector).hide(); can be written as $(selector)['hide']()
So you could pass in variable instead of hard code string
$(selector)[action]()
Beware you will get errors thrown if method represnted by variable doesn't exist, so you should probably create an array of valid methods you will accept and make sure value is in the array before calling the method
Example of testing values in array:
var allowedMethods=['hide','show','slideUp'];
if( $.inArray( action, allowedMethods) >-1){
$(selector)[action]()
}else{
alert( action +' is not a valid method')
}

Instead of dot notation use bracket notation
Also I don't think you need to use the blur handler, in the click handler you can read the value of the input filed
$('#elementA').click(function () {
var action = $('#define-action').val();
$('#elementB')[action]();
});
or if you want to use the blur method then you need to define the variable action is a shared scope of both the click and blur handlers
$('#elementA').click(function () {
$('#elementB')[action]();
});
var action;
$('#define-action').blur(function () {
action = $(this).val();
});

Related

Need a javascript onclick decorator

I have legacy code that includes links with hard-coded onclick handlers (bad, I know).
link
I need to decorate that onclick function. In other words, I need to to replace the hard-coded onclick function with another function of my own that will first call the original function and then allow me to call my own code.
This is what I've tried, to no avail:
var oldFunc = $('a.linkClass').attr('onclick');
function newFunc(oldFunc) {
return function(oldFunc) {
oldFunc();
// my add'l code
}
}
$('a.linkClass').attr('onclick', '').unbind('click');
$('a.linkClass').click(newFunc(oldFunc));
First issue is need proper selector to find the onclick elements. $('[onclick]') will find all elements in page with that attribute. Also you need to remove the onclick attribute, trying to unbind with jQUery won't work
Assuming each onclick only has one function you could try:
$('[onclick]').each(function(){
var $el=$(this)
var funcName=$el.attr('onclick').replace('()','');
$el.click(window[funcName]).removeAttr('onclick');
});
Just realizing this won't work if any params in function
You are trying to wrap multiple events, but to do that you need to loop over the elements and wrap each one in turn (javascript can't store multiple functions in a single variable like that!) Also you get a string from onclick, so you'll need to eval it (which is generally a BadThing (tm). But the real bad thing here is that you're using onclick in the first place.
var elementsToFix = $('a.linkClass');
for( var i = 0; i < elementsToFix.length; ++ i ) {
var obj = elementsToFix.eq( i );
var oldFnc = obj.attr( 'onclick' );
obj.removeAttr( 'onclick' ).on( 'click', (function( curOldFnc ) {
return function( ) {
// pre-wrapper here
eval( curOldFnc );
// post-wrapper here
}
}( oldFnc )) );
}
This uses the super-evil eval. That's bad, and the only reason I'm using it is because you get a string from attr('onclick') instead of a function. The correct solution is to never use onclick in the first place.
jsfiddle example: http://jsfiddle.net/Jdn6V/1
As the function called from the onclick handler is in the global scope, the easy solution would be to just remove the onclick handler, store the string, and eval it later.
Of course eval is bad, and there are ways to parse the string, remove the parenthesis and keep any arguments, and call it as window[oldFunc] etc. but as a quick example, here it is with eval (which is evil)
$('a.linkClass').each(function() {
var old = $(this).attr('onclick');
$(this).attr('onclick', '').on('click', function(e) {
e.preventDefault();
eval.apply(window, [old]);
alert('new');
});
});
FIDDLE
without eval
$('a.linkClass').each(function() {
var old = $(this).attr('onclick'),
func = old.split('(')[0],
param = old.split('(')[1].replace(')','').split(',');
$(this).attr('onclick', '').on('click', function(e) {
e.preventDefault();
window[func].apply(window, param);
alert('new')
});
});
FIDDLE
.attr() always returns a string, so you'd have to eval it to execute the function.
You can get the original function this way, and not need to eval it later:
var oldFunc = $('a.linkClass')[0].onclick;
([0] picks the "pure" DOM element that has the onclick function.)
Now you can bind the function to the element:
$('a.linkClass').click( function(e) {
// new code here
// ...
oldFunc(e);
});
(e given as the parameter, just in case the old function uses it.)
The additional benefit of this is that it works regardless of what's in the old onclick attribute because it's wrapped in a function, so e.g. onclick="foo(); bar(); return false;" works correctly.

How to select empty inputs (value="") using jQuery

How can I check for empty values of (required) input fields within a section, and then add a class to them on an event, using jQuery? So far, I have tried:
jQuery("#sender_container input.required").val("").addClass("error");
But that seems to SET the value, rather than checking it. Any ideas?
jQuery("#sender_container input.required").filter(function() {
return !this.value;
}).addClass("error");​
Why you have to use filter and not [value=""] you can see in this DEMO
The reason is: attribute selectors check the initial state of the element, not the current state. (note that you can change the "initial" state with the attr function, but it's bad practice, you should always use prop)
So if you change the input value, the current value won't effect the attribute selector. not wise... :)
Notes:
.val() returns the value of the form element, and breaks the jQuery chain,
$('selector').val().addClass('foo') Error, the return value is a string\ number
.val(valueToSet) sets the value of the form element and doesn't break the jQuery chain.
$('selector').val("some value").addClass('foo') - Valid, the returned value is a jQuery
$('input:text[value=]','#sender_container').addClass('error');
DEMO
$('#sender_container input.required[value=""]').addClass('error')
jQuery('#sender_container input.required[value=""]').addClass("error");
You can try this:
$('input:not([value!=""])').addClass('error');
DEMO
Note: This answer should not be used, and the only reason it wasn't deleted is so it can be learned from.
$field = $("#sender_container input.required");
if( ! $field.val())
{
$field.addClass("error");
}
this simple way may work.
If you only need to select based on the initial attribute value of the input then the following will do:
var elements = $('#sender_container input.required[value=""]')
But be aware that this won't work if the value attribute isn't present. It also won't work for the current input value if it has been changed by user or script.
If you'd like to get the current input value you can use jquery's filter function:
var elements = $('#sender_container input.required').filter(function() {
return this.value === '';
// alternatively for "no value":
// return !this.value;
})
After you've selected the jquery elements you can add your class:
elements.addClass('error');
to get all fields inspected this might help.
$('#sender_container [required]').each(function(index)
{
if (!($(this).val())) $(this).addClass('error');
}
});

jquery get the html code for all radios/checkboxes within a form

I am trying to parse some elements of a form.
I have with me the form ID/form name.
Now I want to parse through all radio buttons with name= "radio123"(or id="radio123").
But when I try $(this).html on each element (of a radio button)... then I get a blank value...
How do I access the HTML code for all radiobuttons/checkboxes within a form?
This is the normal behavior for jQuery.fn.html function: This method uses the browser's innerHTML property. Look at the examples if you don't understand what I mean.
I don't know why you want to get the HTML (if you want the value, look at the jQuery.fn.val method), but here's a solution
$("input:radio").each(function () {
console.log( this.outerHTML );
});
Be careful with the outerHTML, as it is not supported across all browsers you could use this function:
function getOuterHTML( node ) {
var parent = node.parentNode,
el = document.createElement( parent.tagName ),
shtml;
el.appendChild( node );
shtml = el.innerHTML;
parent.appendChild( node );
return shtml;
}
// use it like getOuterHTML( this ) in the preceding each loop
Something like this should work -
var htmlarr = [];
$("input[type='radio'][name='radio123'],[type='radio'][id='radio123']").each(function () {
//any logic you need here
htmlarr.push($(this).clone().wrap('<div>').parent().html());
})
Demo - http://jsfiddle.net/tJ2Zc/
The code uses this method $(this).clone().wrap('<div>').parent().html() to get the outer HTML of a DOM element. More info can be found in the question - Get selected element's outer HTML
The code above writes all the radio button html into an array but you could change it to do what you wished within the loop.

Moving inline code into function, with object name generation

I am customizing Denis Gritcyuk's Popup date picker.
This pop-up script uses inline Javascript in a href link, to set the selected date into the input field, in the parent window, that is was called for. An example URL looks like:
<a href="javascript:window.opener.document.formname.field.value='03-10-2011';
window.close();">3</a>
The input field name, (e.g. document.formname.field), is passed to the script as a string parameter.
I would like to add things done when that link is clicked (e.g. change background color of field, set flag, etc.). So while this DOES work, it's getting ugly fast.
<a href="javascript:window.opener.document.formname.field.value='03-10-2011';
window.opener.document.formname.field.style.backgroundColor='#FFB6C1';
window.close();">3</a>
How would I move these inline commands into a JS function? This would give me much cleaner URLs and code. The URL would now look something like
3
with a function like (this example obviously does NOT work):
function updateField (str_target, str_datetime) {
var fieldName = "window.opener" + str_target;
[fieldName].value = str_datetime;
[fieldName].style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
So any suggestions on how this can be done, please?
I'd prefer to hide the dom path tracing back from the current window back to the opener. It's appropriate to bake that into the function since the function will always be used in the context of that child popup. Then your function call is cleaner and more readable. Obviously, replace "myField" with the ID of the field you're intending to update.
3
function updateField ( str_date, str_fieldname ) {
var fieldToUpdate = document.getElementById( str_fieldname );
fieldToUpdate.value = str_date;
fieldToUpdate.style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
You're acessing the property incorrectly. Try:
function updateField (str_target, str_datetime) {
var fieldName = window.opener;
str_target = str_target.split('.');
for (var i = 0; i < str_target.length; i++)
fieldName = fieldName[str_target[i]];
fieldName.value = str_datetime;
fieldName.style.backgroundColor = '#FFB6C1';
// Set flag, etc.
window.close();
}
The bracket notation ([]) is only used for properties of objects, not objects themselves. If you found my post helpful, please vote for it.
You can build a string and evaluate it as code using the eval function, but I would recommend against it.
There are a couple of things wrong with your code:
You cannot use the [] operator in a global context, you have to suffix it on an object, so you can say window["opener"] and this will be equivalent to window.opener, but there is no such thing as simply ["window"]
When navigating nested properties, as in window.opener.document you cannot navigate multiple levels using the [] operator. I.e. window["opener.document"] is not allowed. You must use window["opener"]["document"] instead.

JavaScript: Dynamic Field Names

HI All,
I have a piece of javaScript that removes commas from a provided string (in my case currency values)
It is:
function replaceCommaInCurrency(myField, val)
{
var re = /,/g;
document.net1003Form.myField.value=val.replace(re, '');
}
'MyField' was my attempt to dynamically have this work on any field that I pass in, but it doesn't work, I get errors saying 'MyField' is not valid. I sort of get my, but I thought this was valid.
I am calling by using: onBlur="replaceCommaInCurrency(this.name, this.value);return false;"
this.name and this.value are passing in the right values...field name and its value.
How do I do this dynamically?
-Jason
You can use eval to make your code snippet work:
eval("document.net1003Form." + myField + ".value=val.replace(re, '');");
As mentioned below, the square brackets work (and don't suck like eval), stupid me for forgetting about those:
document.net1003Form[myField].value=val.replace(re, '');
Alternatively, try something like this:
function replaceCommaInCurrency(field){
var re = /,/g;
field.value = field.value.replace(re, '');
}
Which gets called like so:
onBlur="replaceCommaInCurrency(this); return false";
You should consider using a javascript toolkit for things like this. You could set a class like "currency" on each input, then use this snippet of jQuery based Javascript to handle everything:
$(function(){
$("input.currency").bind('blur', function(){
this.value = $(this).val().replace(',', '');
})
});
This code would fire on document ready, attach an event handler to each input with currency as its class, and then do the replacements. Note that you don't need a regex for replacement as well.
If you code it right into the markup like that, e.g. onblur="replaceCommaInCurrency(this)", the control originating the event gets passed as the parameter. Then you should be able to do something like:
myField.value = myField.value.replace(re, '');
with jQuery:
var jqField = $(myField);
jqField.val(jqField.val().replace(re, ''));
In general, you should be using a framework that will handle low level functionality like this, but the specific answer to your question is to use bracket notation for the field name:
function replaceCommaInCurrency( myField, val)
{
var re = /,/g;
document.net1003Form[myField].value=val.replace(re, '');
}
function removeCommaInCurrency(myField)
{
var re = /,/g;
myField.value=myField.value.replace(re, '');
}
-- and then call it like this:
<input type="text" name="..." onchange="removeCommaInCurrency(this);">
flatline and roenving's solution with ‘this’ is the cleaner approach, it also avoids the problems of ‘document.formname.fieldname’.
(Use ‘document.forms.formname’ to access a form without possible clashing on forms having the same name as members of the document object, and ‘forms.elements.fieldname’ to do the same with fields. Like all JavaScript object, object[namevariable] can also be used. Or, better, add IDs and use the unambiguous document.getElementById method.)
By moving binding into the script you can also remove the inline JavaScript of the onclick attribute, making the markup cleaner still:
<input type="text" class="number" name="something" />
...
<script type="text/javascript"> // external script is best, linked after all forms
function numberfield_bind() {
var inputs= document.getElementsByTagName('input');
for (var inputi= inputs.length; inputi-->0;)
if (inputs[inputi].className=='number')
inputs[inputi].onchange= numberfield_change;
}
function numberfield_change() {
this.value= this.value.split(',').join('');
}
numberfield_bind();
</script>

Categories

Resources