contents

  1. 1. 網站看板娘製作
    1. 1.1. 簡介
    2. 1.2. 製作開始
      1. 1.2.1. 前置作業
      2. 1.2.2. JQuery Code
      3. 1.2.3. CSS
      4. 1.2.4. Stylus
    3. 1.3. 如何使用 How to use
      1. 1.3.1. 一般網頁
      2. 1.3.2. Hexo Blog
  2. 2. 學習與撰寫過程
  3. 3. GitHub
  4. 4. Reference

網站看板娘製作

簡介

仿製偽春菜,用於網站小幫手,或者象徵物般的存在,高階可以引入對話 AI。 原版偽春菜,常見的別名又稱伺か、何か、任意、さくら。是一種電腦的桌面程式。視其功能的不同,從站在那陪使用者聊聊天解解悶,或報時對時收郵件,甚至處理電腦中大大小小的事都有可能辦到 而網站移植版有許多版本,看到大部分為php 版本、以WordPress Blog插件為大宗。 移植版常有的功能縮減為顯示公告、賣萌、統計上站人數等。跟電腦版不同較少出現會隨互動顯著成長的類型,另外在技術層面上,很多牽扯到資料庫的運用,相當複雜。

在靜態頁面上,如何簡單運用外連資料庫就是本次課題,決定開始偷偷動手腳了。

對了,Jquery 的模組化單純是老尼克推坑,接著朝向 AI 系統發展,就以目前情況來看,可能沒有時間去完成或了解。但是有一個關鍵詞 AIML 網址內附程式,可能會幫助興趣者從零開始建造,如果要有中文可能要去調用翻譯機就是了。還是要說明一下,這裡偷偷用了 google 提供的服務,所以沒有完善的資料庫語法,算是邪門歪道。

製作開始

前置作業

  • 獲取自己的 Google Spreadsheet 的 key 和 formkey。
  • 建立方式
    • 製作 Google 表單,也就是問卷。
    • 放出一個選項命名為 ‘store_data_base’ (預設,否則您將要修改 json)
    • 之後您將會得到表單對應的試算表。
    • 分別找到 key 和 formkey 還有表單欄位的 html tag id.
      • key - 在相對的試算表中,查閱當前網址
        https://docs.google.com/spreadsheet/ccc?key=0ArRwmWo93u-mdG93a2dkSWxIbHEzZjRIeDdxZXdsU1E&usp=drive_web#gid=0
        
        key=後面一串便是您需要的,您可以檢查以上的值和代碼中的預設值。
      • formkey - 在您開啟問卷的網址中
        https://docs.google.com/forms/d/1xADUIiBq1ksH7lxwSch1Nz_p2gSxdJttmv5OJOxJye0/viewform
        
        會發現 d/formkey/viewform 就在其中。
      • html tag id - 對問卷頁面查閱原始碼,找到輸入欄位類似於 entry.2030600456 的格式。
  • 本站使用的 My Google Spreadsheet 如有表單建立疑慮可參考。

  • 以下代碼可能會與 GitHub 上不同,會盡可能去兩邊更新。

JQuery Code

