Using change(); twice for same div causing problems - javascript

UPDATE** This is probably too much code. But... heres the situation. I have a search at the top of the page. I use some fancy jQuery so when you click on a select option(#categoris) a new select option(#type) appears next to it. Now, I have another change event. On keyup of any text field or change of any select, an ajax search is fired. This works on everything but #type. #type is the select option that pops out from #categories on change(); So, I need change to work on #type. Here's the code pop out the #type select option. You can just skim. Code works fine...
$(document).ready(function() {
$('#category').change(function() {
var category = $('#category').val();
//CATEGORIES...
// any_type / NULL
var any_category = '<div id="type_holder_line"></div>';
// Music
var music = '<div id="type_text">Type</div><img src="app/search/images/arrow.gif" id="arrow" /><select name="music_type" id="type"><option value="any_style" selected="selected">Any Style</option><option value="Jazz">Jazz</option><option value="Rock">Rock</option></select>';
// Restaurants
var restaurant = '<div id="type_text">Type</div><img src="app/search/images/arrow.gif" id="arrow" /><select name="restaurant_type" id="type"><option value="Japanese">Japanese</option><option value="Mexican">Mexican</option></select>';
if($(this).val() == 'Any Category') {
$('#type_holder').html(any_category);
}
if($(this).val() == 'music_page') {
$('#type_holder').html(music);
}
if($(this).val() == 'restaurant_page') {
$('#type_holder').html(restaurant);
}
});
Here, is the change();. #type should instantiate the search on change(); But, doesn't either because it's made from #categories on change();. Or, because I'm using change(); twice.
// *** START *** keyup / change (for select option)
$('#loc, #dist, #category, #type, #search_title').bind('keyup change', // HERE, #type is ignored because it's created from #categories on change(); function() {
var loc = $('#loc').val();
var dist = $('#dist').val();
var category = $('#category').val();
var type = $('#type').val();
var search_title = $('#search_title').val();
if(loc == '' && search_title != '') {
$.post('http://localhost/app/search/page_type/music_spot/search.name.php', {
category:category,
type:type,
search_title:search_title
},
function(data) {
$('#front_left').html(data);
});
}
});
});

I think you should try the live() function. Because the live function handle the dynamically created elements but you can read more on documentation :)
So you can try something like this:
$('#loc, #dist, #category, #type, #search_title').live('keyup change', function(){
// code here
});
Please read the manual because I see now that the .live() function is deprecated for jquery 1.7, and choose the appropiate function for your jquery version.
I hope this resolve your problem, and sorry for my english :">

Related

Angular JS calculation based on input boxes

I read this thread:
Simple Percentage Calculation of an Input Field with JQuery
But can't seem to get it to work for my situation. I have two input boxes, Wholesale and Sell Price, and I want to calculate the markup (difference) on the fly as the user is changing their Sell Price. I've built a simplified version of what I'm trying to do here:
http://jsfiddle.net/schuss/rp0brqj1/2/
And below is the JS - can anyone see what I'm doing wrong? Thanks!!
$(function() {
// cache elements that are used at least twice
var $sellprice = $("#SellPrice"),
$markup = $("#markup"),
$wholesale = $("#wholesale");
// attach handler to input keydown event
$sellprice.keyup(function(e){
if (e.which == 13) {
return;
}
var sellprice = parseFloat($sellprice.val()),
markup = sellprice-wholesale;
if (isNaN(sellprice)) {
$markup.hide();
return;
}
else {
$markup.fadeIn().text(markup.toFixed(2));
}
});
});
You want to set the value of input field, so in this case you need to use $.fn.val method:
$markup.fadeIn().val(markup.toFixed(2));
Demo: http://jsfiddle.net/rp0brqj1/6/
Try this (I haven't included the else - and don't forget to include JQuery in your fiddles!):
$(function() {
var $sellprice = $("#SellPrice"),
$markup = $("#markup"),
$wholesale = $("#Wholesale");
$sellprice.on('keyup', function(){
$markup.val(parseFloat($sellprice.val()-$wholesale.val()))
});
});
Fiddle

Converting Span to Input

