初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+171
View File
@@ -0,0 +1,171 @@
var CMS = {
events: {
//请求成功的回调
onAjaxSuccess: function (ret, onAjaxSuccess) {
var data = typeof ret.data !== 'undefined' ? ret.data : null;
var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg : '操作成功';
if (typeof onAjaxSuccess === 'function') {
var result = onAjaxSuccess.call(this, data, ret);
if (result === false)
return;
}
layer.msg(msg, {icon: 1});
},
//请求错误的回调
onAjaxError: function (ret, onAjaxError) {
var data = typeof ret.data !== 'undefined' ? ret.data : null;
var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg : '操作失败';
if (typeof onAjaxError === 'function') {
var result = onAjaxError.call(this, data, ret);
if (result === false) {
return;
}
}
layer.msg(msg, {icon: 2});
},
//服务器响应数据后
onAjaxResponse: function (response) {
try {
var ret = typeof response === 'object' ? response : JSON.parse(response);
if (!ret.hasOwnProperty('code')) {
$.extend(ret, {code: -2, msg: response, data: null});
}
} catch (e) {
var ret = {code: -1, msg: e.message, data: null};
}
return ret;
}
},
api: {
//获取修复后可访问的cdn链接
cdnurl: function (url) {
return /^(?:[a-z]+:)?\/\//i.test(url) ? url : Config.upload.cdnurl + url;
},
//发送Ajax请求
ajax: function (options, success, error) {
options = typeof options === 'string' ? {url: options} : options;
var st, index = 0;
st = setTimeout(function () {
index = layer.load();
}, 150);
options = $.extend({
type: "POST",
dataType: "json",
xhrFields: {
withCredentials: true
},
success: function (ret) {
clearTimeout(st);
index && layer.close(index);
ret = CMS.events.onAjaxResponse(ret);
if (ret.code === 1) {
CMS.events.onAjaxSuccess(ret, success);
} else {
CMS.events.onAjaxError(ret, error);
}
},
error: function (xhr) {
clearTimeout(st);
index && layer.close(index);
var ret = {code: xhr.status, msg: xhr.statusText, data: null};
CMS.events.onAjaxError(ret, error);
}
}, options);
return $.ajax(options);
},
//提示并跳转
msg: function (message, url) {
var callback = typeof url === 'function' ? url : function () {
if (typeof url !== 'undefined' && url) {
location.href = url;
}
};
layer.msg(message, {
icon: 1,
time: 2000
}, callback);
},
//表单提交事件
form: function (elem, success, error, submit) {
var delegation = typeof elem === 'object' && typeof elem.prevObject !== 'undefined' ? elem.prevObject : document;
$(delegation).on("submit", elem, function (e) {
var form = $(e.target);
if (typeof submit === 'function') {
if (false === submit.call(form, success, error)) {
return false;
}
}
$("[type=submit]", form).prop("disabled", true);
CMS.api.ajax({
url: form.attr("action"),
data: form.serialize(),
complete: function (xhr) {
var token = xhr.getResponseHeader('__token__');
if (token) {
$("input[name='__token__']").val(token);
}
$("[type=submit]", form).prop("disabled", false);
}
}, function (data, ret) {
//刷新客户端token
if (data && typeof data.token !== 'undefined') {
$("input[name='__token__']").val(data.token);
}
//自动保存草稿设置
var autosaveKey = $("textarea[data-autosave-key]", form).data("autosave-key");
if (autosaveKey && localStorage) {
localStorage.removeItem("autosave-" + autosaveKey);
$(".md-autosave", form).addClass("hidden");
}
if (typeof success === 'function') {
if (false === success.call(form, data, ret)) {
return false;
}
}
}, function (data, ret) {
//刷新客户端token
if (data && typeof data.token !== 'undefined') {
$("input[name='__token__']").val(data.token);
}
if (typeof error === 'function') {
if (false === error.call(form, data, ret)) {
return false;
}
}
});
return false;
});
},
//localStorage存储
storage: function (key, value) {
key = key.split('.');
var _key = key[0];
var o = JSON.parse(localStorage.getItem(_key));
if (typeof value === 'undefined') {
if (o == null)
return null;
if (key.length === 1) {
return o;
}
_key = key[1];
return typeof o[_key] !== 'undefined' ? o[_key] : null;
} else {
if (key.length === 1) {
o = value;
} else {
if (o && typeof o === 'object') {
o[key[1]] = value;
} else {
o = {};
o[key[1]] = value;
}
}
localStorage.setItem(_key, JSON.stringify(o));
}
}
}
}
+462
View File
@@ -0,0 +1,462 @@
$(function () {
window.isMobile = !!("ontouchstart" in window);
function AddFavorite(sURL, sTitle) {
if (/firefox/i.test(navigator.userAgent)) {
return false;
} else if (window.external && window.external.addFavorite) {
window.external.addFavorite(sURL, sTitle);
return true;
} else if (window.sidebar && window.sidebar.addPanel) {
window.sidebar.addPanel(sTitle, sURL, "");
return true;
} else {
var touch = (navigator.userAgent.toLowerCase().indexOf('mac') != -1 ? 'Command' : 'CTRL');
layer.msg('请使用 ' + touch + ' + D 添加到收藏夹.');
return false;
}
}
var len = function (str) {
if (!str)
return 0;
var length = 0;
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) >= 0x4e00 && str.charCodeAt(i) <= 0x9fa5) {
length += 2;
} else {
length++;
}
}
return length;
};
//new LazyLoad({elements_selector: ".lazy"});
layer.config({focusBtn: false});
//栏目高亮
var nav = $("header.header .navbar-nav");
if ($("li.active", nav).length === 0) {
var current = nav.data("current");
var currentNav = $("a[href='" + location.href + "']", nav)[0] || $("a[href='" + location.pathname + "']", nav)[0] || $("li[value='" + current + "'] > a", nav)[0];
currentNav && $(currentNav, nav).parents("li").addClass("active");
}
//移动端菜单点击
$(document).on("click", ".navbar-collapse.collapse.in .navbar-nav .dropdown-submenu > a", function () {
$(this).parents("li.dropdown").addClass("open");
return false;
});
//移动浏览器左右滑动
$(document).on('touchstart', '.carousel', function (event) {
const xClick = event.originalEvent.touches[0].pageX;
$(this).one('touchmove', function (event) {
const xMove = event.originalEvent.touches[0].pageX;
const sensitivityInPx = 5;
if (Math.floor(xClick - xMove) > sensitivityInPx) {
$(this).carousel('next');
} else if (Math.floor(xClick - xMove) < -sensitivityInPx) {
$(this).carousel('prev');
}
});
$(this).on('touchend', function () {
$(this).off('touchmove');
});
});
// 点击收藏
$(".addbookbark").attr("rel", "sidebar").click(function () {
//使用数据库收藏
CMS.api.ajax({
url: $(this).data("action"),
data: {type: $(this).data("type"), aid: $(this).data("aid")}
});
//使用浏览器收藏
//return !AddFavorite(window.location.href, $(this).attr("title"));
});
// 点赞
$(document).on("click", ".btn-like", function () {
var that = this;
var id = $(this).data("id");
var type = $(this).data("type");
if (CMS.api.storage(type + "vote." + id)) {
layer.msg("你已经点过赞了");
return false;
}
CMS.api.ajax({
data: $(this).data()
}, function (data, ret) {
$("span", that).text(type === 'like' ? ret.data.likes : ret.data.dislikes);
CMS.api.storage(type + "vote." + id, true);
return false;
}, function () {
return false;
});
});
// 加载更多
$(document).on("click", ".btn-loadmore", function () {
var that = this;
var page = parseInt($(this).data("page"));
var container = $(this).data("container");
container = container ? $(container) : $(".article-list,.product-list");
var loadmoreText = $(this).text();
$(that).text("正在加载").prop("disabled", true);
CMS.api.ajax({
url: $(that).attr("href"),
}, function (data, ret) {
if (data) {
$(data).appendTo(container);
page++;
$(that).attr("href", $(that).data("url").replace("__page__", page)).data("page", page);
$(that).text(loadmoreText).prop("disabled", false);
} else {
$(that).replaceWith('<div class="loadmore loadmore-line loadmore-nodata"><span class="loadmore-tips">暂无更多数据</span></div>');
}
return false;
}, function (data) {
$(that).text(loadmoreText).prop("disabled", false);
});
return false;
});
//滚动加载更多
$(window).scroll(function () {
var loadmore = $(".btn-loadmore");
if (loadmore.length > 0 && !loadmore.prop("disabled") && (loadmore.data("autoload") === undefined || loadmore.data("autoload"))) {
if ($(window).scrollTop() - loadmore.height() > loadmore.offset().top - $(window).height()) {
loadmore.trigger("click");
}
}
});
setTimeout(function () {
if ($(window).scrollTop() > 0) {
$(window).trigger("scroll");
}
}, 500);
//评论列表
if ($("#comment-container").length > 0) {
var ci, si;
$("#commentlist dl dd div,#commentlist dl dd dl dd").on({
mouseenter: function () {
clearTimeout(ci);
var _this = this;
ci = setTimeout(function () {
$(_this).find("small:first").find("a").stop(true, true).fadeIn();
}, 100);
},
mouseleave: function () {
clearTimeout(ci);
$(this).find("small:first").find("a").stop(true, true).fadeOut();
}
});
$(".reply").on("click", function () {
$("#pid").val($(this).data("id"));
$(this).parent().parent().append($("div#postcomment").detach());
$("#postcomment h3 a").show();
$("#commentcontent").focus().val($(this).attr("title"));
});
$("#postcomment h3 a").bind("click", function () {
$("#comment-container").append($("div#postcomment").detach());
$(this).hide();
});
$(".expandall a").on("click", function () {
$(this).parent().parent().find("dl.hide").fadeIn();
$(this).fadeOut();
});
$(document).on("click", "#submit", function () {
var btn = $(this);
var tips = $("#actiontips");
tips.removeClass();
var content = $("#commentcontent").val();
if (len(content) < 3) {
tips.addClass("text-danger").html("评论内容长度不正确!最少3个字符").fadeIn().change();
return false;
}
if (btn.prop("disabled")) {
return false;
}
var form = $("#postform");
btn.attr("disabled", "disabled");
tips.html('正在提交...');
$.ajax({
url: form.prop("action"),
type: 'POST',
data: form.serialize(),
dataType: 'json',
success: function (json) {
btn.removeAttr("disabled");
if (json.code == 1) {
$("#pid").val(0);
tips.addClass("text-success").html(json.msg || "评论成功!").fadeIn(300).change();
$("#commentcontent").val('');
$("#commentcount").text(parseInt($("#commentcount").text()) + 1);
setTimeout(function () {
location.reload();
}, 1500);
} else {
tips.addClass("text-danger").html(json.msg).fadeIn();
}
if (json.data && json.data.token) {
$("#postform input[name='__token__']").val(json.data.token);
}
},
error: function () {
btn.removeAttr("disabled");
tips.addClass("text-danger").html("评论失败!请刷新页面重试!").fadeIn();
}
});
return false;
});
$("#commentcontent").on("keydown", function (e) {
if ((e.metaKey || e.ctrlKey) && (e.keyCode == 13 || e.keyCode == 10)) {
$("#submit").trigger('click');
return false;
}
});
$("#actiontips").on("change", function () {
clearTimeout(si);
si = setTimeout(function () {
$("#actiontips").fadeOut();
}, 8000);
});
$(document).on("keyup change", "#commentcontent", function (e) {
if (e.metaKey || e.ctrlKey || [13, 10, 18, 91].indexOf(e.keyCode) > -1) {
return false;
}
var max = 1000;
var c = $(this).val();
var length = len(c);
var t = $("#actiontips");
if (max >= length) {
t.removeClass().show().addClass("loading").html("你还可以输入 <font color=green>" + (Math.floor((max - length) / 2)) + "</font> 字");
$("#submit").removeAttr("disabled");
} else {
t.removeClass().show().addClass("loading").html("你已经超出 <font color=red>" + (Math.ceil((length - max) / 2)) + "</font> 字");
$("#submit").attr("disabled", "disabled");
}
});
}
// 余额支付提示
$(document).on('click', '.btn-balance', function (e) {
var that = this;
layer.confirm("确认支付¥" + $(this).data("price") + "元用于购买?", function () {
CMS.api.ajax({
url: $(that).attr("href")
}, function (data, ret) {
CMS.api.msg(ret.msg, ret.url);
}, function (data, ret) {
});
});
return false;
});
// 回到顶部
$('#back-to-top').on('click', function (e) {
e.preventDefault();
$('html,body').animate({
scrollTop: 0
}, 700);
});
//如果是PC则移除navbar的dropdown点击事件
if (!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobi/i.test(navigator.userAgent)) {
$("#navbar-collapse [data-toggle='dropdown']").removeAttr("data-toggle");
} else {
$(".navbar-nav ul li:not(.dropdown-submenu):not(.dropdown) a").removeAttr("data-toggle");
}
if (!isMobile) {
var search = $("#searchinput");
var form = search.closest("form");
search.autoComplete({
minChars: 1,
cache: false,
menuClass: 'autocomplete-searchmenu',
header: '',
footer: '',
source: function (term, response) {
try {
xhr.abort();
} catch (e) {
}
xhr = $.getJSON(search.data("suggestion-url"), {q: term}, function (data) {
response(data);
});
},
onSelect: function (e, term, item) {
if (typeof callback === 'function') {
callback.call(elem, term, item);
} else {
form.trigger("submit");
}
}
});
}
// 手机端左右滑动切换菜单栏
if (isMobile && 'ontouchstart' in document.documentElement) {
var startX, startY, moveEndX, moveEndY, relativeX, relativeY, element;
element = $('#navbar-collapse');
$("body").on("touchstart", function (e) {
startX = e.originalEvent.changedTouches[0].pageX;
startY = e.originalEvent.changedTouches[0].pageY;
});
$("body").on("touchend", function (e) {
moveEndX = e.originalEvent.changedTouches[0].pageX;
moveEndY = e.originalEvent.changedTouches[0].pageY;
relativeX = moveEndX - startX;
relativeY = moveEndY - startY;
//右滑
if (relativeX > 45) {
if ((Math.abs(relativeX) - Math.abs(relativeY)) > 50 && !element.hasClass("active") && startX < ($(window).width() / 4)) {
$(".sidebar-toggle").trigger("click");
}
}
//左滑
else if (relativeX < -45) {
if ((Math.abs(relativeX) - Math.abs(relativeY)) > 50 && element.hasClass("active")) {
$(".sidebar-toggle").trigger("click");
}
}
});
}
// 打赏
$(".btn-donate").popover({
trigger: 'hover',
placement: 'top',
html: true,
content: function () {
return "<img src='" + $(this).data("image") + "' width='250' height='250'/>";
}
});
$(document).on("click", ".btn-paynow", function () {
var paytype = $(this).data("paytype");
var price = $(this).data("price");
var nameArr = {wechat: "微信", alipay: "支付宝", balance: "余额"};
var that = this;
var tips = function () {
layer.confirm("请根据支付状态选择下面的操作按钮", {title: "温馨提示", icon: 0, btn: ["支付成功", "支付失败"]}, function () {
location.reload();
});
};
if (paytype) {
layer.confirm("确认使用" + (typeof nameArr[paytype] !== 'undefined' ? nameArr[paytype] : "未知") + "进行支付?<br>支付金额:¥" + price + "元", {title: "温馨提示", icon: 3, focusBtn: false, btn: ["立即支付", "取消支付"]}, function (index, layero) {
$(".layui-layer-btn0", layero).attr("href", $(that).attr("href")).attr("target", "_blank");
tips();
});
return false;
} else {
tips();
}
});
//点击切换
$(document).on("click", ".sidebar-toggle", function () {
var collapse = $("#navbar-collapse");
if (collapse.hasClass("active")) {
$(".navbar-collapse-bg").remove();
} else {
$("<div />").addClass("navbar-collapse-bg").insertAfter(collapse).on("click", function () {
$(".sidebar-toggle").trigger("click");
});
}
collapse.toggleClass("active");
$(this).toggleClass("active");
});
//内容中的图片点击事件
$(document).on("click", ".article-text img", function () {
if ($(this).closest("a").length > 0) {
return;
}
var that = this;
var data = [];
var index = 0;
$(".article-text img").each(function (i, j) {
if (that == this) {
index = i;
}
data.push({
"src": $(this).attr("src") //原图地址
});
});
layer.photos({
photos: {
"start": index, "data": data
},
// scrollbar: true,
// full: true,
// closeBtn: 1
});
return false;
});
//分享参数配置
var shareConfig = {
title: $("meta[property='og:title']").attr("content") || document.title,
description: $("meta[property='og:description']").attr("content") || $("meta[name='description']").attr("content") || "",
url: $("meta[property='og:url']").attr("content") || location.href,
image: $("meta[property='og:image']").attr("content") || ""
};
//微信公众号内分享
if (typeof wx != 'undefined') {
shareConfig.url = location.href;
CMS.api.ajax({
url: "/addons/cms/ajax/share",
data: {url: shareConfig.url},
loading: false
}, function (data, ret) {
try {
wx.config({
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'checkJsApi',
'updateAppMessageShareData',
'updateTimelineShareData',
]
});
var shareData = {
title: shareConfig.title,
desc: shareConfig.description,
link: shareConfig.url,
imgUrl: shareConfig.image,
success: function () {
layer.closeAll();
},
cancel: function () {
layer.closeAll();
}
};
wx.ready(function () {
wx.updateAppMessageShareData(shareData);
wx.updateTimelineShareData(shareData);
});
} catch (e) {
console.log(e);
}
return false;
}, function () {
return false;
}
);
$(".social-share").on("click", ".icon-wechat", function () {
layer.msg("请点击右上角的●●●进行分享");
return false;
}).find(".wechat-qrcode").remove();
}
});
@@ -0,0 +1,215 @@
/*
jQuery autoComplete v1.0.7
Copyright (c) 2014 Simon Steinberger / Pixabay
GitHub: https://github.com/Pixabay/jQuery-autoComplete
License: http://www.opensource.org/licenses/mit-license.php
*/
(function ($) {
$.fn.autoComplete = function (options) {
var o = $.extend({}, $.fn.autoComplete.defaults, options);
// public methods
if (typeof options == 'string') {
this.each(function () {
var that = $(this);
if (options == 'destroy') {
$(window).off('resize.autocomplete', that.updateSC);
that.off('blur.autocomplete focus.autocomplete keydown.autocomplete keyup.autocomplete');
if (that.data('autocomplete'))
that.attr('autocomplete', that.data('autocomplete'));
else
that.removeAttr('autocomplete');
$(that.data('sc')).remove();
that.removeData('sc').removeData('autocomplete');
}
});
return this;
}
return this.each(function () {
var that = $(this);
// sc = 'suggestions container'
that.sc = $('<div class="autocomplete-suggestions ' + o.menuClass + '"></div>');
that.data('sc', that.sc).data('autocomplete', that.attr('autocomplete'));
that.attr('autocomplete', 'off');
that.cache = {};
that.last_val = '';
that.updateSC = function (resize, next) {
that.sc.css({
top: that.offset().top + that.outerHeight() - (that.sc.css("position") == "fixed" ? $(window).scrollTop() : 0),
left: that.offset().left,
width: that.outerWidth()
});
if (!resize) {
that.sc.show();
if (!that.sc.maxHeight) that.sc.maxHeight = parseInt(that.sc.css('max-height'));
if (!that.sc.suggestionHeight) that.sc.suggestionHeight = $('.autocomplete-suggestion', that.sc).first().outerHeight();
if (that.sc.suggestionHeight)
if (!next) that.sc.scrollTop(0);
else {
var scrTop = that.sc.scrollTop(), selTop = next.offset().top - that.sc.offset().top;
if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0)
that.sc.scrollTop(selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight);
else if (selTop < 0)
that.sc.scrollTop(selTop + scrTop);
}
}
}
$(window).on('resize.autocomplete', that.updateSC);
that.sc.appendTo('body');
that.on('click', function () {
if ($(this).val().length > 0 && that.sc.is(":hidden")) {
setTimeout(function () {
that.sc.show();
}, 100);
}
});
that.sc.on('mouseleave', '.autocomplete-suggestion', function () {
$('.autocomplete-suggestion.selected').removeClass('selected');
});
that.sc.on('mouseenter', '.autocomplete-suggestion', function () {
$('.autocomplete-suggestion.selected').removeClass('selected');
$(this).addClass('selected');
});
that.sc.on('mousedown click', '.autocomplete-suggestion', function (e) {
var item = $(this), v = item.data('val');
if (v || item.hasClass('autocomplete-suggestion')) { // else outside click
that.val(v);
o.onSelect(e, v, item);
that.sc.hide();
}
return false;
});
that.on('blur.autocomplete', function () {
try {
over_sb = $('.autocomplete-suggestions:hover').length;
} catch (e) {
over_sb = 0;
} // IE7 fix :hover
if (!over_sb) {
that.last_val = that.val();
that.sc.hide();
setTimeout(function () {
that.sc.hide();
}, 350); // hide suggestions on fast input
} else if (!that.is(':focus')) setTimeout(function () {
that.focus();
}, 20);
});
if (!o.minChars) that.on('focus.autocomplete', function () {
that.last_val = '\n';
that.trigger('keyup.autocomplete');
});
function suggest(data) {
var val = that.val();
that.cache[val] = data;
if (data.length && val.length >= o.minChars) {
var s = '';
if (data.length > 0) {
s += typeof o.header === 'function' ? o.header.call(data, o, that) : o.header;
for (var i = 0; i < data.length; i++) s += o.renderItem(data[i], val);
s += typeof o.footer === 'function' ? o.footer.call(data, o, that) : o.footer;
}
that.sc.html(s);
that.updateSC(0);
} else
that.sc.hide();
}
that.on('keydown.autocomplete', function (e) {
// down (40), up (38)
if ((e.which == 40 || e.which == 38) && that.sc.html()) {
var next, sel = $('.autocomplete-suggestion.selected', that.sc);
if (!sel.length) {
next = (e.which == 40) ? $('.autocomplete-suggestion', that.sc).first() : $('.autocomplete-suggestion', that.sc).last();
that.val(next.addClass('selected').data('val'));
} else {
next = (e.which == 40) ? sel.next('.autocomplete-suggestion') : sel.prev('.autocomplete-suggestion');
if (next.length) {
sel.removeClass('selected');
that.val(next.addClass('selected').data('val'));
} else {
sel.removeClass('selected');
that.val(that.last_val);
next = 0;
}
}
that.updateSC(0, next);
return false;
}
// esc
else if (e.which == 27) that.val(that.last_val).sc.hide();
// enter or tab
else if (e.which == 13 || e.which == 9) {
var sel = $('.autocomplete-suggestion.selected', that.sc);
if (sel.length && that.sc.is(':visible')) {
o.onSelect(e, sel.data('val'), sel);
setTimeout(function () {
that.sc.hide();
}, 20);
}
}
});
that.on('keyup.autocomplete', function (e) {
if (!~$.inArray(e.which, [13, 27, 35, 36, 37, 38, 39, 40])) {
var val = that.val();
if (val.length >= o.minChars) {
if (val != that.last_val) {
that.last_val = val;
clearTimeout(that.timer);
if (o.cache) {
if (val in that.cache) {
suggest(that.cache[val]);
return;
}
// no requests if previous suggestions were empty
for (var i = 1; i < val.length - o.minChars; i++) {
var part = val.slice(0, val.length - i);
if (part in that.cache && !that.cache[part].length) {
suggest([]);
return;
}
}
}
that.timer = setTimeout(function () {
o.source(val, suggest)
}, o.delay);
}
} else {
that.last_val = val;
that.sc.hide();
}
}
});
});
}
$.fn.autoComplete.defaults = {
source: 0,
minChars: 3,
delay: 150,
cache: 1,
menuClass: '',
header: '',
footer: '',
renderItem: function (item, search) {
// escape special characters
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
},
onSelect: function (e, term, item) {
}
};
}(jQuery));
File diff suppressed because one or more lines are too long
@@ -0,0 +1,429 @@
/*
jQuery Tags Input Plugin 1.3.3
Copyright (c) 2011 XOXCO, Inc
Documentation for this plugin lives here:
http://xoxco.com/clickable/jquery-tags-input
Licensed under the MIT license:
http://www.opensource.org/licenses/mit-license.php
ben@xoxco.com
*/
(function ($) {
var delimiter = [];
var tags_callbacks = [];
$.fn.doAutosize = function (o) {
var minWidth = $(this).data('minwidth'),
maxWidth = $(this).data('maxwidth'),
val = '',
input = $(this),
testSubject = $('#' + $(this).data('tester_id'));
if (val === (val = input.val())) {
return;
}
// Enter new content into testSubject
var escaped = val.replace(/&/g, '&amp;').replace(/\s/g, ' ').replace(/</g, '&lt;').replace(/>/g, '&gt;');
testSubject.html(escaped);
// Calculate new width + whether to change
var testerWidth = testSubject.width(),
newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
currentWidth = input.width(),
isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
|| (newWidth > minWidth && newWidth < maxWidth);
// Animate width
if (isValidWidthChange) {
input.width(newWidth);
}
};
$.fn.resetAutosize = function (options) {
// alert(JSON.stringify(options));
var minWidth = $(this).data('minwidth') || options.minInputWidth || $(this).width(),
maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width() - options.inputPadding),
val = '',
input = $(this),
testSubject = $('<tester/>').css({
position: 'absolute',
top: -9999,
left: -9999,
width: 'auto',
fontSize: input.css('fontSize'),
fontFamily: input.css('fontFamily'),
fontWeight: input.css('fontWeight'),
letterSpacing: input.css('letterSpacing'),
whiteSpace: 'nowrap'
}),
testerId = $(this).attr('id') + '_autosize_tester';
if (!$('#' + testerId).length > 0) {
testSubject.attr('id', testerId);
testSubject.appendTo('body');
}
input.data('minwidth', minWidth);
input.data('maxwidth', maxWidth);
input.data('tester_id', testerId);
input.css('width', minWidth);
};
$.fn.addTag = function (value, options) {
options = jQuery.extend({focus: false, callback: true}, options);
this.each(function () {
var id = $(this).attr('id');
var tagslist = $(this).val().split(delimiter[id]);
if (tagslist[0] == '') {
tagslist = [];
}
value = jQuery.trim(value);
if (options.unique) {
var skipTag = $(this).tagExist(value);
if (skipTag == true) {
//Marks fake input as not_valid to let styling it
$('#' + id + '_tag').addClass('not_valid');
}
} else {
var skipTag = false;
}
if (value != '' && skipTag != true) {
$('<span>').addClass('tag').append(
$('<span>').text(value),
$('<a>', {
href: '#',
title: '移除标签',
html: '&times;'
}).click(function () {
return $('#' + id).removeTag(escape(value));
})
).insertBefore('#' + id + '_addTag');
tagslist.push(value);
$('#' + id + '_tag').val('');
if (options.focus) {
$('#' + id + '_tag').focus();
} else {
$('#' + id + '_tag').blur();
}
$.fn.tagsInput.updateTagsField(this, tagslist);
if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) {
var f = tags_callbacks[id]['onAddTag'];
f.call(this, value);
}
if (tags_callbacks[id] && tags_callbacks[id]['onChange']) {
var i = tagslist.length;
var f = tags_callbacks[id]['onChange'];
f.call(this, $(this), tagslist[i - 1]);
}
}
});
return false;
};
$.fn.removeTag = function (value) {
value = unescape(value);
this.each(function () {
var id = $(this).attr('id');
var old = $(this).val().split(delimiter[id]);
$('#' + id + '_tagsinput .tag').remove();
str = '';
for (i = 0; i < old.length; i++) {
if (old[i] != value) {
str = str + delimiter[id] + old[i];
}
}
$.fn.tagsInput.importTags(this, str);
if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) {
var f = tags_callbacks[id]['onRemoveTag'];
f.call(this, value);
}
});
return false;
};
$.fn.tagExist = function (val) {
var id = $(this).attr('id');
var tagslist = $(this).val().split(delimiter[id]);
return (jQuery.inArray(val, tagslist) >= 0); //true when tag exists, false when not
};
// clear all existing tags and import new ones from a string
$.fn.importTags = function (str) {
var id = $(this).attr('id');
$('#' + id + '_tagsinput .tag').remove();
$.fn.tagsInput.importTags(this, str);
}
$.fn.tagsInput = function (options) {
var settings = jQuery.extend({
interactive: true,
defaultText: 'add a tag',
minChars: 0,
width: '300px',
height: '100px',
autocomplete: {selectFirst: false},
addOnBlur: true,
hide: true,
delimiter: ',',
delimiterSpace: true,
unique: true,
removeWithBackspace: true,
placeholderColor: '#666666',
autosize: true,
comfortZone: 20,
inputPadding: 6 * 2
}, options);
var uniqueIdCounter = 0;
this.each(function () {
// If we have already initialized the field, do not do it again
if (typeof $(this).attr('data-tagsinput-init') !== 'undefined') {
return;
}
// Mark the field as having been initialized
$(this).attr('data-tagsinput-init', true);
if (settings.hide) {
$(this).hide();
}
var id = $(this).attr('id');
if (!id || delimiter[$(this).attr('id')]) {
id = $(this).attr('id', 'tags' + new Date().getTime() + (uniqueIdCounter++)).attr('id');
}
var data = jQuery.extend({
pid: id,
real_input: '#' + id,
holder: '#' + id + '_tagsinput',
input_wrapper: '#' + id + '_addTag',
fake_input: '#' + id + '_tag'
}, settings);
delimiter[id] = data.delimiter;
if (settings.onAddTag || settings.onRemoveTag || settings.onChange || settings.onKeyDown) {
tags_callbacks[id] = [];
tags_callbacks[id]['onAddTag'] = settings.onAddTag;
tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag;
tags_callbacks[id]['onChange'] = settings.onChange;
tags_callbacks[id]['onKeyDown'] = settings.onKeyDown;
}
var markup = '<div id="' + id + '_tagsinput" class="tagsinput"><div id="' + id + '_addTag">';
if (settings.interactive) {
markup = markup + '<input id="' + id + '_tag" value="" data-default="' + settings.defaultText + '" />';
}
markup = markup + '</div><div class="tags_clear"></div></div>';
$(markup).insertAfter(this);
$(data.holder).css('width', settings.width);
$(data.holder).css('min-height', settings.height);
$(data.holder).css('height', settings.height);
if ($(data.real_input).val() != '') {
$.fn.tagsInput.importTags($(data.real_input), $(data.real_input).val());
}
if (settings.interactive) {
$(data.fake_input).val($(data.fake_input).attr('data-default'));
$(data.fake_input).css('color', settings.placeholderColor);
$(data.fake_input).resetAutosize(settings);
$(data.holder).bind('click', data, function (event) {
$(event.data.fake_input).focus();
});
$(data.fake_input).bind('focus', data, function (event) {
if ($(event.data.fake_input).val() == $(event.data.fake_input).attr('data-default')) {
$(event.data.fake_input).val('');
}
$(event.data.fake_input).css('color', '#000000');
});
if (typeof settings.autocomplete != 'undefined') {
if (jQuery.fn.autoComplete !== undefined) {
var xhr;
$(data.fake_input).autoComplete($.extend({
source: function (term, response) {
try {
xhr.abort();
} catch (e) {
}
xhr = $.getJSON(settings.autocomplete.url, {q: term}, function (data) {
response(data);
});
},
renderItem: function (item, search) {
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
},
onSelect: function (e, term, item) {
if (item) {
$('#' + id).addTag($(item).data("val") + "", {focus: true, unique: (settings.unique)});
}
}
}, settings.autocomplete));
} else if (jQuery.Autocompleter !== undefined) {
$(data.fake_input).autocomplete(settings.autocomplete.url, settings.autocomplete);
$(data.fake_input).bind('result', data, function (event, data, formatted) {
if (data) {
$('#' + id).addTag(data[0] + "", {focus: true, unique: (settings.unique)});
}
});
} else if (jQuery.ui.autocomplete !== undefined) {
$(data.fake_input).autocomplete(settings.autocomplete);
$(data.fake_input).bind('autocompleteselect', data, function (event, ui) {
$(event.data.real_input).addTag(ui.item.value, {focus: true, unique: (settings.unique)});
return false;
});
}
}
if (settings.addOnBlur) {
// if a user tabs out of the field, create a new tag
$(data.fake_input).bind('blur', data, function (event) {
var d = $(this).attr('data-default');
if ($(event.data.fake_input).val() != '' && $(event.data.fake_input).val() != d) {
if ((event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)))
$(event.data.real_input).addTag($(event.data.fake_input).val(), {focus: true, unique: (settings.unique)});
} else {
$(event.data.fake_input).val($(event.data.fake_input).attr('data-default'));
$(event.data.fake_input).css('color', settings.placeholderColor);
}
return false;
});
}
// if user types a default delimiter like comma,semicolon and then create a new tag
$(data.fake_input).bind('keypress textInput', data, function (event) {
if (_checkDelimiter.call(this, event)) {
var value = $(event.data.fake_input).val();
if (value.indexOf(event.data.delimiter) > -1 || (event.data.delimiterSpace && value.indexOf(" ") > -1)) {
$(event.data.fake_input).addClass('not_valid');
return false;
}
event.preventDefault();
if ((event.data.minChars <= value.length) && (!event.data.maxChars || (event.data.maxChars >= value.length)))
$(event.data.real_input).addTag(value, {focus: true, unique: (settings.unique)});
$(event.data.fake_input).resetAutosize(settings);
return false;
} else if (event.data.autosize) {
$(event.data.fake_input).doAutosize(settings);
}
});
//Delete last tag on backspace
data.removeWithBackspace && $(data.fake_input).bind('keydown', function (event) {
if (event.keyCode == 8 && $(this).val() == '') {
event.preventDefault();
var last_tag = $(this).closest('.tagsinput').find('.tag:last').find("span").text();
var id = $(this).attr('id').replace(/_tag$/, '');
last_tag = last_tag.replace(/[\s]+x$/, '');
$('#' + id).removeTag(escape(last_tag));
$(this).trigger('focus');
}
});
$(data.fake_input).bind('keydown', function (event) {
var id = $(this).attr('id').replace(/_tag$/, '');
if (tags_callbacks[id] && tags_callbacks[id]['onKeyDown']) {
var f = tags_callbacks[id]['onKeyDown'];
f.call(this, event);
}
});
$(data.fake_input).blur();
//Removes the not_valid class when user changes the value of the fake input
if (data.unique) {
$(data.fake_input).keydown(function (event) {
if (event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) {
$(this).removeClass('not_valid');
}
});
}
} // if settings.interactive
});
return this;
};
$.fn.tagsInput.updateTagsField = function (obj, tagslist) {
var id = $(obj).attr('id');
$(obj).val(tagslist.join(delimiter[id]));
};
$.fn.tagsInput.importTags = function (obj, val) {
$(obj).val('');
var id = $(obj).attr('id');
var tags = val.split(delimiter[id]);
for (i = 0; i < tags.length; i++) {
$(obj).addTag(tags[i], {focus: false, callback: false});
}
if (tags_callbacks[id] && tags_callbacks[id]['onChange']) {
var f = tags_callbacks[id]['onChange'];
f.call(obj, obj, tags[i]);
}
};
/**
* check delimiter Array
* @param event
* @returns {boolean}
* @private
*/
var _checkDelimiter = function (event) {
var found = false;
var key = event.keyCode || event.which || event.charCode;
key = key || event.originalEvent.data.charCodeAt(0);
if (key == 0 || key == 229) {
var value = $(this).val();
key = value.charCodeAt(value.length - 1);
}
if (key == 13 || (event.data.delimiterSpace && key == 32)) {
return true;
}
if (typeof event.data.delimiter === 'string') {
if (key == event.data.delimiter.charCodeAt(0)) {
found = true;
}
} else {
$.each(event.data.delimiter, function (index, delimiter) {
if (key == delimiter.charCodeAt(0)) {
found = true;
}
});
}
return found;
}
})(jQuery);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long