jquery.morris.ukagaka.resource.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
(function($){ // 封裝起來, 以免和外界js 變數衝突到
$.fn.extend({
//plugin name - animatemenu // 定義 plugin 名稱
ukagaka: function(options) {
//Settings list and the default values // 設定plugin input parameters 的預設值
var defaults = {
googleKey: '0ArRwmWo93u-mdG93a2dkSWxIbHEzZjRIeDdxZXdsU1E',
googleFormkey: '1xADUIiBq1ksH7lxwSch1Nz_p2gSxdJttmv5OJOxJye0',
googleSheet: "od6",
googleSheetField: "entry.2030600456",
talkTime: 10000
};
// 把預設值和實際輸入值比對, 如果有傳入值的則以傳入值為主
// 如此便得到輸入值 options (在此匿名函式中存在之變數)
var options = $.extend(defaults, options);
// 執行此 plugin 的實際動作, 對其作用對象的陣列迭代(iterate over), 例如說對$(".class_name") 呼叫此plugin, 則 this.each 就代表所有帶有 class_name 為 class 屬性的DOM element
return this.each(function() {
var o = options;
//Assign current element to variable, in this case is UL element
var obj = $(this); // obj 代表迭代到的單一物件
var key = o.googleKey;
var sheet = o.googleSheet;
var formkey = o.googleFormkey;
var sheetfield = o.googleSheetField;
var talking = [];
var innerSettingHTML = "";
innerSettingHTML += "<div id='ukagaka_img'></div>";
innerSettingHTML += "<div class='ukagaka_box'>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_msgbox'>汝 先看看周遭</div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_menubox' style='display:none'>使用選單功能&#65292;吾才不需要汝教。<br/><br/><span id='ukagaka_menu_btn_addstring'>$ 學習</span><span id='ukagaka_menu_btn_renewlist'>$ 日誌</span><span id='ukagaka_menu_btn_exit'>$ 結束</span></div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_stringinput' style='display:none'>請輸入讓偽春菜學的句子<br/><br/><input id='ukagaka_addstring' type='text'/><span id='ukagaka_addmenu_add'>$ 增加</span><span id='ukagaka_btn_menu'>$ 取消</span></div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_renewlist' style='display:none'>更新日誌<br/><br/>Morris 修正<br/><br/>找尋 AI 系統<br/>找尋 AI 對話<br/><br/><span id='ukagaka_btn_menu'>$ 取消</span></div>";
innerSettingHTML += "<input id='ukagaka_sheetfield' type='hidden' value='" + sheetfield + "'>";
innerSettingHTML += "</div>";
obj.html(innerSettingHTML);
var footerMenuHTML = "";
footerMenuHTML += "<div id='ukagaka_controlpanel'>";
footerMenuHTML += "<span id='ukagaka_btn_display'>Display</span> ";
footerMenuHTML += "<span id='ukagaka_btn_menu'>Menu</span>";
footerMenuHTML += "</div>";
obj.after(footerMenuHTML);
function reloadtalking(){
/* JSON / load string from database */
$.getJSON("https://spreadsheets.google.com/feeds/list/" + key + "/" + sheet + "/public/values?alt=json", function(JData){
for (var i = 0; i < JData.feed.entry.length; i++) {
talking[i] = JData.feed.entry[i].gsx$storedatabase.$t;
// console.log("talk stmt : " + talking[i]);
}
$('input#ukagaka_addstring').attr('placeholder', '目前春菜學會了' + JData.feed.entry.length + '個字彙');
});
};
$(window).load(function(){
var talk_timer = setInterval(talkingbox, o.talkTime);
function talkingbox() {
if($("#ukagaka_msgbox").css("display") != 'none')
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html(talking[Math.floor(Math.random() * talking.length)]).fadeIn(500)});
}
});
reloadtalking();
obj.draggable();
$(document).on('click', "span#ukagaka_btn_display", function(event) {
$("#ukagaka_panel").fadeToggle(1000);
});
$(document).on('click', "span#ukagaka_menu_btn_exit", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_btn_menu", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_menubox").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_menu_btn_addstring", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_stringinput").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_menu_btn_renewlist", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_renewlist").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_addmenu_add", function(event) {
var add = $("input#ukagaka_addstring").val();
var googleSheetField = $('input#ukagaka_sheetfield').val();
var sendData = {};
sendData[googleSheetField] = add;
if(!((add.length <= 1) || add.indexOf('script') > -1|| add.indexOf('body') > -1 ||
add.indexOf('style') > -1 || add.indexOf('link') > -1 || add.indexOf('iframe') > -1 || add.indexOf('head') > -1 ||
add.indexOf('nav')>-1||add.indexOf('object')>-1||add.indexOf('embed')>-1)){
$.ajax({
type: 'POST',
url: 'https://docs.google.com/forms/d/' + formkey + '/formResponse',
data: sendData,
dataType: "xml",
statusCode: {
0: function() {
$("input#ukagaka_addstring").attr("value","");
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html("偽春菜學習了 !").fadeIn(1000)});
},
200: function() {
$("input#ukagaka_addstring").attr("value","");
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html("偽春菜學習了 !").fadeIn(1000)});
}
}
});
} else {
alert("OOPS!偽春菜不接受這個字串喔!");
}
});
});
}
});
})(jQuery);

CSS

以下 CSS 為原作設定。

ukagaka.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ukagaka_controlpanel {
background:white;padding:8px;
box-shadow:#555 0px 0px 4px;
text-shadow: #555 0px 0px 1px;
margin-bottom:-3px;
border-radius:5px 5px 0 0;
position:fixed;
right:40px;
bottom:0px;
font-size:10pt;
z-index:101;
}
#ukagaka_controlpanel span, #ukagaka_panel span {
padding:5px;
cursor:pointer;
height:0px;
}
#ukagaka_panel {
position: fixed;
right: 10px;
bottom: 10px;
width: 88.2px;
height: 230.3px;
z-index:10;
}
/* ukagaka msgbox */
.ukagaka_box{
position: absolute;
bottom: 117px;
right: 97px;
font-size: 10pt;
}
.ukagaka_msg{
width:195px;
background: white;
padding:10px;
word-wrap: break-word;
word-break: normal;
color:black;
box-shadow:rgba(15,15,15,0.8) 0px 0px 8px;
}
.ukagaka_msg::after {
width:10px;
height:10px;
-moz-transform:rotate(45deg);
-webkit-transform:rotate(45deg);
-o-transform:rotate(45deg);
-ms-transform:rotate(45deg);
transform:rotate(45deg);
background:white;
content: '';
float: right;
margin-right: -14px;
margin-top:7px;
box-shadow:rgba(15,15,15,0.8) 3px -3px 8px -3px;
}
/* */
#ukagaka_img {
background: url(./img/ukagaka_img.png) no-repeat;
width: 126px;
height: 329px;
transform: scale(0.7);
-ms-transform: scale(0.7);
-webkit-transform: scale(0.7);
-o-transform: scale(0.7);
-moz-transform: scale(0.7);
position: absolute;
top: -49px;
right: -19px;
}
#ukagaka_stringinput input {
width:95%;
}

