Merge branch 'sync-from-leanote.com'

This commit is contained in:
lealife
2015-10-10 18:10:41 +08:00
108 changed files with 2786 additions and 9363 deletions

View File

@@ -90,6 +90,7 @@ gulp.task('devToProHtml', function() {
.pipe(replace(/<!-- pro_app_js -->/, '<script src="/js/app.min.js"></script>')) // 替换
.pipe(replace(/<!-- pro_markdown_js -->/, '<script src="/js/markdown.min.js"></script>')) // 替换
.pipe(replace(/<!-- pro_tinymce_init_js -->/, "var tinyMCEPreInit = {base: '/public/tinymce', suffix: '.min'};")) // 替换
.pipe(replace(/plugins\/main.js/, "plugins/main.min.js")) // 替换
// 连续两个空行换成一个空行, 没用
.pipe(replace(/\n\n/g, '\n'))
.pipe(replace(/\n\n/g, '\n'))
@@ -99,9 +100,180 @@ gulp.task('devToProHtml', function() {
.pipe(gulp.dest(noteProBase));
});
// tinymce
// Get used keys
// 只获取需要js i18n的key
var path = require('path');
gulp.task('i18n', function() {
var keys = {};
var reg = /getMsg\(["']+(.+?)["']+/g;
function getKey(data) {
while(ret = reg.exec(data)) {
keys[ret[1]] = 1;
}
}
// 先获取需要的key
function ls(ff) {
var files = fs.readdirSync(ff);
for(fn in files) {
var fname = ff + path.sep + files[fn];
var stat = fs.lstatSync(fname);
if(stat.isDirectory() == true) {
ls(fname);
}
else {
if ((fname.indexOf('.html') > 0 || fname.indexOf('.js') > 0)) {
// console.log(fname);
// if (fname.indexOf('min.js') < 0) {
var data = fs.readFileSync(fname, "utf-8");
// 得到getMsg里的key
getKey(data);
// }
}
}
}
}
var tinymceBase = base + '/tinymce_4.1.9';
console.log('parsing used keys');
ls(base + '/admin');
ls(base + '/blog');
ls(base + '/dist');
ls(base + '/js');
ls(base + '/libs');
ls(base + '/member');
ls(base + '/tinymce');
console.log('parsed');
// msg.zh
function getAllMsgs(fname) {
var msg = {};
var data = fs.readFileSync(fname, "utf-8");
var lines = data.split('\n');
for (var i = 0; i < lines.length; ++i) {
var line = lines[i];
// 忽略注释
if (line[0] == '#' || line[1] == '#') {
continue;
}
var lineArr = line.split('=');
if (lineArr.length >= 2) {
var key = lineArr[0];
lineArr.shift();
msg[key] = lineArr.join('=');
// msg[lineArr[0]] = lineArr[1];
}
}
return msg;
}
// msg.zh, msg.js
function genI18nJsFile(fromFilename, keys) {
var msgs = getAllMsgs(leanoteBase + '/messages/' + fromFilename);
var toFilename = fromFilename + '.js';
var toMsgs = {};
for (var i in msgs) {
// 只要需要的
if (i in keys) {
toMsgs[i] = msgs[i];
}
}
var str = 'var MSG=' + JSON.stringify(toMsgs) + ';';
str += 'function getMsg(key, data) {var msg = MSG[key];if(msg) {if(data) {if(!isArray(data)) {data = [data];}' +
'for(var i = 0; i < data.length; ++i) {' +
'msg = msg.replace("%s", data[i]);' +
'}' +
'}' +
'return msg;' +
'}' +
'return key;' +
'}';
// 写入到文件中
fs.writeFile(base + '/js/i18n/' + toFilename, str);
}
genI18nJsFile('msg.zh', keys);
genI18nJsFile('msg.en', keys);
genI18nJsFile('msg.fr', keys);
genI18nJsFile('blog.zh', keys);
genI18nJsFile('blog.en', keys);
genI18nJsFile('blog.fr', keys);
});
// plugins压缩
gulp.task('plugins', function() {
gulp.src(base + '/js/plugins/libs/*.js')
.pipe(uglify()) // 压缩
// .pipe(concat('main.min.js'))
.pipe(gulp.dest(base + '/js/plugins/libs-min'));
// 所有js合并成一个
var jss = [
'note_info',
'tips',
'history',
'attachment_upload',
'editor_drop_paste',
'main'
];
for(var i in jss) {
jss[i] = base + '/js/plugins/' + jss[i] + '.js';
}
gulp.src(jss)
.pipe(uglify()) // 压缩
.pipe(concat('main.min.js'))
.pipe(gulp.dest(base + '/js/plugins'));
});
// mincss
var minifycss = require('gulp-minify-css');
gulp.task('minifycss', function() {
gulp.src(base + '/css/bootstrap.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css'));
gulp.src(base + '/css/font-awesome-4.2.0/css/font-awesome.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/font-awesome-4.2.0/css'));
gulp.src(base + '/css/zTreeStyle/zTreeStyle.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/zTreeStyle'));
gulp.src(base + '/dist/themes/default.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/dist/themes'));
gulp.src(base + '/js/contextmenu/css/contextmenu.css')
.pipe(rename({suffix: '-min'}))
.pipe(minifycss())
.pipe(gulp.dest(base + '/js/contextmenu/css'));
// theme
// 用codekit
var as = ['default', 'simple', 'writting', /*'writting-overwrite', */ 'mobile'];
/*
for(var i = 0; i < as.length; ++i) {
gulp.src(base + '/css/theme/' + as[i] + '.css')
.pipe(minifycss())
.pipe(gulp.dest(base + '/css/theme'));
}
*/
});
// tinymce
// !! You must has tinymce_dev on public/
var tinymceBase = base + '/tinymce_dev';
gulp.task('tinymce', function() {
// 先清理
fs.unlink(tinymceBase + '/js/tinymce/tinymce.dev.js');
@@ -126,6 +298,7 @@ gulp.task('tinymce', function() {
});
// 合并css, 无用
// Deprecated
gulp.task('concatCss', function() {
return gulp
.src([markdownRaw + '/css/default.css', markdownRaw + '/css/md.css'])
@@ -135,4 +308,4 @@ gulp.task('concatCss', function() {
gulp.task('concat', ['concatDepJs', 'concatAppJs', 'concatMarkdownJs']);
gulp.task('html', ['devToProHtml']);
gulp.task('default', ['concat', 'html']);
gulp.task('default', ['concat', 'plugins', 'minifycss', 'i18n', 'html']);

View File

@@ -2,11 +2,11 @@ package controllers
import (
"github.com/revel/revel"
// "encoding/json"
// "encoding/json"
"github.com/leanote/leanote/app/info"
"gopkg.in/mgo.v2/bson"
// . "github.com/leanote/leanote/app/lea"
// "io/ioutil"
// . "github.com/leanote/leanote/app/lea"
// "io/ioutil"
)
// Album controller
@@ -19,7 +19,6 @@ func (c Album) GetAlbums() revel.Result {
re := albumService.GetAlbums(c.GetUserId())
return c.RenderJson(re)
}
func (c Album) DeleteAlbum(albumId string) revel.Result {
re, msg := albumService.DeleteAlbum(c.GetUserId(), albumId)
return c.RenderJson(info.Re{Ok: re, Msg: msg})
@@ -29,12 +28,12 @@ func (c Album) DeleteAlbum(albumId string) revel.Result {
func (c Album) AddAlbum(name string) revel.Result {
album := info.Album{
AlbumId: bson.NewObjectId(),
Name: name,
Seq: -1,
UserId: c.GetObjectUserId()}
Name: name,
Seq: -1,
UserId: c.GetObjectUserId()}
re := albumService.AddAlbum(album)
if(re) {
if re {
return c.RenderJson(album)
} else {
return c.RenderJson(false)
@@ -44,4 +43,4 @@ func (c Album) AddAlbum(name string) revel.Result {
// update alnum name
func (c Album) UpdateAlbum(albumId, name string) revel.Result {
return c.RenderJson(albumService.UpdateAlbum(albumId, c.GetUserId(), name))
}
}

View File

@@ -86,7 +86,8 @@ func (c Auth) Logout() revel.Result {
// 体验一下
func (c Auth) Demo() revel.Result {
email := configService.GetGlobalStringConfig("demoUsername")
pwd := configService.GetGlobalStringConfig("demoPassword");
pwd := configService.GetGlobalStringConfig("demoPassword")
userInfo, err := authService.Login(email, pwd)
if err != nil {
return c.RenderJson(info.Re{Ok: false})

View File

@@ -84,6 +84,13 @@ func (c BaseController) GetUserInfo() info.User {
return info.User{}
}
func (c BaseController) GetUserAndBlogUrl() info.UserAndBlogUrl {
if userId, ok := c.Session["UserId"]; ok && userId != "" {
return userService.GetUserAndBlogUrl(userId);
}
return info.UserAndBlogUrl{}
}
// 这里的session都是cookie中的, 与数据库session无关
func (c BaseController) GetSession(key string) string {
v, ok := c.Session[key]

View File

@@ -265,10 +265,6 @@ func (c Blog) getCates(userBlog info.UserBlog) {
}
}
Log("cates")
LogJ(cates)
LogJ(catesTree);
c.RenderArgs["cates"] = cates
c.RenderArgs["catesTree"] = catesTree
}
@@ -352,9 +348,10 @@ func (c Blog) blogCommon(userId string, userBlog info.UserBlog, userInfo info.Us
// 得到主题信息
themeInfo := themeService.GetThemeInfo(userBlog.ThemeId.Hex(), userBlog.Style)
c.RenderArgs["themeInfo"] = themeInfo
Log(">>")
Log(userBlog.Style)
Log(userBlog.ThemeId.Hex())
// Log(">>")
// Log(userBlog.Style)
// Log(userBlog.ThemeId.Hex())
return true, userBlog
}

View File

@@ -69,13 +69,13 @@ func (c File) UploadAvatar() revel.Result {
c.UpdateSession("Logo", re.Id);
}
}
return c.RenderJson(re)
}
// leaui image plugin upload image
func (c File) UploadImageLeaui(albumId string) revel.Result {
re := c.uploadImage("", albumId);
re := c.uploadImage("", albumId)
return c.RenderJson(re)
}
@@ -84,74 +84,80 @@ func (c File) UploadImageLeaui(albumId string) revel.Result {
func (c File) uploadImage(from, albumId string) (re info.Re) {
var fileUrlPath = ""
var fileId = ""
var resultCode = 0 // 1表示正常
var resultCode = 0 // 1表示正常
var resultMsg = "error" // 错误信息
var Ok = false
defer func() {
re.Id = fileId // 只是id, 没有其它信息
re.Code = resultCode
re.Msg = resultMsg
re.Ok = Ok
}()
file, handel, err := c.Request.FormFile("file")
if err != nil {
return re
}
defer file.Close()
// 生成上传路径
newGuid := NewGuid()
userId := c.GetUserId()
if(from == "logo" || from == "blogLogo") {
fileUrlPath = "public/upload/" + c.GetUserId() + "/images/logo"
fileUrlPath = "public/upload/" + Digest3(userId) + "/" + userId + "/images/logo"
} else {
fileUrlPath = "files/" + c.GetUserId() + "/images"
fileUrlPath = "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images"
}
dir := revel.BasePath + "/" + fileUrlPath
dir := revel.BasePath + "/" + fileUrlPath
err = os.MkdirAll(dir, 0755)
if err != nil {
return re
}
// 生成新的文件名
filename := handel.Filename
var ext string;
var ext string
if from == "pasteImage" {
ext = ".png"; // TODO 可能不是png类型
ext = ".png" // TODO 可能不是png类型
} else {
_, ext = SplitFilename(filename)
if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
resultMsg = "Please upload image"
return re
}
}
filename = NewGuid() + ext
filename = newGuid + ext
data, err := ioutil.ReadAll(file)
if err != nil {
LogJ(err)
return re
}
var maxFileSize float64
if(from == "logo") {
maxFileSize = configService.GetUploadSize("uploadAvatarSize");
if from == "logo" {
maxFileSize = configService.GetUploadSize("uploadAvatarSize")
} else if from == "blogLogo" {
maxFileSize = configService.GetUploadSize("uploadBlogLogoSize");
maxFileSize = configService.GetUploadSize("uploadBlogLogoSize")
} else {
maxFileSize = configService.GetUploadSize("uploadImageSize");
maxFileSize = configService.GetUploadSize("uploadImageSize")
}
if maxFileSize <= 0 {
maxFileSize = 1000
}
// > 2M?
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
if float64(len(data)) > maxFileSize*float64(1024*1024) {
resultCode = 0
resultMsg = fmt.Sprintf("The file Size is bigger than %vM", maxFileSize)
return re
}
toPath := dir + "/" + filename;
toPath := dir + "/" + filename
err = ioutil.WriteFile(toPath, data, 0777)
if err != nil {
LogJ(err)
@@ -164,26 +170,27 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
fileUrlPath += "/" + filename
resultCode = 1
resultMsg = "Upload Success!"
// File
fileInfo := info.File{Name: filename,
Title: handel.Filename,
Path: fileUrlPath,
Size: filesize}
id := bson.NewObjectId();
Path: fileUrlPath,
Size: filesize}
id := bson.NewObjectId()
fileInfo.FileId = id
fileId = id.Hex()
if(from == "logo" || from == "blogLogo") {
fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename
}
if(from == "logo" || from == "blogLogo") {
fileId = fileUrlPath
}
Ok, resultMsg = fileService.AddImage(fileInfo, albumId, c.GetUserId(), from == "" || from == "pasteImage")
resultMsg = c.Message(resultMsg)
fileInfo.Path = ""; // 不要返回
fileInfo.Path = "" // 不要返回
re.Item = fileInfo
return re
}
@@ -204,6 +211,7 @@ func (c File) DeleteImage(fileId string) revel.Result {
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
return c.RenderJson(re)
}
//-----------
// 输出image
@@ -226,35 +234,39 @@ func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
return c.RenderJson(re)
}
// 复制外网的图片, 成公共图片 放在/upload下
// 复制外网的图片
// 都要好好的计算大小
func (c File) CopyHttpImage(src string) revel.Result {
re := info.NewRe()
fileUrlPath := "upload/" + c.GetUserId() + "/images"
dir := revel.BasePath + "/public/" + fileUrlPath
// 生成上传路径
newGuid := NewGuid()
userId := c.GetUserId()
fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images"
dir := revel.BasePath + "/" + fileUrlPath
err := os.MkdirAll(dir, 0755)
if err != nil {
return c.RenderJson(re)
}
filesize, filename, _, ok := netutil.WriteUrl(src, dir)
if !ok {
re.Msg = "copy error"
return c.RenderJson(re)
}
// File
fileInfo := info.File{Name: filename,
Title: filename,
Path: fileUrlPath + "/" + filename,
Size: filesize}
id := bson.NewObjectId();
Path: fileUrlPath + "/" + filename,
Size: filesize}
id := bson.NewObjectId()
fileInfo.FileId = id
re.Id = id.Hex()
re.Item = fileInfo.Path
// re.Item = fileInfo.Path
re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true)
return c.RenderJson(re)
}
}

View File

@@ -21,13 +21,12 @@ func (c Index) Default() revel.Result {
}
// leanote展示页, 没有登录的, 或已登录明确要进该页的
func (c Index) Index() revel.Result {
c.SetUserInfo()
c.RenderArgs["title"] = "leanote"
c.RenderArgs["openRegister"] = configService.GlobalStringConfigs["openRegister"]
lang := c.SetLocale()
c.SetLocale()
return c.RenderTemplate("home/index_" + lang + ".html");
return c.RenderTemplate("home/index.html");
}
// 建议

View File

@@ -24,8 +24,8 @@ type Note struct {
// 否则, 转向登录页面
func (c Note) Index(noteId, online string) revel.Result {
c.SetLocale()
userInfo := c.GetUserInfo()
userInfo := c.GetUserAndBlogUrl()
userId := userInfo.UserId.Hex()
// 没有登录
@@ -126,7 +126,7 @@ func (c Note) Index(noteId, online string) revel.Result {
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
// return c.RenderTemplate("note/note.html")
if isDev, _ := revel.Config.Bool("mode.dev"); isDev && online == "" {
return c.RenderTemplate("note/note-dev.html")
} else {
@@ -138,13 +138,13 @@ func (c Note) Index(noteId, online string) revel.Result {
// 已登录, 得到用户基本信息(notebook, shareNotebook), 跳转到index.html中
// 否则, 转向登录页面
func (c Note) ListNotes(notebookId string) revel.Result {
_, notes := noteService.ListNotes(c.GetUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false);
_, notes := noteService.ListNotes(c.GetUserId(), notebookId, false, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(notes)
}
// 得到trash
func (c Note) ListTrashNotes() revel.Result {
_, notes := noteService.ListNotes(c.GetUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false);
_, notes := noteService.ListNotes(c.GetUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(notes)
}

View File

@@ -29,8 +29,8 @@ func (c User) Account(tab int) revel.Result {
// 修改用户名, 需要重置session
func (c User) UpdateUsername(username string) revel.Result {
re := info.NewRe();
if(c.GetUsername() == "demo") {
re := info.NewRe()
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo"
return c.RenderRe(re);
}
@@ -48,8 +48,8 @@ func (c User) UpdateUsername(username string) revel.Result {
// 修改密码
func (c User) UpdatePwd(oldPwd, pwd string) revel.Result {
re := info.NewRe();
if(c.GetUsername() == "demo") {
re := info.NewRe()
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo"
return c.RenderRe(re);
}
@@ -94,9 +94,9 @@ func (c User) ReSendActiveEmail() revel.Result {
}
// 修改Email发送激活邮箱
func (c User) UpdateEmailSendActiveEmail(email string) revel.Result {
func (c User) updateEmailSendActiveEmail(email, pwd string) revel.Result {
re := info.NewRe()
if(c.GetUsername() == "demo") {
if c.GetUserId() == configService.GetGlobalStringConfig("demoUserId") {
re.Msg = "cannotUpdateDemo"
return c.RenderJson(re);
}
@@ -193,4 +193,4 @@ func (c User) UpdateLeftIsMin(leftIsMin bool) revel.Result {
}
}
return c.RenderJson(re)
}
}

View File

@@ -23,16 +23,16 @@ type ApiAuth struct {
// 失败返回 {Ok: false, Msg: ""}
func (c ApiAuth) Login(email, pwd string) revel.Result {
var msg = ""
userInfo, err := authService.Login(email, pwd)
if err != nil {
// 登录错误, 则错误次数++
msg = "wrongUsernameOrPassword"
} else {
if err == nil {
token := bson.NewObjectId().Hex()
sessionService.SetUserId(token, userInfo.UserId.Hex())
return c.RenderJson(info.AuthOk{Ok: true, Token: token, UserId: userInfo.UserId, Email: userInfo.Email, Username: userInfo.Username})
}
} else {
// 登录错误, 则错误次数++
msg = "wrongUsernameOrPassword"
}
return c.RenderJson(info.ApiRe{Ok: false, Msg: c.Message(msg)})
}
@@ -66,4 +66,4 @@ func (c ApiAuth) Register(email, pwd string) revel.Result {
// 注册
re.Ok, re.Msg = authService.Register(email, pwd, "")
return c.RenderJson(re)
}
}

View File

@@ -74,7 +74,9 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
}
// 生成上传路径
filePath := "files/" + userId + "/attachs"
newGuid := NewGuid()
filePath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/attachs"
dir := revel.BasePath + "/" + filePath
err = os.MkdirAll(dir, 0755)
if err != nil {
@@ -83,7 +85,7 @@ func (c ApiBaseContrller) uploadAttach(name string, noteId string) (ok bool, msg
// 生成新的文件名
filename := handel.Filename
_, ext := SplitFilename(filename) // .doc
filename = NewGuid() + ext
filename = newGuid + ext
toPath := dir + "/" + filename;
err = ioutil.WriteFile(toPath, data, 0777)
if err != nil {
@@ -124,8 +126,12 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
return
}
defer file.Close()
newGuid := NewGuid()
// 生成上传路径
fileUrlPath := "files/" + c.getUserId() + "/images"
userId := c.getUserId()
fileUrlPath := "files/" + Digest3(userId) + "/" + userId + "/" + Digest2(newGuid) + "/images"
dir := revel.BasePath + "/" + fileUrlPath
err = os.MkdirAll(dir, 0755)
if err != nil {
@@ -139,7 +145,7 @@ func (c ApiBaseContrller) upload(name string, noteId string, isAttach bool) (ok
return
}
filename = NewGuid() + ext
filename = newGuid + ext
data, err := ioutil.ReadAll(file)
if err != nil {
return

View File

@@ -70,6 +70,7 @@ func (c ApiNote) GetNotes(notebookId string) revel.Result {
func (c ApiNote) GetTrashNotes() revel.Result {
_, notes := noteService.ListNotes(c.getUserId(), "", true, c.GetPage(), pageSize, defaultSortField, false, false)
return c.RenderJson(noteService.ToApiNotes(notes))
}
// get Note

View File

@@ -68,7 +68,7 @@ var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": tru
},
"Oauth": map[string]bool{"GithubCallback": true},
"File": map[string]bool{"OutputImage": true, "OutputFile": true},
"Attach": map[string]bool{"Download": true, "DownloadAll": true},
"Attach": map[string]bool{"Download": true/*, "DownloadAll": true*/},
}
func needValidate(controller, method string) bool {

View File

@@ -355,3 +355,20 @@ func Err(err error) bool {
}
return true
}
// 检查mognodb是否lost connection
// 每个请求之前都要检查!!
func CheckMongoSessionLost() {
// fmt.Println("检查CheckMongoSessionLostErr")
err := Session.Ping()
if err != nil {
Log("Lost connection to db!")
Session.Refresh()
err = Session.Ping()
if err == nil {
Log("Reconnect to db successful.")
} else {
Log("重连失败!!!! 警告")
}
}
}

View File

@@ -70,6 +70,13 @@ type UserAccount struct {
MaxPerAttachSize int `bson:"MaxPerAttachSize" json:"-"` // 单个附件大小
}
// note主页需要
type UserAndBlogUrl struct {
User
BlogUrl string `BlogUrl`
PostUrl string `PostUrl`
}
// 用户与博客信息结合, 公开
type UserAndBlog struct {
UserId bson.ObjectId `bson:"_id,omitempty"` // 必须要设置bson:"_id" 不然mgo不会认为是主键

View File

@@ -11,6 +11,8 @@ import (
"gopkg.in/mgo.v2/bson"
"time"
"strings"
"github.com/PuerkitoBio/goquery"
"bytes"
math_rand "math/rand"
)
@@ -23,6 +25,22 @@ func Md5(s string) string {
return hex.EncodeToString(h.Sum(nil))
}
// 3位数的转换, 为了用bson.id -> 3位数
func Digest3(str string) string {
var b rune = 0
for _, k := range str {
b += k
}
return fmt.Sprintf("%d", b % 1000)
}
func Digest2(str string) string {
var b rune = 0
for _, k := range str {
b += k
}
return fmt.Sprintf("%d", b % 100)
}
// Guid
func NewGuid() string {
b := make([]byte, 48)
@@ -124,73 +142,48 @@ func ReplaceAll(oldStr, pattern, newStr string) string {
}
// 获取纯文本
func SubStringHTMLToRaw(param string, length int) (result string) {
func SubStringHTMLToRaw(param string, length int) string {
if param == "" {
return ""
return param
}
result = ""
n := 0
var temp rune // 中文问题, 用rune来解决
rStr := []rune(param)
lenStr := len(rStr)
isCode := false
for i := 0; i < len(rStr); i++ {
resultRune := make([]rune, length)
// s := ""
for i := 0; i < lenStr; i++ {
temp = rStr[i]
if temp == '<' {
isCode = true
continue
} else if temp == '>' {
isCode = false
result += " "; // 空格
resultRune[n] = ' ';
n++
if n >= length {
break
}
continue
}
if !isCode {
result += string(temp)
resultRune[n] = temp;
// s += string(temp)
n++
if n >= length {
break
}
}
}
return
result := string(resultRune[0:n])
return strings.Trim(result, " ")
}
// 获取摘要, HTML
func SubStringHTML(param string, length int, end string) string {
if param == "" {
return ""
}
// 先取出<pre></pre>占位..
result := ""
// 1
n := 0
var temp rune // 中文问题, 用rune来解决
isCode := false //是不是HTML代码
isHTML := false //是不是HTML特殊字符,如&nbsp;
rStr := []rune(param)
for i := 0; i < len(rStr); i++ {
temp = rStr[i]
if temp == '<' {
isCode = true
} else if temp == '&' {
isHTML = true
} else if temp == '>' && isCode {
n = n - 1
isCode = false
} else if temp == ';' && isHTML {
isHTML = false
}
if !isCode && !isHTML {
n = n + 1
}
result += string(temp)
if n >= length {
break
}
}
result += end
// 自带方法补全html
func fixHtml(result string) string {
// 取出所有标签
tempResult := ReplaceAll(result, "(>)[^<>]*(<?)", "$1$2") // 把标签中间的所有内容都去掉了
@@ -233,6 +226,71 @@ func SubStringHTML(param string, length int, end string) string {
return result
}
// 获取摘要, HTML
func SubStringHTML(param string, length int, end string) string {
if param == "" {
return param
}
result := ""
rStr := []rune(param)
lenStr := len(rStr)
if lenStr <= length {
result = param
} else {
// 1
n := 0
var temp rune // 中文问题, 用rune来解决
isCode := false //是不是HTML代码
isHTML := false //是不是HTML特殊字符,如&nbsp;
var i = 0;
for ; i < lenStr; i++ {
temp = rStr[i]
if temp == '<' {
isCode = true
} else if temp == '&' {
isHTML = true
} else if temp == '>' && isCode {
// n = n - 1
isCode = false
} else if temp == ';' && isHTML {
isHTML = false
}
if !isCode && !isHTML {
n = n + 1
}
// 每一次都相加, 速度非常慢!, 重新分配内存, 7倍的差距
// result += string(temp)
if n >= length {
break
}
}
result = string(rStr[0:i])
if end != "" {
result += end
}
}
// 使用goquery来取出html, 为了补全html
htmlReader := bytes.NewBufferString(result)
dom, err1 := goquery.NewDocumentFromReader(htmlReader)
if err1 == nil {
html, _ := dom.Html()
html = strings.Replace(html, "<html><head></head><body>", "", 1)
html = strings.Replace(html, "</body></html>", "", 1)
// TODO 把style="float: left"去掉
return html
// 如果有错误, 则使用自己的方法补全, 有风险
} else {
return fixHtml(result)
}
}
// 是否是合格的密码
func IsGoodPwd(pwd string) (bool, string) {
if pwd == "" {
@@ -249,7 +307,7 @@ func IsEmail(email string) bool {
if email == "" {
return false;
}
ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-z\-A-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,3}$`, email)
ok, _ := regexp.MatchString(`^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[_a-z\-A-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,6}$`, email)
return ok
}

View File

@@ -2,7 +2,7 @@ package route
import (
"github.com/revel/revel"
// "github.com/leanote/leanote/app/service"
"github.com/leanote/leanote/app/db"
// . "github.com/leanote/leanote/app/lea"
"net/url"
"strings"
@@ -42,6 +42,10 @@ func RouterFilter(c *revel.Controller, fc []revel.Filter) {
}
*/
if route.ControllerName != "Static" {
// 检查mongodb 是否lost
db.CheckMongoSessionLost()
// api设置
// leanote.com/api/user/get => ApiUser::Get
//* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了

View File

@@ -63,10 +63,19 @@ func (this *AttachService) updateNoteAttachNum(noteId bson.ObjectId, addNum int)
// list attachs
func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
attachs := []info.Attach{}
// 判断是否有权限为笔记添加附件
if !shareService.HasUpdateNotePerm(noteId, userId) {
// 判断是否有权限为笔记添加附件, userId为空时表示是分享笔记的附件
if userId != "" && !shareService.HasUpdateNotePerm(noteId, userId) {
return attachs
}
// 笔记是否是自己的
note := noteService.GetNoteByIdAndUserId(noteId, userId)
if note.NoteId == "" {
return attachs
}
// TODO 这里, 优化权限控制
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)

View File

@@ -45,7 +45,9 @@ func (this *BlogService) GetBlogByIdAndUrlTitle(userId string, noteIdOrUrlTitle
return this.GetBlog(noteIdOrUrlTitle)
}
note := info.Note{}
db.GetByQ(db.Notes, bson.M{"UserId": bson.ObjectIdHex(userId), "UrlTitle": encodeValue(noteIdOrUrlTitle), "IsBlog": true, "IsTrash": false}, &note)
db.GetByQ(db.Notes, bson.M{"UserId": bson.ObjectIdHex(userId), "UrlTitle": encodeValue(noteIdOrUrlTitle),
"IsBlog": true,
"IsTrash": false, "IsDeleted": false}, &note)
return this.GetBlogItem(note)
}
@@ -56,7 +58,7 @@ func (this *BlogService) GetBlog(noteId string) (blog info.BlogItem) {
}
func (this *BlogService) GetBlogItem(note info.Note) (blog info.BlogItem) {
if note.NoteId == "" || !note.IsBlog {
return
return info.BlogItem{}
}
// 内容
@@ -131,7 +133,8 @@ func (this *BlogService) ListBlogs(userId, notebookId string, page, pageSize int
func (this *BlogService) GetBlogTags(userId string) []info.TagCount {
// 得到所有博客
tagCounts := []info.TagCount{}
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true}
// tag不能为空
query := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true, "Tag": bson.M{"$ne": ""}}
db.TagCounts.Find(query).Sort("-Count").All(&tagCounts)
return tagCounts
}
@@ -142,7 +145,7 @@ func (this *BlogService) ReCountBlogTags(userId string) bool {
// 得到所有博客
notes := []info.Note{}
userIdO := bson.ObjectIdHex(userId)
query := bson.M{"UserId": userIdO, "IsTrash": false, "IsBlog": true}
query := bson.M{"UserId": userIdO, "IsTrash": false, "IsDeleted": false, "IsBlog": true}
db.ListByQWithFields(db.Notes, query, []string{"Tags"}, &notes)
db.DeleteAll(db.TagCounts, bson.M{"UserId": userIdO, "IsBlog": true})
@@ -184,7 +187,7 @@ Posts: []
*/
func (this *BlogService) ListBlogsArchive(userId, notebookId string, year, month int, sortField string, isAsc bool) []info.Archive {
// _, notes := noteService.ListNotes(userId, notebookId, false, 1, 99999, sortField, isAsc, true);
q := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true, "IsTrash": false}
q := bson.M{"UserId": bson.ObjectIdHex(userId), "IsBlog": true, "IsTrash": false, "IsDeleted": false}
if notebookId != "" {
q["NotebookId"] = bson.ObjectIdHex(notebookId)
}
@@ -291,9 +294,10 @@ func (this *BlogService) SearchBlogByTags(tags []string, userId string, pageNumb
// 不是trash的
query := bson.M{"UserId": bson.ObjectIdHex(userId),
"IsTrash": false,
"IsBlog": true,
"Tags": bson.M{"$all": tags}}
"IsTrash": false,
"IsDeleted": false,
"IsBlog": true,
"Tags": bson.M{"$all": tags}}
q := db.Notes.Find(query)
@@ -366,10 +370,10 @@ func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bo
if !isAsc {
// 降序
/*
------- pre
----- now
--- next
--
------- pre
----- now
--- next
--
*/
// 上一篇时间要比它大, 找最小的
sortFieldT1 = bson.M{"$gte": baseTime} // 为什么要相等, 因为将notebook发布成博客, 会统一修改note的publicTime, 此时所有notes都一样
@@ -393,12 +397,14 @@ func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bo
sortFieldR2 = sorterField
}
// 1
// 上一篇, 比基时间要小, 但是是最后一篇, 所以是降序
note := info.Note{}
query := bson.M{"UserId": userIdO,
"IsTrash": false,
"IsBlog": true,
"_id": bson.M{"$ne": bson.ObjectIdHex(noteId)},
query := bson.M{"UserId": userIdO,
"IsTrash": false,
"IsDeleted": false,
"IsBlog": true,
"_id": bson.M{"$ne": bson.ObjectIdHex(noteId)},
sorterField: sortFieldT1,
}
q := db.Notes.Find(query)
@@ -430,7 +436,7 @@ func (this *BlogService) ListAllBlogs(userId, tag string, keywords string, isRec
skipNum, sortFieldR := parsePageAndSort(page, pageSize, sorterField, isAsc)
// 不是trash的
query := bson.M{"IsTrash": false, "IsBlog": true, "Title": bson.M{"$ne": "欢迎来到leanote!"}}
query := bson.M{"IsTrash": false, "IsDeleted": false, "IsBlog": true, "Title": bson.M{"$ne": "欢迎来到leanote!"}}
if tag != "" {
query["Tags"] = bson.M{"$in": []string{tag}}
}
@@ -496,6 +502,9 @@ func (this *BlogService) ListAllBlogs(userId, tag string, keywords string, isRec
content = noteContent.Abstract
}
*/
if len(note.Tags) == 1 && note.Tags[0] == "" {
note.Tags = nil
}
blogs[i] = info.BlogItem{note, "", content, hasMore, userMap[note.UserId]}
}
pageInfo = info.NewPage(page, pageSize, count, nil)

View File

@@ -21,14 +21,26 @@ func (this *NoteService) GetNote(noteId, userId string) (note info.Note) {
// 不能是已经删除了的, life bug, 客户端删除后, 竟然还能在web上打开
func (this *NoteService) GetNoteById(noteId string) (note info.Note) {
note = info.Note{}
if noteId == "" {
return
}
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "IsDeleted": false}, &note)
return
}
func (this *NoteService) GetNoteByIdAndUserId(noteId, userId string) (note info.Note) {
note = info.Note{}
if noteId == "" || userId == "" {
return
}
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "UserId": bson.ObjectIdHex(userId), "IsDeleted": false}, &note)
return
}
// 得到blog, blogService用
// 不要传userId, 因为是公开的
func (this *NoteService) GetBlogNote(noteId string) (note info.Note) {
note = info.Note{}
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId), "IsBlog": true, "IsTrash": false}, &note)
db.GetByQ(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId),
"IsBlog": true, "IsTrash": false, "IsDeleted": false}, &note)
return
}
// 通过id, userId得到noteContent
@@ -418,7 +430,7 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
if isBlog, ok := needUpdate["IsBlog"]; ok {
isBlog2 := isBlog.(bool)
if note.IsBlog != isBlog2 {
db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, bson.M{"IsBlog": isBlog2})
this.UpdateNoteContentIsBlog(noteId, userId, isBlog2);
// 重新发布成博客
if !note.IsBlog {
@@ -459,6 +471,11 @@ func (this *NoteService) UpdateNote(updatedUserId, noteId string, needUpdate bso
return true, "", afterUsn
}
// 当设置/取消了笔记为博客
func (this *NoteService) UpdateNoteContentIsBlog(noteId, userId string, isBlog bool) {
db.UpdateByIdAndUserIdMap(db.NoteContents, noteId, userId, bson.M{"IsBlog": isBlog})
}
// 附件修改, 增加noteIncr
func (this *NoteService) IncrNoteUsn(noteId, userId string) int {
afterUsn := userService.IncrUsn(userId)
@@ -572,6 +589,8 @@ func (this *NoteService) ToBlog(userId, noteId string, isBlog, isTop bool) bool
ok := db.UpdateByIdAndUserIdMap(db.Notes, noteId, userId, noteUpdate)
// 重新计算tags
go (func() {
this.UpdateNoteContentIsBlog(noteId, userId, isBlog);
blogService.ReCountBlogTags(userId)
})()
return ok
@@ -734,6 +753,7 @@ func (this *NoteService) SearchNote(key, userId string, pageNumber, pageSize int
// 不是trash的
query := bson.M{"UserId": bson.ObjectIdHex(userId),
"IsTrash": false,
"IsDeleted": false, // 不能搜索已删除了的
"$or": orQ,
}
if isBlog {
@@ -819,14 +839,14 @@ func (this *NoteService) SearchNoteByTags(tags []string, userId string, pageNumb
//------------
// 统计
func (this *NoteService) CountNote(userId string) int {
q := bson.M{"IsTrash": false}
q := bson.M{"IsTrash": false, "IsDeleted": false}
if userId != "" {
q["UserId"] = bson.ObjectIdHex(userId)
}
return db.Count(db.Notes, q)
}
func (this *NoteService) CountBlog(userId string) int {
q := bson.M{"IsBlog": true, "IsTrash": false}
q := bson.M{"IsBlog": true, "IsTrash": false, "IsDeleted": false}
if userId != "" {
q["UserId"] = bson.ObjectIdHex(userId)
}

View File

@@ -85,13 +85,13 @@ func (this *ThemeService) getDefaultTheme(style string) info.Theme {
// 用户的主题路径设置
func (this *ThemeService) getUserThemeBasePath(userId string) string {
return revel.BasePath + "/public/upload/" + userId + "/themes"
return revel.BasePath + "/public/upload/" + Digest3(userId) + "/" + userId + "/themes"
}
func (this *ThemeService) getUserThemePath(userId, themeId string) string {
return this.getUserThemeBasePath(userId) + "/" + themeId
}
func (this *ThemeService) getUserThemePath2(userId, themeId string) string {
return "public/upload/" + userId + "/themes/" + themeId
return "public/upload/" + Digest3(userId) + "/" + userId + "/themes/" + themeId
}
// 新建主题
@@ -412,10 +412,18 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string)
themeIdO := bson.NewObjectId()
themeId := themeIdO.Hex()
targetPath := this.getUserThemePath(userId, themeId) // revel.BasePath + "/public/upload/" + userId + "/themes/" + themeId
err := os.MkdirAll(targetPath, 0755)
if err != nil {
msg = "error"
return
}
if ok, msg = archive.Unzip(path, targetPath); !ok {
DeleteFile(targetPath)
Log("oh no")
return
}
// 主题验证
if ok, msg = this.ValidateTheme(targetPath, "", ""); !ok {
DeleteFile(targetPath)

View File

@@ -69,6 +69,13 @@ func (this *UserService) GetUsername(userId string) string {
return user.Username
}
// 得到用户名
func (this *UserService) GetUsernameById(userId bson.ObjectId) string {
user := info.User{}
db.GetByQWithFields(db.Users, bson.M{"_id": userId}, []string{"Username"}, &user)
return user.Username
}
// 是否存在该用户 email
func (this *UserService) IsExistsUser(email string) bool {
if this.GetUserId(email) == "" {
@@ -107,6 +114,13 @@ func (this *UserService) setUserLogo(user *info.User) {
}
}
// 仅得到用户
func (this *UserService) GetUser(userId string) info.User {
user := info.User{}
db.Get(db.Users, userId, &user)
return user
}
// 得到用户信息 userId
func (this *UserService) GetUserInfo(userId string) info.User {
user := info.User{}
@@ -202,19 +216,33 @@ func (this *UserService) MapUserAndBlogByUserIds(userIds []bson.ObjectId) map[st
return userAndBlogMap
}
// 得到用户信息+博客主页
func (this *UserService) GetUserAndBlogUrl(userId string) info.UserAndBlogUrl {
user := this.GetUserInfo(userId)
userBlog := blogService.GetUserBlog(userId)
blogUrls := blogService.GetBlogUrls(&userBlog, &user)
return info.UserAndBlogUrl{
User: user,
BlogUrl: blogUrls.IndexUrl,
PostUrl: blogUrls.PostUrl,
}
}
// 得到userAndBlog公开信息
func (this *UserService) GetUserAndBlog(userId string) info.UserAndBlog {
user := this.GetUserInfo(userId)
userBlog := blogService.GetUserBlog(userId)
return info.UserAndBlog{
UserId: user.UserId,
Username: user.Username,
Email: user.Email,
Logo: user.Logo,
UserId: user.UserId,
Username: user.Username,
Email: user.Email,
Logo: user.Logo,
BlogTitle: userBlog.Title,
BlogLogo: userBlog.Logo,
BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username),
BlogUrls: blogService.GetBlogUrls(&userBlog, &user),
BlogLogo: userBlog.Logo,
BlogUrl: blogService.GetUserBlogUrl(&userBlog, user.Username),
BlogUrls: blogService.GetBlogUrls(&userBlog, &user),
}
}
@@ -362,7 +390,7 @@ func (this *UserService) UpdateEmail(token string) (ok bool, msg, email string)
tokenInfo := info.Token{}
if ok, msg, tokenInfo = tokenService.VerifyToken(token, info.TokenUpdateEmail); ok {
// 修改之后的邮箱
email = tokenInfo.Email
email = strings.ToLower(tokenInfo.Email)
// 先验证该email是否被注册了
if userService.IsExistsUser(email) {
ok = false

View File

@@ -90,7 +90,7 @@ func decodeValue(val string) string {
v, _ := url.ParseQuery("a=" + val)
return v.Get("a")
}
func encodeValue(val string) string {
if val == "" {
return val
@@ -99,16 +99,17 @@ func encodeValue(val string) string {
v.Set("", val)
return v.Encode()[1:]
}
// 添加笔记时通过title得到urlTitle
func fixUrlTitle(urlTitle string) string {
if urlTitle != "" {
// 把特殊字段给替换掉
// str := `life "%&()+,/:;<>=?@\|`
// str := `life "%&()+,/:;<>=?@\|`
reg, _ := regexp.Compile("/|#|\\$|!|\\^|\\*|'| |\"|%|&|\\(|\\)|\\+|\\,|/|:|;|<|>|=|\\?|@|\\||\\\\")
urlTitle = reg.ReplaceAllString(urlTitle, "-")
urlTitle = strings.Trim(urlTitle, "-") // 左右单独的-去掉
// 把空格替换成-
// urlTitle = strings.Replace(urlTitle, " ", "-", -1)
// urlTitle = strings.Replace(urlTitle, " ", "-", -1)
for strings.Index(urlTitle, "--") >= 0 { // 防止出现连续的--
urlTitle = strings.Replace(urlTitle, "--", "-", -1)
}
@@ -119,11 +120,20 @@ func fixUrlTitle(urlTitle string) string {
func getUniqueUrlTitle(userId string, urlTitle string, types string, padding int) string {
urlTitle2 := urlTitle
// 判断urlTitle是不是过长, 过长则截断, 300
// 不然生成index有问题
// it will not index a single field with more than 1024 bytes.
// If you're indexing a field that is 2.5MB, it's not really indexing it, it's being skipped.
if len(urlTitle2) > 320 {
urlTitle2 = urlTitle2[:300] // 为什么要少些, 因为怕无限循环, 因为把padding截了
}
if padding > 1 {
urlTitle2 = urlTitle + "-" + strconv.Itoa(padding)
}
userIdO := bson.ObjectIdHex(userId)
var collection *mgo.Collection
if types == "note" {
collection = db.Notes
@@ -136,9 +146,10 @@ func getUniqueUrlTitle(userId string, urlTitle string, types string, padding int
padding++
urlTitle2 = urlTitle + "-" + strconv.Itoa(padding)
}
return urlTitle2
}
// types == note,notebook,single
func GetUrTitle(userId string, title string, types string) string {
urlTitle := strings.Trim(title, " ")

View File

@@ -26,10 +26,10 @@
</section>
<div id="boxFooter">
<p>
<a href="/index">leanote</a> © 2014
<a href="/index">leanote</a> © 2015
</p>
</div>
</body>
</html>
{{end}}
{{end}}

View File

@@ -26,10 +26,10 @@
</section>
<div id="boxFooter">
<p>
<a href="/index">leanote</a> © 2014
<a href="/index">leanote</a> © 2015
</p>
</div>
</body>
</html>
{{end}}
{{end}}

View File

@@ -8,14 +8,16 @@
<br />
leanote@leanote.com
<br />
Copyright © 2014-2015 <a href="http://leanote.com">Leanote</a>
Copyright © 2014-2015 <a href="https://leanote.com">Leanote</a>
<br />
Powered by <a href="https://leanote.com">Leanote</a>
</div>
<div class="col-md-6">
<i class="fa fa-globe fa-3x icon-muted"></i>
<h2>Join Us</h2>
<a href="https://github.com/leanote/leanote">github leanote</a>
<a href="https://github.com/leanote/leanote">Github Leanote</a>
<br />
QQ Group: 158716820
QQ Group: 158716820, 158716820
</div>
</div>
</div>

View File

@@ -6,7 +6,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="keywords" content="leanote,leanote.com">
<meta name="description" content="Leanote, {{msg $ "moto"}}">
<meta property="qc:admins" content="2451332115167456375" />
<meta name="author" content="leanote">
<title>{{.title}}</title>
@@ -46,18 +45,18 @@ function log(o) {
<ul class="nav navbar-nav navbar-left">
<li><a href="/index#" data-target="body" class="smooth-scroll">{{msg . "home"}}</a></li>
<li style="position: relative;">
<a id="" href="http://leanote.com/service" title="" class="">{{msg . "service"}}</a>
<div class="red-circle" style=""></div>
</li>
<li style="position: relative; margin-right: 3px;">
<a href="http://bbs.leanote.com" target="_blank" class="">{{msg . "discussion"}}</a>
</li>
<li><a id="leanoteBlog" href="http://lea.leanote.com" target="_blank" title="lea++, leanote blog platform" class="">lea++</a></li>
<li><a id="leanoteBlog" href="http://lea.leanote.com" target="_blank" title="Lea++, leanote blog platform" class="">Lea++</a></li>
<li><a id="leanoteApp" href="http://app.leanote.com" target="_blank" title="Leanote App" class="">{{msg . "desktopApp"}}</a></li>
<li>
<a href="http://leanote.org#donate" target="_blank" class="">{{msg . "donate"}}</a>
</li>
<li><a href="http://leanote.org" target="_blank" title="leanote.org" class="">leanote.org</a></li>
{{if .userInfo.Email}}
<li id="loginBtns">
{{msg . "hi"}}, {{.userInfo.Username}}

View File

@@ -1,26 +1,22 @@
{{template "home/header.html" .}}
<style>
</style>
<section>
<div class="header">
<h2>leanote, {{msg . "moto"}}</h2>
<h2>Leanote, {{msg . "moto"}}</h2>
<p>{{msg . "moto3"}}</p>
<p>{{msg . "moto2"}}</p>
<div>
<a class="btn btn-primary" href="https://github.com/leanote/leanote">{{msg . "fork github"}}</a>
<a class="btn btn-default btn-primary" href="/register">{{msg . "register"}}</a>
&nbsp;
&nbsp;
<a class="btn btn-default" href="/demo">{{msg . "try"}}</a>
{{if .openRegister}}
&nbsp;
&nbsp;
OR
&nbsp;
&nbsp;
<a class="btn btn-default" href="/register">{{msg . "register"}}</a>
{{if not .userInfo.UserId}}
<a class="btn btn-default" href="/login">{{msg . "login"}}</a>
&nbsp;
&nbsp;
{{end}}
<a class="btn btn-default" href="/demo">{{msg . "try"}}</a>
</div>
</div>
@@ -29,13 +25,23 @@
<div class="img-header">
<img src="/images/home/mac-btns.png"/>
</div>
<img src="/images/home/preview2.png" style="width: 750px;" />
<div id="webSliderContainer">
<img class="web-slider" data-text="Default theme - markdown" src="/images/slider/v2/default_markdown.png"/>
<img class="web-slider hide-img" data-text="Default theme - rich editor" src="/images/slider/v2/simple_tinymce.png"/>
<img class="web-slider hide-img" data-text="Simple theme - markdown" src="/images/slider/v2/simple_markdown.png"/>
<img class="web-slider hide-img" data-text="Writting mode" src="/images/slider/v2/writting.png"/>
</div>
</div>
<div class="slider-desc"><span id="webText">Default theme - markdown</span></div>
<div class="mobile">
<div class="mobile-header">
<img src="/images/home/mac-dot.png" />
</div>
<img class="mobile-image" src="/images/home/mobile.png" />
<div id="mobileSliderContainer">
<img class="mobile-slider" data-text="Mobile" src="/images/slider/v2/mobile_simple_list.png" />
<img class="mobile-slider hide-img" data-text="Mobile markdown" src="/images/slider/v2/mobile_markdown.png" />
</div>
<div class="slider-desc mobile-text"><span id="mobileText">Default theme - markdown</span></div>
</div>
</div>
</section>
@@ -46,6 +52,10 @@
<div class="col-md-3">
<h3>{{msg . "knowledge"}}</h3>
<p>{{msg . "knowledgeInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "blog"}}</h3>
<p>{{msg . "blogInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "share"}}</h3>
@@ -55,81 +65,27 @@
<h3>{{msg . "cooperation"}}</h3>
<p>{{msg . "cooperationInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "blog"}}</h3>
<p>{{msg . "blogInfo"}}</p>
</div>
</div>
</div>
<div class="container" id="download">
<h2 style="margin: 20px 0;text-align: center;">{{msg . "download"}}</h2>
<div class="row">
<div style="width:300px; margin:auto; padding: 10px;">
Linux : <a href="https://github.com/leanote/leanote/releases/download/0.4/leanote-linux-v0.4.bin.tar.gz">leanote-linux-v0.4.bin.tar.gz</a> <br />
MacOS X : <a href="https://github.com/leanote/leanote/releases/download/0.4/leanote-mac-v0.4.bin.tar.gz">leanote-mac-v0.4.bin.tar.gz</a> <br />
<br />
<a href="https://github.com/leanote/leanote#3-how-to-install-leanote">{{msg . "howToInstallLeanote"}}</a>
</div>
</div>
</div>
<div class="container" id="donate">
<h2 style="margin: 20px 0;text-align: center;">{{msg . "donate"}}</h2>
<div class="row">
<div style="width:500px; margin:auto; padding: 10px;">
<p>
您可以通过支付宝向leanote捐赠, 所捐赠的钱将用来leanote开发.
</p>
<p>
支付宝账号: <b>pay@leanote.com</b>
</p>
<p>
或使用支付宝扫以下二维码捐赠:
</p>
<p style="text-align: center">
<img src="/images/leanote/leanote_alipay.jpg" style="padding: 10px;
border: 2px solid #eee;
border-radius: 10px;"/>
</p>
<p>
我们会定期将捐赠名单发布在 <a href="http://leanote.com/blog/view/5417ecf81a910828fd000000">捐赠列表</a>
</p>
<p>
感谢您对leanote的支持!
</p>
<hr />
<p>
有任何疑问, 建议或需其它服务或支持, 欢迎联系 <code>leanote@leanote.com</code> 或加入官方QQ群: <code>158716820</code> 谢谢!
</p>
</div>
</div>
</div>
{{template "home/footer.html"}}
<script src="/js/jquery-1.9.0.min.js"></script>
<script src="/js/bootstrap.js"></script>
<script>
var lang = '{{.locale}}';
</script>
<script src="/js/home/index.js"></script>
<script>
$(function() {
/*
var u = navigator.userAgent;
var isMobile = u.indexOf('Android')>-1 || u.indexOf('Linux')>-1;
if(isMobile || $("body").width() < 600) {
location.href = "/mobile/index";
}
*/
// 平滑滚动
$(".smooth-scroll").click(function(e) {
e.preventDefault();
var t = $(this).attr("target");
var targetOffset = $(t).offset().top - 80;
$('html,body').animate({scrollTop: targetOffset}, 300);
});
});
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?d0c988e37b452b3bf1220d45b30f2de2";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>

View File

@@ -1,138 +0,0 @@
{{template "home/header.html" .}}
<style>
</style>
<section>
<div class="header">
<h2>Leanote, {{msg . "moto"}}</h2>
<p>{{msg . "moto3"}}</p>
<p>
Knowledge, Blog, Sharing, Cooperation... all in leanote
</p>
<div>
<a class="btn btn-primary" href="https://github.com/leanote/leanote">{{msg . "fork github"}}</a>
&nbsp;
&nbsp;
<a class="btn btn-default" href="/demo">{{msg . "try"}}</a>
&nbsp;
&nbsp;
<a class="btn btn-default" href="/login">{{msg . "login"}}</a>
{{if .openRegister}}
&nbsp;
&nbsp;
<a class="btn btn-default" href="/register">{{msg . "register"}}</a>
{{end}}
</div>
</div>
<div class="preview" style="position: relative;">
<div>
<div class="img-header">
<img src="/images/home/mac-btns.png"/>
</div>
<img src="/images/home/preview2.png" style="width: 750px;" />
</div>
<div class="mobile">
<div class="mobile-header">
<img src="/images/home/mac-dot.png" />
</div>
<img class="mobile-image" src="/images/home/mobile.png" />
</div>
</div>
</section>
<div class="container" id="aboutLeanote">
<h2>{{msg . "aboutLeanote"}}</h2>
<div class="row">
<div class="col-md-3">
<h3>{{msg . "knowledge"}}</h3>
<p>{{msg . "knowledgeInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "share"}}</h3>
<p>{{msg . "shareInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "cooperation"}}</h3>
<p>{{msg . "cooperationInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "blog"}}</h3>
<p>{{msg . "blogInfo"}}</p>
</div>
</div>
</div>
<hr />
<div class="container" id="donate">
<h2 style="margin: 20px 0;text-align: center;">{{msg . "donate"}}</h2>
<div class="row">
<div style="width:500px; margin:auto; padding: 10px;">
<p>
You can use <a href="http://alipay.com">alipay</a> to donate us, The donated money will be used to develop leanote.
</p>
<p>
Alipay Account: <b>pay@leanote.com</b>
</p>
<p>
Or you can use alipay app to scan the code to donate us:
</p>
<p style="text-align: center">
<img src="/images/leanote/leanote_alipay.jpg" style="padding: 10px;
border: 2px solid #eee;
border-radius: 10px; width: 200px;"/>
</p>
<p>
The donation list will be published at <a href="http://leanote.com/blog/view/5417ecf81a910828fd000000">Donation List</a>
</p>
<p>
Thanks for your support!
</p>
<hr />
<p>
Any questions, suggestions or need more supports, you are welcomed to contact us via <code>leanote@leanote.com</code> or the QQ Group <code>158716820</code> Thanks!
</p>
</div>
</div>
</div>
{{template "home/footer.html"}}
<script src="/js/jquery-1.9.0.min.js"></script>
<script src="/js/bootstrap.js"></script>
<script>
$(function() {
/*
var u = navigator.userAgent;
var isMobile = u.indexOf('Android')>-1 || u.indexOf('Linux')>-1;
if(isMobile || $("body").width() < 600) {
location.href = "/mobile/index";
}
*/
// 平滑滚动
$(".smooth-scroll").click(function(e) {
e.preventDefault();
var t = $(this).attr("target");
var targetOffset = $(t).offset().top - 80;
$('html,body').animate({scrollTop: targetOffset}, 300);
});
function setCookie(name, value) {
var Days = 10*365;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
$('#lang a').click(function() {
var lang = $(this).data('lang');
setCookie('LEANOTE_LANG', lang);
location.reload();
});
});
</script>
</body>
</html>

View File

@@ -1,138 +0,0 @@
{{template "home/header.html" .}}
<style>
</style>
<section>
<div class="header">
<h2>Leanote, {{msg . "moto"}}</h2>
<p>{{msg . "moto3"}}</p>
<p>{{msg . "moto2"}}</p>
<div>
<a class="btn btn-primary" href="https://github.com/leanote/leanote">{{msg . "fork github"}}</a>
&nbsp;
&nbsp;
<a class="btn btn-default" href="/demo">{{msg . "try"}}</a>
&nbsp;
&nbsp;
<a class="btn btn-default" href="/login">{{msg . "login"}}</a>
{{if .openRegister}}
&nbsp;
&nbsp;
<a class="btn btn-default" href="/register">{{msg . "register"}}</a>
{{end}}
</div>
</div>
<div class="preview" style="position: relative;">
<div>
<div class="img-header">
<img src="/images/home/mac-btns.png"/>
</div>
<img src="/images/home/preview2.png" style="width: 750px;" />
</div>
<div class="mobile">
<div class="mobile-header">
<img src="/images/home/mac-dot.png" />
</div>
<img class="mobile-image" src="/images/home/mobile.png" />
</div>
</div>
</section>
<div class="container" id="aboutLeanote">
<h2>{{msg . "aboutLeanote"}}</h2>
<div class="row">
<div class="col-md-3">
<h3>{{msg . "knowledge"}}</h3>
<p>{{msg . "knowledgeInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "share"}}</h3>
<p>{{msg . "shareInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "cooperation"}}</h3>
<p>{{msg . "cooperationInfo"}}</p>
</div>
<div class="col-md-3">
<h3>{{msg . "blog"}}</h3>
<p>{{msg . "blogInfo"}}</p>
</div>
</div>
</div>
<hr />
<div class="container" id="donate">
<h2 style="margin: 20px 0;text-align: center;">{{msg . "donate"}}</h2>
<div class="row">
<div style="width:500px; margin:auto; padding: 10px;">
<p>
您可以通过<a href="http://alipay.com">支付宝</a>向leanote捐赠, 所捐赠的款项将用于开发leanote.
</p>
<p>
支付宝账号: <b>pay@leanote.com</b>
</p>
<p>
或使用支付宝扫以下二维码捐赠:
</p>
<p style="text-align: center">
<img src="/images/leanote/leanote_alipay.jpg" style="padding: 10px;
border: 2px solid #eee;
border-radius: 10px; width: 200px;"/>
</p>
<p>
我们会定期将捐赠名单发布在 <a href="http://leanote.com/blog/view/5417ecf81a910828fd000000">捐赠列表</a>
</p>
<p>
感谢您对leanote的支持!
</p>
<hr />
<p>
有任何疑问, 建议或需其它服务或支持, 欢迎联系 <code>leanote@leanote.com</code> 或加入官方QQ群: <code>158716820</code> 谢谢!
</p>
</div>
</div>
</div>
{{template "home/footer.html"}}
<script src="/js/jquery-1.9.0.min.js"></script>
<script src="/js/bootstrap.js"></script>
<script>
$(function() {
/*
var u = navigator.userAgent;
var isMobile = u.indexOf('Android')>-1 || u.indexOf('Linux')>-1;
if(isMobile || $("body").width() < 600) {
location.href = "/mobile/index";
}
*/
// 平滑滚动
$(".smooth-scroll").click(function(e) {
e.preventDefault();
var t = $(this).attr("target");
var targetOffset = $(t).offset().top - 80;
$('html,body').animate({scrollTop: targetOffset}, 300);
});
function setCookie(name, value) {
var Days = 10*365;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
$('#lang a').click(function() {
var lang = $(this).data('lang');
setCookie('LEANOTE_LANG', lang);
location.reload();
});
});
</script>
</body>
</html>

View File

@@ -72,7 +72,7 @@ $(function() {
showMsg("{{msg . "inputEmail"}}", "email");
return;
} else {
var myreg = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[0-9a-zA-Z]{2,3}$/;
var myreg = /^([a-zA-Z0-9]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-_]+@([a-zA-Z0-9\-]+[_|\_|\.|\-]?)*[a-zA-Z0-9\-]+\.[0-9a-zA-Z]{2,6}$/;
if(!myreg.test(email)) {
showMsg("{{msg . "wrongEmail"}}", "email");
return;
@@ -117,4 +117,4 @@ $(function() {
});
</script>
</body>
</html>
</html>

View File

@@ -13,11 +13,15 @@
<span class="label label-green">{{msg . "verified"}}</span>
{{else}}
<span class="label label-red">{{msg . "unVerified"}}</span>
<a class="raw nowToActive">{{msg . "verifiedNow"}}</a>
<a class="a raw nowToActive">{{msg . "verifiedNow"}}</a>
{{msg . "or"}}
<a class="raw reSendActiveEmail">{{msg . "resendVerifiedEmail"}}</a>
<a class="a raw reSendActiveEmail">{{msg . "resendVerifiedEmail"}}</a>
{{end}}
<!--
<hr />
<div class="alert alert-danger" id="emailMsg" style="display: none"></div>
<div class="form-group">
<label>{{msg . "email"}}</label>
@@ -29,12 +33,28 @@
]'
data-msg_target="#emailMsg"
/>
{{msg . "updateEmailTips"}}
<div class="form-tips">{{msg . "updateEmailTips"}}</div>
</div>
<div class="form-group">
<label class="control-label" for="pwd">{{msg . "password"}}</label>
<input type="password" class="form-control" id="pwd" name="pwd"
data-rules='[
{rule: "required", msg: "inputPassword"},
{rule: "password", msg: "errorPassword"}
]'
data-msg_target="#emailMsg"
>
<div class="form-tips">{{msg . "inputLoginPasswordTips"}}</div>
</div>
-->
</div>
<!--
<footer class="panel-footer text-right bg-light lter">
<button type="submit" id="emailBtn" class="btn btn-success">{{msg . "submit"}}</button>
</footer>
-->
</section>
</form>
</div>
@@ -76,7 +96,8 @@ $("#emailBtn").click(function(e) {
return;
}
var email = $("#email").val();
post("/user/updateEmailSendActiveEmail", {email: email}, function(e) {
var pwd = $("#pwd").val();
post("/user/updateEmailSendActiveEmail", {email: email, pwd: pwd}, function(e) {
if(e.Ok) {
var url = getEmailLoginAddress(email);
showAlert("#emailMsg", getMsg("verifiedEmaiHasSent") +" <a href='" + url + "' target='_blank'>" + getMsg("checkEmail") + "</a>", "success");

View File

@@ -24,7 +24,7 @@
]'
data-msg_target="#pwdMsg"
>
{{msg . "passwordTips"}}
<div class="form-tips">{{msg . "passwordTips"}}</div>
</div>
<div class="form-group">
<label class="control-label" for="pwd2">{{msg . "password2"}}</label>

View File

@@ -10,23 +10,23 @@
<meta name="description" content="Leanote, {{msg $ "moto"}}">
<title>Leanote, {{msg $ "moto"}}</title>
<link href="/css/bootstrap.css" rel="stylesheet" />
<link href="/css/bootstrap-min.css" rel="stylesheet" />
<!-- 先加载, 没有样式, 宽度不定 -->
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
<!-- leanote css -->
<link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
<link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
<link href="/css/font-awesome-4.2.0/css/font-awesome-min.css" rel="stylesheet" />
<link href="/css/zTreeStyle/zTreeStyle-min.css" rel="stylesheet" />
<!-- mdeditor -->
<link href="/public/dist/themes/default.css" rel="stylesheet" />
<link href="/public/dist/themes/default-min.css" rel="stylesheet" />
<!-- context-menu -->
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu-min.css" type="text/css" />
<script>
var hash = location.hash;
if(hash.indexOf("writing") >= 0) {
var files = '<link rel="stylesheet" href="/css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
} else {
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css?t=3" type="text/css" id="themeLink" />';
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css?t=4" type="text/css" id="themeLink" />';
}
document.write(files);
</script>
@@ -160,7 +160,7 @@ function log(o) {
</li>
<li role="presentation" class="my-link" >
<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}">
<a target="_blank" href="{{$.userInfo.BlogUrl}}">
<i class="fa fa-bold"></i>
{{msg . "myBlog"}}</a>
</li>
@@ -475,34 +475,36 @@ function log(o) {
</div>
<ul class="pull-right" id="editorTool">
<li><a class="ios7-a " id="saveBtn" title="ctrl+s"
data-toggle="dropdown">
<span class="fa fa-save"></span>
{{msg . "save"}}</a></li>
<li><a class="ios7-a " id="saveBtn"
data-toggle="dropdown" title="ctrl+s {{msg . "save"}}">
<span class="fa fa-save"></span></a></li>
<li class="dropdown" id="noteInfoDropdown">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach" title="{{msg . "Information"}}">
<span class="fa fa-info"></span>
</a>
<div class="dropdown-menu" id="noteInfo"></div>
</li>
<li class="dropdown" id="attachDropdown">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach" title="{{msg . "attachments"}}">
<span class="fa fa-paperclip"></span>
{{msg . "attachments"}}<span id="attachNum"></span>
<span id="attachNum"></span>
</a>
<div class="dropdown-menu" id="attachMenu">
<ul id="attachList">
</ul>
<form id="uploadAttach" method="post" action="/attach/UploadAttach" enctype="multipart/form-data">
<div id="dropAttach" class="dropzone">
<a class="btn btn-success btn-choose-file">
<i class="fa fa-upload"></i>
<span>Choose File</span>
<span>{{msg . "Choose File"}}</span>
</a>
<a class="btn btn-default" id="downloadAllBtn">
<i class="fa fa-download"></i>
<span>Download All</span>
</a>
<a class="btn btn-default" id="linkAllBtn">
<i class="fa fa-link"></i>
<span>Link All</span>
<span>{{msg . "Download All"}}</span>
</a>
<input type="file" name="file" multiple/>
</div>
<div id="attachUploadMsg">
@@ -511,14 +513,12 @@ function log(o) {
</div>
</li>
<li><a class="ios7-a " id="tipsBtn"
data-toggle="dropdown">
<span class="fa fa-question"></span>
{{msg . "editorTips"}}</a></li>
<li><a class="ios7-a " id="contentHistory"
data-toggle="dropdown">
<span class="fa fa-history"></span>
{{msg . "history"}}</a></li>
data-toggle="dropdown" title="{{msg . "history"}}">
<span class="fa fa-history"></span></a></li>
<li><a class="ios7-a " id="tipsBtn"
data-toggle="dropdown" title="{{msg . "editorTips"}}">
<span class="fa fa-question"></span></a></li>
</ul>
</div>
@@ -530,7 +530,7 @@ function log(o) {
<div id="noteReadTop">
<h2 id="noteReadTitle"></h2>
<div class="clearfix" id="noteReadInfo">
<i class="fa fa-bookmark-o"></i>
<i class="fa fa-bookmark-o"></i>
<span id="noteReadTags"></span>
<!-- 修改时间 -->
@@ -538,7 +538,7 @@ function log(o) {
<span id="noteReadUpdatedTime"></span>
<!-- 修改时间 -->
<i class="fa fa-clock-o"></i> {{msg . "create"}}
<i class="fa fa-clock-o"></i> {{msg . "create"}}
<span id="noteReadCreatedTime"></span>
</div>
</div>
@@ -857,24 +857,7 @@ function log(o) {
</div><!-- /.modal -->
<!-- 编辑器提示 -->
<div class="modal fade bs-modal-sm" id="tipsDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" class="modalTitle">{{msg . "editorTips"}}</h4>
</div>
<div class="modal-body">
{{msg . "editorTipsInfo"}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{msg . "close"}}</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- modal 静态区域 -->
<div class="display: hidden">
@@ -946,7 +929,7 @@ window.require = {
<script src="/public/dist/main.min.js"></script>
<!-- /dev -->
<script src="/public/js/upload_paste/main.js"></script>
<script src="/public/js/plugins/main.js"></script>
</body>
</html>
</html>

View File

@@ -10,23 +10,23 @@
<meta name="description" content="Leanote, {{msg $ "moto"}}">
<title>Leanote, {{msg $ "moto"}}</title>
<link href="/css/bootstrap.css" rel="stylesheet" />
<link href="/css/bootstrap-min.css" rel="stylesheet" />
<!-- 先加载, 没有样式, 宽度不定 -->
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
<!-- leanote css -->
<link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
<link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
<link href="/css/font-awesome-4.2.0/css/font-awesome-min.css" rel="stylesheet" />
<link href="/css/zTreeStyle/zTreeStyle-min.css" rel="stylesheet" />
<!-- mdeditor -->
<link href="/public/dist/themes/default.css" rel="stylesheet" />
<link href="/public/dist/themes/default-min.css" rel="stylesheet" />
<!-- context-menu -->
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu-min.css" type="text/css" />
<script>
var hash = location.hash;
if(hash.indexOf("writing") >= 0) {
var files = '<link rel="stylesheet" href="/css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
} else {
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css?t=3" type="text/css" id="themeLink" />';
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css?t=4" type="text/css" id="themeLink" />';
}
document.write(files);
</script>
@@ -160,7 +160,7 @@ function log(o) {
</li>
<li role="presentation" class="my-link" >
<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}">
<a target="_blank" href="{{$.userInfo.BlogUrl}}">
<i class="fa fa-bold"></i>
{{msg . "myBlog"}}</a>
</li>
@@ -475,34 +475,36 @@ function log(o) {
</div>
<ul class="pull-right" id="editorTool">
<li><a class="ios7-a " id="saveBtn" title="ctrl+s"
data-toggle="dropdown">
<span class="fa fa-save"></span>
{{msg . "save"}}</a></li>
<li><a class="ios7-a " id="saveBtn"
data-toggle="dropdown" title="ctrl+s {{msg . "save"}}">
<span class="fa fa-save"></span></a></li>
<li class="dropdown" id="noteInfoDropdown">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach" title="{{msg . "Information"}}">
<span class="fa fa-info"></span>
</a>
<div class="dropdown-menu" id="noteInfo"></div>
</li>
<li class="dropdown" id="attachDropdown">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach">
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach" title="{{msg . "attachments"}}">
<span class="fa fa-paperclip"></span>
{{msg . "attachments"}}<span id="attachNum"></span>
<span id="attachNum"></span>
</a>
<div class="dropdown-menu" id="attachMenu">
<ul id="attachList">
</ul>
<form id="uploadAttach" method="post" action="/attach/UploadAttach" enctype="multipart/form-data">
<div id="dropAttach" class="dropzone">
<a class="btn btn-success btn-choose-file">
<i class="fa fa-upload"></i>
<span>Choose File</span>
<span>{{msg . "Choose File"}}</span>
</a>
<a class="btn btn-default" id="downloadAllBtn">
<i class="fa fa-download"></i>
<span>Download All</span>
</a>
<a class="btn btn-default" id="linkAllBtn">
<i class="fa fa-link"></i>
<span>Link All</span>
<span>{{msg . "Download All"}}</span>
</a>
<input type="file" name="file" multiple/>
</div>
<div id="attachUploadMsg">
@@ -511,14 +513,12 @@ function log(o) {
</div>
</li>
<li><a class="ios7-a " id="tipsBtn"
data-toggle="dropdown">
<span class="fa fa-question"></span>
{{msg . "editorTips"}}</a></li>
<li><a class="ios7-a " id="contentHistory"
data-toggle="dropdown">
<span class="fa fa-history"></span>
{{msg . "history"}}</a></li>
data-toggle="dropdown" title="{{msg . "history"}}">
<span class="fa fa-history"></span></a></li>
<li><a class="ios7-a " id="tipsBtn"
data-toggle="dropdown" title="{{msg . "editorTips"}}">
<span class="fa fa-question"></span></a></li>
</ul>
</div>
@@ -530,7 +530,7 @@ function log(o) {
<div id="noteReadTop">
<h2 id="noteReadTitle"></h2>
<div class="clearfix" id="noteReadInfo">
<i class="fa fa-bookmark-o"></i>
<i class="fa fa-bookmark-o"></i>
<span id="noteReadTags"></span>
<!-- 修改时间 -->
@@ -538,7 +538,7 @@ function log(o) {
<span id="noteReadUpdatedTime"></span>
<!-- 修改时间 -->
<i class="fa fa-clock-o"></i> {{msg . "create"}}
<i class="fa fa-clock-o"></i> {{msg . "create"}}
<span id="noteReadCreatedTime"></span>
</div>
</div>
@@ -857,24 +857,7 @@ function log(o) {
</div><!-- /.modal -->
<!-- 编辑器提示 -->
<div class="modal fade bs-modal-sm" id="tipsDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" class="modalTitle">{{msg . "editorTips"}}</h4>
</div>
<div class="modal-body">
{{msg . "editorTipsInfo"}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{msg . "close"}}</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- modal 静态区域 -->
<div class="display: hidden">
@@ -928,7 +911,7 @@ window.require = {
<script src="/public/js/upload_paste/main.js"></script>
<script src="/public/js/plugins/main.min.js"></script>
</body>
</html>
</html>

View File

@@ -53,6 +53,7 @@ inputEmail=Email is required
wrongEmail=Wrong email
wrongUsernameOrPassword=Wrong username or password
inputPassword=Password is required
inputLoginPasswordTips=Please input login password
wrongPassword=Wrong password
logining=Sign in
loginSuccess=login success
@@ -101,7 +102,7 @@ clearSearch=Clear Search
all=Newest
trash=Trash
delete=Delete
unTitled=Untitled
unTitled=UnTitled
defaultShare=Default sharing
leftHidden=Hidden slide bar
leftShow=Show slide bar
@@ -112,6 +113,9 @@ saving=Saving
saveSuccess=Save success
SearchNote=Search Note
SearchNotebook=Search Notebook
Choose File=Choose File
Download All=Download All
Information=Information
update=Update
create=Create
@@ -213,8 +217,6 @@ inviteEmailBody=Hi,I am %s, %s is awesome, come on!
# 历史记录
historiesNum=We have saved at most <b>10</b> latest histories with each note
noHistories=No histories
fold=Fold
unfold=Unfold
datetime=Datetime
restoreFromThisVersion=Restore from this version
confirmBackup=Are you sure to restore from this version? We will backup the current note.
@@ -252,6 +254,7 @@ themeValidHasRoundInclude=WARNING: Templates have circular references!
memberCenter=Member Center
userNotExists=The user is not exists
hasUsers=The user already exists
Leanote Blog Theme Api=Leanote Blog Theme Api
# yu
service=Service

View File

@@ -43,19 +43,20 @@ curUser=Email
# form
submit=提交
Submit=提交
register=Sign up
login=Sign in
register=注册
login=登录
Password=密码
password2=Confirm your password
password2=请确认密码
email=Email
inputUsername=Username(email) is required
inputEmail=Email is required
wrongEmail=Wrong email
wrongUsernameOrPassword=Wrong username or password
inputPassword=Password is required
wrongPassword=Wrong password
logining=Sign in
loginSuccess=login success
inputUsername=请输入用户名或Email
inputEmail=请输入Email
wrongEmail=Email错误
wrongUsernameOrPassword=用户名或密码错误
inputPassword=请输入密码
inputLoginPasswordTips=请输入登录密码
wrongPassword=密码错误
logining=登录
loginSuccess=登录成功
hi=Hi
welcomeUseLeanote=欢迎使用leanote
@@ -133,6 +134,13 @@ saving=正在保存
saveSuccess=保存成功
SearchNote=搜索笔记
SearchNotebook=搜索笔记本
Choose File=选择文件
Download All=下载全部
Information=信息
Are you sure to delete it ?=确认删除?
Insert link into content=将附件链接插入到内容中
Download=下载
Delete=删除
update=更新
create=创建
@@ -238,8 +246,6 @@ inviteEmailBody=Hi, 你好, 我是%s, %s非常好用, 快来注册吧!
# 历史记录
historiesNum=leanote会保存笔记的最近<b>10</b>份历史记录
noHistories=无历史记录
fold=折叠
unfold=展开
datetime=日期
restoreFromThisVersion=从该版本还原
confirmBackup=确定要从该版还原? 还原前leanote会备份当前版本到历史记录中.
@@ -278,6 +284,7 @@ themeValidHasRoundInclude=警告: 模板存在循环引用问题!
memberCenter=个人中心
userNotExists=该成员沿未注册
hasUsers=已存在该成员
Leanote Blog Theme Api=Leanote博客主题API
# yu
service=服务

7
public/css/bootstrap-min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
// Bordered & Pulled
// -------------------------
.#{$fa-css-prefix}-border {
padding: .2em .25em .15em;
border: solid .08em $fa-border-color;
border-radius: .1em;
}
.pull-right { float: right; }
.pull-left { float: left; }
.#{$fa-css-prefix} {
&.pull-left { margin-right: .3em; }
&.pull-right { margin-left: .3em; }
}

View File

@@ -0,0 +1,11 @@
// Base Class Definition
// -------------------------
.#{$fa-css-prefix} {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
font-size: inherit; // can't have font-size inherit on line above, so need to override
text-rendering: auto; // optimizelegibility throws things off #1094
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -0,0 +1,6 @@
// Fixed Width Icons
// -------------------------
.#{$fa-css-prefix}-fw {
width: (18em / 14);
text-align: center;
}

View File

@@ -0,0 +1,552 @@
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
.#{$fa-css-prefix}-music:before { content: $fa-var-music; }
.#{$fa-css-prefix}-search:before { content: $fa-var-search; }
.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; }
.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; }
.#{$fa-css-prefix}-star:before { content: $fa-var-star; }
.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; }
.#{$fa-css-prefix}-user:before { content: $fa-var-user; }
.#{$fa-css-prefix}-film:before { content: $fa-var-film; }
.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; }
.#{$fa-css-prefix}-th:before { content: $fa-var-th; }
.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; }
.#{$fa-css-prefix}-check:before { content: $fa-var-check; }
.#{$fa-css-prefix}-remove:before,
.#{$fa-css-prefix}-close:before,
.#{$fa-css-prefix}-times:before { content: $fa-var-times; }
.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; }
.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; }
.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; }
.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; }
.#{$fa-css-prefix}-gear:before,
.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; }
.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; }
.#{$fa-css-prefix}-home:before { content: $fa-var-home; }
.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; }
.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; }
.#{$fa-css-prefix}-road:before { content: $fa-var-road; }
.#{$fa-css-prefix}-download:before { content: $fa-var-download; }
.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; }
.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; }
.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; }
.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; }
.#{$fa-css-prefix}-rotate-right:before,
.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; }
.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; }
.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; }
.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; }
.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; }
.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; }
.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; }
.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; }
.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; }
.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; }
.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; }
.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; }
.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; }
.#{$fa-css-prefix}-book:before { content: $fa-var-book; }
.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; }
.#{$fa-css-prefix}-print:before { content: $fa-var-print; }
.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; }
.#{$fa-css-prefix}-font:before { content: $fa-var-font; }
.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; }
.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; }
.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; }
.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; }
.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; }
.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; }
.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; }
.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; }
.#{$fa-css-prefix}-list:before { content: $fa-var-list; }
.#{$fa-css-prefix}-dedent:before,
.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; }
.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; }
.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; }
.#{$fa-css-prefix}-photo:before,
.#{$fa-css-prefix}-image:before,
.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; }
.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; }
.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; }
.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; }
.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; }
.#{$fa-css-prefix}-edit:before,
.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; }
.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; }
.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; }
.#{$fa-css-prefix}-arrows:before { content: $fa-var-arrows; }
.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; }
.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; }
.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; }
.#{$fa-css-prefix}-play:before { content: $fa-var-play; }
.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; }
.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; }
.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; }
.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; }
.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; }
.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; }
.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; }
.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; }
.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; }
.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; }
.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; }
.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; }
.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; }
.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; }
.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; }
.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; }
.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; }
.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; }
.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; }
.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; }
.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; }
.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; }
.#{$fa-css-prefix}-mail-forward:before,
.#{$fa-css-prefix}-share:before { content: $fa-var-share; }
.#{$fa-css-prefix}-expand:before { content: $fa-var-expand; }
.#{$fa-css-prefix}-compress:before { content: $fa-var-compress; }
.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; }
.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; }
.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; }
.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; }
.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; }
.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; }
.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; }
.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; }
.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; }
.#{$fa-css-prefix}-warning:before,
.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; }
.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; }
.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; }
.#{$fa-css-prefix}-random:before { content: $fa-var-random; }
.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; }
.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; }
.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; }
.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; }
.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; }
.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; }
.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; }
.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; }
.#{$fa-css-prefix}-arrows-v:before { content: $fa-var-arrows-v; }
.#{$fa-css-prefix}-arrows-h:before { content: $fa-var-arrows-h; }
.#{$fa-css-prefix}-bar-chart-o:before,
.#{$fa-css-prefix}-bar-chart:before { content: $fa-var-bar-chart; }
.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; }
.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; }
.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; }
.#{$fa-css-prefix}-key:before { content: $fa-var-key; }
.#{$fa-css-prefix}-gears:before,
.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; }
.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; }
.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; }
.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; }
.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; }
.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; }
.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; }
.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; }
.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; }
.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; }
.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; }
.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; }
.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; }
.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; }
.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; }
.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; }
.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; }
.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; }
.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; }
.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; }
.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; }
.#{$fa-css-prefix}-github:before { content: $fa-var-github; }
.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; }
.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; }
.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; }
.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; }
.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; }
.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; }
.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; }
.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; }
.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; }
.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; }
.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; }
.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; }
.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; }
.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; }
.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; }
.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; }
.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; }
.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; }
.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; }
.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; }
.#{$fa-css-prefix}-arrows-alt:before { content: $fa-var-arrows-alt; }
.#{$fa-css-prefix}-group:before,
.#{$fa-css-prefix}-users:before { content: $fa-var-users; }
.#{$fa-css-prefix}-chain:before,
.#{$fa-css-prefix}-link:before { content: $fa-var-link; }
.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; }
.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; }
.#{$fa-css-prefix}-cut:before,
.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; }
.#{$fa-css-prefix}-copy:before,
.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; }
.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; }
.#{$fa-css-prefix}-save:before,
.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; }
.#{$fa-css-prefix}-square:before { content: $fa-var-square; }
.#{$fa-css-prefix}-navicon:before,
.#{$fa-css-prefix}-reorder:before,
.#{$fa-css-prefix}-bars:before { content: $fa-var-bars; }
.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; }
.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; }
.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; }
.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; }
.#{$fa-css-prefix}-table:before { content: $fa-var-table; }
.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; }
.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; }
.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; }
.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; }
.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; }
.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; }
.#{$fa-css-prefix}-money:before { content: $fa-var-money; }
.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; }
.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; }
.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; }
.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; }
.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; }
.#{$fa-css-prefix}-unsorted:before,
.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; }
.#{$fa-css-prefix}-sort-down:before,
.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; }
.#{$fa-css-prefix}-sort-up:before,
.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; }
.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; }
.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; }
.#{$fa-css-prefix}-rotate-left:before,
.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; }
.#{$fa-css-prefix}-legal:before,
.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; }
.#{$fa-css-prefix}-dashboard:before,
.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; }
.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; }
.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; }
.#{$fa-css-prefix}-flash:before,
.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; }
.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; }
.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; }
.#{$fa-css-prefix}-paste:before,
.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; }
.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; }
.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; }
.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; }
.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; }
.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; }
.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; }
.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; }
.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; }
.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; }
.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; }
.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; }
.#{$fa-css-prefix}-building-o:before { content: $fa-var-building-o; }
.#{$fa-css-prefix}-hospital-o:before { content: $fa-var-hospital-o; }
.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; }
.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; }
.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; }
.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; }
.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; }
.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; }
.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; }
.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; }
.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; }
.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; }
.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; }
.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; }
.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; }
.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; }
.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; }
.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; }
.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; }
.#{$fa-css-prefix}-mobile-phone:before,
.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; }
.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; }
.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; }
.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; }
.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; }
.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; }
.#{$fa-css-prefix}-mail-reply:before,
.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; }
.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; }
.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; }
.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; }
.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; }
.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; }
.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; }
.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; }
.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; }
.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; }
.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; }
.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; }
.#{$fa-css-prefix}-code:before { content: $fa-var-code; }
.#{$fa-css-prefix}-mail-reply-all:before,
.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; }
.#{$fa-css-prefix}-star-half-empty:before,
.#{$fa-css-prefix}-star-half-full:before,
.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; }
.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; }
.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; }
.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; }
.#{$fa-css-prefix}-unlink:before,
.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; }
.#{$fa-css-prefix}-question:before { content: $fa-var-question; }
.#{$fa-css-prefix}-info:before { content: $fa-var-info; }
.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; }
.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; }
.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; }
.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; }
.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; }
.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; }
.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; }
.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; }
.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; }
.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; }
.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; }
.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; }
.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; }
.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; }
.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; }
.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; }
.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; }
.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; }
.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; }
.#{$fa-css-prefix}-unlock-alt:before { content: $fa-var-unlock-alt; }
.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; }
.#{$fa-css-prefix}-ellipsis-h:before { content: $fa-var-ellipsis-h; }
.#{$fa-css-prefix}-ellipsis-v:before { content: $fa-var-ellipsis-v; }
.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; }
.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; }
.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; }
.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; }
.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; }
.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; }
.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; }
.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; }
.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; }
.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; }
.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; }
.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; }
.#{$fa-css-prefix}-toggle-down:before,
.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; }
.#{$fa-css-prefix}-toggle-up:before,
.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; }
.#{$fa-css-prefix}-toggle-right:before,
.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; }
.#{$fa-css-prefix}-euro:before,
.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; }
.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; }
.#{$fa-css-prefix}-dollar:before,
.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; }
.#{$fa-css-prefix}-rupee:before,
.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; }
.#{$fa-css-prefix}-cny:before,
.#{$fa-css-prefix}-rmb:before,
.#{$fa-css-prefix}-yen:before,
.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; }
.#{$fa-css-prefix}-ruble:before,
.#{$fa-css-prefix}-rouble:before,
.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; }
.#{$fa-css-prefix}-won:before,
.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; }
.#{$fa-css-prefix}-bitcoin:before,
.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; }
.#{$fa-css-prefix}-file:before { content: $fa-var-file; }
.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; }
.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; }
.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; }
.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; }
.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; }
.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; }
.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; }
.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; }
.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; }
.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; }
.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; }
.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; }
.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; }
.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; }
.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; }
.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; }
.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; }
.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; }
.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; }
.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; }
.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; }
.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; }
.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; }
.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; }
.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; }
.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; }
.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; }
.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; }
.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; }
.#{$fa-css-prefix}-android:before { content: $fa-var-android; }
.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; }
.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; }
.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; }
.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; }
.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; }
.#{$fa-css-prefix}-female:before { content: $fa-var-female; }
.#{$fa-css-prefix}-male:before { content: $fa-var-male; }
.#{$fa-css-prefix}-gittip:before { content: $fa-var-gittip; }
.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; }
.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; }
.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; }
.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; }
.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; }
.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; }
.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; }
.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; }
.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; }
.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; }
.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; }
.#{$fa-css-prefix}-toggle-left:before,
.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; }
.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; }
.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; }
.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; }
.#{$fa-css-prefix}-turkish-lira:before,
.#{$fa-css-prefix}-try:before { content: $fa-var-try; }
.#{$fa-css-prefix}-plus-square-o:before { content: $fa-var-plus-square-o; }
.#{$fa-css-prefix}-space-shuttle:before { content: $fa-var-space-shuttle; }
.#{$fa-css-prefix}-slack:before { content: $fa-var-slack; }
.#{$fa-css-prefix}-envelope-square:before { content: $fa-var-envelope-square; }
.#{$fa-css-prefix}-wordpress:before { content: $fa-var-wordpress; }
.#{$fa-css-prefix}-openid:before { content: $fa-var-openid; }
.#{$fa-css-prefix}-institution:before,
.#{$fa-css-prefix}-bank:before,
.#{$fa-css-prefix}-university:before { content: $fa-var-university; }
.#{$fa-css-prefix}-mortar-board:before,
.#{$fa-css-prefix}-graduation-cap:before { content: $fa-var-graduation-cap; }
.#{$fa-css-prefix}-yahoo:before { content: $fa-var-yahoo; }
.#{$fa-css-prefix}-google:before { content: $fa-var-google; }
.#{$fa-css-prefix}-reddit:before { content: $fa-var-reddit; }
.#{$fa-css-prefix}-reddit-square:before { content: $fa-var-reddit-square; }
.#{$fa-css-prefix}-stumbleupon-circle:before { content: $fa-var-stumbleupon-circle; }
.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; }
.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; }
.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; }
.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; }
.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; }
.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; }
.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; }
.#{$fa-css-prefix}-language:before { content: $fa-var-language; }
.#{$fa-css-prefix}-fax:before { content: $fa-var-fax; }
.#{$fa-css-prefix}-building:before { content: $fa-var-building; }
.#{$fa-css-prefix}-child:before { content: $fa-var-child; }
.#{$fa-css-prefix}-paw:before { content: $fa-var-paw; }
.#{$fa-css-prefix}-spoon:before { content: $fa-var-spoon; }
.#{$fa-css-prefix}-cube:before { content: $fa-var-cube; }
.#{$fa-css-prefix}-cubes:before { content: $fa-var-cubes; }
.#{$fa-css-prefix}-behance:before { content: $fa-var-behance; }
.#{$fa-css-prefix}-behance-square:before { content: $fa-var-behance-square; }
.#{$fa-css-prefix}-steam:before { content: $fa-var-steam; }
.#{$fa-css-prefix}-steam-square:before { content: $fa-var-steam-square; }
.#{$fa-css-prefix}-recycle:before { content: $fa-var-recycle; }
.#{$fa-css-prefix}-automobile:before,
.#{$fa-css-prefix}-car:before { content: $fa-var-car; }
.#{$fa-css-prefix}-cab:before,
.#{$fa-css-prefix}-taxi:before { content: $fa-var-taxi; }
.#{$fa-css-prefix}-tree:before { content: $fa-var-tree; }
.#{$fa-css-prefix}-spotify:before { content: $fa-var-spotify; }
.#{$fa-css-prefix}-deviantart:before { content: $fa-var-deviantart; }
.#{$fa-css-prefix}-soundcloud:before { content: $fa-var-soundcloud; }
.#{$fa-css-prefix}-database:before { content: $fa-var-database; }
.#{$fa-css-prefix}-file-pdf-o:before { content: $fa-var-file-pdf-o; }
.#{$fa-css-prefix}-file-word-o:before { content: $fa-var-file-word-o; }
.#{$fa-css-prefix}-file-excel-o:before { content: $fa-var-file-excel-o; }
.#{$fa-css-prefix}-file-powerpoint-o:before { content: $fa-var-file-powerpoint-o; }
.#{$fa-css-prefix}-file-photo-o:before,
.#{$fa-css-prefix}-file-picture-o:before,
.#{$fa-css-prefix}-file-image-o:before { content: $fa-var-file-image-o; }
.#{$fa-css-prefix}-file-zip-o:before,
.#{$fa-css-prefix}-file-archive-o:before { content: $fa-var-file-archive-o; }
.#{$fa-css-prefix}-file-sound-o:before,
.#{$fa-css-prefix}-file-audio-o:before { content: $fa-var-file-audio-o; }
.#{$fa-css-prefix}-file-movie-o:before,
.#{$fa-css-prefix}-file-video-o:before { content: $fa-var-file-video-o; }
.#{$fa-css-prefix}-file-code-o:before { content: $fa-var-file-code-o; }
.#{$fa-css-prefix}-vine:before { content: $fa-var-vine; }
.#{$fa-css-prefix}-codepen:before { content: $fa-var-codepen; }
.#{$fa-css-prefix}-jsfiddle:before { content: $fa-var-jsfiddle; }
.#{$fa-css-prefix}-life-bouy:before,
.#{$fa-css-prefix}-life-buoy:before,
.#{$fa-css-prefix}-life-saver:before,
.#{$fa-css-prefix}-support:before,
.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; }
.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; }
.#{$fa-css-prefix}-ra:before,
.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; }
.#{$fa-css-prefix}-ge:before,
.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; }
.#{$fa-css-prefix}-git-square:before { content: $fa-var-git-square; }
.#{$fa-css-prefix}-git:before { content: $fa-var-git; }
.#{$fa-css-prefix}-hacker-news:before { content: $fa-var-hacker-news; }
.#{$fa-css-prefix}-tencent-weibo:before { content: $fa-var-tencent-weibo; }
.#{$fa-css-prefix}-qq:before { content: $fa-var-qq; }
.#{$fa-css-prefix}-wechat:before,
.#{$fa-css-prefix}-weixin:before { content: $fa-var-weixin; }
.#{$fa-css-prefix}-send:before,
.#{$fa-css-prefix}-paper-plane:before { content: $fa-var-paper-plane; }
.#{$fa-css-prefix}-send-o:before,
.#{$fa-css-prefix}-paper-plane-o:before { content: $fa-var-paper-plane-o; }
.#{$fa-css-prefix}-history:before { content: $fa-var-history; }
.#{$fa-css-prefix}-circle-thin:before { content: $fa-var-circle-thin; }
.#{$fa-css-prefix}-header:before { content: $fa-var-header; }
.#{$fa-css-prefix}-paragraph:before { content: $fa-var-paragraph; }
.#{$fa-css-prefix}-sliders:before { content: $fa-var-sliders; }
.#{$fa-css-prefix}-share-alt:before { content: $fa-var-share-alt; }
.#{$fa-css-prefix}-share-alt-square:before { content: $fa-var-share-alt-square; }
.#{$fa-css-prefix}-bomb:before { content: $fa-var-bomb; }
.#{$fa-css-prefix}-soccer-ball-o:before,
.#{$fa-css-prefix}-futbol-o:before { content: $fa-var-futbol-o; }
.#{$fa-css-prefix}-tty:before { content: $fa-var-tty; }
.#{$fa-css-prefix}-binoculars:before { content: $fa-var-binoculars; }
.#{$fa-css-prefix}-plug:before { content: $fa-var-plug; }
.#{$fa-css-prefix}-slideshare:before { content: $fa-var-slideshare; }
.#{$fa-css-prefix}-twitch:before { content: $fa-var-twitch; }
.#{$fa-css-prefix}-yelp:before { content: $fa-var-yelp; }
.#{$fa-css-prefix}-newspaper-o:before { content: $fa-var-newspaper-o; }
.#{$fa-css-prefix}-wifi:before { content: $fa-var-wifi; }
.#{$fa-css-prefix}-calculator:before { content: $fa-var-calculator; }
.#{$fa-css-prefix}-paypal:before { content: $fa-var-paypal; }
.#{$fa-css-prefix}-google-wallet:before { content: $fa-var-google-wallet; }
.#{$fa-css-prefix}-cc-visa:before { content: $fa-var-cc-visa; }
.#{$fa-css-prefix}-cc-mastercard:before { content: $fa-var-cc-mastercard; }
.#{$fa-css-prefix}-cc-discover:before { content: $fa-var-cc-discover; }
.#{$fa-css-prefix}-cc-amex:before { content: $fa-var-cc-amex; }
.#{$fa-css-prefix}-cc-paypal:before { content: $fa-var-cc-paypal; }
.#{$fa-css-prefix}-cc-stripe:before { content: $fa-var-cc-stripe; }
.#{$fa-css-prefix}-bell-slash:before { content: $fa-var-bell-slash; }
.#{$fa-css-prefix}-bell-slash-o:before { content: $fa-var-bell-slash-o; }
.#{$fa-css-prefix}-trash:before { content: $fa-var-trash; }
.#{$fa-css-prefix}-copyright:before { content: $fa-var-copyright; }
.#{$fa-css-prefix}-at:before { content: $fa-var-at; }
.#{$fa-css-prefix}-eyedropper:before { content: $fa-var-eyedropper; }
.#{$fa-css-prefix}-paint-brush:before { content: $fa-var-paint-brush; }
.#{$fa-css-prefix}-birthday-cake:before { content: $fa-var-birthday-cake; }
.#{$fa-css-prefix}-area-chart:before { content: $fa-var-area-chart; }
.#{$fa-css-prefix}-pie-chart:before { content: $fa-var-pie-chart; }
.#{$fa-css-prefix}-line-chart:before { content: $fa-var-line-chart; }
.#{$fa-css-prefix}-lastfm:before { content: $fa-var-lastfm; }
.#{$fa-css-prefix}-lastfm-square:before { content: $fa-var-lastfm-square; }
.#{$fa-css-prefix}-toggle-off:before { content: $fa-var-toggle-off; }
.#{$fa-css-prefix}-toggle-on:before { content: $fa-var-toggle-on; }
.#{$fa-css-prefix}-bicycle:before { content: $fa-var-bicycle; }
.#{$fa-css-prefix}-bus:before { content: $fa-var-bus; }
.#{$fa-css-prefix}-ioxhost:before { content: $fa-var-ioxhost; }
.#{$fa-css-prefix}-angellist:before { content: $fa-var-angellist; }
.#{$fa-css-prefix}-cc:before { content: $fa-var-cc; }
.#{$fa-css-prefix}-shekel:before,
.#{$fa-css-prefix}-sheqel:before,
.#{$fa-css-prefix}-ils:before { content: $fa-var-ils; }
.#{$fa-css-prefix}-meanpath:before { content: $fa-var-meanpath; }