I am developing web app, I have such a requirement that whenever user click on text inside span i need convert it into input field and on blur i need to convert it back to span again. So i am using following script in one of my jsp page.
Java Script:
<script type="text/javascript">
function covertSpan(id){
$('#'+id).click(function() {
var input = $("<input>", { val: $(this).text(),
type: "text" });
$(this).replaceWith(input);
input.select();
});
$('input').live('blur', function () {
var span=$("<span>", {text:$(this).val()});
$(this).replaceWith(span);
});
}
JSP Code:
<span id="loadNumId" onmouseover="javascript:covertSpan(this.id);">5566</span>
Now my problem is, everything works fine only for the first time. I mean whenever i click on the text inside span for the first time it converts into input field and again onblur it coverts back from input field to normal text. But if try once again to do so it won't work. Whats wrong with above script?
Would be good to change your dom structure to something like this (note that the span and the input are side by side and within a shared parent .inputSwitch
<div class="inputSwitch">
First Name: <span>John</span><input />
</div>
<div class="inputSwitch">
Last Name: <span>Doe</span><input />
</div>
Then we can do our JS like this, it will support selecting all on focus and tabbing to get to the next/previous span/input: http://jsfiddle.net/x33gz6z9/
var $inputSwitches = $(".inputSwitch"),
$inputs = $inputSwitches.find("input"),
$spans = $inputSwitches.find("span");
$spans.on("click", function() {
var $this = $(this);
$this.hide().siblings("input").show().focus().select();
}).each( function() {
var $this = $(this);
$this.text($this.siblings("input").val());
});
$inputs.on("blur", function() {
var $this = $(this);
$this.hide().siblings("span").text($this.val()).show();
}).on('keydown', function(e) {
if (e.which == 9) {
e.preventDefault();
if (e.shiftKey) {
$(this).blur().parent().prevAll($inputSwitches).first().find($spans).click();
} else {
$(this).blur().parent().nextAll($inputSwitches).first().find($spans).click();
}
}
}).hide();
I understand you think that element replacement is a nice thing, however, I would use a prompt to get the text. Why? It is a lot easier and actually a bit prettier for the user as well. If you are curious on how to do it, I show you.
html:
<span class='editable'>foobar</span>
js:
$(function()
{
$('span.editable').click(function()
{
var span = $(this);
var text = span.text();
var new_text = prompt("Change value", text);
if (new_text != null)
span.text(new_text);
});
});
http://jsfiddle.net/qJxhV/1/
First, you need to change your click handler to use live() as well. You should take note, though, that live() has been deprecated for quite a while now. You should be using on() in both cases instead.
Secondly, when you replace the input with the span, you don't give the element an id. Therefore, the element no longer matches the selector for your click handler.
Personally, I would take a different (and simpler) approach completely. I would have both the span and in the input in my markup side by side. One would be hidden while the other is shown. This would give you less chance to make mistakes when trying to recreate DOM elements and improve performance since you won't constantly be adding/removing elements from the DOM.
A more generic version of smerny's excellent answer with id's can be made by slightly altering two lines:
$input.attr("ID", "loadNum"); becomes $input.attr("ID", $(this).attr("ID")); -- this way, it simply takes the current id, and keeps it, whatever it is.
Similarly,
$span.attr("ID", "loadNum"); becomes $span.attr("ID", $(this).attr("ID"));
This simply allows the functions to be applied to any div. With two similar lines added, both id and class work fine. See example.
I have done little change in code, By using this input type cant be blank, it will back to its real value.
var switchToInput = function () {
var $input = $("<input>", {
val: $(this).text(),
type: "text",
rel : jQuery(this).text(),
});
$input.addClass("loadNum");
$(this).replaceWith($input);
$input.on("blur", switchToSpan);
$input.select();
};
var switchToSpan = function () {
if(jQuery(this).val()){
var $text = jQuery(this).val();
} else {
var $text = jQuery(this).attr('rel');
}
var $span = $("<span>", {
text: $text,
});
$span.addClass("loadNum");
$(this).replaceWith($span);
$span.on("click", switchToInput);
}
$(".loadNum").on("click", switchToInput);
jsFiddle:- https://jsfiddle.net/svsp3wqL/

How can I update a input using a div click event

I've got the following code in my web page, where I need to click on the input field and add values using the number pad provided! I use a script to clear the default values from the input when the focus comes to it, but I'm unable to add the values by clicking on the number pad since when I click on an element the focus comes from the input to the clicked number element. How can I resolve this issue. I tried the following code, but it doesn't show the number in the input.
var lastFocus;
$("#test").click(function(e) {
// do whatever you want here
e.preventDefault();
e.stopPropagation();
$("#results").append(e.html());
if (lastFocus) {
$("#results").append("setting focus back<br>");
setTimeout(function() {lastFocus.focus()}, 1);
}
return(false);
});
$("textarea").blur(function() {
lastFocus = this;
$("#results").append("textarea lost focus<br>");
});
Thank you.
The first thing I notice is your selector for the number buttons is wrong
$('num-button').click(function(e){
Your buttons have a class of num-button so you need a dot before the class name in the selector:
$('.num-button').click(function(e){
Secondly, your fiddle was never setting lastFocus so be sure to add this:
$('input').focus(function() {
lastFocus = this;
...
Thirdly, you add/remove the watermark when entering the field, but ot when trying to add numbers to it (that would result in "Watermark-text123" if you clicked 1, then 2 then 3).
So, encalpsulate your functionality in a function:
function addOrRemoveWatermark(elem)
{
if($(elem).val() == $(elem).data('default_val') || !$(elem).data('default_val')) {
$(elem).data('default_val', $(elem).val());
$(elem).val('');
}
}
And call that both when entering the cell, and when clicking the numbers:
$('input').focus(function() {
lastFocus = this;
addOrRemoveWatermark(this);
});
and:
$('.num-button').click(function(e){
e.preventDefault();
e.stopPropagation();
addOrRemoveWatermark(lastFocus);
$(lastFocus).val($(lastFocus).val() + $(this).children('span').html());
});
You'll see another change above - you dont want to use append when appends an element, you want to just concatenate the string with the value of the button clicked.
Here's a working branch of your code: http://jsfiddle.net/Zrhze/
This should work:
var default_val = '';
$('input').focus(function() {
lastFocus = $(this);
if($(this).val() == $(this).data('default_val') || !$(this).data('default_val')) {
$(this).data('default_val', $(this).val());
$(this).val('');
}
});
$('input').blur(function() {
if ($(this).val() == '') $(this).val($(this).data('default_val'));
});
var lastFocus;
$('.num-button').click(function(e){
e.preventDefault();
e.stopPropagation();
var text = $(e.target).text();
if (!isNaN(parseInt(text))) {
lastFocus.val(lastFocus.val() + text);
}
});
Live demo
Add the following function:
$('.num-button').live( 'click', 'span', function() {
$currObj.focus();
$currObj.val( $currObj.val() + $(this).text().trim() );
});
Also, add the following variable to global scope:
$currObj = '';
Here is the working link: http://jsfiddle.net/pN3eT/7/
EDIT
Based on comment, you wouldn't be needing the var lastFocus and subsequent code.
The updated fiddle lies here http://jsfiddle.net/pN3eT/28/

need the script to be called for "onload" too not just on "blur"

the code is:
$(document).ready(function () {
$('#url0, #url1, #url2, #url3, #url4, #url5, #url6, #url7, #url8, #url9, #url10').each(function(index, element) {
$(element).blur(function() {
var vals = this.value.split(/\s+/);
var $container = $(this).hide().prev().show().empty();
$.each(vals, function(i, val) {
if (i > 0) {
$("<span> </span>").appendTo($container);
}
$("<a />")
.html(val)
.attr('href',/^https?:\/\//.test(val) ? val : 'http://' + val)
.appendTo($container)
.click(handleClickEvent);
});
});
}).trigger('blur');
// ms to wait for a doubleclick
var doubleClickThreshold = 300;
// timeout container
var clickTimeout;
$('.aCustomDiv a').click(handleClickEvent);
$('.aCustomDiv').click(handleDivClick);
function handleClickEvent(e) {
var that = this;
var event;
if (clickTimeout) {
try {
clearTimeout(clickTimeout);
} catch(x) {};
clickTimeout = null;
handleDoubleClick.call(that, e);
return false;
}
clickTimeout = setTimeout(function() {
clickTimeout = null;
handleClick.call(that, event);
}, doubleClickThreshold);
return false;
}
function handleDivClick(e) {
var $this = $(this);
$this.parent()
.find('input,textarea')
.show()
.focus();
$this.hide();
}
function handleDoubleClick(e) {
var $this = $(this).parent();
$this.parent()
.find('input,textarea')
//.val($a.text())
.show()
.focus();
$this.hide();
}
function handleClick(e) {
window.open(this.href, '_blank')
}
});
HTML CODE:
<div style="padding:0 !important;margin-top:8px !important;">
<div class="aCustomDiv" style="padding: 0px ! important; display: block;">
www.google.com<span></span>www.facebook.com<span></span>www.wikipedia.org
</div>
<input type="text" value="www.google.com www.facebook.com www.wikipedia.org" onchange="immediateEditItemInCart(this.value,'url',0,'pr','35')" class="mandatory0" id="url0" style="display: none;" readonly="readonly">
this script does the following:
converts the text to url for those ids (url0 ...)
double click on the link makes it editable
one click on the div area, next to link makes it editable
one click on the link => goes to the page
my problem : for some reason i don't know, the one click on the link doesn't go to the page but edits it, only the FIRST time , after that works great, so i want the first function to be called also onload not only when blur. how can i do this ?
As far as loading on startup, javascript is single threaded so just firing a method will work if you keep things in order (... just add a couple of parens). But because you are trying to access the DOM you do want to wait for the elements to be available (otherwise you will get nothing back from a selector).
But you do already have:
$(document).ready( function(){} );
Which does exactly what you are asking for, it also has a shorthand of:
$( function(){} );
So I would have to agree with rodneyrehm that is it probably some collision that you have with other js on your page. You might want to encapsulate it a bit in some namespace to make sure that is the not the problem.
I wrote up a quick version that should get your on your way as a starting point if you are still having problems: http://jsfiddle.net/scispear/dUWwB/. I pulled the 'updateURL ' method out in case your ajax call (you mentioned) was just pre-populating the field (that way you could pass in the value also).
It also works with multiple inputs/displays which is what I think you were going for was not 100% sure.

Using jquery to monitor form field changes

Trying to learn some jquery to implement an autosave feature and need some assistance. I have some code to monitor the status of form fields to see if there has been any change. Everything works, but I need to only monitor the changes in a specific form, not all form inputs on the page. There is a search box and a newsletter form on the same page and when these form fields are changed, they are detected as well, which I need to filter out somehow or better yet, only target the specific form.
$(function(){
setInterval("CheckDirty()",10000);
$(':input').each(function() {
$(this).data('formValues', $(this).val());
});
});
function CheckDirty()
{
var isDirty = false;
$(':input').each(function () {
if($(this).data('formValues') != $(this).val()) {
isDirty = true;
}
});
if(isDirty == true){
alert("isDirty=" + isDirty);
}
}
Just add a class to the form and use it to filter
$('.form :input').each(function() {
$(this).data('formValues', $(this).val());
});
EDIT
Just a suggestion, you can attach the change event directly to the form
live demo here : http://jsfiddle.net/jomanlk/kNx8p/1/
<form>
<p><input type='text'></p>
<p><input type='text'></p>
<p><input type='checkbox'></p>
</form>
<p><input type='text'></p>
<div id='log'></div>
$('form :input').change(function(){
$('#log').prepend('<p>Form changed</p>')
});
You can easily improve this by adding a timer and making it save every xx seconds.
var $jq= jQuery.noConflict();
$jq(function() { $jq('#extensibleForm').data('serialize',$jq('#extensibleForm').serialize());
});
function formHasChanged(){
if($jq('#extensibleForm').serialize()!=$jq('#extensibleForm').data('serialize')){
alert("Data Changed....");
return (false);
}
return true;
}
what's your form's id?
you just need to make your selector more specific :)
instead of $(':input').each(function() {
use
$('#yourFormId').find(':input').each(function() {
You can use the .change() function and then use $(this) to denote you want to work with just the field that is actively being changed.
$('#myForm input[type="text"]').change(function() {
$(this)...
});
Edit: #myForm is your form ID so you can target a specific form. You can even specify just type="text" fields within that form, as in my example.
Here you can see it working: http://jsfiddle.net/paska/zNE2C/
$(function(){
setInterval(function() {
$("#myForm").checkDirty();
},10000);
$("#myForm :input").each(function() {
$(this).data('formValues', $(this).val());
});
$.fn.checkDirty = function() {
var isDirty = false;
$(this).find(':input').each(function () {
if($(this).data('formValues') != $(this).val()) {
isDirty = true;
}
});
if(isDirty == true){
alert("isDirty=" + isDirty);
}
};
});
I think you can use a class to select the type of input you want.
<input class="savethis" ... />
Then in jQuery use this.
$(':input .savethis').each(function() { ...
You can specify an id attribute (say theForm) to your form element and then select only those input fields inside it.
then try selecting with
$(':input', '#theForm')
I respect all the working answers but for me I think using the focus event might be much better than change event. This is how I accomplished my watchChange() function is JS:
var changeInterval = 0;
var changeLength = 0; //the length of the serverData
var serverData = {value:''}; //holds the data from the server
var fieldLength = 0; //the length of the value of the field we are tracking
var frequency = 10000;
function watchChange() {
$input.on('focus', function() {
var $thisInput = $(this);
//we need the interval value so that we destroy
//setInterval when the input loses focus.
changeInterval = setInterval(function() {
changeLength = serverData.value.length;
fieldLength = $thisInput.val().length;
//we only save changes if there is any modification
if (changeLength !== fieldLength) {
$.ajax({
url: 'path/to/data/handler',
dataType: 'json',
data: "data=" + $thisInput.val(),
method: 'post'
}).done(function(data) {
serverData = data;
}); //end done
} //end if
}, frequency); //end setInterval
//and here we destroy our watcher on the input
//when it loses focus
}).on('blur', function() {
clearInterval(changeInterval);
});
}
Even though this approach seems to be naive but it gave me what I wanted!

Categories

Resources