jQuery - Detect value change which use .val() function - javascript

We all know that use the val() will not trigger the change event, so we also use .trigger('change') behind the val().
But the problem is that someone write the val() did't with trigger() and it's a external file that I can't edit it.
So, how can I detect value change through some code same like below:
$('.elem').on('change', function(){
// do something
});

My suggestion is to override jquery's val()
var originalValFn = jQuery.fn.val;
jQuery.fn.val = function() {
this.trigger('change');
originalValFn.apply( this, arguments );
}
jsfiddle: http://jsfiddle.net/2L7hohjz/js

var originalValFn = jQuery.fn.val;
function getErrorObject(){
try { throw Error('') } catch(err) { return err; }
}
jQuery.fn.val = function() {
if ($(this).hasClass( "element" )) {
var err = getErrorObject();
var caller_line = err.stack.split("\n")[4];
var index = caller_line.indexOf("at ");
var clean = caller_line.slice(index+2, caller_line.length);
console.log(clean);
console.log(arguments);
}
originalValFn.apply( this, arguments );
};

Try:
setTimeout(function() {
if (currentValue != previousValue)
{
// do something
}
}, 500);
Thank you,

I commonly use the solution from this post to get around problems like this one:
hidden input change event
watchField('.elem', function(){
//do some stuff here
});
function watchField(selector, callback) {
var input = $(selector);
var oldvalue = input.val();
setInterval(function(){
if (input.val()!=oldvalue){
oldvalue = input.val();
callback();
}
}, 100);
}

Try:
$('.elem').on('keyUp', function(){
// do something
});
or
$('.elem').on('lostFocus', function(){
// do something
});
Thank you,

Related

this value of input field .val() not a function

I have this jquery code to check for any value on a given input and then add a simple class if the input has a value.
But in console i receive error that .val() is not a function?
my code is:
$.fn.tkFormControlMaterial = function(){
this
.blur(function () {
if (this.val())
this.addClass('used');
else
this.removeClass('used');
})
.after('<span class="ma-form-highlight"></span><span class="ma-form-bar"></span>');
};
bind will set you free
$.fn.tkFormControlMaterial = function(){
this
.blur(function () {
if (this.val())
this.addClass('used');
else
this.removeClass('used');
}.bind(this))
.after('<span class="ma-form-highlight"></span><span class="ma-form-bar"></span>');
}.bind(this);
I found the solution.
If anyone needs a working sample of my own code above:
$.fn.tkFormControlMaterial = function(){
$(this)
.blur(function () {
if ($(this).val())
$(this).addClass('used');
else
$(this).removeClass('used');
})
.after('<span class="ma-form-highlight"></span><span class="ma-form-bar"></span>');
};
You could also try to use the "self" pattern.
var _self = this;
$.fn.tkFormControlMaterial = function(){
_self
.blur(function () {
if (_self.val())
_self.addClass('used');
else
_self.removeClass('used');
})
.after('<span class="ma-form-highlight"></span><span class="ma-form-bar"></span>');
};

Get the element in a JQuery Callback

