Liferay 7 date picker does not trigger onChange - liferay

I added this AUI date picker to my JSP:
<aui:input
type="text"
id="myDate"
name="my-date"
value="2017-12-14"
placeholder="yyyy-mm-dd"
onChange="javascript:alert('date changed');"/>
<aui:script>
AUI().use(
'aui-datepicker',
function(A) {
new A.DatePicker(
{
trigger: '#<portlet:namespace/>myDate',
mask: '%Y-%m-%d',
popover: {
zIndex: 1000
}
}
);
}
);
</aui:script>
Problem: Changing the date using the calendar widget that pops up does not display the alert.
If I ignore the widget and change the date manually (using the keyboard), the alert correctly shows up as soon as the input loses focus.
What am I doing wrong?
How to have onChange be called whenever the date is changed, be via mouse or keyboard?

As the guys in the comments mentioned use the js callback definitions. There are a couple of examples in the documentation.
https://alloyui.com/examples/datepicker
If you really want to have the onChange also there, you can trigger the change event from the js callback code.
<button class="btn btn-primary"><i class="icon-calendar icon-white"></i> Select the date</button>
<script>
YUI().use(
'aui-datepicker',
function(Y) {
new Y.DatePicker(
{
trigger: 'button',
popover: {
zIndex: 1
},
on: {
selectionChange: function(event) {
console.log(event.newSelection)
}
}
}
);
}
);
</script>

Related

Angularjs Material md-datepicker within Formly template will not open calendar pane

I'm trying to create a Formly template using md-datepicker. Unfortunately, when I click on the md-datepicker control within my form the calendar panel does not open.
controller code:
{
className: 'col-xs-6',
key: 'dateCreated',
type: 'materialdatepicker',
templateOptions: {
label: 'Created'
},
expressionProperties: {
'templateOptions.disabled': function () {
return !vm.options.editMode;
},
'templateOptions.required': function () {
return vm.options.editMode;
}
}
}
template:
<script type="text/ng-template" id="materialdatepicker.html">
<div layout="column">
<div flex="100">
<p class="input-group" style="display: block; margin: 0px;">
<md-datepicker id="{{::id}}" name="{{::id}}" ng-model="model[options.key]"></md-datepicker>
</p>
<div class="formlyMessages" ng-messages="fc.$error" ng-if="fc.$touched">
<div class="formlyMessage" ng-message="{{::name}}" ng-repeat="(name, message) in ::options.validation.messages">
{{message(fc.$viewValue, fc.$modelValue, this)}}
</div>
</div>
</div>
</div>
</script>
formly config:
formlyConfigProvider.setType({
name: 'materialdatepicker',
templateUrl: 'materialdatepicker.html',
wrapper: ['bootstrapLabel', 'bootstrapHasError'],
defaultOptions: {
ngModelAttrs: ngModelAttrs
},
controller: ['$scope', function ($scope) {
$scope.materialdatepicker = {};
}]
});
I can't seem to figure out how to get the calendar panel to open. I'm not getting any errors in the console and the control does get populated with my initial value.
Any ideas?
What I forgot to mention in my original post was that this form is contained within a modal window ($uibModal). As such, the calendar pane was popping up behind my modal window.
The solution found here worked for me: Angular Material DatePicker Calendar Shows Behind Angular Modal
You need to tell your calendar pane to open with a high z-index so it renders above the modal. Place this style sheet code into your modal html:
<style>
.md-datepicker-calendar-pane {
z-index: 1200;
}
</style>

Edit an object in backbone

