jqGrid: Link in a cell not clickable, and also not link-like - jqgrid

I have used a custom formatter for one of the columns in my jqGrid. Here is the formatter:
formatter: function(cellvalue, options, rowObject) {
var link = $('<a>', {
text: 'Click Me'
href: '#',
click: function() {
alert('sdfsfsd');
// my stuff
}
});
return link[0].outerHTML;
}
There are two problems:
The link is not clickable. When I click the link, the row gets selected! Is there a way to not bypass row selection, but also make the link clickable? [Update: I tried using the beforeSelectRow: function(row, e) { return false;} to disable selection. But still not able to click the link. I can see in the html that the cell value is a link indeed.]
The link is not link like, meaning it is not blue/underlined, as usual it looks like. I have not overidden anything in my CSS.
Help much appreciated!
Thanks
Vivek Ragunathan
UPDATE: I found that this is not a problem with the grid as such. But the click handler does not get linked with the hyperlink. I also tried this code instead but no luck!
var link = $('<a>', {
text: 'Click Me'
href: '#'
}).click(function() {
alert('sdfsfsd');
// my stuff
});
Thanks

Since the link is created dynamically (using jquery), and then the HTML of that object is consumed, the handler will not be part of the HTML. So in this case, the link has to be created out of string directly:
formatter: function(cellvalue, options, row) {
var handler = "someHandlerDefined(" + options.rowId + ")";
return "<a href=# onclick='" + handler + "'>Link</a>";
}
That worked!

Related

Global Expand/ collapse button for jqGrid with subgrids

I am using jqGRid with subgrid configuration to display my data. I would like to have global expand & collapse button to display or hide all subgrid information. Does jqGrid library provide this feature by any means?
jqGrid has no "Expand/Collapse all". I modified the demo from the old answer which demonstrates creating on grid with local subgrids. The resulting demo you can see here:
and it has additional "+" button in the column header of "subgrids" column. If one clicks on the button all subgrids will be expanded:
I used the following code in the demo:
var subGridOptions = $grid.jqGrid("getGridParam", "subGridOptions"),
plusIcon = subGridOptions.plusicon,
minusIcon = subGridOptions.minusicon,
expandAllTitle = "Expand all subgrids",
collapseAllTitle = "Collapse all subgrids";
$("#jqgh_" + $grid[0].id + "_subgrid")
.html('<a style="cursor: pointer;"><span class="ui-icon ' + plusIcon +
'" title="' + expandAllTitle + '"></span></a>')
.click(function () {
var $spanIcon = $(this).find(">a>span"),
$body = $(this).closest(".ui-jqgrid-view")
.find(">.ui-jqgrid-bdiv>div>.ui-jqgrid-btable>tbody");
if ($spanIcon.hasClass(plusIcon)) {
$spanIcon.removeClass(plusIcon)
.addClass(minusIcon)
.attr("title", collapseAllTitle);
$body.find(">tr.jqgrow>td.sgcollapsed")
.click();
} else {
$spanIcon.removeClass(minusIcon)
.addClass(plusIcon)
.attr("title", expandAllTitle);
$body.find(">tr.jqgrow>td.sgexpanded")
.click();
}
});
You can simply make it to behave like as toggle as follows.
Take a button.
onlick of it call the function, say toggleSubgrid();
function toggleSubgrid(){
if($('#YOURGRIDID td').hasClass('sgexpanded')){
$('.ui-icon-minus').trigger('click');
}
else if($('#YOURGRIDID td').hasClass('sgcollapsed')){
$('.ui-icon-plus').trigger('click');
}
}
This will work for all rows that are already loaded. You might need to scope the selector a bit, as fits your needs.
function expandAll () {
$( ".tree-plus" ).click();
};
function collapseAll () {
$( ".tree-minus" ).click();
};

About knockoutjs - how to data-bind with text: and click:

