Wiring up javascript events and passing parameters - javascript

A bit background:
I've got a page with a table and a number of checkboxes. The page is generated in asp.net.
Each row has a checkbox, there's a checkbox in the header, and in certain cells there will be groups of check boxes (you get the picure lots of checkboxes).
Each of these check boxes currently works fine with a little bit of javascript magic in their onclick events.
so you have something like:
<td><input type="checkbox" id="sellRow1" onclick="javascript:highlightRow(this, 'AlternateRowStyle1');"/></td>
Not much of a surprise there then.
Ok so the here's the problem:
So this works fine however I need each of the check boxes to reflect the states of other checkboxes. So for example: the checkbox in the header changes the values of the row checkboxes, changes to the row checkboxes can change the header check box etc.
I know what you're thinking: easy just call that Javascript function highlightRow.
But if I did how would I get the parameters (ok the this is easy but where on earth could I get that 'AlternateRowStyle1'?)
So I guess the question is: Where do I put those parameters so I can get at them with JS in a nice cross browser way. (<PossibleRedHerring>tried putting custom attributes on each checkbox but wasn't sure that was the correct way to go</PossibleRedHerring>), also I'd prefer not having to keep calling back to the server if that's at all avoidable.
(btw sorry if this is a bit badly formatted / written, I'm extraordinarily tired!)
Update:
Ok so in the end I managed to dodge the custom attributes as noticed that there was a hierarchy to the check boxes. This meant I was able to trigger the click event of the child checkboxes (which inturn would call it's childrens' click event etc) luckily in this case the flow will never go in the opposite direction causing an infinite loop (there are a lot of comments / documentation to point this out!)
The only interesting thing with this is the difference between click events in IE and in firefox, chrome and safari. IE allows anything to have a click where as the others limit click to INPUT elements of type button, checkbox, radio, reset or submit. I kind of wanted to use event bubbling to attach the click events to an element that contained a group of checkboxes.
In the end went with a bit of a hack:
// In IE every element supports Click wilst Firefox (also chrome and safari) only supports INPUT elements of type button, checkbox, radio, reset or submit
// https://developer.mozilla.org/en/DOM/element.click
// this function allows both browers to support click on all elements
function FireClickEvent(element)
{
if (element.click)
{
element.click();
}
else
{
// We don't have a click on this element, so add our own.
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
element.dispatchEvent(evt);
}
}
Think that could be somewhat improved but it does the business for now.
Should also admit this was my first shot at proper javascript. It's a bit of a scary language (esp when hitting the dom!) interesting though, am looking forward to spending a bit of time delving in further.

you can do this quite easily by using jquery. you can define some custom attributes on the checkboxes depending upon their position and pick up the value of attributes on click and manipulate the css of rows, checkbox the way you want.
thats how you can define alternate row color for the table using jquery
$("table tr:nth-child(even)").addClass("striped");
<style>
.striped{
background-color:#efefef;
}
</style>

I think custom attributes is indeed your solution, can't see any problem with that. Although I would put something like an alternate-row-style as an attribute of the row, and not as an attribute of the checkbox.

If I understand you correctly; you want to be able to klick on the header and all the checkboxes in that same row will be checked?
I would set a cssclass for the "th"-element and use that same class on each of the "td"-elements.
I would place the alternating class on every second "tr" element. That way you can style differently if it's an alternating item or not.
I would also use jQuery to easily create the js-code.
I would NOT add custom attributes since... well you can't just add your own imaginary attributes, that's why we have html-standards.

Related

Trying to add functionality to select option

In my program the user first enters some data to filter and the result goes to one dropdown select menu lets call this functionality function_1 . If there is only one result the it goes to make another query, lets call this function_2.
My problem here is when i have 2 or more results i should be able to:
1) check out the different options i get by clicking on the select to display all the options with a scrollbar if needed
2) After he saw the options there he clicks on one of them to activate function_2
The usual answers use the "change" event but, wont work if the user picks first default value because there is no change, he would have to pick an undesired result and go back to the first.
Using the click event on the select makes also unnecessary work because it triggers twice (one when i open the dropdown, other when option is selected)
Main problem here i think is the jquery selector, but im not sure if it can be done just with that.
This is an example of what im trying:
// function_1 in ajax
.done(result){
$.each(result.data,function (){
$('#select_ex').append("<option value...... ></option>");
if (result.count()===1){
$('#select_ex').trigger('change');
}
});
}
$('#select_ex option').change(function(){// tried with change, click or focus
function_2();
}
The html contains
<select name="select_ex" id="select_ex" size="0" ></select>
EDIT:
Not related to the duplicate question mentioned, since i already know why it doesnt select the option, besides it doesnt apply either since it only talks about connectors with ID, which is not even the point here (I could do my thing without IDs). Im asking for funcionality similar to ":selected" but with option->click.
Another workaround i thought of is filling the select with an empty/hidden field and set the selected property it, filtering afterwards and using the regular change event... but then the first item would be blank and doesn't seem very logic to me.
So I came to seek for any fresh ideas.
EDIT2
I added a white option for the multiple result and erased it afterwards by adding this line of code to imvain2 solution (where needed)
$("#select_ex option[value='0']").each(function() {$(this).remove();});
Although fixing your change function so that is is called for the select and not the option is important, your problem is the default selected option itself. As you mentioned, if they want the first option, they have to select something else to trigger the change function.
I would recommend adding a "blank" option as the first option and setting it as selected.
var $select_ex = $("#select_ex");
.done(result){
$select_ex.empty().append("<option value='0'>Select Your Ex Below!</option>");
$.each(result.data,function (){
$select_ex.append("<option value...... ></option>");
});
$select_ex.val("0");
}
$select_ex.change(function_2);

Rerender Dynamic Elements when using jQuery Plugin Selectize and Bootstrap-Switch

I am new to jQuery so please go easy, I have a form that will represent an Advanced Search. Users will be able to add rows to refine their specific search.
Each row has 3 elements: A Checkbox & 2 x Select boxes.
As can be seen in the fiddle I am using jquery to clone the row and place the cloned row after the last row.
Everything is working fine except visually I would like the checkbox to use Bootstrap-Switch http://www.bootstrap-switch.org/
And the select boxes to use Selectize https://github.com/brianreavis/selectize.js
Now, when I clone the row with these plugins not active, everything works.
I have NO idea how to re-render or re activate them once a new row is inserted.
Is this something that is plugin specific? Or kind of universal to jquery?
I have read HEAPS of answers on here about similar things but I cannot seem to get it right.
Here is the jquery snippet:
$adSearchForm = $('#adSearchForm');
$adSearchForm.on('click', 'button, input, select, option', function (event) {
console.log("Button Clicked", event)
});
$('#addSearchRow').click(function(event){
$('[data-content=adSearch-3]:first').clone().insertAfter('[data-content=adSearch-3]:last');
// $('.searchByField,.searchOperator').selectize({refreshItems: true});
// $('[data-toggle=switch]').bootstrapSwitch({refreshItems: true});
});
Here is the fiddle, hope its ok. http://jsfiddle.net/CkVQr/6/
Thankyou very much for your help.
Cheers
Plugins change your HTML
There are two major problems you may not be fully aware of with your code:
Whenever you do a .clone() it merely deep clones your DOM element subtree, but not any event handlers bound to cloned elements.
Your .selectize() plugin changes HTML of your form quite considerably, converting input elements to other things. So whenever you clone your already converted select filter row, and subsequently want to run .selectize() on it again, this particular plugin won't find any suitable input elements to convert. Hence it won't work. Everything will just look as it should but won't work.
What can be done?
The main idea is that whenever you clone your search filter row, you have to clone your original HTML and not after it was converted using your plugins.
HTML Templates to the rescue
One of the possibilities is to change you page (and functionality) a bit and put your search filter row in a template and always use that. When you create your first row, you should read the template (and cache it) and add+convert it on your page. When you'd add an additional row, just use the same cached template and add+convert it again.
HTML template
<script id="filterRow" type="text/x-template">
<!-- Your filter rown HTML goes in here -->
</script>
Some Javascript
var cachedTemplate = cachedTemplate || $("#filterRow").html();
...
$('#addSearchRow').click(function(evt) {
var newRow = cachedTemplate.clone(); // clone for reusability
newRow.insertAfter('[data-content=adSearch-3]:last');
newRow.selectize();
...
});

Preserve selection after clicking a custom button in tinyMCE issue

Here is my issue :
I have a custom button with a code onClick. This code modify the selection's parent node, and I would like that my selection stays the same after my code, but tinyMCE disable my selection and give me a caret instead.
I tried getRng() and setRng from tinyMCE API but without success, the results are pretty odd. Sometimes it works and sometimes it deactivate my selection and give me a caret instead. Plus, sometimes it works only 2 times and then my button does not respond.
Here is my code which does not work:
onclick : function() {
range_selection = tinymce.activeEditor.selection.getRng();
//Here is my own code which modify my parent node
tinymce.activeEditor.selection.setRng(range_selection);
}
Problem here is that this range is probably not applicable anymore because of a changed DOm structure. I would use a bookmark to overcome this issue:
var bookmark = ed.selection.getBookmark();
// do what you like to do here
ed.selection.`moveToBookmark`(bookmark);

Changing value of select box in Zurb's Foundation via JavaScript

I'm having difficulty changing the value of select box in Zurb's foundation. I'm using the custom forms which just hides the actual select box and uses an unordered list as the select box.
My problem is that the usual method of changing the value of select box doesn't work:
$('#selectboxID').val('something')
The code above assumes that the value of each of the options in the select box is the same with the text:
<option value="1">1</option>
I also tried:
$($('.dropdown ul li')[1]).addClass('current')
$($('.dropdown ul li')[0]).removeClass('current') //remove current class from the other one
But it doesn't work either.
There's also alternative use case when you're binding on change event yourself, you might not want to trigger it. Code to just force a refresh on select:
Foundation.libs.forms.refresh_custom_select(#jQueryElement, true)
where #jQueryElement is a original hidden select.
You have to trigger "change" event after changing selected index.
Example:
// Change selected option
$('#selectboxID').val('something');
// Or use selectedIndex: $("#selectboxID")[0].selectedIndex = 0;
// Fire change event
$('#selectboxID').trigger('change');
Hope this helps
There have been some modifications to the way that the change event is handled recently in the Foundation code.
You can still achieve what you want using the trigger() method, but you have to add a 'force refresh' flag:
$('#selectboxID').trigger('change', true);
If you are using Foundation 3:
Updated to the latest Foundation 3 release.
Setting selectedIndex, using JQuery's val() or anything which triggers a change event is working out of the box.
If you are using Foundation 4:
This seems to be a regression. As a - hopefully temporary - workaround you can force to update the custom select by using the refresh_custom_selection method, e.g.:
Foundation.libs.forms.refresh_custom_selection($('select'))
Note: It is refresh_custom_selection, not refresh_custom_select!
It is not necessary to use the latter (or trigger('change', true)) because they both completely rebuild the custom select, i.e. they re-copy your select options which involves lots of DOM manipulation and it can slow things down a lot. (Depending on the size of your select options and your other code)
On the other hand refresh_custom_selection just updates the displayed value which is a much more lightweight operation.
PS: Instead of refresh_custom_selection you could also use
$('a.current', $select.next()).text($('option:selected', $select).text());
But that code makes assumptions on the generated HTML, so it is better to stick to the provide utility methods

jQuery searchable checkbox list and tristate checkbox

I'm building a simple asp page on which I have list of peoples with checkbox on left of every name.
I've managed to create a simple jQuery script that allows hiding and showing rows of table based on input:
http://jsfiddle.net/Tq97v/ (first part)
As You can see I can enter part of name and then specific row are hidden.
Using red "x" I can uncheck all checkboxes.
What I'm trying to do now is to change that static red "x" into tristate checkbox.
Don't have idea how to even start.
Do I must add change listener to every checkbox in my list?
Second thing - how to create multiple instances of the same "plugin" on site.
Right now I'm identifying input by it, but it would be nice to call function with that input as param, and it would fine table after that input and create necessary logic.
This way I could call function multiple times on page to have more than one list.
I'm not asking for whole solution (of course it is always welcome :) ) but what I need is idea how to accomplish this in efficient way and as optimized as possible, because sometimes my list has 500+ elements.
P.S. don't look at HTML code, it is ASP generated.
I found this plugin: https://github.com/bcollins/jquery.tristate, but I have no idea how to use it with my list.
UPDATE:
I've managed to turn my code into functions, but right now I must call 3 functions for every list.
Here is my updated code: http://jsfiddle.net/65MEV/4/
How can I change it to one function? Will it be better?
This is my updated code. Still thinking about way of doing that Indeterminate Checkbox instead of my remove image.
UPDATE2
I build working code :)
http://jsfiddle.net/65MEV/9/
But I would like to improve it as much as possible.
Any suggestions are welcome!
A tristate checkbox is like the Three-Portal Device: an illusion.
What you actually want is to make the checkbox indeterminate (by setting the property of the same name to true). To implement this, you will need a change (or click) handler on each checkbox, then you'll need to check if all of them are in the same state, and if not then you set the indeterminate property. It's a hassle, really, because you rarely see indeterminate checkboxes and so most users don't know what to do with them. To be avoided, if possible.
To create multiple instances of the same plugin access elements relatively to an other element.
For example: in your case instead of keeping the item in a jQuery object var $tableRows = $('table.myList tr'); access them in the event.
$('#user_name').keyup(function () {
var sValue = $.trim($('input#user_name').val());
if(lastInput==sValue) return;
var $tableRows = $(this).next().next().find("table.myList tr");
if (sValue == '') {
$tableRows.show();
} else {
$tableRows.each(function () {
var oLabel = $(this).find('label');
if (oLabel.length > 0) {
if (oLabel.text().toLowerCase().indexOf(sValue.toLowerCase()) >= 0) {
$(this).show();
} else {
$(this).hide();
}
}
});
lastInput=sValue;
}
});
and you only have your actual list.
And for the tree state checkbox you don t need a plugin just add a button or link and every click check it status you can keep the status by jQuery data and change the element image according to this data.

Categories