I'm exploring the potential of jquery to satisfy some of our UI requirements, and am experiencing some curious behaviour. I'm very new to jQuery, and I'm trying to implement a basic pub-sub type of pattern that's hooked into the show & hide functions.
Despite the custom event mechanism looking perfectly simple on the surface, it isn't behaving as I expect. I can't see my syntactical mistake, so I must be misunderstanding the way these custom events are intended to work.
When I execute this code, Here's what I think should happen.
Initially (after doc.Ready) the question2 element should be hidden.
When I click on the 'Vermont' radio button, question 2 should be made visible followed by one alert box indicating that 'question2 has been made visible'.
When I click on another radio button, question 2 should be hidden followed by one alert box indicating that question 2 has been made hidden.
What is actually happening is that I get numerous alert boxes when making question 2 visible, and none when I hide it?
Please help me understand why it's doing this.
Here is the script:
<script type="text/javascript">
function processRadioButtonASD() {
var isChecked = ($("input[name=question1]:checked").val() == "question1.Vermont");
if (isChecked == true) {
$("[data-uniquename=question2]").show(250);
} else {
$("[data-uniquename=question2]").hide(250);
}
}
function detectVisibilityChange(uniqueName) {
$("[data-uniquename=" + uniqueName + "]").bind("madeVisible", function () {
alert($(this).attr("data-uniquename") + " was made visible");
});
$("[data-uniquename=" + uniqueName + "]").bind("madeHidden", function () {
alert($(this).attr("data-uniquename") + " was made hidden");
});
}
$(function () {
$.each(["show", "hide"], function () {
var _oldFn = $.fn[this];
$.fn[this] = function () {
var wasVisible = $(this).is(':visible');
var result = _oldFn.apply(this, arguments);
var isVisible = $(this).is(':visible');
if ((isVisible == true) && (wasVisible == false)) {
$(this).triggerHandler("madeVisible");
} else if ((isVisible == false) && (wasVisible == true)) {
$(this).triggerHandler("madeHidden");
}
return result;
}
});
});
$(document).ready(function () {
processRadioButtonASD();
detectVisibilityChange("question2");
$("input[name='question1']").change(function () { processRadioButtonASD(); });
});
</script>
Here is the html:
<div id="content">
<div id="radioButtonASD" class="example">
<h2>radio button visibility trigger</h2>
<div data-uniquename="question1" class="question">
<label for="question1">
Question 1) (select Vermont to show Question2)
</label>
<br />
<label data-uniquename="question1.Maine">
<input name="question1" data-uniquename="question1.Maine" type="radio" value="me" />Maine</label><br />
<label data-uniquename="question1.Vermont">
<input name="question1" data-uniquename="question1.Vermont" type="radio" value="question1.Vermont" />Vermont</label><br />
<label data-uniquename="question1.NewHampshire">
<input name="question1" data-uniquename="question1.NewHampshire" type="radio" value="question1.NewHampshire" />New
Hampshire</label><br />
<label data-uniquename="question1.Conneticut">
<input name="question1" data-uniquename="question1.Conneticut" type="radio" value="question1.Conneticut" />Conneticut</label><br />
<label data-uniquename="question1.Massachusetts">
<input name="question1" data-uniquename="question1.Massachusetts" type="radio" value="question1.Massachusetts" />Massachusetts
</label>
</div>
<br />
<div data-uniquename="question2" class="question">
<label>
Question 2)
</label>
<br />
<select>
<option data-uniquename="question2.honda" value="honda">Honda</option>
<option data-uniquename="question2.volvo" value="volvo">Volvo</option>
<option data-uniquename="question2.saab" value="saab">Saab</option>
<option data-uniquename="question2.mercedes" value="mercedes">Mercedes</option>
<option data-uniquename="question2.audi" value="audi">Audi</option>
</select>
</div>
</div>
</div>
Thanks for looking.
I came up with an alternative way.
$.each(["show", "hide"], function() {
var effect = $.fn[this];
$.fn[this] = function(duration, move, callback) {
// Match the arguments
var speed = duration;
var easing = callback && move || move && !jQuery.isFunction( move ) && move;
var fn = callback || !callback && move || jQuery.isFunction( duration ) && duration;
// Wrap the callback function
var wrapped = fn;
var wasVisible = $(this).is(':visible');
fn = function(){
var isVisible = $(this).is(':visible');
$.proxy(wrapped, this);
if ((isVisible == true) && (wasVisible == false)) {
$(this).triggerHandler("madeVisible");
} else if ((isVisible == false) && (wasVisible == true)) {
$(this).triggerHandler("madeHidden");
}
};
// Run the effect with the wrapped callback
return effect.call(this, speed, easing, fn);
};
});
The idea is make use of the callback function. From there you can refactor and clean the code.
Take a look at a working example.
Related
I have a JQM 1.4.2 filterable listview which contain entries in different languages.
I would like to search only within items code, not the whole description, whereby i set the data-filtertext for list items to the item code, e.g. "Apple" or "Banana".
This works ok but now i need an additional language filter, e.g. "EN", "DE", and so on:
...
<li data-filtertext="Apple language_en">
<h2>Title</h2>
<p>Red fruit</p>
<p class="ui-li-aside"><strong>EN</strong></p>
</li>
...
...
<li data-filtertext="Banana language_de">
<h2>Titel</h2>
<p>Beschreibung</p>
<p class="ui-li-aside"><strong>DE</strong></p>
</li>
...
This is my data input:
<form class="ui-filterable">
<div class="ui-grid-a">
<div class="ui-block-a">
<input id="descriptions-input" data-type="search" placeholder="Search..." />
</div>
<div class="ui-block-b">
<fieldset data-role="controlgroup" data-type="horizontal">
<input name="lang-en" id="lang-en" type="checkbox" data-mini="true">
<label for="lang-en">EN</label>
<input name="lang-de" id="lang-de" type="checkbox" data-mini="true">
<label for="lang-de">DE</label>
<input name="lang-fr" id="lang-fr" type="checkbox" data-mini="true">
<label for="lang-fr">FR</label>
</fieldset>
</div>
</div>
</form>
What i try to do now, is that when a checkbox is selected, only the list items belonging to that language are visible.
How can i set this additional filter to my filterable jQuery Mobile listview?
Plunker: http://plnkr.co/edit/TV6rcatzdvaIvQzWBdoI?p=preview
EDIT:
This is the final solution, thanks to EZANKER: https://jsfiddle.net/m64kg5fw/4/
The filterable widget as a filterCallback property: http://api.jquerymobile.com/filterable/#option-filterCallback
You can use this to write a function that checks both the text and which language checkboxes are checked.
$(document).on("pagecreate", "#list-descriptions", function () {
$("#descriptions-list").filterable('option', 'filterCallback', checkedOrMatch);
$("#searchLangs input").on("change", function(){
$("#descriptions-list").filterable("refresh");
});
});
function checkedOrMatch(idx, searchValue) {
var ret = false;
var en = $("#lang-en").is(':checked');
var de = $("#lang-de").is(':checked');
var fr = $("#lang-fr").is(':checked');
var ignoreLang = false;
if (!en && !de && !fr) {
ignoreLang = true;
}
if (searchValue && searchValue.length > 0) {
searchValue = searchValue.toLowerCase();
var filttext = $(this).data("filtertext") || '';
filttext = filttext.toLowerCase();
if (filttext.indexOf(searchValue) < 0) {
ret = true; //filter this one out
} else if (!ignoreLang) {
//found filter text now check language
if ( (filttext.indexOf("language_en") > 0 && !en) || (filttext.indexOf("language_de") > 0 && !de) || (filttext.indexOf("language_fr") > 0 && !fr) ) {
ret = true; //filter this one out
}
}
}
return ret;
}
Updated DEMO
The checkedOrMatch functions runs for each item in the list. It first tests if the entered search text is found in the filter text. If it is, it then sees which language buttons are checked and tests the item for that language. I also added code to re-trigger the filter if the user selects language buttons after typing the search criteria.
NOTE: if the user types in "lang" you might not get what you want... In that case you could move the language designation out of the filter text and into a separate data-attribute.
I have a K-button on kendo grid, when onclick of that button I am expecting to redirect to controller with parameters, but onclick of that button it is not doing anything, even I kept debugger but still no go, it is not at all triggering am I missing anything let me know, I have tried both " and ' along with different format like $(".info").on('click', function ()
CODE
<script id="template" type="text/kendo-template">
#if(ResultFormatID != 3) { #
<input type="checkbox" #= data.Action ? checked="checked" : "" # class=\"check_row\"/>
# } else { #
<input type="button" class="k-button info" name="info" value="Preview" />
# } #
</script>
$('.info').click(function() {
debugger;
var row = $(this).closest("tr");
var item = Grid.dataItem(row);
window.location.href = '/Login/FreeText?profileID=' + rowIDs + '&billid=' + billID;
});
try this code
<a class="info k-button" >Preview</a>
$(document).one('click', '.info', function () {
console.log("clicked");
});
I am atempting to clone a div (multiple times) and add increments so I can parse the results into a database using XML. I only want to clone the form section not the data entered. The Div I am cloning has 3 selects and 2 radios (all of which when added need to be empty).
HTML
<div id="Template1" class="template">
<div class="_100">
<div class="_25"> <fieldset>
<label class="label_analysis" for="analysis">Analyte:</label>
<select class="select_analyte" name="analysis" id="analysis">
<option value="">Select</option>
<option value="TN">TN</option>
<option value="TP,NO2+3">TP,NO2+3</option>
</select> </fieldset></div>
<div data-role="controlgroup" class="_13">
<label><input type="checkbox" data-mini="true" name="Filtered" id="Filtered" value="True">
0.45u Filtered</label>
<label><input type="checkbox" data-mini="true" name="Dup" id="Dup" value="True">
Field Dup</label></div>
<div class="_25"><fieldset>
<label class="label_preserve" for="preserve">Preserved</label>
<select class="select_preserve" name="preserve" id="preserve">
<option value="">Select</option>
<option value="HNO3">HNO₃</option>
<option value="H2SO4">H₂SO₄</option>
</select></fieldset></div>
<div class="_20"> <fieldset>
<label class="label_cool" for="cool">Cooled</label>
<select class="select_cool" name="cool" id="cool">
<option value="">Select</option>
<option value="Ice">Ice</option>
<option value="Frozen">Frozen</option>
<option value="None">None</option>
</select>
</fieldset></div>
<div class="_13">
Add Analyte
Remove</div>
</div>
</div>
<div id="place" class="place"></div>
I have tried two different scripts
This script works as I want to hide the remove button on the original div and only have it appear on the cloned but it doesn't increment.
(function($){
var Template = $('.Template');
var count = 0;
$('.removeNew').hide().on('click', function(e) {
e.preventDefault();
$(this).closest('.Template').remove();
});
$('a.showNew').on('click', function(e) {
e.preventDefault();
var clone = Template.clone(true, true).insertAfter("#place").find('.removeNew').show().end();
});
})(jQuery);
and this one which increments but doesn't hide the remove button
$('#showNew').click(function() {
var num = $('.template').length,
newNum = new Number(num + 1),
newElem = $('#Template' + num).clone(true, true).attr('id', 'Template' + newNum).appendTo('#place');
newElem.find('.analysis').attr('id', 'ID' + newNum + '_analysis').attr('name', 'ID' + newNum + '_analysis').val();
newElem.find('.preserve').attr('id', 'ID' + newNum + '_preserve').attr('name', 'ID' + newNum + '_preserve').val();
newElem.find('.cool').attr('id', 'ID' + newNum + '_cool').attr('name', 'ID' + newNum + '_cool').val();
$('#Template'+ num).after(newElem);
});
})
I am wondering if there is some way to combine them...
I am also having issues as no matter what I seem to try the original div becomes the clone, complete with remove button, while what should be the original div can be changed.
I believe the simplest approach is to have an original copy of the template hidden and base all clones off of that. This fiddle demonstrates this approach.
(function ($) {
var Template = $('#Template');
var count = 0;
var nextId = 0;
Template.find('.removeNew').on('click', function (e) {
e.preventDefault();
$(this).closest('.template').remove();
count--;
});
function cloneTemplate(removable) {
var clone = Template.clone(true, true);
clone.attr('id', clone.attr('id') + nextId);
clone.find('label[for]').each(function( index ) {
var elem = $(this);
elem.attr('for', elem.attr('for') + nextId);
});
clone.find('select, input').each(function( index ) {
var elem = $(this);
elem.attr('id', elem.attr('id') + nextId);
elem.attr('name', elem.attr('name') + nextId);
});
if (!removable) {
clone.find('.removeNew').remove();
}
clone.insertBefore("#addNew").removeClass('hide');
count++;
nextId++;
}
// Create First Analyte and delete the remove button.
cloneTemplate(false);
$('a.showNew').on('click', function (e) {
e.preventDefault();
cloneTemplate(true);
return false;
});
})(jQuery);
It didn't make sense to have the Add New button inside the template so I moved it outside. All new clones are added before the Add New button.
You should notice in the script above that the first element is created by cloning the Template. Then new elements are created calling the same clone function when the Add New button is clicked.
Note: This solution does not include updating element id or name attributes. Something that you almost certainly want to do.
I have tried to use knockoutjs template binding to bind fieldsets dynamically which contain group of radio buttons. Here my problem is mobile radio button css not applying for radio buttons. I have searched in stackoverflow I have found issue for button but i didn't find for radio buttons. So can you please find me the solution
<script type="text/x-jquery-tmpl" id="MobileQuestionTemplate">
<div data-role="fieldcontain">
<div class="divborder">
<label id="l2" for="select-choice-1" class="questiontext" data-bind="text: QuestionText"></label>
<br />
<fieldset data-role="controlgroup" data-mini="true" align="center" data- bind="attr: { visible: QuestionType==13,id:QuestionID+'_fld'},template: {name:'MobileOptionTemplate', foreach: OptionList}"></fieldset>
</div>
</div>
</script>
<script type="text/x-jquery-tmpl" id="MobileOptionTemplate">
<input type="radio" data-bind="attr: {id:QuestionID+'_'+OptionID+'_rbt',val:OptionID,name: QuestionID+'_selectedObjects'}"/>
<label data-bind="text: OptionText ,attr: { for: QuestionID+'_'+OptionID+'_rbt'}" />
</script>
<table id="tblMobileMgrQuestions" data-bind="template: {name:'MobileQuestionTemplate', foreach: MobileManagerviewmodel.ManagerQuestions}">
</table>
Can you please tell me where I need to change the code in js to apply css
$.ajax(
{
url: "/Render/LoadSurveyManagerQuestions?surveyGuid=" + surveyGuid + "&surveyItemGuid=" + rsg,
success: function (result)
{
ko.bindingHandlers['button'] =
{
init: function (element, valueAccessor)
{
debugger;
$(element).button(ko.utils.unwrapObservable(valueAccessor()));
}
}
debugger;
var SurveyManagerQuestion = function (managerQuestions)
{
var Self = this;
Self.ManagerQuestions = ko.observableArray(managerQuestions);
Self.AssignQuestionAnswer = function (option)
{
ko.utils.arrayFirst(Self.ManagerQuestions(), function (question)
{
if (question.QuestionID == option.QuestionID)
{
question.OptionId = option.OptionID;
question.OptionText = option.OptionText;
}
});
};
Self.Save = function ()
{
alert('hi');
};
};
debugger;
MobileManagerviewmodel = new SurveyManagerQuestion(result);
ko.applyBindings(MobileManagerviewmodel, document.getElementById("tblMobileMgrQuestions"));
}
});
Thanks for any help in advance.
To enhance the markup of radio buttons dynamically, use the below.
$('input[type=radio]').checkboxradio().trigger('create')
Hi I found the following code from this page JQuery UI DatePicker using 2 date fields trying to get date difference
However I don't understand the datepicker ui enough to be able to stop the first datepicker from letting you only select from todays date. Im sure its simple but can someone please help!
<script type="text/javascript">
var DatePicked = function() {
var departure = $("#CheckIn");
var arrival = $("#CheckOut");
var nights = $("#Nights");
var triggeringElement = $(this);
var minArrivalDate = new Date();
var departureDate = departure.datepicker("getDate");
if (departureDate != null) {
minArrivalDate.setDate(departureDate.getDate() + 1);
} else {
minArrivalDate.setDate(minArrivalDate.getDate() + 1);
}
arrival.datepicker('option', 'minDate', minArrivalDate);
var arrivalDate = arrival.datepicker("getDate");
if (departureDate != null && arrivalDate != null && triggeringElement.attr("id") != "Nights") {
var oneDay = 1000*60*60*24;
var difference = Math.ceil((arrivalDate.getTime() - departureDate.getTime()) / oneDay);
nights.val(difference);
} else if (departureDate != null && triggeringElement.attr("id") == "Nights") {
var nightsEntered = parseInt(nights.val());
if (nightsEntered >= 1) {
var newArrivalDate = new Date();
newArrivalDate.setDate(departureDate.getDate() + nightsEntered);
arrival.datepicker("setDate", newArrivalDate);
} else {
alert("Nights must be greater than 1.");
}
}
}
$(function() {
$("#CheckIn, #CheckOut").datepicker({
onSelect: DatePicked
});
$("#Nights").change(DatePicked);
DatePicked();
});
</script>
Form:
<form class="enquiry" action="assets/scripts/booking.php" method="get" name="Booking">
<div class="Widget_Form_Spacer">
<label for="CheckIn">Check-In</label>
<input id="CheckIn" name="CheckIn" type="text" class="tF bL" value="<?php echo date("m/d/Y"); ?>" />
</div>
<div class="Widget_Form_Spacer Right">
<label for="CheckOut">Check-Out</label>
<input id="CheckOut" name="CheckOut" type="text" class="tF bL" value="" />
</div>
<div class="Widget_Form_Spacer Short">
<label for="Nights">Nights</label>
<input id="Nights" name="Nights" type="text" class="tF nL" value="1" onclick="clickclear(this, '1')" onblur="clickrecall(this,'1')" />
</div>
<div class="Widget_Form_Spacer Short">
<label for="Adults">Adults</label>
<input name="Adults" type="text" class="tF nL" value="1" onclick="clickclear(this, '1')" onblur="clickrecall(this,'1')" />
</div>
<div class="Widget_Form_Spacer Long">
<input name="Check" type="submit" value="Check Availability" />
</div>
</form>
You can use the minDate jquery UI datepicker option:
$("#date").datepicker({ minDate: new Date() });
Live DEMO