:::

DSpace新增input-type——安裝篇

布丁布丁吃布丁

DSpace新增input-type——安裝篇

DSpace新增input-type目錄

  1. 安裝篇
  2. TextEditor篇
  3. FileUpload篇
  4. XMLMetadata篇

目前的DSpace 1.4.2~1.5雖然提供了很多input-type,像onebox(單欄)、textarea(多行)、dropdown(下拉式),但是使用起來還是覺得不夠,尤其是資料儲存無法像樹狀結構一樣靈活,在設計Metadata的時候更是一個很大的限制(雖然很多架設DSpace的人都沒有更動過input-forms的樣子)。

為了改進DSpace的不足,我以DSpace 1.5版開發出以下三種輸入表單型態:

texteditor

把原本的textarea以FCKeditor取代,並設定自動隱藏工具列。最後輸出資料則是html程式碼。

image

fileupload

在edit-metadata的步驟中,透過AJAX技術直接使用DSpace上傳步驟的功能。

上傳前:image

上傳後:image

xmlmetadata

可允許樹狀結構的metadata,並允許特定節點重複,可更靈活地儲存資料。一樣具備onebox、dropdown、textarea、texteditor、fileupload等多種輸入類型。

image

此篇介紹如何修改DSpace 1.5的各個檔案,以呈現出以上的功能,使用與設定則留到其他篇再講吧!


安裝環境與路徑縮寫說明

DSpace 1.5版本跟之前的1.4.2版本各程式存放的路徑上有很大的差別,此處我以1.5版為主,安裝在CentOS 5 Final上,JSP伺服器是Apache Tomcat 6.0.16

以下說明各路徑的簡寫:

[dspace-source]:DSpace原始檔的位置,通常位於「/opt/dspace-1.5.0-src-release/」

[dspace-jspui-webapp]:JSPUI原始碼路徑,通常位於「[dspace-source]/dspace-jspui/dspace-jspui-webapp/src/main/webapp」之中。根據文件說明,修改之後存放的檔案請放到「[dspace-source]/dspace/modules/jspui/src/main/webapp/」之中。

[dspace-jspui-api]:JSPUI的API,通常位於「/opt/dspace-1.5.0-src-release/dspace-jspui/dspace-jspui-api/src/main/java/org/dspace/app/webui/」。

[dspace-api]:DSpace的API,許多核心程式都擺在這邊,通常位於「[dspace-source]/dspace-api/src/main/java/org/dspace/」

[dspace]:DSpace安裝完成之後的目的地,包括input-forms.xml設定檔都要在這邊修改。預設的位置是「/dspace/」。

[tomcat]:JSP伺服器的安裝位置,通常是在「/opt/apache-tomcat-6.0.16/」裡面。

那麼以下就是安裝與修改的步驟囉!我會列出「路徑與檔名」、「我的程式碼下載」、「程式碼說明」以方便大家修改或安裝。因為細節繁雜,所以有可能有所遺漏,請在下方的回應欄盡量批評吧!


[dspace-jspui-webapp]/extension/...... (extension.20081018.zip)

這是一個新開啟的資料夾,裡面擺放我撰寫的JavaScript、CSS程式,請下載附件extension.zip,並擺放到該路徑去。裡面又分成幾個部份:(以下檔案所指的根目錄就是「[dspace-jspui-webapp]/extension/」,之後其他敘述也同這個道理)

/jquery.js:JavaScript的函式庫jQuery,在此使用的是1.2.1版本,讓JavaScript程式撰寫起來輕鬆很多,我撰寫的JavaScript都會用到jQuery。

/fckeditor/FCKeditor 2.6.3版本,一種JavaScript的網頁內嵌所見即得編輯器,可用類似Word的操作介面、建立HTML程式碼。用於input-type: texteditor,可改善DSpace 1.5只能顯示單調文字的缺點。

/fckeditor/fckeditor_display_toggle.js:用來自動隱藏/顯示工具列的函式。

/ajaxfileupload/ajaxfileupload.js:jQuery的Plugin,我改寫成適合DSpace檔案上傳的版本。

/ajaxfileupload/ajaxfileupload_fn.js:供input-type: fileupload呼叫ajaxfileupload.js的函式,裡面可設定fileupload的參數,但照以下安裝步驟的話是不需要修改此設定的。

/ajaxfileupload/ajaxfileupload_fnXML.js:給XMLMetadata呼叫ajaxfileupload.js的函式。

/xmlmetadata/dspace-inputtype-xml.js:XMLMetadata主要的JavaScript函式程式碼。

/xmlmetadata/dspace-inputtype-xml.css:XMLMetadata在呈現表單跟表格時的樣式表。

/xmlmetadata/ui.datepicker.js:jQuery的UI:Datepicker,可以方便挑選日期,用於XMLMetdata的input-type: date,我想這應該比DSpace原本的date好用很多。

/xmlmetadata/flora.datepicker.css:Datepicker的樣式表。

/display-item/metadata-value-display.js:在Display Item頁面時,針對fileupload跟xmlmetadata兩種資料調整呈現的樣貌。

這些程式只用短短的半個月時間寫完,也還沒做嚴格的測試,如果之後有改良的版本,會直接在此更新,並加上日期版本。


[dspace-jspui-webapp]/submit/...... (submit.20081015.zip)

這邊我修改了在進行上傳步驟的程式碼,以下一一說明。

/edit-metadata.jsp

image

DSpace描述階段的程式碼,為了能夠新增這三種input-type,在這一頁下了很多功夫。以下是修改細項:

修改1:引用所需的JavaScript跟CSS檔案。 請在<dspace>標籤開始之後插入這些引用吧。(紅色部份是新增的程式碼)

<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.edit-metadata.title">

<script type="text/javascript" src="<%= request.getContextPath() %>/extension/jquery.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/fckeditor/fckeditor.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload_fn.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload_fnXML.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/fckeditor/fckeditor_display_toggle.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/xmlmetadata/dspace-inputtype-xml.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/xmlmetadata/ui.datepicker.js"></script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/flora.datepicker.css" type="text/css" media="screen" title="Flora (Default)">
<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/dspace-inputtype-xml.css" type="text/css" media="screen">

修改2:定義要丟給新增函式的變數。包括workspaceItem的ID(目前遞交作業的ID)、nonInternalBistreams的ID(哪些是公開的檔案)、hasMultipleFiles(是否允許多檔案上傳)、defaultValue(XMLMetadata的預設呈現樣貌)。請加在設定inputType、label跟closedVocabulary的後面吧。(紅色部份是新增的程式碼)



       String label = inputs[z].getLabel();
       boolean closedVocabulary = inputs[z].isClosedVocabulary();

