Xpages Bootstrap启用日历

时间:2017-01-26 19:37:10

标签: xpages

在启用Bootstrap的Web应用程序中使用iNotesCalendar视图提供了一个不太吸引人的日历(见下文)

enter image description here

有没有办法在日历周围包装一些引导样式?我在XPages4Bootstrap或Bootstrap页面上找不到任何关于bootstrap日历的信息。

1 个答案:

答案 0 :(得分:1)

正如埃里克所说,我将回答我自己的问题。一个非常好的起点是Frank's excellent post

我会发布很多代码和尽可能多的解释。

首先,您需要获取文件并将其添加到NSF的WebContent文件夹中,您可以在Package Explorer中找到它。我制作了一个名为“FullCalendar”的子文件夹,以保持秩序井然。

enter image description here

为您的日历创建自定义控件。 [此条目底部的代码。]

我的自定义控件中有一些东西我必须添加到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>