jqGrid - modal forms for custom operations - forms

In most of my grids, if I want to perform a "custom operation" that displays some data in a jqGrid modal form and allow the users to click "submit" to do something, I am able to simply leverage the existing "Edit" operation and tweak it to my needs.
However, I am working on a grid where the Add, Edit, and Delete operations are all in use, and I need an additional "custom operation" that opens a jqGrid modal form to display a couple of the columns along with a submit button to send the key ID to the target URL.
Normally this is very easy to simply re-task the Edit function, but since Edit is in use, I'm not sure how to do this. Does jqGrid have a proper method for creating new custom operations that display modal forms just like Edit does?

In the end, I was not able to find a way to do this through "core" jqGrid features and ended up simply adding a new button to the grid which opens my own custom modal box.
The multi-select features of jqGrid were also used to allow the user to select multiple records to be passed off to this custom function when the new button is clicked.
Here was the code for adding the button to jqGrid. The AJAX call retrieves the HTML content for the modal that is being populated (in JSON format):
.navButtonAdd('#listAllSupplierPurchasesGridPager', {
caption: "Mark Paid",
buttonicon: "ui-icon-add",
onClickButton: function () {
var s;
s = $("#listAllSupplierPurchasesGrid").jqGrid('getGridParam', 'selarrrow');
if (s.length > 0) {
// Make AJAX call to get the dynamic form content
$.ajax({
cache: false,
async: true,
type: 'POST',
url: "/TargetItems/MarkPurchasesPaidRequest",
data: {
PurchaseIds: JSON.stringify(s)
},
success: function (content) {
// Add the content to the div
$('#MarkPurchasePaidModal').html(content);
// Display the modal
$("#MarkPurchasePaidModal").dialog("open");
},
error: function (res, status, exception) {
alert(status + ": " + exception);
},
modal: true
});
}
},
position: "first"
})
The jQuery for setting up the basic modal box:
$("#MarkPurchasePaidModal").dialog({
autoOpen: false,
width: 768,
autoheight: true,
show: {
effect: "blind",
duration: 250
},
modal: true
});
And the div HTML to hold the modal:
<div id="MarkPurchasePaidModal" role="dialog" title="Mark Purchases Paid" class="container"></div>

Related

Tinymce Windowmanager.open() Parameters

I use wordpress and currently writing a plugin for the tinymce-editor. I use the windowmanager.open() function to show a modal, but I dont know how to hide the ok button in this modal. The official documentation is very slim: https://www.tinymce.com/docs/api/tinymce/tinymce.windowmanager/#open
I assume you are creating the modal as per the documentation link you provide, if so, then the buttons parameter let you specify the buttons to add to the modal and the actions of said buttons, like this:
tinymce.activeEditor.windowManager.open({
url: 'file.htm',
buttons: [{
text: 'Accept',
subtype: 'primary',
onclick: 'submit'
},
{
text: 'Custom',
onclick: function(){
//Add custom action here
}
},
{
text: 'Close',
onclick: 'close'
}
],
width: 320,
height: 240
}, {
custom_param: 1
});
passing an empty buttons parameter gives no buttons in the modal, the 'submit' and 'close' strings in onclick button's parameter make the buttons perform those actions, you can add custom logic by defining an anonymous function instead, you can also add custom logic to the 'submit' action by adding the onsubmit parameter, like this:
onsubmit: function() {
//custom logic
}
Tinymce documentation is not much help, I've been researching something similar this past days, these links might be useful for you:
https://www.tinymce.com/docs/api/tinymce/tinymce.plugin/
https://docs.contenido.org/display/CONDEVE/TinyMCE+4#TinyMCE4-Writingownplugins

Is it possible to have a date input in a w2ui toolbar

I am wondering if there is any way one could place a date input control in a toolbar similar to the one used for date input on a form?
Yes, it's possible, but it's quirky.
You will have to define the input field as a toolbar button:
{ type: 'html', id: 'roles', html: '<input id="id_role">' },
and in the toolbar's onRefresh() event you will have to cast the input to the desired w2filed:
onRefresh: function(event) {
if(event.target == 'roles'){
// w2field in toolbar must be initialized during refresh
// see: https://github.com/vitmalina/w2ui/issues/886
event.onComplete = function(ev){
$("#id_role").w2field('list', { items: roles });
};
}
},
In my example I'm inserting a drop down list, but you can adjust it to your needs.
Please see https://github.com/vitmalina/w2ui/issues/886 for an "official" reply.

Dynamically updating a TinyMCE 4 ListBox