>     //For fileupload
     int workspaceItemID = si.getSubmissionItem().getID();
     Bitstream[] bitstreams = si.getSubmissionItem().getItem().getNonInternalBitstreams();
     ArrayList nonInternalBistreamsID = new ArrayList();  //new Int(bitstreams);
     for (int i = 0; i < bitstreams.length; i++)
         nonInternalBistreamsID.add(bitstreams[i].getID());
     boolean hasMultipleFiles = si.getSubmissionItem().hasMultipleFiles();
    
     //For XMLMetadata & other
     String defaultValue = inputs[z].getDefaultValue();

修改3:新增input-type呼叫函式的判斷式。在下方有if else的判斷式,程式會依照input-type的值不同,呼叫不同的函式,那麼我們就把這三個新增的函式也加入判斷之中,新增在list跟onebox之間吧。(紅色部份是新增的程式碼)

       else if (inputType.equals("list"))
       {
          doList(out, item, fieldName, dcSchema, dcElement, dcQualifier,
               repeatable, inputs[z].getPairs(), label);
       }
     else if (inputType.equals("texteditor"))
       {
         doTextEditor(out, item, fieldName, dcSchema, dcElement, dcQualifier,
                repeatable, fieldCountIncr, label, pageContext, vocabulary,
               closedVocabulary, request.getContextPath() + "/extension/fckeditor/");
       }
     else if (inputType.equals("fileupload"))
       {
         doFileUpload(out, item, fieldName, dcSchema, dcElement, dcQualifier,
              repeatable, fieldCountIncr, label, pageContext, vocabulary,
              closedVocabulary, workspaceItemID, nonInternalBistreamsID,
           hasMultipleFiles);
       }
     else if (inputType.equals("xmlmetadata"))
       {
         doXMLMetadata(out, item, fieldName, dcSchema, dcElement, dcQualifier,
                repeatable, fieldCountIncr, label, pageContext, vocabulary,
               closedVocabulary, workspaceItemID,
            nonInternalBistreamsID, hasMultipleFiles, defaultValue);
       }

       else
       {
         doOneBox(out, item, fieldName, dcSchema, dcElement, dcQualifier,
              repeatable, fieldCountIncr, label, pageContext, vocabulary,
              closedVocabulary);
       }

