Anyone know ho开发者_StackOverflow中文版w to have the calendar view expanded all by default?? Seen a lot of information on how to do this with SP 2007 but not SP 2010.
Kuldeep, thanks for this script! I have modified it slightly to expand all rows of the calendar by removing the break and checking to see if the anchor text is "collapse". If it's not "collapse", a click is executed. Note that you only need to click on one item per row. Otherwise, you might toggle back to collapsed.
Another problematic side effect of adding the CEWP to the Calendar page is that you lose the Change View dropdown. You have to use the calendar ribbon to change views.
I would also like to find a more robust solution, but here is my slighly improved solution:
<script type="text/javascript">
_spBodyOnLoadFunctionNames.push("myFuncAfterLoad");
function myFuncAfterLoad() {
var oldCalendarNotify4a = SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function () {
oldCalendarNotify4a();
myFuncToExpandCalendar();
}
}
function myFuncToExpandCalendar() {
try {
var aTags = document.getElementsByTagName('A');
for (i = 0; i < aTags.length; i++) {
if ((aTags[i].evtid == "expand_collapse") && (aTags[i].innerText != "collapse")) {
(aTags[i]).click();
}
}
}
catch (err) {
alert(err.message);
}
}
</script>
Not the best approach but it works, add the following script on your page in CEWP or inline:
<script type="text/javascript">
_spBodyOnLoadFunctionNames.push("myFuncafterLoad");
function myFuncafterLoad(){var OldCalendarNotify4a = SP.UI.ApplicationPages.CalendarNotify.$4a;SP.UI.ApplicationPages.CalendarNotify.$4a = function (){myFunctoExpandCalendar();OldCalendarNotify4a();}}
function myFunctoExpandCalendar(){try{var aTags=document.getElementsByTagName('A');for(i=0;i<aTags.length;i++){try{if(aTags[i].evtid=="expand_collapse"){aTags[i].click();break;}}catch(err){ alert('Bad Call at' + aTags[i].href);}}}catch(err){alert(err.message);}}</script>
What it does is after the calendar is loaded it searches for the first expand link and simulates a click.
I had to use the traditional Javascript as I cannot trigger click using JQuery, because the click method is not added using JQuery.
Let me know if somefine finds a better solution.
Two options for this one. Stick one or the other of the following in a CEWP.
The first one will override the function that is used to determine how many items to display before showing the expand/collapse link. I have set this to 100 in the example below to ensure that in my use case, I never even see the expand/collapse buttons and I always get every item rendered all the time.
<script type="text/javascript">
_spBodyOnLoadFunctionNames.push('WaitForCalendarToLoad');
function WaitForCalendarToLoad()
{
SP.UI.ApplicationPages.SummaryItemRenderer.prototype.$2u = function ()
{
ULSvSp: ;
if (!this.$1A_1) this.$1A_1 = 100;
return this.$1A_1
}
}
</script>
The second option overrides the calendar notify event, so that after all the items are rendered, the script will find the first calendar instance, and call it's expand all function. This will ensure every cell is expanded by default but will still show the collapse links.
<script type="text/javascript">
_spBodyOnLoadFunctionNames.push('WaitForCalendarToLoad');
function WaitForCalendarToLoad()
{
var old$4a = SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function ()
{
old$4a();
ctrl = SP.UI.ApplicationPages.CalendarInstanceRepository.firstInstance();
if (ctrl) {
ctrl.expandAll();
}
}
}
</script>
I'm using this (in 2013):
<style>
.ms-cal-nav { display:none; }
</style>
<script type="text/javascript">
LoadSodByKey("SP.UI.ApplicationPages.Calendar.js", function () {
window.setTimeout(ExpandCalendar, 500);
});
function ExpandCalendar() {
// expand always
$('.ms-cal-nav:has(img[src$="/expandbttn.gif"])').each(function() { this.click(); });
window.setTimeout(ExpandCalendar, 1000);
}
</script>
It runs every second, which isn't great, but seems to do the job
So based on the original solutions provided by Andrew Peacock (presumably for SP2010), I was able to use those as a stating point to put together a working solution for SP2016.
The big difference seems to be that CalendarNotify is deprecated in SP2016, which causes many of the SP2010-based solutions not to work in newer versions. Then there are additional complications if using overlaid calendars; it seems that the HTML elements for events on overlaid calendars are not rendered until very late in the page load process - even waiting on the last sourced script on the page (sp.ui.socialribbon.js) using SP.SOD does not wait long enough for those to be available. I believe this is why most, if not all of the solutions for SP2016 calendars that rely on these being available must end up using either setTimeout() or setInterval(). In our case, for the second solution, we need to wait until all overlaid events have been rendered on the calendar before calling the calendar's expandAll() function or it won't work.
With that said, these are the two SP2016-compatible solutions I came up with, based off the original SP2010 solutions noted above. The first removes the expand/collapse link altogether and ensures that the calendar will always be expanded to show all events.
The first method overrides the built-in function that sets the "collapse item limit" (the number of items that will force the "expand/collapse" link to appear).
<script type="text/javascript">
function setCalendarCollapseItemLimit() {
// Configure the calendar's "collapse item limit" so that it always shows
// all items by default and never collapses them.
SP.UI.ApplicationPages.SummaryItemRenderer.prototype.$3V_1 = function() {
ULSvSp:;
if(!this.$1B_1) {
// This sets the "collapse item limit" to 100 events
this.$1B_1 = 100;
}
return this.$1B_1;
}
}
// Call our function once the necessary script is loaded (sp.ui.applicationpages.calendar.js in this case).
ExecuteOrDelayUntilScriptLoaded(setCalendarCollapseItemLimit, "sp.ui.applicationpages.calendar.js");
</script>
The advantage of this method is that it stays expanded even if new events are added to the calendar after the page loads, with no need to manually re-expand or refresh the page. The downside is that this solution may need updating after an upgrade since the obfuscated variable names may change (this example was confirmed working w/ SP2016 w/ the 7/2017 CU - v16.0.4561.1000).
The second method calls the calendar's built-in expandAll() function once all the events are displayed. The advantage of this method is that it leaves the "collapse" link available for the user to collapse the calendar if desired.
<script type="text/javascript">
function expandAllCalendarItems() {
var cal = SP.UI.ApplicationPages.CalendarInstanceRepository.firstInstance();
if (cal) {
cal.expandAll();
return true;
} else {
return false;
}
}
// We need to use setInterval() here so that the calendar will be expanded when it becomes available and
// after any overlaid calendar events have been rendered. An interval of 1400 seems to be sufficient for this.
// We store the return value so that we can clear it (stop the loop) once we’ve successfully expanded it.
var expItemsInterval = setInterval(function() {
var retVal = expandAllCalendarItems();
if (retVal === true) {
// Calendar was expanded - clear interval
clearInterval(expItemsInterval);
}
}, 1400);
</script>
I'm not a huge fan of this solution though since it has a couple big downsides. One is that the calendar will re-collapse if a new event is added to it after the page is loaded. More importantly, however, is the fact that we are relying on the interval being long enough to wait for all overlaid calendar events to be rendered on the page (if using calendar overlays). Therefore we have a sort of race condition here; an interval of 1400 seems to be long enough in my testing for it to work properly, but theoretically if the overlaid events take too long to render, this solution might not work. If not using overlaid calendars then this should not be an issue.
A more proper solution would probably be to use something like a MutationObserver to watch for new elements being added to the page (specifically, divs with a class of .ms-acal-mdiv), and call expandAll() again if a new one is detected. This would also solve the problem of re-expanding the calendar after a new event is added.
All in all, if showing the "collapse" link to the user is not required, I prefer the first solution. I think its the cleanest and most foolproof, since it does not rely on setInterval() and works with both regular and overlaid calendars.
Big thanks to Andrew Peacock for the original solutions here; those put me on the right track for figuring these out for SP2016.
*EDIT: Removed the jQuery dependency since it was unnecessary, and added script tags around the code. This would need to be implemented via SharePoint Designer, right under the PlaceHolderMain tag (using a SEWP or CEWP would probably work as well but I didn't test using those methods).
function expandCalendar()
{
var calendar = SP.UI.ApplicationPages.CalendarInstanceRepository.firstInstance();
if (calendar && typeof calendar.expandAll === 'function') {
calendar.expandAll();
}
精彩评论