View File

@@ -0,0 +1,13 @@
// Icon Sizes
// -------------------------
/* makes the font 33% larger relative to the icon container */
.#{$fa-css-prefix}-lg {
font-size: (4em / 3);
line-height: (3em / 4);
vertical-align: -15%;
}
.#{$fa-css-prefix}-2x { font-size: 2em; }
.#{$fa-css-prefix}-3x { font-size: 3em; }
.#{$fa-css-prefix}-4x { font-size: 4em; }
.#{$fa-css-prefix}-5x { font-size: 5em; }

View File

@@ -0,0 +1,19 @@
// List Icons
// -------------------------
.#{$fa-css-prefix}-ul {
padding-left: 0;
margin-left: $fa-li-width;
list-style-type: none;
> li { position: relative; }
}
.#{$fa-css-prefix}-li {
position: absolute;
left: -$fa-li-width;
width: $fa-li-width;
top: (2em / 14);
text-align: center;
&.#{$fa-css-prefix}-lg {
left: -$fa-li-width + (4em / 14);
}
}

View File

@@ -0,0 +1,25 @@
// Mixins
// --------------------------
@mixin fa-icon() {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
font-size: inherit; // can't have font-size inherit on line above, so need to override
text-rendering: auto; // optimizelegibility throws things off #1094
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@mixin fa-icon-rotate($degrees, $rotation) {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
-webkit-transform: rotate($degrees);
-ms-transform: rotate($degrees);
transform: rotate($degrees);
}
@mixin fa-icon-flip($horiz, $vert, $rotation) {
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
-webkit-transform: scale($horiz, $vert);
-ms-transform: scale($horiz, $vert);
transform: scale($horiz, $vert);
}

View File

@@ -0,0 +1,14 @@
/* FONT PATH
* -------------------------- */
@font-face {
font-family: 'FontAwesome';
src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
//src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
font-weight: normal;
font-style: normal;
}

View File

@@ -0,0 +1,20 @@
// Rotated & Flipped Icons
// -------------------------
.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); }
.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); }
.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); }
.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); }
.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); }
// Hook for IE8-9
// -------------------------
:root .#{$fa-css-prefix}-rotate-90,
:root .#{$fa-css-prefix}-rotate-180,
:root .#{$fa-css-prefix}-rotate-270,
:root .#{$fa-css-prefix}-flip-horizontal,
:root .#{$fa-css-prefix}-flip-vertical {
filter: none;
}

