Date and Time picker as custom editor in Tabulator - tabulator

How do I create a custom date and time picker editor instead of just a date picker editor?
I have made a date and time picker from jquery-ui library with a jquery-ui-timepicker add-on independently, but i cannot get this to work with tabulator custom editor.
Any help would be great. thank you!

Tabulator's documentation includes a guide to making custom editors
Essentially the important bits are that it needs to return a DOM Node, that is should call the 'success' function when a value has been set and 'cancel' if the value hasn't changed.
In the case of a jquery UI widget then you also need to make sure you instantiate the widget inside the onRendered callback which is triggered when the element is added to the DOM otherwise jQuery will error.
As a basic example based on the built in input editor:
var dateFormatter = function(cell, onRendered, success, cancel, editorParams){
var cellValue = cell.getValue(),
var input = document.createElement("input"); // define input element
//assign current cell value to input element
input.value = typeof cellValue !== "undefined" ? cellValue : "";
//handle loss of focus to the input element and changes in value
function onChange(e){
if(((cellValue === null || typeof cellValue === "undefined") && input.value !== "") || input.value !== cellValue){
success(input.value); //if value has changed save value
}else{
cancel(); //otherwise cancel edit
}
}
//submit new value on blur or change
input.addEventListener("change", onChange);
input.addEventListener("blur", onChange);
//instantiate the jQuery widget
onRendered(function(){
$(input).datepicker({
//date picker setup options
});
});
//return input element
return input;
}
(Using the blur event may cause issues if you have to click in controls for the jQuery widget so you may want to comment out the blur event listener)
(Also the change event may not be what you need depending on the usage case but i believe the jquery datepicker widget has an onSelect callback that you could use to trigger the success function)
You would then need to attach the formatter to the column in its column definition:
{title:"Date", field:"date", formatter:dateFormatter}

Related

How to prevent full refresh using onChange event SSJS

(You may be able to figure out an answer by ONLY reading the last question by itself, but I included everything for reference if necessary)
The onChange of one field is causing displayErrors to show validation results prior to when I need it to do that.
On an xpage, I have these two comboboxes:
1.) locationType
2.) locationEtc
Choices for locationEtc are dependent on what was selected in locationType field.
In the locationEtc field, the choices are using one computed value with this code:
try
{
var locType = getComponent("locationType").getValue();
var key = '';
switch(locType) {
case 'Commuity Service Center':
key = 'loc_cso';
break;
case 'RYDC':
key = 'loc_rydc';
break;
case 'YDC':
key = 'loc_ydc';
break;
case 'HQ':
key = 'loc_hq';
break;
default:
key = 'facilities';
}
var luChoices = #DbLookup('','keywords', key, 'choices');
luChoices.unshift("Select one|''");
return luChoices;
}
catch(e)
{
print("Error:::::"+e);
}
The choices were NOT changing for locationEtc whenever I pick a locationType, but then they do when I add code to clear the location field whenever locationType changes, using a simple action for onChange event of locationType field:
This is great, but when it all refreshes, my displayErrors control appears (yellow background area) showing required field validation results, and a lot of the fields are not filled in yet by design.
How can I make the displayErrors to show ONLY when tying to submit?
Thanks everyone who can help.
Matt
Set disableValidators="true" on the simple action that you created

Value in xp:confirm is not being updated after partial refresh. Why?

On an xpage I calculate the message for an xp:confirm control:
var arr = viewScope.get("attachmentsAll");
if(arr.length>0){
return "";
}else{
return arr.length + " Are you sure want to upload the file?";
}
the viewScope is being updated after the event has been executed. I check this via a xp:text and I notice that this assumption is true.
<xp:text escape="true" id="computedField1"><xp:this.value><![CDATA[#{javascript:var arr = viewScope.get("attachmentsAll")
return arr.length + " number?"}]]></xp:this.value></xp:text>
The xp:confirm and xp:text reside in the same panel that is being partially updated after the event.
Can anyone explain me why the value for the viewScope variable is updated in the xp:text control and not in the xp:confirm control?
The main idea of my answer to your previous question was to put hidden input with computed value. What if you try to use <xp:this.script> instead of xp:confirm, and get the confirmation message from that hidden input the same way?
Update
The reason and the alternative solution that does not require to make any changes to existing xpage
It came out that the back-end instance of xp:confirm evaluates the new message correctly. The new value is even being sent to the browser with the response to ajax request. But one of the functions of XSP client module is built so that it won't update the querySubmit listener function if there already exists one with the same name. So, we are stuck with the old confirmation function that contains the old message. There is a way to override this behavior without breaking any other features. I have tried this and it works for me.
Create a new JavaScript library (client-side). Add the code:
if (!XSP._pushListenerTuned) {
XSP.__pushListener = XSP._pushListener;
XSP._pushListener = function x__pl(listeners, formId, clientId, scriptId, listener) {
if (scriptId && scriptId.endsWith("_confirm")) {
for (var i = 0; i < listeners.length; i++) {
if (scriptId == listeners[i].scriptId) {
listeners.splice(i, 1);
}
}
listeners.push(new this._SubmitListener(formId, listener, clientId, scriptId));
} else {
XSP.__pushListener(listeners, formId, clientId, scriptId, listener);
}
}
XSP._pushListenerTuned = true;
}
Attach your new library as resource globally via theme or as page resource on required page. I guess placing the above code as scriptBlock on a required page should also work. Now, any xp:confirm component on any page (if you used theme resource), or on particular page and everywhere after visiting this page (if you used page resource or scriptBlock), will work as naturally expected.

