Find out when full calendar loaded events - fullcalendar

I have a fullCalendar widget created somewhere. I cannot change the code that initialize it. So I cannot add any callbacks in the first call.
Anything like this:
$(elem).fullCalendar({
complete: function () {
...
}
})
Actually creates a new fullCalendar instead of modifying the actual fullCalendar to change/add the complete callback.
Is there an other way to find out when events are loaded I was thinking about polling clientEvents but I realize that I could have no events in one month so I cannot expect the array to always have something in it.
By the way, it's fullCalendar 1.6.

You can define callbacks after the calendar object has been initialized, and to determine when all events have been rendered, use the eventAfterAllRender event. Here's how:
var calendar = $('#calendar').fullCalendar('getCalendar');
calendar.on('eventAfterAllRender', function(view) {
alert('all events rendered!');
});
Nevermind, this feature is only available starting in version 2.4.
Instead, you could poll the DOM for fullcalendar element existence, like this:
function checkForInit() {
if($(".fc-view").children().length) {
alert("initialized!");
} else {
setTimeout(function() {
checkForInit();
}, 10);
}
}
$(document).ready(function() {
checkForInit();
});

You can use eventAfterAllRender event, available from version 1.6:
$(elem).fullCalendar({
eventAfterAllRender: function (view) {
...
}
})

Ok I found a solution that seems to be working!
var waitPrint = true
function autoPrint() {
var elem = $('.fc')
var calendar = elem.data('fullCalendar')
console.log('Searching calendar')
if (calendar && waitPrint) {
waitPrint = false
console.log('Bund new event')
var _super = calendar.options.eventAfterAllRender
calendar.options.eventAfterAllRender = function (event, element, view) {
if (_super) {
_super.apply(this, arguments)
}
window.print()
}
} else if (waitPrint) {
setTimeout(autoPrint, 100)
}
}
autoPrint()
Here I'm polling for an element with the fc class. As soon as I find one, I check for the existence of the "data" named fullCalendar. If it returns a dict, then it means that the fullCalendar instance has been created. This is pretty much what Dane proposed for version 2.4 but this in 1.6 there is no getter. We have to get it ourselves. Luckily, it's stored in the data of the element and not in some other cryptic places.
Move on to the next step, fullCalendar isn't an eventEmitter in 1.x, but we still have access to options which seems to be just a reference to the options that were passed at first. I override the eventAfterAllRender. Call the method that was already defined if present and call my print method when it's done.
Technically from there, we can override almost any defined method from there. The only problem is that you have to do it faster than fullCalendar get initialized.
I believe that if we dig deeper, we could potentially patch the calendar library directly to remove the timing issues. Polling isn't very great.
Best Solution So far
var oldFullCalendar = $.fn.fullCalendar
function newFull(options) {
var _super_func = null
if (typeof options == 'string') {
oldFullCalendar.apply(this, arguments)
} else {
options = options || {}
if (options.loading) {
_super_func = options.loading
}
options.loading = function (loading) {
console.log(loading, 'loading')
if (_super_func) {
_super_func.apply(this, arguments)
}
if (!loading) {
window.print()
}
}
oldFullCalendar.apply(this, arguments)
}
}
$.fn.fullCalendar = newFull
The first solution could probably be improved by overriding loading instead. Since it's the method that notify when loading has been processed and which is also apparently called after the eventAfterAllRender callback.

Related

addEventListener on Panel

I have a use-case where I need to programmatically add/remove the onClick event associated with a panel.
I have tried the following solution but receive a cijCell.addEventListener is not a function error.
function cij_enabled(){
var cijCell = app.pages.Home.descendants.cellFour;
var index = cijCell.styles.indexOf('disabled-card');
if (Report.riskOfLoss === 'High') {
cijCell.styles.splice(index, 1);
cijCell.addEventListener("click", function() {
app.popups.Customer.visible = true;
});
} else {
if (index === -1){
cijCell.styles.push('disabled-card');
cijCell.removeEventListener("click", function() {
app.popups.Customer.visible = true;
});
}
}
}
How can I achieve the desired outcome? Is adding eventlisteners possible in this fashion through app maker?
You can definitely do so and you got it almost right. The only thing you need to understand is that the appmaker widget is not a native html element hence the error:
cijCell.addEventListener is not a function
Fortunately, AppMaker has a way of getting the native html elements associated to a widget. You need to use the getElement() method and then you can use the add/remove event listeners methods. So you should change your code from cijCell.addEventListener... to cijCell.getElement().addEventListener...
Reference: https://developers.google.com/appmaker/scripting/api/widgets#Panel