I'm trying to modify the TinyMCE 4 "link" plugin to allow users to select content from ListBox elements that are dynamically updated by AJAX requests.
I'm creating the ListBox elements in advance of editor.windowManager.open(), so they are initially rendered properly. I have an onselect handler that performs the AJAX request, and gets a response in JSON format.
What I need to do with the JSON response is to have it update another ListBox element, replacing the existing items with the new results.
I'm baffled, and the documentation is terribly unclear. I don't know if I should replace the entire control, or delete items and then add new ones. I don't know if I need to instantiate a new ListBox control, or render it to HTML, etc.
Basically, I have access to the original rendered ListBox (name: "module"} with
win.find('#module');
I have the new values from the AJAX request:
var data = tinymce.util.JSON.parse(text).data;
And I've tried creating a new Control configuration object, like
newCtrlconfig = {
type: 'listbox',
label: 'Class',
values: data
};
but I wouldn't know how to render it, much less have it replace the existing one.
I tried
var newList = tinymce.ui.Factory.create(newCtrlconfig);
and then
newList.renderHtml()
but even then, the rendered HTML did not contain any markup for the items. And examining these objects is just frustrating: there are "settings", "values", "_values", "items" all of which will happily store my values, but it isn't even clear which of them will work.
Since it's a ListBox and not a simple SELECT menu, I can't even easily use the DOM to manipulate the values.
Has anyone conquered the TinyMCE ListBox in 4.x?
I found this on the TinyMCE forum and I have confirmed that it works:
tinymce.PluginManager.add('myexample', function(editor, url) {
var self = this, button;
function getValues() {
return editor.settings.myKeyValueList;
}
// Add a button that opens a window
editor.addButton('myexample', {
type: 'listbox',
text: 'My Example',
values: getValues(),
onselect: function() {
//insert key
editor.insertContent(this.value());
//reset selected value
this.value(null);
},
onPostRender: function() {
//this is a hack to get button refrence.
//there may be a better way to do this
button = this;
},
});
self.refresh = function() {
//remove existing menu if it is already rendered
if(button.menu){
button.menu.remove();
button.menu = null;
}
button.settings.values = button.settings.menu = getValues();
};
});
Call following code block from ajax success method
//Set new values to myKeyValueList
tinyMCE.activeEditor.settings.myKeyValueList = [{text: 'newtext', value: 'newvalue'}];
//Call plugin method to reload the dropdown
tinyMCE.activeEditor.plugins.myexample.refresh();
The key here is that you need to do the following:
Get the 'button' reference by taking it from 'this' in the onPostRender method
Update the button.settings.values and button.settings.menu with the values you want
To update the existing list, call button.menu.remove() and button.menu = null
I tried the solution from TinyMCE forum, but I found it buggy. For example, when I tried to alter the first ListBox multiple times, only the first time took effect. Also first change to that box right after dialogue popped up didn't take any effect.
But to the solution:
Do not call button.menu.remove();
Also, the "hack" for getting button reference is quite unnecessary. Your job can be done simply using:
var button = win.find("#button")[0];
With these modification, my ListBoxes work just right.
Whole dialogue function:
function ShowDialog() {
var val;
win = editor.windowManager.open({
title: 'title',
body: {type: 'form',
items: [
{type: 'listbox',
name: 'categorybox',
text: 'pick one',
value: 0,
label: 'Section: ',
values: categories,
onselect: setValuebox(this.value())
},
{type: 'listbox',
name: 'valuebox',
text:'pick one',
value: '',
label: 'Page: ',
values: pagelist[0],
onselect: function(e) {
val = this.value();
}
}
]
},
onsubmit: function(e) {
//do whatever
}
});
var valbox = win.find("#valuebox")[0];
function setValuebox(i){
//feel free to call ajax
valbox.value(null);
valbox.menu = null;
valbox.settings.menu = pagelist[i];
// you can also set a value from pagelist[i]["values"][0]
}
}
categories and pagelist are JSONs generated from DB before TinyMCE load. pagelist[category] = data for ListBox for selected category. category=0 means all.
Hope I helped somebody, because I've been struggling this for hours.
It looks like the tinyMCE version that is included in wordpress 4.3 changed some things, and added a state object that caches the initial menu, so changing the menu is not enough anymore.
One will probably have to update the state object as well. Here is an example of updating the menu with data coming from an ajax request:
editor.addButton('shortcodes', {
icon: 'icon_shortcodes',
tooltip: 'Your tooltip',
type: 'menubutton',
onPostRender: function() {
var ctrl = this;
$.getJSON( ajaxurl , function( menu) {
// menu is the array containing your menu items
ctrl.state.data.menu = ctrl.settings.menu = menu;
});
}
});
As far as I can tell, these other approaches are broken in TinyMCE 4.9.
After spending most of the day tinkering to fix my own usage of these approaches, this is the working function I've found:
function updateListbox(win, data) { // win is a tinymce.ui.Window
listbox = win.find('#listbox'); // Substitute your listbox 'name'
formItem = listbox.parent();
listbox.remove();
formItem.append({
label: 'Dynamic Listbox',
type: 'listbox',
name: 'listbox',
values: data
});
}

