Overriding events in Sap ui 5 - uiview

I created custom Controller which Extends
sap.ui.commons.ValueHelpField
and I want to override valueHelpRequest event but I was unable to override the method. I was overriding event like method. Can anyone tell me how to override the event

This is the normal way of using a ValueHelpField.
// create a default ValueHelpField
var oVHF1 = new sap.ui.commons.ValueHelpField('VHF1',{
value: "default",
tooltip: "This is a tooltip",
valueHelpRequest: function(){alert('ValueHelpRequest fired');}
}).placeAt("sample1");
valueHelpRequest event has a user-defined function to be triggered. If the customization that you want could be in the event handler function, then you need not override event implementation.
Else if you would like to change the way the event is triggered, then please refer below:
For Every event 'xyz', a corresponding 'fireXyz' method is generated, which shall be called on native browser events like 'click' etc.,
Browser events shall be handled in the Control implementation in methods like 'onclick' for 'click', 'ontap' for 'tap'...
In ValueHelpField control, the fireValueHelpRequest method is called on browser events like 'click' and 'sapshow' i.e. from methods 'onclick' and 'onsapshow'.
If you would like custom behavior, then override methods 'onclick' and 'onsapshow', check the current implementation, and add customization as needed.
Hope it helps.

sap.ui.core.Control.extend("nabisoft.bookstore.controls.Book", {
// the control API:
metadata : {
properties : {
//some properties
},
aggregations : {
//some aggregation
},
associations: {
//some association
},
events : {
valueHelpRequest: function(e){
alert("clicked");
}
}
},

sap.ui.commons.ValueHelpField.extend("HoverButton", {
metadata: {
events: {
"hover" : {}
}
},
onmouseover : function(evt) {
this.fireHover();
},
renderer: {}
});
var myControl = new HoverButton("myBtn", {
text: "Hover Me",
hover: function(evt) {
alert("Button " + evt.getSource().getId() + " was hovered.");
}
});
myControl.placeAt("content");
var myControl = new HoverButton("myBtn", {
text: "Hover Me",
hover: function(evt) {
alert("Button " + evt.getSource().getId() + " was hovered.");
}
});
myControl.placeAt("content");

Related

Rails / Trix Editor save changes via AJAX to server

I am using the very simple to implement Trix Editor provided from Basecamp in an "Edit View".
How would one save automatically changes, without having the user to interact through the update button?
I am thinking about something like this:
(OLD SCRIPT)
window.setInterval(function() {
localStorage["editorState"] = JSON.stringify(element.editor)
}, 5000);
What I actually want to do:
post a ajax "post" request to the rails server. something like:
$('trix-editor').on('blur', function() {
var sendname = $('#note_name').val();
var sendlink = $('#linkinput').val();
var sendnote = $('input[name="note[note]"]').val();
$.ajax({
type: "POST",
url: "/notes",
data: { note: { name: sendname, link: sendlink, note: sendnote } },
success: function(data) {
alert(data.id);
return false;
},
error: function(data) {
return false;
}
});
(There is as well the problem with authentification and devise. Only if you are loged in you should be able to send an ajax post request ..??)
Even better would be to save changes only when the user changes some data, and then wait 5s and then push the updated data via json to the server. I have no clue how to do that...
PS: would have loved to tag this question with a "trix-editor" tag, sorry have not enought rep for doing so...
If you are using plain JavaScript, use a hidden input field:
<form>
<input type="hidden" id="noticeEditorContent"/>
<trix-editor input="noticeEditorContent" id="x" style="min-height: 200px;"></trix-editor>
</form>
Now you have access to the element with the ID x.
Which means, with getElementById, you can do something like that:
var richTex = document.getElementById("x");
With this variable, you can either set an interval as you already explained, or you are using jQuery to do the job:
$('#x').on('input', function() {
localStorage["editorState"] = JSON.stringify($('#x').val());
});
Just a suggestion. You can write this code a bit nicer and cleaner.
Now it depends. Is setting an interval every 5 seconds better or writing every change to the LocalStorage?
Suggestion:
Save the input when the user deselects the field:
$('#x').on('blur', function() {
localStorage["editorState"] = JSON.stringify($('#x').val());
});
Update: Here is a working JSFiddle.
so I came up with this code which saves via ajax on 'trix-blur' (which fires when the user disselects the trix-editor). There is only the question left if this code is secure enought with devise, or if now anyone can send data to be saved?!?
I have the authentification in the notes controller like that:
before_action :authenticate_user!
and here is the javascript part (with a custom messages functionality):
$('trix-editor').on('trix-blur', function() {
var sendname = $('#note_name').val();
var sendlink = $('#linkinput').val();
var sendnote = $('input[name="note[note]"]').val();
var sendid = $('#note_id').val();
$.ajax({
type: "PUT",
url: "/notes/" + sendid,
dataType: "json",
data: { note: { name: sendname, link: sendlink, note: sendnote }, id: sendid, commit: "Update Note" },
success: function(data) {
addMessage('auto saved ...', 'msg-success');
return false;
},
error: function(data) {
alert('error');
return false;
}
});
var addMessage = function(msg, msgclass) {
$('#notifications').append('<div id="msg" class="msg '+msgclass+'">'+msg+'</div>');
setTimeout(function() {
$('#msg:last-child').addClass('msgvisible');
}, 100);
displayMessage();
};
var displayMessage = function() {
setTimeout(function() {
hideMessage();
}, 2000);
};
var hideMessage = function() {
$('#msg').addClass('msghide');
setTimeout( function() {
deleteMessage();
}, 300);
};
var deleteMessage = function() {
$('#msg').remove();
if ($('#notificatosn').find('#msg') > 1) {
displayMessage();
}
};
});
Per the Trix project page the trix-editor emits different events on specific conditions.
The trix-change event is what you need; it fires whenever the editor’s contents has changed.
So, the first line of your JavaScript code could be
$('trix-editor').on('trix-change', function() {
/* Here will be your code to save the editor's contents. */
})

backbone jquery-ui dialog buttons external function

For a jquery-ui dialog inside a render function, can I have buttons that point to another function and not inline it?
var MyView = Backbone.View.extend({
submit: function(event) { /* foo */ },
buttons: [{
'text' : 'SUBMIT',
'click' : this.submit // <== like this
}],
render: function() {
this.$el.append("I'm a dialog with a button").dialog({ buttons: this.buttons });
return this;
}
});
I ran the above code as is, and it seems like the engine can't find submit:
Uncaught TypeError: Cannot call method 'apply' of undefined jquery-ui.js:10018
$.widget._createButtons.$.each.props.click jquery-ui.js:10018
jQuery.event.dispatch jquery-1.9.1.js:3074
jQuery.event.add.elemData.handle jquery-1.9.1.js:2750
The buttons array is interpreted when you declare your view and at that point this is set to the root object (probably window). You can demonstrate this behavior by assigning something to window.submit. For example,
window.submit = function() {
console.log('window submit');
}
is triggered when you click on your button. See http://jsfiddle.net/nikoshr/AmRkp/ for a demo.
A solution to your problem would be to use your definition as a template to build a custom array of buttons for each instance. Something like this :
var MyView = Backbone.View.extend({
submit: function(event) {
console.log(this, 'submit');
},
buttons: [{
'text' : 'SUBMIT',
'click' : 'submit'
}],
render: function() {
var mybuttons;
//extract the buttons from an array or function,
mybuttons = _.result(this, 'buttons');
//build the array
mybuttons = _.map(mybuttons, function(obj) {
// for each object describing a button
//create a clone to avoid problems
obj = _.clone(obj);
//set the callback, bound to the view
obj.click = _.bind(this[obj.click], this);
return obj;
}, this);
this.$el.append("I'm a dialog with a button").dialog({
buttons: mybuttons
});
return this;
}
});
See http://jsfiddle.net/nikoshr/AmRkp/3/ to play with

jQuery UI animation Callback executing before animation starts

I'm trying to get some animation to work during a Backbone View's render operation that is called when I have refreshed the data of the underlying model to a new record.
SiteView = Backbone.View.extend({
initialize: function () {
this.model.bind('change', this.render, this);
},
render: function () {
if (this.model.get('name')) {
var callback = function (view) {
view.$("#activesite_name").empty().append(view.model.get('name'));
view.$("#activesite_desc").empty().append(view.model.get('description'));
$(view.el).show('drop', { direction: 'down' }, 'slow').removeClass('hidden');
};
$(this.el).filter(':visible').fadeOut(500, callback(this));
}
}
});
However, the jQuery UI callback function is being executed before the show operation is, resulting in the UI updating and then disappearing when refreshing from one model selection to another.
How can I get the callback to be called only once the element is properly hidden?
Try this:
render: function () {
if (this.model.get('name')) {
var view = this;
var callback = function () {
view.$("#activesite_name").empty().append(view.model.get('name'));
view.$("#activesite_desc").empty().append(view.model.get('description'));
view.$el.show('drop', { direction: 'down' }, 'slow').removeClass('hidden');
};
$(this.el).filter(':visible').fadeOut(500, callback);
}
}

TipTip only working on second hover after ajaxpost

Situation:
My tooltips show up on my page. Opening my fancybox works. Doing the ajax post from that fancybox works.
But my tooltips don't work in that fancybox. And they don't work after my ajax post.
I tried to reinitialize TipTip with the callbacks of fancybox.
EDIT
Title changes
So I found a way to let it run on the second hover after post but not on first hover.
I also found some explanations here but it still didn't fix my problem. Probably doing it wrong.
EDIT 2
Tootip in fancybox working use afterShow only.
Changes
added this in $(function () { so that it calls this function instead of initTipTip.
$(".tooltip").live('mouseover', function () {
$(this).tipTip();
});
Code of my function that does the post thing and closes my fancybox.
var reservation = MakeReservation();
var oldDateSplit = $("#resDate").val().split('/');
var newDateSplit = $("#dateEditReservation").val().split('/');
var oldDate = new Date(oldDateSplit[2], oldDateSplit[1] - 1, oldDateSplit[0]);
var newDate = new Date(newDateSplit[2], newDateSplit[1] - 1, newDateSplit[0]);
var time = $("#txtTime");
$.ajax({
url: ResolveUrl('~/Reservation/CheckSettings'),
data: "JSONString=" + reservation + "&hasJavaScriptMethod=" + true
}).done(function (data) {
if (data.length == 0 || oldDate.getTime() == newDate.getTime()) {
$.fancybox.close();
var id = $("#reservationId").val();
$("#reservationList").load(ResolveUrl('~/Reservation/reservationList',
function () { initTipTip(); }));
$("#reservationDetail").load(ResolveUrl('~/Reservation/DetailInfo',
function () { initTipTip(); }), { reservationId: id });
$("#reservationList").on("hover", " .tooltip", function () { $(this).tipTip(); });
}
else {
$(".errorDiv").removeClass("hidden");
$(".errorDiv").html(data);
$(".btnReservations").removeAttr('disabled');
}
});
NEW
$(".tooltip").live('mouseover', function () {
$(this).tipTip();
});
}
Still the same as before the edit.
Code initialization for TipTip
function initTipTip () {
$(".tooltip").tipTip();
}
Code of fancybox
function openFancy() {
$("a.inline").fancybox({
'type': 'ajax',
'afterShow': function () {
return initTipTip();
}
});
$("a.inlineBlockedDate").fancybox({
'type': 'ajax',
'ajax': { cache: false },
'afterShow': function () {
return initTipTip();
}
});
}
I found the solution for this.
So I used my .live in $(function(){ like in my question but I did not use ".tooltip" here but the table itself. I also use initTipTip here instead of $(this).tipTip();
So this solves the Tooltip from TipTip.
Explanation: This is because the tooltip.live only gets triggered on first hover and not when the table 'refreshes'. So now you add that event on that refresh of the table
Correct me if I'm wrong here.
So no need for any other .tiptip stuff or InitTipTip then in $(function(){
$("#reservationList").live('mouseover', function () {
initTipTip();
});
I hope your problem gets solved with this question.

jquery multiple dialogs to return value to function that called it

I have a application with many dialogs and created a function to open a dialog and also load data into it, so other functions could open a dialog and process the users option.
The problem is when I call openDialog it stops the function that called it. I thought by adding a return value so when a button is clicked the calling function can process the users response.
function customer_crud(op)
{
var formData = $("#customer_details_form").serialize();
var debugData = formData.replace(/&/g,'<br />');
var text = "<p>Customer Function: " + op + "</p><p>" + debugData + "</p>";
if(openDialog('DEBUG', text)){
alert("TRUE");
} else {
alert("FALSE");
}
}
function openDialog(title, text) {
var dialogOpts = {
title: title,
modal: true,
autoOpen: false,
buttons: {
"Delete all items": function() {
$( this ).dialog( "close" );
return true;
},
Cancel: function() {
$( this ).dialog( "close" );
return false
}
}
};
$("#dialog").dialog(dialogOpts);
$("#dialog").html(text).dialog('open');
}
The above code opens the dialog but throws false before anything is selected. If someone could please help me or sugguest a better way I would be greatful.
I plan to pass dialogOpts to the function but placed it in there for testing.
Thanks
I have a single dialog that can be called from multiple buttons. Only one step in the process changes depending on which button is pushed. The result of the dialog goes into a different field depending on the button. So, I set a variable in the click function before calling the dialog. Then, in my dialog, I have a switch statement which checks the variable and adds the value to the appropriate field. You could similarly use a switch statement to do the different functionality depending on which dialog you're calling.
function openDialog(title, text) {
var dialogOpts = {
title: title,
modal: true,
autoOpen: false,
buttons: {
"Delete all items": function() {
switch (item_type) {
case "primary":
...
break;
case "insurance":
...
break;
case "safety":
...
break;
case "sales":
...
break;
}
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog("close");
}
}
};
$("#dialog").dialog(dialogOpts)
.html(text).dialog('open');
}
There is no return value in your openDialog function. Thats why you will always get False.
You can't really have a dialog like this, since it's not synchronous/blocking, a better approach would be to call the desired method when you click the dialog button, like this:
function customer_crud(op)
{
var formData = $("#customer_details_form").serialize();
var debugData = formData.replace(/&/g,'<br />');
var text = "<p>Customer Function: " + op + "</p><p>" + debugData + "</p>";
openDialog('DEBUG', text);
}
function delete_items() {
alert("Deleting!");
}
function openDialog(title, text) {
var dialogOpts = {
title: title,
modal: true,
autoOpen: false,
buttons: {
"Delete all items": function() {
$(this).dialog("close");
delete_items();
},
Cancel: function() {
$(this).dialog("close");
}
}
};
$("#dialog").dialog(dialogOpts)
.html(text).dialog('open');
}

Resources