My question might seems long, but I am trying to give relevant information in detail so please bear with me.
I am using tooltipster tooltip plugin (http://iamceege.github.io/tooltipster/) on my website. However my question is more related to JS instead of tooltipster plug in. I am easily able to integrate the tooltip plugin on my website and it is working just fine on images, buttons, etc where the content is static. However, I am populating tables dynamically based on the JSON response and I can't get the tooltip working on the table cells.
First I thought there might be some problem with the plugin. In a flash I switched to bootstrap inbuilt tooltip and I am facing the same problem. I can get bootstrap tooltip to work on other other elements apart from the table cells.
Here is my JS where I am adding the class customToolTip
function addBetTypeProductsToLegend(table) {
var betType = $.data(table, 'BetTableData').betType,
legendRow = $.data(table, 'BetTableData').legendRow,
productNotFount = true,
td;
$.each(betType.products, function(index,value) {
var betTypeHint = 'betTypeId_' + value.id + '_hint';
td = element.create('td');
element.setId(td, value.id);
element.setClassName(td, 'customToolTip'); // adding customToolTip class
element.setTitle(td, window[ 'betTypeId_' + value.id + '_hint']); // setting respective title tags
element.setInnerHtml(td, getBrandBetName(value.name));
legendRow.appendChild(td);
productNotFount = false;
});
// Racing Specials
td = element.create('td');
element.setId(td, betType.id);
element.setInnerHtml(td, betType.name);
if (productNotFount) legendRow.appendChild(td);
}
This is how I am assigning class name and title attributes
var element = {
create: function(htmlIndentifier) {
return document.createElement(htmlIndentifier);
},
setClassName: function(element, className) {
element.className = className;
},
setTitle: function(element, title) {
element.title = title;
}
}
JS plugin initialization
$(document).ready(function() {
$('.customToolTip').tooltipster({
animation: 'fade',
delay: 400,
theme: 'tooltipster-IB',
touchDevices: false,
trigger: 'hover'
});
});
So the above doesn't apply to the table cell I tried to use bootstrap tooltip and initialize the function like this.
$(".customToolTip").tooltip({
placement : 'top'
});
It works fine for other elements apart from table cells.
I tried to set padding as well for tooltip as well
$('.customToolTip').each(function(e) {
var p = $(this).parent();
if(p.is('td')) {
$(this).css('padding', p.css('padding'));
p.css('padding', '0 0');
}
$(this).tooltip({
placement: 'top'
});
});
I followed couple of other posts where people were facing problem with tooltip and table cells
bootstrap "tooltip" and "popover" add extra size in table
https://github.com/twbs/bootstrap/issues/5687
Seems like I have deal with the layout issue later on first I need to show the custom tooltip instead of default title attribute.
Your initialization starts on document ready, when table does not exist in DOM yet. So $('.customToolTip') does not find those.
What you need is to make function, something like this:
function BindTooltips(target) {
target = target || $(document);
target.find('.customToolTip').tooltipster({
animation: 'fade',
delay: 400,
theme: 'tooltipster-IB',
touchDevices: false,
trigger: 'hover'
});
}
And launch it on document ready, so it will find all .customToolTip in your document.
Then after your table is being inserted into dom launch this function again and provide container (table) as argument.
Related
I want to hide certain elements in my already filtered div with mixitup. According to kunkalabs documentation here I should be able to do this by calling the .remove() method.
I tried it on one of theirs examples and I wasn't able to get it working. It always shows an error. I have an example here: https://jsfiddle.net/gtr347mh/
I took this directly from the documentation so I have no idea why it's not working:
var containerEl = document.querySelector('.container2');
var mixer = mixitup(containerEl, {
multifilter: {
enable: true
},
animation: {
effects: 'fade translateZ(-100px)'
}
});
var elementsToRemove = containerEl.querySelectorAll('.toremove');
console.log(elementsToRemove.length)
mixer.remove(elementsToRemove)
.then(function() {
console.log(containerEl.querySelectorAll('.toremove').length);
});
It should hide any div with the class "tohide" but it doesn't.
Is there any way to fix this?
Using slider-pro, I am having trouble getting slide count for the number of slides inside the carousel. I have looked at this solution, but am having no luck. My code looks like this:
$(document).ready(function($) {
$('.slider-pro').sliderPro();
});
var slider = $( this ).data( 'sliderPro' );
$(this).append('<div class="counter"><span class="active">'+ (parseInt(slider.getSelectedSlide()) + 1) +'</span>/'+slider.getTotalSlides()+'</div>');
slider.on( 'gotoSlide', function( event ) {
$(this).find('.counter .active').text(event.index + 1);
});
But I get a console error:
TypeError: slider is undefined, can't access property "getSelectedSlide" of it
I am not much of a jquery guy, so I'm not sure why it is giving me this error when in fact the property getSelectedSlide is defined in the jquery.sliderPro.js file. Perhaps I'm not calling it correctly or need to bind the property to a class or id. I'm not sure. I've tried both, but nothing seems to work.
Thanks so much!
Unfortunately, I'm using the class selector to initialize multiple sliders on the same page with the same parameters. I don't want to use id because I will have to create a unique id for every slider instance, which I don't want and will become unmanageable. I also cannot dynamically generate an id for each slider. An example page is here:
BFMagazine
Right now, I have to hardcode the slider number/total into every slide, which isn't ideal.
The relevant Slider-Pro js used is:
$(document).ready(function($) {
$('.slider-pro').sliderPro({
width: '100%',
arrows: true,
fadeArrows: false,
buttons: false,
fade: true,
fadeDuration: 200,
thumbnailPosition: 'bottom',
thumbnailWidth: 75,
thumbnailHeight: 75,
autoplay: false,
fullScreen: false,
breakpoints: {
480: {
thumbnailWidth: 40,
thumbnailHeight: 40
}
}
});
$.each('.slider-pro', function() {
var slider = $('.slider-pro').data('sliderPro');
$('.slider-pro').append('<div class="counter"><span class="active">' + (parseInt(slider.getSelectedSlide()) + 1) +
'</span>/' + slider.getTotalSlides() + '</div>');
slider.on('gotoSlide', function(event) {
$('.slider-pro').find('.counter .active').text(event.index + 1);
});
});
});
I'm getting a console error:
TypeError: cannot use 'in' operator to search for 'length' in '.slider-pro'
I am using jquery-2.1.4.min.js
Any suggestions would be greatly appreciated.
Thanks so much!
It's a simple issue actually the code you have found is missing some other details regarding how it's being used; that code need to be used inside an object or event handler context so this will refer to the object but in your case you are trying to use it outside so there is no context for this therefore we can't use it as such.
Anyway as you have told you are new to jquery that's fine; what you need to do is instead of using this use the css selector directly if you are "outside", so you have
var slider = $('.slider-pro').data( 'sliderPro' );
// here this is not ok as it is "outside"
$('.slider-pro').append('<div class="counter"><span class="active">'+ (parseInt(slider.getSelectedSlide()) + 1)
+'</span>/'+slider.getTotalSlides()+'</div>');
slider.on('gotoSlide', function( event ) {
$(this).find('.counter .active').text(event.index + 1);
// here this is ok as it is "inside"
});
Update:
You were almost there but instead of using this each you were needed to use this each, the difference between the two is that the second one specially used for Dom nodes and you can use this magic inside to refer to each item without actually giving them any explicit property like ids
$('.slider-pro').each(function(index, element) {
//using $(element) instead of $(this) should work too
$(this).sliderPro({
//..options
});
var slider = $(this).data('sliderPro');
$(this).append('<div class="counter"><span class="active">' + (parseInt(slider.getSelectedSlide()) + 1) +
'</span>/' + slider.getTotalSlides() + '</div>');
slider.on('gotoSlide', function(event) {
$(this).find('.counter .active').text(event.index + 1);
// finds only the .counter and .active inside the current slider divsnot touching .counter and .active of other slider divs
});
});
A brief explanation would be, the $(selector).each(..) loops over all the Dom nodes that match the selector and gives you a context this that will always refer to the current item of the iteration but only within the scope of each function.For instance if matched items are a set of <div>s then you can refer to each <div> individually
I have a table which is copied verbatim from one div to another. I did this so that I could have a fixed table header with a scrollable body. The first div id is #headdiv and the second div class is .bodydiv, and the contents of #headdiv are duplicated into .bodydiv with this function:
$('.bodydiv').html($('#headdiv').html());
And then I modify the display/visibility properties of the two divs to make them look like one table. See here for the html and css: http://jsfiddle.net/jbswetnam/KNnAd/5/
Now, what I want to do is make some help text appear when the user hovers over cells in the table. I can do this with the following functions using element id's:
//Copied and modified from https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
function showInfo(info, display) {
document.getElementById('infoBox').innerHTML = info;
document.getElementById('infoBox').style.display = display;
}
function makeInfoCallback(info, display) {
return function() {
showInfo(info, display);
};
}
function setupInfo() {
var infoText = [
{'id': 'header', 'info': 'Header Row'},
{'id': 'alpha', 'info': 'Alpha'}
];
for (var i = 0; i < infoText.length; i++) {
var item = infoText[i];
document.getElementById(item.id).onmouseover =
makeInfoCallback(item.info, "");
document.getElementById(item.id).onmouseout =
makeInfoCallback("", "none");
}
}
setupInfo();
As you can see at http://jsfiddle.net/jbswetnam/KNnAd/5/, when you hover over the table header, the text "Header Row" appears. What I'm trying to do is make the text "Alpha" appear when you hover over the cell that says "Alpha".
I know why the function works in the header and not the body. The header has an id which is referenced in the function above, whereas the body cells that you see are copied from #headdiv and therefore their id's are not valid. But I don't know enough about Javascript to know how to fix the problem. Using classes instead of id's doesn't work. I have a feeling that I can refactor the whole script using this and perhaps calling the function out of each cell, but I just don't know how to do that.
Any help would be appreciated!
Got it done with this code:
function makeInfo() {
$('.info').hover(
function() {
$('#infoBox').html($(this).attr('info'));
$('#infoBox').css('display', '');
},
function() {
$('#infoBox').css('display', 'none');
});
}
makeInfo();
You can see the updated HTML at the same jsfiddle.
I'm using jqGrid to build a custom inline entry widget on a page. The relevant part of the jqjGrid setup is:
colModel:[ {
// Other columns removed.
{name:'ship',index:'ship', width:90, editable: true, sortable: false,
edittype: "custom",
editoptions:{ custom_element: customElement,
custom_value: customValue} }
],
And my callback function is:
function customElement(value, options) {
var a = $("<input>").attr({
type: 'text',
size: 2,
value: value,
style: 'float: left'
}).add(
$("<span>").attr({
style: 'float: left; margin-top: 2px;',
'class': 'ui-icon ui-icon-search'
}).click(function() {
// My custom function here.
})
).appendTo($("<div>"));
return a;
}
This all works properly.
However, I'm building a library to manage several jqgrid tables on a page. I'd like to use the same function to build the custom elements on several of those tables. The problem is that this particular click() function needs to know which jquery table it's dealing with.
I can get the table ID through a hacky way at the beginning of customElement and pass it in the closure to the function:
var fieldID = options.id;
var rowID = fieldID.replace(/_.*/, "");
var containingTable = $("#" + rowID + "_id").closest("table");
But this assumes that the column "id" exists in the current jqGrid, and it's an earlier (leftward) column. I can't use the "ship" column because it hasn't been created yet. I can't assume there are other rows in the table that would have a "ship" column either.
How can I, in a custom_element handler, reliably get a handle to the "calling" table?
I agree that it's a problem in the current code of jqGrid. There are no simple and elegant way to get the id of the grid for which the control are created.
One workaround you already suggested. I can suggest you one more version to get the id of "the calling table".
Custom element can be used for every editing mode: inline editing, form editing and cell editing. The click handle receive Event object e
.click(function(e) {
// My custom function here.
})
which you can to detect the id of the "the calling grid". In case of inline editing or cell editing the detection is the most easy. It will be
.click(function(e) {
var $grid = $(e.target).closest('table.ui-jqgrid-btable');
...
})
Inside of click event handler of the form editing you can use
.click(function(e) {
// you can do the following
var $t = $(e.target).closest('table.EditTable'),
tid = $t.attr('id'); // id=TblGrid_list
if (typeof tid === "string" && tid.substr(0, 8) === 'TblGrid_') {
var gridId = tid.substr(8);
}
var grid = $('#' + $.jgrid.jqID(gridId));
// or the following
var $f = $(e.target).closest('form.FormGrid'),
fid = $f.attr('id'); // id=FrmGrid_list
if (typeof fid === "string" && fid.substr(0, 8) === 'FrmGrid_') {
var grid_id = tid.substr(8);
}
var mygrid = $('#' + $.jgrid.jqID(grid_id));
...
})
The code above use the fact that the editing form contains two elements which ids will be constructed based on the id of the grid: the <table> element inside of the editing form has the id="TblGrid_list" if the grid id="list" and the <form> element has the id="FrmGrid_list".
The usage of $('#' + $.jgrid.jqID(gridId)) is more safe as $('#' + gridId) because it gives correct results in case when the grid id contain meta characters. The jqID function is very easy (see here). It makes just escaping of the meta characters used in the jQuery selector.
I have a jqGrid with a navBar that has search: true and multipleSearch: true. I would like to add a button to my UI that automatically adds an additional rule to the search.
I've tried manipulating the postData for the filter directly, but values added this way don't show up in the search UI.
I've also tried accessing the search box directly using jQuery, like this:
$('#fbox_list').searchFilter().add();
$('#fbox_list .sf .data input').each(function(index) {
alert($(this).val());
});
But, in addition to feeling hackish, it only works if the user has already clicked on the search button (the fbox_list div is not constructed on load).
Has anyone else dealt with an issue like this?
For the sake of posterity, here is the hack I'm currently using. The grid has an ID of list and the pager has an ID of pager:
jQuery(document).ready(function() {
//Initialize grid.
//Initialize the navigation bar (#pager)
//Hack to force creation of the search grid.
//The filter's ID is of the form #fbox_<gridId>
jQuery('#pager .ui-icon-search').click();
jQuery('#fbox_list').searchFilter().close();
//Example button events for adding/clearing the filter.
jQuery("#btnAddFilter").click(function() {
//Adds a filter for the first column being equal to 'filterValue'.
var postFilters = jQuery("#list").jqGrid('getGridParam', 'postData').filters;
if (postFilters) {
$('#fbox_list').searchFilter().add();
}
var colModel = jQuery("#list").jqGrid('getGridParam', 'colModel');
//The index into the colModel array for the column we wish to filter.
var colNum = 0;
var col = colModel[colNum];
$('#fbox_list .sf .fields select').last().val(col.index).change();
$('#fbox_list .sf .data input').last().val('filterValue');
$('#fbox_list .sf .ops select.field' + colNum).last().val('eq').change();
$('#fbox_list').searchFilter().search();
});
jQuery("#btnClearFilter").click(function() {
$('#fbox_list').searchFilter().reset();
});
});
If you mean the filter toolbar, you can do this: (status is the col name -- so, replace "#gs_status" w/ "#gs_" + your_col_name
jQuery("#distributor_grid").jqGrid('showCol',['status']);
jQuery(".ui-search-toolbar #gs_status")
.val('ALL')
;
$('#distributor_grid').RefreshData(); // triggers toolbar
to clear inputs, selects and reset grid
$("td#refresh_navGrid").click();