I'm having trouble getting the element in a jQuery Callback function. I have tried various suggestions of $(this) and $(this.element) with no success.
$.fn.onTypeFinished = function (func) {
$(this).bind("keypress", onKeyPress)
function onKeyPress() {
setTimeout(onTimeOut, 500);
}
function onTimeOut() {
func.apply();
}
return this;
};
$(".user-input").onTypeFinished(function () {
var ntabindex = parseFloat($(this.element).attr('tabindex'));
ntabindex++;
$('input[tabindex=' + ntabindex + ']').focus();
});
I have been thinking I need some way to pass a reference to this to the callback function but no other similar posts seem to suggest that route.
Here is a JSFiddle of what I am trying to do. The gist of the functionality is I'm trying to auto advance to the next input according to tabindex.
http://jsfiddle.net/helfon/fdu8xw0h/2/
Thanks
From your code it looks like you want to pass the element on which the keypress has occurred as this to the callback.
For that to happen you need to pass the correct context to the timeout handler, for which we can use .bind() as shown below.
Also to make the timer work correctly some other corrections are also made.
$.fn.onTypeFinished = function(func) {
$(this).bind("keypress", onKeyPress)
function onKeyPress() {
var onTypeFinished = $(this).data('onTypeFinished');
if (!onTypeFinished) {
onTypeFinished = {};
$(this).data('onTypeFinished', onTypeFinished);
}
clearTimeout(onTypeFinished.keytimer);
onTypeFinished.keytimer = setTimeout(onTimeOut.bind(this), 500);
}
function onTimeOut() {
func.apply(this);
}
return this;
};
$(".user-input").onTypeFinished(function() {
//$('input[tabindex=3]').focus();
var ntabindex = parseFloat(this.getAttribute('tabindex'));
ntabindex++;
$('input[tabindex=' + ntabindex + ']').focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="1" tabindex=1 class="user-input">
<input id="2" tabindex=2 class="user-input">
<input id="3" tabindex=3 class="user-input">
<input id="4" tabindex=4 class="user-input">
As per the logs, it seems that your this keyword inside the jQuery fn is pointing to the window object instead, I've bound the functions as follows and passed this in your apply, and got it working so that this points to the input elements instead:
$.fn.onTypeFinished = function (func) {
var time;
$(this).each(function () {
$(this).on('keypress', onKeyPress);
});
function onKeyPress() {
clearTimeout(time);
time = setTimeout(onTimeOut.bind(this), 500);
}
function onTimeOut() {
func.apply(this);
}
return this;
};
$(".user-input").onTypeFinished(function () {
//$('input[tabindex=3]').focus();
var ntabindex = parseFloat($(this).attr('tabindex'));
++ntabindex;
$('input[tabindex=' + ntabindex + ']').focus();
});
http://jsfiddle.net/fdu8xw0h/9/
You have to also iterate over the array of elements as your selector is returning an array of inputs, so you have to handle them separately, otherwise your event will occur only once, i've tested it and it goes from the first input to the second and then it stops working. With the approach i've pasted here it will go from input to input.
You should understand that this changes whenever you change scope. Always var $this = $(this) to lock it down.
$.fn.onTypeFinished = function (func) {
var $this = $(this);
$this.bind("keypress", onKeyPress);
function onKeyPress() {
setTimeout(onTimeOut, 500);
}
function onTimeOut() {
func($this); //I would personally send this, like how you do $.each(function(count, element){})
}
return this;
};
$(".user-input").onTypeFinished(function (t) {
var ntabindex = parseInt($(t).attr('tabindex')) + 1; //You should parse int here
$('input[tabindex=' + ntabindex + ']').focus();
});
Of course, you can simplify the above more into:
$.fn.onTypeFinished = function (func) {
var $this = $(this);
$this.bind("keypress", onKeyPress);
function onKeyPress() {
setTimeout(function(){
func($this);
}, 500);
}
return this;
};
$(".user-input").onTypeFinished(function (t) {
$('input[tabindex=' + String(parseInt($(t).attr('tabindex')) + 1) + ']').focus();
});
The jsfiddle: http://jsfiddle.net/vimxts/fdu8xw0h/6/

mouseover set by jquery not working in ie7

i need to set the call the function active() on onmouseover area on image, i tried to set onmouseover using jquery , this work in all browser but not in IE7 so please anybody suggest me hint to work this code on IE7
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).attr('onmouseover', "active('area"+i+"','"+Id+"',"+i+")");
i++
});
});
the active function code as follow:-
function active(value,value2,value3)
{
$("#"+value).css({'display':'block'});
$("#area"+value3+"_link").css({'text-decoration':'underline'});
$('#'+value2).mouseout(function(){$('#'+value).css({'display':'none'});$("#area"+value3+"_link").css({'color':'#707070','text-decoration':'none'});});
}
and no js error shown.
Why are you using $(this).attr('onmouseover'. Only reason I am seeing is i
You can simply use .index()
$("#map area").on('mouseover', function(){
var i = $("#map area").index(this) + 1;
active('area'+ i, $(this).attr('id'), i);
})
Note: .index() starts with 0
Try changing to anonymous function definition like this
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).attr('onmouseover', function() {...your code here...});
i++;
// and you missed the ; after i++
});
});
Try:)
$(document).ready(function(){
var i = 1;
$("#map area").each(function(){
var Id = $(this).attr('id');
$(this).mouseover(function(){
active('area"+i+"','"+Id+"',"+i+")");
i++;
});
});
Attach event using following func e.g. addEvent('mouseover', $(this).get(0), <callback>)
function addEvent(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
elem.attachEvent("on"+evnt, func);
}
else { // No much to do
elem[evnt] = func;
}
}

Calling Javascript Functions by name

If I have an element on the page like this ...
<span data-function="DoSomething">Click</span>
... and i put this in my page header ...
$(document).ready(function()
{
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fName);
});
});
... what goes in place of the comment produce the desired effect of executing the function called "DoSomething".
Note:
I no the code above wont work, my question is how to make this work (translate 'DoSomething' in to DoSomething();)
Any ideas guys?
The functions should be available. Try putting them in an Object, like this:
$(document).ready(function()
{
var fns = {
DoSomething: function() {/* ... */},
DoAnotherthing: function() {/* ... */}
};
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fns[fName]);
});
});
Here's a jsfiddle, demonstrating a way to keep everything local to one namespace and assigning handlers based on the data attribute of elements.
Try calling function with window object -
$(document).ready(function() {
$('[data-function]').each(function() {
var fName = $(this).attr('data-function');
if (typeof (window[fName]) === "function") {
$(this).click(window[fName]);
}
});
}
You can use something like
$(this).click(window[fName]);
Where window would be replaced by the appropriate expression if the function DoSomething is not defined in the global scope.
Maybe a little bit clean way:
http://jsfiddle.net/whsPG/
var myfuncs = {
alert : function() {
alert("An Alert");
},
changeName: function(obj) {
$(obj).text('Other Text');
}
};
$('[data-function]').on('click', function()
{
value = $(this).data('function');
if (myfuncs.hasOwnProperty(value)) {
myfuncs[value](this);
}
});
​

How to detect if some text box is changed via external script?

I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}

Categories