How are you guys? I'm new to the framework Knockoutjs, I wonder if I'm doing it right. (Need a little help.) :)
I have a tag and would contain the same data-bind = text: anything and click: any function. The question is: Is it possible to do this? This is the correct way? Follow what I'm talking about: (I am using an example from the website itself) where when the user clicks the "Click Me" he adds +1 on the counter. I want that when the user clicks the tag call the same function. :)
HTML:
<div>You've clicked <span data-bind='text: numberOfClicks, click: registerClick'> </span> times</div>
JS:
var ClickCounterViewModel = function() {
this.numberOfClicks = ko.observable(0);
this.registerClick = function() {
this.numberOfClicks(this.numberOfClicks() + 1);
};
this.resetClicks = function() {
this.numberOfClicks(0);
};
this.hasClickedTooManyTimes = ko.computed(function() {
return this.numberOfClicks() >= 3;
}, this);
};
ko.applyBindings(new ClickCounterViewModel());
Follows the file jsFiddle: Here
Many thanks in advance.
Yes it is possible to have several binding pairs in one data-bind attribute.
You just have separated them with a comma ,
You asked : I want that when the user clicks the tag call the same function.
But you already code it.
You can click on the counter or on the button it increments the counter.

Add a hyperlink in one of the columns in JQGrid and clicking on Hyperlink should open a new window