Stylus

  • 如果你在 Nodejs 下想使用,這裡提供本站使用的 ukagaka.styl。
  • 最後在 theme/xxxx/source/css/style.styl 進行匯入。
    1
    @import '_partial/ukagaka'
theme/xxxx/source/css/_partial/ukagaka.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#ukagaka_controlpanel
font-size 1.1em
padding 0 0 0.3125em 0
position fixed
right 40px
bottom 0px
background color-section
span
font-family font-custom-family
color color-blue
border-radius 10px
border-width 5px
border-style solid solid solid
&:hover
color color-theme2
transition color .5s
#ukagaka_panel
padding 0.5em 2% 1em
width 88.2px
height 230.3px
position fixed
right 40px
bottom 40px
span
padding 5px
cursor pointer
height 0px
.ukagaka_box
border-radius 10px
border-width 5px
border-style solid dashed dashed
position absolute
bottom 150px
right 120px
font-size 100%
background color-section
color gray
.ukagaka_msg
border-radius 10px
padding 0.5em 2% 1em
color color-white
width 195px
font-family font-custom-family, font-default
&::before
font-smoothing()
padding-right 0.5em
span#ukagaka_menu_btn_addstring, span#ukagaka_menu_btn_renewlist,
span#ukagaka_menu_btn_exit
border-radius 5px
border-width 1px
border-style solid solid solid
display inline
color color-blue
&:hover
color color-theme2
&::before
font-smoothing()
padding-right 0.5em
span#ukagaka_btn_menu, span#ukagaka_addmenu_add
border-radius 5px
border-width 1px
border-style solid solid solid
display inline
color color-blue
&:hover
color color-theme2
&::before
font-smoothing()
padding-right 0.5em
#ukagaka_img
background url(/img/ukagaka_img.png) no-repeat
width 150px
height 350px
transform scale(0.7)
-ms-transform scale(0.7)
-webkit-transform: scale(0.7)
-o-transform scale(0.7)
-moz-transform scale(0.7)
position absolute
top -49px
right -19px
#ukagaka_stringinput
>input
width 95%

如何使用 How to use

一般網頁

  • 記得要使用 utf-8 的網頁,否則中文將會炸掉。
  • 記的要使用 jquery-ui.js。
  • 記得要使用 jquery-x.x.x.js。
  • 最後引入咱們的 ukagaka.resource.js 和 ukagaka.css。
  • 然後與一般的 jquery 綁定相同,請參考以下代碼。
  • 如果您要客製化,請傳入 $(element).ukagaka(options);
  • options 的操作,請詳見 $(element).ukagaka({xxx:yyy, zzz:www});
main.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script src='jquery.morris.ukagaka.resource.js' type='text/javascript'></script>
<link type="text/css" rel="stylesheet" href="ukagaka.css">
<!-- ukagaka start -->
<script>
$(document).ready(function() {
$('#ukagaka_panel').ukagaka();
});
</script>
<div id='ukagaka_panel'>
</div>
<!-- ukagaka end -->
</body>
</html>

Hexo Blog

萬里花

  • 如果您希望每一頁都能見到
    • 在 footer.ejs 下插入 HTML TAG 代碼。
    • 在 after_footer.ejs 進行綁定
  • 反之,請自行摸索
theme/xxxx/layout/_partial/post/after_footer.ejs
1
2
3
4
5
6
7
<% if (config.ukagaka) { %>
<script src="<%- config.root %>js/jquery-ui.js"></script>
<script src="<%- config.root %>js/jquery.morris.ukagaka.resource.js"></script>
<script type="text/javascript">
$('#ukagaka_panel').ukagaka();
</script>
<% } %>
  • 插入位置看您的造化
theme/xxxx/layout/_partial/post/footer.ejs
1
2
3
4
5
<!-- ukagaka BEGIN -->
<div id='ukagaka_panel'>
</div>
<!-- ukagaka END -->

學習與撰寫過程

第一次寫 JQuery 和 Google Spreadsheet 相關,然後將 CSS 修改成 Stylus。

  • Stylus 是 CSS 的前置處理,有點類似 .cpp 產出 .exe 的關係。
  • 改寫時一堆問題,Stylus 默認縮排 2 個空白,編譯上一堆問題沒發現,導致浪費時間。
  • Google Spreadsheet 由於現在比較新版,每個表單的輸入欄位 id 也有所不同,所以可能會比較特別一點。
  • 什麼是靜態網頁的定義越來越模糊,javascript 帶你引入一堆外部資料庫,用低廉免錢重新審視。
  • 學習用 ajax 調用 Google Spreadsheet 資料。
  • Track code 能力訓練。

GitHub

Reference