修改4:宣告doTextEditor()、doFileUpload()跟doXMLMetadata()。請寫在doList結尾之後吧(紅色的部份是新增的程式碼):

          }//end doList

    void doTextEditor(javax.servlet.jsp.JspWriter out, Item item,
      String fieldName, String schema, String element, String qualifier, boolean repeatable,
      int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary, String sBasePath)
      throws java.io.IOException
    {

      DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY);
      int fieldCount = defaults.length + fieldCountIncr;
      StringBuffer sb = new StringBuffer();
      String val;

      if (fieldCount == 0)
         fieldCount = 1;

      for (int i = 0; i < fieldCount; i++)
      {
   if (i == 0)
      sb.append("<tr><td class=\"submitFormLabel\">")
        .append(label)
        .append("</td>");
   else
      sb.append("<tr><td> </td>");

         if (i < defaults.length)
           val = defaults[i].value;
         else
           val = "";

         sb.append("<td colspan=\"2\">");

         String textareaName = fieldName;
         if (repeatable && i>0)
            textareaName = textareaName + "_" + i;

         sb.append("<textarea name=\"")
           .append(fieldName);
         if (repeatable && i>0)
           sb.append("_").append(i);
         sb.append("\" rows=\"4\" cols=\"45\"")
           .append(hasVocabulary(vocabulary)&&closedVocabulary?" readonly=\"readonly\" ":"")
           .append("   >")
           .append(val)
     .append("</textarea>")
     .append(doControlledVocabulary(fieldName + (repeatable?"_" + i:""), pageContext, vocabulary));
      

       //FCKeditor ReplaceTextarea
      
       sb.append("<script type=\"text/javascript\">\n")
         .append("  var oFCKeditor = new FCKeditor( \"")
           .append(fieldName);
         if (repeatable && i>0)
           sb.append("_").append(i);
         sb.append("\" ) ;\n")
       .append("  oFCKeditor.Config[\"ToolbarStartExpanded\"] = false ;\n")
         .append("  oFCKeditor.BasePath  = \""+sBasePath+"\" ;\n")
         .append("  oFCKeditor.ReplaceTextarea() ;\n")
         .append("</script>\n");

     sb.append("</td>\n");

   if (repeatable && i < defaults.length)
   {
      // put a remove button next to filled in values
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
        .append("_remove_")
        .append(i)
//        .append("\" value=\"Remove This Entry\"/> </td></tr>");
        .append("\" value=\"")
           .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove"))
           .append("\"/> </td></tr>");
   }
   else if (repeatable && i == fieldCount - 1)
   {
      // put a 'more' button next to the last space
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
//        .append("_add\" value=\"Add More\"/> </td></tr>");
        .append("_add\" value=\"")
        .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add"))
        .append("\"/> </td></tr>");
   }
   else
   {
      // put a blank if nothing else
      sb.append("<td> </td></tr>");
   }
      }

      out.write(sb.toString());
    }  //void doTextEditor()

    void doFileUpload(javax.servlet.jsp.JspWriter out, Item item,
      String fieldName, String schema, String element, String qualifier, boolean repeatable,
      int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary,
    int workspaceItemID, ArrayList nonInternalBistreamsID, boolean hasMultipleFiles)
      throws java.io.IOException
    {

      DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY);
    fieldCountIncr = 1;
      int fieldCount = defaults.length + fieldCountIncr;
      StringBuffer sb = new StringBuffer();
      String val;
    
      if (fieldCount == 0)
         fieldCount = 1;

      for (int i = 0; i < fieldCount; i++)
      {
   if (i == 0)
      sb.append("<tr><td class=\"submitFormLabel\">")
        .append(label)
        .append("</td>");
   else
      sb.append("<tr><td> </td>");

         if (i < defaults.length)
           val = defaults[i].value.replaceAll("\"", """);
         else
           val = "";
      
    if (!val.equals(""))
    {
      String[] tempID = val.split("/");
      if (tempID.length > 2)
      {
        //String id = tempID[(tempID.length - 2)];
      int id = Integer.parseInt(tempID[(tempID.length - 2)]);
      
      int index = nonInternalBistreamsID.indexOf(id);
      if (index == -1)  continue;
      }
    }
      
         String inputName = fieldName;
         if (repeatable && i>0)
           inputName = inputName + "_" + i;


       sb.append("<td colspan=\"2\">");

    if (hasMultipleFiles == true)
    {
    sb.append("\n<input type=\"text\" id=\""+inputName+"\" name=\""+inputName+"\" value=\""+val+"\" style=\"display:none\"   />\n")
      .append("  <input type=\"file\" onchange=\"jQuery(this).nextAll('button.fileupload-do:first').click()\" />\n")
      .append("  <span></span>\n")
      .append("  <button class=\"fileupload-do\" onclick=\"return ajaxFileUpload(this, "+workspaceItemID+", '"+label+"');\" type=\"button\">Upload</button>\n");
      
       if (!val.equals(""))
       {
      sb.append("  <script type=\"text/javascript\">")
        .append("  ajaxFileUploadExist(\""+inputName+"\");")
        .append("</script>");
       }
    }  //if (hasMultipleFiles == true)
    else
    {
      sb.append("Please check \""+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.initial-questions.elem3")+"\"! \n");
    }
       sb.append("</td>\n");
    

   if (repeatable && i < defaults.length)
   {
      // put a remove button next to filled in values
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
        .append("_remove_")
        .append(i)
//        .append("\" value=\"Remove This Entry\"/> </td></tr>");
        .append("\" value=\"")
           .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove"))
           .append("\" style=\"display:none\" ")
      .append("/>")
      .append("<button type=\"button\" onclick=\"ajaxFileUploadRemove(this, "+workspaceItemID+")\">"+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>")
      .append(" </td></tr>");
   }
   else if (repeatable && i == fieldCount - 1)
   {
      // put a 'more' button next to the last space
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
//        .append("_add\" value=\"Add More\"/> </td></tr>");
        .append("_add\" value=\"")
        .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add"))
        .append("\"/> </td></tr>");
   }
   else
   {
      // put a blank if nothing else
      sb.append("<td>")
      .append("  <button class=\"fileupload-cancel\" onclick=\"return ajaxFileUploadCancel(this, "+workspaceItemID+")\" style=\"display:none\" type=\"button\">"+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>\n")
      .append(" </td></tr>");
   }
      }

      out.write(sb.toString());
    }  //end of doFileUpload

    void doXMLMetadata(javax.servlet.jsp.JspWriter out, Item item,
      String fieldName, String schema, String element, String qualifier, boolean repeatable,
      int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary,
    int workspaceItemID, ArrayList nonInternalBistreamsID, boolean hasMultipleFiles, String defaultValue)
      throws java.io.IOException
    {

      DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY);
      int fieldCount = defaults.length + fieldCountIncr;
      StringBuffer sb = new StringBuffer();
      String val;

      if (fieldCount == 0)
         fieldCount = 1;

      for (int i = 0; i < fieldCount; i++)
      {
   if (i == 0)
      sb.append("<tr><td class=\"submitFormLabel\">")
        .append(label)
        .append("</td>");
   else
      sb.append("<tr><td> </td>");

         if (i < defaults.length)
           val = defaults[i].value;
         else if (defaultValue != null)
           val = defaultValue;
     else
       val = "";
    
         sb.append("<td colspan=\"2\">");

         String textareaName = fieldName;
         if (repeatable && i>0)
            textareaName = textareaName + "_" + i;

         sb.append("<textarea id=\""+textareaName+"\" name=\"")
           .append(fieldName);
         if (repeatable && i>0)
           sb.append("_").append(i);
         sb.append("\" rows=\"4\" cols=\"45\"")
           .append(hasVocabulary(vocabulary)&&closedVocabulary?" readonly=\"readonly\" ":"")
           .append("   >")
           .append(val)
     .append("</textarea>")
     .append(doControlledVocabulary(fieldName + (repeatable?"_" + i:""), pageContext, vocabulary));
      

       //XMLMetadata Form Creator
       if (!val.equals(""))
     {
       sb.append("\n\n<script type=\"text/javascript\">\n")
         .append("var xm = new XMLMetadata(\""+textareaName+"\");\n")
         .append("xm.workspaceItemID = "+workspaceItemID+";\n")
         .append("xm.fieldTitle = '"+label+"';\n");
       if (hasMultipleFiles == false)
       {
         sb.append("xm.hasMultipleFiles = false;\n");
        sb.append("xm.langNotHasMultipleFiles = \"Please check \'"+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.initial-questions.elem3")+"\'!\";\n");
       }
      
       if (nonInternalBistreamsID.size() != 0)
       {
         String nIBIDary = "[";
         for (int b = 0; b < nonInternalBistreamsID.size(); b++)
         {
          if (b > 0)
            nIBIDary = nIBIDary + ",";
          nIBIDary = nIBIDary + nonInternalBistreamsID.get(b);
         }
         nIBIDary = nIBIDary + "]";
         sb.append("xm.nonInternalBistreamsID = "+nIBIDary+";\n");
       }
       sb.append("xm.createRootForm();\n");
       sb.append("</script>\n");
      }

     sb.append("</td>\n");

   if (repeatable && i < defaults.length)
   {
      // put a remove button next to filled in values
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
        .append("_remove_")
        .append(i)
//        .append("\" value=\"Remove This Entry\"/> </td></tr>");
        .append("\" value=\"")
           .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove"))
           .append("\"/> </td></tr>");
   }
   else if (repeatable && i == fieldCount - 1)
   {
      // put a 'more' button next to the last space
      sb.append("<td><input type=\"submit\" name=\"submit_")
        .append(fieldName)
//        .append("_add\" value=\"Add More\"/> </td></tr>");
        .append("_add\" value=\"")
        .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add"))
        .append("\"/> </td></tr>");
   }
   else
   {
      // put a blank if nothing else
      sb.append("<td> </td></tr>");
   }
      }

      out.write(sb.toString());
    }  //void doXMLMetadata()

%>

doTextEditor()跟doXMLMetadata()是參考doTextArea()而來的,而doFileUpload()則是參考doOneBox()。

修改5:移除doPersonalName()、doSeriesNumber()跟doTwoBox()的寬度限制。不知為何這些函式都把表格寬度鎖死了,他們裡面都會擁有類似的程式碼,我舉doPersonalName()的設定為例:(紅色為刪除寬度限制的程式碼,附近的註解則是原本有限制寬度的程式碼)

      //Width hints used here to affect whole table
      headers.append("<tr><td> </td>") //.append("<tr><td width=\"40%\"> </td>")
             //.append("<td class=\"submitFormDateLabel\" width=\"5%\">")
       .append("<td class=\"submitFormDateLabel\">")
//             .append("Last name<br>e.g. <strong>Smith</strong></td>")
       .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.lastname"))
       .append("</td>")
             //.append("<td class=\"submitFormDateLabel\" width=\"5%\">")
      .append("<td class=\"submitFormDateLabel\">")
//             .append("First name(s) + \"Jr\"<br> e.g. <strong>Donald Jr</strong></td>")
       .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.firstname"))
       .append("</td>")
             //.append("<td width=\"40%\"> </td>")
      .append("<td> </td>")
             .append("</tr>");
      out.write(headers.toString());

修改6:修改欄位寬度配置。每一列輸入欄位中間都會間隔一個調整欄位寬度用的列,我們可以藉由調整這一列來控制欄位大小,但前提是要先移除掉上面那幾個函式裡面的寬度限制。(紅色部份是修改過後的值,表示左右各保留10%留白,中間則是有80%的寬度。)

<%-- HACK: Using this line to give the browser hints as to the widths of cells --%>
       <tr>
         <td width="10%"> </td>
         <td colspan="2" width="80%"> </td>
         <td width="10%"> </td>
       </tr>
/upload-file-list.jsp跟/get-file-format.jsp

image upload-file-list.jsp

image get-file-format.jsp

前者上傳檔案之後的列表、後者是當上傳檔案格式不明時會提示使用者選擇檔案格式的網頁。當這些網頁被讀取時,我想要轉換成以json格式呈現剛剛上傳檔案的資料(json是JavaSciprt常用的輕量級資料語言)。要讓upload-file-list.jsp跟get-file-format.jsp正常運作,必需要傳送以下參數:

  • workspace_item_id:遞交階段的ID,可由si.getSubmissionItem().getID()取得,這段程式碼寫在edit-metadata的修改2當中。
  • step:上傳檔案的階段,預設是「3」,以下教學會將之改成「2」。可在ajaxfileupload_fn.js裡面設定。
  • page:上傳檔案只會有1頁,輸入「1」即可。可在ajaxfileupload_fn.js裡面設定。
  • jsp:預設是由choose-file.jsp傳送過去,輸入值為「/submit/choose-file.jsp」即可。可在ajaxfileupload_fn.js裡面設定。
  • description:上傳檔案的敘述,可空白或不傳,我在fileupload的設定是會傳label的值。可在ajaxfileupload.js裡面設定。
  • submit_upload:要有值程式才知道是上傳的步驟,我則是固定填入「&gt;」。可在ajaxfileupload.js裡面設定。

修改:用網址設定呈現時轉址到顯示json的網頁。如果網址中包含「action=json」,那麼我就轉到另一個顯示json的網頁去。轉址的這段程式碼插入在<dspace>標籤前後,細節如下:(紅色部份為<dspace>標籤之外新增的程式碼)

  String action = (String) UIUtil.getOriginalURL(request);
if (action.indexOf("action=json") != -1)
{
   JSPManager.showJSP(request, response,
                    "/submit/upload-file-json.jsp");
}
else
{
%>

<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.get-file-format.title" nocache="true">

……

</dspace:layout>
<%
}  
%>
/upload-file-json.jsp

上面的修改之後會轉到這個網頁,這是我另外撰寫的程式。該程式會去取得最新上傳的檔案(專門指bitstream),回傳filename、url、format等參數。程式也很簡單,只有22行,原始碼如下:

<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="" %>
<%@ page import="org.dspace.core.Context" %>
<%@ page import="org.dspace.app.webui.servlet.SubmissionController" %>
<%@ page import="org.dspace.app.util.SubmissionInfo" %>
<%@ page import="org.dspace.content.Bitstream" %>
<%@ page import="org.dspace.app.webui.util.UIUtil" %>
<%
    // Obtain DSpace context
    Context context = UIUtil.obtainContext(request);    

  //get submission information object
    SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request);

Bitstream[] bitstreams = subInfo.getSubmissionItem().getItem().getNonInternalBitstreams();
Bitstream json_bitsream = bitstreams[0];  //bitstreams[(bitstreams.length-1)];  
%>
{
  error: '',
  filename: '<%= bitstreams[(bitstreams.length-1)].getName() %>',
  url: '<%= request.getContextPath() %>/retrieve/<%= bitstreams[(bitstreams.length-1)].getID() %>/<%= org.dspace.app.webui.util.UIUtil.encodeBitstreamName(bitstreams[(bitstreams.length-1)].getName()) %>',
  format: '<%= bitstreams[(bitstreams.length-1)].getFormatDescription() %>'
}

[dspace-jspui-webapp]/display-item.jsp (display-item.20081015.zip)

image

這是顯示item的頁面。我希望顯示的值能夠動態地調整成指定的樣式,而不是只有文字。像是XMLMetadata我希望能以樹狀結構呈現、fileupload則是呈現檔名。

修改1:引用JavaScript跟CSS檔案。作法同edit-metdata.jsp的修改1,程式碼如下:(紅色部份為新增的程式碼)

<dspace:layout title="<%= title %>">

<%
    if (handle != null)
    {
%>

<script type="text/javascript" src="<%= request.getContextPath() %>/extension/jquery.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/display-item/metadata-value-display.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/fckeditor/fckeditor.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload_fn.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/ajaxfileupload/ajaxfileupload_fnXML.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/fckeditor/fckeditor_display_toggle.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/xmlmetadata/dspace-inputtype-xml.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/extension/xmlmetadata/ui.datepicker.js"></script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/flora.datepicker.css" type="text/css" media="screen" title="Flora (Default)">
<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/dspace-inputtype-xml.css" type="text/css" media="screen">



    <table align="center" class="miscTable">

修改2:呼叫metadataValueDisplay()。全部網頁顯示之後的最後,呼叫metadataValueDisplay()以動態調整內容的顯示。程式碼如下:(紅色的部份為新增的程式碼)

<%
    }
%>
    <p class="submitFormHelp"><fmt:message key="jsp.display-item.copyright"/></p>
  <script type="text/javascript">
  metadataValueDisplay("<%= request.getContextPath() %>");
  </script>

</dspace:layout>

老實說,這並不是很好的作法。建議能從JSP顯示的時候就能呈現檔案或XML的樹狀結構,而不是等網頁讀出來再用JavaScript動態修改。但這部份程式得花另一番功夫了。


[dspace-api]/...... (dspace-api.20081015.zip)

API的三個檔案,不小心改錯的話很容易讓整個DSpace都毀掉喔。

/submit/step/DescribeStep.java

此程式會依照input-type來決定資料的儲存方式,由於我新增的三種input-type都是跟著onebox、textarea來跑的,所以就跟他們一樣的設定即可。程式碼如下:(紅色部份為新增的程式)

            else if ((inputType.equals("onebox"))
                    || (inputType.equals("twobox"))
                    || (inputType.equals("textarea"))
          || (inputType.equals("texteditor"))
          || (inputType.equals("xmlmetadata"))
          || (inputType.equals("fileupload")))

            {
                readText(request, item, schema, element, qualifier, inputs[j]
                        .getRepeatable(), "en");
            }
/app/util/DCInput.java

DSpace並沒有預設值的功能,item template文件樣板只是預設該collection底下的item會擁有固定的值,但這跟我們一般認知的預設值:「每次新增欄位時,某些值是被預先載入的」有段差異,尤其是XMLMetadata是將表單的形式預先寫入才能運作,因此我們要幫他新增取得default-value的功能。

修改1:宣告內用變數defaultValue:(紅色部份是新增的程式碼)

    /** is the entry closed to vocabulary terms? */
    private boolean closedVocabulary = false;
    
    /**  for XMLMetadata  */
    private String defaultValue = null;

修改2:用get取得裡面的資料:(紅色部份是新增的程式碼)

        vocabulary = (String) fieldMap.get("vocabulary");
        //for XMLMetadata
        defaultValue = (String) fieldMap.get("default-value");

        String closedVocabularyStr = (String) fieldMap.get("closedVocabulary");

修改3:宣告公用函式getDefaultValue():(紅色部份是新增的程式碼)

  public boolean isClosedVocabulary() {
    return closedVocabulary;
  }
  
  /** for XMLMetadata */
  public String getDefaultValue()
    {
        return defaultValue;
    }

/core/Utils.java

原本DSpace在display item的頁面中,如果你存的資料裡面有用到一些特殊字元的時候,會被轉換成顯示於HTML的脫逸字元(Escape characters,都會以「&」開頭、「;」結尾),以避免這些可能是HTML程式碼的字元影響版面呈現或程式運作。這種脫逸字元跟C、Java、PHP等會用反斜線「\」來脫逸的方式不同,是HTML獨特的編碼。

在DSpace當中,將會被脫逸掉的字元如下:

  • 「&」→「&amp;」
  • 「"」→「&quot;」
  • 「<」→「&lt;」
  • 「>」→「&gt;」」

※HTML的拖曳字元,可以參考網頁:HTML Escape Characters: Complete List

由於我們用到了由FCKeditor轉換而來的HTML,也會使用XMLMetdata來儲存、顯示資料,我們就不能讓他把這些字元脫逸。接著我們就是addEntities()的內容,程式碼如下:(紅色表示註解掉字元脫逸的程式)

    public static String addEntities(String value)
    {
        if (value==null || value.length() == 0)
            return value;
        
        //value = value.replaceAll("&", "&");
        //value = value.replaceAll("\"", """);

        // actually, &apos; is an XML entity, not in HTML.
        // that's why it's commented out.
        // value = value.replaceAll("'", "&apos;");
        //value = value.replaceAll("<", "<");
        //value = value.replaceAll(">", ">");


        return value;
    }

