How to set active tab of jquery ui tabs using custom function? - jquery-ui

I want to set active tab in jquery ui tabs based on output of a function active_tab(), but active_tab() function do not run when tabs are initialized.
function active_tab()
{
var t = 1;
// some conditions
return t;
}
$( "#tabs1" ).tabs({
active: function(){
active_tab();
}
});

jQuery UI Tabs option for active expects a number, true, or false.
Which panel is currently open. Multiple types supported:
Boolean: Setting active to false will collapse all panels. This requires the collapsible option to be true.
Integer: The zero-based index of the panel that is active (open). A negative value selects panels going backward from the last panel.
I would advise the following type of code:
function active_tab(tbs, i){
if(i == undefined){
i = 0;
}
// Add Other Conditions
tbs.tabs("option", "activate", i);
return i;
}
$("#tabs1").tabs();
activate_tabs($("#tabs1"), 1);
Another method would be:
function active_tab(){
var t = 1;
// some conditions
return t;
}
$("#tabs1").tabs();
$("#tabs1").tabs("option", "activate", activate_tab());
You can also do the following:
$("#tabs1").tabs({
activate: activate_tab()
});

Related

how to retain expand/collapse state in jqgrid grouping?

I have implemented a jqgrid in grouping method. By default I have kept the groups collapsed using groupCollapse:true parameter of jqgrid. My grid works well but When I expand the group and sort a column, the whole grid is reloaded and the expanded state of the column is not retained. How can I retain the expanded state while sorting?
Please write always which version of jqGrid, which you use (can use), and from which fork (free jqGrid, commercial Guriddo jqGrid JS or an old jqGrid in version <=4.7).
Your requirements could be easy realized in "free jqGrid", which I develop. It allows to use groupCollapse as callback function, which returns Boolean (see the issue). In combination with onClickGroup callback or jqGridGroupingClickGroup event one can easy persist the grouping state.
UPDATED: I created the demo https://jsfiddle.net/92da8xhq/, which demonstrates how one can persist the collapsing state in the grouping grid. Below I describe shortly the code. The demo uses one level of grouping to make the code more simple for understanding.
I added custom collapsedGroups: {} parameter to jqGrid. We will use the parameter to hold the list of collapsed groups. I used collapsedGroups: { "test2": true } in the demo to demonstrated that we can create the grid with some collapsed groups at the beginning. We don't use the value of the property of collapsedGroups object. Just the existence of the property test2 for example means that the group with the value test2 has collapsed state.
The demo uses groupCollapse property of groupingView defined as the callback function. The function tests whether the group is in the list of collapsed groups (has collapsedGroups property with some value)
groupingView: {
groupField: ["name"],
groupCollapse: function (options) {
var collapsedGroups = $(this).jqGrid("getGridParam", "collapsedGroups") || {};
// options looks like { group: number, rowid: string }
if (collapsedGroups.hasOwnProperty(options.group.value)) {
return true;
}
return false;
}
}
We adjust additionally the properties of the custom collapsedGroups parameter after expanding/collapsing of the group. We use the following onClickGroup callback:
onClickGroup: function (hid, isCollapsed) {
var p = $(this).jqGrid("getGridParam"),
iGroup = $(this).jqGrid("getGroupHeaderIndex", hid),
group = p.groupingView.groups[iGroup];
if (p.collapsedGroups == null) {
// be sure that the custom parameter is initialized as an empty object
p.collapsedGroups = {};
}
if (isCollapsed) {
// we place group.value in the p.collapsedGroups object as a property
if (!p.collapsedGroups.hasOwnProperty(group.value)) {
// create the property group.value in with some value
p.collapsedGroups[group.value] = true;
}
} else if (p.collapsedGroups.hasOwnProperty(group.value)) {
// remove group.value property from the p.collapsedGroups object
delete p.collapsedGroups[group.value];
}
}
groupingView: {
groupCollapse: true,
groupField: ["name"],
plusicon: 'ace-icon fa fa-plus-square purple',
minusicon: 'ace-icon fa fa-edit red'
}

Get selected columns for a columntoggle table