I have a jqgrid with certain columns and I need hyperlink in one of the columns, clicking on the hyperlink should open a new window, basically call a window.open().
Also when I call the window.open(), I need the hyperlink column value.
Please provide me with some sample code.Anyhelp would be highly appreciated.
Thanks
Oleg, I tried the below code and it is throwing error "object expected" in load().
{name:'FileName', FileName:'price', width:60, align:"center", formatter:returnMyLink}
function returnMyLink(cellValue, options, rowdata)
{
return "<a href='javascript:load();'>Open Window</a>";
}
function load()
{
var guid = 'CEF9C407-2500-4619-95E3-8E6227B65954';
window.open ('/irj/servlet/prt/portal/prtroot/com.medline.medpack.ExcelViewerPL.ExcelViewer?report=CustomerBenefit&reportId='+guid );
}
I did try the document.delegate to capture the a href event.
$(document).delegate('#CustomerSavingsView .jqgrow td a[href="#"]', 'click',function()
{
alert('test');
}
I was not able to capture this event either.
Sorry Im new to Jquery. Please correct me if Im wrong.
Thanks
This is how I solved it. In the grid complete event added the following code.
hl = "<a href='#Test' target='_blank' id='hlink"+cl+"'>Test</a>";
And then added a event handler for it.
$(document).delegate('#CustomerSavingsView .jqgrow td a[href*="#Test"]', 'click', function ()
{
var guid = 'CEF9C407-2500-4619-95E3-8E6227B65954';
window.open('/irj/servlet/prt/portal/prtroot/com.medline.medpack.ExcelViewerPL.ExcelViewer?report=CustomerBenefit&reportId='+guid );
}
This solved the purpose. Thanks again Oleg and Walter.
maybe this will be help:
in colModel,define a col: {name:'test',formatter:linkformatter}
and in javascript create a function named linkformatter which returns a link;
like:
function linkformatter( cellvalue, options, rowObject){
return '<a href='xxxxxx' />';
}
The predefined formatter 'showlink' can be used to create the link in the grid column. You can use target property of the formatoptions options to define target of the link.
First declare the Jquery JQGrid column definition as follows
colModel: [{ name: 'Notes/Memos', width: "5", sortable: true, classes: 'ellip', resizable: false, formatter: MethodFormatter }]
The formatter property takes the method name which is invoked with the three parameters which internally having the cells value and its id and the following method returns the hyperlink.
function MethodFormatter(cellValue, options, rowObject) {
var selectedRowId = options.rowId;
return '<a href="javascript:MethodJS(' + selectedRowId + ')" style="color: #3366ff" id="' + selectedRowId + '" >' + cellValue + '</a>';}
The following JS Function is invoked after clicking the hyperlink which opens up another page in a window.
function MethodJS(selectedRowId) {
document.location.href = "ViewContact.aspx?NoteID=" + selectedRowId;
}
My approach involves fewer lines of code and gives the solution asked for. In my grid, a column called Project Number is formatted as a hyper link. It opens a new page and passes the project number as a parameter.
colNames: ["Project #", ...],
colModel: [
{ name: 'Project Number', index: 'Project Number', width: 80, key: true, formatter: 'showlink', formatoptions: { baseLinkUrl: 'Details.aspx', target: '_new' } },
Note where I have key: true. Without this, the url returns the row number. The url returned is http://localhost:57631/Details.aspx?id=2103
I'm using jqGrid version 5.0.1
This is my pattern. As I said, it is much more code than Oleg's suggestion of using the showlink formatter, but it is more customizable.
// bind a live event handler to any elements matching the selector 'a.linkWindowOpener'
$('a.linkWindowOpener').live('click', linkWindowOpener);
// colModel settings
{ name: 'ItemDescription', index: 'ItemDescription', formatter: itemDescription_formatter, unformat: itemDescription_unformatter },
// custom formatter to create the hyperlink
function itemDescription_formatter(cellvalue, options, rowObject) {
var html = '';
var itemID = rowObject.itemID;
var itemDescription = cellvalue;
var a = $('<a>')
.attr('href', '/Forms/WorkOrder/ViewItem.aspx?ItemID=' + itemID)
.attr('data-itemDescription', itemDescription )
.html(itemDescription)
.addClass('linkWindowOpener');
html = a.getHtml();
return html;
}
// unformatter to return the raw value
function itemDescription_unformatter( cellvalue, options, cell) {
return $('a', cell).attr('data-itemDescription');
}
// event handler to call when clicking the hyperlink
function linkWindowOpener(event) {
event.preventDefault();
event.stopPropagation();
var o = $(event.currentTarget);
var url = o.attr('href');
window.open(url);
return false;
}
// jQuery extenision function I wrote to get the HTML of an element
// returns the HTML of an element. It works by wrapping the element
// inside a DIV and calling DIV.html(). It then returns the element back to
// it's original DOM location
jQuery.fn.getHtml = function () {
var elm = $(this[0]);
// create a div
var div = $('<div>');
// append it to the parent of the target element
elm.parent().append(div);
// append the element to the div
div.append(elm);
// get the html of the div
var html = div.html();
// move element back to its parent
div.parent().append(elm);
div.remove();
return html;
}

How to get selected text using the Firefox Add-On SDK?

I'm trying to create a Firefox add-on using the online Add-On SDK.
I'm starting with something simple - I want to add a toolbar button that reads the current selected text.
The documentation for the Selection object makes this looks simple enough:
var selection = require("selection");
if (selection.text)
console.log(selection.text);
This doesn't seem to work for me, I just get null.
Here's my complete code:
var selection = require("selection");
require("widget").Widget({
id: "widgetID1",
label: "Test Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
console.log('selection.text = ' + selection.text);
}
});
I've also tried to create the selection object inside the onClick even, with the same effect.
I am able to use the select event to get notified on new selections, so I guess I can use that instead (and keep the value), but I wonder why the above code isn't working... What am I doing wrong?
The selection variable as defined will only have the selected text as long as it is in focus. Clicking on the widget icon takes focus away from the selected text, so it sees no text selected.
Thats why it works when used inside the listener function.
To confirm this, I tried logging its value when a toolbar button is pressed (using the toolbarbutton module), and it works. Pressing a toolbar button (presumably) does not steal focus.
Here's the code, and you can test it online too:
var selection = require("selection");
var tbb = require("toolbarbutton").ToolbarButton({
id: "test",
label: "test",
image: "http://www.mozilla.org/favicon.ico",
onCommand: function(event) {
console.log('selection = ' + JSON.stringify(selection)); // works!
}
});
Here is a solution using the select event:
var selection = require("selection");
var selectedText = '';
function selectionChanged(event){
//todo: check for selection.isContiguous
selectedText = selection.text;
}
selection.on('select', selectionChanged);
require("widget").Widget({
id: "widgetID1",
label: "Test Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
console.log('Selection: ' + selectedText);
}
});

jqGrid trigger "Loading..." overlay

Does anyone know how to trigger the stock jqGrid "Loading..." overlay that gets displayed when the grid is loading? I know that I can use a jquery plugin without much effort but I'd like to be able to keep the look-n-feel of my application consistent with that of what is already used in jqGrid.
The closes thing I've found is this:
jqGrid display default "loading" message when updating a table / on custom update
n8
If you are searching for something like DisplayLoadingMessage() function. It does not exist in jqGrid. You can only set the loadui option of jqGrid to enable (default), disable or block. I personally prefer block. (see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options). But I think it is not what you wanted.
The only thing which you can do, if you like the "Loading..." message from jqGrid, is to make the same one. I'll explain here what jqGrid does to display this message: Two hidden divs will be created. If you have a grid with id=list, this divs will look like following:
<div style="display: none" id="lui_list"
class="ui-widget-overlay jqgrid-overlay"></div>
<div style="display: none" id="load_list"
class="loading ui-state-default ui-state-active">Loading...</div>
where the text "Loading..." or "Lädt..." (in German) comes from $.jgrid.defaults.loadtext. The ids of divs will be constructed from the "lui_" or "load_" prefix and grid id ("list"). Before sending ajax request jqGrid makes one or two of this divs visible. It calls jQuery.show() function for the second div (id="load_list") if loadui option is enable. If loadui option is block, however, then both divs (id="lui_list" and id="load_list") will be shown with respect of .show() function. After the end of ajax request .hide() jQuery function will be called for one or two divs. It's all.
You will find the definition of all css classes in ui.jqgrid.css or jquery-ui-1.8.custom.css.
Now you have enough information to reproduce jqGrid "Loading..." message, but if I were you I would think one more time whether you really want to do this or whether the jQuery blockUI plugin is better for your goals.
I use
$('.loading').show();
$('.loading').hide();
It works fine without creating any new divs
Simple, to show it:
$("#myGrid").closest(".ui-jqgrid").find('.loading').show();
Then to hide it again
$("#myGrid").closest(".ui-jqgrid").find('.loading').hide();
I just placed below line in onSelectRow event of JQ grid it worked.
$('.loading').show();
The style to override is [.ui-jqgrid .loading].
You can call $("#load_").show() and .hide() where is the id of your grid.
its is worling with $('div.loading').show();
This is also useful even other components
$('#editDiv').dialog({
modal : true,
width : 'auto',
height : 'auto',
buttons : {
Ok : function() {
//Call Action to read wo and
**$('div.loading').show();**
var status = call(...)
if(status){
$.ajax({
type : "POST",
url : "./test",
data : {
...
},
async : false,
success : function(data) {
retVal = true;
},
error : function(xhr, status) {
retVal = false;
}
});
}
if (retVal == true) {
retVal = true;
$(this).dialog('close');
}
**$('div.loading').hide();**
},
Cancel : function() {
retVal = false;
$(this).dialog('close');
}
}
});
As mentioned by #Oleg the jQuery Block UI have lots of good features during developing an ajax base applications. With it you can block whole UI or a specific element called element Block
For the jqGrid you can put your grid in a div (sampleGrid) and then block the grid as:
$.extend($.jgrid.defaults, {
ajaxGridOptions : {
beforeSend: function(xhr) {
$("#sampleGrid").block();
},
complete: function(xhr) {
$("#sampleGrid").unblock();
},
error: function(jqXHR, textStatus, errorThrown) {
$("#sampleGrid").unblock();
}
}
});
If you want to not block and not make use of the builtin ajax call to get the data
datatype="local"
you can extend the jqgrid functions like so:
$.jgrid.extend({
// Loading function
loading: function (show) {
if (show === undefined) {
show = true;
}
// All elements of the jQuery object
this.each(function () {
if (!this.grid) return;
// Find the main parent container at level 4
// and display the loading element
$(this).parents().eq(3).find(".loading").toggle(show);
});
return show;
}
});
and then simple call
$("#myGrid").loading();
or
$("#myGrid").loading(true);
to show loading on all your grids (of course changing the grid id per grid) or
$("#myGrid").loading(false);
to hide the loading element, targeting specific grid in case you have multiple grids on the same page
In my issues I used
$('.jsgrid-load-panel').hide()
Then
$('.jsgrid-load-panel').show()

Resources