I am new to using backbone in parse.com environment. I simply want to edit the second model object but I dont know how to open the edit box for the second object.
The current working model is the following, I have added "dblclick label.todo-job" : "edit1" and can get it started by double clicking it.
events: {
"click .toggle" : "toggleDone",
"dblclick label.todo-content" : "edit",
"dblclick label.todo-job" : "edit1",
"click .todo-destroy" : "clear",
"keypress .edit" : "updateOnEnter",
"blur .edit" : "close"
},
The following is the function to allow editing my object.
edit1: function() {
$(this.el).addClass("editing");
this.input.focus();
},
However, it only opens this object "label.todo-content" to edit while I want to edit "label.todo-job". How can I change the focus to the new object.
Thats the whole code if you need.
// The DOM element for a todo item...
var TodoView = Parse.View.extend({
//... is a list tag.
tagName: "li",
// Cache the template function for a single item.
template: _.template($('#item-template').html()),
// The DOM events specific to an item.
events: {
"click .toggle" : "toggleDone",
"dblclick label.todo-content" : "edit",
"dblclick label.todo-job" : "edit1",
"dblclick label.todo-phone" : "edit2",
"dblclick label.todo-email" : "edit3",
"dblclick label.todo-website" : "edit4",
"dblclick label.todo-address" : "edit5",
"click .todo-destroy" : "clear",
"keypress .edit" : "updateOnEnter",
"blur .edit" : "close"
},
// The TodoView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a Todo and a TodoView in this
// app, we set a direct reference on the model for convenience.
initialize: function() {
_.bindAll(this, 'render', 'close', 'remove');
this.model.bind('change', this.render);
this.model.bind('destroy', this.remove);
},
// Re-render the contents of the todo item.
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
this.input = this.$('.edit');
return this;
},
// Toggle the `"done"` state of the model.
toggleDone: function() {
this.model.toggle();
},
// Switch this view into `"editing"` mode, displaying the input field.
edit: function() {
$(this.el).addClass("editing");
this.input.focus();
},
edit1: function() {
$(this.el).addClass("editing");
this.input.focus();
},
edit2: function() {
$(this.el).addClass("editing");
this.input.focus();
},
edit3: function() {
$(this.el).addClass("editing");
this.input.focus();
},
edit4: function() {
$(this.el).addClass("editing");
this.input.focus();
},
edit5: function() {
$(this.el).addClass("editing");
this.input.focus();
},
// Close the `"editing"` mode, saving changes to the todo.
close: function() {
this.model.save({content: this.input.val()});
$(this.el).removeClass("editing");
},
// If you hit `enter`, we're through editing the item.
updateOnEnter: function(e) {
if (e.keyCode == 13) this.close();
},
// Remove the item, destroy the model.
clear: function() {
this.model.destroy();
}
});
Below is the objects added in the HTML.
<script type="text/template" id="item-template">
<li class="<%= done ? 'completed' : '' %>">
<div class="view">
<li><label class="todo-content"><%= _.escape(content) %></label></li>
<li><label class="todo-job"><%= _.escape(job) %></label></li>
<li><label class="todo-phone"><%= _.escape(phone) %></label></li>
<li><label class="todo-email"><%= _.escape(email) %></label></li>
<li><label class="todo-website"><%= _.escape(web) %></label></li>
<li><label class="todo-address"><%= _.escape(address) %></label></li>
<li><label class="todo-postcode"><%= _.escape(postcode) %></label></li>
<button class="todo-destroy"></button>
</div>
<input class="edit" value="<%= _.escape(content) %>">
<input class="edit" value="<%= _.escape(content) %>"> /*I need to edit this instead of the object above this*/
</li>
</script>
An event triggers on the deepest possible element.which means this of Event handler function is not element you select for event listener but element where the actual event occurs.
I don't know about parse.com though,I assume that label.todo-content is inside of label.todo-job. And that makes Event handler's callback this into label.todo-content.
So If you explicitly select element to focus,It should work.
FYI, Backbone View has $(http://backbonejs.org/#View-dollar) and $el (http://backbonejs.org/#View-$el) parameters to use jQuery methods for elements in side of the View.Since global $ is able to edit any elements over each controller's View area, using this.$ is always recommended.
edit1: function() {
this.$el.addClass("editing");
this.$("label.todo-job").focus();
},
EDITED
I got what you asked about.
I do not know how you wrote your HTML code but the code you provided is pointing first input if your input tags have class name,
edit1: function() {
this.$el.addClass("editing");
this.$(".yourClassNameForInput").focus();
},
or if you do know have class/id name,You can also do this.
edit1: function() {
this.$el.addClass("editing");
this.$("input").eq(0).focus();
},
....
edit5: function() {
this.$el.addClass("editing");
this.$("label.todo-job").eq(4).focus();
}

Avoid to show the keyboard when a selectOneMenu is selected on mobile devices

I need to avoid to show the keyboard when a selectOneMenu is selected on mobile devices
Someone suggests to use h:selectOneMenu in this question:
How do I prevent the keyboard from popping up on a p:selectOneMenu using Primefaces?
But I need to use the p:selectOneMenu component
You can override the SelectOneMenu focusFilter function.
What we have to do is adding one more condition, if it's not a mobile device do the focus otherwise don't do it.
Here's the overridden function, just execute it in the document.ready.
//check if it's a mobile device
mobileDevice = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
PrimeFaces.widget.SelectOneMenu.prototype.focusFilter = function(timeout) {
if(!mobileDevice) {
if(timeout) {
var $this = this;
setTimeout(function() {
$this.focusFilter();
}, timeout);
}
else {
this.filterInput.focus();
}
}
}
Then we check if it's a mobileDevice again, if so we remove the foucsInput this time
if(mobileDevice) {
for (var propertyName in PrimeFaces.widgets) {
if (PrimeFaces.widgets[propertyName] instanceof PrimeFaces.widget.SelectOneMenu) {
PrimeFaces.widgets[propertyName].focusInput.remove();
}
}
}
Note: This has been fixed in PrimeFaces 5.2.
A small working example can be found on github, And an online Demo.
Try these on the id of your selectOneMenu (using jQuery)
$(".mySelect").focus(function() {
$(this).blur();
});
OR
$('body').on("focus", '.mySelect', function(){
$(this).blur();
});
OR other example using the blur attribute (using just javascript):
If the HTML for these fields looked like this:
<input type="text" name="username" id="username">
<input type="password" name="password" id="password">
Then the JavaScript would be:
document.getElementById('username').blur();
document.getElementById('password').blur();
Blur: is an event is sent to an element when it loses focus
These worked for me before.
I hope this helps!
:)

