在启用Bootstrap的Web应用程序中使用iNotesCalendar视图提供了一个不太吸引人的日历(见下文)
有没有办法在日历周围包装一些引导样式?我在XPages4Bootstrap或Bootstrap页面上找不到任何关于bootstrap日历的信息。
答案 0 :(得分:1)
正如埃里克所说,我将回答我自己的问题。一个非常好的起点是Frank's excellent post。
我会发布很多代码和尽可能多的解释。
首先,您需要获取文件并将其添加到NSF的WebContent文件夹中,您可以在Package Explorer中找到它。我制作了一个名为“FullCalendar”的子文件夹,以保持秩序井然。
为您的日历创建自定义控件。 [此条目底部的代码。]
我的自定义控件中有一些东西我必须添加到Frank的解释中,这些解释特别适用于我的环境 - 他们可能也适用于你的。
首先,请注意我将xsp.resources.aggregate属性设置为“true”,这会覆盖数据库设置false。我不记得为什么我必须这样做,但除非我这样做,否则我的日历不起作用。
注意:我找到了code and the reason in this post。
接下来,我添加了三个资源,其中3个与FullCalendar相关(第四个是一些常见的布局css)。这里的顺序非常重要。必须在 moment.min.js之前加载,必须在fullcalendar.min.js之前加载。虽然不看jQuery吗? jQuery已经加载到我的主题中,不想再次加载它。
请注意,使用head标记和属性时刻会加载一些不熟悉的语法。我发布了一个关于使用Bootstrap with Full Calendar的问题。长话短说,你还必须解决AMD问题(见帖子),然后像我一样加载资源来实现这一点,尽管我想我做错了什么!
按钮等有一些标准类型的代码,还有一个div容器。真正的工作是在脚本块中,重要的部分是调用其余服务。我试图使其相当标准 - 我总是将rest元素放在一个名为XpRest.xsp的设计元素中,然后在每个元素上添加一个特定的名称,这个元素是CalendarEvents。
此rest服务元素调用java Rest服务。其余服务扩展库设计元素的代码是:
<xe:restService
id="restService2"
pathInfo="calendarEvents"
ignoreRequestParams="false"
state="false"
preventDojoStore="true">
<xe:this.service>
<xe:customRestService
contentType="application/json"
serviceBean="com.XXXX.rest.CalendarEvents">
</xe:customRestService>
</xe:this.service>
</xe:restService>
所以这将调用java rest服务,其代码是......
package com.XXXXX.rest;
import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.openntf.domino.Database;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewNavigator;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.DateTime;
import com.ibm.commons.util.io.json.JsonException;
import com.ibm.commons.util.io.json.util.JsonWriter;
import com.ibm.domino.services.ServiceException;
import com.ibm.domino.services.rest.RestServiceEngine;
import com.ibm.xsp.extlib.component.rest.CustomService;
import com.ibm.xsp.extlib.component.rest.CustomServiceBean;
import com.scoular.cache.CacheBean;
public class CalendarEvents extends CustomServiceBean {
@SuppressWarnings("unused")
private Database dataDB;
@Override
public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {
try {
HttpServletRequest request = engine.getHttpRequest();
HttpServletResponse response = engine.getHttpResponse();
response.setHeader("Content-Type", "application/json; charset=UTF-8");
response.setContentType("application/json");
response.setHeader("Cache-Control", "no-cache");
response.setCharacterEncoding("utf-8");
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods", "GET, POST");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "86400");
String method = request.getMethod();
if (method.equals("GET")) {
this.doGet(request, response);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, JsonException {
try {
Integer cnt = 0;
ViewNavigator nav;
View chgView;
DateTime tmpDte;
Date tmpDte2;
Database DB = this.getDataDB();
chgView = DB.getView("(xpViewCalendar01)");
nav = chgView.createViewNav();
Writer out = response.getWriter();
JsonWriter writer = new JsonWriter(out, false);
writer.isCompact();
writer.startArray();
for (ViewEntry entry : nav) {
//Vector<?> columnValues = entry.getColumnValues();
cnt = cnt + 1;
writer.startArrayItem();
writer.startObject();
//Event Title
writer.startProperty("title");
writer.outStringLiteral(String.valueOf(entry.getColumnValues().get(0)));
writer.endProperty();
//Change id
writer.startProperty("id");
writer.outStringLiteral(cnt.toString());
writer.endProperty();
//Start Date and Time
writer.startProperty("start");
tmpDte = (DateTime) entry.getColumnValues().get(4);
tmpDte2 = tmpDte.toJavaDate();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
String tmpStr = df.format(tmpDte2);
writer.outStringLiteral(tmpStr);
writer.endProperty();
//End Date and Time (same as start)
writer.startProperty("end");
writer.outStringLiteral(tmpStr);
writer.endProperty();
writer.endObject();
writer.endArrayItem();
}
writer.endArray();
writer.flush();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Database getDataDB() {
Session session = Factory.getSession();
Database DataDB = session.getDatabase(CacheBean.get().getAppDataDBPath());
return DataDB;
}
public void setDataDB(Database dataDB) {
this.dataDB = dataDB;
}
}
这个休息服务还没有完全完成,因为我没有抓住“结束”日期,也没有抓住allDay元素,尽管我已经在报名表中为它们添加了钩子。但我认为添加到此代码非常容易。
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.properties>
<xp:parameter name="xsp.resources.aggregate" value="true" />
</xp:this.properties>
<xp:this.resources>
<xp:headTag tagName="script">
<xp:this.attributes>
<xp:parameter name="type" value="text/javascript" />
<xp:parameter name="src"
value="FullCalendar/moment.min.js" />
</xp:this.attributes>
</xp:headTag>
<xp:script src="FullCalendar/fullcalendar.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet href="FullCalendar/fullcalendar1.min.css"></xp:styleSheet>
<xp:styleSheet href="/cc_CommonGrid.css"></xp:styleSheet>
</xp:this.resources>
<!--The Container-->
<div class="container-fluid">
<!--The Button Bar-->
<div class="toolbar" style="width: 100% !important">
<div class="row">
<span style="margin-right:10px">
<button type="button" id="newDoc"
class="btn btn-primary">
Add Event
</button>
</span>
<span style="float: right">
<div class="input-group" style="width:300px">
<input type="text" id="searchInput"
class="form-control"
style="border-radius: 5px; border-bottom-right-radius:0px ;border-top-right-radius: 0px"
placeholder="Search for..." />
</div>
</span>
</div>
</div>
<!--The Button Bar-->
<!--The Grid-->
<div
id="div1"
class="row"
style="margin-top:15px">
<!--The Grid-->
<xp:div
id="grid"
style="background-color:rgb(255,255,255)"
styleClass="cal">
</xp:div>
<!--The Grid-->
</div>
<!--The Grid-->
</div>
<!--The Container-->
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[// Add Document
$('#newDoc').click(function(event){
var url = "xpFormEvent.xsp";
window.open(url,"_self");
});
$(document).ready(function() {
//Get URL for web serice
var b1 = "#{javascript:context.getUrl().getAddress().replace(view.getPageName(), '');}"
var b2 = b1 + "/xpRest.xsp/calendarEvents";
var calCon = $(".cal");
calCon.fullCalendar({
header: {
left: 'prevYear,nextYear',
center: 'title',
right: 'today,month,prev,next'
},
eventSources: [
{
url: b2
}
]
});
})
]]></xp:this.value>
</xp:scriptBlock>
</xp:view>
好的,这里是ccCalendarView01的代码:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:this.properties>
<xp:parameter name="xsp.resources.aggregate" value="true" />
</xp:this.properties>
<xp:this.resources>
<xp:headTag tagName="script">
<xp:this.attributes>
<xp:parameter name="type" value="text/javascript" />
<xp:parameter name="src"
value="FullCalendar/moment.min.js" />
</xp:this.attributes>
</xp:headTag>
<xp:script src="FullCalendar/fullcalendar.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet href="FullCalendar/fullcalendar1.min.css"></xp:styleSheet>
<xp:styleSheet href="/cc_CommonGrid.css"></xp:styleSheet>
</xp:this.resources>
<!--The Container-->
<div class="container-fluid">
<!--The Button Bar-->
<div class="toolbar" style="width: 100% !important">
<div class="row">
<span style="margin-right:10px">
<button type="button" id="newDoc"
class="btn btn-primary">
Add Event
</button>
</span>
<span style="float: right">
<div class="input-group" style="width:300px">
<input type="text" id="searchInput"
class="form-control"
style="border-radius: 5px; border-bottom-right-radius:0px ;border-top-right-radius: 0px"
placeholder="Search for..." />
</div>
</span>
</div>
</div>
<!--The Button Bar-->
<!--The Grid-->
<div
id="div1"
class="row"
style="margin-top:15px">
<!--The Grid-->
<xp:div
id="grid"
style="background-color:rgb(255,255,255)"
styleClass="cal">
</xp:div>
<!--The Grid-->
</div>
<!--The Grid-->
</div>
<!--The Container-->
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[// Add Document
$('#newDoc').click(function(event){
var url = "xpFormEvent.xsp";
window.open(url,"_self");
});
$(document).ready(function() {
//Get URL for web serice
var b1 = "#{javascript:context.getUrl().getAddress().replace(view.getPageName(), '');}"
var b2 = b1 + "/xpRest.xsp/calendarEvents";
var calCon = $(".cal");
calCon.fullCalendar({
header: {
left: 'prevYear,nextYear',
center: 'title',
right: 'today,month,prev,next'
},
eventSources: [
{
url: b2
}
]
});
})
]]></xp:this.value>
</xp:scriptBlock>
</xp:view>