由於存在同名字檔案在/app/util/Utils.java,千萬要小心不要覆蓋錯囉!


[dspace]/config/...... (config.20081015.zip)

調整DSpace的設定。

/input-forms.dtd

此文件定義了input-forms.xml的格式,我們在此處加上default-value的宣告。

修改1:宣告field裡面的default-value是可選擇性的:(紅色部份為新增的程式碼)

<!ATTLIST page number NMTOKEN #REQUIRED>
<!ELEMENT field (dc-schema, dc-element, dc-qualifier?, repeatable?, label, input-type, hint, required?, vocabulary?, default-value?) >
<!ELEMENT dc-schema (#PCDATA) >

修改2:宣告default-value這個元素:(紅色部份為新增的程式碼)

<!ELEMENT form-value-pairs (value-pairs)* >
<!ELEMENT value-pairs (pair)+ >

<!ELEMENT default-value (#PCDATA) >
/item-submission.xml

此處調整敘述階段(describe)跟上傳階段(upload)的順序。原本的順序如下

  1. 取得開始的資訊:他會問你一些問題,像是是否要上傳多個檔案、是否擁有多個標題之類的,你要打勾來決定。
  2. 敘述資料:填寫由input-forms.xml規定好的表單。
  3. 上傳檔案:上傳bitstream檔案。DSpace的設計理念是前面的敘述階段在敘述這個檔案,例如論文的作者、出版資訊等等。預設此階段是一定上傳資料,不過可以在dspace.cfg裡面取消這個設定。
  4. 確認資料:網頁會列出你之前填寫及上傳的資訊,並讓你回頭去修正。
  5. 授權條款的確認

修改:敘述階段與上傳階段互換。如果要在敘述階段上傳檔案,即使我們在上傳階段並不上傳資料,還是必須先經過上傳階段才行。因此我們將敘述階段跟上傳階段調換過來,程式碼如下:(紅色部份為兩個互換的階段)

     <!--Step 1 will be to gather initial information-->
    <step>
      <heading>submit.progressbar.initial-questions</heading>
    <processing-class>org.dspace.submit.step.InitialQuestionsStep</processing-class>
    <jspui-binding>org.dspace.app.webui.submit.step.JSPInitialQuestionsStep</jspui-binding>         
    <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.InitialQuestionsStep</xmlui-binding>
      <workflow-editable>true</workflow-editable>
    </step>  

      <!--Step 2 will be to Upload the item-->
      <step>
        <heading>submit.progressbar.upload</heading>
        <processing-class>org.dspace.submit.step.UploadStep</processing-class>
        <jspui-binding>org.dspace.app.webui.submit.step.JSPUploadStep</jspui-binding>
    <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.UploadStep</xmlui-binding>
        <workflow-editable>true</workflow-editable>
      </step>
          
      <!--Step 3 will be to Describe the item.-->
      <step>
        <heading>submit.progressbar.describe</heading>
        <processing-class>org.dspace.submit.step.DescribeStep</processing-class>
        <jspui-binding>org.dspace.app.webui.submit.step.JSPDescribeStep</jspui-binding>
    <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.DescribeStep</xmlui-binding>
        <workflow-editable>true</workflow-editable>
      </step>
   

    <!--Step 4 will be to Verify/Review everything -->
    <step>
        <heading>submit.progressbar.verify</heading>
        <processing-class>org.dspace.submit.step.VerifyStep</processing-class>
      <jspui-binding>org.dspace.app.webui.submit.step.JSPVerifyStep</jspui-binding>
    <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.ReviewStep</xmlui-binding>
    <workflow-editable>true</workflow-editable>
      </step>
/dspace.cfg
此處有很多DSpace的設定,也包含了是否限制一定要上傳檔案的設定。修改的程式碼如下:(紅色部份為新增的設定) ##### Settings for Submission Process #####

# Should the submit UI block submissions marked as theses?
webui.submit.blocktheses = false

# Whether or not we REQUIRE that a file be uploaded
# during the 'Upload' step in the submission process
# Defaults to true; If set to 'false', submitter has option to skip upload
#webui.submit.upload.required = true
webui.submit.upload.required = false


DSpace操作步驟說明

以上修改完畢之後,還需要進行重新安裝的步驟。

DSpace 1.5版重新安裝:出處在說明文件DSpace System Documentation: Configuration and Customization ([dspace-source]/dspace/docs/configure.html#jspui,dspace.1.5.0.configure.zip),大致上步驟如下:

  1. 進入指令模式
  2. 移動到你的[dspace-source]/dspace/目錄
    > cd [dspace-source]/dspace/
  3. 執行ant編譯
    > mvn package
  4. 移動到你的[dspace-source]/dspace/target/dspace-[version].dir目錄
    > [dspace-source]/dspace/target/dspace-[version].dir
  5. 執行ant打包
    > ant -Dconfig=[dspace]/config/dspace.cfg update
  6. 停止你的Tomcat伺服器
    > cd [tomcat]/bin/
    > ./shutdown.sh
  7. 複製新的.war檔案到Tomcat的webpapps目錄:
    > \cp -rf [dspace]/webapps/* [tomcat]/webapps/
  8. 重新啟動Tomcat伺服器
    > cd [tomcat]/bin/
    > ./startup.sh


參考資料


本來想要一篇之內寫完的,沒想到內容已經長到令人看不下去的地步,連Windows Live Writer連帶的都變得很慢,這就是警告我該換一篇寫了。繼續努力!

(more...)

布丁的自我簡介(2008年版)

布丁的自我簡介(2008年版)

pudding(500px)
姓名 陳勇汀(ㄊㄧㄥ)
暱稱 布丁 (布丁布丁吃布丁)
出生年 民國74年
e-mail puddingchen.35@gmail.com
專長 以網頁程式為主:JavaScript (jQuery)、CSSPHP,略懂Java跟JSP
對於網路伺服器管理、電腦維護也頗有心得。
興趣 找些有趣的系統功能或演算法來實作。

自我期許

在這電腦、網際網路盛行的時代中,圖資界對於資訊的典藏、組織、蒐集至今有許多發揮的空間。對我來說,比起資工資管等技術領域,圖資界對於資訊的觀點更讓我感興趣。秉持著「比起看書就能上手的技術,更要學習的具有意義與影響力的目標」的精神,今天也以感恩的心一邊學習、一邊將所學所得回饋給這個世界。

學歷:徹頭徹尾的社會科系圖資人

著作目錄

政大圖檔
  • Chih-Ming Chen and Yong-Ting Chen, "Digital Library with Reading Annotation Tool for Supporting Effective Reading Learning," the 9th IEEE International Conference on Advanced Learning Technologies (ICALT 2009).
  • Chih-Ming Chen, Mei-Ling Wang, Ming-Yueh Tsay, Dun-Yuan Zhang and Yong-Ting Chen, "Developing a Taiwan Libraries' History Digital Library with Reader Knowledge Archiving and Sharing Services Based on DSpace Platform," Under prepare for The Electronic Library.[SSCI, EI收錄]
  • 王梅玲, 蔡明月, 陳志銘, 柯雲娥, 蔡佳縈, 陳勇汀, 林怡甄, "台灣圖書館史數位圖書館建構之研究," 圖書館學與資訊科學, 34卷1期, 頁15-38, 2008.
輔大圖資

參與計畫與成果

先寫研究所再寫大學。

政大圖檔所台灣百年圖書館史暨數位圖書館先導計畫 (民國96年)

第一次參加具有數十人規模團隊的數位典藏計畫,我在陳志銘老師帶領之下從學長接手DSpace系統開發,對於初學Java&JSP的我來說修改得仍不是很成熟,但大部分功能修改已經不成問題。

台灣百年圖書館史在作為數位圖書館的功能有張敦媛學姐的標註功能(http://0rz.tw/e34Xs)跟SRU(Search and Retrieve via URL) (http://0rz.tw/5f4V2)開放查詢檢索的結果。技術服務期末報告就探討SRU對於數位典藏開放的議題

政大圖檔所:中華民國圖書館學會九十七學年度「數位典藏實務與加值服務研習班」 (民國97年)

由於台灣百年圖書館史計畫的公開,DSpace的操作遂成為本所教學內容。不僅在王梅玲老師的技術服務課堂中讓學生們操作、上傳,更在暑假期間的研習班中開班授課,我在數位典藏系統與平台設計裡面擔任DSpace的操作與設定說明,授課內容請看數位典藏系統與平台設計—以DSPACE為例 (http://0rz.tw/1e4Sd)。

政大圖檔所:教育部全國通識教育資源平台建構與永續發展計畫 (民國97年)

此為開發通識教材與教師資料的典藏計畫,陳志銘老師負責此計畫中技術部份的子計畫4,底下聘有多位助理,而身為兼任助理的我則是負責以DSpace為主的技術指導兼程式開發。(在寫這篇的時候,我也還在做這些事情)

我的Blog上發佈了數篇關於DSpace的教學與開發的功能供人參考 (http://0rz.tw/5a4Uj),請各位不吝指教。

政大圖檔所:數位圖書館暨數位學習實驗室管理員 (民國96年到97年)

陳志銘老師所領導的實驗室在今年教育部計畫3台伺服器加入之前,伺服器數量多達9台。我跟學長負責維護這些伺服器及本所的電腦,除了實驗室佈線、器材管理、IP分配、電腦安裝重灌之外,對於Windows、Linux也略有心得,熟悉操作ApacheIISApache TomcatMySQLPostgreSQL(還不敢說熟)等網頁與資料庫伺服器,安裝並修改過XOOPSMediaWikiDSpace等系統,後來更將部份伺服器規劃虛擬化運作。實驗室的伺服器就跟我的玩具一樣親密。

輔大圖資:林麗娟老師的國科會計畫 (民國92年到95年)
  • 民國92及93年,「資訊科技應用與創意教學專案 」(NSC 93-2511-S-030-001)
  • 民國93年,「資訊融入自然領域專題式學習」 (NSC 93-2520-S-030-001)
  • 民國94年,「由動機談討電腦人因網路互動學習」 (NSC 94-2520-S-030-002)
  • 民國95年,「網路學習知討論表現與不同個人特質分析」(NSC 95-2520-S-030-001)

image 大學二年級時林麗娟老師招攬我進實驗室,主要負責伺服器維護、系統架設與開發以及分析研究內容。這是我接觸網頁伺服器的開始,在此打下對於Linux、Apache、PHP等技術的基礎。在這些計畫當中,我投注心力最多的是大家e起來互動式計分討論區,除了繼承學長的系統之外,還開發了網路線上問卷功能。

輔大圖資:國科會95年大專生參與專題研究計畫「網路非同步互動引言機制之建置與分析」(民國95年)

clip_image002[1]

林麗娟老師建議我對於自己加上去的「互動引言功能」去探討其對學生非同步討論學習的影響,這是我第一次獨立進行研究。本研究使用了內容分析法、訪談法來得知此系統對於學生的影響,一邊做研究一邊跑去上研究所中邱子恆老師的質性研究課程,最後從質性與量化分析驗證互動引言機制的成效。

然而對於當時學術研究能力不足的我來說,本研究不盡如人意,但卻也成為我後來的苦膽,時時提醒我不可再犯當時的研究失誤。


在申報獎學金的時候,發現自己著作目錄不全,回頭看看自我簡介又覺得自介實在很簡略,於是又重寫了一篇,也方便以後的自介整理。在「網站典藏」(Web archive)議題逐漸抬頭的時候,我也順著這潮流,另開一篇自我介紹,舊的介紹請看這邊

就請大家多多指教囉。

(more...)

論文壓力很大嗎?快來問我論文進度到哪邊吧

布丁布丁吃布丁

論文壓力很大嗎?快來問我論文進度到哪邊吧

2008-10-09-221

研究所念到二年級,最近很流行的話題是:「你的論文寫到哪邊了?」

政大圖檔所要畢業需要有兩個條件:學分修滿、畢業論文。要寫畢業論文也沒這麼簡單,首先要通過資格考或投稿發表才能夠進行論文計劃書,計劃書要找三位評審委員(包括自己的指導老師)進行口試,通過之後才能繼續進行研究。計劃書通過在六個月之後,才能進行畢業論文口試,一樣要找三位評審委員,審查之後再進行修改、繳交,這樣才算完成畢業論文。

在兩年畢業的時程上,現在我們同學已經在準備10月底申請計劃書口試,估計大概11月到12月就能口試完畢。因此,在同學間最常聽到的就會是「你的論文進度到哪邊?」「終於要開始寫第三章了。」「找文獻好難喔,又沒有時間看。」「每次meeting時壓力都好大,老師都改好多。」

為了各位同學著想,我想如果把我的現狀列一下、讓你們比較比較,也許可以減輕你們一些壓力。


「我這學期修11學分」

在圖檔所每學期限制13學分的狀況下,我修11學分已經是跟學弟妹差不多的狀況。修的課程為:「檔案學研討」、「知識組織與資訊取用」、「研究方法」、「資料探勘」,其中前三科是必修,而大部分都是有很多報告、課業壓力跟剛入學的學弟妹相比是差不多的程度。

對於有先修的同學來說,他們大概修三到四門課。對於跟我一樣是圖資相關科系直升的同學來說,他們只要修一門課。

圖檔所修課課程規劃真是太偉大了。

「我還在做教育部計畫」

聽說之前楊老師以為我論文都已經寫完了,而王老師也以為我在拼論文。秉持著以誠待人的精神,我在暑假時我帶教育部計畫助理、整理實驗室跟所上電腦設備,直到最近還是在寫DSpace的擴充功能 (最近幾天應該會把這個功能寫上來)。

如果你想問「教育部計畫不是有專任助理嗎?」那這之間錯綜複雜的程度,我想坐下來喝咖啡喝一整天應該都講不完,而且我寧願把時間放在解決問題上。

「我在meeting時,也一直都是報告計畫進度」

跟著陳老師meeting也快要兩年了。

第一年時作頂尖大學計畫,下學期稍微有讀幾篇paper,也快樂地唸了點書。

第二年的現在,我還在教育部計畫裡面,作瑣碎事情。

是的,就跟Blog標題一樣,我正在朝著不是畢業的方向無奈地急速狂奔中。最近連聽課的時候都還在寫程式,頁首那幾張就是程式的memo。

大家都覺得自己壓力很大的情況下而不淌這種混水,那就我來淌吧。儘管不被老師們、助教們認同,不被同學、朋友們理解,這也是我在目前的現況中所能找到最好的解決方案了。

「老師,我想作研究,我非常想作研究。」

來到研究所最大的樂趣,就是感受到了研究的魅力。我開始認識到別人是如何從原有的狀態當中找出新的知識、創造各種可能性,然後讓這個世界更有趣。

作為一個程式設計師,我只是寫出別人想要的系統、程式;作為一個圖書館員,我只是處理著例行事務,或是編著編不完的書。但只有作為研究員,才能到處去尋找、開發可能性,並用自己的雙手去實現這個可能性。

我不甘心讓自己在還沒體驗到作研究、投稿發表的樂趣之前就離開這個環境。

我為在課堂或實作中發現的有趣研究議題,卻因為作不完的計畫、所務而沒有時間去做感到遺憾。

我對於這個不能正視資訊設備與系統管理的重要性、以及對資訊人才不重視的環境感到失望。

我已經聽膩了「這能提昇你電腦的功力」、「coding等級會提高」、「出去之後會比較好找工作」的這種無關痛癢的安慰詞。把學生拿去作電腦維修員、程式設計師或是系統管理者這種出去業界也會做的事情,對讓他能夠成為研究者的幫助,到底有多少?

能夠專心投入在論文上,老師也在指導你們寫論文(而不是作計畫)的同學們啊,你們不覺得很幸福嗎?


最後一個是:

「同學,作研究真的很快樂、很幸福的。」

蔡老師常說讀書很幸福,但我覺得作研究也很快樂。

當很多人因為經濟因素、家庭因素而不得不出社會討飯吃、在職場中奮鬥的時候,我們不僅可以讀書、吸收新知,而且可以只為了找尋那可能不賺錢、大家都不重視的一種發現,而投入所有時間精力去作研究、作實驗。

看著同年齡的同學已經在職場中奮鬥,自己卻能夠在課堂、報告、程式中徜徉而不事生產,我常為此感到羞愧,到現在都還沒能準備回饋父母。

但能成為研究生,能在這種不為利益、只為知識的環境中學習、作研究、寫論文,是非常幸福的!

一起快樂地作研究吧,共勉之!

(more...)

整理電源延長線:掛勾與開關加蓋

布丁布丁吃布丁

整理電源延長線:掛勾與開關加蓋

2008-09-28-211

用電源延長線來配置電源的時候,通常會遇到兩個問題:延長線容易移動無法固定、開關容易因踢到而切斷。

最近在B&Q特立屋找到了一些小配件,可以幫忙解決這兩個問題,雖然很笨的感覺,不過也寫出來給大家參考看看吧。


2008-09-28-198

電源延長線後面通常都有掛勾,掛勾的位置不盡相同,通常是用釘子來掛起來。可惜的是目前我們的環境不能用釘子釘在牆壁上,只能用黏貼的方式來固定。

想到的解決方案有:

  1. 泡綿雙面膠:穩定,但難以移動,而且對牆面損害大。
  2. 魔鬼氈:穩定,而且可以移動。仔細想想這應該是最好的解決方案。
  3. 掛勾。

方案3中,要找到能插得進這麼小的掛勾其實很難。在B&Q裡面有小橢圓鐵鉤5個一組39元,背後為泡綿雙面膠固定,承受重量為0.6KG,應該算是最好的物品。

2008-09-27-183 2008-09-28-201

來比較看看掛上去前後的差異:

2008-09-28-210 2008-09-28-208


再來是電源延長線的開關,由於時常不小心踢到、踩到、或按到,導致線路上的電器全部斷電,因此有想要把該開關封起來。

雖然也可以用強力膠、熱溶膠之類的來固定開關,但是要是之後還要用到開關,那就麻煩了。

2008-09-27-185  2008-09-28-204

剛好我們也在B&Q找到了電話配線槽末端接頭BTCE-2M,其大小剛好與電源延長線的開關差不多,一包5個為65元。

蓋起來的前後如下:

2008-09-28-207 2008-09-28-205

最後再用膠帶綁起來,就是一個很安全的蓋子囉!


不要懷疑,配置電源跟網路線路,這真的是個研究生在做的事情……

(more...)

補強Plurk的搜尋功能:用 RSS Reader

布丁布丁吃布丁

0 Comments

補強Plurk的搜尋功能:用 RSS Reader

image

Plurk的搜尋功能對於英文語系以外的語言似乎找不太到。

我之前PO了一篇「日本知名聲優歌手 榊原ゆい & 茅原実里 即將於今年12月7日(日)來台開唱!有榊原耶.....」的Plurk,用搜尋功能居然找不到。那Plurk就少了memo的功能,連自己說了什麼都不知道,不免有點缺憾。

但其實Plurk也有RSS可以使用!Plurk RSS Feeds提示了我們Plurk的RSS位置:

http://www.plurk.com/user/你的Plurk帳號.xml

試著作一個簡單的產生器看看:

您的Plurk名稱:

您的RSS位置:


接下來,就把這個RSS丟到Google Reader去看看吧!

image

試著在自己Plurk裡面搜尋「日本知名聲優」,就可以找到自己發的那一篇Plurk

image

獨立的Plurk頁面也會包含回應的內容,可見Plurk的服務相當週到。例如來看看這篇家裏的小雞Plurk

image

缺點就是沒辦法看到私密Plurk,找不到自己的秘密memo,還是有點不夠完美啊。

(more...)

DSpace教學講座(四):修改實例之修正TextEditor

布丁布丁吃布丁

DSpace教學講座(四):修改實例之修正TextEditor

image

寫程式,Debug(偵錯)是家常便飯,雖然的確很煩,但也不需要因此驚慌。

上一篇DSpace教學講座(四):修改實例中,我們修改的texteditor發生了兩個問題:只能呼叫一個FCKeditor、敘述遞交不能進到下一步。因此我把接下來偵錯的步驟一步步地在投影片上呈現。

投影片下載(Google Page Creator)

投影片下載(政治大學研究生空間)

本次投影片附加的檔案有「edit-metadata.jsp」跟「DescribeStep.java」這兩個,請按此下載。前者需要擺到jspui裡面,後者則是在dspace-api裡面。在原始碼裡面將這兩個檔案覆蓋之後,再加上之前就上傳的fckeditor,然後再重新編譯,就可以正常使用texteditor囉。

(more...)

DSpace教學講座(四):修改實例

布丁布丁吃布丁

DSpace教學講座(四):修改實例

image

為了讓大家能夠將之前所學融會貫通,本次教學則是教大家修改DSpace的兩個功能出來。一個是為Metadata表單中的Input-type增加一種所見即得編輯器:TextEditor;另一個則是透過查詢資料表「handle」來為Item物件增加另一種找尋的方法:findByHandle。

在本次講座中,應用到許多之前講述的方法。如果有遇到不清楚的部份,記得要回頭看看之前是怎麼講的喔!

投影片下載(政治大學研究生空間)

投影片下載(政治大學研究生空間)

※這份投影片有後續修正,請看下一篇Blog:DSpace教學講座(四):修改實例之修正TextEditor

投影片下載(Google Page Creator)

投影片下載(政治大學研究生空間)

附件下載


DSpace講座就這樣結束了。教完的時候,台下的人給我的眼神,依然帶有著無助。

這一系列的教學是以DSpace 1.5為對象,為了讓計畫成員都具備有使用與修改DSpace的能力,然而JAVA與JSP需要看書學、DSpace的設定則是有說明書Wiki可以看。因此我主要是將自己的經驗寫出來,而不是拿說明書一一去撰寫。

「為什麼DSpace的上傳跟編輯介面還是不一樣?」「為什麼DSpace的上傳檔案還是這麼麻煩?」這些問題,我也沒辦法,就只能動手去修改。

我還有想改的功能,但是我沒有時間可以讓我一直花在這上面,總有一種遺憾的感覺。

不管怎麼說,勉勵一起研究DSpace的人,加油吧!

(more...)