I am working with Joomla's new SubForm code. This allows the user to duplicate a set of inputs and reuse them. Basically a repeatable form.
This form creates the following structure.
<div class="subform-repeatable-group">
<div class="control-group jform_params__content__content0__dc_subheader-cg"></div>
<div class="control-group jform_params__content__content0__dc_typeofcontent-cg"></div>
<div class="control-group jform_params__content__content0__dc_toc_image-cg"></div>
</div>
The issue is that the SubForm is loaded inside the parent form but Joomla sees it as a independent form. Therefore the normal Show/Hide functions no longer work. So I have to create my own.
What do I got and what is not good
This is the generated Select:
<select id="jform_params_theme_selection" name="jform[params][theme_selection]" class="chzn-done">
<option value="3dperspective" selected="selected">3D Perspective</option>
<option value="default">Default</option>
<option value="notheme">Select a theme!</option>
</select>
I already got the piece of code that will check if the select value on the parent form is selected.
$('#jform_params_theme_selection').bind('change', function (e) {
if( $('#jform_params_theme_selection').val() == 'notheme') {
} else if( $('#jform_params_theme_selection').val() == 'default') {
} else if( $('#jform_params_theme_selection').val() == '3dperspective') {
}
}).trigger('change');
Now I can offcourse for each element add it manually like this:
$('[class$="__dc_typeofcontent-cg"]').hide();
But there must be a better way.
What do I want.
I want to use the .hide() function on every item that has the following letters/symbols in its class __dc_ and has as .parents(.subform-repeatable-group)
Bit of extra information
There is another theme that does not have __dc_ but is called __threed_ so I must be able to define the letters/symbols.
I already checked if I could use something with X amount of positions from the front or a X amount of positions from the back but that is constantly changing.
Thanks everyone for helping.
As usual I am going to keep searching and updating this post whenever I get more results.
Could use filter() something like:
var cGroups = $('.subform-repeatable-group .control-group');
var hideTheme = '_dc';
var showTheme = '_threed';
cGroups.filter(function(){
return this.className.indexOf(hideTheme )>-1
}).hide()
cGroups.filter(function(){
return this.className.indexOf(showTheme )>-1
}).show()
DEMO
Your question is a bit convoluted so I focused on the what you want part.
Assuming you don't have much control over the classes that Joomla throws in there, no matter what you're going to need to build a way to capture the parent class and the child sub string you're looking for. But assuming you have both of those, you can make the show hide a bit generic. You can always tell jQ to look for children with a substring within a parent.
$("[class*='"+searchclass+"']",parent)
A fiddle for you: https://jsfiddle.net/dvdxt58f/1/
The most efficient way is the one suggested by charlietfl but there is another way to solve it.
(function ($) {
$(document).ready(function() {
$('#jform_params_theme_selection').bind('change', function (e) {
if( $('#jform_params_theme_selection').val() == 'notheme') {
} else if( $('#jform_params_theme_selection').val() == 'default') {
$( ".subform-repeatable-group div[class*='__threed_']" ).hide();
$( ".subform-repeatable-group div[class*='__dc_']" ).show();
} else if( $('#jform_params_theme_selection').val() == '3dperspective') {
$( ".subform-repeatable-group div[class*='__threed_']" ).show();
$( ".subform-repeatable-group div[class*='__dc_']" ).hide();
}
}).trigger('change');
});
})(jQuery);
Basically you use the * selector and with that you create:
$( ".subform-repeatable-group div[class*='__threed_']" ).hide();
I added this one as it might be useful in some occasions even when I go with charlietfl's answer.
Demo: https://jsfiddle.net/tdo9go2q/11/
Related
I'm using ACF for the first time and struggling to get this to work. I've created a Select field with 2 options (This is controlled backend on the specific page)
<select id="acf-field_5bf80363f0c0f" class="" name="acf[field_5bf80363f0c0f]" data-ui="0" data-ajax="0" data-multiple="0" data-placeholder="Select" data-allow_null="0">
<option value="No Issues">No Issues</option>
<option value="Issues reported" selected="selected" data-i="0">Issues Reported</option>
</select>
What i would like to achive is that if selected option is not equal to No Issues, it would add a custom class (.Error) to the selected div with the id #ServiceStatus1 for example. I've attempted with my limited knowledge of jQuery but no joy.
Hope this makes sense, any advice is really appreciated.
<script type ="text/javascript">
$(function() {
$('#acf-field_5bf80363f0c0f').ready(function(){
$('.Error').hide();
$('#ServiceStatus1' + $('.Error').val() != 'No Issues').show();
});
});
</script>
Your question and your code seem to be asking different questions...
If you want to add/remove a class based on the value in the select, you could do:
$(function() {
function addServiceStatusClass(e){
if($(this).val() != 'No Issues'){
$('#ServiceStatus1').addClass('Error');
}else{
$('#ServiceStatus1').removeClass('Error');
}
}
$('#acf-field_5bf80363f0c0f').ready(addServiceStatusClass);
$('#acf-field_5bf80363f0c0f').change(addServiceStatusClass);
});
Example:
http://jsfiddle.net/m2o361th/2/
But if all you want to do is show/hide #ServiceStatus1 based on the value, you can do:
$(function() {
function addServiceStatusClass(e){
if($(this).val() != 'No Issues'){
$('#ServiceStatus1').show();
}else{
$('#ServiceStatus1').hide();
}
}
$('#acf-field_5bf80363f0c0f').ready(addServiceStatusClass);
$('#acf-field_5bf80363f0c0f').change(addServiceStatusClass);
});
Example:
http://jsfiddle.net/m2o361th/3/
Also as a reminder, if you're using the version of jQuery included with WordPress, you have to wrap your functions in a function mapped to jQuery:
(function($){
// contains one of the above functions...
})( jQuery );
Thank you so much for the above. I've tweaked your above code to factor in that the select field is backend and my div is frontend. The working code for this is...
$(function() {
function addServiceStatusClass(e){
if($('#Multistream').text() != 'No Issues'){
$('#ServiceStatus1').addClass('Error');
}else{
$('#ServiceStatus1').removeClass('Error');
}
}
$('#acf-field_5bf80363f0c0f').ready(addServiceStatusClass);
$('#acf-field_5bf80363f0c0f').change(addServiceStatusClass);
});
})( jQuery );
Imagine a table (actually constructed of divs) with rows and in the final cell in each row, I have an input text and a link that look like this:
<input type="text" name="message" id="message_#Model.IncidentId" value="">
Send a Comment
After each row (the parent div), I have a chunk of code like the following to ajaxify the link and text input:
$('#send_#Model.IncidentId').click(function () {
var msg = $('#message_#Model.IncidentId').val();
if (msg != '') { $(this).attr('href', this.href + '?msg=' + msg) }
$.post(this.href, function (json) {
if (json.jsonResult === null) {
$("#msg_#Model.IncidentId").html("Sent...");
} else {
window.location.href = json.jsonResult;
}
});
return false;
});
It works. However, there are at least 10 of these on each page. What I'm trying to do is consolidate the jquery into one function to handle all the links. Can I use jquery "this" or pass the IncidentId to the jquery function or something? It seems like "this" would not work because the input text is outside of the link? How can I do this to have one function for the entire page?
Keep in mind it's not imperative that I splash everything with the IncidentId. So, if I need to make one or more of the ids or names generic, that would be ok. It just needs to not get confused about what pair it's handling. I've seen some comments that a form might help, but 10+ forms on a page is ok? Plus, as it stands, there will never be any other input fields than what is shown above.
I appreciate your help. Thanks.
Update: So, I basically used Søren's recommended html5 data-* (data-id) attribute in my link, gave it a class name, and then moved my url down to the function as well...and then simply replaced all my #Model.IncidentIds. The one catch is that I had to use the following to register my click event:
$(document).on('click', ".ajax-link", function () {
I guess because I'm using handlebars to dynamically generate the page? I hadn't tested the original function since I moved it to my infinite scroll layout mentioned in the comments. Thanks all for replying.
Try this:
<input type="text" name="message" data-input-id="1" value="">
<a class="ajax-link" href="#" data-link-id="1">Send a Comment</a>
$('.ajax-link').click(function () {
var id = $(this).attr('data-link-id');
var msg = $('[data-link-id='+id+']').val();
if (msg != '') { $(this).attr('href', this.href + '?msg=' + msg) }
$.post(this.href, function (json) {
if (json.jsonResult === null) {
$("[data-link-id='+id+']").html("Sent...");
} else {
console.debug(json.jsonResult);
}
});
return false;
});
Make sure the link and field have the same id
First, make sure you have some useful class name's in place. E.g.,
<input type="text" class="incident-message" name="message" id="message_#Model.IncidentId" value="">
Send a Comment
That should allow you to create a nice, row-generic script like this:
$('.incident-link').click(function(e) {
e.preventDefault();
var $this = $(this),
$row = $this.closest('div'),
$msg = $row.find('.incident-message');
var msg = $msg.val();
if (msg != '') {
$this.attr('href', $this.attr('href') + '?msg=' + msg);
}
$.post($this.attr('href'), function (json) {
if (json.jsonResult === null) {
// I didn't see any markup for your #msg element, but assuming
// that you give it a useful classname, you can do something
// similar to this:
$row.find('.some-msg-className').html('Sent...');
} else {
window.location.href = json.jsonResult;
}
});
});
As far as grouping the events to a single handler, just use a class instead of id's.
$('.thisKind').click(function () {
or if the content is dynamic, use a single event for the parent with a selector in the on() method
$('#parentId').on("click", ".thisKind", function() {
As far as the this usage, you should familiarize yourself with jquery's DOM traversal using closest() to go up the tree and find() to go down
I have a view that loads select elements dynamically into the page on certain button clicks. Each of these selects have the same id value followed with an index value based on how many times the button is clicked. so the id would be like
id="my_id_" + numOfClicks;
I have also given all these selectors the same class value
class="selects"
What is the best way to have an event handler for when the selected option changes in any of the drop downs. right now I have the following:
$('.selects').change(function() {
if($('this option:selected').val() == 0) {
}
else {
}
});
So what I'm trying to do is first get the right select element using "this" then figure out which of the options are selected. Is there a better/more efficient way to do this?
As you say these get added at runtime, you'll want a delegated event handler. Within the handler, as the comments have pointed out, it's just $(this).val() to get the selected value of that select box. So:
$("selector for some container they're in").on("change", ".selects", function() {
if($(this).val() == 0) {
}
else {
}
});
For instance, if they're all inside an element with the class container, then:
$(".container").on("change", ".selects", function() {
if($(this).val() == 0) {
}
else {
}
});
If there's no other suitable container, you can just use $(document).on(..., but usually it's better to handle things a bit closer to where they are than that.
Side note: Values are always strings, but == will coerce, so "0" == 0 is true. Still, it's useful to remember that they're strings.
Assuming html input.selects:
$('body').on('change', '.selects', function() {
if($(this).val() == '0') {
}
else {
}
});
http://jsfiddle.net/r4pxx0yy/1/
No quote around this.
I'm creating a dropdown menu for mobile site
http://gthost.dyndns.org/kudu/en/
when I click on My Account and click on Who we are, submenu still show,,
I Want to hide it after I click on the link.
this is JavaScript code
var $j = jQuery.noConflict();
$j(document).ready(function () {
$j(".account").click(function () {
var X = $j(this).attr('id');
if (X == 1) {
$j(".submenu").hide();
$j(this).attr('id', '0');
} else {
$j(".submenu").show();
$j(this).attr('id', '1');
}
});
//Mouseup textarea false
$j(".submenu").mouseup(function () {
return false
});
$j(".account").mouseup(function () {
return false
});
//Textarea without editing.
$j(document).mouseup(function () {
$j(".submenu").hide();
$j(".account").attr('id', '');
});
});
i would try using:
$('.submenu').css({display:"none"});
instead of .hide();
Two things strike me as odd here.
Why are your ID's integers - valid names start with [a-z_] etc.
Why are you changing the ID? An ID is meant to be a unique identifier and should persist as long as the element does. If you wish to store information about the state of an element within the element itself, then perhaps look into data attributes.
Without seeing your HTML structure everyone is going to be guessing but rather than whatever you are trying to do with the ID's it looks like you could logically use jQuery.toggle:
$j(".account").click(function(){
$j(".submenu").toggle();
});
How can I do that?
event.target returns a HTML object,
and my element is a jQuery object.
Is there a better way to find out if event.target = my_jquery_object, besides comparing IDs or classes?
I want to make sure that it's the same object, not just a element with a similar class...
I tried with $(event.target) !== the_element and it fails
the_element is defined at the begining as $('.something', $(this))
What I am trying to do is to make a box close when the user clicks outside of it, but with the condition that the click wasn't made on the link that opened the box in the first place.
So I have this:
$(document).click(function(event){
if(($(event.target).parents().index(box) == -1)
&& box.is(':visible')){
close();
}
});
And I want to add another condition that verifies that the click wasn't made on the link that opened the box.
This works, but I don't like it:
if($(event.target).attr('id') != the_element)
:)
You can get the actual DOM element from the jQuery using .get(0) or simply the_element[0]. It would probably be better to check with jQuery, though.
if (the_element.is(event.target))
{
...
}
Using your example:
$(document).click(function(event){
if (the_element.is(event.target)) {
return false;
}
if(($(event.target).parents().index(box) == -1)
&& box.is(':visible')){
close();
}
});
Try -
if(event.target === the_element[0])
the_element[0] should unwrap your jQuery object and return a 'normal' DOM object, you can then compare it against the DOM object returned by event.target.
Maybe I'm wrong, but it looks like nobody understood the question?... I also want to know how to GET JQUERY OBJECT on which I used listener function from the EVENT.TARGET, but not a DOM node for a jquery object!!))
So... I found not a very handy, but working solution:
var elem = $('<input type="text" class="input" />');
elem.focus( $.proxy( function( e )
{
this.onInpFocus( e, elem );
}, this ) );
And modified the listener's callback method to receive 2 arguments:
onInpFocus : function( e, inp )
Instead of using simple way like:
elem.focus( $.proxy( this.onInpFocus, this ) );
Actually, I found another way, much more handy one :)
Just need to use the data argument:
Data to be passed to the handler in event.data when an event is
triggered.
Now my code looks like this:
var inp = $('<input type="text" />');
inp.focus( { j : inp } , $.proxy( this.onInpFocus, this ) );
//and the handler method
onInpFocus : function( e )
{
var inp = e.data.j;
...
}