Material Angular md-autocomplete clear and blur after selection (multi select)

I am trying to use md-autocomplete in Angular Material as a multi selector. The idea is, that the selected element from the autocomplete will be added to an object array after selection and then the selection will be removed from the md-autocomplete. I was able to clear the md-autocomplete, but the focus stays on the md-autocomplete input and so the autocomplete suggestions are still visible.
Example:
http://cdpn.io/QjQGVQ
Code:
function selectedItemChange(item) {
$log.info('Item changed to ' + JSON.stringify(item));
if(item)
{
//check if item is already selected
if($filter('filter')(vm.contactsSelected, function (d) {return d.id === item.id;})[0])
{
$log.info('Item already selected. Will not add it again.');
}
else
{
//add id to object
vm.contactsSelected.push(item);
}
// clear search field
vm.searchText = '';
vm.selectedItem = undefined;
//somehow blur the autocomplete focus
//$mdAutocompleteCtrl.blur();
}
}
PS: I am aware I could use the contact chips of Angular Material instead, but I was still wondering how the blur could be achieved.
If you set md-no-cache="true" property inside your the list will dissapear, but input field will not be cleared. I think is better solution than clearing input field but leaving the list visible, but is up to you.

Kentico 7 hide editable text if it's empty

I have an editable text web part on a page template. It has a custom HTML envelope before and after the text. How can I hide the whole thing, envelope included, if the editable text is empty?
I need to hide it because the envelope adds stylized markup that shouldn't be visible when there is no text.
Can it be done with a K# snippet on the Visible property? I'm unclear how interrogating a document's property works.
Thanks!
Try this as the "Visible" property:
{% (ViewMode != "LiveSite") || (CMSContext.CurrentDocument.editabletext != "") #%}
Change "editabletext" to whatever you have for your web part control ID.
I'm not familiar with Kentico but these solutions might help. They may not address your problem specifically but might aid in a solution.
CMSEditableImage Extension Method
I came up with a way to check this, I added an extension method for
the CMSEditableImage class that takes the CurrentPage PageInfo object
to check the value of the editable region, don't know if this is the
best way or not, but here's the code.
public static bool IsPopulated(this CMSEditableImage editableImage, PageInfo currentPage)
{
bool isPopulated = false;
string value = currentPage.EditableItems.EditableRegions[editableImage.ID.ToLower()].ToString();
if (!string.IsNullOrEmpty(value))
{
value = value.ToUpper();
isPopulated = (value == "<IMAGE><PROPERTY NAME=\"IMAGEPATH\"></PROPERTY></IMAGE>") ? false : true;
}
return isPopulated;
}
via http://devnet.kentico.com/Forums/f19/fp5/t4454/Empty-CMSEditableImage.aspx
JavaScript Method
The webcontainer needs an id, example:
<h2 id="webpart-header">Headline</h2>
Then I have a small javascript function that is attached in an
external js file:
/* Hide Webcontainer via javascript if empty*/
function hideLayer(element) {
elem = document.getElementById( element );
elem.style.display = "none";
}
Now in the wep part configuration, at no data behaviour, you uncheck the checkbox and call the js function by entering following
script in the no record found text: hideLayer("webpart-header");
Whereby webpart-header the id name of your container is. You could
also have a more complex <div> structure here.
via http://devnet.kentico.com/Forums/f22/fp3/t4180/Webcontainer-and-hide-if-no-data.aspx

How to disable validators for a specific field from a button

I have a xpage that loads a Bootstrap modal window (see picture). I need to validate the data only the user pushes the 'Add New' button. I do not want the validators to run when 'Save and Continue' or 'Previous' buttons are pressed.
The modal dialog is a custom control used many times throughout the application. I cannot change the buttons to disable validators because most of the time I want to validate. The center content is stored in its own custom control.
My question is can I add code to the button to get a handle to each control, and set the disableValidators to true. I haven't been able to figure out how to do this. I have already tried computing the disableValidators but was totally unsuccessful. The fields are all bound to scoped variables.
I know that I can use clientside validation here, but the rest of the application uses server-side and I want to be consistent + this is a responsive app, and clientside on mobile is annoying.
Rather than adding code to button to and setting disableValidators for each control I would suggest the other way round. For each control set the required property only if user pushes 'Add New' button.
This blog post by Tommy Valand describes it in detail. The below function lets you test if a specific component triggered an update.
// Used to check which if a component triggered an update
function submittedBy( componentId ){
try {
var eventHandlerClientId = param.get( '$$xspsubmitid' );
var eventHandlerId = #RightBack( eventHandlerClientId, ':' );
var eventHandler = getComponent( eventHandlerId );
if( !eventHandler ){ return false; }
var parentComponent = eventHandler.getParent();
if( !parentComponent ){ return false; }
return ( parentComponent.getId() === componentId );
} catch( e ){ /*Debug.logException( e );*/ }
}
So if you want the validation to run only when the user clicks a specific 'Add New' button then write this in all the required-attributes:
return submittedBy('id-of-add-new-button')

Resources