IE does not pick up form processing data in inputs in a jQuery Dialog

I have an HTML5 page with several data inputs inside a jQuery Dialog box. I sweep this data into form processing with the input attribute form=dataInput. It works fine in Firefox and Chrome, but not in IE because IE does not support the input form attribute. Something about the Dialog widget makes input box elements 'invisible' to form processing. The form attribute fixes this for browsers that support HTML5, but no released IE has this support. I tried $('.ui-dialog').appendTo('form'); in the Dialog open: option, but it does not fix the problem. Is there a way to get IE to sweep input data out of a Dialog widget and into $_POST ?
Here is a sample of an input box inside the Dialog
<label><input type="radio" id="unitedStates" name="country" form="dataInput" value="US">United States</label>
I use the jQuery Form plug-in to perform the submit. It has some options, like beforeSubmit and beforeSerialize, but I don't understand the documentation or the submit process well enough to know if they can be used to solve this problem. Please be specific with code or tutorials. I'm new enough to this that I don't follow general instructions well. ;-) (BTW, IE has the other feature support I need, just not this one.)
Here's my code with Andrew Hagner's suggestion and my modification. Dialog works, but IE does not set a value for the country. What needs to change?
var countrySelected = $("input[type=radio][name=country]").val(); //set earlier by W3C geocoding
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
countrySelected = $('input[name=country]:checked').val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Updated:
// Before you enter dialog, assign the element you will
// be grabbing the info from to a variable.
var countrySelectionElement = $("input[type=radio][name=country]").val();
var countrySelected = "";
var countryChooser = $('#countryChoices').dialog( {
autoOpen: false,
bgiframe: true,
height: 300,
width: 850,
resizable: false,
draggable: true,
title: "Click to select another country",
open: function () {
$('#regions').tabs(
{
event: "mouseover",
})
},
buttons: {
'Close / continue location input': function ()
{
// Since jQuery won't work in here, use the variable
// we assigned above to access value.
countrySelected = countrySelectionElement.val();
$(this).dialog('close');
}
}
});
//then later on
getCityFromGeonames3Step(countrySelected);
Original:
Before you open the dialog assign the input to a variable:
function OpenDialog()
{
var input = $("yourinput");
// Open dialog, use input to work with that element.
// If you want you can then place the entered data in a hidden field
// using jQuery, in the same way we are using input here. Then you will
// be able to post that data back however you like.
}
I had this problem the other day, I found this solution on jQuery's Dialog site.
http://jqueryui.com/demos/dialog/#modal-form

JQuery DatePicker icon only appears after clicking on textbox

I am using the jQuery DatePicker control in an ASP.NET MVC application.
I created a control called DateTime.ascx, so that whenever I call the Html.TextBoxFor() method passing it a field of type DateTime, this control comes into play, and a textbox+datepicker is rendered, overriding the standard functionality which produces just a textbox.
This is the control:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%=Html.TextBox("",
(Model.HasValue ? Model.Value.ToString("MM/dd/yyyy") : DateTime.Today.ToShortDateString()),
new { #class = "UseDatePicker" } )%>
And here is an example call:
<%: Html.EditorFor(model => model.Project.IssueDate)%>
Now, I also include on the master page a script called DatePickerConfig.js which, well, configures the datepicker. Here it is:
$(document).ready(function () {
$(".UseDatePicker").live('click', function () {
$(this).datepicker('destroy').datepicker({
showOn: "both",
buttonImage: "../../Content/calendar.gif",
buttonImageOnly: true,
changeMonth: true,
changeYear: true
}).focus();
});
});
Now, my problem: when the page loads, only a text box appears for editing the datetime field. When I click on the textbox, the calendar pops out as expected, and at the same time the button image appears. What I would like is for the buttonn image to be visible as soon as the page loads, and before the user starts to interact with the control.
Thanks.
The problem is you aren't binding the datepicker until you click on the textbox, so there is no button to bind until that loads. You should just bind the datepicker, Is there a reason you unbind and rebind on every button click? Per your current explanation, this would make more sense:
$(document).ready(function () {
$(".UseDatePicker").each(function(i) {
$(this).datepicker({
showOn: "both",
buttonImage: "../../Content/calendar.gif",
buttonImageOnly: true,
changeMonth: true,
changeYear: true
});
});
});
This will go through each field expecting a datepicker and bind the picker to that textbox.