View File

@@ -0,0 +1,29 @@
// Spinning Icons
// --------------------------
.#{$fa-css-prefix}-spin {
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}

View File

@@ -0,0 +1,20 @@
// Stacked Icons
// -------------------------
.#{$fa-css-prefix}-stack {
position: relative;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2em;
vertical-align: middle;
}
.#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x {
position: absolute;
left: 0;
width: 100%;
text-align: center;
}
.#{$fa-css-prefix}-stack-1x { line-height: inherit; }
.#{$fa-css-prefix}-stack-2x { font-size: 2em; }
.#{$fa-css-prefix}-inverse { color: $fa-inverse; }

View File

@@ -0,0 +1,561 @@
// Variables
// --------------------------
$fa-font-path: "../fonts" !default;
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts" !default; // for referencing Bootstrap CDN font files directly
$fa-css-prefix: fa !default;
$fa-version: "4.2.0" !default;
$fa-border-color: #eee !default;
$fa-inverse: #fff !default;
$fa-li-width: (30em / 14) !default;
$fa-var-adjust: "\f042";
$fa-var-adn: "\f170";
$fa-var-align-center: "\f037";
$fa-var-align-justify: "\f039";
$fa-var-align-left: "\f036";
$fa-var-align-right: "\f038";
$fa-var-ambulance: "\f0f9";
$fa-var-anchor: "\f13d";
$fa-var-android: "\f17b";
$fa-var-angellist: "\f209";
$fa-var-angle-double-down: "\f103";
$fa-var-angle-double-left: "\f100";
$fa-var-angle-double-right: "\f101";
$fa-var-angle-double-up: "\f102";
$fa-var-angle-down: "\f107";
$fa-var-angle-left: "\f104";
$fa-var-angle-right: "\f105";
$fa-var-angle-up: "\f106";
$fa-var-apple: "\f179";
$fa-var-archive: "\f187";
$fa-var-area-chart: "\f1fe";
$fa-var-arrow-circle-down: "\f0ab";
$fa-var-arrow-circle-left: "\f0a8";
$fa-var-arrow-circle-o-down: "\f01a";
$fa-var-arrow-circle-o-left: "\f190";
$fa-var-arrow-circle-o-right: "\f18e";
$fa-var-arrow-circle-o-up: "\f01b";
$fa-var-arrow-circle-right: "\f0a9";
$fa-var-arrow-circle-up: "\f0aa";
$fa-var-arrow-down: "\f063";
$fa-var-arrow-left: "\f060";
$fa-var-arrow-right: "\f061";
$fa-var-arrow-up: "\f062";
$fa-var-arrows: "\f047";
$fa-var-arrows-alt: "\f0b2";
$fa-var-arrows-h: "\f07e";
$fa-var-arrows-v: "\f07d";
$fa-var-asterisk: "\f069";
$fa-var-at: "\f1fa";
$fa-var-automobile: "\f1b9";
$fa-var-backward: "\f04a";
$fa-var-ban: "\f05e";
$fa-var-bank: "\f19c";
$fa-var-bar-chart: "\f080";
$fa-var-bar-chart-o: "\f080";
$fa-var-barcode: "\f02a";
$fa-var-bars: "\f0c9";
$fa-var-beer: "\f0fc";
$fa-var-behance: "\f1b4";
$fa-var-behance-square: "\f1b5";
$fa-var-bell: "\f0f3";
$fa-var-bell-o: "\f0a2";
$fa-var-bell-slash: "\f1f6";
$fa-var-bell-slash-o: "\f1f7";
$fa-var-bicycle: "\f206";
$fa-var-binoculars: "\f1e5";
$fa-var-birthday-cake: "\f1fd";
$fa-var-bitbucket: "\f171";
$fa-var-bitbucket-square: "\f172";
$fa-var-bitcoin: "\f15a";
$fa-var-bold: "\f032";
$fa-var-bolt: "\f0e7";
$fa-var-bomb: "\f1e2";
$fa-var-book: "\f02d";
$fa-var-bookmark: "\f02e";
$fa-var-bookmark-o: "\f097";
$fa-var-briefcase: "\f0b1";
$fa-var-btc: "\f15a";
$fa-var-bug: "\f188";
$fa-var-building: "\f1ad";
$fa-var-building-o: "\f0f7";
$fa-var-bullhorn: "\f0a1";
$fa-var-bullseye: "\f140";
$fa-var-bus: "\f207";
$fa-var-cab: "\f1ba";
$fa-var-calculator: "\f1ec";
$fa-var-calendar: "\f073";
$fa-var-calendar-o: "\f133";
$fa-var-camera: "\f030";
$fa-var-camera-retro: "\f083";
$fa-var-car: "\f1b9";
$fa-var-caret-down: "\f0d7";
$fa-var-caret-left: "\f0d9";
$fa-var-caret-right: "\f0da";
$fa-var-caret-square-o-down: "\f150";
$fa-var-caret-square-o-left: "\f191";
$fa-var-caret-square-o-right: "\f152";
$fa-var-caret-square-o-up: "\f151";
$fa-var-caret-up: "\f0d8";
$fa-var-cc: "\f20a";
$fa-var-cc-amex: "\f1f3";
$fa-var-cc-discover: "\f1f2";
$fa-var-cc-mastercard: "\f1f1";
$fa-var-cc-paypal: "\f1f4";
$fa-var-cc-stripe: "\f1f5";
$fa-var-cc-visa: "\f1f0";
$fa-var-certificate: "\f0a3";
$fa-var-chain: "\f0c1";
$fa-var-chain-broken: "\f127";
$fa-var-check: "\f00c";
$fa-var-check-circle: "\f058";
$fa-var-check-circle-o: "\f05d";
$fa-var-check-square: "\f14a";
$fa-var-check-square-o: "\f046";
$fa-var-chevron-circle-down: "\f13a";
$fa-var-chevron-circle-left: "\f137";
$fa-var-chevron-circle-right: "\f138";
$fa-var-chevron-circle-up: "\f139";
$fa-var-chevron-down: "\f078";
$fa-var-chevron-left: "\f053";
$fa-var-chevron-right: "\f054";
$fa-var-chevron-up: "\f077";
$fa-var-child: "\f1ae";
$fa-var-circle: "\f111";
$fa-var-circle-o: "\f10c";
$fa-var-circle-o-notch: "\f1ce";
$fa-var-circle-thin: "\f1db";
$fa-var-clipboard: "\f0ea";
$fa-var-clock-o: "\f017";
$fa-var-close: "\f00d";
$fa-var-cloud: "\f0c2";
$fa-var-cloud-download: "\f0ed";
$fa-var-cloud-upload: "\f0ee";
$fa-var-cny: "\f157";
$fa-var-code: "\f121";
$fa-var-code-fork: "\f126";
$fa-var-codepen: "\f1cb";
$fa-var-coffee: "\f0f4";
$fa-var-cog: "\f013";
$fa-var-cogs: "\f085";
$fa-var-columns: "\f0db";
$fa-var-comment: "\f075";
$fa-var-comment-o: "\f0e5";
$fa-var-comments: "\f086";
$fa-var-comments-o: "\f0e6";
$fa-var-compass: "\f14e";
$fa-var-compress: "\f066";
$fa-var-copy: "\f0c5";
$fa-var-copyright: "\f1f9";
$fa-var-credit-card: "\f09d";
$fa-var-crop: "\f125";
$fa-var-crosshairs: "\f05b";
$fa-var-css3: "\f13c";
$fa-var-cube: "\f1b2";
$fa-var-cubes: "\f1b3";
$fa-var-cut: "\f0c4";
$fa-var-cutlery: "\f0f5";
$fa-var-dashboard: "\f0e4";
$fa-var-database: "\f1c0";
$fa-var-dedent: "\f03b";
$fa-var-delicious: "\f1a5";
$fa-var-desktop: "\f108";
$fa-var-deviantart: "\f1bd";
$fa-var-digg: "\f1a6";
$fa-var-dollar: "\f155";
$fa-var-dot-circle-o: "\f192";
$fa-var-download: "\f019";
$fa-var-dribbble: "\f17d";
$fa-var-dropbox: "\f16b";
$fa-var-drupal: "\f1a9";
$fa-var-edit: "\f044";
$fa-var-eject: "\f052";
$fa-var-ellipsis-h: "\f141";
$fa-var-ellipsis-v: "\f142";
$fa-var-empire: "\f1d1";
$fa-var-envelope: "\f0e0";
$fa-var-envelope-o: "\f003";
$fa-var-envelope-square: "\f199";
$fa-var-eraser: "\f12d";
$fa-var-eur: "\f153";
$fa-var-euro: "\f153";
$fa-var-exchange: "\f0ec";
$fa-var-exclamation: "\f12a";
$fa-var-exclamation-circle: "\f06a";
$fa-var-exclamation-triangle: "\f071";
$fa-var-expand: "\f065";
$fa-var-external-link: "\f08e";
$fa-var-external-link-square: "\f14c";
$fa-var-eye: "\f06e";
$fa-var-eye-slash: "\f070";
$fa-var-eyedropper: "\f1fb";
$fa-var-facebook: "\f09a";
$fa-var-facebook-square: "\f082";
$fa-var-fast-backward: "\f049";
$fa-var-fast-forward: "\f050";
$fa-var-fax: "\f1ac";
$fa-var-female: "\f182";
$fa-var-fighter-jet: "\f0fb";
$fa-var-file: "\f15b";
$fa-var-file-archive-o: "\f1c6";
$fa-var-file-audio-o: "\f1c7";
$fa-var-file-code-o: "\f1c9";
$fa-var-file-excel-o: "\f1c3";
$fa-var-file-image-o: "\f1c5";
$fa-var-file-movie-o: "\f1c8";
$fa-var-file-o: "\f016";
$fa-var-file-pdf-o: "\f1c1";
$fa-var-file-photo-o: "\f1c5";
$fa-var-file-picture-o: "\f1c5";
$fa-var-file-powerpoint-o: "\f1c4";
$fa-var-file-sound-o: "\f1c7";
$fa-var-file-text: "\f15c";
$fa-var-file-text-o: "\f0f6";
$fa-var-file-video-o: "\f1c8";
$fa-var-file-word-o: "\f1c2";
$fa-var-file-zip-o: "\f1c6";
$fa-var-files-o: "\f0c5";
$fa-var-film: "\f008";
$fa-var-filter: "\f0b0";
$fa-var-fire: "\f06d";
$fa-var-fire-extinguisher: "\f134";
$fa-var-flag: "\f024";
$fa-var-flag-checkered: "\f11e";
$fa-var-flag-o: "\f11d";
$fa-var-flash: "\f0e7";
$fa-var-flask: "\f0c3";
$fa-var-flickr: "\f16e";
$fa-var-floppy-o: "\f0c7";
$fa-var-folder: "\f07b";
$fa-var-folder-o: "\f114";
$fa-var-folder-open: "\f07c";
$fa-var-folder-open-o: "\f115";
$fa-var-font: "\f031";
$fa-var-forward: "\f04e";
$fa-var-foursquare: "\f180";
$fa-var-frown-o: "\f119";
$fa-var-futbol-o: "\f1e3";
$fa-var-gamepad: "\f11b";
$fa-var-gavel: "\f0e3";
$fa-var-gbp: "\f154";
$fa-var-ge: "\f1d1";
$fa-var-gear: "\f013";
$fa-var-gears: "\f085";
$fa-var-gift: "\f06b";
$fa-var-git: "\f1d3";
$fa-var-git-square: "\f1d2";
$fa-var-github: "\f09b";
$fa-var-github-alt: "\f113";
$fa-var-github-square: "\f092";
$fa-var-gittip: "\f184";
$fa-var-glass: "\f000";
$fa-var-globe: "\f0ac";
$fa-var-google: "\f1a0";
$fa-var-google-plus: "\f0d5";
$fa-var-google-plus-square: "\f0d4";
$fa-var-google-wallet: "\f1ee";
$fa-var-graduation-cap: "\f19d";
$fa-var-group: "\f0c0";
$fa-var-h-square: "\f0fd";
$fa-var-hacker-news: "\f1d4";
$fa-var-hand-o-down: "\f0a7";
$fa-var-hand-o-left: "\f0a5";
$fa-var-hand-o-right: "\f0a4";
$fa-var-hand-o-up: "\f0a6";
$fa-var-hdd-o: "\f0a0";
$fa-var-header: "\f1dc";
$fa-var-headphones: "\f025";
$fa-var-heart: "\f004";
$fa-var-heart-o: "\f08a";
$fa-var-history: "\f1da";
$fa-var-home: "\f015";
$fa-var-hospital-o: "\f0f8";
$fa-var-html5: "\f13b";
$fa-var-ils: "\f20b";
$fa-var-image: "\f03e";
$fa-var-inbox: "\f01c";
$fa-var-indent: "\f03c";
$fa-var-info: "\f129";
$fa-var-info-circle: "\f05a";
$fa-var-inr: "\f156";
$fa-var-instagram: "\f16d";
$fa-var-institution: "\f19c";
$fa-var-ioxhost: "\f208";
$fa-var-italic: "\f033";
$fa-var-joomla: "\f1aa";
$fa-var-jpy: "\f157";
$fa-var-jsfiddle: "\f1cc";
$fa-var-key: "\f084";
$fa-var-keyboard-o: "\f11c";
$fa-var-krw: "\f159";
$fa-var-language: "\f1ab";
$fa-var-laptop: "\f109";
$fa-var-lastfm: "\f202";
$fa-var-lastfm-square: "\f203";
$fa-var-leaf: "\f06c";
$fa-var-legal: "\f0e3";
$fa-var-lemon-o: "\f094";
$fa-var-level-down: "\f149";
$fa-var-level-up: "\f148";
$fa-var-life-bouy: "\f1cd";
$fa-var-life-buoy: "\f1cd";
$fa-var-life-ring: "\f1cd";
$fa-var-life-saver: "\f1cd";
$fa-var-lightbulb-o: "\f0eb";
$fa-var-line-chart: "\f201";
$fa-var-link: "\f0c1";
$fa-var-linkedin: "\f0e1";
$fa-var-linkedin-square: "\f08c";
$fa-var-linux: "\f17c";
$fa-var-list: "\f03a";
$fa-var-list-alt: "\f022";
$fa-var-list-ol: "\f0cb";
$fa-var-list-ul: "\f0ca";
$fa-var-location-arrow: "\f124";
$fa-var-lock: "\f023";
$fa-var-long-arrow-down: "\f175";
$fa-var-long-arrow-left: "\f177";
$fa-var-long-arrow-right: "\f178";
$fa-var-long-arrow-up: "\f176";
$fa-var-magic: "\f0d0";
$fa-var-magnet: "\f076";
$fa-var-mail-forward: "\f064";
$fa-var-mail-reply: "\f112";
$fa-var-mail-reply-all: "\f122";
$fa-var-male: "\f183";
$fa-var-map-marker: "\f041";
$fa-var-maxcdn: "\f136";
$fa-var-meanpath: "\f20c";
$fa-var-medkit: "\f0fa";
$fa-var-meh-o: "\f11a";
$fa-var-microphone: "\f130";
$fa-var-microphone-slash: "\f131";
$fa-var-minus: "\f068";
$fa-var-minus-circle: "\f056";
$fa-var-minus-square: "\f146";
$fa-var-minus-square-o: "\f147";
$fa-var-mobile: "\f10b";
$fa-var-mobile-phone: "\f10b";
$fa-var-money: "\f0d6";
$fa-var-moon-o: "\f186";
$fa-var-mortar-board: "\f19d";
$fa-var-music: "\f001";
$fa-var-navicon: "\f0c9";
$fa-var-newspaper-o: "\f1ea";
$fa-var-openid: "\f19b";
$fa-var-outdent: "\f03b";
$fa-var-pagelines: "\f18c";
$fa-var-paint-brush: "\f1fc";
$fa-var-paper-plane: "\f1d8";
$fa-var-paper-plane-o: "\f1d9";
$fa-var-paperclip: "\f0c6";
$fa-var-paragraph: "\f1dd";
$fa-var-paste: "\f0ea";
$fa-var-pause: "\f04c";
$fa-var-paw: "\f1b0";
$fa-var-paypal: "\f1ed";
$fa-var-pencil: "\f040";
$fa-var-pencil-square: "\f14b";
$fa-var-pencil-square-o: "\f044";
$fa-var-phone: "\f095";
$fa-var-phone-square: "\f098";
$fa-var-photo: "\f03e";
$fa-var-picture-o: "\f03e";
$fa-var-pie-chart: "\f200";
$fa-var-pied-piper: "\f1a7";
$fa-var-pied-piper-alt: "\f1a8";
$fa-var-pinterest: "\f0d2";
$fa-var-pinterest-square: "\f0d3";
$fa-var-plane: "\f072";
$fa-var-play: "\f04b";
$fa-var-play-circle: "\f144";
$fa-var-play-circle-o: "\f01d";
$fa-var-plug: "\f1e6";
$fa-var-plus: "\f067";
$fa-var-plus-circle: "\f055";
$fa-var-plus-square: "\f0fe";
$fa-var-plus-square-o: "\f196";
$fa-var-power-off: "\f011";
$fa-var-print: "\f02f";
$fa-var-puzzle-piece: "\f12e";
$fa-var-qq: "\f1d6";
$fa-var-qrcode: "\f029";
$fa-var-question: "\f128";
$fa-var-question-circle: "\f059";
$fa-var-quote-left: "\f10d";
$fa-var-quote-right: "\f10e";
$fa-var-ra: "\f1d0";
$fa-var-random: "\f074";
$fa-var-rebel: "\f1d0";
$fa-var-recycle: "\f1b8";
$fa-var-reddit: "\f1a1";
$fa-var-reddit-square: "\f1a2";
$fa-var-refresh: "\f021";
$fa-var-remove: "\f00d";
$fa-var-renren: "\f18b";
$fa-var-reorder: "\f0c9";
$fa-var-repeat: "\f01e";
$fa-var-reply: "\f112";
$fa-var-reply-all: "\f122";
$fa-var-retweet: "\f079";
$fa-var-rmb: "\f157";
$fa-var-road: "\f018";
$fa-var-rocket: "\f135";
$fa-var-rotate-left: "\f0e2";
$fa-var-rotate-right: "\f01e";
$fa-var-rouble: "\f158";
$fa-var-rss: "\f09e";
$fa-var-rss-square: "\f143";
$fa-var-rub: "\f158";
$fa-var-ruble: "\f158";
$fa-var-rupee: "\f156";
$fa-var-save: "\f0c7";
$fa-var-scissors: "\f0c4";
$fa-var-search: "\f002";
$fa-var-search-minus: "\f010";
$fa-var-search-plus: "\f00e";
$fa-var-send: "\f1d8";
$fa-var-send-o: "\f1d9";
$fa-var-share: "\f064";
$fa-var-share-alt: "\f1e0";
$fa-var-share-alt-square: "\f1e1";
$fa-var-share-square: "\f14d";
$fa-var-share-square-o: "\f045";
$fa-var-shekel: "\f20b";
$fa-var-sheqel: "\f20b";
$fa-var-shield: "\f132";
$fa-var-shopping-cart: "\f07a";
$fa-var-sign-in: "\f090";
$fa-var-sign-out: "\f08b";
$fa-var-signal: "\f012";
$fa-var-sitemap: "\f0e8";
$fa-var-skype: "\f17e";
$fa-var-slack: "\f198";
$fa-var-sliders: "\f1de";
$fa-var-slideshare: "\f1e7";
$fa-var-smile-o: "\f118";
$fa-var-soccer-ball-o: "\f1e3";
$fa-var-sort: "\f0dc";
$fa-var-sort-alpha-asc: "\f15d";
$fa-var-sort-alpha-desc: "\f15e";
$fa-var-sort-amount-asc: "\f160";
$fa-var-sort-amount-desc: "\f161";
$fa-var-sort-asc: "\f0de";
$fa-var-sort-desc: "\f0dd";
$fa-var-sort-down: "\f0dd";
$fa-var-sort-numeric-asc: "\f162";
$fa-var-sort-numeric-desc: "\f163";
$fa-var-sort-up: "\f0de";
$fa-var-soundcloud: "\f1be";
$fa-var-space-shuttle: "\f197";
$fa-var-spinner: "\f110";
$fa-var-spoon: "\f1b1";
$fa-var-spotify: "\f1bc";
$fa-var-square: "\f0c8";
$fa-var-square-o: "\f096";
$fa-var-stack-exchange: "\f18d";
$fa-var-stack-overflow: "\f16c";
$fa-var-star: "\f005";
$fa-var-star-half: "\f089";
$fa-var-star-half-empty: "\f123";
$fa-var-star-half-full: "\f123";
$fa-var-star-half-o: "\f123";
$fa-var-star-o: "\f006";
$fa-var-steam: "\f1b6";
$fa-var-steam-square: "\f1b7";
$fa-var-step-backward: "\f048";
$fa-var-step-forward: "\f051";
$fa-var-stethoscope: "\f0f1";
$fa-var-stop: "\f04d";
$fa-var-strikethrough: "\f0cc";
$fa-var-stumbleupon: "\f1a4";
$fa-var-stumbleupon-circle: "\f1a3";
$fa-var-subscript: "\f12c";
$fa-var-suitcase: "\f0f2";
$fa-var-sun-o: "\f185";
$fa-var-superscript: "\f12b";
$fa-var-support: "\f1cd";
$fa-var-table: "\f0ce";
$fa-var-tablet: "\f10a";
$fa-var-tachometer: "\f0e4";
$fa-var-tag: "\f02b";
$fa-var-tags: "\f02c";
$fa-var-tasks: "\f0ae";
$fa-var-taxi: "\f1ba";
$fa-var-tencent-weibo: "\f1d5";
$fa-var-terminal: "\f120";
$fa-var-text-height: "\f034";
$fa-var-text-width: "\f035";
$fa-var-th: "\f00a";
$fa-var-th-large: "\f009";
$fa-var-th-list: "\f00b";
$fa-var-thumb-tack: "\f08d";
$fa-var-thumbs-down: "\f165";
$fa-var-thumbs-o-down: "\f088";
$fa-var-thumbs-o-up: "\f087";
$fa-var-thumbs-up: "\f164";
$fa-var-ticket: "\f145";
$fa-var-times: "\f00d";
$fa-var-times-circle: "\f057";
$fa-var-times-circle-o: "\f05c";
$fa-var-tint: "\f043";
$fa-var-toggle-down: "\f150";
$fa-var-toggle-left: "\f191";
$fa-var-toggle-off: "\f204";
$fa-var-toggle-on: "\f205";
$fa-var-toggle-right: "\f152";
$fa-var-toggle-up: "\f151";
$fa-var-trash: "\f1f8";
$fa-var-trash-o: "\f014";
$fa-var-tree: "\f1bb";
$fa-var-trello: "\f181";
$fa-var-trophy: "\f091";
$fa-var-truck: "\f0d1";
$fa-var-try: "\f195";
$fa-var-tty: "\f1e4";
$fa-var-tumblr: "\f173";
$fa-var-tumblr-square: "\f174";
$fa-var-turkish-lira: "\f195";
$fa-var-twitch: "\f1e8";
$fa-var-twitter: "\f099";
$fa-var-twitter-square: "\f081";
$fa-var-umbrella: "\f0e9";
$fa-var-underline: "\f0cd";
$fa-var-undo: "\f0e2";
$fa-var-university: "\f19c";
$fa-var-unlink: "\f127";
$fa-var-unlock: "\f09c";
$fa-var-unlock-alt: "\f13e";
$fa-var-unsorted: "\f0dc";
$fa-var-upload: "\f093";
$fa-var-usd: "\f155";
$fa-var-user: "\f007";
$fa-var-user-md: "\f0f0";
$fa-var-users: "\f0c0";
$fa-var-video-camera: "\f03d";
$fa-var-vimeo-square: "\f194";
$fa-var-vine: "\f1ca";
$fa-var-vk: "\f189";
$fa-var-volume-down: "\f027";
$fa-var-volume-off: "\f026";
$fa-var-volume-up: "\f028";
$fa-var-warning: "\f071";
$fa-var-wechat: "\f1d7";
$fa-var-weibo: "\f18a";
$fa-var-weixin: "\f1d7";
$fa-var-wheelchair: "\f193";
$fa-var-wifi: "\f1eb";
$fa-var-windows: "\f17a";
$fa-var-won: "\f159";
$fa-var-wordpress: "\f19a";
$fa-var-wrench: "\f0ad";
$fa-var-xing: "\f168";
$fa-var-xing-square: "\f169";
$fa-var-yahoo: "\f19e";
$fa-var-yelp: "\f1e9";
$fa-var-yen: "\f157";
$fa-var-youtube: "\f167";
$fa-var-youtube-play: "\f16a";
$fa-var-youtube-square: "\f166";

