I'm developing an application in ZF1, using jQuery Mobile. I have a form (fragment):
$options = array('Employee', 'Supervisor', 'Other');
$form1->addElement('select', 'role', array('multioptions' => $options);
$form1->role->setAttribs(array('onchange', 'showHide()'));
$form2->addElement('text', 'position');
I have a script:
function showHide(){
var hide = false;
if(document.getElementById("form1-role").value === "Employee" ||
document.getElementById("form1-role").value === "Supervisor") {
hide = false;
} else {
hide = true;
}
var i;
var elements = [
"form2-position-label",
"form2-position-element"
];
for(i = 0; i < elements.length; i++) {
if(document.getElementById(elements[i]) !== null) {
document.getElementById(elements[i]).hidden = hide;
}
}
}
The idea is - when user selects 'Other' from the list the Textbox 'position' suppose to hide. Otherwise it should be visible. Everything works fine until form validation returns false - then validator messages appear and script stops working.
What is interesting - when I put alert("hello"); to the script, it does show the alert but still doesn't hide the textbox.
You can remove your $form1->role->setAttribs(array('onchange', 'showHide()')); and use this (seeing as you have jQuery on the page anyway).
$(function(){
$('#form1-role').on('change', function(){
var role = $(this).val();
$('#form2-position-label, #form2-position-element')
.toggleClass('hidden', role !== 'Employee' && role !== 'Supervisor');
});
});
This toggles a class on the target elements. So the CSS is simple:
.hidden {
display: none;
}
If you want this to activate on the page rendering as well (i.e. if there is an error message to display), you can put .change(); at the end of the on call.
$(function(){
$('#form1-role').on('change', function(){
var role = $(this).val();
$('#form2-position-label, #form2-position-element')
.toggleClass('hidden', role !== 'Employee' && role !== 'Supervisor');
}).change();
});
This will trigger a change event as soon as the page renders and execute the logic within the handler.
Related
In HTML5 I have a dropdown menu . When choosing different options I hide or show different parts of my page. Here is that script:
document
.getElementById('target')
.addEventListener('change', function () {
'use strict';
var vis = document.querySelector('.vis'),
target = document.getElementById(this.value);
if (vis !== null) {
vis.className = 'inv';
}
if (target !== null ) {
target.className = 'vis';
}
});
However what I want to do now, in another script is to preload an option from the dropdown. I can do it easily with this script:
setSelectedIndex(document.getElementById('target'),'content_1');
function setSelectedIndex(s, valsearch)
{
// Loop through all the items in drop down list
for (i = 0; i< s.options.length; i++)
{
if (s.options[i].value == valsearch)
{
// Item is found. Set its property and exit
s.options[i].selected = true;
break;
}
}
return;
}
This is where my problem comes up, my dropdow will get the value I want, but the part that I want to be shown when choosing that option won't come up.
That is because change events need to happen from the browser.
When the user commits the change explicitly (e.g. by selecting a value
from a 's dropdown with a mouse click, by selecting a date
from a date picker for , by selecting a file in the
file picker for , etc.);
If your using Jquery you can:
$("#id").val("value").trigger('change');
or you can use javascript if your not worried about building the event object:
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
element.dispatchEvent(evt);
}
else
element.fireEvent("onchange");
I would recommend moving your anonymous onchange function into a named function that you can call once onload, and again onchange.
Here is the function I wrote:
function setContent(id) {
//get the current visible content
var vis = document.querySelector('.vis');
//get the target element by id
var target = document.getElementById(id);
//make current vis element inv
if (vis) vis.className = "inv";
//make target element vis
if (target) target.className = 'vis';
}
and a fiddle
edited: got rid of querySelectorAll to stick closer to OP original code and updated fiddle. clarified and commented code.
The problem you have is changing a vale or the selected value of an input with JavaScript does not trigger any change event. So you would need to manually trigger the event.
function setSelectedIndex(s, valsearch)
{
// Loop through all the items in drop down list
for (i = 0; i< s.options.length; i++)
{
if (s.options[i].value == valsearch)
{
// Item is found. Set its property and exit
s.options[i].selected = true;
break;
}
}
//Setting the selected value with JavaScript does not trigger the change event so you need to manually trigger the change event
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
s.dispatchEvent(evt);
} else {
s.fireEvent("onchange");
}
return;
}
I'm having this webpage
http://pocolocoadventures.be/reizen/
And it should filter (with isotope.js) the travelboxes on the page.It does in safari, chrome, firefox, opera, .. but in IE, the filter doesn't work. Even worse, JS doesn't react at all at a click event on te span.
This is the piece of js
// Travel Isotope
var container = $('#travel-wrap');
container.isotope({
animationEngine : 'best-available',
itemSelector: '.travel-box ',
animationOptions : {
duration : 200,
queue : false
},
});
$(".filters span").click(function(){
var elfilters = $(this).parents().eq(1);
if( (elfilters.attr("id") == "alleReizen") && elfilters.hasClass("non-active") )
{
$(".label").each(function(){
inActive( $(this) );
});
setActive(elfilters);
}
else{
//set label alleReizen inactive
inActive( $("#alleReizen") );
if( elfilters.hasClass("non-active") ){
setActive(elfilters);
}
else{
inActive(elfilters);
}
}
checkFilter();
var filters=[];
$(".search.filters").children().each(function(){
var filter = $(this).children().children().attr("data-filter");
if( $(this).hasClass("non-active") ){
filters = jQuery.grep(filters, function(value){
return value != filter;
});
}
else{
if(jQuery.inArray(filter,filters) == -1){
filters.push(filter);
}
}
});
filters = filters.join("");
filterItems(filters);
});
function filterItems(filters){
console.log("filter items with filters:" + filters);
container.isotope({
filter : filters,
}, function noResultsCheck(){
var numItems = $('.travel-box:not(.isotope-hidden)').length;
if (numItems == 0) {
$("#no-results").fadeIn();
$("#no-results").css("display", "block");
}
else{
$("#no-results").fadeOut();
$("#no-results").css("display", "none");
}
});
}
function setActive(el){
el.removeClass("non-active");
var span = el.find('i');
span.removeClass("fa-check-circle-o").addClass("fa-ban");
}
function inActive(el){
el.addClass("non-active");
var span = el.find('i');
span.removeClass("fa-ban").addClass("fa-check-circle-o")
}
function checkFilter(){
var filterdivs = $('.filters span').parent().parent();
if( filterdivs.not('.non-active').length == 0 ){
setActive( $("#alleReizen") );
}
var filterLabels = $(".filters .label");
if( filterLabels.not('.non-active').length == 0){
setActive( $("#alleReizen") );
}
}
function noResultsCheck() {
var numItems = $('.item:not(.isotope-hidden)').length;
if (numItems == 0) {
//do something here, like turn on a div, or insert a msg with jQuery's .html() function
alert("There are no results");
}
}
Probably something small and stupid; but I can't find it..
Thanks in advance!
On your website you've build the buttons like this:
<button>
<span>
</span>
</button>
Now the button element is designed to be a button. It differs from the input button. In the latter you'd set the caption using value. In the button element you set it as a text node. The button element can contain elements like a span. The spec isn't very clear about whether or not you should have event handlers on the children of the button element. It's a browser developers interpretation of allowing it or not.
This problem has been posted here before (a few times)
span inside button, is not clickable in ff
Missing click event for <span> inside <button> element on firefox
It seems that Firefox is allowing it, based upon your findings. IE isn't. So to be on the safe side: use the button the way it was intended.
Wrap the button inside a span (not really logical)
Put the click handler on the button.
$(".filters button").click(...);
played around in the console a bit, and this seemed to work well.
$(".filters").on('click', 'span', function(){
// foo here
console.log('foo');
});
Maybe the filters are manipulated by one of your js files after page load?
.on will allow you to select a container which listens on changes that happen inside it, passing the element you want the actual action to work on.
If it's ok for you, I'd suggest to use the <button> element, instead of the <span>.
Let me know if that works for you.
I have this scenario, I am detecting all forms on a site: document.forms
And I am trying to detect which forms are visible and which are not visible.
var formElement = []
for (i=0,l=document.forms.length;i<l;i++){
var formIndex = document.forms.item(i);
if (<need here just visible forms>){
formElement.push(formIndex);
}
}
Just to say I am doing this over an other pop up window that is communicating with the browser window with that forms, this depends on jQuery being present on the host site so jQuery is not a solution.
What is the best way to do this.
var isVisible = form.style.display != 'none';
UPDATE #1: hidden attribute
Also the element can be invisible if hidden attribute is specified, so the condition
could be changed to
var isVisible = form.style.display != 'none' && !form.hasAttribute('hidden');
UPDATE #2: jQuery approach:
Find all invisible forms:
$('form:hidden');
or
$('form:not(:visible)');
Find all visible forms:
$('form:visible');
Check is form visible:
$(form).is(':visible');
UPDATE #3: particular case (for original code in question)
It's working pretty well to determine visible forms using a function from my demo:
function isVisible(el) {
return el.style.display != 'none' && !el.hidden;
}
var formElement = [];
for (i=0, l=document.forms.length; i<l; i++) {
var formIndex = document.forms.item(i);
if(isVisible(formIndex)) {
formElement.push(formIndex);
}
}
console.log(formElement);
It's the same loop is this one in demo:
for(var i = document.forms.length; 0 < i--;) {
log('Form #' + i + ': ' + isVisible(document.forms[i]));
}
DEMO
UPDATE #4: pop-up window
I've adapted my example for pop-up window, but I have to say that you're NOT ABLE to deal with elements in document from other host - both pop-up and opener windows should belong to same host.
<script type="text/javascript">
var wnd = window.open('popup.html');
function isVisible(el) {
return el.style.display != 'none' && !el.hidden;
}
wnd.onload = function() {
/* This is working pretty well: */
var formElement = [];
console.log(wnd.document.forms);
for (i=0,l=wnd.document.forms.length;i<l;i++){
var formIndex = wnd.document.forms.item(i);
console.log(formIndex);
if (isVisible(formIndex)){
formElement.push(formIndex);
console.log('Form ' + formIndex.id + ' is visible');
}
}
};
</script>
var forms = document.getElementsByTagName("form");
Then, you can loop through the array and check to see if the tag is visible or not.
You can use this:
$(element).is(":visible") // Checks for display:[none|block], ignores visible:[true|false]
Ref. How do I check if an element is hidden in jQuery?
you can use :
$('#form').is(':visible')
The following will go through all forms and tell which ones are visible and which aren't:
$("form").each(function() {
if ($(this).is(":visible")) {
console.log("Visible: ", this);
} else {
console.log("Hidden: ", this);
}
});
or if you want to get all visible ones at once:
$("form:visible")
And the hidden ones:
$("form:hidden")
function customAlert(inputID,msg){
var div = $(".errorPopup");
div.css({"display":"block"});
$("#"+inputID).addClass("CO_form_alert").parent().addClass("alertRed");
if (div.length == 0) {
div = $("<div class='ErrorPopup' onclick='$(this).hide();'></div>");
$("body").prepend(div);
}
div.html(msg)
}
I am using the above jquery to hijack my form's javascript validation and error handling. It's working well, except I need to clear the error messaging and styling once the user clicks back into the field to correct it.
EDIT:
based on answers below, got it working - but I need to remove the focus on the field for IE (it already does this in firefox) -
<!--Jquery function to override JS alert with DOM layer alert message-->
function customAlert(){
var args = arguments;
if(args.length > 1) {
// check that custom alert was called with at least two arguments
var msg = args[0];
$("li").removeClass("alertRed");
$("input").removeClass("CO_form_alert");
$("select").removeClass("CO_form_alert");
var div = $(".errorPopup");
div.css({"display":"block"});
if (div.length == 0) {
div = $("<div class='errorPopup' onclick='$(this).hide();'></div>");
$("body").prepend(div);
}
div.html(msg);
for(var i = 1; i < args.length; i++) {
var inputID = args[i];
$("#"+inputID).addClass("CO_form_alert").parent().addClass("alertRed");
$("#"+inputID).focus(function(){
$(this).unbind('focus'); // remove this handler
$('.errorPopup').hide(); // hide error popup
});
}
}
}
$(":input").keypress(function(event) {
$(".ErrorPopup").html("");
});
Hide the error popup div on the input's focus event:
$('#' + inputID).focus(function() { $('.ErrorPopup').hide(); });
Try this:
function customAlert(inputID,msg){
var div = $(".errorPopup");
div.css({"display":"block"});
$("#"+inputID).addClass("CO_form_alert").parent().addClass("alertRed");
if (div.length == 0) {
div = $("<div class='errorPopup' onclick='$(this).hide();'></div>");
$("body").prepend(div);
}
div.html(msg);
$("#"+inputID).focus(function(){
$(this).unbind('focus'); // remove this handler
$(this).removeClass("CO_form_alert")
.parent().removeClass("alertRed"); // undo changes
$('.errorPopup').hide(); // hide error popup
});
}
I am designing a page where it displays the staff details in following structure :
user can click anywhere in the details box and the checkbox will get selected along with the change in the className of the details <div> box.
The problem i m facing is when i click anywhere in the details box it works fine.. but when i click on checkbox it only changes the className but doesnt make any changes to checkbox.
Also there is one condition, few users are allowed to selected limited staff at a time and few are allowed to select all of them..
I have assigned a myClick() function to the outer <div> box (one with red border)
and the function is :
var selectedCount = 0;
myClick = function(myObj,event)
{
var trgt =(event.srcElement) ? event.srcElement : event.target;
tgName = trgt.tagName;
//following statement gives me correct details element event though i clicked on any child tags
theElem = (tgName == 'DIV') ? trgt : ( (tgName == 'B') ? trgt.parentNode.parentNode : trgt.parentNode);
if(allowed_selection == 'unlimited')
{
if(theElem.className == 'details_clicked')
{
theElem.className = 'details';
theElem.getElementsByTagName('input')[0].checked = false;
}
else if(theElem.className == 'details_hover')
{
theElem.className = 'details_clicked';
if(tgName != 'INPUT') theElem.getElementsByTagName('input')[0].checked = true;
}
}
else
{
if(theElem.className == 'details_clicked')
{
theElem.className = 'details';
theElem.getElementsByTagName('input')[0].checked = false;
selectedCount--;
}
else if(theElem.className == 'details_hover')
{
if(selectedCount == allowed_selection ) return false;
theElem.className = 'details_clicked';
//i think, this is the suspicious area for errors
theElem.getElementsByTagName('input')[0].checked = true;
selectedCount++;
}
}
return false;
};
The problem is these return lines in your function:
return false;
When you connect an event to a form element that performs an action, such as a checkbox or button, returning false will prevent that default action. It stops the event from taking place as it regularly would.
You could try something like this at the top of your function:
var returnValue = (tgName == 'INPUT' && trgt.type == "checkbox") ? true : false;
And then when calling 'return ', use:
return returnValue;
If you return true you allow the checkbox to act as normal and check / uncheck itself.