6-315/www/static/js/awesome.js

465 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// awesome.js
// patch for lower-version IE:
if (! window.console) {
window.console = {
log: function() {},
info: function() {},
error: function () {},
warn: function () {},
debug: function () {}
};
}
// patch for string.trim():
if (! String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
}
if (! Number.prototype.toDateTime) {
var replaces = {
'yyyy': function(dt) {
return dt.getFullYear().toString();
},
'yy': function(dt) {
return (dt.getFullYear() % 100).toString();
},
'MM': function(dt) {
var m = dt.getMonth() + 1;
return m < 10 ? '0' + m : m.toString();
},
'M': function(dt) {
var m = dt.getMonth() + 1;
return m.toString();
},
'dd': function(dt) {
var d = dt.getDate();
return d < 10 ? '0' + d : d.toString();
},
'd': function(dt) {
var d = dt.getDate();
return d.toString();
},
'hh': function(dt) {
var h = dt.getHours();
return h < 10 ? '0' + h : h.toString();
},
'h': function(dt) {
var h = dt.getHours();
return h.toString();
},
'mm': function(dt) {
var m = dt.getMinutes();
return m < 10 ? '0' + m : m.toString();
},
'm': function(dt) {
var m = dt.getMinutes();
return m.toString();
},
'ss': function(dt) {
var s = dt.getSeconds();
return s < 10 ? '0' + s : s.toString();
},
's': function(dt) {
var s = dt.getSeconds();
return s.toString();
},
'a': function(dt) {
var h = dt.getHours();
return h < 12 ? 'AM' : 'PM';
}
};
var token = /([a-zA-Z]+)/;
Number.prototype.toDateTime = function(format) {
var fmt = format || 'yyyy-MM-dd hh:mm:ss'
var dt = new Date(this * 1000);
var arr = fmt.split(token);
for (var i=0; i<arr.length; i++) {
var s = arr[i];
if (s && s in replaces) {
arr[i] = replaces[s](dt);
}
}
return arr.join('');
};
}
function encodeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
// parse query string as object:
function parseQueryString() {
var
// location.search 获取从问号开始的URL(即查询部分)——https://www.jianshu.com/p/c8544728a200
q = location.search,
r = {},
i, pos, s, qs;
// charAt()方法返回指定位置的字符
if (q && q.charAt(0)==='?') {
qs = q.substring(1).split('&');
for (i=0; i<qs.length; i++) {
s = qs[i];
pos = s.indexOf('=');
if (pos <= 0) {
continue;
}
r[s.substring(0, pos)] = decodeURIComponent(s.substring(pos+1)).replace(/\+/g, ' ');
}
}
return r;
}
function gotoPage(i) {
var r = parseQueryString();
r.page = i;
// jQuery.param()序列化一个key/value对象, 返回如width=1680&height=1050
location.assign('?' + $.param(r));
}
function refresh() {
var
t = new Date().getTime(),
url = location.pathname;
if (location.search) {
url = url + location.search + '&t=' + t;
}
else {
url = url + '?t=' + t;
}
location.assign(url);
}
// 根据发帖时间和当前时间决定显示的时间格式
function toSmartDate(timestamp) {
if (typeof(timestamp)==='string') {
timestamp = parseInt(timestamp);
}
if (isNaN(timestamp)) {
return '';
}
var
today = new Date(g_time),
now = today.getTime(),
s = '1分钟前',
t = now - timestamp;
if (t > 604800000) {
// 1 week ago:
var that = new Date(timestamp);
var
y = that.getFullYear(),
m = that.getMonth() + 1,
d = that.getDate(),
hh = that.getHours(),
mm = that.getMinutes();
s = y===today.getFullYear() ? '' : y + '年';
s = s + m + '月' + d + '日' + hh + ':' + (mm < 10 ? '0' : '') + mm;
}
else if (t >= 86400000) {
// 1-6 days ago:
s = Math.floor(t / 86400000) + '天前';
}
else if (t >= 3600000) {
// 1-23 hours ago:
s = Math.floor(t / 3600000) + '小时前';
}
else if (t >= 60000) {
s = Math.floor(t / 60000) + '分钟前';
}
return s;
}
// $(function() {}); 是$(document).ready(function(){ })的简写
// 里面的代码是在页面元素都加载完才执行的
$(function() {
$('.x-smartdate').each(function() {
// $(this) 是一个jQuery对象, text()设置元素的文本内容
// attr() 函数用于设置或返回当前jQuery对象所匹配的元素节点的属性值
$(this).removeClass('x-smartdate').text(toSmartDate($(this).attr('date')));
});
});
// JS Template:
function Template(tpl) {
var
fn,
match,
code = ['var r=[];\nvar _html = function (str) { return str.replace(/&/g, \'&amp;\').replace(/"/g, \'&quot;\').replace(/\'/g, \'&#39;\').replace(/</g, \'&lt;\').replace(/>/g, \'&gt;\'); };'],
re = /\{\s*([a-zA-Z\.\_0-9()]+)(\s*\|\s*safe)?\s*\}/m,
addLine = function (text) {
code.push('r.push(\'' + text.replace(/\'/g, '\\\'').replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '\');');
};
while (match = re.exec(tpl)) {
if (match.index > 0) {
addLine(tpl.slice(0, match.index));
}
if (match[2]) {
code.push('r.push(String(this.' + match[1] + '));');
}
else {
code.push('r.push(_html(String(this.' + match[1] + ')));');
}
tpl = tpl.substring(match.index + match[0].length);
}
addLine(tpl);
code.push('return r.join(\'\');');
fn = new Function(code.join('\n'));
this.render = function (model) {
return fn.apply(model);
};
}
// extends jQuery.form:
$(function () {
console.log('Extends $form...');
$.fn.extend({
showFormError: function (err) {
return this.each(function () {
var
$form = $(this),
$alert = $form && $form.find('.uk-alert-danger'),
fieldName = err && err.data;
if (! $form.is('form')) {
console.error('Cannot call showFormError() on non-form object.');
return;
}
$form.find('input').removeClass('uk-form-danger');
$form.find('select').removeClass('uk-form-danger');
$form.find('textarea').removeClass('uk-form-danger');
if ($alert.length === 0) {
console.warn('Cannot find .uk-alert-danger element.');
return;
}
if (err) {
$alert.text(err.message ? err.message : (err.error ? err.error : err)).removeClass('uk-hidden').show();
if (($alert.offset().top - 60) < $(window).scrollTop()) {
$('html,body').animate({ scrollTop: $alert.offset().top - 60 });
}
if (fieldName) {
$form.find('[name=' + fieldName + ']').addClass('uk-form-danger');
}
}
else {
$alert.addClass('uk-hidden').hide();
$form.find('.uk-form-danger').removeClass('uk-form-danger');
}
});
},
showFormLoading: function (isLoading) {
return this.each(function () {
var
$form = $(this),
$submit = $form && $form.find('button[type=submit]'),
$buttons = $form && $form.find('button');
$i = $submit && $submit.find('i'),
iconClass = $i && $i.attr('class');
if (! $form.is('form')) {
console.error('Cannot call showFormLoading() on non-form object.');
return;
}
if (!iconClass || iconClass.indexOf('uk-icon') < 0) {
console.warn('Icon <i class="uk-icon-*>" not found.');
return;
}
if (isLoading) {
$buttons.attr('disabled', 'disabled');
$i && $i.addClass('uk-icon-spinner').addClass('uk-icon-spin');
}
else {
$buttons.removeAttr('disabled');
$i && $i.removeClass('uk-icon-spinner').removeClass('uk-icon-spin');
}
});
},
postJSON: function (url, data, callback) {
if (arguments.length===2) {
callback = data;
data = {};
}
return this.each(function () {
var $form = $(this);
$form.showFormError();
$form.showFormLoading(true);
_httpJSON('POST', url, data, function (err, r) {
if (err) {
$form.showFormError(err);
$form.showFormLoading(false);
}
callback && callback(err, r);
});
});
}
});
});
// ajax submit form:
function _httpJSON(method, url, data, callback) {
var opt = {
type: method,
dataType: 'json'
};
if (method==='GET') {
opt.url = url + '?' + data;
}
if (method==='POST') {
opt.url = url;
opt.data = JSON.stringify(data || {});
opt.contentType = 'application/json';
}
$.ajax(opt).done(function (r) {
if (r && r.error) {
return callback(r);
}
return callback(null, r);
}).fail(function (jqXHR, textStatus) {
return callback({'error': 'http_bad_response', 'data': '' + jqXHR.status, 'message': '网络好像出问题了 (HTTP ' + jqXHR.status + ')'});
});
}
function getJSON(url, data, callback) {
if (arguments.length===2) {
callback = data;
data = {};
}
if (typeof (data)==='object') {
var arr = [];
$.each(data, function (k, v) {
arr.push(k + '=' + encodeURIComponent(v));
});
data = arr.join('&');
}
_httpJSON('GET', url, data, callback);
}
function postJSON(url, data, callback) {
if (arguments.length===2) {
callback = data;
data = {};
}
_httpJSON('POST', url, data, callback);
}
// extends Vue:
if (typeof(Vue)!=='undefined') {
Vue.filter('datetime', function (value) {
var d = value;
if (typeof(value)==='number') {
d = new Date(value);
}
return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' ' + d.getHours() + ':' + d.getMinutes();
});
Vue.component('pagination', {
template: '<ul class="uk-pagination">' +
'<li v-if="! page.has_previous" class="uk-disabled"><span uk-pagination-previous></span></li>' +
'<li v-if="page.has_previous"><a v-attr="onclick:\'gotoPage(\' + (page.page_index-1) + \')\'" href="#0"><span uk-pagination-previous></span></a></li>' +
'<li class="uk-active"><span v-text="page.page_index"></span></li>' +
'<li v-if="! page.has_next" class="uk-disabled"><span uk-pagination-next></span></li>' +
'<li v-if="page.has_next"><a v-attr="onclick:\'gotoPage(\' + (page.page_index+1) + \')\'" href="#0"><span uk-pagination-next></span></a></li>' +
'</ul>'
});
}
function redirect(url) {
var
hash_pos = url.indexOf('#'),
query_pos = url.indexOf('?'),
hash = '';
if (hash_pos >=0 ) {
hash = url.substring(hash_pos);
url = url.substring(0, hash_pos);
}
url = url + (query_pos >= 0 ? '&' : '?') + 't=' + new Date().getTime() + hash;
console.log('redirect to: ' + url);
location.assign(url);
}
// init:
function _bindSubmit($form) {
$form.submit(function (event) {
event.preventDefault();
showFormError($form, null);
var
fn_error = $form.attr('fn-error'),
fn_success = $form.attr('fn-success'),
fn_data = $form.attr('fn-data'),
data = fn_data ? window[fn_data]($form) : $form.serialize();
var
$submit = $form.find('button[type=submit]'),
$i = $submit.find('i'),
iconClass = $i.attr('class');
if (!iconClass || iconClass.indexOf('uk-icon') < 0) {
$i = undefined;
}
$submit.attr('disabled', 'disabled');
$i && $i.addClass('uk-icon-spinner').addClass('uk-icon-spin');
postJSON($form.attr('action-url'), data, function (err, result) {
$i && $i.removeClass('uk-icon-spinner').removeClass('uk-icon-spin');
if (err) {
console.log('postJSON failed: ' + JSON.stringify(err));
$submit.removeAttr('disabled');
fn_error ? fn_error() : showFormError($form, err);
}
else {
var r = fn_success ? window[fn_success](result) : false;
if (r===false) {
$submit.removeAttr('disabled');
}
}
});
});
$form.find('button[type=submit]').removeAttr('disabled');
}
$(function () {
$('form').each(function () {
var $form = $(this);
if ($form.attr('action-url')) {
_bindSubmit($form);
}
});
});
$(function() {
if (location.pathname === '/' || location.pathname.indexOf('/blog')===0) {
$('li[data-url=blogs]').addClass('uk-active');
}
});
function _display_error($obj, err) {
if ($obj.is(':visible')) {
$obj.hide();
}
var msg = err.message || String(err);
var L = ['<div class="uk-alert uk-alert-danger">'];
L.push('<p>Error: ');
L.push(msg);
L.push('</p><p>Code: ');
L.push(err.error || '500');
L.push('</p></div>');
$obj.html(L.join('')).slideDown();
}
function error(err) {
_display_error($('#error'), err);
}
function fatal(err) {
_display_error($('#loading'), err);
}