View File

@@ -0,0 +1,17 @@
/*!
* Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
@import "variables";
@import "mixins";
@import "path";
@import "core";
@import "larger";
@import "fixed-width";
@import "list";
@import "bordered-pulled";
@import "spinning";
@import "rotated-flipped";
@import "stacked";
@import "icons";

View File

@@ -159,9 +159,13 @@ h1, h2, h3 {
-webkit-overflow-scrolling: touch !important; // for iphone
}
.btn * {
cursor: pointer !important; // 下载所有, 被dropdown
}
.ios7-a {
display: inline-block;
padding: 0 10px 0 5px;
padding: 0 10px;
height: 36px;
vertical-align: middle;
line-height: 36px;
@@ -247,7 +251,7 @@ h1, h2, h3 {
height: 12px;
position: absolute;
top: -12px;
right: 20px;
right: 8px;
background-image: url("../../images/triangle_2x.png");
background-size: 20px 12px;
}
@@ -414,7 +418,16 @@ h1, h2, h3 {
line-height: 40px; margin-top: 10px;
}
/* editor */
#editorTool {
margin: 0;
margin-right: 5px;
padding: 0;
list-style: none;
}
#editorTool li {
display: inline-block;
}
#searchNotebookForAdd {
line-height: normal;
@@ -1481,3 +1494,154 @@ top: 4px;
margin: 3px 0;
height: 26px;
}
// 笔记信息设置
#noteInfo {
width: 400px;
box-sizing: border-box;
padding: 10px 10px;
-webkit-user-select: initial;
table {
width: 100%;
margin: 0;
th {
width: 80px;
}
th, td {
border-top: none;
border-bottom: 1px solid #dddddd;
}
}
a {
cursor: pointer;
}
a.post-url {
background: #FDF936;
}
.post-url-wrap {
span {
display: inline;
}
input {
display: none;
}
&.post-url-edit {
.post-url-pencil {
display: none;
}
.post-url-text {
display: none;
}
input {
display: inline;
}
}
}
}
//===========
// history
.history-modal .modal-dialog {
width: auto !important;
position: absolute;
/* width: 100%; */
/* height: 100%; */
left: 5px;
right: 5px;
top: 5px;
bottom: 5px;
.modal-content {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0;
padding: 0;
overflow: scroll;
.modal-body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0;
.history-list-wrap {
position: absolute;
top: 0;
bottom: 0;
overflow-y: auto;
width: 200px;
border-right: 1px solid #ccc;
box-shadow: 1px 1px 10px #ddd;
.history-list-header {
line-height: 50px;
font-size: 16px;
font-weight: bold;
padding-left: 15px;
border-bottom: 1px solid #eee;
background-color: #ccc;
}
.history-list {
position: absolute;
top: 51px;
bottom: 0;
left: 0;
right: 0;
overflow-y: auto;
margin-bottom: 0;
}
.list-group-item {
border-top: none;
&.active, &:hover {
color: #000;
background-color: #eee;
border-color: #eee;
}
}
}
.history-content-wrap {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 200px;
.close {
padding: 10px 15px;
}
.back {
margin-left: 10px;
margin-top: 5px;
}
.history-content-header {
// background-color: #eee;
height: 51px;
border-bottom: 1px solid #eee;
box-shadow: 5px 0px 5px #ccc;
}
.history-content {
position: absolute;
top: 51px;
bottom: 0;
right: 0;
left: 0;
padding-top: 5px;
padding-right: 5px;
padding-left: 10px;
overflow-y: auto;
}
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -522,24 +522,6 @@ a.raw:hover {
float: right;
}
/* note */
#noteTop {
// background-color: #f0f0f0;
}
/* editor */
#editorTool {
margin: 0;
padding: 0;
list-style: none;
// width: 200px;
}
#editorTool li {
display: inline-block;
}
#noteTitleDiv {
height: 30px;
border-bottom: 1px solid #ddd;