Kendo datepicker is dispalying date in long format with time how to avoid it

This is code I am using can be seen by clicking the this link
http://jsfiddle.net/fGq5w/1/
On click of the button , I change the date. But the time is also displayed.
How to display one date alone when i click the button.
HTML CODE
<input id="myDatePicker" data-bind="value: currentDate" />
<h2>Current Date is:<strong data-bind="text: currentDate"></strong></h2>
<input type='button' value='change Date' onclick='changeDate();return false;' />
Javascript
var vm = {
currentDate: ko.observable()
};
$(function(){
ko.applyBindings(vm);
$("#myDatePicker").kendoDatePicker();
});
function changeDate()
{
alert('ok');
vm.currentDate(new Date(2014,1,1));
}
This is more of a Kendo question. Just format the date with kendo's date formatting tools:
http://docs.kendoui.com/getting-started/framework/globalization/dateformatting
eg...
vm.currentDate(kendo.toString(new Date(2013,0,1), "MM/dd/yyyy"));
Your Code with additional functionality to pre-fill the date TextBox.
var vm = {
currentDate: ko.observable(kendo.toString(new Date(),'MM/dd/yyyy'))
};
$(function(){
ko.applyBindings(vm);
$("#myDatePicker").kendoDatePicker();
});
enter code here
function changeDate()
{
alert('ok');
vm.currentDate(kendo.toString(new Date(2014,1,1),'MM/dd/yyyy'));
}
In Knockout 3.3.0, you can create an extension to handle the formatting since calling a function manually isn't terribly ideal:
(In the snipper below I'm using moment.js to parse the date, but you could use kendo's date parser - although it doesn't work with certain ISO formatted dates)
ko.extenders.stripTime = function (target) {
var result = ko.pureComputed({
read: target,
write: function (value) {
if (value) {
target(moment(value).format(shell.getDateFormatString()));
}
else {
target(value);
}
}
}).extend({ notify: 'always' });
result(target());
return result;
};
In your client-side viewmodel, apply the extension to your observable:
self.SomeDateProperty = ko.observable().extend({ stripTime: null });
I recommend not using ko.toJS when you try to get a javascript object from your observables when using kendo datepicker - Instead, use ko.mapping (you need to download the JS library separately).
var someJavascriptObject = ko.mapping.toJS(viewModel);

How to integrate Stripe "Pay with Card" in backbonejs

I am trying to integrate Stripe "Pay with Card" checkout into backbone Node environment. On the server side, I am using Stripe Node code - that part works good. However, on the client side, I am unable to capture the event.
I would like to capture the submit event from the Stripe popup to call "paymentcharge" method in the view.
Here is my code:
<!-- Stripe Payments Form Template -->
<form id="stripepaymentform" class="paymentformclass">
<script
src="https://checkout.stripe.com/v2/checkout.js" class="stripe-button"
data-key="pk_test_xxxxxxxxxxxxx"
data-amount="0299"
data-name="MyDemo"
data-description="charge for something"
data-image="assets\ico\icon-72.png">
</script>
</form>
Backbone View Class
myprog.PaymentPanelView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
$(this.el).html(this.template());
return this;
},
events : {
"submit" : "paymentcharge"
},
paymentcharge : function( event) {
this.model.set({stripeToken: stripeToken});
}
});
Backbone Model Class
var PaymentChargeModel = Backbone.Model.extend({
url: function(){
return '/api/paymentcharge';
},
defaults: {
}
})
Setup/Call the View from header menu event
if (!this.paymentPanelView) {
this.paymentPanelView = new PaymentPanelView({model: new PaymentChargeModel()});
}
$('#content').html(this.paymentPanelView.el);
this.paymentPanelView.delegateEvents();
this.selectMenuItem('payment-menu');
I think the problem has to do with your View's el and the event you are listening for.
You never explicitly define your View's el, which means it gets initialized to a detached <div> element. You then use your template to fill that <div> with the form element from the template. Even though your <div> is detached, you get to see the content, because you add the content of you el to #content using jquery.
I think the problem is that you are listening for a submit event on the <div> in your el, not the contained <form>. Try changing your events hash to this:
events: {
'submit form#stripepaymentform': 'paymentcharge'
}
Basically, listen for events on the contained element like in jquery's .on. You can also go right to a button click, something like this:
'click #mysubmitbutton': 'paymentcharge'
Hope this helps!

Resources