I have a columntoggle table with some information in it.
I would like to get what are the selected columns, to stock those values in a database and when the user logs back in, using those values to make the table load with the columns he has previously selected.
Is there any way to do this?
Thanks by advance
There is nothing built-in to do this. Here is one way to do it:
jQM creates a column toggle popup with a checkbox for each column assigned a data-priority. The popup takes the id of the table plus '-popup', so you can access the checkboxes with this selector:
$("#myTableid-popup .ui-checkbox label");
Checked items have the class .ui-checkbox-on, while unchecked items have .ui-checkbox-off. Therefore you could get the indexes (indices) of all visible columns:
var selIndex = [];
function SaveSelectedColumns(){
selIndex = [];
$("#myTable-popup .ui-checkbox label").each(function(idx){
if ($(this).hasClass("ui-checkbox-on")){
selIndex.push(idx);
}
});
}
Then to restore visible columns:
function LoadSavedColumns(){
$("#myTable-popup .ui-checkbox label").each(function(idx){
var vis = IsColVisible(idx);
if ($(this).hasClass("ui-checkbox-on") && !vis){
$(this).click();
}
if ($(this).hasClass("ui-checkbox-off") && vis){
$(this).click();
}
});
}
function IsColVisible(idx){
for (var i=0; i<selIndex.length; i++){
if (selIndex[i] == idx) return true;
}
return false;
}
Working DEMO

Datetimepicker`s slowness

I would like to ask you for advice.
On one page I have many jQuery UI datepicker`s. They are visible in Bootstrap Modal when user click on button.
Unfortunately this page is loading very slow(Especially in IE8). I know that datepicker in IE8 is causing slowness but sometime I receive that script stop working.
This is my datetimepicker in Knockout like a custom bindingHandlers
ko.bindingHandlers.datetimepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datetimepickerOptions || {};
$(element).datetimepicker(options);//Line 5
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).datetimepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).datetimepicker("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datetimepicker("getDate");
if (value - current !== 0) {
// LINE 23 $(element).datetimepicker("setDate", value);
}
}
};
I comment Line 23 because before I had the same issue with performance. But then I had the picker like that
<input data-bind="datetimepicker: date,datepickerOptions: { minDate: new Date() }"/>
When I comment it everything works great.
Now I change the do (because I want to have visible datepicker when the modal is shown) and I have the same issue.
When I comment LINE 5 there is no slowness but also my datepicker is not vissible.
Can I call the binding of the datepicker's when user click on button to see the Modal? In this way the binding for datepicker's woudn't be initialized during the page loading?
If I change the jQuery UI datepicker to bootstrap datepicker, there will be some changes in performance?
You could potentially "lazily" initialize your datepicker's. For example, to go along with your existing datepicker binding, you could create a lazyDatepicker binding.
Something like:
ko.bindingHandlers.lazyDatepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//keep the field's value in sync until the datepicker binding has been initialized
var updater = ko.computed(function() {
var options = ko.unwrap(allBindingsAccessor()),
value = $.datepicker.formatDate(options.dateFormat || "mm/dd/yy", ko.unwrap(valueAccessor()));
$(element).val(value);
});
//use "one" so this only fires a single time on initial focus
$(element).one("focus", function() {
//binding will now keep value in sync
updater.dispose();
//apply the actual datepicker
ko.applyBindingAccessorsToNode(element, {
datepicker: valueAccessor,
datepickerOptions: function() { return allBindingsAccessor.get("datepickerOptions"); }
})
});
}
};
Really this just applies the datepicker binding when the field is focused. I also put some logic in there to keep the field up-to-date with the model until the datepicker is actually initialized (the updater computed).
Here is a fiddle: http://jsfiddle.net/rniemeyer/GvLfV/

Custom binding for cleditor fails after sorting elements through knockout sortable