How can I be updated of an attribute change in Meteor?

I have a template that subscribes to a document. Everything works fine in the DOM and Blaze updates as soon as an attribute used in the template helpers is changed.
I also have some custom logic that doesn't appears in the DOM and depends on the document attributes. How can I call a function to change that logic when an attribute is updated?
I'm looking for something like this.data.attr.onChanged where this would refer to the template and this.data is the data send to the template, as usual; or a Meteor function that is rerun on change where I could put my callback in.
I hoped that template.onRendered would be recalled, but that's not the case.
I've read a lot about reactive variables, but could not find how they could be useful here.
[edit] the change is coming from the server that is communicating with another service
I've tried Tracker.autorun like this:
Template.editItem.onRendered(function() {
var self = this;
Tracker.autorun(function () {
console.log("tracker", self.data.item.socketId);
});
});
And the corresponding route is:
Router.route('editItem', {
path: '/edit/:_id',
waitOn: function () {
var sub = Meteor.subscribe('item', this.params._id);
return [sub];
},
data: function () {
return {item: Items.findOne(this.params._id)};
},
action: function () {
if (this.ready())
this.render();
}
});
At some point, the property socketId gets removed from the corresponding document by the server and I'm sure of that since I've checked in the shell, but the tracker doesn't rerun.
Use Template.currentData().item.socketId instead of self.data.item.socketId, this will give you reactivity.
And in templates generally, use self.autorun instead of Tracker.autorun (unlike Tracker.autorun, this will ensure that the autorun is stopped when the template is destroyed). Likewise, if you want to subscribe in a template, use self.subscribe instead of Meteor.subscribe.
Code to see if Template.currentData() works for you:
Template.editItem.onRendered(function() {
var self = this;
self.autorun(function () {
console.log("tracker", Template.currentData().item.socketId);
});
});
I'm not sure if I got you right, you just want to observe your html inputs and apply the new value to your helper method(s) on change?!
If so, you could use session variables to store your temporary UI state:
// observe your input
Template.yourTemplate.events({
"change #inputA": function (event) {
if(event.target.value != "") {
Session.set("valueA", event.target.value);
}
}
}
// apply the changed value on your helper function
Template.yourTemplate.helpers({
getSomeData: function() {
var a = Session.get("valueA");
// do something with a ..
}
}
In meteor's official todo app tutorial this concept is also used.
If you need to re-run something which is not part of DOM/helper, you can use Tracker.autorun. According to meteor docs, Run a function now and rerun it later whenever its dependencies change.
here's the docs link
Try moving the subscription into Tracker.autorun
Template.editItem.onRendered(function() {
var self = this;
Tracker.autorun(function () {
Meteor.subscribe('item', this.params._id);
console.log("tracker", self.data.item.socketId);
});
});
Of course you can't use this.params there so you can store this as a Session variable

how to overwrite initialization of standard method

can we use standard 'InsertCpDialog$initialize()' in our javascript like this , so that i can call other function once it get initializes. I used like below code but it is not working. :(
Type.registerNamespace("Extensions");
Extensions.InsertCpDialog.prototype.initialize = function InsertCpDialog$initialize()
{
alert('hi inside insert');
var p = this.properties;
if(window.document.nameProp == "Name" || window.document.title == "Name") {
var browserName=navigator.appName; // Get the Browser Name
if(browserName=="Microsoft Internet Explorer") // For IE
{
alert('hi inside IE');
//window.onload=init(); // Call init function in IE
}
else
{
if (document.addEventListener) // For Firefox
{
alert('hi inside firefox');
//document.addEventListener("DOMContentLoaded", init(), false); // Call init function in Firefox
}
}
}
}
Original(standard) one is like:
Type.registerNamespace ("Tridion.Cme.Views");
Tridion.Cme.Views.InsertCpDialog = function InsertCpDialog()
{
Type.enableInterface(this, "Tridion.Cme.Views.InsertCpDialog");
this.addInterface("Tridion.Cme.Views.DashboardBase");
};
Tridion.Cme.Views.InsertCpDialog.prototype.initialize = function InsertCpDialog$initialize()
{
}
Edit
hi frank thank you, but already i am using same thing in my code to get the list of componet and template listed on a page under CP tab.
function getbtn() {
//alert('inside getbtn');
var sbtn = document.getElementById ("buttonComponentInsert");
$evt.addEventHandler(sbtn , "click", getListofCPBtnClick);
}
function getListofCPBtnClick(e) {
//code will go here
}
My question is :
I need to get selected Component and template Id from Insert CP window.Earlier i was able to get that by changing the CME extension standard code, but i am not suppose to do that, So first i am trying to initialize the "insert CP window" from my javascript code. I can create event handler for that window, but my question is how to initialize that so that i can call any function once it get initialize. Kindly let me know if i anot clear.
Is your script getting loaded into the dialog?
If not, Albert shows how to do that here: http://albertromkes.com/2012/01/30/tridion-gui-extensions-how-to-load-a-javascript-without-showing-a-gui-element/
He then also shows how to listen to events to accomplish something similar to what you are trying to do.

How do I handle dojo datagrid cell updates so I can post them back automatically to the server?

I am using dojo datagrid to display my data. When the end user edit the cell values it should be updated in the server using ajax calls(when the focus goes out of the cell).
Else, I should have a Edit & update/cancel buttons for each row to handle the same feature.
But I don know how to place edit & update buttons inside the grid and capture their events.
By default dojo updates only local the store value(client side). how can I save the updated cell values into the server?
do we need to write any override methods to do so??
I am new to dojo. Any detailed explanation or sample codes would be much appreciated.
Could anyone lend a hand to solve this issue??
Thank you
Regards,
Raj
To be able to push the updates server-side, you've to override _saveCustom() or _saveEverything(). Here is a piece of code (a bit cleaned-up) I'm using to persist an update.
Note that the code below relies on the private _getModifiedItems() because the DataGrid accepts inline editions. If you do know the list of modified items (because the edition is done in a popup and you keep the item key somewhere), retreiving the modified item is simpler.
module.submitUpdates = function() {
var store = <from a variable local to the module>
if (store.isDirty() confirm("Updates to be persisted. Continue?")) {
store._saveCustom = function(saveCompleteCallback, saveFailedCallback) {
var modifiedItem = _getModifiedItems(store)[0];
dojo.xhrPost( {
headers: { "content-type": "application/json; charset=utf-8" },
content: dojo.toJson(modifiedItem),
handleAs: "json",
load: function(response) {
if (response !== null && response.success) {
saveCompleteCallback();
}
else {
saveFailedCallback(response);
}
},
error: saveFailedCallback,
url: "/API/<Object>"
});
};
store.save( {
onComplete : function() {
module.loadCachingRuleList();
},
onError : function(errorData, request) {
_reportUpdateFailure(errorData, errMsg);
}
});
}
};
Here is the code I use to get all updated items when the user is about to loose an updated DataGrid (because he leaves the page or because he wants to refresh the grid content).
Note that the following code was using Dojo 1.3. I haven't check if it's easier with Dojo 1.4... I hope that dojo.Stateful that's going to be introduced in Dojo 1.5 will simplify it, otherwise we'll have to wait for Dojo 1.6 ;)
var _getModifiedItems = function(store) {
var modifiedItems = [];
if (store !== null && store._pending !== null) {
if (store._pending._modifiedItems !== null) {
for (var modifiedItemKey in store._pending._modifiedItems) {
if (store._itemsByIdentity) {
modifiedItems.push(store._itemsByIdentity[modifiedItemKey]);
}
else {
modifiedItems.push(store._arrayOfAllItems[modifiedItemKey]);
}
}
}
if (store._pending._newItems !== null) {
for (var modifiedItemKey in store._pending._newItems) {
if (store._itemsByIdentity) {
modifiedItems.push(store._itemsByIdentity[modifiedItemKey]);
}
else {
modifiedItems.push(store._arrayOfAllItems[modifiedItemKey]);
}
}
}
}
return modifiedItems;
};
var _getDeletedItems = function(store) {
var deletedItems = [];
if (store !== null && store._pending !== null && store._pending._deletedItems !== null) {
for (var deletedItemKey in store._pending._deletedItems) {
if (store._itemsByIdentity) {
deletedItems.push(store._itemsByIdentity[deletedItemKey]);
}
else {
deletedItems.push(store._arrayOfAllItems[deletedItemKey]);
}
}
}
return deletedItems;
};
I hope this helps,
A+, Dom
This isn't a very detailed explanation but yes you should override the method that handles user data entries as I don't see an event for this. So basically create a new class that inherits from the data grid, find the method in the source code that handles the editing and override it to give it an extra action to post it back to the server. You'll want to call the datagrid's default action in that method too.
Some information here (that you probably are already aware of):
http://docs.dojocampus.org/dojox/grid/DataGrid#editing-data
I've extended Dojo's default components before, it's not hard. I find that it's always good to examine the Dojo source and to just be careful when upgrading Dojo to make sure new versions don't break existing features.
To avoid hacking your dojo library, just switch to the YUI2 data table; it's cell editor accepts the asyncsubmitter function that sends your edits to your sever
This is the description from documentation
asyncSubmitter
Function
Implementer defined function that can submit the input value to a server. This function must accept the arguments fnCallback and oNewValue. When the submission is complete, the function must also call fnCallback(bSuccess, oNewValue) to finish the save routine in the CellEditor. This function can also be used to perform extra validation or input value manipulation.
YUI2DataTable

Is there += for window.onload in Javascript?

recently I came up with the following problem:
In my web site in all html pages I call a function in body onLoad event:
<body onLoad="func1();">
This is part of my template for html, so it appears on every page in my site and I can't change that. Now, the deal is that on some pages, I need to call some other functions onload and I tried with window.onload property, but it wipes the calling of func1...
I now that I can just say:
window.onload = func2(); //where func2() calls to func1()
but this seems dirty and lame? Isn't it ?
So, is there a way to add some functions to those that are about to be executed onload, without deleting the old one? In addition I use asp.net if that could help ...
Thanks!
You can use jQuery to chain on load handlers. Repeatedly using jQuery.load or jQuery(document).ready will chain your handlers (I believe). You other option is to do it programmatically, which means you need an auxiliary function that will chain your onload handlers for you. You can do this with a closure (or anonymous function):
var addOnLoadHandler = function(newHandler) {
if (typeof window.onload != 'function') {
window.onload = newHandler;
}
else {
var oldHandler = window.onload;
window.onload = function() {
if (oldHandler) {
oldHandler();
}
newHandler();
};
}
};
You will have to bind your functions programmatically though, so you would have to do:
addOnLoadHandlers(function() {
alert("Hi I am the first onLoad handler!");
});
addOnLoadHandlers(function() {
alert("Hi I am the second onLoad handler!");
});
in a javascript file (or in your html file).
Another approach is to use an array:
var onloaders = new Array();
function runOnLoads() {
for (i = 0; i < onloaders.length; i++) {
try {
var handler = onloaders[i];
handler();
} catch(error) {
alert(error.message);
}
}
}
function addLoader(obj) {
onloaders[onloaders.length] = obj;
}
In your HTML or Javascript file you do:
addLoader(function() {
alert("Hi I am the first onLoad handler!");
});
addLoader(function() {
alert("Hi I am the second onLoad handler!");
});
Then in your html you can just do <body onload="runOnLoads()">
You may want to make the best out of anonymous functions:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
}
else {
window.onload = function() {
oldonload();
func();
}
}
}
Borrowed from the Top 10 custom JavaScript functions of all time.
jQuery has a nice shorthand for adding multiple defined handlers to the "ready" event (does not work with anonymous functions where you have to use $(document).ready(function(){});).
simply
$(myFunction);
$(myFunction2);
One big advantage is that if the DOM has already loaded, this still gets fired, whereas anything you bind to window.onload after the event will not get called.
have you considered a javascript library like jquery, i know that there are other approaches but jquery will make your life so much easier...
$(function(){
//Do stuff when DOM is loaded.
func1();
$('#link').click(function(){
//bind a click event
});
});
The classic approach is to just stick all of your functions at the bottom of the page :)
In jquery you can do
$(document).onload(function() {
// do something
}
//then later on do
$(document).onload(function() {
// do something here too!
}
jQuery will intelligently add both events to the onload event and both will be executed when the page loads. With jQuery you also get crossbrowser support as an added bonus.

Resources