File diff suppressed because one or more lines are too long

View File

@@ -499,17 +499,6 @@ a.raw:hover {
float: right;
}
/* editor */
#editorTool {
margin: 0;
padding: 0;
list-style: none;
// width: 200px;
}
#editorTool li {
display: inline-block;
}
#noteTitleDiv {
height: 30px;
border-bottom: 1px solid #ddd;

File diff suppressed because one or more lines are too long

View File

@@ -14,7 +14,7 @@
@leftNotebookWidth: 170px;
@noteListWidth: 250px;
@noteActiveBg: #65bd77;
@bgColor: #fbfcf7;
@headerBgColor: #fbfcf7;
@fontFamily: 'Open Sans','Helvetica Neue',Arial,'Hiragino Sans GB','Microsoft YaHei','WenQuanYi Micro Hei',sans-serif;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.ztree,.ztree li a{margin:0;color:#333}.ztree li a.tmpTargetNode_inner,ul.tmpTargetzTree,ul.ztree.zTreeDragUL{opacity:.8;filter:alpha(opacity=80)}.ztree *{padding:0;margin:0;font-size:12px}.ztree{padding:5px}.ztree li{padding:0;margin:0;list-style:none;text-align:left;white-space:nowrap;outline:0}.ztree li a{padding:1px 3px 0 0;cursor:pointer;background-color:transparent;text-decoration:none;vertical-align:top;display:block;position:relative}.ztree li a.curSelectedNode,.ztree li a.curSelectedNode_Edit{padding-top:0;background-color:#FFE6B0;color:#000;height:16px;border:1px solid #FFB951;opacity:.8}.ztree li a.tmpTargetNode_inner{padding-top:0;background-color:#eee;color:#000;height:30px;border:1px solid #ccc}.ztree li span{margin-right:2px}.ztree li span.button{line-height:0;margin:0;width:16px;height:16px;display:inline-block;vertical-align:middle;border:0;cursor:pointer;outline:0}.ztree li,.ztree li span,span.tmpzTreeMove_arrow{line-height:30px}.ztree li span.button.ico_open{margin-right:2px;background-position:-110px -16px;vertical-align:top}.ztree li span.button.ico_close{margin-right:2px;background-position:-110px 0;vertical-align:top}.ztree li span.button.ico_docu{margin-right:2px;background-position:-110px -32px;vertical-align:top}.ztree li span.button.edit{margin-right:2px;background-position:-110px -48px;vertical-align:top}.ztree li span.button.remove{margin-right:2px;background-position:-110px -64px;vertical-align:top}ul.tmpTargetzTree{background-color:#FFE6B0}span.tmpzTreeMove_arrow{z-index:333;width:16px;height:30px;display:inline-block;padding:0;margin:0 0 0 15px;border:0;position:absolute}ul.ztree.zTreeDragUL{z-index:333;margin:0;padding:0;position:absolute;width:auto;height:auto;overflow:hidden;background-color:cfcfcf;border:1px dotted #00B83F}.zTreeMask{z-index:1000;background-color:#cfcfcf;opacity:0;filter:alpha(opacity=0);position:absolute}.ztree li ul{margin:0 0 0 10px;padding:0}.ztree>li{border-bottom:1px dashed #eee}.ztree li a{height:30px;padding-top:0}.ztree li a:hover{text-decoration:none;background-color:#E7E7E7}.ztree li a span.button.switch{visibility:hidden}.ztree.showIcon li a span.button.switch{visibility:visible}.ztree li a.curSelectedNode{background-color:#eee;border:0;height:30px}.ztree li span.button{margin-top:-5px;background-image:none}.ztree li span.button.switch{width:16px;height:30px;line-height:30px;text-align:center}.ztree li a.level0 span{font-size:14px}.ztree li span.button.switch.level0,.ztree li span.button.switch.level1{width:20px}.ztree li span.button.noline_open:before{content:"\f107"}.ztree li span.button.noline_close:before{content:"\f105"}.ztree li span.button.noline_open.level0{background-position:0 -18px}.ztree li span.button.noline_close.level0{background-position:-18px -18px}.ztree .tree-title{display:inline-block}

1
public/dist/themes/default-min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
var urlPrefix=UrlPrefix;define("attachment_upload",["jquery.ui.widget","fileupload"],function(){function formatFileSize(bytes){if(typeof bytes!=="number"){return""}if(bytes>=1e9){return(bytes/1e9).toFixed(2)+" GB"}if(bytes>=1e6){return(bytes/1e6).toFixed(2)+" MB"}return(bytes/1e3).toFixed(2)+" KB"}function setDropStyle(dropzoneId,formId){var dropZone=$(dropzoneId);$(formId).bind("dragover",function(e){e.preventDefault();var timeout=window.dropZoneTimeoutAttach;if(timeout){clearTimeout(timeout)}var found=false,node=e.target;do{if(node===dropZone[0]){found=true;break}node=node.parentNode}while(node!=null);if(found){dropZone.addClass("hover")}else{dropZone.removeClass("hover")}window.dropZoneTimeoutAttach=setTimeout(function(){window.dropZoneTimeoutAttach=null;dropZone.removeClass("in hover")},100)})}setDropStyle("#dropAttach","#uploadAttach");setDropStyle("#dropAvatar","#uploadAvatar");var initUploader=function(){$(".dropzone .btn-choose-file").click(function(){$(this).parent().find("input").click()});var $msg=$("#attachUploadMsg");$("#uploadAttach").fileupload({dataType:"json",pasteZone:"",dropZone:$("#dropAttach"),formData:function(form){return[{name:"noteId",value:Note.curNoteId}]},add:function(e,data){var note=Note.getCurNote();if(!note||note.IsNew){alert("This note hasn't saved, please save it firstly!");return}var tpl=$('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');tpl.append(data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small>");$msg.html(tpl);data.context=$msg;var size=data.files[0].size;var maxFileSize=+GlobalConfigs["uploadAttachSize"]||100;if(typeof size=="number"&&size>1024*1024*maxFileSize){tpl.find("img").remove();tpl.removeClass("alert-info").addClass("alert-danger");tpl.append(" Warning: File size is bigger than "+maxFileSize+"M");setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3);return}var jqXHR;setTimeout(function(){jqXHR=data.submit()},10)},done:function(e,data){if(data.result.Ok==true){data.context.html("");Attach.addAttach(data.result.Item)}else{var re=data.result;data.context.html("");var tpl=$('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');tpl.append("<b>Error:</b> "+data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small> "+data.result.Msg);data.context.html(tpl);setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3)}$("#uploadAttachMsg").scrollTop(1e3)},fail:function(e,data){data.context.html("");var tpl=$('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');tpl.append("<b>Error:</b> "+data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small> "+data.errorThrown);data.context.html(tpl);setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3);$("#uploadAttachMsg").scrollTop(1e3)}});var $msg2=$("#avatarUploadMsg");$("#uploadAvatar").fileupload({dataType:"json",dropZone:$("#dropAvatar"),pasteZone:"",add:function(e,data){var tpl=$('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');tpl.append(data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small>");$msg2.html(tpl);data.context=$msg2;var size=data.files[0].size;var maxFileSize=+GlobalConfigs["uploadAvatarSize"]||100;if(typeof size=="number"&&size>1024*1024*maxFileSize){tpl.find("img").remove();tpl.removeClass("alert-info").addClass("alert-danger");tpl.append(" Warning: File size is bigger than "+maxFileSize+"M");setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3);return}var jqXHR;setTimeout(function(){jqXHR=data.submit()},10)},done:function(e,data){if(data.result.Ok==true){data.context.html("");var re=data.result;$("#avatar").attr("src",UrlPrefix+"/"+re.Id)}else{var re=data.result;data.context.html("");var tpl=$('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');tpl.append("<b>Error:</b> "+data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small> "+data.result.Msg);data.context.html(tpl);setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3)}},fail:function(e,data){data.context.html("");var tpl=$('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');tpl.append("<b>Error:</b> "+data.files[0].name+" <small>[<i>"+formatFileSize(data.files[0].size)+"</i>]</small> "+data.errorThrown);data.context.html(tpl);setTimeout(function(tpl){return function(){tpl.remove()}}(tpl),3e3)}})};initUploader()});

View File

@@ -1,216 +0,0 @@
// upload attachment
// 依赖note
var urlPrefix = UrlPrefix;
define('attachment_upload', ['jquery.ui.widget', 'fileupload'], function(){
// Helper function that formats the file sizes
function formatFileSize(bytes) {
if (typeof bytes !== 'number') {
return '';
}
if (bytes >= 1000000000) {
return (bytes / 1000000000).toFixed(2) + ' GB';
}
if (bytes >= 1000000) {
return (bytes / 1000000).toFixed(2) + ' MB';
}
return (bytes / 1000).toFixed(2) + ' KB';
}
function setDropStyle(dropzoneId, formId) {
// drag css
var dropZone = $(dropzoneId);
$(formId).bind('dragover', function (e) {
e.preventDefault();
var timeout = window.dropZoneTimeoutAttach;
if(timeout) {
clearTimeout(timeout);
}
var found = false,
node = e.target;
do {
if (node === dropZone[0]) {
found = true;
break;
}
node = node.parentNode;
} while (node != null);
if (found) {
dropZone.addClass('hover');
} else {
dropZone.removeClass('hover');
}
window.dropZoneTimeoutAttach = setTimeout(function () {
window.dropZoneTimeoutAttach = null;
dropZone.removeClass('in hover');
}, 100);
});
}
setDropStyle("#dropAttach", "#uploadAttach");
setDropStyle("#dropAvatar", "#uploadAvatar");
var initUploader = function() {
$('.dropzone .btn-choose-file').click(function() {
$(this).parent().find('input').click();
});
var $msg = $('#attachUploadMsg');
// Initialize the jQuery File Upload plugin
$('#uploadAttach').fileupload({
dataType: 'json',
pasteZone: '', // 不能通过paste来上传图片
// This element will accept file drag/drop uploading
dropZone: $('#dropAttach'),
formData: function(form) {
return [{name: 'noteId', value: Note.curNoteId}] // 传递笔记本过去
},
// This function is called when a file is added to the queue;
// either via the browse button, or via drag/drop:
add: function(e, data) {
var note = Note.getCurNote();
if(!note || note.IsNew) {
alert("This note hasn't saved, please save it firstly!")
return;
}
var tpl = $('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');
// Append the file name and file size
tpl.append(data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small>');
// Add the HTML to the UL element
$msg.html(tpl);
data.context = $msg;
// 检查文件大小
var size = data.files[0].size;
var maxFileSize = +GlobalConfigs["uploadAttachSize"] || 100;
if(typeof size == 'number' && size > 1024 * 1024 * maxFileSize) {
tpl.find("img").remove();
tpl.removeClass("alert-info").addClass("alert-danger");
tpl.append(" Warning: File size is bigger than " + maxFileSize + "M");
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
return;
}
// Automatically upload the file once it is added to the queue
var jqXHR;
setTimeout(function() {
jqXHR = data.submit();
}, 10);
},
/*
progress: function (e, data) {
},
*/
done: function(e, data) {
if (data.result.Ok == true) {
data.context.html("");
Attach.addAttach(data.result.Item);
} else {
var re = data.result;
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.result.Msg);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
}
$("#uploadAttachMsg").scrollTop(1000);
},
fail: function(e, data) {
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.errorThrown);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
$("#uploadAttachMsg").scrollTop(1000);
}
});
//-------------------
// 已经过时, 没有avatar了
var $msg2 = $('#avatarUploadMsg');
$('#uploadAvatar').fileupload({
dataType: 'json',
dropZone: $('#dropAvatar'),
pasteZone: '',
add: function(e, data) {
var tpl = $('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');
// Append the file name and file size
tpl.append(data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small>');
// Add the HTML to the UL element
$msg2.html(tpl);
data.context = $msg2;
// 检查文件大小
var size = data.files[0].size;
var maxFileSize = +GlobalConfigs["uploadAvatarSize"] || 100;
if(typeof size == 'number' && size > 1024 * 1024 * maxFileSize) {
tpl.find("img").remove();
tpl.removeClass("alert-info").addClass("alert-danger");
tpl.append(" Warning: File size is bigger than " + maxFileSize + "M");
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
return;
}
// Automatically upload the file once it is added to the queue
var jqXHR;
setTimeout(function() {
jqXHR = data.submit();
}, 10);
},
done: function(e, data) {
if (data.result.Ok == true) {
data.context.html("");
var re = data.result;
$("#avatar").attr("src", UrlPrefix + "/" + re.Id);
} else {
var re = data.result;
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.result.Msg);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
}
},
fail: function(e, data) {
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.errorThrown);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
}
});
};
initUploader();
});

File diff suppressed because one or more lines are too long

View File

@@ -1,375 +0,0 @@
// for editor.
// drag image to editor
var urlPrefix = UrlPrefix; // window.location.protocol + "//" + window.location.host;
define('editor_drop_paste', ['jquery.ui.widget', 'fileupload'], function(){
function Process(editor) {
var id = '__mcenew' + (new Date()).getTime();
var str = '<div contenteditable="false" id="' + id + '" class="leanote-image-container">' +
'<img class="loader" src="/images/ajax-loader.gif">' +
'<div class="progress">' +
'<div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" aria-valuenow="2" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">' +
'0%' +
'</div>' +
'</div>' +
'</div>';
this.containerStr = str;
editor.insertContent(str);
var container = $('#' + id);
this.container = container;
this.id = id;
this.processBar = container.find('.progress-bar');
}
Process.prototype.update = function(process) {
var me = this;
// 98%, 不要小数
process = Math.ceil(process * 100);
if(process >= 100) {
process = 99;
}
process += "%";
$('#' + me.id + ' .progress-bar').html(process).css('width', process);
}
Process.prototype.replace = function(src) {
var me = this;
getImageSize(src, function() {
$('#' + me.id).replaceWith('<img src="' + src + '" />');
});
}
Process.prototype.remove = function() {
var me = this;
$('#' + me.id).remove();
}
// 当url改变时, 得到图片的大小
function getImageSize(url, callback) {
var img = document.createElement('img');
function done(width, height) {
img.parentNode.removeChild(img);
callback({width: width, height: height});
}
img.onload = function() {
done(img.clientWidth, img.clientHeight);
};
img.onerror = function() {
done();
};
img.src = url;
var style = img.style;
style.visibility = 'hidden';
style.position = 'fixed';
style.bottom = style.left = 0;
style.width = style.height = 'auto';
document.body.appendChild(img);
}
var i = 1;
function insertImage(data) {
var editor = tinymce.activeEditor;
var dom = editor.dom;
var renderImage = function(data2) {
// 这里, 如果图片宽度过大, 这里设置成500px
var d = {};
var imgElm;
// 先显示loading...
d.id = '__mcenew' + (i++);
d.src = "http://leanote.com/images/loading-24.gif";
imgElm = dom.createHTML('img', d);
tinymce.activeEditor.insertContent(imgElm);
imgElm = dom.get(d.id);
function callback (wh) {
dom.setAttrib(imgElm, 'src', data2.src);
// dom.setAttrib(imgElm, 'width', data2.width);
if(data2.title) {
dom.setAttrib(imgElm, 'title', data2.title);
}
dom.setAttrib(imgElm, 'id', null);
};
getImageSize(data.src, callback);
}
//-------------
// outputImage?fileId=123232323
var fileId = "";
fileIds = data.src.split("fileId=")
if(fileIds.length == 2 && fileIds[1].length == "53aecf8a8a039a43c8036282".length) {
fileId = fileIds[1];
}
if(fileId) {
// 得到fileId, 如果这个笔记不是我的, 那么肯定是协作的笔记, 那么需要将图片copy给原note owner
var curNote = Note.getCurNote();
if(curNote && curNote.UserId != UserInfo.UserId) {
(function(data) {
ajaxPost("/file/copyImage", {userId: UserInfo.UserId, fileId: fileId, toUserId: curNote.UserId}, function(re) {
if(reIsOk(re) && re.Id) {
var urlPrefix = window.location.protocol + "//" + window.location.host;
data.src = urlPrefix + "/file/outputImage?fileId=" + re.Id;
}
renderImage(data);
});
})(data);
} else {
renderImage(data);
}
} else {
renderImage(data);
}
}
var initUploader = function() {
var ul = $('#upload ul');
$('#drop a').click(function() {
// trigger to show file select
$(this).parent().find('input').click();
});
// Initialize the jQuery File Upload plugin
$('#upload').fileupload({
dataType: 'json',
pasteZone: '', // 不允许paste
acceptFileTypes: /(\.|\/)(gif|jpg|jpeg|png|jpe)$/i,
maxFileSize: 210000,
// This element will accept file drag/drop uploading
dropZone: $('#drop'),
formData: function(form) {
return [{name: 'albumId', value: ""}]
},
// This function is called when a file is added to the queue;
// either via the browse button, or via drag/drop:
add: function(e, data) {
var tpl = $('<li><div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div></li>');
// Append the file name and file size
tpl.find('div').append(data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small>');
// Add the HTML to the UL element
data.context = tpl.appendTo(ul);
// data.form[0].action += "&album_id=" + $("#albumsForUpload").val();
// Automatically upload the file once it is added to the queue
var jqXHR = data.submit();
},
done: function(e, data) {
if (data.result.Ok == true) {
data.context.remove();
// life
var data2 = {src: urlPrefix + "/file/outputImage?fileId=" + data.result.Id}
insertImage(data2);
} else {
data.context.empty();
var tpl = $('<li><div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div></li>');
tpl.find('div').append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.result.Msg);
data.context.append(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 2000);
}
$("#uploadMsg").scrollTop(1000);
},
fail: function(e, data) {
data.context.empty();
var tpl = $('<li><div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div></li>');
tpl.find('div').append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.errorThrown);
data.context.append(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 2000);
$("#uploadMsg").scrollTop(1000);
}
});
// Prevent the default action when a file is dropped on the window
$(document).on('drop dragover', function(e) {
e.preventDefault();
});
// Helper function that formats the file sizes
function formatFileSize(bytes) {
if (typeof bytes !== 'number') {
return '';
}
if (bytes >= 1000000000) {
return (bytes / 1000000000).toFixed(2) + ' GB';
}
if (bytes >= 1000000) {
return (bytes / 1000000).toFixed(2) + ' MB';
}
return (bytes / 1000).toFixed(2) + ' KB';
}
function showUpload() {
$("#upload").css("z-index", 12);
var top = +$("#mceToolbar").css("height").slice(0, -2); // px
$("#upload").css("top", top - 8);
$("#upload").show();
}
function hideUpload() {
$("#upload").css("z-index", 0).css("top", "auto").hide();
}
// drag css
$(document).bind('dragover', function (e) {
var dropZone = $('#drop'),
timeout = window.dropZoneTimeout;
if (!timeout) {
dropZone.addClass('in');
showUpload();
} else {
clearTimeout(timeout);
}
var found = false,
node = e.target;
do {
if (node === dropZone[0]) {
found = true;
break;
}
node = node.parentNode;
} while (node != null);
if (found) {
dropZone.addClass('hover');
} else {
dropZone.removeClass('hover');
}
window.dropZoneTimeout = setTimeout(function () {
window.dropZoneTimeout = null;
dropZone.removeClass('in hover');
hideUpload();
}, 100);
});
};
// pasteImage
var pasteImageInit = function() {
// Initialize the jQuery File Upload plugin
var dom, editor;
$('#editorContent').fileupload({
dataType: 'json',
pasteZone: $('#editorContent'),
dropZone: '', // 只允许paste
maxFileSize: 210000,
url: "/file/pasteImage",
paramName: 'file',
formData: function(form) {
return [{name: 'from', value: 'pasteImage'}, {name: 'noteId', value: Note.curNoteId}]
},
/*
paste: function(e, data) {
var jqXHR = data.submit();
},
*/
progress: function(e, data) {
data.process.update(data.loaded / data.total);
},
add: function(e, data) {
var note = Note.getCurNote();
if(!note || note.IsNew) {
alert("This note hasn't saved, please save it firstly!")
return;
}
// 先显示loading...
editor = tinymce.EditorManager.activeEditor;
var process = new Process(editor);
data.process = process;
var jqXHR = data.submit();
/*
d.id = '__mcenew' + (new Date()).getTime();
d.src = "http://leanote.com/images/loading-24.gif"; // 写死了
var img = '<img src="' + d.src + '" id="' + d.id + '" />';
editor.insertContent(img);
var imgElm = $(d.id);
data.imgId = d.id;
data.context = imgElm;
*/
/*
// 上传之
var c = new FormData;
c.append("from", "pasteImage");
// var d;
// d = $.ajaxSettings.xhr();
// d.withCredentials = i;var d = {};
// 先显示loading...
var editor = tinymce.EditorManager.activeEditor;
var dom = editor.dom;
var d = {};
d.id = '__mcenew';
d.src = "http://leanote.com/images/loading-24.gif"; // 写死了
editor.insertContent(dom.createHTML('img', d));
var imgElm = dom.get('__mcenew');
$.ajax({url: "/file/pasteImage", contentType:false, processData:false , data: c, type: "POST"}
).done(function(re) {
if(!re || typeof re != "object" || !re.Ok) {
// 删除
dom.remove(imgElm);
return;
}
// 这里, 如果图片宽度过大, 这里设置成500px
var urlPrefix = UrlPrefix; // window.location.protocol + "//" + window.location.host;
var src = urlPrefix + "/file/outputImage?fileId=" + re.Id;
getImageSize(src, function(wh) {
// life 4/25
if(wh && wh.width) {
if(wh.width > 600) {
wh.width = 600;
}
d.width = wh.width;
dom.setAttrib(imgElm, 'width', d.width);
}
dom.setAttrib(imgElm, 'src', src);
});
dom.setAttrib(imgElm, 'id', null);
});
};
reader.readAsDataURL(blob);
*/
},
done: function(e, data) {
if (data.result.Ok == true) {
// 这里, 如果图片宽度过大, 这里设置成500px
var re = data.result;
var urlPrefix = UrlPrefix; // window.location.protocol + "//" + window.location.host;
var src = urlPrefix + "/file/outputImage?fileId=" + re.Id;
data.process.replace(src);
/*
getImageSize(src, function() {
$img.attr('src', src);
$img.removeAttr('id');
});
*/
} else {
data.process.remove();
}
},
fail: function(e, data) {
data.process.remove();
}
});
};
initUploader();
pasteImageInit();
});

View File

@@ -61,9 +61,12 @@ Note.setNoteCache = function(content, clear) {
if(!Note.cache[content.NoteId]) {
Note.cache[content.NoteId] = content;
} else {
// console.log('pre');
// console.log(Note.cache[content.NoteId].IsBlog);
$.extend(Note.cache[content.NoteId], content);
// console.log(Note.cache[content.NoteId].IsBlog);
}
if(clear == undefined) {
clear = true;
}
@@ -228,7 +231,7 @@ Note.curHasChanged = function(force) {
} catch(e) {
}
}
var hasChanged = {
hasChanged: false, // 总的是否有改变
IsNew: cacheNote.IsNew, // 是否是新添加的
@@ -238,11 +241,11 @@ Note.curHasChanged = function(force) {
NotebookId: cacheNote.NotebookId,
Version: cacheNote.Version || 0, // 版本控制
};
if(hasChanged.IsNew) {
$.extend(hasChanged, cacheNote);
} else {
if(!cacheNote.isDirty) {
if(!force && !cacheNote.isDirty) {
log("no dirty");
hasChanged.hasChanged = false;
return hasChanged;
@@ -619,7 +622,10 @@ Note.changeNote = function(selectNoteId, isShare, needSaveChanged, callback) {
}
// 这里要切换编辑器
switchEditor(cacheNote.IsMarkdown)
switchEditor(cacheNote.IsMarkdown);
// 发送事件
LEA.trigger('noteChanged', cacheNote);
Attach.renderNoteAttachNum(selectNoteId, true);
@@ -631,9 +637,9 @@ Note.changeNote = function(selectNoteId, isShare, needSaveChanged, callback) {
return;
}
Note.setNoteCache(ret, false);
// 把其它信息也带上
ret = Note.cache[selectNoteId]
Note.renderNoteContent(ret);
/* 都用editable的render
if(hasPerm) {
@@ -651,7 +657,7 @@ Note.changeNote = function(selectNoteId, isShare, needSaveChanged, callback) {
setContent(cacheNote);
return;
}
var url = "/note/getNoteContent";
var param = {noteId: selectNoteId};
if(isShare) {
@@ -663,7 +669,11 @@ Note.changeNote = function(selectNoteId, isShare, needSaveChanged, callback) {
if(Note.contentAjax != null) {
Note.contentAjax.abort();
}
Note.contentAjax = ajaxGet(url, param, setContent);
Note.contentAjax = ajaxGet(url, param, function (ret) {
// 因为之前Content内的IsBlog和Note的IsBlog不同步, 所以去掉Content中的IsBlog
delete ret['IsBlog'];
setContent(ret);
});
}
// 渲染
@@ -1075,69 +1085,16 @@ Note.shareNote = function(target) {
var noteId = $(target).attr("noteId");
shareNoteOrNotebook(noteId, true);
}
};
// 历史记录
Note.listNoteContentHistories = function() {
// 弹框
$("#leanoteDialog #modalTitle").html(getMsg("history"));
$content = $("#leanoteDialog .modal-body");
$content.html("");
$("#leanoteDialog .modal-footer").html('<button type="button" class="btn btn-default" data-dismiss="modal">' + getMsg("close") + '</button>');
options = {}
options.show = true;
$("#leanoteDialog").modal(options);
ajaxGet("/noteContentHistory/listHistories", {noteId: Note.curNoteId}, function(re) {
if(!isArray(re)) {$content.html(getMsg("noHistories")); return}
// 组装成一个tab
var str = "<p>" + getMsg("historiesNum") + '</p><div id="historyList"><table class="table table-hover">';
note = Note.cache[Note.curNoteId];
var s = "div"
if(note.IsMarkdown) {
s = "pre";
}
for (i in re) {
var content = re[i]
content.Ab = Note.genAbstract(content.Content, 200);
// 为什么不用tt(), 因为content可能含??
str += '<tr><td seq="' + i + '">#' + (i+1) +'<' + s + ' class="each-content">' + content.Ab + '</' + s + '> <div class="btns">' + getMsg("datetime") + ': <span class="label label-default">' + goNowToDatetime(content.UpdatedTime) + '</span> <button class="btn btn-default all">' + getMsg("unfold") + '</button> <button class="btn btn-primary back">' + getMsg('restoreFromThisVersion') + '</button></div></td></tr>';
}
str += "</table></div>";
$content.html(str);
$("#historyList .all").click(function() {
$p = $(this).parent().parent();
var seq = $p.attr("seq");
var $c = $p.find(".each-content");
var info = re[seq];
if(!info.unfold) { // 默认是折叠的
$(this).text(getMsg("fold")); // 折叠
$c.html(info.Content);
info.unfold = true;
} else {
$(this).text(getMsg("unfold")); // 展开
$c.html(info.Ab);
info.unfold = false
}
});
// 还原
$("#historyList .back").click(function() {
$p = $(this).parent().parent();
var seq = $p.attr("seq");
if(confirm(getMsg("confirmBackup"))) {
// 保存当前版本
Note.curChangedSaveIt();
// 设置之
note = Note.cache[Note.curNoteId];
setEditorContent(re[seq].Content, note.IsMarkdown);
//
hideDialog();
}
});
});
}
// 下载
Note.download = function(url, params) {
var inputs = '';
for (var i in params) {
inputs += '<input name="' + i + '" value="' + params[i] + '">';
}
$('<form target="mdImageManager" action="' + url + '" method="GET">' + inputs + '</form>').appendTo('body').submit().remove();
};
//--------------
// read only
@@ -1256,14 +1213,15 @@ Note.setNote2Blog = function(target) {
if(note.IsBlog != undefined) {
isBlog = !note.IsBlog;
}
// 标志添加/去掉
if(isBlog) {
$(target).find(".item-blog").show();
} else {
$(target).find(".item-blog").hide();
}
ajaxPost("/note/setNote2Blog", {noteId: noteId, isBlog: isBlog}, function(ret) {
if(ret) {
// 标志添加/去掉
if(isBlog) {
$(target).find(".item-blog").show();
} else {
$(target).find(".item-blog").hide();
}
Note.setNoteCache({NoteId: noteId, IsBlog: isBlog}, false); // 不清空NotesByNotebookId缓存
}
});
@@ -1482,6 +1440,11 @@ Note.toggleWriteable = function() {
Note.readOnly = false;
};
Note.getPostUrl = function (note) {
var urlTitle = note.UrlTitle || note.NoteId;
return UserInfo.PostUrl + '/' + urlTitle;
};
// 这里速度不慢, 很快
Note.getContextNotebooks = function(notebooks) {
var moves = [];
@@ -1578,6 +1541,8 @@ Note.initContextmenu = function() {
items.push("set2Blog");
items.push("copy");
} else {
// console.log('haha');
// console.log(note);
// 是否已公开为blog
if(!note.IsBlog) {
items.push("unset2Blog");
@@ -1591,11 +1556,12 @@ Note.initContextmenu = function() {
items.push("copy." + notebookTitle);
}
// diable 这里
menu.applyrule({
name: "target..",
disable: true,
items: items
});
});
}
function beforeContextMenu() {
@@ -1630,7 +1596,7 @@ var Attach = {
e.stopPropagation();
var attachId = $(this).closest('li').data("id");
var t = this;
if(confirm("Are you sure to delete it ?")) {
if(confirm(getMsg("Are you sure to delete it ?"))) {
$(t).button("loading");
ajaxPost("/attach/deleteAttach", {attachId: attachId}, function(re) {
$(t).button("reset");
@@ -1646,21 +1612,20 @@ var Attach = {
self.attachListO.on("click", ".download-attach", function(e) {
e.stopPropagation();
var attachId = $(this).closest('li').data("id");
window.open(UrlPrefix + "/attach/download?attachId=" + attachId);
// location.href = "/attach/download?attachId=" + attachId;
Note.download(UrlPrefix + "/attach/download", {attachId:attachId});
});
// 下载全部
self.downloadAllBtnO.click(function() {
window.open(UrlPrefix + "/attach/downloadAll?noteId=" + Note.curNoteId);
// location.href = "/attach/downloadAll?noteId=" + Note.curNoteId;
Note.download(UrlPrefix + "/attach/downloadAll", {noteId: Note.curNoteId});
});
// make link
self.attachListO.on("click", ".link-attach", function(e) {
e.stopPropagation();
var attachId = $(this).closest('li').data("id");
var attach = self.attachsMap[attachId];
var src = UrlPrefix + "/attach/download?attachId=" + attachId;
Note.toggleWriteable();
if(LEA.isMarkdownEditor() && MD) {
MD.insertLink(src, attach.Title);
} else {
@@ -1668,8 +1633,9 @@ var Attach = {
tinymce.activeEditor.insertContent('<a target="_blank" href="' + src + '">' + attach.Title + '</a>');
}
});
// make all link
/*
self.linkAllBtnO.on("click",function(e) {
e.stopPropagation();
var note = Note.getCurNote();
@@ -1685,6 +1651,7 @@ var Attach = {
tinymce.activeEditor.insertContent('<a target="_blank" href="' + src + '">' + title + '</a>');
}
});
*/
},
attachListO: $("#attachList"),
attachNumO: $("#attachNum"),
@@ -1728,14 +1695,17 @@ var Attach = {
*/
var html = "";
var attachNum = attachs.length;
var titleDelete = getMsg('Delete');
var titleDownload = getMsg('Download');
var titleLink = getMsg('Insert link into content');
for(var i = 0; i < attachNum; ++i) {
var each = attachs[i];
html += '<li class="clearfix" data-id="' + each.AttachId + '">' +
'<div class="attach-title">' + each.Title + '</div>' +
'<div class="attach-process"> ' +
' <button class="btn btn-sm btn-warning delete-attach" data-loading-text="..."><i class="fa fa-trash-o"></i></button> ' +
' <button type="button" class="btn btn-sm btn-primary download-attach"><i class="fa fa-download"></i></button> ' +
' <button type="button" class="btn btn-sm btn-default link-attach" title="Insert link into content"><i class="fa fa-link"></i></button> ' +
' <button class="btn btn-sm btn-warning delete-attach" data-loading-text="..." title="' + titleDelete + '"><i class="fa fa-trash-o"></i></button> ' +
' <button type="button" class="btn btn-sm btn-primary download-attach" title="' + titleDownload + '"><i class="fa fa-download"></i></button> ' +
' <button type="button" class="btn btn-sm btn-default link-attach" title="' + titleLink + '"><i class="fa fa-link"></i></button> ' +
'</div>' +
'</li>';
self.attachsMap[each.AttachId] = each;
@@ -1807,7 +1777,7 @@ var Attach = {
},
downloadAll: function() {
}
}
};
//------------------- 事件
$(function() {
@@ -1824,7 +1794,9 @@ $(function() {
}
});
$("#noteItemList").on("click", ".item", function(event) {
event.stopPropagation();
// 为什么要stop, 这会导致context, dropdown不隐藏
// event.stopPropagation();
var noteId = $(this).attr("noteId");
// 手机端处理
@@ -1839,7 +1811,7 @@ $(function() {
Note.changeNoteForPjax(noteId, true, false);
}
});
// 当前笔记可以已修改
$('#editorContent, #wmd-input, #noteTitle').on('keyup input', function() {
Note.curNoteIsDirtied();
@@ -1849,7 +1821,7 @@ $(function() {
Note.curNoteIsDirtied();
});
*/
//------------------
// 新建笔记
// 1. 直接点击新建 OR
@@ -1901,33 +1873,39 @@ $(function() {
//--------------------
// Note.initContextmenu();
//------------
// 文档历史
$("#contentHistory").click(function() {
Note.listNoteContentHistories()
});
$("#saveBtn").click(function() {
Note.curChangedSaveIt(true);
});
// blog
$("#noteItemList").on("click", ".item-blog", function(e) {
e.preventDefault();
// 这导致其它dropdown不能隐藏
e.stopPropagation();
// 所以
$(document).click();
// 得到ID
var noteId = $(this).parent().attr('noteId');
window.open("/blog/view/" + noteId);
var note = Note.getNote(noteId);
if (note) {
window.open(Note.getPostUrl(note));
}
});
// note setting
$("#noteItemList").on("click", ".item-my .item-setting", function(e) {
e.preventDefault();
// 这导致其它dropdown不能隐藏
e.stopPropagation();
// 所以
$(document).click();
var $p = $(this).parent();
Note.contextmenu.showMenu(e, $p);
});
// readony
// 修改
$('.toolbar-update').click(function() {

View File

@@ -480,7 +480,8 @@ function initEditor() {
e.preventDefault();
return;
}
Note.saveNote(e);
// 这里就不要了, 避免两次updateNote
// Note.saveNote(e);
// 当输入的时候, 把当前raw删除掉
LeaAce.removeCurToggleRaw();
@@ -511,12 +512,12 @@ function initEditor() {
"searchreplace leanote_nav leanote_code tabfocus",
"table textcolor" ], // nonbreaking directionality charmap
toolbar1 : "formatselect | forecolor backcolor | bold italic underline strikethrough | leaui_image | leanote_code leanote_inline_code | bullist numlist | alignleft aligncenter alignright alignjustify",
toolbar2 : "outdent indent blockquote | link unlink | table | hr removeformat | subscript superscript |searchreplace | pastetext pasteCopyImage | leanote_ace_pre | fontselect fontsizeselect",
toolbar2 : "outdent indent blockquote | link unlink | table | hr removeformat | subscript superscript |searchreplace | pastetext | leanote_ace_pre | fontselect fontsizeselect",
// 使用tab键: http://www.tinymce.com/wiki.php/Plugin3x:nonbreaking
// http://stackoverflow.com/questions/13543220/tiny-mce-how-to-allow-people-to-indent
// nonbreaking_force_tab : true,
menubar : false,
toolbar_items_size : 'small',
statusbar : false,
@@ -554,7 +555,7 @@ function initEditor() {
window.onbeforeunload = function(e) {
Note.curChangedSaveIt();
}
// 全局ctrl + s
$("body").on('keydown', Note.saveNote);
}
@@ -813,12 +814,7 @@ function scrollTo(self, tagName, text) {
// $ul.css("max-height", getMaxDropdownHeight(this));
});
//--------
// 编辑器帮助
$("#tipsBtn").click(function() {
showDialog2("#tipsDialog");
});
/*
//--------
// 建议
$("#yourSuggestions").click(function() {
@@ -843,6 +839,7 @@ function scrollTo(self, tagName, text) {
}
});
});
*/
// 编辑器模式
em.init();
@@ -916,10 +913,12 @@ var Pjax = {
// ajax后调用
changeNote: function(noteInfo) {
var me = this;
log("push");
var noteId = noteInfo.NoteId;
var title = noteInfo.Title;
var url = '/note/' + noteId;
if (location.href.indexOf('?online') > 0) {
url += '?online=1'
}
if(location.hash) {
url += location.hash;
}

View File

@@ -28,6 +28,54 @@ var MarkdownEditor;
var ScrollLink;
var MD;
//-------------
// 全局事件机制
$.extend(LEA, {
_eventCallbacks: {},
_listen: function(type, callback) {
var callbacks = this._eventCallbacks[type] || (this._eventCallbacks[type] = []);
callbacks.push(callback);
},
// on('a b', function(params) {})
on: function(name, callback) {
var names = name.split(/\s+/);
for (var i = 0; i < names.length; ++i) {
this._listen(names[i], callback);
}
return this;
},
// off('a b', function(params) {})
off: function(name, callback) {
var types = name.split(/\s+/);
var i, j, callbacks, removeIndex;
for (i = 0; i < types.length; i++) {
callbacks = this._eventCallbacks[types[i].toLowerCase()];
if (callbacks) {
removeIndex = null;
for (j = 0; j < callbacks.length; j++) {
if (callbacks[j] == callback) {
removeIndex = j;
}
}
if (removeIndex !== null) {
callbacks.splice(removeIndex, 1);
}
}
}
},
// LEA.trigger('a', {});
trigger: function(type, params) {
var callbacks = this._eventCallbacks[type] || [];
if (callbacks.length === 0) {
return;
}
for (var i = 0; i < callbacks.length; i++) {
callbacks[i].call(this, params);
}
}
});
//---------------------
// 公用方法
@@ -829,10 +877,11 @@ function hideLoading() {
}
// 注销, 先清空cookie
function setCookie(c_name, value, expiredays){
function setCookie(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString());
document.cookie = c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) + 'path=/';
document.cookie = c_name+ "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) + 'path=/note';
}
function logout() {
setCookie("LEANOTE_SESSION", '', -1);

View File

@@ -0,0 +1 @@
.b-m-mpanel{background:url(images/contextmenu/menu_bg.gif) left repeat-y #fff;border:1px solid #ccc;position:absolute;padding:2px 0;z-index:99997;left:0;top:0;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box;overflow:auto}.b-m-split{height:6px;background:url(images/contextmenu/m_splitLine.gif) center repeat-x;font-size:0;margin:0 2px}.b-m-idisable,.b-m-ifocus,.b-m-item{padding:4px 10px 4px 4px;cursor:default;line-height:100%}.b-m-idisable{color:grey}.b-m-arrow,.b-m-ibody{overflow:hidden;text-overflow:ellipsis}.b-m-arrow{background:url(images/contextmenu/m_arrow.gif) right no-repeat}.b-m-idisable .b-m-arrow{background:0 0}.b-m-idisable img,.b-m-ifocus img,.b-m-item img{margin-right:8px;width:16px}.b-m-ifocus{background-color:#CDE3F6}.b-m-idisable img{visibility:hidden}.c-text{display:inline-block;padding-left:3px}.b-m-icon{width:23px;padding-left:3px}

File diff suppressed because one or more lines are too long

37
public/js/home/index.js Normal file
View File

@@ -0,0 +1,37 @@
/* /index 首页 */
$(function() {
// 平滑滚动
$(".smooth-scroll").click(function(e) {
e.preventDefault();
var t = $(this).data("target");
var targetOffset = $(t).offset().top - 80;
$('html,body').animate({scrollTop: targetOffset}, 300);
});
function slider(webImgs, descT) {
var webImgsLen = webImgs.length;
var curIndex = 0;
setInterval(function() {
webImgs.eq(curIndex).stop().animate({opacity: '0'}, 1000);
curIndex = (curIndex+1)%webImgsLen;
var curImg = webImgs.eq(curIndex);
curImg.stop().animate({opacity: '1'}, 1000);
descT.text(curImg.data("text"));
}, 5000);
}
slider($(".web-slider"), $("#webText"));
slider($(".mobile-slider"), $("#mobileText"));
function setCookie(name, value) {
var Days = 10*365;
var exp = new Date();
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
$('#lang a').click(function() {
var lang = $(this).data('lang');
setCookie('LEANOTE_LANG', lang);
location.reload();
});
});

View File

@@ -1,16 +1 @@
var MSG = {"a":"a","aboutMe":"About Me","author":"Author","baseInfoSet":"Base info","blogClass":"Category","blogDesc":"Description","blogLogo":"Logo","blogLogoTips":"Upload image to replace blog title","blogName":"Title","blogNav":"Blog nav","blogNavs":"Navs","blogSet":"Blog configuration","cancel":"Cancel","chooseComment":"Comment System","chooseReason":"请选择举报理由","comment":"Comment","commentSet":"Comment","comments":"Comments","community":"Community","confirm":"Confirm","confirmDeleteComment":"Are you sure?","createdTime":"Created at","daysAgo":"days ago","delete":"Delete","disqusHelp":"Please input your Disqus Id","domain":"Custom domain","domainSet":"Domain","elegant":"Elegant","error":"Error","fullBlog":"Full blog","home":"Home","hoursAgo":"hours ago","justNow":"Just now","latestPosts":"Latest posts","like":"Like","minutesAgo":"minutes ago","monthsAgo":"months ago","more":"More...","moreShare":"More","navFixed":"Nav fixed at left side","needHelp":"Need help?","next":"Next","noBlog":"No blog","noTag":"No tag","none":"None","openComment":"Open comment?","other":"Other","previous":"Previous","qqZone":"QQ Zone","quickLinks":"Quick links","renren":"Renren","reply":"Reply","report":"Report","reportBlog?":"举报该博客?","reportComment?":"举报该评论?","reportReason":"Reason","reportReason1":"不友善内容","reportReason2":"广告等垃圾信息","reportReason3":"违法违规内容","reportReason4":"不宜公开讨论的政治内容","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","saveSuccess":"Save success","scanQRCode":"Open weichat and scan the QR code","signIn":"Sign In","signUp":"Sign Up","sinaWeibo":"Weibo","subDomain":"Sub domain","submitComment":"Submit","tencentWeibo":"Tencent Weibo","theme":"Theme","themeSet":"Theme","unlike":"Unlike","updatedTime":"Updated at","viewers":"Viewers","weeksAgo":"weeks ago","weixin":"Weichat"};
function getMsg(key, data) {
var msg = MSG[key]
if(msg) {
if(data) {
if(!isArray(data)) {
data = [data];
}
for(var i = 0; i < data.length; ++i) {
msg = msg.replace("%s", data[i]);
}
}
return msg;
}
return key;
}
var MSG={"noTag":"No tag","saveSuccess":"Save success","none":"None","like":"Like","unlike":"Unlike","delete":"Delete","cancel":"Cancel","confirm":"Confirm","chooseReason":"请选择举报理由","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","error":"Error","reportComment?":"举报该评论?","reportBlog?":"举报该博客?","confirmDeleteComment":"Are you sure?","scanQRCode":"Open weichat and scan the QR code","justNow":"Just now","minutesAgo":"minutes ago","hoursAgo":"hours ago","daysAgo":"days ago","weeksAgo":"weeks ago","monthsAgo":"months ago"};function getMsg(key, data) {var msg = MSG[key];if(msg) {if(data) {if(!isArray(data)) {data = [data];}for(var i = 0; i < data.length; ++i) {msg = msg.replace("%s", data[i]);}}return msg;}return key;}

View File

@@ -1,16 +1 @@
var MSG = {"a":"a","aboutMe":"A propos de moi","author":"Auteur","baseInfoSet":"Information de base","blogClass":"Catégorie","blogDesc":"Description","blogLogo":"Logo","blogLogoTips":"Téléverser une image pour remplacer le titre du blog","blogName":"Titre","blogNav":"Navigation du blog","blogNavs":"Navigation","blogSet":"Configuration du blog","cancel":"Annuler","chooseComment":"Système de commentaires","chooseReason":"请选择举报理由","comment":"Commenter","commentSet":"Commentaires","comments":"Commentaires","community":"Communauté","confirm":"Confirmer","confirmDeleteComment":"Êtes-vous sûr?","createdTime":"Créé à","daysAgo":"Il y a plusieurs jours","delete":"Effacer","disqusHelp":"Veuillez renseigner votre identifiant Disqus","domain":"Domaine personnalisé","domainSet":"Domaine","elegant":"Elegant","error":"Erreur","fullBlog":"Blog entier","home":"Accueil","hoursAgo":"Il y a plusieurs heures","justNow":"Seulement maintenant","latestPosts":"Dernières publications","like":"J'aime","minutesAgo":"Il y a quelques minutes","monthsAgo":"Il y a plusieurs mois","more":"Plus...","moreShare":"Plus","navFixed":"Navigation figée sur le côté gauche","needHelp":"Besoin d'aide?","next":"Suivant","noBlog":"Aucun blog","noTag":"Aucune étiquette","none":"Aucun","openComment":"Ouvrir un commentaire?","other":"Autre","previous":"Précédent","qqZone":"QQ Zone","quickLinks":"Liens rapides","renren":"Renren","reply":"Répondre","report":"Rapport","reportBlog?":"举报该博客?","reportComment?":"举报该评论?","reportReason":"Raison","reportReason1":"不友善内容","reportReason2":"广告等垃圾信息","reportReason3":"违法违规内容","reportReason4":"不宜公开讨论的政治内容","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","saveSuccess":"Sauvegarde réussie","scanQRCode":"Ouvrez Weichat et scannez le QR Code","signIn":"S'identifier","signUp":"S'incrire","sinaWeibo":"Weibo","subDomain":"Sous-domaine","submitComment":"Soumettre","tencentWeibo":"Tencent Weibo","theme":"Thème","themeSet":"Thème","unlike":"Je n'aime plus","updatedTime":"Mis à jour à","viewers":"Lecteurs","weeksAgo":"Il y a plusieurs semaines","weixin":"Weichat"};
function getMsg(key, data) {
var msg = MSG[key]
if(msg) {
if(data) {
if(!isArray(data)) {
data = [data];
}
for(var i = 0; i < data.length; ++i) {
msg = msg.replace("%s", data[i]);
}
}
return msg;
}
return key;
}
var MSG={"noTag":"Aucune étiquette","saveSuccess":"Sauvegarde réussie","none":"Aucun","like":"J'aime","unlike":"Je n'aime plus","delete":"Effacer","cancel":"Annuler","confirm":"Confirmer","chooseReason":"请选择举报理由","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","error":"Erreur","reportComment?":"举报该评论?","reportBlog?":"举报该博客?","confirmDeleteComment":"Êtes-vous sûr?","scanQRCode":"Ouvrez Weichat et scannez le QR Code","justNow":"Seulement maintenant","minutesAgo":"Il y a quelques minutes","hoursAgo":"Il y a plusieurs heures","daysAgo":"Il y a plusieurs jours","weeksAgo":"Il y a plusieurs semaines","monthsAgo":"Il y a plusieurs mois"};function getMsg(key, data) {var msg = MSG[key];if(msg) {if(data) {if(!isArray(data)) {data = [data];}for(var i = 0; i < data.length; ++i) {msg = msg.replace("%s", data[i]);}}return msg;}return key;}

View File

@@ -1,16 +1 @@
var MSG = {"a":"a","aboutMe":"关于我","author":"作者","baseInfoSet":"基本设置","blog":"博客","blogClass":"分类","blogDesc":"博客描述","blogLogo":"博客Logo","blogLogoTips":"上传logo将显示logo(替代博客标题)","blogName":"博客标题","blogNav":"导航","blogNavs":"导航","blogSet":"博客设置","cancel":"取消","chooseComment":"选择评论系统","chooseReason":"请选择举报理由","comment":"评论","commentSet":"评论设置","comments":"评论","community":"社区","confirm":"确认","confirmDeleteComment":"确定删除该评论?","createdTime":"创建","daysAgo":"天前","delete":"删除","disqusHelp":"请填写您申请的Disqus唯一url前缀. 建议您申请Disqus帐号, 这样可以自己管理评论. 或使用leanote的默认Disqus Id. ","domain":"自定义域名","domainSet":"域名设置","elegant":"大气","error":"错误","fullBlog":"全文","home":"主页","hoursAgo":"个小时前","justNow":"刚刚","latestPosts":"最近发表","like":"赞","minutesAgo":"分钟前","monthsAgo":"个月前","more":"更多...","moreShare":"更多分享","navFixed":"导航左侧固定","needHelp":"需要帮助?","next":"下一页","noBlog":"无博客","noTag":"无","none":"无","openComment":"开启评论?","other":"其它","previous":"上一页","qqZone":"QQ空间","quickLinks":"快速链接","renren":"人人网","reply":"回复","report":"举报","reportBlog?":"举报该博客?","reportComment?":"举报该评论?","reportReason":"举报理由","reportReason1":"不友善内容","reportReason2":"广告等垃圾信息","reportReason3":"违法违规内容","reportReason4":"不宜公开讨论的政治内容","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","saveSuccess":"保存成功","scanQRCode":"打开微信扫一扫二维码","signIn":"登录","signUp":"注册","sinaWeibo":"新浪微博","subDomain":"博客子域名","submitComment":"发表评论","tencentWeibo":"腾讯微博","theme":"主题","themeSet":"主题设置","unlike":"取消赞","updatedTime":"更新","viewers":"人读过","weeksAgo":"周前","weixin":"微信"};
function getMsg(key, data) {
var msg = MSG[key]
if(msg) {
if(data) {
if(!isArray(data)) {
data = [data];
}
for(var i = 0; i < data.length; ++i) {
msg = msg.replace("%s", data[i]);
}
}
return msg;
}
return key;
}
var MSG={"noTag":"","saveSuccess":"保存成功","none":"无","like":"赞","unlike":"取消赞","delete":"删除","cancel":"取消","confirm":"确认","chooseReason":"请选择举报理由","reportSuccess":"举报成功, 我们处理后会通知作者, 感谢您的监督","error":"错误","reportComment?":"举报该评论?","reportBlog?":"举报该博客?","confirmDeleteComment":"确定删除该评论?","scanQRCode":"打开微信扫一扫二维码","justNow":"刚刚","minutesAgo":"分钟前","hoursAgo":"个小时前","daysAgo":"天前","weeksAgo":"前","monthsAgo":"个月前"};function getMsg(key, data) {var msg = MSG[key];if(msg) {if(data) {if(!isArray(data)) {data = [data];}for(var i = 0; i < data.length; ++i) {msg = msg.replace("%s", data[i]);}}return msg;}return key;}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -25,7 +25,6 @@ define('attachment_upload', ['jquery.ui.widget', 'fileupload'], function(){
if(timeout) {
clearTimeout(timeout);
}
var found = false,
node = e.target;
do {
@@ -48,7 +47,6 @@ define('attachment_upload', ['jquery.ui.widget', 'fileupload'], function(){
}
setDropStyle("#dropAttach", "#uploadAttach");
setDropStyle("#dropAvatar", "#uploadAvatar");
var initUploader = function() {
$('.dropzone .btn-choose-file').click(function() {
@@ -140,76 +138,6 @@ define('attachment_upload', ['jquery.ui.widget', 'fileupload'], function(){
$("#uploadAttachMsg").scrollTop(1000);
}
});
//-------------------
// 已经过时, 没有avatar了
var $msg2 = $('#avatarUploadMsg');
$('#uploadAvatar').fileupload({
dataType: 'json',
dropZone: $('#dropAvatar'),
pasteZone: '',
add: function(e, data) {
var tpl = $('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');
// Append the file name and file size
tpl.append(data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small>');
// Add the HTML to the UL element
$msg2.html(tpl);
data.context = $msg2;
// 检查文件大小
var size = data.files[0].size;
var maxFileSize = +GlobalConfigs["uploadAvatarSize"] || 100;
if(typeof size == 'number' && size > 1024 * 1024 * maxFileSize) {
tpl.find("img").remove();
tpl.removeClass("alert-info").addClass("alert-danger");
tpl.append(" Warning: File size is bigger than " + maxFileSize + "M");
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
return;
}
// Automatically upload the file once it is added to the queue
var jqXHR;
setTimeout(function() {
jqXHR = data.submit();
}, 10);
},
done: function(e, data) {
if (data.result.Ok == true) {
data.context.html("");
var re = data.result;
$("#avatar").attr("src", UrlPrefix + "/" + re.Id);
} else {
var re = data.result;
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.result.Msg);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
}
},
fail: function(e, data) {
data.context.html("");
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.errorThrown);
data.context.html(tpl);
setTimeout((function(tpl) {
return function() {
tpl.remove();
}
})(tpl), 3000);
}
});
};
initUploader();

View File

@@ -258,6 +258,7 @@ define('editor_drop_paste', ['jquery.ui.widget', 'fileupload'], function(){
});
};
var lastTime = 0;
// pasteImage
var pasteImageInit = function() {
@@ -285,7 +286,19 @@ define('editor_drop_paste', ['jquery.ui.widget', 'fileupload'], function(){
data.process.update(data.loaded / data.total);
}
},
// 调用了两次
// 不知道为什么会触发两次
add: function(e, data) {
// 防止两次
var now = (new Date()).getTime();
if (now - lastTime < 500) {
// console.log('haha');
return;
}
// console.log('nono');
lastTime = now;
var note = Note.getCurNote();
curNote = note;
if(!note || note.IsNew) {

View File

@@ -0,0 +1,161 @@
/**
* @file 历史记录
* @author life
*
*/
define('history', [], function() {
var tpl = ['<div class="modal fade history-modal" tabindex="-1" role="dialog" aria-hidden="true">',
'<div class="modal-dialog modal-lg ">',
'<div class="modal-content">',
'<div class="modal-header">',
'<h4 class="modal-title" class="modalTitle">' + + '</h4>',
'</div>',
'<div class="modal-body clearfix">',
'<div class="history-list-wrap pull-left">',
'<div class="history-list-header">' + getMsg('history') +' (<span class="history-num"></span>)</div>',
'<div class="history-list list-group"></div>',
'</div>',
'<div class="history-content-wrap pull-left">',
'<div class="history-content-header">',
'<a class="btn btn-primary back">' + getMsg('restoreFromThisVersion') + '</a>',
'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>',
'</div>',
'<div class="history-content"></div>',
'</div>',
'</div>',
'<div class="modal-footer hide">',
'<button type="button" class="btn btn-default" data-dismiss="modal">' + getMsg('close') + '</button>',
'</div>',
'</div>',
'</div>',
'</div>'].join('');
var $tpl = $(tpl);
var $historyContent = $tpl.find('.history-content');
var $historyList = $tpl.find('.history-list');
var $historyNum = $tpl.find('.history-num');
var view = {
note: null,
list: [],
curIndex: 0,
renderContent: function (i) {
var content = this.list[i].Content;
this.curIndex = i;
var wrap = '<div>';
var wrapEnd = '</div>';
if (this.note.IsMarkdown) {
wrap = '<pre>';
wrapEnd = '</pre>';
}
$historyContent.html(wrap + content + wrapEnd);
var as = $historyList.find('a');
as.removeClass('active');
as.eq(i).addClass('active');
},
render: function (list) {
var navs = '';
this.list = list;
if (list) {
for(var i = 0; i < list.length; ++i) {
var content = list[i];
navs += '<a class="list-group-item" data-index="' + i + '"><span class="badge">#' + (i+1)+ '</span>' + goNowToDatetime(content.UpdatedTime) + '</a>';
}
}
$historyList.html(navs);
this.renderContent(0);
$historyNum.html(list.length);
// show
$tpl.modal({show: true});
},
bind: function () {
var me = this;
$("#contentHistory").click(function() {
me.getHistories();
});
$historyList.on('click', 'a', function () {
var index = $(this).data('index');
me.renderContent(index);
});
// 还原
$tpl.find('.back').click(function() {
if(confirm(getMsg("confirmBackup"))) {
// 保存当前版本
Note.curChangedSaveIt(true);
// 设置之
note = Note.cache[Note.curNoteId];
setEditorContent(me.list[me.curIndex].Content, note.IsMarkdown);
$tpl.modal('hide');
// 保存
Note.curChangedSaveIt(true);
}
});
},
getHistories: function () {
var me = this;
var note = Note.getCurNote();
me.note = note;
ajaxGet("/noteContentHistory/listHistories", {noteId: Note.curNoteId}, function(re) {
if(!isArray(re)) {
alert(getMsg('noHistories'));
return;
}
me.render(re);
return;
// 组装成一个tab
var str = "<p>" + getMsg("historiesNum") + '</p><div id="historyList"><table class="table table-hover">';
note = Note.cache[Note.curNoteId];
var s = "div"
if(note.IsMarkdown) {
s = "pre";
}
for (i in re) {
var content = re[i]
content.Ab = Note.genAbstract(content.Content, 200);
// 为什么不用tt(), 因为content可能含??
str += '<tr><td seq="' + i + '">#' + (i+1) +'<' + s + ' class="each-content">' + content.Ab + '</' + s + '> <div class="btns">' + getMsg("datetime") + ': <span class="label label-default">' + goNowToDatetime(content.UpdatedTime) + '</span> <button class="btn btn-default all">' + getMsg("unfold") + '</button> <button class="btn btn-primary back">' + getMsg('restoreFromThisVersion') + '</button></div></td></tr>';
}
str += "</table></div>";
$content.html(str);
$("#historyList .all").click(function() {
$p = $(this).parent().parent();
var seq = $p.attr("seq");
var $c = $p.find(".each-content");
var info = re[seq];
if(!info.unfold) { // 默认是折叠的
$(this).text(getMsg("fold")); // 折叠
$c.html(info.Content);
info.unfold = true;
} else {
$(this).text(getMsg("unfold")); // 展开
$c.html(info.Ab);
info.unfold = false
}
});
});
},
init: function () {
var me = this;
this.bind();
}
};
view.init();
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(t){"use strict";t(window.jQuery)}(function(t){"use strict";var e=0;t.ajaxTransport("iframe",function(r){if(r.async){var a,n,p;return{send:function(o,i){a=t('<form style="display:none;"></form>'),a.attr("accept-charset",r.formAcceptCharset),p=/\?/.test(r.url)?"&":"?","DELETE"===r.type?(r.url=r.url+p+"_method=DELETE",r.type="POST"):"PUT"===r.type?(r.url=r.url+p+"_method=PUT",r.type="POST"):"PATCH"===r.type&&(r.url=r.url+p+"_method=PATCH",r.type="POST"),n=t('<iframe src="javascript:false;" name="iframe-transport-'+(e+=1)+'"></iframe>').bind("load",function(){var e,p=t.isArray(r.paramName)?r.paramName:[r.paramName];n.unbind("load").bind("load",function(){var e;try{if(e=n.contents(),!e.length||!e[0].firstChild)throw new Error}catch(r){e=void 0}i(200,"success",{iframe:e}),t('<iframe src="javascript:false;"></iframe>').appendTo(a),a.remove()}),a.prop("target",n.prop("name")).prop("action",r.url).prop("method",r.type),r.formData&&t.each(r.formData,function(e,r){t('<input type="hidden"/>').prop("name",r.name).val(r.value).appendTo(a)}),r.fileInput&&r.fileInput.length&&"POST"===r.type&&(e=r.fileInput.clone(),r.fileInput.after(function(t){return e[t]}),r.paramName&&r.fileInput.each(function(e){t(this).prop("name",p[e]||r.paramName)}),a.append(r.fileInput).prop("enctype","multipart/form-data").prop("encoding","multipart/form-data")),a.submit(),e&&e.length&&r.fileInput.each(function(r,a){var n=t(e[r]);t(a).prop("name",n.prop("name")),n.replaceWith(a)})}),a.append(n).appendTo(document.body)},abort:function(){n&&n.unbind("load").prop("src","javascript".concat(":false;")),a&&a.remove()}}}}),t.ajaxSetup({converters:{"iframe text":function(e){return e&&t(e[0].body).text()},"iframe json":function(e){return e&&t.parseJSON(t(e[0].body).text())},"iframe html":function(e){return e&&t(e[0].body).html()},"iframe script":function(e){return e&&t.globalEval(t(e[0].body).text())}}})});

File diff suppressed because one or more lines are too long

38
public/js/plugins/main.js Normal file
View File

@@ -0,0 +1,38 @@
// 插件, 不是立刻就需要的功能
// 1. 上传, 粘贴图片2
// 2. 笔记信息
// 3. 历史记录
// 4. 附件
requirejs.config({
paths: {
// life
'editor_drop_paste': 'js/plugins/editor_drop_paste',
'attachment_upload': 'js/plugins/attachment_upload',
'jquery.ui.widget': 'js/plugins/libs-min/jquery.ui.widget',
'fileupload': 'js/plugins/libs-min/jquery.fileupload',
'iframe-transport': 'js/plugins/libs-min/jquery.iframe-transport',
'note_info': 'js/plugins/note_info',
'tips': 'js/plugins/tips',
'history': 'js/plugins/history',
},
shim: {
// life
'fileupload': {deps: ['jquery.ui.widget', 'iframe-transport']},
}
});
// 异步加载
setTimeout(function () {
// 小异步
require(["editor_drop_paste", "attachment_upload"]);
require(['note_info']);
// 大异步
setTimeout(function () {
require(['tips']);
require(['history']);
}, 10);
});

6
public/js/plugins/main.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,123 @@
/**
* @file 笔记信息
* @author life
*
*/
define('note_info', [], function() {
var tpl = ['<table>',
'<tr><th>' + getMsg('Create Time') + '</th><td id="noteInfoCreatedTime"></td></tr>',
'<tr><th>' + getMsg('Update Time') + '</th><td id="noteInfoUpdatedTime"></td></tr>',
'<tr class="post-url-tr">',
'<th>' + getMsg('Post Url') + '</th>',
'<td>',
'<div class="post-url-wrap">',
'<span class="post-url-base">http://blog.leanote.com/life/post/</span><span><span class="post-url-text">life-life-life-a-leanote</span>',
'<input type="text" class="form-control">',
'</span>',
' <a class="post-url-pencil" title="' + getMsg('update') + '"><i class="fa fa-pencil"></i></a>',
'</div>',
'</td>',
'</tr>',
'</table>'].join('');
var $tpl = $(tpl);
var $noteInfoCreatedTime = $tpl.find('#noteInfoCreatedTime');
var $noteInfoUpdatedTime = $tpl.find('#noteInfoUpdatedTime');
var $noteInfoPostUrl = $tpl.find('#noteInfoPostUrl');
var $noteInfoPostUrlTr = $tpl.find('.post-url-tr');
var $postUrlWrap = $tpl.find('.post-url-wrap');
var $input = $tpl.find('input');
var $postUrlBase = $tpl.find('.post-url-base');
var $postUrlText = $tpl.find('.post-url-text');
var view = {
$noteInfo: $('#noteInfo'),
note: null,
bind: function () {
var me = this;
$('#noteInfoDropdown').click(function () {
me.render();
});
$tpl.find('.post-url-pencil').click(function () {
$postUrlWrap.addClass('post-url-edit');
$input.val(decodeURI(me.note.UrlTitle));
$input.focus();
});
$input.keydown(function (e) {
if(e.keyCode === 13) {
$input.blur();
}
});
$input.blur(function () {
$postUrlWrap.removeClass('post-url-edit');
var val = $input.val();
if (!val) {
return;
}
ajaxPost("/member/blog/updateBlogUrlTitle", {noteId: me.note.NoteId, urlTitle: val}, function(re) {
if(reIsOk(re)) {
var encodedUrl = encodeURI(re.Item);
me.note.UrlTitle = encodedUrl;
$postUrlText.text(decodeURI(me.note.UrlTitle));
} else {
alert(re.Msg || "error");
}
});
});
// 当笔记Change时, 重新render
LEA.on('noteChanged', function (note) {
me.render(note);
});
},
getPostUrl: function (note) {
return '';
},
rendered: false,
render: function (note) {
var me = this;
if (!note) {
note = Note.getCurNote();
}
if (!note) {
return;
}
me.note = note;
$noteInfoCreatedTime.html(goNowToDatetime(note.CreatedTime));
$noteInfoUpdatedTime.html(goNowToDatetime(note.UpdatedTime));
if (!note.IsBlog) {
$noteInfoPostUrlTr.addClass('hide');
}
else {
$noteInfoPostUrlTr.removeClass('hide');
// post-url
$postUrlBase.text(UserInfo.PostUrl + '/');
$postUrlText.text(decodeURI(note.UrlTitle));
}
if (!me.rendered) {
me.$noteInfo.html($tpl);
me.rendered = true;
}
},
init: function () {
this.bind();
}
};
view.init();
});

32
public/js/plugins/tips.js Normal file
View File

@@ -0,0 +1,32 @@
/**
* @file 提示帮助
* @author life
*
*/
define('tips', [], function() {
var tpl = ['<div class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">',
'<div class="modal-dialog modal-sm">',
'<div class="modal-content">',
'<div class="modal-header">',
'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>',
'<h4 class="modal-title" class="modalTitle">' + getMsg('editorTips') + '</h4>',
'</div>',
'<div class="modal-body">' + getMsg('editorTipsInfo') + '</div>',
'<div class="modal-footer">',
'<button type="button" class="btn btn-default" data-dismiss="modal">' + getMsg('close') + '</button>',
'</div>',
'</div>',
'</div>',
'</div>'].join('');
var $tpl = $(tpl);
var view = {
init: function () {
$("#tipsBtn").click(function() {
$tpl.modal({show: true});
});
}
};
view.init();
});

View File

@@ -1,17 +0,0 @@
// 上传, 粘贴图片
requirejs.config({
paths: {
// life
'editor_drop_paste': 'js/upload_paste/editor_drop_paste',
'attachment_upload': 'js/upload_paste/attachment_upload',
'jquery.ui.widget': 'js/upload_paste/libs/jquery.ui.widget',
'fileupload': 'js/upload_paste/libs/jquery.fileupload',
'iframe-transport': 'js/upload_paste/libs/jquery.iframe-transport'
},
shim: {
// life
'fileupload': {deps: ['jquery.ui.widget', 'iframe-transport']},
}
});
require(["editor_drop_paste", "attachment_upload"], function() {
});

View File

@@ -47,8 +47,9 @@ define("tinymce/pasteplugin/Clipboard", [
ajaxPost("/file/copyHttpImage", {src: src}, function(ret) {
if(reIsOk(ret)) {
// 将图片替换之
var src = urlPrefix + "/" + ret.Item;
var dom = editor.dom
// var src = urlPrefix + "/" + ret.Item;
var src = urlPrefix + "/file/outputImage?fileId=" + ret.Id;
var dom = editor.dom;
for(var i in ids) {
var id = ids[i];
var imgElm = dom.get(id);
@@ -114,7 +115,7 @@ define("tinymce/pasteplugin/Clipboard", [
var needCopyImages = {}; // src => [id1,id2]
var time = (new Date()).getTime();
try {
var $html = $("<div>" + html + "</div");
var $html = $("<div>" + html + "</div>");
var $imgs = $html.find("img");
for(var i = 0; i < $imgs.length; ++i) {
var $img = $imgs.eq(i)

View File

@@ -44,26 +44,11 @@ define("tinymce/pasteplugin/Plugin", [
}
}
}
function togglePasteCopyImage() {
if (clipboard.copyImage) {
this.active(false);
clipboard.copyImage = false
} else {
clipboard.copyImage = true;
this.active(true);
if (!userIsInformed2) {
editor.windowManager.alert(
"When copy other site's images (not in leanote) into editor, it will copy the image into your album."
);
userIsInformed2 = true;
}
}
}
self.clipboard = clipboard = new Clipboard(editor);
self.quirks = new Quirks(editor);
self.wordFilter = new WordFilter(editor);
clipboard.copyImage = true;
if (editor.settings.paste_as_text) {
self.clipboard.pasteFormat = "text";
@@ -116,13 +101,6 @@ define("tinymce/pasteplugin/Plugin", [
onclick: togglePlainTextPaste,
active: self.clipboard.pasteFormat == "text"
});
editor.addButton('pasteCopyImage', {
icon: 'copy',
tooltip: "When Paste other site's image, copy it into my album as public image",
onclick: togglePasteCopyImage,
active: self.clipboard.copyImage === true
});
editor.addMenuItem('pastetext', {
text: 'Paste as text',

View File

@@ -117,4 +117,4 @@
writeScripts();
})(this);
// $hash: e0933a5a75e12f26b54b4e7b86f5bdc2
// $hash: 769ceeebf4bee26f9b01e49867bcf0ce

View File

@@ -232,8 +232,9 @@ define("tinymce/pasteplugin/Clipboard", [
ajaxPost("/file/copyHttpImage", {src: src}, function(ret) {
if(reIsOk(ret)) {
// 将图片替换之
var src = urlPrefix + "/" + ret.Item;
var dom = editor.dom
// var src = urlPrefix + "/" + ret.Item;
var src = urlPrefix + "/file/outputImage?fileId=" + ret.Id;
var dom = editor.dom;
for(var i in ids) {
var id = ids[i];
var imgElm = dom.get(id);
@@ -299,7 +300,7 @@ define("tinymce/pasteplugin/Clipboard", [
var needCopyImages = {}; // src => [id1,id2]
var time = (new Date()).getTime();
try {
var $html = $("<div>" + html + "</div");
var $html = $("<div>" + html + "</div>");
var $imgs = $html.find("img");
for(var i = 0; i < $imgs.length; ++i) {
var $img = $imgs.eq(i)
@@ -1103,26 +1104,11 @@ define("tinymce/pasteplugin/Plugin", [
}
}
}
function togglePasteCopyImage() {
if (clipboard.copyImage) {
this.active(false);
clipboard.copyImage = false
} else {
clipboard.copyImage = true;
this.active(true);
if (!userIsInformed2) {
editor.windowManager.alert(
"When copy other site's images (not in leanote) into editor, it will copy the image into your album."
);
userIsInformed2 = true;
}
}
}
self.clipboard = clipboard = new Clipboard(editor);
self.quirks = new Quirks(editor);
self.wordFilter = new WordFilter(editor);
clipboard.copyImage = true;
if (editor.settings.paste_as_text) {
self.clipboard.pasteFormat = "text";
@@ -1175,13 +1161,6 @@ define("tinymce/pasteplugin/Plugin", [
onclick: togglePlainTextPaste,
active: self.clipboard.pasteFormat == "text"
});
editor.addButton('pasteCopyImage', {
icon: 'copy',
tooltip: "When Paste other site's image, copy it into my album as public image",
onclick: togglePasteCopyImage,
active: self.clipboard.copyImage === true
});
editor.addMenuItem('pastetext', {
text: 'Paste as text',

File diff suppressed because one or more lines are too long

View File

@@ -1,611 +0,0 @@
/**
* Clipboard.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/**
* This class contains logic for getting HTML contents out of the clipboard.
*
* We need to make a lot of ugly hacks to get the contents out of the clipboard since
* the W3C Clipboard API is broken in all browsers that have it: Gecko/WebKit/Blink.
* We might rewrite this the way those API:s stabilize. Browsers doesn't handle pasting
* from applications like Word the same way as it does when pasting into a contentEditable area
* so we need to do lots of extra work to try to get to this clipboard data.
*
* Current implementation steps:
* 1. On keydown with paste keys Ctrl+V or Shift+Insert create
* a paste bin element and move focus to that element.
* 2. Wait for the browser to fire a "paste" event and get the contents out of the paste bin.
* 3. Check if the paste was successful if true, process the HTML.
* (4). If the paste was unsuccessful use IE execCommand, Clipboard API, document.dataTransfer old WebKit API etc.
*
* @class tinymce.pasteplugin.Clipboard
* @private
*/
define("tinymce/pasteplugin/Clipboard", [
"tinymce/Env",
"tinymce/dom/RangeUtils",
"tinymce/util/VK",
"tinymce/pasteplugin/Utils"
], function(Env, RangeUtils, VK, Utils) {
return function(editor) {
var self = this, pasteBinElm, lastRng, keyboardPasteTimeStamp = 0, draggingInternally = false;
var pasteBinDefaultContent = '%MCEPASTEBIN%', keyboardPastePlainTextState;
var mceInternalUrlPrefix = 'data:text/mce-internal,';
/**
* Pastes the specified HTML. This means that the HTML is filtered and then
* inserted at the current selection in the editor. It will also fire paste events
* for custom user filtering.
*
* @param {String} html HTML code to paste into the current selection.
*/
function pasteHtml(html) {
var args, dom = editor.dom;
args = editor.fire('BeforePastePreProcess', {content: html}); // Internal event used by Quirks
args = editor.fire('PastePreProcess', args);
html = args.content;
if (!args.isDefaultPrevented()) {
// User has bound PastePostProcess events then we need to pass it through a DOM node
// This is not ideal but we don't want to let the browser mess up the HTML for example
// some browsers add &nbsp; to P tags etc
if (editor.hasEventListeners('PastePostProcess') && !args.isDefaultPrevented()) {
// We need to attach the element to the DOM so Sizzle selectors work on the contents
var tempBody = dom.add(editor.getBody(), 'div', {style: 'display:none'}, html);
args = editor.fire('PastePostProcess', {node: tempBody});
dom.remove(tempBody);
html = args.node.innerHTML;
}
if (!args.isDefaultPrevented()) {
editor.insertContent(html, {merge: editor.settings.paste_merge_formats !== false});
}
}
}
/**
* Pastes the specified text. This means that the plain text is processed
* and converted into BR and P elements. It will fire paste events for custom filtering.
*
* @param {String} text Text to paste as the current selection location.
*/
function pasteText(text) {
text = editor.dom.encode(text).replace(/\r\n/g, '\n');
var startBlock = editor.dom.getParent(editor.selection.getStart(), editor.dom.isBlock);
// Create start block html for example <p attr="value">
var forcedRootBlockName = editor.settings.forced_root_block;
var forcedRootBlockStartHtml;
if (forcedRootBlockName) {
forcedRootBlockStartHtml = editor.dom.createHTML(forcedRootBlockName, editor.settings.forced_root_block_attrs);
forcedRootBlockStartHtml = forcedRootBlockStartHtml.substr(0, forcedRootBlockStartHtml.length - 3) + '>';
}
if ((startBlock && /^(PRE|DIV)$/.test(startBlock.nodeName)) || !forcedRootBlockName) {
text = Utils.filter(text, [
[/\n/g, "<br>"]
]);
} else {
text = Utils.filter(text, [
[/\n\n/g, "</p>" + forcedRootBlockStartHtml],
[/^(.*<\/p>)(<p>)$/, forcedRootBlockStartHtml + '$1'],
[/\n/g, "<br />"]
]);
if (text.indexOf('<p>') != -1) {
text = forcedRootBlockStartHtml + text;
}
}
pasteHtml(text);
}
/**
* Creates a paste bin element as close as possible to the current caret location and places the focus inside that element
* so that when the real paste event occurs the contents gets inserted into this element
* instead of the current editor selection element.
*/
function createPasteBin() {
var dom = editor.dom, body = editor.getBody();
var viewport = editor.dom.getViewPort(editor.getWin()), scrollTop = viewport.y, top = 20;
var scrollContainer;
lastRng = editor.selection.getRng();
if (editor.inline) {
scrollContainer = editor.selection.getScrollContainer();
// Can't always rely on scrollTop returning a useful value.
// It returns 0 if the browser doesn't support scrollTop for the element or is non-scrollable
if (scrollContainer && scrollContainer.scrollTop > 0) {
scrollTop = scrollContainer.scrollTop;
}
}
/**
* Returns the rect of the current caret if the caret is in an empty block before a
* BR we insert a temporary invisible character that we get the rect this way we always get a proper rect.
*
* TODO: This might be useful in core.
*/
function getCaretRect(rng) {
var rects, textNode, node, container = rng.startContainer;
rects = rng.getClientRects();
if (rects.length) {
return rects[0];
}
if (!rng.collapsed || container.nodeType != 1) {
return;
}
node = container.childNodes[lastRng.startOffset];
// Skip empty whitespace nodes
while (node && node.nodeType == 3 && !node.data.length) {
node = node.nextSibling;
}
if (!node) {
return;
}
// Check if the location is |<br>
// TODO: Might need to expand this to say |<table>
if (node.tagName == 'BR') {
textNode = dom.doc.createTextNode('\uFEFF');
node.parentNode.insertBefore(textNode, node);
rng = dom.createRng();
rng.setStartBefore(textNode);
rng.setEndAfter(textNode);
rects = rng.getClientRects();
dom.remove(textNode);
}
if (rects.length) {
return rects[0];
}
}
// Calculate top cordinate this is needed to avoid scrolling to top of document
// We want the paste bin to be as close to the caret as possible to avoid scrolling
if (lastRng.getClientRects) {
var rect = getCaretRect(lastRng);
if (rect) {
// Client rects gets us closes to the actual
// caret location in for example a wrapped paragraph block
top = scrollTop + (rect.top - dom.getPos(body).y);
} else {
top = scrollTop;
// Check if we can find a closer location by checking the range element
var container = lastRng.startContainer;
if (container) {
if (container.nodeType == 3 && container.parentNode != body) {
container = container.parentNode;
}
if (container.nodeType == 1) {
top = dom.getPos(container, scrollContainer || body).y;
}
}
}
}
// Create a pastebin
pasteBinElm = dom.add(editor.getBody(), 'div', {
id: "mcepastebin",
contentEditable: true,
"data-mce-bogus": "all",
style: 'position: absolute; top: ' + top + 'px;' +
'width: 10px; height: 10px; overflow: hidden; opacity: 0'
}, pasteBinDefaultContent);
// Move paste bin out of sight since the controlSelection rect gets displayed otherwise on IE and Gecko
if (Env.ie || Env.gecko) {
dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) == 'rtl' ? 0xFFFF : -0xFFFF);
}
// Prevent focus events from bubbeling fixed FocusManager issues
dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function(e) {
e.stopPropagation();
});
pasteBinElm.focus();
editor.selection.select(pasteBinElm, true);
}
/**
* Removes the paste bin if it exists.
*/
function removePasteBin() {
if (pasteBinElm) {
var pasteBinClone;
// WebKit/Blink might clone the div so
// lets make sure we remove all clones
// TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
while ((pasteBinClone = editor.dom.get('mcepastebin'))) {
editor.dom.remove(pasteBinClone);
editor.dom.unbind(pasteBinClone);
}
if (lastRng) {
editor.selection.setRng(lastRng);
}
}
pasteBinElm = lastRng = null;
}
/**
* Returns the contents of the paste bin as a HTML string.
*
* @return {String} Get the contents of the paste bin.
*/
function getPasteBinHtml() {
var html = '', pasteBinClones, i, clone, cloneHtml;
// Since WebKit/Chrome might clone the paste bin when pasting
// for example: <img style="float: right"> we need to check if any of them contains some useful html.
// TODO: Man o man is this ugly. WebKit is the new IE! Remove this if they ever fix it!
pasteBinClones = editor.dom.select('div[id=mcepastebin]');
for (i = 0; i < pasteBinClones.length; i++) {
clone = pasteBinClones[i];
// Pasting plain text produces pastebins in pastebinds makes sence right!?
if (clone.firstChild && clone.firstChild.id == 'mcepastebin') {
clone = clone.firstChild;
}
cloneHtml = clone.innerHTML;
if (html != pasteBinDefaultContent) {
html += cloneHtml;
}
}
return html;
}
/**
* Gets various content types out of a datatransfer object.
*
* @param {DataTransfer} dataTransfer Event fired on paste.
* @return {Object} Object with mime types and data for those mime types.
*/
function getDataTransferItems(dataTransfer) {
var data = {};
if (dataTransfer) {
// Use old WebKit/IE API
if (dataTransfer.getData) {
var legacyText = dataTransfer.getData('Text');
if (legacyText && legacyText.length > 0) {
if (legacyText.indexOf(mceInternalUrlPrefix) == -1) {
data['text/plain'] = legacyText;
}
}
}
if (dataTransfer.types) {
for (var i = 0; i < dataTransfer.types.length; i++) {
var contentType = dataTransfer.types[i];
data[contentType] = dataTransfer.getData(contentType);
}
}
}
return data;
}
/**
* Gets various content types out of the Clipboard API. It will also get the
* plain text using older IE and WebKit API:s.
*
* @param {ClipboardEvent} clipboardEvent Event fired on paste.
* @return {Object} Object with mime types and data for those mime types.
*/
function getClipboardContent(clipboardEvent) {
return getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer);
}
/**
* Checks if the clipboard contains image data if it does it will take that data
* and convert it into a data url image and paste that image at the caret location.
*
* @param {ClipboardEvent} e Paste/drop event object.
* @param {DOMRange} rng Optional rng object to move selection to.
* @return {Boolean} true/false if the image data was found or not.
*/
function pasteImageData(e, rng) {
var dataTransfer = e.clipboardData || e.dataTransfer;
function processItems(items) {
var i, item, reader, hadImage = false;
function pasteImage(reader) {
if (rng) {
editor.selection.setRng(rng);
rng = null;
}
pasteHtml('<img src="' + reader.result + '">');
}
if (items) {
for (i = 0; i < items.length; i++) {
item = items[i];
if (/^image\/(jpeg|png|gif|bmp)$/.test(item.type)) {
reader = new FileReader();
reader.onload = pasteImage.bind(null, reader);
reader.readAsDataURL(item.getAsFile ? item.getAsFile() : item);
e.preventDefault();
hadImage = true;
}
}
}
return hadImage;
}
if (editor.settings.paste_data_images && dataTransfer) {
return processItems(dataTransfer.items) || processItems(dataTransfer.files);
}
}
/**
* Chrome on Android doesn't support proper clipboard access so we have no choice but to allow the browser default behavior.
*
* @param {Event} e Paste event object to check if it contains any data.
* @return {Boolean} true/false if the clipboard is empty or not.
*/
function isBrokenAndroidClipboardEvent(e) {
var clipboardData = e.clipboardData;
return navigator.userAgent.indexOf('Android') != -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0;
}
function getCaretRangeFromEvent(e) {
return RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc());
}
function hasContentType(clipboardContent, mimeType) {
return mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
}
function isKeyboardPasteEvent(e) {
return (VK.metaKeyPressed(e) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45);
}
function registerEventHandlers() {
editor.on('keydown', function(e) {
function removePasteBinOnKeyUp(e) {
// Ctrl+V or Shift+Insert
if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
removePasteBin();
}
}
// Ctrl+V or Shift+Insert
if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
keyboardPastePlainTextState = e.shiftKey && e.keyCode == 86;
// Edge case on Safari on Mac where it doesn't handle Cmd+Shift+V correctly
// it fires the keydown but no paste or keyup so we are left with a paste bin
if (keyboardPastePlainTextState && Env.webkit && navigator.userAgent.indexOf('Version/') != -1) {
return;
}
// Prevent undoManager keydown handler from making an undo level with the pastebin in it
e.stopImmediatePropagation();
keyboardPasteTimeStamp = new Date().getTime();
// IE doesn't support Ctrl+Shift+V and it doesn't even produce a paste event
// so lets fake a paste event and let IE use the execCommand/dataTransfer methods
if (Env.ie && keyboardPastePlainTextState) {
e.preventDefault();
editor.fire('paste', {ieFake: true});
return;
}
removePasteBin();
createPasteBin();
// Remove pastebin if we get a keyup and no paste event
// For example pasting a file in IE 11 will not produce a paste event
editor.once('keyup', removePasteBinOnKeyUp);
editor.once('paste', function() {
editor.off('keyup', removePasteBinOnKeyUp);
});
}
});
editor.on('paste', function(e) {
// Getting content from the Clipboard can take some time
var clipboardTimer = new Date().getTime();
var clipboardContent = getClipboardContent(e);
var clipboardDelay = new Date().getTime() - clipboardTimer;
var isKeyBoardPaste = (new Date().getTime() - keyboardPasteTimeStamp - clipboardDelay) < 1000;
var plainTextMode = self.pasteFormat == "text" || keyboardPastePlainTextState;
keyboardPastePlainTextState = false;
if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
removePasteBin();
return;
}
if (pasteImageData(e)) {
removePasteBin();
return;
}
// Not a keyboard paste prevent default paste and try to grab the clipboard contents using different APIs
if (!isKeyBoardPaste) {
e.preventDefault();
}
// Try IE only method if paste isn't a keyboard paste
if (Env.ie && (!isKeyBoardPaste || e.ieFake)) {
createPasteBin();
editor.dom.bind(pasteBinElm, 'paste', function(e) {
e.stopPropagation();
});
editor.getDoc().execCommand('Paste', false, null);
clipboardContent["text/html"] = getPasteBinHtml();
}
setTimeout(function() {
var content;
// Grab HTML from Clipboard API or paste bin as a fallback
if (hasContentType(clipboardContent, 'text/html')) {
content = clipboardContent['text/html'];
} else {
content = getPasteBinHtml();
// If paste bin is empty try using plain text mode
// since that is better than nothing right
if (content == pasteBinDefaultContent) {
plainTextMode = true;
}
}
content = Utils.trimHtml(content);
// WebKit has a nice bug where it clones the paste bin if you paste from for example notepad
// so we need to force plain text mode in this case
if (pasteBinElm && pasteBinElm.firstChild && pasteBinElm.firstChild.id === 'mcepastebin') {
plainTextMode = true;
}
removePasteBin();
// If we got nothing from clipboard API and pastebin then we could try the last resort: plain/text
if (!content.length) {
plainTextMode = true;
}
// Grab plain text from Clipboard API or convert existing HTML to plain text
if (plainTextMode) {
// Use plain text contents from Clipboard API unless the HTML contains paragraphs then
// we should convert the HTML to plain text since works better when pasting HTML/Word contents as plain text
if (hasContentType(clipboardContent, 'text/plain') && content.indexOf('</p>') == -1) {
content = clipboardContent['text/plain'];
} else {
content = Utils.innerText(content);
}
}
// If the content is the paste bin default HTML then it was
// impossible to get the cliboard data out.
if (content == pasteBinDefaultContent) {
if (!isKeyBoardPaste) {
editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.');
}
return;
}
if (plainTextMode) {
pasteText(content);
} else {
pasteHtml(content);
}
}, 0);
});
editor.on('dragstart dragend', function(e) {
draggingInternally = e.type == 'dragstart';
});
editor.on('drop', function(e) {
var rng = getCaretRangeFromEvent(e);
if (e.isDefaultPrevented() || draggingInternally) {
return;
}
if (pasteImageData(e, rng)) {
return;
}
if (rng && editor.settings.paste_filter_drop !== false) {
var dropContent = getDataTransferItems(e.dataTransfer);
var content = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain'];
if (content) {
e.preventDefault();
editor.undoManager.transact(function() {
if (dropContent['mce-internal']) {
editor.execCommand('Delete');
}
editor.selection.setRng(rng);
content = Utils.trimHtml(content);
if (!dropContent['text/html']) {
pasteText(content);
} else {
pasteHtml(content);
}
});
}
}
});
editor.on('dragover dragend', function(e) {
if (editor.settings.paste_data_images) {
e.preventDefault();
}
});
}
self.pasteHtml = pasteHtml;
self.pasteText = pasteText;
editor.on('preInit', function() {
registerEventHandlers();
// Remove all data images from paste for example from Gecko
// except internal images like video elements
editor.parser.addNodeFilter('img', function(nodes) {
if (!editor.settings.paste_data_images) {
var i = nodes.length;
while (i--) {
var src = nodes[i].attributes.map.src;
// Some browsers automatically produce data uris on paste
// Safari on Mac produces webkit-fake-url see: https://bugs.webkit.org/show_bug.cgi?id=49141
if (src && /^(data:image|webkit\-fake\-url)/.test(src)) {
if (!nodes[i].attr('data-mce-object') && src !== Env.transparentSrc) {
nodes[i].remove();
}
}
}
}
});
});
};
});

View File

@@ -1,110 +0,0 @@
/**
* Plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/**
* This class contains the tinymce plugin logic for the paste plugin.
*
* @class tinymce.pasteplugin.Plugin
* @private
*/
define("tinymce/pasteplugin/Plugin", [
"tinymce/PluginManager",
"tinymce/pasteplugin/Clipboard",
"tinymce/pasteplugin/WordFilter",
"tinymce/pasteplugin/Quirks"
], function(PluginManager, Clipboard, WordFilter, Quirks) {
var userIsInformed;
PluginManager.add('paste', function(editor) {
var self = this, clipboard, settings = editor.settings;
function togglePlainTextPaste() {
if (clipboard.pasteFormat == "text") {
this.active(false);
clipboard.pasteFormat = "html";
} else {
clipboard.pasteFormat = "text";
this.active(true);
if (!userIsInformed) {
editor.windowManager.alert(
'Paste is now in plain text mode. Contents will now ' +
'be pasted as plain text until you toggle this option off.'
);
userIsInformed = true;
}
}
}
self.clipboard = clipboard = new Clipboard(editor);
self.quirks = new Quirks(editor);
self.wordFilter = new WordFilter(editor);
if (editor.settings.paste_as_text) {
self.clipboard.pasteFormat = "text";
}
if (settings.paste_preprocess) {
editor.on('PastePreProcess', function(e) {
settings.paste_preprocess.call(self, self, e);
});
}
if (settings.paste_postprocess) {
editor.on('PastePostProcess', function(e) {
settings.paste_postprocess.call(self, self, e);
});
}
editor.addCommand('mceInsertClipboardContent', function(ui, value) {
if (value.content) {
self.clipboard.pasteHtml(value.content);
}
if (value.text) {
self.clipboard.pasteText(value.text);
}
});
// Block all drag/drop events
if (editor.paste_block_drop) {
editor.on('dragend dragover draggesture dragdrop drop drag', function(e) {
e.preventDefault();
e.stopPropagation();
});
}
// Prevent users from dropping data images on Gecko
if (!editor.settings.paste_data_images) {
editor.on('drop', function(e) {
var dataTransfer = e.dataTransfer;
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
e.preventDefault();
}
});
}
editor.addButton('pastetext', {
icon: 'pastetext',
tooltip: 'Paste as text',
onclick: togglePlainTextPaste,
active: self.clipboard.pasteFormat == "text"
});
editor.addMenuItem('pastetext', {
text: 'Paste as text',
selectable: true,
active: clipboard.pasteFormat,
onclick: togglePlainTextPaste
});
});
});

Some files were not shown because too many files have changed in this diff Show More