First up: check this fiddle.
I have sortable array of elements created with the Knockout sortable library. When I initially apply the binding the cleditor initializes fine.
However, when sortable elements are sorted, the cleditor fails to re-initialize (I'm not sure what happens but cleditor fails). The cleditor just displays "true" instead of actual value in Firefox, and nothing in all other browsers.
I'm trying to figure out where the problem is, whether it is on the custom binding, or jQuery-UI, or the Knockout sortable library?
I am not recieving any errors in my console.
ko.bindingHandlers.cleditor = {
init: function(element, valueAccessor, allBindingsAccessor) {
var modelValue = valueAccessor(),
allBindings = allBindingsAccessor();
var $editor = jQuery(element).cleditor({
height: 50,
controls: "bold italic underline | bullets numbering | undo redo"
});
$editor[0].change(function() {
var elementValue = $editor[0].doc.body.innerHTML;
if (ko.isWriteableObservable(modelValue)) {
modelValue(elementValue);
} else {
if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].cleditor) {
allBindings['_ko_property_writers'].cleditor(elementValue);
}
}
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()) || '',
$editor = jQuery(element).cleditor();
if ($editor[0].doc.body.innerHTML !== value) {
//$editor[0].doc.body.innerHTML = value;
$editor[0].doc.body.innerHTML = value;
$editor[0].focus();
}
}
};
How can I make the cleditor to work, even after the elements are sorted?
I found this resource, but I couldn't find anything wrong in code as said in that topic.
The link you provided was helpful. The CLEditor refresh method is the right way to update it after it's dragged. It just needs to be done at the correct time, using the sortable stop event.
stop: function(event, ui) {
$(ui.item).find("textarea").cleditor()[0].refresh();
}
http://jsfiddle.net/mbest/rh8c2/1/
I also worked to integrate this into your cleditor binding. In the init function:
jQuery(document).on('sortstop', function(event, ui) {
if (jQuery.contains(ui.item[0], element)) {
jQuery(element).cleditor()[0].refresh();
}
});
I also made a change in the update function to keep the <textarea> value in sync, because refresh updates the editor's value from the <textarea>:
$editor[0].updateTextArea();
http://jsfiddle.net/mbest/jw7Je/7/

Knockout jQueryUI Autocomplete how to use input value if nothing selected from autocomplete list

I am using the custom binding provided in How to create an auto-complete combobox?
I want to allow the user to either select a value from the list of suggestions or enter a value that is not in the list of suggestions. How can I get the value of the input into my observable field?
For example, if the user types 'smi' the autocomplete list will show Smith and other surnames beginning with 'smi', however, if they do not select an option from the list, I just want to set the value of my observable field to be 'smi'. At present, the only way the observable propety is set is when the user selects an item from the list of suggestions.
I have the following code (HTML):
<input type="text" data-bind="
value: surname,
jqAuto: { autoFocus: true },
jqAutoSource: surnames,
jqAutoQuery: surnameAutocomplete,
jqAutoValue: surname"
/>
JavaScript view model (simplified):
var vm = {
surnames: ko.observableArray(),
surname: ko.observable(),
surnameAutocomplete: function (searchTerm, result) {
repository.surnameAutocomplete(searchTerm, result);
};
Solution:
I amended the custom binding handler in two places:
init: function - added the following
// New setting to allow / disallow a user to enter values that are in the autocomplete list.
forceSelection = allBindings.jqAutoForceSelection;
options change function - amended to the following
//on a change, make sure that it is a valid value or clear out the model value
options.change = function (event, ui) {
var currentValue = $(element).val();
// Start: new code, check new setting on whether to force user to make a selection
if (!forceSelection) {
writeValueToModel(currentValue);
return;
}
// End: new code
var matchingItem = ko.utils.arrayFirst(unwrap(source), function (item) {
return unwrap(inputValueProp ? item[inputValueProp] : item) === currentValue;
});
if (!matchingItem) {
writeValueToModel(null);
}
}
I also found that the first item in the autocomplete list was being automatically selected, but then noticed by setting autofocus: false solved my issue, e.g.,
<input type="text" data-bind="
jqAuto: { autoFocus: false }, /* This fixes the auto select issue */
jqAutoSource: surnames,
jqAutoQuery: surnameAutocomplete,
jqAutoValue: surname,
jqAutoForceSelection: false"
/>
If you look closely at the binding handler you're using, you will notice this section:
//on a change, make sure that it is a valid value or clear out the model value
options.change = function(event, ui) {
var currentValue = $(element).val();
var matchingItem = ko.utils.arrayFirst(unwrap(source), function(item) {
return unwrap(item[inputValueProp]) === currentValue;
});
if (!matchingItem) {
writeValueToModel(null);
}
What this section of the binding handler essentially does is check if the text the user entered into the text field matches something in the autocomplete dropdown, and if it doesn't, it clears the model value (which it sounds like what you want to change).
You can either try deleting this section or extend it to suit your purposes.

Resources