增加文本比较功能
@@ -40,6 +40,12 @@ const (
|
|||||||
BookObserver = 3
|
BookObserver = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LoggerOperate = "operate"
|
||||||
|
LoggerSystem = "system"
|
||||||
|
LoggerException = "exception"
|
||||||
|
LoggerDocument = "document"
|
||||||
|
)
|
||||||
const (
|
const (
|
||||||
//本地账户校验
|
//本地账户校验
|
||||||
AuthMethodLocal = "local"
|
AuthMethodLocal = "local"
|
||||||
|
@@ -458,7 +458,7 @@ func (c *DocumentController) Upload() {
|
|||||||
attachment.DocumentId = doc_id
|
attachment.DocumentId = doc_id
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, "png") || strings.EqualFold(ext, "gif") {
|
if strings.EqualFold(ext, ".jpg") || strings.EqualFold(ext, ".jpeg") || strings.EqualFold(ext, ".png") || strings.EqualFold(ext, ".gif") {
|
||||||
|
|
||||||
attachment.HttpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, commands.WorkingDirectory), "\\", "/", -1)
|
attachment.HttpPath = "/" + strings.Replace(strings.TrimPrefix(filePath, commands.WorkingDirectory), "\\", "/", -1)
|
||||||
if strings.HasPrefix(attachment.HttpPath, "//") {
|
if strings.HasPrefix(attachment.HttpPath, "//") {
|
||||||
@@ -1078,6 +1078,11 @@ func (c *DocumentController) RestoreHistory() {
|
|||||||
c.JsonResult(0, "ok", doc)
|
c.JsonResult(0, "ok", doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *DocumentController) Compare() {
|
||||||
|
c.Prepare()
|
||||||
|
c.TplName = "document/compare.tpl"
|
||||||
|
}
|
||||||
|
|
||||||
//递归生成文档序列数组.
|
//递归生成文档序列数组.
|
||||||
func RecursiveFun(parent_id int, prefix, dpath string, c *DocumentController, book *models.BookResult, docs []*models.Document, paths *list.List) {
|
func RecursiveFun(parent_id int, prefix, dpath string, c *DocumentController, book *models.BookResult, docs []*models.Document, paths *list.List) {
|
||||||
for _, item := range docs {
|
for _, item := range docs {
|
||||||
|
@@ -12,6 +12,9 @@ import (
|
|||||||
"github.com/lifei6671/godoc/conf"
|
"github.com/lifei6671/godoc/conf"
|
||||||
"github.com/lifei6671/godoc/models"
|
"github.com/lifei6671/godoc/models"
|
||||||
"github.com/lifei6671/godoc/utils"
|
"github.com/lifei6671/godoc/utils"
|
||||||
|
"path/filepath"
|
||||||
|
"github.com/lifei6671/godoc/commands"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ManagerController struct {
|
type ManagerController struct {
|
||||||
@@ -511,3 +514,105 @@ func (c *ManagerController) PrivatelyOwned() {
|
|||||||
}
|
}
|
||||||
c.JsonResult(0, "ok")
|
c.JsonResult(0, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//附件列表.
|
||||||
|
func (c *ManagerController) AttachList() {
|
||||||
|
c.Prepare()
|
||||||
|
c.TplName = "manager/attach_list.tpl"
|
||||||
|
|
||||||
|
pageIndex, _ := c.GetInt("page", 1)
|
||||||
|
|
||||||
|
attachList, totalCount, err := models.NewAttachment().FindToPager(pageIndex, conf.PageSize)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalCount > 0 {
|
||||||
|
html := utils.GetPagerHtml(c.Ctx.Request.RequestURI, pageIndex, conf.PageSize, int(totalCount))
|
||||||
|
|
||||||
|
c.Data["PageHtml"] = html
|
||||||
|
} else {
|
||||||
|
c.Data["PageHtml"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
for _,item := range attachList {
|
||||||
|
|
||||||
|
p := filepath.Join(commands.WorkingDirectory,item.FilePath)
|
||||||
|
|
||||||
|
item.IsExist = utils.FileExists(p)
|
||||||
|
|
||||||
|
}
|
||||||
|
c.Data["Lists"] = attachList
|
||||||
|
}
|
||||||
|
|
||||||
|
//附件详情.
|
||||||
|
func (c *ManagerController) AttachDetailed() {
|
||||||
|
c.Prepare()
|
||||||
|
c.TplName = "manager/attach_detailed.tpl"
|
||||||
|
attach_id,_ := strconv.Atoi(c.Ctx.Input.Param(":id"))
|
||||||
|
|
||||||
|
if attach_id <= 0 {
|
||||||
|
c.Abort("404")
|
||||||
|
}
|
||||||
|
|
||||||
|
attach,err := models.NewAttachmentResult().Find(attach_id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("AttachDetailed => ",err)
|
||||||
|
if err == orm.ErrNoRows {
|
||||||
|
c.Abort("404")
|
||||||
|
}else{
|
||||||
|
c.Abort("500")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attach.FilePath = filepath.Join(commands.WorkingDirectory,attach.FilePath)
|
||||||
|
attach.HttpPath = c.BaseUrl() + attach.HttpPath
|
||||||
|
|
||||||
|
attach.IsExist = utils.FileExists(attach.FilePath)
|
||||||
|
|
||||||
|
c.Data["Model"] = attach
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除附件.
|
||||||
|
func (c *ManagerController) AttachDelete() {
|
||||||
|
c.Prepare()
|
||||||
|
attach_id,_ := c.GetInt("attach_id")
|
||||||
|
|
||||||
|
if attach_id <= 0 {
|
||||||
|
c.Abort("404")
|
||||||
|
}
|
||||||
|
attach,err := models.NewAttachment().Find(attach_id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
beego.Error("AttachDelete => ",err)
|
||||||
|
c.JsonResult(6001,err.Error())
|
||||||
|
}
|
||||||
|
if err := attach.Delete();err != nil {
|
||||||
|
beego.Error("AttachDelete => ",err)
|
||||||
|
c.JsonResult(6002,err.Error())
|
||||||
|
}
|
||||||
|
c.JsonResult(0,"ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
"github.com/lifei6671/godoc/conf"
|
"github.com/lifei6671/godoc/conf"
|
||||||
|
"github.com/lifei6671/godoc/utils"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attachment struct .
|
// Attachment struct .
|
||||||
@@ -86,3 +88,49 @@ func (m *Attachment) FindListByDocumentId(doc_id int) (attaches []*Attachment, e
|
|||||||
_, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", doc_id).OrderBy("-attachment_id").All(&attaches)
|
_, err = o.QueryTable(m.TableNameWithPrefix()).Filter("document_id", doc_id).OrderBy("-attachment_id").All(&attaches)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//分页查询附件
|
||||||
|
func (m *Attachment) FindToPager(pageIndex, pageSize int) (attachList []*AttachmentResult, totalCount int64, err error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
totalCount, err = o.QueryTable(m.TableNameWithPrefix()).Count()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
offset := (pageIndex - 1) * pageSize
|
||||||
|
|
||||||
|
var list []*Attachment
|
||||||
|
|
||||||
|
_, err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-attachment_id").Offset(offset).Limit(pageSize).All(&list)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range list {
|
||||||
|
attach := &AttachmentResult{}
|
||||||
|
attach.Attachment = *item
|
||||||
|
attach.FileShortSize = utils.FormatBytes(int64(attach.FileSize))
|
||||||
|
|
||||||
|
book := NewBook()
|
||||||
|
|
||||||
|
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", item.BookId).One(book, "book_name"); e == nil {
|
||||||
|
attach.BookName = book.BookName
|
||||||
|
} else {
|
||||||
|
attach.BookName = "[不存在]"
|
||||||
|
}
|
||||||
|
doc := NewDocument()
|
||||||
|
|
||||||
|
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", item.DocumentId).One(doc, "document_name"); e == nil {
|
||||||
|
attach.DocumentName = doc.DocumentName
|
||||||
|
} else {
|
||||||
|
attach.DocumentName = "[不存在]"
|
||||||
|
}
|
||||||
|
attach.LocalHttpPath = strings.Replace(item.FilePath,"\\","/",-1)
|
||||||
|
|
||||||
|
attachList = append(attachList, attach)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
61
models/attachment_result.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/lifei6671/godoc/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AttachmentResult struct {
|
||||||
|
Attachment
|
||||||
|
IsExist bool
|
||||||
|
BookName string
|
||||||
|
DocumentName string
|
||||||
|
FileShortSize string
|
||||||
|
Account string
|
||||||
|
LocalHttpPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAttachmentResult() *AttachmentResult {
|
||||||
|
return &AttachmentResult{ IsExist : false }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *AttachmentResult) Find(id int) (*AttachmentResult,error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
attach := NewAttachment()
|
||||||
|
|
||||||
|
err := o.QueryTable(m.TableNameWithPrefix()).Filter("attachment_id",id).One(attach)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return m,err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Attachment = *attach
|
||||||
|
|
||||||
|
book := NewBook()
|
||||||
|
|
||||||
|
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", attach.BookId).One(book, "book_name"); e == nil {
|
||||||
|
m.BookName = book.BookName
|
||||||
|
} else {
|
||||||
|
m.BookName = "[不存在]"
|
||||||
|
}
|
||||||
|
doc := NewDocument()
|
||||||
|
|
||||||
|
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", attach.DocumentId).One(doc, "document_name"); e == nil {
|
||||||
|
m.DocumentName = doc.DocumentName
|
||||||
|
} else {
|
||||||
|
m.DocumentName = "[不存在]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if attach.CreateAt > 0 {
|
||||||
|
member := NewMember()
|
||||||
|
if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id",attach.CreateAt).One(member,"account");e == nil {
|
||||||
|
m.Account = member.Account
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.FileShortSize = utils.FormatBytes(int64(attach.FileSize))
|
||||||
|
m.LocalHttpPath = strings.Replace(m.FilePath,"\\","/",-1)
|
||||||
|
|
||||||
|
return m,nil
|
||||||
|
}
|
@@ -3,19 +3,23 @@ package models
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
"github.com/lifei6671/godoc/conf"
|
"github.com/lifei6671/godoc/conf"
|
||||||
|
"sync/atomic"
|
||||||
|
"github.com/astaxie/beego/orm"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var loggerQueue = &logQueue{ channel : make(chan *Logger,100),isRuning : 0 }
|
||||||
Logger_Operate = "operate"
|
|
||||||
Logger_System = "system"
|
type logQueue struct {
|
||||||
Logger_Exception = "exception"
|
channel chan *Logger
|
||||||
)
|
isRuning int32
|
||||||
|
}
|
||||||
|
|
||||||
// Logger struct .
|
// Logger struct .
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
LoggerId int64 `orm:"pk;auto;unique;column(log_id)" json:"log_id"`
|
LoggerId int64 `orm:"pk;auto;unique;column(log_id)" json:"log_id"`
|
||||||
MemberId int `orm:"column(member_id);type(int)" json:"member_id"`
|
MemberId int `orm:"column(member_id);type(int)" json:"member_id"`
|
||||||
// 日志类别:operate 操作日志/ system 系统日志/ exception 异常日志
|
// 日志类别:operate 操作日志/ system 系统日志/ exception 异常日志 / document 文档操作日志
|
||||||
Category string `orm:"column(category);size(255);default(operate)" json:"category"`
|
Category string `orm:"column(category);size(255);default(operate)" json:"category"`
|
||||||
Content string `orm:"column(content);type(text)" json:"content"`
|
Content string `orm:"column(content);type(text)" json:"content"`
|
||||||
OriginalData string `orm:"column(original_data);type(text)" json:"original_data"`
|
OriginalData string `orm:"column(original_data);type(text)" json:"original_data"`
|
||||||
@@ -41,7 +45,34 @@ func NewLogger() *Logger {
|
|||||||
return &Logger{}
|
return &Logger{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Logger) Add() error {
|
||||||
|
if m.MemberId <= 0 {
|
||||||
|
return errors.New("用户ID不能为空")
|
||||||
|
}
|
||||||
|
if m.Category == "" {
|
||||||
|
m.Category = "system"
|
||||||
|
}
|
||||||
|
if m.Content == "" {
|
||||||
|
return errors.New("日志内容不能为空")
|
||||||
|
}
|
||||||
|
loggerQueue.channel <- m
|
||||||
|
if atomic.LoadInt32(&(loggerQueue.isRuning)) <= 0 {
|
||||||
|
atomic.AddInt32(&(loggerQueue.isRuning),1)
|
||||||
|
go addLoggerAsync()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLoggerAsync() {
|
||||||
|
defer atomic.AddInt32(&(loggerQueue.isRuning),-1)
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
for{
|
||||||
|
logger := <- loggerQueue.channel
|
||||||
|
|
||||||
|
o.Insert(logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -29,6 +29,10 @@ func init() {
|
|||||||
beego.Router("/manager/setting",&controllers.ManagerController{},"*:Setting")
|
beego.Router("/manager/setting",&controllers.ManagerController{},"*:Setting")
|
||||||
beego.Router("/manager/books/transfer", &controllers.ManagerController{},"post:Transfer")
|
beego.Router("/manager/books/transfer", &controllers.ManagerController{},"post:Transfer")
|
||||||
beego.Router("/manager/books/open", &controllers.ManagerController{},"post:PrivatelyOwned")
|
beego.Router("/manager/books/open", &controllers.ManagerController{},"post:PrivatelyOwned")
|
||||||
|
beego.Router("/manager/attach/list", &controllers.ManagerController{},"*:AttachList")
|
||||||
|
beego.Router("/manager/attach/detailed/:id", &controllers.ManagerController{},"*:AttachDetailed")
|
||||||
|
beego.Router("/manager/attach/delete", &controllers.ManagerController{},"post:AttachDelete")
|
||||||
|
|
||||||
|
|
||||||
beego.Router("/setting", &controllers.SettingController{},"*:Index")
|
beego.Router("/setting", &controllers.SettingController{},"*:Index")
|
||||||
beego.Router("/setting/password", &controllers.SettingController{},"*:Password")
|
beego.Router("/setting/password", &controllers.SettingController{},"*:Password")
|
||||||
@@ -59,6 +63,7 @@ func init() {
|
|||||||
beego.Router("/api/:key/create",&controllers.DocumentController{},"post:Create")
|
beego.Router("/api/:key/create",&controllers.DocumentController{},"post:Create")
|
||||||
beego.Router("/api/:key/delete", &controllers.DocumentController{},"post:Delete")
|
beego.Router("/api/:key/delete", &controllers.DocumentController{},"post:Delete")
|
||||||
beego.Router("/api/:key/content/?:id",&controllers.DocumentController{},"*:Content")
|
beego.Router("/api/:key/content/?:id",&controllers.DocumentController{},"*:Content")
|
||||||
|
beego.Router("/api/:key/compare/:id", &controllers.DocumentController{},"*:Compare")
|
||||||
|
|
||||||
beego.Router("/history/get", &controllers.DocumentController{},"get:History")
|
beego.Router("/history/get", &controllers.DocumentController{},"get:History")
|
||||||
beego.Router("/history/delete", &controllers.DocumentController{},"*:DeleteHistory")
|
beego.Router("/history/delete", &controllers.DocumentController{},"*:DeleteHistory")
|
||||||
|
@@ -48,6 +48,9 @@ h6 {
|
|||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
font-weight: 200
|
font-weight: 200
|
||||||
}
|
}
|
||||||
|
table>tbody>tr:hover{
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
}
|
||||||
.m-manual:not(.manual-mobile) ::-webkit-scrollbar {
|
.m-manual:not(.manual-mobile) ::-webkit-scrollbar {
|
||||||
height: 10px;
|
height: 10px;
|
||||||
width: 7px;
|
width: 7px;
|
||||||
|
@@ -25,6 +25,12 @@ textarea{
|
|||||||
color: green;
|
color: green;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
.input-readonly{
|
||||||
|
border: 1px solid rgba(34,36,38,.15);
|
||||||
|
background-color: #fff !important;
|
||||||
|
-webkit-box-shadow : none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar , body .scrollbar-track-color{
|
::-webkit-scrollbar , body .scrollbar-track-color{
|
||||||
height: 9px;
|
height: 9px;
|
||||||
@@ -51,7 +57,10 @@ textarea{
|
|||||||
}
|
}
|
||||||
.manual-header .navbar-brand,.manual-header a {
|
.manual-header .navbar-brand,.manual-header a {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #563d7c
|
color: #563d7c;
|
||||||
|
max-width: 300px;
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.manual-reader .slidebar {
|
.manual-reader .slidebar {
|
||||||
margin: 5px 10px 0 0;
|
margin: 5px 10px 0 0;
|
||||||
|
@@ -72,7 +72,8 @@ function getSiblingSort (node) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个文档
|
* 删除一个文档
|
||||||
@@ -219,6 +220,67 @@ window.documentHistory = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
//格式化文件大小
|
||||||
|
function formatBytes($size) {
|
||||||
|
var $units = [" B", " KB", " MB", " GB", " TB"];
|
||||||
|
|
||||||
|
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
|
||||||
|
|
||||||
|
return $size.toFixed(2) + $units[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadImage($id,$callback) {
|
||||||
|
/** 粘贴上传图片 **/
|
||||||
|
document.getElementById($id).addEventListener('paste', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var clipboard = e.clipboardData;
|
||||||
|
for (var i = 0, len = clipboard.items.length; i < len; i++) {
|
||||||
|
if (clipboard.items[i].kind === 'file' || clipboard.items[i].type.indexOf('image') > -1) {
|
||||||
|
var imageFile = clipboard.items[i].getAsFile();
|
||||||
|
|
||||||
|
var fileName = Date.parse(new Date());
|
||||||
|
|
||||||
|
switch (imageFile.type){
|
||||||
|
case "image/png" : fileName += ".png";break;
|
||||||
|
case "image/jpg" : fileName += ".jpg";break
|
||||||
|
case "image/jpeg" : fileName += ".jpeg";break;
|
||||||
|
case "image/gif" : fileName += ".gif";break;
|
||||||
|
default : layer.msg("不支持的图片格式");return;
|
||||||
|
}
|
||||||
|
var form = new FormData();
|
||||||
|
|
||||||
|
form.append('editormd-image-file', imageFile, fileName);
|
||||||
|
|
||||||
|
var layerIndex = 0;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: window.imageUploadURL,
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: form,
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
beforeSend: function() {
|
||||||
|
layerIndex = $callback('before');
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
layer.close(layerIndex);
|
||||||
|
$callback('error');
|
||||||
|
layer.msg("图片上传失败");
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
layer.close(layerIndex);
|
||||||
|
$callback('success', data);
|
||||||
|
if(data.errcode !== 0){
|
||||||
|
layer.msg(data.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
window.vueApp = new Vue({
|
window.vueApp = new Vue({
|
||||||
|
@@ -37,4 +37,12 @@ Date.prototype.format = function(fmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt;
|
return fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function formatBytes($size) {
|
||||||
|
var $units = [" B", " KB", " MB", " GB", " TB"];
|
||||||
|
|
||||||
|
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
|
||||||
|
|
||||||
|
return $size.toFixed(2) + $units[$i];
|
||||||
|
}
|
@@ -45,6 +45,18 @@ $(function () {
|
|||||||
loadDocument($select_node);
|
loadDocument($select_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
uploadImage("docEditor",function ($state, $res) {
|
||||||
|
if($state === "before"){
|
||||||
|
return layer.load(1, {
|
||||||
|
shade: [0.1,'#fff'] //0.1透明度的白色背景
|
||||||
|
});
|
||||||
|
}else if($state === "success"){
|
||||||
|
if($res.errcode === 0) {
|
||||||
|
var value = '';
|
||||||
|
window.editor.insertValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onchange : function () {
|
onchange : function () {
|
||||||
resetEditorChanged(true);
|
resetEditorChanged(true);
|
||||||
|
85
static/mergely/editor/editor.css
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
body { margin: 0; }
|
||||||
|
#banner { background: transparent url(images/banner.png); width: 33px; height: 30px; position: absolute; left: 3px; top: 3px; }
|
||||||
|
.wicked-menu { font-family: 'Noto Sans', sans-serif; margin: 2px 0 2px 40px; }
|
||||||
|
.wicked-menu a.link { margin-left: 10px; }
|
||||||
|
.ui-widget { font-size:13px; }
|
||||||
|
|
||||||
|
/* color dialog */
|
||||||
|
#dialog-colors { }
|
||||||
|
#dialog-colors label { width: 85px; display: inline-block; font-weight: bold; padding: 5px; }
|
||||||
|
#dialog-colors input[type=text] { width: 70px; border: 1px solid #444; float:right; }
|
||||||
|
#dialog-colors fieldset { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; border: 1px solid #ccc; width: 222px; padding-right: 15px; }
|
||||||
|
|
||||||
|
/* import dialog */
|
||||||
|
#dialog-upload label { font-weight: bold; display: inline-block; width: 80px; line-height: 1.5em; }
|
||||||
|
.no-title .ui-dialog-titlebar { display:none; }
|
||||||
|
.no-title .ui-dialog-content { padding: 0; }
|
||||||
|
#file-lhs-progress,
|
||||||
|
#file-rhs-progress { height: 22px; width: 240px; vertical-align: middle; line-height: 1.5em; display: none; }
|
||||||
|
.progress-label { float: left; width: 100%; color: #fff; font-weight: bold; font-size: .8em; padding-left: 10px; }
|
||||||
|
|
||||||
|
/* icons */
|
||||||
|
.icon-undo { background-image: url(images/undo.png); }
|
||||||
|
.icon-redo { background-image: url(images/redo.png); }
|
||||||
|
.icon-save { background-image: url(images/download.png); }
|
||||||
|
.icon-check { background-image: url(images/check.png); }
|
||||||
|
.icon-import { background-image: url(images/upload.png); }
|
||||||
|
.icon-swap { background-image: url(images/swap.png); }
|
||||||
|
.icon-arrow-right { background-image: url(images/arrow-right.png); }
|
||||||
|
.icon-arrow-right-v { background-image: url(images/arrow-right-v.png); }
|
||||||
|
.icon-arrow-right-vv { background-image: url(images/arrow-right-vv.png); }
|
||||||
|
.icon-arrow-left-v { background-image: url(images/arrow-left-v.png); }
|
||||||
|
.icon-arrow-left-vv { background-image: url(images/arrow-left-vv.png); }
|
||||||
|
.icon-arrow-up { background-image: url(images/arrow-up-v.png); }
|
||||||
|
.icon-arrow-down { background-image: url(images/arrow-down-v.png); }
|
||||||
|
.icon-x-mark { background-image: url(images/x-mark.png); }
|
||||||
|
.icon-share { background-image: url(images/share.png); }
|
||||||
|
|
||||||
|
|
||||||
|
.tipsy-inner {
|
||||||
|
padding: 8px;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 250px;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.find {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
z-index: 4;
|
||||||
|
padding: 10px 20px 10px 10px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
float: right;
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
border-bottom-left-radius: 10px;
|
||||||
|
max-height: 26px;
|
||||||
|
-webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
-moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.find > button {
|
||||||
|
padding: 3px 0px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 25px;
|
||||||
|
width: 26px;
|
||||||
|
vertical-align: top;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.find > button:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.find > button > span.icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
background-position: center center;
|
||||||
|
}
|
703
static/mergely/editor/editor.js
Normal file
@@ -0,0 +1,703 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
function getParameters() {
|
||||||
|
var parameters = {};
|
||||||
|
window.location.search.substr(1).split('&').forEach(function(pair) {
|
||||||
|
if (pair === '') return;
|
||||||
|
var parts = pair.split('=');
|
||||||
|
if (parts.length === 2 && parts[1].search(/^(true|1)$/i) >= 0) {
|
||||||
|
parameters[parts[0]] = true;
|
||||||
|
}
|
||||||
|
else if (parts.length === 2 && parts[1].search(/^(false|0)$/i) >= 0) {
|
||||||
|
parameters[parts[0]] = false;
|
||||||
|
}
|
||||||
|
else parameters[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
get: function(name, defaultValue) {
|
||||||
|
if (parameters.hasOwnProperty(name)) return parameters[name];
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var parameters = getParameters();
|
||||||
|
if (parameters.get('test', false)) {
|
||||||
|
var li = $('<li>Tests</li>');
|
||||||
|
var ul = $('<ul>');
|
||||||
|
for (var i = 1; i <= 8; ++i) {
|
||||||
|
ul.append($('<li id="examples-test' + i + '">Test ' + i + '</li>'));
|
||||||
|
}
|
||||||
|
li.append(ul);
|
||||||
|
$('#main-menu').append(li);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFind(column) {
|
||||||
|
if (!column.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var ed = $('#mergely');
|
||||||
|
var find = column.find('.find');
|
||||||
|
var input = find.find('input[type="text"]');
|
||||||
|
var side = column.attr('id').indexOf('-lhs') > 0 ? 'lhs' : 'rhs';
|
||||||
|
var origautoupdate = ed.mergely('options').autoupdate;
|
||||||
|
find.slideDown('fast', function() {
|
||||||
|
input.focus();
|
||||||
|
// disable autoupdate, clear both sides of diff
|
||||||
|
ed.mergely('options', {autoupdate: false});
|
||||||
|
ed.mergely('unmarkup');
|
||||||
|
});
|
||||||
|
find.find('.find-prev').click(function() {
|
||||||
|
ed.mergely('search', side, input.val(), 'prev');
|
||||||
|
});
|
||||||
|
find.find('.find-next').click(function() {
|
||||||
|
ed.mergely('search', side, input.val(), 'next');
|
||||||
|
});
|
||||||
|
find.find('.find-close').click(function() {
|
||||||
|
find.css('display', 'none')
|
||||||
|
ed.mergely('options', {autoupdate: origautoupdate});
|
||||||
|
});
|
||||||
|
|
||||||
|
input.keydown(function(evt) {
|
||||||
|
if (evt.which != 13 && evt.which != 27) return true;
|
||||||
|
if (evt.which == 27) {
|
||||||
|
find.css('display', 'none');
|
||||||
|
ed.mergely('options', {autoupdate: origautoupdate});
|
||||||
|
}
|
||||||
|
ed.mergely('search', side, input.val());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).keydown(function(event) {
|
||||||
|
if (!( String.fromCharCode(event.which).toLowerCase() == 'f' && event.ctrlKey)) return true;
|
||||||
|
event.preventDefault();
|
||||||
|
var range = window.getSelection().getRangeAt(0);
|
||||||
|
var column = $(range.commonAncestorContainer).parents('.mergely-column');
|
||||||
|
handleFind(column);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
String.prototype.random = function(length) {
|
||||||
|
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
|
||||||
|
var randomstring = ''
|
||||||
|
for (var i=0; i<length; i++) {
|
||||||
|
var rnum = Math.floor(Math.random() * chars.length);
|
||||||
|
randomstring += chars.substring(rnum,rnum+1);
|
||||||
|
}
|
||||||
|
return randomstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
// body is pre-hidden for better rendering
|
||||||
|
$('body').css("visibility", "");
|
||||||
|
|
||||||
|
var ed = $('#mergely');
|
||||||
|
var menu = $('#main-menu');
|
||||||
|
var toolbar = $('#toolbar');
|
||||||
|
ed.mergely({
|
||||||
|
width: 'auto',
|
||||||
|
height: 'auto',
|
||||||
|
cmsettings: {
|
||||||
|
lineNumbers: true,
|
||||||
|
readOnly: isSample
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (parameters.get('lhs', null)) {
|
||||||
|
var url = parameters.get('lhs');
|
||||||
|
crossdomainGET(ed, 'lhs', url);
|
||||||
|
}
|
||||||
|
if (parameters.get('rhs', null)) {
|
||||||
|
var url = parameters.get('rhs');
|
||||||
|
crossdomainGET(ed, 'rhs', url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set query string options
|
||||||
|
var urloptions = {};
|
||||||
|
var optmap = {
|
||||||
|
au: 'autoupdate',
|
||||||
|
ws: 'ignorews',
|
||||||
|
cs: 'ignorecase',
|
||||||
|
sb: 'sidebar',
|
||||||
|
vp: 'viewport',
|
||||||
|
wl: 'wrap_lines',
|
||||||
|
ln: 'line_numbers'
|
||||||
|
};
|
||||||
|
var doopt = false;
|
||||||
|
for (var name in optmap) {
|
||||||
|
if (!optmap.hasOwnProperty(name)) continue;
|
||||||
|
if (parameters.get(name, null) !== null) {
|
||||||
|
urloptions[optmap[name]] = parameters.get(name);
|
||||||
|
doopt = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parameters.get('rm', null) !== null) {
|
||||||
|
// special-case url property
|
||||||
|
urloptions.rhs_margin = parameters.get('rm') ? 'left' : 'right';
|
||||||
|
}
|
||||||
|
if (doopt) {
|
||||||
|
// apply query-string options
|
||||||
|
ed.mergely('options', urloptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set query string colors
|
||||||
|
// cb: change border
|
||||||
|
// cg: change background
|
||||||
|
// ab: added border
|
||||||
|
// ag: added background
|
||||||
|
// db: deleted border
|
||||||
|
// dg: deleted background
|
||||||
|
var color_defaults = {
|
||||||
|
cb: 'cccccc', cg: 'fafafa',
|
||||||
|
ab: 'a3d1ff', ag: 'ddeeff',
|
||||||
|
db: 'ff7f7f', dg: 'ffe9e9'
|
||||||
|
};
|
||||||
|
applyParameterCss(false);
|
||||||
|
|
||||||
|
//history.pushState({}, null, '');
|
||||||
|
|
||||||
|
window.addEventListener('popstate', function(ev) {
|
||||||
|
if (ev.state) {
|
||||||
|
parameters = getParameters();
|
||||||
|
applyParameterCss(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load
|
||||||
|
if (key.length == 8) {
|
||||||
|
$.when(
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET', async: true, dataType: 'text',
|
||||||
|
data: { 'key':key, 'name': 'lhs' },
|
||||||
|
url: '/ajax/handle_get.php',
|
||||||
|
success: function (response) {
|
||||||
|
ed.mergely('lhs', response);
|
||||||
|
},
|
||||||
|
error: function(xhr, ajaxOptions, thrownError){
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET', async: true, dataType: 'text',
|
||||||
|
data: { 'key':key, 'name': 'rhs' },
|
||||||
|
url: '/ajax/handle_get.php',
|
||||||
|
success: function (response) {
|
||||||
|
ed.mergely('rhs', response);
|
||||||
|
},
|
||||||
|
error: function(xhr, ajaxOptions, thrownError){
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).done(function() {
|
||||||
|
var anchor = window.location.hash.substring(1);
|
||||||
|
if (anchor) {
|
||||||
|
// if an anchor has been provided, then parse the anchor in the
|
||||||
|
// form of: 'lhs' or 'rhs', followed by a line, e.g: lhs100.
|
||||||
|
var m = anchor.match(/([lr]hs)([0-9]+)/);
|
||||||
|
if (m && m.length == 3) {
|
||||||
|
console.log(m);
|
||||||
|
ed.mergely('scrollTo', m[1], parseInt(m[2],10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// find
|
||||||
|
var find = $('.find');
|
||||||
|
var flhs = find.clone().attr('id', 'mergely-editor-lhs-find');
|
||||||
|
var frhs = find.clone().attr('id', 'mergely-editor-rhs-find');
|
||||||
|
$('#mergely-editor-lhs').append(flhs);
|
||||||
|
$('#mergely-editor-rhs').append(frhs);
|
||||||
|
find.remove();
|
||||||
|
|
||||||
|
var iconconf = {
|
||||||
|
'options-autodiff': {
|
||||||
|
get: function() { return ed.mergely('options').autoupdate },
|
||||||
|
set: function(value) {
|
||||||
|
var au = !ed.mergely('options').autoupdate;
|
||||||
|
ed.mergely('options', {autoupdate: au});
|
||||||
|
var params = updateQueryStringParam('au', au ? 1 : 0, 1);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-ignorews': {
|
||||||
|
get: function() { return ed.mergely('options').ignorews },
|
||||||
|
set: function(value) {
|
||||||
|
var ws = !ed.mergely('options').ignorews;
|
||||||
|
ed.mergely('options', {ignorews: ws});
|
||||||
|
var params = updateQueryStringParam('ws', ws ? 1 : 0, 0);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-ignorecase': {
|
||||||
|
get: function() { return ed.mergely('options').ignorecase },
|
||||||
|
set: function(value) {
|
||||||
|
var cs = !ed.mergely('options').ignorecase;
|
||||||
|
ed.mergely('options', {ignorecase: cs});
|
||||||
|
var params = updateQueryStringParam('cs', cs ? 1 : 0, 0);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-sidebars': {
|
||||||
|
get: function() { console.log('sidebar', this); return ed.mergely('options').sidebar },
|
||||||
|
set: function(value) {
|
||||||
|
var sb = !ed.mergely('options').sidebar;
|
||||||
|
ed.mergely('options', {sidebar: sb});
|
||||||
|
var params = updateQueryStringParam('sb', sb ? 1 : 0, 1);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-viewport': {
|
||||||
|
get: function() { console.log('viewport', this); return ed.mergely('options').viewport },
|
||||||
|
set: function(value) {
|
||||||
|
var vp = !ed.mergely('options').viewport;
|
||||||
|
ed.mergely('options', {viewport: vp});
|
||||||
|
var params = updateQueryStringParam('vp', vp ? 1 : 0, 0);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-swapmargin': {
|
||||||
|
get: function() { return (ed.mergely('options').rhs_margin == 'left'); },
|
||||||
|
set: function(value) {
|
||||||
|
var rm = ed.mergely('options').rhs_margin == 'left' ? 'right' : 'left';
|
||||||
|
ed.mergely('options', {rhs_margin: rm });
|
||||||
|
var params = updateQueryStringParam('rm', rm == 'left' ? 1 : 0, 0);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-linenumbers': {
|
||||||
|
get: function() { console.log('wrap', this); return ed.mergely('options').line_numbers },
|
||||||
|
set: function(value) {
|
||||||
|
var ln = !ed.mergely('options').line_numbers;
|
||||||
|
ed.mergely('options', {line_numbers: ln});
|
||||||
|
var params = updateQueryStringParam('ln', ln ? 1 : 0, 1);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'options-wrap': {
|
||||||
|
get: function() { console.log('wrap', this); return ed.mergely('options').wrap_lines },
|
||||||
|
set: function(value) {
|
||||||
|
var wl = !ed.mergely('options').wrap_lines;
|
||||||
|
ed.mergely('options', {wrap_lines: wl});
|
||||||
|
var params = updateQueryStringParam('wl', wl ? 1 : 0, 0);
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'edit-left-readonly': {
|
||||||
|
get: function() { return ed.mergely('cm', 'lhs').getOption('readOnly'); },
|
||||||
|
set: function(value) { ed.mergely('cm', 'lhs').setOption('readOnly', value); }
|
||||||
|
},
|
||||||
|
'edit-right-readonly': {
|
||||||
|
get: function() { return ed.mergely('cm', 'rhs').getOption('readOnly'); },
|
||||||
|
set: function(value) { ed.mergely('cm', 'rhs').setOption('readOnly', value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var menu_opts = {
|
||||||
|
hasIcon: function(id) {
|
||||||
|
return iconconf.hasOwnProperty(id);
|
||||||
|
},
|
||||||
|
getIcon: function(id) {
|
||||||
|
if (iconconf[id].get()) return 'icon-check';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function handle_operation(id) {
|
||||||
|
if (id == 'file-new') {
|
||||||
|
window.location = '/editor';
|
||||||
|
}
|
||||||
|
else if (id == 'file-save') {
|
||||||
|
// download directly from browser
|
||||||
|
var text = ed.mergely('diff');
|
||||||
|
if (navigator.userAgent.toLowerCase().indexOf('msie') === -1) {
|
||||||
|
if (key == '') key = ''.random(8);
|
||||||
|
var link = jQuery('<a />', {
|
||||||
|
href: 'data:application/stream;base64,' + window.btoa(unescape(encodeURIComponent(text))),
|
||||||
|
target: '_blank',
|
||||||
|
text: 'clickme',
|
||||||
|
id: key
|
||||||
|
});
|
||||||
|
link.attr('download', key + '.diff');
|
||||||
|
jQuery('body').append(link);
|
||||||
|
var a = $('a#' + key);
|
||||||
|
a[0].click();
|
||||||
|
a.remove();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var blob = new Blob([text]);
|
||||||
|
window.navigator.msSaveOrOpenBlob(blob, key + '.diff');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (id == 'file-share') {
|
||||||
|
handleShare(ed);
|
||||||
|
}
|
||||||
|
else if (id == 'file-import') {
|
||||||
|
importFiles(ed);
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-undo') {
|
||||||
|
ed.mergely('cm', 'lhs').getDoc().undo();
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-redo') {
|
||||||
|
ed.mergely('cm', 'lhs').getDoc().redo();
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-undo') {
|
||||||
|
ed.mergely('cm', 'rhs').getDoc().undo();
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-redo') {
|
||||||
|
ed.mergely('cm', 'rhs').getDoc().redo();
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-find') {
|
||||||
|
handleFind(ed.find('#mergely-editor-lhs'));
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-merge-right') {
|
||||||
|
ed.mergely('mergeCurrentChange', 'rhs');
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-merge-right-file') {
|
||||||
|
ed.mergely('merge', 'rhs');
|
||||||
|
}
|
||||||
|
else if ([
|
||||||
|
'edit-left-readonly',
|
||||||
|
'edit-right-readonly',
|
||||||
|
'options-autodiff',
|
||||||
|
'options-sidebars',
|
||||||
|
'options-swapmargin',
|
||||||
|
'options-viewport',
|
||||||
|
'options-ignorews',
|
||||||
|
'options-ignorecase',
|
||||||
|
'options-wrap',
|
||||||
|
'options-linenumbers',
|
||||||
|
].indexOf(id) >= 0) {
|
||||||
|
iconconf[id].set(!iconconf[id].get());
|
||||||
|
menu.wickedmenu('update', id);
|
||||||
|
}
|
||||||
|
else if (id == 'edit-left-clear') {
|
||||||
|
ed.mergely('clear', 'lhs');
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-find') {
|
||||||
|
handleFind(ed.find('#mergely-editor-rhs'));
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-merge-left') {
|
||||||
|
ed.mergely('mergeCurrentChange', 'lhs');
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-merge-left-file') {
|
||||||
|
ed.mergely('merge', 'lhs');
|
||||||
|
}
|
||||||
|
else if (id == 'edit-right-clear') {
|
||||||
|
ed.mergely('clear', 'rhs');
|
||||||
|
}
|
||||||
|
else if (id == 'options-colors') {
|
||||||
|
colorSettings(ed);
|
||||||
|
}
|
||||||
|
else if (id == 'view-swap') {
|
||||||
|
ed.mergely('swap');
|
||||||
|
}
|
||||||
|
else if (id == 'view-refresh') {
|
||||||
|
ed.mergely('update');
|
||||||
|
}
|
||||||
|
else if (id == 'view-change-next') {
|
||||||
|
ed.mergely('scrollToDiff', 'next');
|
||||||
|
}
|
||||||
|
else if (id == 'view-change-prev') {
|
||||||
|
ed.mergely('scrollToDiff', 'prev');
|
||||||
|
}
|
||||||
|
else if (id == 'view-clear') {
|
||||||
|
ed.mergely('unmarkup');
|
||||||
|
}
|
||||||
|
else if (id.indexOf('examples-') == 0) {
|
||||||
|
var test_config = {
|
||||||
|
test1: {lhs: 'one\ntwo\nthree', rhs: 'two\nthree'},
|
||||||
|
test2: {lhs: 'two\nthree', rhs: 'one\ntwo\nthree'},
|
||||||
|
test3: {lhs: 'one\nthree', rhs: 'one\ntwo\nthree'},
|
||||||
|
test4: {lhs: 'one\ntwo\nthree', rhs: 'one\nthree'},
|
||||||
|
test5: {lhs: 'to bee, or not to be', rhs: 'to be, or not to bee'},
|
||||||
|
test6: {lhs: 'to be, or not to be z', rhs: 'to be, to be'},
|
||||||
|
test7: {lhs: 'remained, & to assume', rhs: 'and to assume'},
|
||||||
|
test8: {lhs: 'to be, or not to be', rhs: 'to be, or not to be'}
|
||||||
|
};
|
||||||
|
var test = id.split('examples-')[1];
|
||||||
|
ed.mergely('lhs', test_config[test]['lhs']);
|
||||||
|
ed.mergely('rhs', test_config[test]['rhs']);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.wickedmenu(menu_opts).bind('selected', function(ev, id) {
|
||||||
|
return handle_operation(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
toolbar.wickedtoolbar({}).bind('selected', function(ev, id) {
|
||||||
|
if (!id) return false;
|
||||||
|
return handle_operation(id.replace(/^tb-/, ''));
|
||||||
|
});
|
||||||
|
|
||||||
|
toolbar.find('li[title]').tipsy({opacity: 1});
|
||||||
|
menu.find('li[title]').tipsy({opacity: 1, delayIn: 1000, gravity: 'w'});
|
||||||
|
|
||||||
|
function handleShare(ed) {
|
||||||
|
var fork = $(this).attr('id') == 'fork';
|
||||||
|
if (key == '') key = ''.random(8);
|
||||||
|
var count = 0;
|
||||||
|
function post_save(side, text) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST', async: true, dataType: 'text',
|
||||||
|
url: '/ajax/handle_file.php',
|
||||||
|
data: { 'key': key, 'name': side, 'content': text },
|
||||||
|
success: function (nkey) {
|
||||||
|
++count;
|
||||||
|
if (count == 2) {
|
||||||
|
var url = '/ajax/handle_save.php?key=' + key;
|
||||||
|
if (fork) url += '&nkey=' + ''.random(8);
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET', async: false, dataType: 'text',
|
||||||
|
url: url,
|
||||||
|
success: function (nkey) {
|
||||||
|
// redirect
|
||||||
|
if (nkey.length) window.location.href = '/' + $.trim(nkey) + '/';
|
||||||
|
},
|
||||||
|
error: function(xhr, ajaxOptions, thrownError){
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, ajaxOptions, thrownError){
|
||||||
|
alert(thrownError);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function save_files() {
|
||||||
|
var lhs = ed.mergely('get', 'lhs');
|
||||||
|
var rhs = ed.mergely('get', 'rhs');
|
||||||
|
post_save('lhs', lhs);
|
||||||
|
post_save('rhs', rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
$( '#dialog-confirm' ).dialog({
|
||||||
|
resizable: false, width: 350, modal: true,
|
||||||
|
buttons: {
|
||||||
|
'Save for Sharing': function() {
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
save_files();
|
||||||
|
},
|
||||||
|
Cancel: function() {
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function crossdomainGET(ed, side, url) {
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET', dataType: 'text',
|
||||||
|
data: {url: url},
|
||||||
|
url: '/ajax/handle_crossdomain.php',
|
||||||
|
contentType: 'text/plain',
|
||||||
|
success: function (response) {
|
||||||
|
ed.mergely(side, response);
|
||||||
|
},
|
||||||
|
error: function(xhr, ajaxOptions, thrownError){
|
||||||
|
console.error('error', xhr, ajaxOptions, thrownError);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function importFiles(ed) {
|
||||||
|
// -------------
|
||||||
|
// file uploader - html5 file upload to browser
|
||||||
|
function file_load(target, side) {
|
||||||
|
var file = target.files[0];
|
||||||
|
var reader = new FileReader();
|
||||||
|
var $target = $(target);
|
||||||
|
function trigger(name, event) { $target.trigger(name, event); }
|
||||||
|
reader.onloadstart = function(evt) { trigger('start'); }
|
||||||
|
reader.onprogress = function(evt) { trigger('progress', evt); }
|
||||||
|
reader.onload = function(evt) { trigger('loaded', evt.target.result); }
|
||||||
|
reader.onerror = function (evt) {
|
||||||
|
alert(evt.target.error.name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
reader.readAsText(file, 'UTF-8');
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
alert(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var file_data = {};
|
||||||
|
$('#file-lhs, #file-rhs').change(function (evt) {
|
||||||
|
var re = new RegExp('.*[\\\\/](.*)$');
|
||||||
|
var match = re.exec($(this).val());
|
||||||
|
var fname = match ? match[1] : 'unknown';
|
||||||
|
|
||||||
|
var progressbar = $('#' + evt.target.id + '-progress');
|
||||||
|
|
||||||
|
file_load(evt.target);
|
||||||
|
$(evt.target).bind('start', function(ev){
|
||||||
|
$(evt.target).css('display', 'none');
|
||||||
|
progressbar.css('display', 'inline-block');
|
||||||
|
});
|
||||||
|
$(evt.target).bind('progress', function(ev, progress){
|
||||||
|
var loaded = (progress.loaded / progress.total) * 100;
|
||||||
|
progressbar.find('> .progress-label').text(loaded + '%');
|
||||||
|
progressbar.progressbar('value', loaded);
|
||||||
|
});
|
||||||
|
$(evt.target).bind('loaded', function(ev, file){
|
||||||
|
progressbar.progressbar('value', 100);
|
||||||
|
progressbar.find('> .progress-label').text(fname);
|
||||||
|
file_data[evt.target.id] = file;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#file-lhs-progress').progressbar({value: 0});
|
||||||
|
$('#file-rhs-progress').progressbar({value: 0});
|
||||||
|
$('#dialog-upload .tabs').tabs();
|
||||||
|
function callbackName(data) {
|
||||||
|
console.log('callbackName', data);
|
||||||
|
}
|
||||||
|
$('#dialog-upload').dialog({
|
||||||
|
dialogClass: 'no-title',
|
||||||
|
resizable: false,
|
||||||
|
width: '450px',
|
||||||
|
modal: true,
|
||||||
|
buttons: {
|
||||||
|
Import: function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
|
||||||
|
var urls = { lhs: $('#url-lhs').val(), rhs: $('#url-rhs').val() };
|
||||||
|
for (var side in urls) {
|
||||||
|
var url = urls[side];
|
||||||
|
if (!url) continue;
|
||||||
|
crossdomainGET(ed, side, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_data.hasOwnProperty('file-lhs')) {
|
||||||
|
ed.mergely('lhs', file_data['file-lhs']);
|
||||||
|
}
|
||||||
|
if (file_data.hasOwnProperty('file-rhs')) {
|
||||||
|
ed.mergely('rhs', file_data['file-rhs']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Cancel: function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function colorSettings(ed) {
|
||||||
|
// get current settings
|
||||||
|
var sd = $('<span style="display:none" class="mergely ch d lhs start end">C</span>');
|
||||||
|
var sa = $('<span style="display:none" class="mergely bg a rhs start end">C</span>');
|
||||||
|
var sc = $('<span style="display:none" class="mergely c rhs start end">C</span>');
|
||||||
|
$('body').append(sd);
|
||||||
|
$('body').append(sa);
|
||||||
|
$('body').append(sc);
|
||||||
|
var conf = {
|
||||||
|
'c-border': {id: '#c-border', getColor: function() { return sc.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
|
||||||
|
'c-bg': {id: '#c-bg', getColor: function() { return sc.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
|
||||||
|
'a-border': {id: '#a-border', getColor: function() { return sa.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
|
||||||
|
'a-bg': {id: '#a-bg', getColor: function() { return sa.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
|
||||||
|
'd-border': {id: '#d-border', getColor: function() { return sd.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
|
||||||
|
'd-bg': {id: '#d-bg', getColor: function() { return sd.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }}
|
||||||
|
};
|
||||||
|
$.each(conf, function(key, item){$(item.id).val(item.getColor()); });
|
||||||
|
var f = $.farbtastic('#picker');
|
||||||
|
$('.colorwell').each(function(){ f.linkTo(this); }).focus(function(){
|
||||||
|
var tthis = $(this);
|
||||||
|
f.linkTo(this);
|
||||||
|
var item = conf[tthis.attr('id')];
|
||||||
|
f.setColor(item.getColor());
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#dialog-colors').dialog({
|
||||||
|
width: 490, modal: true,
|
||||||
|
buttons: {
|
||||||
|
Apply: function() {
|
||||||
|
var cborder = $('#c-border').val();
|
||||||
|
var aborder = $('#a-border').val();
|
||||||
|
var dborder = $('#d-border').val();
|
||||||
|
var abg = $('#a-bg').val();
|
||||||
|
var dbg = $('#d-bg').val();
|
||||||
|
var cbg = $('#c-bg').val();
|
||||||
|
var textCss = makeColorCss(cborder, cbg, aborder, abg, dborder, dbg);
|
||||||
|
applyColorCss(textCss, cborder, cbg, aborder, abg, dborder, dbg, true);
|
||||||
|
},
|
||||||
|
Reset: function() {
|
||||||
|
},
|
||||||
|
Close: function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function makeColorCss(changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground) {
|
||||||
|
var text =
|
||||||
|
'.mergely.a.rhs.start{border-top-color:' + addedBorder + ';}\n\
|
||||||
|
.mergely.a.lhs.start.end,\n\
|
||||||
|
.mergely.a.rhs.end{border-bottom-color:' + addedBorder + ';}\n\
|
||||||
|
.mergely.a.rhs{background-color:' + addedBackground + ';}\n\
|
||||||
|
.mergely.d.lhs{background-color:' + deletedBackground + ';}\n\
|
||||||
|
.mergely.d.lhs.end,\n\
|
||||||
|
.mergely.d.rhs.start.end{border-bottom-color:' + deletedBorder + ';}\n\
|
||||||
|
.mergely.d.rhs.start.end.first{border-top-color:' + deletedBorder + ';}\n\
|
||||||
|
.mergely.d.lhs.start{border-top-color:' + deletedBorder + ';}\n\
|
||||||
|
.mergely.c.lhs,\n\
|
||||||
|
.mergely.c.rhs{background-color:' + changeBackground + ';}\n\
|
||||||
|
.mergely.c.lhs.start,\n\
|
||||||
|
.mergely.c.rhs.start{border-top-color:' + changeBorder + ';}\n\
|
||||||
|
.mergely.c.lhs.end,\n\
|
||||||
|
.mergely.c.rhs.end{border-bottom-color:' + changeBorder + ';}\n\
|
||||||
|
.mergely.ch.a.rhs{background-color:' + addedBackground + ';}\n\
|
||||||
|
.mergely.ch.d.lhs{background-color:' + deletedBackground + ';color: #888;}';
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
function applyParameterCss(saveState) {
|
||||||
|
var cb = '#' + parameters.get('cb',color_defaults.cb),
|
||||||
|
cg = '#' + parameters.get('cg',color_defaults.cg),
|
||||||
|
ab = '#' + parameters.get('ab',color_defaults.ab),
|
||||||
|
ag = '#' + parameters.get('ag',color_defaults.ag),
|
||||||
|
db = '#' + parameters.get('db',color_defaults.db),
|
||||||
|
dg = '#' + parameters.get('dg',color_defaults.dg);
|
||||||
|
applyColorCss(makeColorCss(cb, cg, ab, ag, db, dg), cb, cg, ab, ag, db, dg, saveState);
|
||||||
|
}
|
||||||
|
function applyColorCss(cssText, changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground, saveState) {
|
||||||
|
$('<style type="text/css">' + cssText + '</style>').appendTo('head');
|
||||||
|
ed.mergely('options', {
|
||||||
|
fgcolor:{a:addedBorder,c:changeBorder,d:deletedBorder}
|
||||||
|
});
|
||||||
|
var params = updateQueryStringParam('cb', changeBorder.replace(/#/g, ''), color_defaults.cb);
|
||||||
|
params = updateQueryStringParam('cg', changeBackground.replace(/#/g, ''), color_defaults.cg, params);
|
||||||
|
params = updateQueryStringParam('ab', addedBorder.replace(/#/g, ''), color_defaults.ab, params);
|
||||||
|
params = updateQueryStringParam('ag', addedBackground.replace(/#/g, ''), color_defaults.ag, params);
|
||||||
|
params = updateQueryStringParam('db', deletedBorder.replace(/#/g, ''), color_defaults.db, params);
|
||||||
|
params = updateQueryStringParam('dg', deletedBackground.replace(/#/g, ''), color_defaults.dg, params);
|
||||||
|
|
||||||
|
if (saveState) {
|
||||||
|
updateHistory(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updateHistory(params) {
|
||||||
|
var baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
|
||||||
|
window.history.pushState({}, null, baseUrl + params);
|
||||||
|
}
|
||||||
|
// Explicitly save/update a url parameter using HTML5's replaceState().
|
||||||
|
function updateQueryStringParam(key, value, defaultValue, urlQueryString) {
|
||||||
|
urlQueryString = urlQueryString || document.location.search;
|
||||||
|
var parts = urlQueryString.replace(/^\?/, '').split(/&/), found = false;
|
||||||
|
for (var i in parts) {
|
||||||
|
if (parts[i].startsWith(key + '=')) {
|
||||||
|
found = true;
|
||||||
|
if (value === defaultValue) {
|
||||||
|
// value is default value, remove option
|
||||||
|
parts.splice(i, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// make new value
|
||||||
|
parts[i] = key + '=' + value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (parts[i].length === 0) {
|
||||||
|
parts.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
parts.push(key + '=' + value);
|
||||||
|
}
|
||||||
|
return (parts.length) ? '?' + parts.join('&') : '';
|
||||||
|
}
|
||||||
|
});
|
6
static/mergely/editor/editor.min.js
vendored
Normal file
290
static/mergely/editor/editor.php
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
<?php
|
||||||
|
$key = '';
|
||||||
|
$debug = False;
|
||||||
|
if (isset($_GET['key'])) {
|
||||||
|
$key = $_GET['key'];
|
||||||
|
}
|
||||||
|
if (isset($_GET['debug'])) {
|
||||||
|
$debug = filter_var($_GET['debug'], FILTER_VALIDATE_BOOLEAN);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" /><title>Mergely - Diff online, merge documents</title>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="description" content="Merge and Diff your documents with diff online and share" />
|
||||||
|
<meta name="keywords" content="diff,merge,compare,jsdiff,comparison,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
|
||||||
|
<meta name="author" content="Jamie Peabody" />
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
|
<link rel="canonical" href="http://www.mergely.com" />
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
|
||||||
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
|
||||||
|
|
||||||
|
<link type="text/css" rel="stylesheet" href="/style/mergely-theme/jquery-ui-1.10.1.custom.css" />
|
||||||
|
<link type='text/css' rel='stylesheet' href='/Mergely/editor/lib/wicked-ui.css' />
|
||||||
|
<script type="text/javascript" src="/Mergely/editor/lib/wicked-ui.js"></script>
|
||||||
|
|
||||||
|
<link type='text/css' rel='stylesheet' href='/Mergely/editor/lib/tipsy/tipsy.css' />
|
||||||
|
<script type="text/javascript" src="/Mergely/editor/lib/tipsy/jquery.tipsy.js"></script>
|
||||||
|
<script type="text/javascript" src="/Mergely/editor/lib/farbtastic/farbtastic.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/Mergely/editor/lib/farbtastic/farbtastic.css" />
|
||||||
|
<?php
|
||||||
|
if ($debug) {
|
||||||
|
?>
|
||||||
|
<script type="text/javascript" src="/Mergely/lib/codemirror.js"></script>
|
||||||
|
<script type="text/javascript" src="/Mergely/lib/mergely.js"></script>
|
||||||
|
<script type="text/javascript" src="/Mergely/editor/editor.js"></script>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
?>
|
||||||
|
<script type="text/javascript" src="/Mergely/lib/codemirror.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/Mergely/lib/mergely.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/Mergely/editor/editor.min.js"></script>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/Mergely/lib/codemirror.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/Mergely/lib/mergely.css" />
|
||||||
|
<link type='text/css' rel='stylesheet' href='/Mergely/editor/editor.css' />
|
||||||
|
<script type="text/javascript" src="/Mergely/lib/searchcursor.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var key = '<?php echo htmlspecialchars($key, ENT_QUOTES, 'UTF-8'); ?>';
|
||||||
|
var isSample = key == 'usaindep';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- analytics -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _gaq = _gaq || [];
|
||||||
|
_gaq.push(['_setAccount', 'UA-85576-5']);
|
||||||
|
_gaq.push(['_trackPageview']);
|
||||||
|
(function() {
|
||||||
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||||
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||||
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- google +1 -->
|
||||||
|
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
|
||||||
|
</head>
|
||||||
|
<body style="visibility:hidden">
|
||||||
|
<div id="fb-root"></div><script>(function(d, s, id) {
|
||||||
|
var js, fjs = d.getElementsByTagName(s)[0];
|
||||||
|
if (d.getElementById(id)) return;
|
||||||
|
js = d.createElement(s); js.id = id;
|
||||||
|
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
|
||||||
|
fjs.parentNode.insertBefore(js, fjs);
|
||||||
|
}(document, 'script', 'facebook-jssdk'));</script>
|
||||||
|
|
||||||
|
|
||||||
|
<a href="/"><div id="banner"></div></a>
|
||||||
|
|
||||||
|
<!-- menu -->
|
||||||
|
<ul id="main-menu">
|
||||||
|
<li accesskey="f">
|
||||||
|
File
|
||||||
|
<ul>
|
||||||
|
<li id="file-new" accesskey="n" data-hotkey="Alt+N">New</li>
|
||||||
|
<li id="file-import" data-icon="icon-import">Import...</li>
|
||||||
|
<li id="file-save" accesskey="s" data-hotkey="Alt+S" data-icon="icon-save">Save .diff</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="file-share" data-icon="icon-share">Share</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li accesskey="l">
|
||||||
|
Left
|
||||||
|
<ul>
|
||||||
|
<li id="edit-left-undo" accesskey="z" data-hotkey="Ctrl+Z" data-icon="icon-undo">Undo</li>
|
||||||
|
<li id="edit-left-redo" accesskey="y" data-hotkey="Ctrl+Y" data-icon="icon-redo">Redo</li>
|
||||||
|
<li id="edit-left-find">Find</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="edit-left-merge-right" data-hotkey="Alt+→" data-icon="icon-arrow-right-v">Merge change right</li>
|
||||||
|
<li id="edit-left-merge-right-file" data-icon="icon-arrow-right-vv">Merge file right</li>
|
||||||
|
<li id="edit-left-readonly">Read only</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="edit-left-clear">Clear</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li accesskey="r">
|
||||||
|
Right
|
||||||
|
<ul>
|
||||||
|
<li id="edit-right-undo" accesskey="z" data-hotkey="Ctrl+Z" data-icon="icon-undo">Undo</li>
|
||||||
|
<li id="edit-right-redo" accesskey="y" data-hotkey="Ctrl+Y" data-icon="icon-redo">Redo</li>
|
||||||
|
<li id="edit-right-find">Find</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="edit-right-merge-left" data-hotkey="Alt+←" data-icon="icon-arrow-left-v">Merge change left</li>
|
||||||
|
<li id="edit-right-merge-left-file" data-icon="icon-arrow-left-vv">Merge file left</li>
|
||||||
|
<li id="edit-right-readonly">Read only</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="edit-right-clear">Clear</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li accesskey="v">
|
||||||
|
View
|
||||||
|
<ul>
|
||||||
|
<li id="view-swap" data-icon="icon-swap">Swap sides</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="view-refresh" accesskey="v" data-hotkey="Alt+V" title="Generates diff markup">Render diff view</li>
|
||||||
|
<li id="view-clear" accesskey="c" data-hotkey="Alt+C" title="Clears diff markup">Clear render</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="view-change-prev" data-hotkey="Alt+↑" title="View previous change">View prev change</li>
|
||||||
|
<li id="view-change-next" data-hotkey="Alt+↓" title="View next change">View next change</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li accesskey="o">
|
||||||
|
Options
|
||||||
|
<ul>
|
||||||
|
<li id="options-wrap">Wrap lines</li>
|
||||||
|
<li id="options-ignorews">Ignore white space</li>
|
||||||
|
<li id="options-ignorecase">Ignore case</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="options-viewport" title="Improves performance for large files">Enable viewport</li>
|
||||||
|
<li id="options-sidebars" title="Improves performance for large files">Enable side bars</li>
|
||||||
|
<li id="options-swapmargin">Swap right margin</li>
|
||||||
|
<li id="options-linenumbers">Enable line numbers</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="options-autodiff" title="Diffs are computed automatically">Enable auto-diff</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="options-colors">Colors...</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li accesskey="m">
|
||||||
|
Mergely
|
||||||
|
<ul>
|
||||||
|
<li><a class="link" href="/" target="site">Home</a></li>
|
||||||
|
<li><a class="link" href="/about" target="site">About</a></li>
|
||||||
|
<li><a class="link" href="/license" target="site">License</a></li>
|
||||||
|
<li><a class="link" href="/download" target="site">Download</a></li>
|
||||||
|
<li><a class="link" href="/doc" target="site">Mergely development guide</a></li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li><a class="link" href="/united-states-declaration-of-independence?wl=1" target="_blank">United States Declaration of Independence Draft</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php
|
||||||
|
if (!$debug) {
|
||||||
|
?>
|
||||||
|
<li accesskey="s">
|
||||||
|
Social
|
||||||
|
<ul>
|
||||||
|
<li id="social-twitter">
|
||||||
|
<div style="padding: 10px 10px 5px 10px" title="Twitter">
|
||||||
|
<a href="https://twitter.com/share" class="twitter-share-button" data-via="jamiepeabody">Tweet</a>
|
||||||
|
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li id="social-facebook">
|
||||||
|
<div style="padding: 10px 10px 5px 10px" title="Facebook">
|
||||||
|
<div class="fb-like" data-href="http://www.mergely.com" data-send="true" data-width="200" data-show-faces="true"></div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li id="social-google">
|
||||||
|
<div style="padding: 10px 10px 5px 10px" title="Google+"><g:plusone></g:plusone></div>
|
||||||
|
</li>
|
||||||
|
<li id="social-reddit">
|
||||||
|
<div style="padding: 10px 10px 5px 10px" title="Reddit">
|
||||||
|
<a target="_blank" href="http://www.reddit.com/submit" onclick="window.location = 'http://www.reddit.com/submit?url=' + encodeURIComponent(window.location); return false" style="color:black;text-decoration:none;"><img src="http://www.reddit.com/static/spreddit1.gif" alt="submit to reddit" border="0" />
|
||||||
|
<span>Reddit</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- toolbar -->
|
||||||
|
<ul id="toolbar">
|
||||||
|
<li id="tb-file-share" data-icon="icon-share" title="Share">Share</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="tb-file-import" data-icon="icon-import" title="Import">Import</li>
|
||||||
|
<li id="tb-file-save" data-icon="icon-save" title="Save .diff">Save .diff</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="tb-view-change-prev" data-icon="icon-arrow-up" title="Previous change">Previous change</li>
|
||||||
|
<li id="tb-view-change-next" data-icon="icon-arrow-down" title="Next change">Next change</li>
|
||||||
|
<li class="separator"></li>
|
||||||
|
<li id="tb-edit-right-merge-left" data-icon="icon-arrow-left-v" title="Merge change left">Merge change left</li>
|
||||||
|
<li id="tb-edit-left-merge-right" data-icon="icon-arrow-right-v" title="Merge change right">Merge change right</li>
|
||||||
|
<li id="tb-view-swap" data-icon="icon-swap" title="Swap sides">Swap sides</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- dialog upload -->
|
||||||
|
<div id="dialog-upload" title="File import" style="display:none">
|
||||||
|
<div class="tabs">
|
||||||
|
<ul>
|
||||||
|
<li><a href="#tabs-1">Import File</a></li>
|
||||||
|
<li><a href="#tabs-2">Import URL</a></li>
|
||||||
|
</ul>
|
||||||
|
<div id="tabs-1">
|
||||||
|
<p>
|
||||||
|
Files are imported directly into your browser. They are <em>not</em> uploaded to the server.
|
||||||
|
</p>
|
||||||
|
<label for="file-lhs">Left file</label> <input id="file-lhs" style="display:inline-block" type="file"><div id="file-lhs-progress"><div class="progress-label">Loading...</div></div><br />
|
||||||
|
<label for="file-rhs">Right file</label> <input id="file-rhs" style="display:inline-block" type="file"><div id="file-rhs-progress"><div class="progress-label">Loading...</div></div><br />
|
||||||
|
</div>
|
||||||
|
<div id="tabs-2">
|
||||||
|
<p>
|
||||||
|
Files are imported directly into your browser. They are <em>not</em> uploaded to the server.
|
||||||
|
</p>
|
||||||
|
<label for="url-lhs">Left URL</label> <input id="url-lhs" type="input" size="40"><div id="file-lhs-progress"><div class="progress-label">Loading...</div></div><br />
|
||||||
|
<label for="url-rhs">Right URL</label> <input id="url-rhs" type="input" size="40"><div id="file-rhs-progress"><div class="progress-label">Loading...</div></div><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- dialog colors -->
|
||||||
|
<div id="dialog-colors" title="Mergely Color Settings" style="display:none">
|
||||||
|
<div id="picker" style="float: right;"></div>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Changed</legend>
|
||||||
|
<label for="c-border">Border:</label><input type="text" id="c-border" name="c-border" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
<label for="c-bg">Background:</label><input type="text" id="c-bg" name="c-bg" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Added</legend>
|
||||||
|
<label for="a-border">Border:</label><input type="text" id="a-border" name="a-border" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
<label for="a-bg">Background:</label><input type="text" id="a-bg" name="a-bg" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Deleted</legend>
|
||||||
|
<label for="d-border">Border:</label><input type="text" id="d-border" name="d-border" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
<label for="d-bg">Background:</label><input type="text" id="d-bg" name="d-bg" class="colorwell" />
|
||||||
|
<br />
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- dialog confirm -->
|
||||||
|
<div id="dialog-confirm" title="Save a Permanent Copy?" style="display:none;">
|
||||||
|
<p>
|
||||||
|
Are you sure you want to save? A permanent copy will be
|
||||||
|
created at the server and a link will be provided for you to share the URL
|
||||||
|
in an email, blog, twitter, etc.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- find -->
|
||||||
|
<div class="find">
|
||||||
|
<input type="text" />
|
||||||
|
<button class="find-prev"><span class="icon icon-arrow-up"></span></button>
|
||||||
|
<button class="find-next"><span class="icon icon-arrow-down"></span></button>
|
||||||
|
<button class="find-close"><span class="icon icon-x-mark"></span></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- editor -->
|
||||||
|
<div style="position: absolute;top: 73px;bottom: 10px;left: 5px;right: 5px;overflow-y: hidden;padding-bottom: 2px;">
|
||||||
|
<div id="mergely">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
static/mergely/editor/images/arrow-down-v.png
Normal file
After Width: | Height: | Size: 274 B |
BIN
static/mergely/editor/images/arrow-left-v.png
Normal file
After Width: | Height: | Size: 243 B |
BIN
static/mergely/editor/images/arrow-left-vv.png
Normal file
After Width: | Height: | Size: 319 B |
BIN
static/mergely/editor/images/arrow-right-v.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
static/mergely/editor/images/arrow-right-vv.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
static/mergely/editor/images/arrow-right.png
Normal file
After Width: | Height: | Size: 218 B |
BIN
static/mergely/editor/images/arrow-up-v.png
Normal file
After Width: | Height: | Size: 288 B |
BIN
static/mergely/editor/images/banner.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
static/mergely/editor/images/check.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
static/mergely/editor/images/download.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
static/mergely/editor/images/redo.png
Normal file
After Width: | Height: | Size: 266 B |
BIN
static/mergely/editor/images/share.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
static/mergely/editor/images/swap.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
static/mergely/editor/images/undo.png
Normal file
After Width: | Height: | Size: 263 B |
BIN
static/mergely/editor/images/upload.png
Normal file
After Width: | Height: | Size: 301 B |
BIN
static/mergely/editor/images/x-mark.png
Normal file
After Width: | Height: | Size: 234 B |
341
static/mergely/editor/lib/farbtastic/LICENSE.txt
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
51
static/mergely/editor/lib/farbtastic/farbtastic.css
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Farbtastic Color Picker 1.2
|
||||||
|
* © 2008 Steven Wittens
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
.farbtastic {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.farbtastic * {
|
||||||
|
position: absolute;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.farbtastic, .farbtastic .wheel {
|
||||||
|
width: 195px;
|
||||||
|
height: 195px;
|
||||||
|
}
|
||||||
|
.farbtastic .color, .farbtastic .overlay {
|
||||||
|
top: 47px;
|
||||||
|
left: 47px;
|
||||||
|
width: 101px;
|
||||||
|
height: 101px;
|
||||||
|
}
|
||||||
|
.farbtastic .wheel {
|
||||||
|
background: url(wheel.png) no-repeat;
|
||||||
|
width: 195px;
|
||||||
|
height: 195px;
|
||||||
|
}
|
||||||
|
.farbtastic .overlay {
|
||||||
|
background: url(mask.png) no-repeat;
|
||||||
|
}
|
||||||
|
.farbtastic .marker {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
margin: -8px 0 0 -8px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: url(marker.png) no-repeat;
|
||||||
|
}
|
||||||
|
|
367
static/mergely/editor/lib/farbtastic/farbtastic.js
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
/**
|
||||||
|
* Farbtastic Color Picker 1.2
|
||||||
|
* © 2008 Steven Wittens
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
jQuery.fn.farbtastic = function (callback) {
|
||||||
|
$.farbtastic(this, callback);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
jQuery.farbtastic = function (container, callback) {
|
||||||
|
var container = $(container).get(0);
|
||||||
|
return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery._farbtastic = function (container, callback) {
|
||||||
|
// Store farbtastic object
|
||||||
|
var fb = this;
|
||||||
|
|
||||||
|
// Insert markup
|
||||||
|
$(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
|
||||||
|
var e = $('.farbtastic', container);
|
||||||
|
fb.wheel = $('.wheel', container).get(0);
|
||||||
|
// Dimensions
|
||||||
|
fb.radius = 84;
|
||||||
|
fb.square = 100;
|
||||||
|
fb.width = 194;
|
||||||
|
|
||||||
|
// Fix background PNGs in IE6
|
||||||
|
if (navigator.appVersion.match(/MSIE [0-6]\./)) {
|
||||||
|
$('*', e).each(function () {
|
||||||
|
if (this.currentStyle.backgroundImage != 'none') {
|
||||||
|
var image = this.currentStyle.backgroundImage;
|
||||||
|
image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
|
||||||
|
$(this).css({
|
||||||
|
'backgroundImage': 'none',
|
||||||
|
'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to the given element(s) or callback.
|
||||||
|
*/
|
||||||
|
fb.linkTo = function (callback) {
|
||||||
|
// Unbind previous nodes
|
||||||
|
if (typeof fb.callback == 'object') {
|
||||||
|
$(fb.callback).unbind('keyup', fb.updateValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset color
|
||||||
|
fb.color = null;
|
||||||
|
|
||||||
|
// Bind callback or elements
|
||||||
|
if (typeof callback == 'function') {
|
||||||
|
fb.callback = callback;
|
||||||
|
}
|
||||||
|
else if (typeof callback == 'object' || typeof callback == 'string') {
|
||||||
|
fb.callback = $(callback);
|
||||||
|
fb.callback.bind('keyup', fb.updateValue);
|
||||||
|
if (fb.callback.get(0).value) {
|
||||||
|
fb.setColor(fb.callback.get(0).value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
fb.updateValue = function (event) {
|
||||||
|
if (this.value && this.value != fb.color) {
|
||||||
|
fb.setColor(this.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change color with HTML syntax #123456
|
||||||
|
*/
|
||||||
|
fb.setColor = function (color) {
|
||||||
|
var unpack = fb.unpack(color);
|
||||||
|
// JAMIE WAS HERE rgb(r, g, b) modification
|
||||||
|
if (!unpack && color) {
|
||||||
|
color = fb.RGBToHex(color);
|
||||||
|
if (color) unpack = fb.unpack(color);
|
||||||
|
}
|
||||||
|
// JAMIE WAS HERE rgb(r, g, b) modification
|
||||||
|
if (fb.color != color && unpack) {
|
||||||
|
fb.color = color;
|
||||||
|
fb.rgb = unpack;
|
||||||
|
fb.hsl = fb.RGBToHSL(fb.rgb);
|
||||||
|
fb.updateDisplay();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change color with HSL triplet [0..1, 0..1, 0..1]
|
||||||
|
*/
|
||||||
|
fb.setHSL = function (hsl) {
|
||||||
|
fb.hsl = hsl;
|
||||||
|
fb.rgb = fb.HSLToRGB(hsl);
|
||||||
|
fb.color = fb.pack(fb.rgb);
|
||||||
|
fb.updateDisplay();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the coordinates of the given event relative to the center
|
||||||
|
* of the widget.
|
||||||
|
*/
|
||||||
|
fb.widgetCoords = function (event) {
|
||||||
|
var x, y;
|
||||||
|
var el = event.target || event.srcElement;
|
||||||
|
var reference = fb.wheel;
|
||||||
|
|
||||||
|
if (typeof event.offsetX != 'undefined') {
|
||||||
|
// Use offset coordinates and find common offsetParent
|
||||||
|
var pos = { x: event.offsetX, y: event.offsetY };
|
||||||
|
|
||||||
|
// Send the coordinates upwards through the offsetParent chain.
|
||||||
|
var e = el;
|
||||||
|
while (e) {
|
||||||
|
e.mouseX = pos.x;
|
||||||
|
e.mouseY = pos.y;
|
||||||
|
pos.x += e.offsetLeft;
|
||||||
|
pos.y += e.offsetTop;
|
||||||
|
e = e.offsetParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the coordinates starting from the wheel widget.
|
||||||
|
var e = reference;
|
||||||
|
var offset = { x: 0, y: 0 }
|
||||||
|
while (e) {
|
||||||
|
if (typeof e.mouseX != 'undefined') {
|
||||||
|
x = e.mouseX - offset.x;
|
||||||
|
y = e.mouseY - offset.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset.x += e.offsetLeft;
|
||||||
|
offset.y += e.offsetTop;
|
||||||
|
e = e.offsetParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset stored coordinates
|
||||||
|
e = el;
|
||||||
|
while (e) {
|
||||||
|
e.mouseX = undefined;
|
||||||
|
e.mouseY = undefined;
|
||||||
|
e = e.offsetParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use absolute coordinates
|
||||||
|
var pos = fb.absolutePosition(reference);
|
||||||
|
x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
|
||||||
|
y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
|
||||||
|
}
|
||||||
|
// Subtract distance to middle
|
||||||
|
return { x: x - fb.width / 2, y: y - fb.width / 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mousedown handler
|
||||||
|
*/
|
||||||
|
fb.mousedown = function (event) {
|
||||||
|
// Capture mouse
|
||||||
|
if (!document.dragging) {
|
||||||
|
$(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
|
||||||
|
document.dragging = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check which area is being dragged
|
||||||
|
var pos = fb.widgetCoords(event);
|
||||||
|
fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
|
||||||
|
|
||||||
|
// Process
|
||||||
|
fb.mousemove(event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mousemove handler
|
||||||
|
*/
|
||||||
|
fb.mousemove = function (event) {
|
||||||
|
// Get coordinates relative to color picker center
|
||||||
|
var pos = fb.widgetCoords(event);
|
||||||
|
|
||||||
|
// Set new HSL parameters
|
||||||
|
if (fb.circleDrag) {
|
||||||
|
var hue = Math.atan2(pos.x, -pos.y) / 6.28;
|
||||||
|
if (hue < 0) hue += 1;
|
||||||
|
fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
|
||||||
|
var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
|
||||||
|
fb.setHSL([fb.hsl[0], sat, lum]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mouseup handler
|
||||||
|
*/
|
||||||
|
fb.mouseup = function () {
|
||||||
|
// Uncapture mouse
|
||||||
|
$(document).unbind('mousemove', fb.mousemove);
|
||||||
|
$(document).unbind('mouseup', fb.mouseup);
|
||||||
|
document.dragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the markers and styles
|
||||||
|
*/
|
||||||
|
fb.updateDisplay = function () {
|
||||||
|
// Markers
|
||||||
|
var angle = fb.hsl[0] * 6.28;
|
||||||
|
$('.h-marker', e).css({
|
||||||
|
left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
|
||||||
|
top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.sl-marker', e).css({
|
||||||
|
left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
|
||||||
|
top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Saturation/Luminance gradient
|
||||||
|
$('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
|
||||||
|
|
||||||
|
// Linked elements or callback
|
||||||
|
if (typeof fb.callback == 'object') {
|
||||||
|
// Set background/foreground color
|
||||||
|
$(fb.callback).css({
|
||||||
|
backgroundColor: fb.color,
|
||||||
|
color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change linked value
|
||||||
|
$(fb.callback).each(function() {
|
||||||
|
if (this.value && this.value != fb.color) {
|
||||||
|
this.value = fb.color;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (typeof fb.callback == 'function') {
|
||||||
|
fb.callback.call(fb, fb.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get absolute position of element
|
||||||
|
*/
|
||||||
|
fb.absolutePosition = function (el) {
|
||||||
|
var r = { x: el.offsetLeft, y: el.offsetTop };
|
||||||
|
// Resolve relative to offsetParent
|
||||||
|
if (el.offsetParent) {
|
||||||
|
var tmp = fb.absolutePosition(el.offsetParent);
|
||||||
|
r.x += tmp.x;
|
||||||
|
r.y += tmp.y;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Various color utility functions */
|
||||||
|
fb.pack = function (rgb) {
|
||||||
|
var r = Math.round(rgb[0] * 255);
|
||||||
|
var g = Math.round(rgb[1] * 255);
|
||||||
|
var b = Math.round(rgb[2] * 255);
|
||||||
|
return '#' + (r < 16 ? '0' : '') + r.toString(16) +
|
||||||
|
(g < 16 ? '0' : '') + g.toString(16) +
|
||||||
|
(b < 16 ? '0' : '') + b.toString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fb.unpack = function (color) {
|
||||||
|
if (color.length == 7) {
|
||||||
|
return [parseInt('0x' + color.substring(1, 3)) / 255,
|
||||||
|
parseInt('0x' + color.substring(3, 5)) / 255,
|
||||||
|
parseInt('0x' + color.substring(5, 7)) / 255];
|
||||||
|
}
|
||||||
|
else if (color.length == 4) {
|
||||||
|
return [parseInt('0x' + color.substring(1, 2)) / 15,
|
||||||
|
parseInt('0x' + color.substring(2, 3)) / 15,
|
||||||
|
parseInt('0x' + color.substring(3, 4)) / 15];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fb.HSLToRGB = function (hsl) {
|
||||||
|
var m1, m2, r, g, b;
|
||||||
|
var h = hsl[0], s = hsl[1], l = hsl[2];
|
||||||
|
m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
|
||||||
|
m1 = l * 2 - m2;
|
||||||
|
return [this.hueToRGB(m1, m2, h+0.33333),
|
||||||
|
this.hueToRGB(m1, m2, h),
|
||||||
|
this.hueToRGB(m1, m2, h-0.33333)];
|
||||||
|
}
|
||||||
|
|
||||||
|
fb.hueToRGB = function (m1, m2, h) {
|
||||||
|
h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
|
||||||
|
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
|
||||||
|
if (h * 2 < 1) return m2;
|
||||||
|
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
|
||||||
|
return m1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JAMIE WAS HERE
|
||||||
|
fb.RGBToHex = function(color) {
|
||||||
|
var exp = new RegExp(/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3}\s*)\)/i);
|
||||||
|
if(exp.test(color)) {
|
||||||
|
var results = exp.exec(color);
|
||||||
|
var r = parseInt(results[1]).toString(16);
|
||||||
|
var g = parseInt(results[2]).toString(16);
|
||||||
|
var b = parseInt(results[3]).toString(16);
|
||||||
|
if (r.length < 2) r = '0' + r;
|
||||||
|
if (g.length < 2) g = '0' + g;
|
||||||
|
if (b.length < 2) b = '0' + b;
|
||||||
|
return '#' + r + g + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// JAMIE WAS HERE
|
||||||
|
|
||||||
|
fb.RGBToHSL = function (rgb) {
|
||||||
|
var min, max, delta, h, s, l;
|
||||||
|
var r = rgb[0], g = rgb[1], b = rgb[2];
|
||||||
|
min = Math.min(r, Math.min(g, b));
|
||||||
|
max = Math.max(r, Math.max(g, b));
|
||||||
|
delta = max - min;
|
||||||
|
l = (min + max) / 2;
|
||||||
|
s = 0;
|
||||||
|
if (l > 0 && l < 1) {
|
||||||
|
s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
|
||||||
|
}
|
||||||
|
h = 0;
|
||||||
|
if (delta > 0) {
|
||||||
|
if (max == r && max != g) h += (g - b) / delta;
|
||||||
|
if (max == g && max != b) h += (2 + (b - r) / delta);
|
||||||
|
if (max == b && max != r) h += (4 + (r - g) / delta);
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
return [h, s, l];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install mousedown handler (the others are set on the document on-demand)
|
||||||
|
$('*', e).mousedown(fb.mousedown);
|
||||||
|
|
||||||
|
// Init color
|
||||||
|
fb.setColor('#000000');
|
||||||
|
|
||||||
|
// Set linked elements/callback
|
||||||
|
if (callback) {
|
||||||
|
fb.linkTo(callback);
|
||||||
|
}
|
||||||
|
}
|
81
static/mergely/editor/lib/farbtastic/index.html
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Papermashup.com | jQuery Color picker</title>
|
||||||
|
<link href="../style.css" rel="stylesheet" type="text/css" />
|
||||||
|
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="farbtastic.js"></script>
|
||||||
|
<link rel="stylesheet" href="farbtastic.css" type="text/css" />
|
||||||
|
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
$(document).ready(function() {
|
||||||
|
var f = $.farbtastic('#picker');
|
||||||
|
var p = $('#picker').css('opacity', 0.25);
|
||||||
|
var selected;
|
||||||
|
$('.colorwell')
|
||||||
|
.each(function () { f.linkTo(this); $(this).css('opacity', 0.75); })
|
||||||
|
.focus(function() {
|
||||||
|
if (selected) {
|
||||||
|
$(selected).css('opacity', 0.75).removeClass('colorwell-selected');
|
||||||
|
}
|
||||||
|
f.linkTo(this);
|
||||||
|
p.css('opacity', 1);
|
||||||
|
$(selected = this).css('opacity', 1).addClass('colorwell-selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
font-family:Verdana, Geneva, sans-serif;
|
||||||
|
font-size:14px;
|
||||||
|
margin:0px;
|
||||||
|
padding:0px;}
|
||||||
|
|
||||||
|
.colorwell{
|
||||||
|
padding:5px;
|
||||||
|
font-size:18px;
|
||||||
|
color:#333;
|
||||||
|
font-family:Verdana, Geneva, sans-serif;
|
||||||
|
border:1px #CCC solid;}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="header"><a href="http://www.papermashup.com/"><img src="../images/logo.png" width="348" height="63" border="0" /></a></div>
|
||||||
|
<div id="container">
|
||||||
|
|
||||||
|
|
||||||
|
<h1>jQuery 'Farbtastic' Color Picker</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="" style="width: 500px;">
|
||||||
|
<div id="picker" style="float: right;"></div>
|
||||||
|
<div class="form-item"><label for="color1">Color 1:</label><input type="text" id="color1" name="color1" class="colorwell" value="#edfa00" /></div>
|
||||||
|
<div class="form-item"><label for="color2">Color 2:</label><input type="text" id="color2" name="color2" class="colorwell" value="#ff9505" /></div>
|
||||||
|
<div class="form-item"><label for="color3">Color 3:</label><input type="text" id="color3" name="color3" class="colorwell" value="#f86c2a" /></div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clear"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="footer"><a href="http://www.papermashup.com">papermashup.com</a> | <a href="http://papermashup.com/jquery-farbtastic-colour-picker/">Back to tutorial</a></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
try {
|
||||||
|
var pageTracker = _gat._getTracker("UA-7025232-1");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
} catch(err) {}</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
static/mergely/editor/lib/farbtastic/marker.png
Normal file
After Width: | Height: | Size: 652 B |
BIN
static/mergely/editor/lib/farbtastic/mask.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
static/mergely/editor/lib/farbtastic/wheel.png
Normal file
After Width: | Height: | Size: 12 KiB |
61
static/mergely/editor/lib/gatag.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// This javascript tags file downloads and external links in Google Analytics.
|
||||||
|
// You need to be using the Google Analytics New Tracking Code (ga.js)
|
||||||
|
// for this script to work.
|
||||||
|
// To use, place this file on all pages just above the Google Analytics tracking code.
|
||||||
|
// All outbound links and links to non-html files should now be automatically tracked.
|
||||||
|
//
|
||||||
|
// This script has been provided by Goodwebpractices.com
|
||||||
|
// Thanks to ShoreTel, MerryMan and Colm McBarron
|
||||||
|
//
|
||||||
|
// www.goodwebpractices.com
|
||||||
|
// VKI has made changes as indicated below.
|
||||||
|
|
||||||
|
if (document.getElementsByTagName) {
|
||||||
|
// Initialize external link handlers
|
||||||
|
var hrefs = document.getElementsByTagName("a");
|
||||||
|
for (var l = 0; l < hrefs.length; l++) {
|
||||||
|
// try {} catch{} block added by erikvold VKI
|
||||||
|
try{
|
||||||
|
//protocol, host, hostname, port, pathname, search, hash
|
||||||
|
if (hrefs[l].protocol == "mailto:") {
|
||||||
|
startListening(hrefs[l],"click",trackMailto);
|
||||||
|
} else if (hrefs[l].hostname == location.host) {
|
||||||
|
var path = hrefs[l].pathname + hrefs[l].search;
|
||||||
|
var isDoc = path.match(/\.(?:doc|eps|jpg|png|svg|xls|ppt|pdf|xls|zip|txt|vsd|vxd|js|css|rar|exe|wma|mov|avi|wmv|mp3)($|\&|\?)/);
|
||||||
|
if (isDoc) {
|
||||||
|
startListening(hrefs[l],"click",trackExternalLinks);
|
||||||
|
}
|
||||||
|
} else if (!hrefs[l].href.match(/^javascript:/)) {
|
||||||
|
startListening(hrefs[l],"click",trackExternalLinks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startListening (obj,evnt,func) {
|
||||||
|
if (obj.addEventListener) {
|
||||||
|
obj.addEventListener(evnt,func,false);
|
||||||
|
} else if (obj.attachEvent) {
|
||||||
|
obj.attachEvent("on" + evnt,func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackMailto (evnt) {
|
||||||
|
var href = (evnt.srcElement) ? evnt.srcElement.href : this.href;
|
||||||
|
var mailto = "/mailto/" + href.substring(7);
|
||||||
|
if (typeof(pageTracker) == "object") pageTracker._trackPageview(mailto);
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackExternalLinks (evnt) {
|
||||||
|
var e = (evnt.srcElement) ? evnt.srcElement : this;
|
||||||
|
while (e.tagName != "A") {
|
||||||
|
e = e.parentNode;
|
||||||
|
}
|
||||||
|
var lnk = (e.pathname.charAt(0) == "/") ? e.pathname : "/" + e.pathname;
|
||||||
|
if (e.search && e.pathname.indexOf(e.search) == -1) lnk += e.search;
|
||||||
|
if (e.hostname != location.host) lnk = "/external/" + e.hostname + lnk;
|
||||||
|
if (typeof(pageTracker) == "object") pageTracker._trackPageview(lnk);
|
||||||
|
}
|
258
static/mergely/editor/lib/tipsy/jquery.tipsy.js
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
// tipsy, facebook style tooltips for jquery
|
||||||
|
// version 1.0.0a
|
||||||
|
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
||||||
|
// released under the MIT license
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
function maybeCall(thing, ctx) {
|
||||||
|
return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isElementInDOM(ele) {
|
||||||
|
while (ele = ele.parentNode) {
|
||||||
|
if (ele == document) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Tipsy(element, options) {
|
||||||
|
this.$element = $(element);
|
||||||
|
this.options = options;
|
||||||
|
this.enabled = true;
|
||||||
|
this.fixTitle();
|
||||||
|
};
|
||||||
|
|
||||||
|
Tipsy.prototype = {
|
||||||
|
show: function() {
|
||||||
|
var title = this.getTitle();
|
||||||
|
if (title && this.enabled) {
|
||||||
|
var $tip = this.tip();
|
||||||
|
|
||||||
|
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
|
||||||
|
$tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
|
||||||
|
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
|
||||||
|
|
||||||
|
var pos = $.extend({}, this.$element.offset(), {
|
||||||
|
width: this.$element[0].offsetWidth,
|
||||||
|
height: this.$element[0].offsetHeight
|
||||||
|
});
|
||||||
|
|
||||||
|
var actualWidth = $tip[0].offsetWidth,
|
||||||
|
actualHeight = $tip[0].offsetHeight,
|
||||||
|
gravity = maybeCall(this.options.gravity, this.$element[0]);
|
||||||
|
|
||||||
|
var tp;
|
||||||
|
switch (gravity.charAt(0)) {
|
||||||
|
case 'n':
|
||||||
|
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gravity.length == 2) {
|
||||||
|
if (gravity.charAt(1) == 'w') {
|
||||||
|
tp.left = pos.left + pos.width / 2 - 15;
|
||||||
|
} else {
|
||||||
|
tp.left = pos.left + pos.width / 2 - actualWidth + 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$tip.css(tp).addClass('tipsy-' + gravity);
|
||||||
|
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
|
||||||
|
if (this.options.className) {
|
||||||
|
$tip.addClass(maybeCall(this.options.className, this.$element[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.fade) {
|
||||||
|
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
|
||||||
|
} else {
|
||||||
|
$tip.css({visibility: 'visible', opacity: this.options.opacity});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function() {
|
||||||
|
if (this.options.fade) {
|
||||||
|
this.tip().stop().fadeOut(function() { $(this).remove(); });
|
||||||
|
} else {
|
||||||
|
this.tip().remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fixTitle: function() {
|
||||||
|
var $e = this.$element;
|
||||||
|
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
|
||||||
|
$e.attr('original-title', $e.attr('title') || '').removeAttr('title');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getTitle: function() {
|
||||||
|
var title, $e = this.$element, o = this.options;
|
||||||
|
this.fixTitle();
|
||||||
|
var title, o = this.options;
|
||||||
|
if (typeof o.title == 'string') {
|
||||||
|
title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
|
||||||
|
} else if (typeof o.title == 'function') {
|
||||||
|
title = o.title.call($e[0]);
|
||||||
|
}
|
||||||
|
title = ('' + title).replace(/(^\s*|\s*$)/, "");
|
||||||
|
return title || o.fallback;
|
||||||
|
},
|
||||||
|
|
||||||
|
tip: function() {
|
||||||
|
if (!this.$tip) {
|
||||||
|
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
|
||||||
|
this.$tip.data('tipsy-pointee', this.$element[0]);
|
||||||
|
}
|
||||||
|
return this.$tip;
|
||||||
|
},
|
||||||
|
|
||||||
|
validate: function() {
|
||||||
|
if (!this.$element[0].parentNode) {
|
||||||
|
this.hide();
|
||||||
|
this.$element = null;
|
||||||
|
this.options = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
enable: function() { this.enabled = true; },
|
||||||
|
disable: function() { this.enabled = false; },
|
||||||
|
toggleEnabled: function() { this.enabled = !this.enabled; }
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.tipsy = function(options) {
|
||||||
|
|
||||||
|
if (options === true) {
|
||||||
|
return this.data('tipsy');
|
||||||
|
} else if (typeof options == 'string') {
|
||||||
|
var tipsy = this.data('tipsy');
|
||||||
|
if (tipsy) tipsy[options]();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = $.extend({}, $.fn.tipsy.defaults, options);
|
||||||
|
|
||||||
|
function get(ele) {
|
||||||
|
var tipsy = $.data(ele, 'tipsy');
|
||||||
|
if (!tipsy) {
|
||||||
|
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
|
||||||
|
$.data(ele, 'tipsy', tipsy);
|
||||||
|
}
|
||||||
|
return tipsy;
|
||||||
|
}
|
||||||
|
|
||||||
|
function enter() {
|
||||||
|
var tipsy = get(this);
|
||||||
|
tipsy.hoverState = 'in';
|
||||||
|
if (options.delayIn == 0) {
|
||||||
|
tipsy.show();
|
||||||
|
} else {
|
||||||
|
tipsy.fixTitle();
|
||||||
|
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function leave() {
|
||||||
|
var tipsy = get(this);
|
||||||
|
tipsy.hoverState = 'out';
|
||||||
|
if (options.delayOut == 0) {
|
||||||
|
tipsy.hide();
|
||||||
|
} else {
|
||||||
|
setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options.live) this.each(function() { get(this); });
|
||||||
|
|
||||||
|
if (options.trigger != 'manual') {
|
||||||
|
var binder = options.live ? 'live' : 'bind',
|
||||||
|
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
|
||||||
|
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
|
||||||
|
this[binder](eventIn, enter)[binder](eventOut, leave);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.tipsy.defaults = {
|
||||||
|
className: null,
|
||||||
|
delayIn: 0,
|
||||||
|
delayOut: 0,
|
||||||
|
fade: false,
|
||||||
|
fallback: '',
|
||||||
|
gravity: 'n',
|
||||||
|
html: false,
|
||||||
|
live: false,
|
||||||
|
offset: 0,
|
||||||
|
opacity: 0.8,
|
||||||
|
title: 'title',
|
||||||
|
trigger: 'hover'
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.tipsy.revalidate = function() {
|
||||||
|
$('.tipsy').each(function() {
|
||||||
|
var pointee = $.data(this, 'tipsy-pointee');
|
||||||
|
if (!pointee || !isElementInDOM(pointee)) {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Overwrite this method to provide options on a per-element basis.
|
||||||
|
// For example, you could store the gravity in a 'tipsy-gravity' attribute:
|
||||||
|
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
|
||||||
|
// (remember - do not modify 'options' in place!)
|
||||||
|
$.fn.tipsy.elementOptions = function(ele, options) {
|
||||||
|
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.tipsy.autoNS = function() {
|
||||||
|
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.tipsy.autoWE = function() {
|
||||||
|
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* yields a closure of the supplied parameters, producing a function that takes
|
||||||
|
* no arguments and is suitable for use as an autogravity function like so:
|
||||||
|
*
|
||||||
|
* @param margin (int) - distance from the viewable region edge that an
|
||||||
|
* element should be before setting its tooltip's gravity to be away
|
||||||
|
* from that edge.
|
||||||
|
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
|
||||||
|
* if there are no viewable region edges effecting the tooltip's
|
||||||
|
* gravity. It will try to vary from this minimally, for example,
|
||||||
|
* if 'sw' is preferred and an element is near the right viewable
|
||||||
|
* region edge, but not the top edge, it will set the gravity for
|
||||||
|
* that element's tooltip to be 'se', preserving the southern
|
||||||
|
* component.
|
||||||
|
*/
|
||||||
|
$.fn.tipsy.autoBounds = function(margin, prefer) {
|
||||||
|
return function() {
|
||||||
|
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
|
||||||
|
boundTop = $(document).scrollTop() + margin,
|
||||||
|
boundLeft = $(document).scrollLeft() + margin,
|
||||||
|
$this = $(this);
|
||||||
|
|
||||||
|
if ($this.offset().top < boundTop) dir.ns = 'n';
|
||||||
|
if ($this.offset().left < boundLeft) dir.ew = 'w';
|
||||||
|
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
|
||||||
|
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
|
||||||
|
|
||||||
|
return dir.ns + (dir.ew ? dir.ew : '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery);
|
25
static/mergely/editor/lib/tipsy/tipsy.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }
|
||||||
|
.tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }
|
||||||
|
|
||||||
|
/* Rounded corners */
|
||||||
|
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
|
||||||
|
|
||||||
|
/* Uncomment for shadow */
|
||||||
|
/*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/
|
||||||
|
|
||||||
|
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
|
||||||
|
|
||||||
|
/* Rules to colour arrows */
|
||||||
|
.tipsy-arrow-n { border-bottom-color: #000; }
|
||||||
|
.tipsy-arrow-s { border-top-color: #000; }
|
||||||
|
.tipsy-arrow-e { border-left-color: #000; }
|
||||||
|
.tipsy-arrow-w { border-right-color: #000; }
|
||||||
|
|
||||||
|
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
|
||||||
|
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||||
|
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||||
|
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||||
|
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||||
|
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||||
|
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
|
||||||
|
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
|
152
static/mergely/editor/lib/wicked-ui.css
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 jamie.peabody@gmail.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* menu configurable options */
|
||||||
|
.wicked-menu { z-index: 7; } /* cm uses index <= 6 */
|
||||||
|
.wicked-menu { font-size: 13px; }
|
||||||
|
.wicked-menu, .wicked-menu ul, .wicked-menu li > a.menu-item {
|
||||||
|
color: #333; /* text color */
|
||||||
|
}
|
||||||
|
.wicked-menu li > a { color: #000; text-decoration:none;} /* regular link color */
|
||||||
|
.wicked-menu li > a:hover { text-decoration:underline; } /* regular link:hover */
|
||||||
|
.wicked-menu > li.hover > a.menu-item,
|
||||||
|
.wicked-menu, .wicked-menu ul {
|
||||||
|
background-color: #fff; /* background color */
|
||||||
|
}
|
||||||
|
.wicked-menu > li.hover,
|
||||||
|
.wicked-menu ul li:hover > ul,
|
||||||
|
.wicked-menu ul {
|
||||||
|
border: 1px solid #cbcbcb; /* menu border color */
|
||||||
|
}
|
||||||
|
.wicked-menu li:hover { background: #efefef; } /* hover menu background color */
|
||||||
|
.wicked-menu ul,
|
||||||
|
.wicked-menu > li.hover,
|
||||||
|
.wicked-menu ul li:hover > ul { /* drop shadow */
|
||||||
|
-webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
-moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
|
||||||
|
}
|
||||||
|
/* -- global settings -- */
|
||||||
|
.wicked-menu { margin: 0px; padding: 0px; }
|
||||||
|
.wicked-menu, .wicked-menu ul { margin: 0; padding: 0; }
|
||||||
|
.wicked-menu li { display: inline-block; list-style-type: none; cursor:pointer; }
|
||||||
|
.wicked-menu li > a.menu-item { text-decoration: none; }
|
||||||
|
.wicked-menu ul { display: none; }
|
||||||
|
.wicked-menu ul li { width: 100%; position: relative; }
|
||||||
|
.wicked-menu ul li > a.menu-item > span { padding-left: 10px; }
|
||||||
|
|
||||||
|
/* top menu */
|
||||||
|
.wicked-menu > li > a > *, .wicked-menu > li { display: inline-block; }
|
||||||
|
.wicked-menu li > ul > li > * { padding: 5px; display: inline-block; } /* padding other menu-item */
|
||||||
|
.wicked-menu > li > a.menu-item > * { padding: 7px 7px; }
|
||||||
|
.wicked-menu > li { position: relative; border: 1px solid transparent; }
|
||||||
|
.wicked-menu > li.hover > a.menu-item > * { padding: 7px 7px 3px 7px; }
|
||||||
|
.wicked-menu > li.hover > a.menu-item {
|
||||||
|
/* lose the top-level focus indicator on hover */
|
||||||
|
outline: none;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
z-index: 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* menu items */
|
||||||
|
.wicked-menu li.hover > ul,
|
||||||
|
.wicked-menu ul li:hover > ul { display: block; position: absolute; }
|
||||||
|
.wicked-menu ul li:hover > ul { margin-top: 5px; }
|
||||||
|
/* drop menu */
|
||||||
|
.wicked-menu ul { z-index: 7; min-width: 210px; top: 2.1em; left: -1px; }
|
||||||
|
|
||||||
|
.wicked-menu > li.hover {
|
||||||
|
/* for the top-level menu, after hovering do not show background */
|
||||||
|
background: transparent; position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wicked-menu ul > li > a.menu-item { line-height: 2.35em; display:inline-block; width:100%; padding: 0; }
|
||||||
|
|
||||||
|
/* menu layout for icons and hotkeys */
|
||||||
|
.wicked-menu span.hotkey { float: right; margin-right: 10px; }
|
||||||
|
.wicked-menu ul > li > a.menu-item > span.icon {
|
||||||
|
padding-left: 31px;
|
||||||
|
background-position: 7px center;
|
||||||
|
background-color: transparent;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wicked-menu ul li:hover > ul { min-width: 210px; top: 0px; left: 100%; }
|
||||||
|
|
||||||
|
.wicked-menu li.separator { border-top: 1px solid #e5e5e5; height: 3px; display: block; line-height: 3em; margin-top: 3px; }
|
||||||
|
.wicked-menu li.separator:hover { background: transparent; cursor:default; }
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* toolbar configurable options */
|
||||||
|
.wicked-toolbar {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
height: 30px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
border-right: 0;
|
||||||
|
border-left: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.wicked-toolbar li span {
|
||||||
|
width: 1px;
|
||||||
|
color: transparent;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.wicked-toolbar li {
|
||||||
|
height: 22px;
|
||||||
|
width: 28px;
|
||||||
|
margin: 3px;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
.wicked-toolbar li.separator {
|
||||||
|
border-right:1px solid #e5e5e5;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
.wicked-toolbar li.hover {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 2px;
|
||||||
|
box-shadow: rgba(0, 0, 0, .1) 0 1px 3px 0;
|
||||||
|
-webkit-transition: all 0.25s ease;
|
||||||
|
-moz-transition: all 0.25s ease;
|
||||||
|
-o-transition: all 0.25s ease;
|
||||||
|
transition: all 0.25s ease;
|
||||||
|
}
|
||||||
|
.wicked-toolbar .icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background-position: center center;
|
||||||
|
background-color: transparent;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.wicked-toolbar a {
|
||||||
|
display: block;
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
288
static/mergely/editor/lib/wicked-ui.js
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013 jamie.peabody@gmail.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
;(function( $, window, document, undefined ){
|
||||||
|
var pluginName = 'wickedtoolbar';
|
||||||
|
var SHIFT = new RegExp(/shift/i);
|
||||||
|
var ALT = new RegExp(/alt/i);
|
||||||
|
var CTRL = new RegExp(/ctrl/i);
|
||||||
|
var ARROW_DOWN = new RegExp(/↓/);
|
||||||
|
var ARROW_UP = new RegExp(/↑/);
|
||||||
|
var ARROW_LEFT = new RegExp(/←/);
|
||||||
|
var ARROW_RIGHT = new RegExp(/→/);
|
||||||
|
|
||||||
|
var keys = {
|
||||||
|
shift: 16,
|
||||||
|
alt: 17,
|
||||||
|
ctrl: 18,
|
||||||
|
meta: 91,
|
||||||
|
arrow_up: 38,
|
||||||
|
arrow_down: 40,
|
||||||
|
arrow_left: 37,
|
||||||
|
arrow_right: 39
|
||||||
|
};
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
hasIcon: function(id) { },
|
||||||
|
getIcon: function(id) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
function MenuBase(element, options) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.element = $(element);
|
||||||
|
this.settings = $.extend({}, defaults, options);
|
||||||
|
this.bindings = [];
|
||||||
|
// for each menu item, modify and wrap in div
|
||||||
|
this.element.find('li').each(function () {
|
||||||
|
var tthis = $(this);
|
||||||
|
|
||||||
|
// since the DOM is modifying wrt to icons, it can match the li[data-cion] from
|
||||||
|
// the HTML definition, or the span.icon from the modified DOM
|
||||||
|
var icons = tthis.closest('ul').find('li[data-icon], span.icon').length > 0;
|
||||||
|
|
||||||
|
var tnode = tthis.contents().filter(function() { return this.nodeType == 3; }).first();
|
||||||
|
var text = tnode.text().trim();
|
||||||
|
|
||||||
|
// remove the text node
|
||||||
|
tnode.remove();
|
||||||
|
|
||||||
|
if (!text || !text.length) return; // not a regular menu item
|
||||||
|
|
||||||
|
// change: <li>Text</li>
|
||||||
|
// to: <li>
|
||||||
|
// <a>
|
||||||
|
// <span>Text</span>
|
||||||
|
// </a>
|
||||||
|
// </li>
|
||||||
|
var li = tthis;
|
||||||
|
var div = $('<a class="menu-item" href="#">');
|
||||||
|
div.click(function(ev) {
|
||||||
|
$(this).focus();
|
||||||
|
// li.id > a
|
||||||
|
var id = $(this).parent().attr('id');
|
||||||
|
if (id) {
|
||||||
|
self.element.trigger('selected', [id]);
|
||||||
|
$(this).parents('.hover').removeClass('hover');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
var span;
|
||||||
|
if (self.settings._type == 'menu') {
|
||||||
|
span = $('<span>' + text + '</span>');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
span = $('<span></span>');
|
||||||
|
}
|
||||||
|
div.append(span);
|
||||||
|
|
||||||
|
if (self.settings._type == 'menu') {
|
||||||
|
// accesskey
|
||||||
|
var accesskey = tthis.attr('accesskey');
|
||||||
|
if (accesskey) {
|
||||||
|
div.attr('accesskey', accesskey);
|
||||||
|
tthis.removeAttr('accesskey');
|
||||||
|
}
|
||||||
|
|
||||||
|
// hotkey
|
||||||
|
var hotkey = tthis.attr('data-hotkey');
|
||||||
|
if (hotkey) {
|
||||||
|
tthis.removeAttr('data-hotkey');
|
||||||
|
div.append('<span class="hotkey">' + hotkey + '</span>');
|
||||||
|
|
||||||
|
if (!accesskey) {
|
||||||
|
// add our own handler
|
||||||
|
var parts = hotkey.split('+');
|
||||||
|
var bind = {};
|
||||||
|
for (var i = 0; i < parts.length; ++i) {
|
||||||
|
if (SHIFT.test(parts[i])) {
|
||||||
|
bind.shiftKey = true;
|
||||||
|
}
|
||||||
|
else if (ALT.test(parts[i])) {
|
||||||
|
bind.altKey = true;
|
||||||
|
}
|
||||||
|
else if (CTRL.test(parts[i])) {
|
||||||
|
bind.ctrlKey = true;
|
||||||
|
}
|
||||||
|
else if (ARROW_DOWN.test(parts[i])) {
|
||||||
|
bind.which = keys.arrow_down;
|
||||||
|
}
|
||||||
|
else if (ARROW_UP.test(parts[i])) {
|
||||||
|
bind.which = keys.arrow_up;
|
||||||
|
}
|
||||||
|
else if (ARROW_RIGHT.test(parts[i])) {
|
||||||
|
bind.which = keys.arrow_right;
|
||||||
|
}
|
||||||
|
else if (ARROW_LEFT.test(parts[i])) {
|
||||||
|
bind.which = keys.arrow_left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bind.target = div;
|
||||||
|
self.bindings.push(bind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// icon
|
||||||
|
var id = tthis.attr('id'), icon;
|
||||||
|
if (self.settings.hasIcon(id)) {
|
||||||
|
span.addClass('icon');
|
||||||
|
icon = self.settings.getIcon(id);
|
||||||
|
if (icon) {
|
||||||
|
span.addClass(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
icon = tthis.attr('data-icon');
|
||||||
|
if (icon) {
|
||||||
|
tthis.removeAttr('data-icon');
|
||||||
|
span.addClass('icon ' + icon);
|
||||||
|
}
|
||||||
|
else if (icons) {
|
||||||
|
span.addClass('icon');
|
||||||
|
}
|
||||||
|
li.prepend(div);
|
||||||
|
});
|
||||||
|
$(document).on('keydown', function(ev) {
|
||||||
|
for (var i = 0; i < self.bindings.length; ++i) {
|
||||||
|
var bind = self.bindings[i];
|
||||||
|
// handle custom key events
|
||||||
|
if ((bind.shiftKey === undefined ? true : (bind.shiftKey === ev.shiftKey)) &&
|
||||||
|
(bind.ctrlKey === undefined ? true : (bind.ctrlKey === ev.ctrlKey)) &&
|
||||||
|
(bind.altKey === undefined ? true : (bind.altKey === ev.altKey)) &&
|
||||||
|
bind.which && ev.which && (bind.which === ev.which)) {
|
||||||
|
bind.target.trigger('click');
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuBase.prototype.update = function (id) {
|
||||||
|
var li = this.element.find('#' + id), icon;
|
||||||
|
var span = li.find('span:first-child');
|
||||||
|
if (this.settings.hasIcon(id)) {
|
||||||
|
span.removeClass(); // this could be brutally unfair
|
||||||
|
span.addClass('icon');
|
||||||
|
icon = this.settings.getIcon(id);
|
||||||
|
if (icon) {
|
||||||
|
span.addClass(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// Menu
|
||||||
|
// ------------
|
||||||
|
function Menu(element, options) {
|
||||||
|
options._type = 'menu';
|
||||||
|
$.extend(this, new MenuBase(element, options)) ;
|
||||||
|
this.constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu.prototype.constructor = function () {
|
||||||
|
this.element.addClass('wicked-ui wicked-menu');
|
||||||
|
var self = this;
|
||||||
|
var dohover = function(ev) {
|
||||||
|
$(this).parent().addClass('hover');
|
||||||
|
if ($(this).closest('ul').hasClass('wicked-menu')) {
|
||||||
|
// if the closest ul is a 'menu' (i.e. if this item is a top-level menu), then
|
||||||
|
// aply focus
|
||||||
|
$(this).focus();
|
||||||
|
}
|
||||||
|
if (!self.accessing) {
|
||||||
|
// Set 'accessing' to true and one document click to cancel it
|
||||||
|
self.accessing = true;
|
||||||
|
$(document).one('click', function() {
|
||||||
|
if (!self.accessing) return;
|
||||||
|
self.accessing = false;
|
||||||
|
self.element.find('.hover').removeClass('hover');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.element.find('> li > a.menu-item').click(dohover);
|
||||||
|
|
||||||
|
this.element.find('> li > ul > li ul.drop-menu').each(function() {
|
||||||
|
// li > a + ul
|
||||||
|
$(this).prev('a.menu-item').addClass('icon-arrow-right');
|
||||||
|
|
||||||
|
$(this).prev('a.menu-item').hover(dohover);
|
||||||
|
$(this).prev('a.menu-item').mouseleave(
|
||||||
|
function() {
|
||||||
|
$(this).parent().removeClass('hover');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.element.find('> li > a.menu-item').hover(
|
||||||
|
function() {
|
||||||
|
if (!self.accessing) return;
|
||||||
|
self.element.find('.hover').removeClass('hover');
|
||||||
|
$.proxy(dohover, this)();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
// Toolbar
|
||||||
|
// ------------
|
||||||
|
function Toolbar(element, options) {
|
||||||
|
options._type = 'toolbar';
|
||||||
|
$.extend(this, new MenuBase(element, options)) ;
|
||||||
|
this.constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolbar.prototype.constructor = function () {
|
||||||
|
this.element.addClass('wicked-ui wicked-toolbar');
|
||||||
|
this.element.find('> li > a.menu-item').hover(
|
||||||
|
function(){ $(this).parent().addClass('hover'); },
|
||||||
|
function(){ $(this).parent().removeClass('hover'); }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var plugins = { wickedmenu: Menu, wickedtoolbar: Toolbar };
|
||||||
|
for (var key in plugins) {
|
||||||
|
(function(name, Plugin){
|
||||||
|
$.fn[name] = function (options) {
|
||||||
|
var args = arguments;
|
||||||
|
return this.each(function () {
|
||||||
|
if (typeof options === 'object' || !options) {
|
||||||
|
if (!$.data(this, 'plugin_' + name)) {
|
||||||
|
$.data(this, 'plugin_' + name, new Plugin( this, options ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var d = $.data(this, 'plugin_' + name);
|
||||||
|
if (!d) {
|
||||||
|
$.error('jQuery.' + name + ' plugin does not exist');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return d[options](Array.prototype.slice.call(args, 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})(key, plugins[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
})( jQuery, window, document );
|
334
static/mergely/lib/codemirror.css
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
/* BASICS */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
/* Set height, width, borders, and global font properties here */
|
||||||
|
font-family: monospace;
|
||||||
|
height: 300px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PADDING */
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: 4px 0; /* Vertical padding around content */
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
padding: 0 4px; /* Horizontal padding of content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
background-color: white; /* The little square between H and V scrollbars */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-linenumbers {}
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
padding: 0 3px 0 5px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: right;
|
||||||
|
color: #999;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-guttermarker { color: black; }
|
||||||
|
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||||
|
|
||||||
|
/* CURSOR */
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
/* Shown when moving in bi-directional text */
|
||||||
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
|
border-left: 1px solid silver;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0;
|
||||||
|
background: #7e7;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor div.CodeMirror-cursors {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-animate-fat-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0;
|
||||||
|
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||||
|
-moz-animation: blink 1.06s steps(1) infinite;
|
||||||
|
animation: blink 1.06s steps(1) infinite;
|
||||||
|
background-color: #7e7;
|
||||||
|
}
|
||||||
|
@-moz-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can style cursor different in overwrite (non-insert) mode */
|
||||||
|
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||||
|
|
||||||
|
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||||
|
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEFAULT THEME */
|
||||||
|
|
||||||
|
.cm-s-default .cm-header {color: blue;}
|
||||||
|
.cm-s-default .cm-quote {color: #090;}
|
||||||
|
.cm-negative {color: #d44;}
|
||||||
|
.cm-positive {color: #292;}
|
||||||
|
.cm-header, .cm-strong {font-weight: bold;}
|
||||||
|
.cm-em {font-style: italic;}
|
||||||
|
.cm-link {text-decoration: underline;}
|
||||||
|
.cm-strikethrough {text-decoration: line-through;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-keyword {color: #708;}
|
||||||
|
.cm-s-default .cm-atom {color: #219;}
|
||||||
|
.cm-s-default .cm-number {color: #164;}
|
||||||
|
.cm-s-default .cm-def {color: #00f;}
|
||||||
|
.cm-s-default .cm-variable,
|
||||||
|
.cm-s-default .cm-punctuation,
|
||||||
|
.cm-s-default .cm-property,
|
||||||
|
.cm-s-default .cm-operator {}
|
||||||
|
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||||
|
.cm-s-default .cm-variable-3 {color: #085;}
|
||||||
|
.cm-s-default .cm-comment {color: #a50;}
|
||||||
|
.cm-s-default .cm-string {color: #a11;}
|
||||||
|
.cm-s-default .cm-string-2 {color: #f50;}
|
||||||
|
.cm-s-default .cm-meta {color: #555;}
|
||||||
|
.cm-s-default .cm-qualifier {color: #555;}
|
||||||
|
.cm-s-default .cm-builtin {color: #30a;}
|
||||||
|
.cm-s-default .cm-bracket {color: #997;}
|
||||||
|
.cm-s-default .cm-tag {color: #170;}
|
||||||
|
.cm-s-default .cm-attribute {color: #00c;}
|
||||||
|
.cm-s-default .cm-hr {color: #999;}
|
||||||
|
.cm-s-default .cm-link {color: #00c;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-error {color: #f00;}
|
||||||
|
.cm-invalidchar {color: #f00;}
|
||||||
|
|
||||||
|
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||||
|
|
||||||
|
/* Default styles for common addons */
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||||
|
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||||
|
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||||
|
|
||||||
|
/* STOP */
|
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of
|
||||||
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
overflow: scroll !important; /* Things will break if this is overridden */
|
||||||
|
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||||
|
/* See overflow: hidden in .CodeMirror */
|
||||||
|
margin-bottom: -30px; margin-right: -30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
height: 100%;
|
||||||
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.CodeMirror-sizer {
|
||||||
|
position: relative;
|
||||||
|
border-right: 30px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
|
before actual scrolling happens, thus preventing shaking and
|
||||||
|
flickering artifacts. */
|
||||||
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-vscrollbar {
|
||||||
|
right: 0; top: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-hscrollbar {
|
||||||
|
bottom: 0; left: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-scrollbar-filler {
|
||||||
|
right: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
left: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
position: absolute; left: 0; top: 0;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
white-space: normal;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: -30px;
|
||||||
|
/* Hack to make IE7 behave */
|
||||||
|
*zoom:1;
|
||||||
|
*display:inline;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 4;
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-elt {
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
cursor: text;
|
||||||
|
min-height: 1px; /* prevents collapsing before first draw */
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
/* Reset some styles that the rest of the page might have set */
|
||||||
|
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap pre {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linebackground {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linewidget {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-widget {}
|
||||||
|
|
||||||
|
.CodeMirror-code {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */
|
||||||
|
.CodeMirror-scroll,
|
||||||
|
.CodeMirror-sizer,
|
||||||
|
.CodeMirror-gutter,
|
||||||
|
.CodeMirror-gutters,
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-measure {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-cursor { position: absolute; }
|
||||||
|
.CodeMirror-measure pre { position: static; }
|
||||||
|
|
||||||
|
div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
div.CodeMirror-dragcursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-focused div.CodeMirror-cursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-selected { background: #d9d9d9; }
|
||||||
|
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||||
|
.CodeMirror-crosshair { cursor: crosshair; }
|
||||||
|
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||||
|
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||||
|
|
||||||
|
.cm-searching {
|
||||||
|
background: #ffa;
|
||||||
|
background: rgba(255, 255, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||||
|
.CodeMirror span { *vertical-align: text-bottom; }
|
||||||
|
|
||||||
|
/* Used to force a border model for a node */
|
||||||
|
.cm-force-border { padding-right: .1px; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Hide the cursor when printing */
|
||||||
|
.CodeMirror div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See issue #2901 */
|
||||||
|
.cm-tab-wrap-hack:after { content: ''; }
|
||||||
|
|
||||||
|
/* Help users use markselection to safely style text background */
|
||||||
|
span.CodeMirror-selectedtext { background: none; }
|
8890
static/mergely/lib/codemirror.js
Normal file
5
static/mergely/lib/codemirror.min.js
vendored
Normal file
45
static/mergely/lib/mergely.css
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
/* required */
|
||||||
|
.mergely-column textarea { width: 80px; height: 200px; }
|
||||||
|
.mergely-column { float: left; }
|
||||||
|
.mergely-margin { float: left; }
|
||||||
|
.mergely-canvas { float: left; width: 28px; }
|
||||||
|
|
||||||
|
/* resizeable */
|
||||||
|
.mergely-resizer { width: 100%; height: 100%; }
|
||||||
|
|
||||||
|
/* style configuration */
|
||||||
|
.mergely-column { border: 1px solid #ccc; }
|
||||||
|
.mergely-active { border: 1px solid #a3d1ff; }
|
||||||
|
|
||||||
|
.mergely.a,.mergely.d,.mergely.c { color: #000; }
|
||||||
|
|
||||||
|
.mergely.a.rhs.start { border-top: 1px solid #a3d1ff; }
|
||||||
|
.mergely.a.lhs.start.end,
|
||||||
|
.mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; }
|
||||||
|
.mergely.a.rhs { background-color: #ddeeff; }
|
||||||
|
.mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; }
|
||||||
|
|
||||||
|
.mergely.d.lhs { background-color: #ffe9e9; }
|
||||||
|
.mergely.d.lhs.end,
|
||||||
|
.mergely.d.rhs.start.end { border-bottom: 1px solid #f8e8e8; }
|
||||||
|
.mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #f8e8e8; }
|
||||||
|
.mergely.d.lhs.start { border-top: 1px solid #f8e8e8; }
|
||||||
|
|
||||||
|
.mergely.c.lhs,
|
||||||
|
.mergely.c.rhs { background-color: #fafafa; }
|
||||||
|
.mergely.c.lhs.start,
|
||||||
|
.mergely.c.rhs.start { border-top: 1px solid #a3a3a3; }
|
||||||
|
.mergely.c.lhs.end,
|
||||||
|
.mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
|
||||||
|
|
||||||
|
.mergely.ch.a.rhs { background-color: #ddeeff; }
|
||||||
|
.mergely.ch.d.lhs { background-color: #ffe9e9; text-decoration: line-through; color: red !important; }
|
||||||
|
|
||||||
|
.mergely.current.start { border-top: 1px solid #000 !important; }
|
||||||
|
.mergely.current.end { border-bottom: 1px solid #000 !important; }
|
||||||
|
.mergely.current.lhs.a.start.end,
|
||||||
|
.mergely.current.rhs.d.start.end { border-top: 0 !important; }
|
||||||
|
.mergely.current.CodeMirror-linenumber { color: #F9F9F9; font-weight: bold; background-color: #777; }
|
||||||
|
.CodeMirror-linenumber { cursor: pointer; }
|
||||||
|
.CodeMirror-code { color: #717171; }
|
1685
static/mergely/lib/mergely.js
Normal file
7
static/mergely/lib/mergely.min.js
vendored
Normal file
131
static/mergely/lib/searchcursor.js
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
(function(){
|
||||||
|
var Pos = CodeMirror.Pos;
|
||||||
|
|
||||||
|
function SearchCursor(cm, query, pos, caseFold) {
|
||||||
|
this.atOccurrence = false; this.cm = cm;
|
||||||
|
if (caseFold == null && typeof query == "string") caseFold = false;
|
||||||
|
|
||||||
|
pos = pos ? cm.clipPos(pos) : Pos(0, 0);
|
||||||
|
this.pos = {from: pos, to: pos};
|
||||||
|
|
||||||
|
// The matches method is filled in based on the type of query.
|
||||||
|
// It takes a position and a direction, and returns an object
|
||||||
|
// describing the next occurrence of the query, or null if no
|
||||||
|
// more matches were found.
|
||||||
|
if (typeof query != "string") { // Regexp match
|
||||||
|
if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
|
||||||
|
this.matches = function(reverse, pos) {
|
||||||
|
if (reverse) {
|
||||||
|
query.lastIndex = 0;
|
||||||
|
var line = cm.getLine(pos.line).slice(0, pos.ch), match = query.exec(line), start = 0;
|
||||||
|
while (match) {
|
||||||
|
start += match.index + 1;
|
||||||
|
line = line.slice(start);
|
||||||
|
query.lastIndex = 0;
|
||||||
|
var newmatch = query.exec(line);
|
||||||
|
if (newmatch) match = newmatch;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
start--;
|
||||||
|
} else {
|
||||||
|
query.lastIndex = pos.ch;
|
||||||
|
var line = cm.getLine(pos.line), match = query.exec(line),
|
||||||
|
start = match && match.index;
|
||||||
|
}
|
||||||
|
if (match && match[0])
|
||||||
|
return {from: Pos(pos.line, start),
|
||||||
|
to: Pos(pos.line, start + match[0].length),
|
||||||
|
match: match};
|
||||||
|
};
|
||||||
|
} else { // String query
|
||||||
|
if (caseFold) query = query.toLowerCase();
|
||||||
|
var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
|
||||||
|
var target = query.split("\n");
|
||||||
|
// Different methods for single-line and multi-line queries
|
||||||
|
if (target.length == 1) {
|
||||||
|
if (!query.length) {
|
||||||
|
// Empty string would match anything and never progress, so
|
||||||
|
// we define it to match nothing instead.
|
||||||
|
this.matches = function() {};
|
||||||
|
} else {
|
||||||
|
this.matches = function(reverse, pos) {
|
||||||
|
var line = fold(cm.getLine(pos.line)), len = query.length, match;
|
||||||
|
if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
|
||||||
|
: (match = line.indexOf(query, pos.ch)) != -1)
|
||||||
|
return {from: Pos(pos.line, match),
|
||||||
|
to: Pos(pos.line, match + len)};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.matches = function(reverse, pos) {
|
||||||
|
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
|
||||||
|
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
|
||||||
|
if (reverse ? offsetA >= pos.ch || offsetA != match.length
|
||||||
|
: offsetA <= pos.ch || offsetA != line.length - match.length)
|
||||||
|
return;
|
||||||
|
for (;;) {
|
||||||
|
if (reverse ? !ln : ln == cm.lineCount() - 1) return;
|
||||||
|
line = fold(cm.getLine(ln += reverse ? -1 : 1));
|
||||||
|
match = target[reverse ? --idx : ++idx];
|
||||||
|
if (idx > 0 && idx < target.length - 1) {
|
||||||
|
if (line != match) return;
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
|
||||||
|
if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
|
||||||
|
return;
|
||||||
|
var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
|
||||||
|
return {from: reverse ? end : start, to: reverse ? start : end};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchCursor.prototype = {
|
||||||
|
findNext: function() {return this.find(false);},
|
||||||
|
findPrevious: function() {return this.find(true);},
|
||||||
|
|
||||||
|
find: function(reverse) {
|
||||||
|
var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
|
||||||
|
function savePosAndFail(line) {
|
||||||
|
var pos = Pos(line, 0);
|
||||||
|
self.pos = {from: pos, to: pos};
|
||||||
|
self.atOccurrence = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (this.pos = this.matches(reverse, pos)) {
|
||||||
|
if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
|
||||||
|
this.atOccurrence = true;
|
||||||
|
return this.pos.match || true;
|
||||||
|
}
|
||||||
|
if (reverse) {
|
||||||
|
if (!pos.line) return savePosAndFail(0);
|
||||||
|
pos = Pos(pos.line-1, this.cm.getLine(pos.line-1).length);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var maxLine = this.cm.lineCount();
|
||||||
|
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
|
||||||
|
pos = Pos(pos.line + 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
from: function() {if (this.atOccurrence) return this.pos.from;},
|
||||||
|
to: function() {if (this.atOccurrence) return this.pos.to;},
|
||||||
|
|
||||||
|
replace: function(newText) {
|
||||||
|
if (!this.atOccurrence) return;
|
||||||
|
var lines = CodeMirror.splitLines(newText);
|
||||||
|
this.cm.replaceRange(lines, this.pos.from, this.pos.to);
|
||||||
|
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
|
||||||
|
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
|
||||||
|
return new SearchCursor(this, query, pos, caseFold);
|
||||||
|
});
|
||||||
|
})();
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AbsolutePath(p string) (string,error) {
|
func AbsolutePath(p string) (string,error) {
|
||||||
@@ -50,3 +51,58 @@ func CopyFile(dstName, srcName string) (written int64, err error) {
|
|||||||
return io.Copy(dst, src)
|
return io.Copy(dst, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FormatBytes(size int64) string {
|
||||||
|
units := []string{" B", " KB", " MB", " GB", " TB"}
|
||||||
|
|
||||||
|
s := float64(size)
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
for ; s >= 1024 && i < 4 ; i ++ {
|
||||||
|
s /= 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return fmt.Sprintf("%.2f%s",s,units[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func Round(val float64, places int) float64 {
|
||||||
|
var t float64
|
||||||
|
f := math.Pow10(places)
|
||||||
|
x := val * f
|
||||||
|
if math.IsInf(x, 0) || math.IsNaN(x) {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
if x >= 0.0 {
|
||||||
|
t = math.Ceil(x)
|
||||||
|
if (t - x) > 0.50000000001 {
|
||||||
|
t -= 1.0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t = math.Ceil(-x)
|
||||||
|
if (t + x) > 0.50000000001 {
|
||||||
|
t -= 1.0
|
||||||
|
}
|
||||||
|
t = -t
|
||||||
|
}
|
||||||
|
x = t / f
|
||||||
|
|
||||||
|
if !math.IsInf(x, 0) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
44
views/document/compare.tpl
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>文档比较 - Powered by MinDoc</title>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="description" content="Merge and Diff your documents with diff online and share" />
|
||||||
|
<meta name="keywords" content="diff,merge,compare,jsdiff,comparison,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
|
||||||
|
<meta name="author" content="Jamie Peabody" />
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
|
||||||
|
<script type="text/javascript" src="/static/jquery/1.12.4/jquery.min.js"></script>
|
||||||
|
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/lib/wicked-ui.css' />
|
||||||
|
<script type="text/javascript" src="/static/mergely/editor/lib/wicked-ui.js"></script>
|
||||||
|
|
||||||
|
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/lib/tipsy/tipsy.css' />
|
||||||
|
<script type="text/javascript" src="/static/mergely/editor/lib/tipsy/jquery.tipsy.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/mergely/editor/lib/farbtastic/farbtastic.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/mergely/editor/lib/farbtastic/farbtastic.css" />
|
||||||
|
<script type="text/javascript" src="/static/mergely/lib/codemirror.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/mergely/lib/mergely.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/mergely/editor/editor.min.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/mergely/lib/codemirror.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/mergely/lib/mergely.css" />
|
||||||
|
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/editor.css' />
|
||||||
|
<script type="text/javascript" src="/static/mergely/lib/searchcursor.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var key = '';
|
||||||
|
var isSample = key == 'usaindep';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body style="visibility:hidden">
|
||||||
|
|
||||||
|
<!-- editor -->
|
||||||
|
<div style="position: absolute;top: 0px;bottom: 10px;left: 5px;right: 5px;overflow-y: hidden;padding-bottom: 2px;">
|
||||||
|
<div id="mergely"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -189,7 +189,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a :href="item.http_path" target="_blank" :title="item.file_name">${item.file_name}</a>
|
<a :href="item.http_path" target="_blank" :title="item.file_name">${item.file_name}</a>
|
||||||
<span class="text">(${(item.file_size/1024/1024).toFixed(4)}MB)</span>
|
<span class="text">(${ formatBytes(item.file_size) })</span>
|
||||||
<span class="error-message">${item.message}</span>
|
<span class="error-message">${item.message}</span>
|
||||||
<button type="button" class="btn btn-sm close" @click="removeAttach(item.attachment_id)">
|
<button type="button" class="btn btn-sm close" @click="removeAttach(item.attachment_id)">
|
||||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||||
|
105
views/manager/attach_detailed.tpl
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<title>附件管理 - Powered by MinDoc</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap -->
|
||||||
|
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<link href="/static/css/main.css" rel="stylesheet">
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js" }}"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="manual-reader">
|
||||||
|
{{template "widgets/header.tpl" .}}
|
||||||
|
<div class="container manual-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="page-left">
|
||||||
|
<ul class="menu">
|
||||||
|
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="page-right">
|
||||||
|
<div class="m-box">
|
||||||
|
<div class="box-head">
|
||||||
|
<strong class="box-title">附件管理</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文件名称</label>
|
||||||
|
<input type="text" value="{{.Model.FileName}}" class="form-control input-readonly" readonly placeholder="文件名称">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>是否存在</label>
|
||||||
|
{{if .Model.IsExist }}
|
||||||
|
<input type="text" value="存在" class="form-control input-readonly" readonly placeholder="项目名称">
|
||||||
|
{{else}}
|
||||||
|
<input type="text" value="已删除" class="form-control input-readonly" readonly placeholder="项目名称">
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>项目名称</label>
|
||||||
|
<input type="text" value="{{.Model.BookName}}" class="form-control input-readonly" readonly placeholder="项目名称">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文档名称</label>
|
||||||
|
<input type="text" value="{{.Model.DocumentName}}" class="form-control input-readonly" readonly placeholder="文档名称">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文件路径</label>
|
||||||
|
<input type="text" value="{{.Model.FilePath}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>下载路径</label>
|
||||||
|
<input type="text" value="{{.Model.HttpPath}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>文件大小</label>
|
||||||
|
<input type="text" value="{{.Model.FileShortSize}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>上传时间</label>
|
||||||
|
<input type="text" value="{{date .Model.CreateTime "Y-m-d H:i:s"}}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户账号</label>
|
||||||
|
<input type="text" value="{{ .Model.Account }}" class="form-control input-readonly" readonly placeholder="文件路径">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<a href="{{urlfor "ManagerController.AttachList" }}" class="btn btn-success btn-sm">返回</a>
|
||||||
|
{{if .Model.IsExist }}
|
||||||
|
<a href="{{.Model.LocalHttpPath}}" class="btn btn-default btn-sm" target="_blank" title="下载到本地">下载</a>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{template "widgets/footer.tpl" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/vuejs/vue.min.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="/static/js/main.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
119
views/manager/attach_list.tpl
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<title>附件管理 - Powered by MinDoc</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap -->
|
||||||
|
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<link href="{{cdncss "/static/css/main.css"}}" rel="stylesheet">
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js" }}"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="manual-reader">
|
||||||
|
{{template "widgets/header.tpl" .}}
|
||||||
|
<div class="container manual-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="page-left">
|
||||||
|
<ul class="menu">
|
||||||
|
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="page-right">
|
||||||
|
<div class="m-box">
|
||||||
|
<div class="box-head">
|
||||||
|
<strong class="box-title">附件管理</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="attach-list" id="attachList">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>附件名称</th>
|
||||||
|
<th>项目名称</th>
|
||||||
|
<th>文件大小</th>
|
||||||
|
<th>是否存在</th>
|
||||||
|
<th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range $index,$item := .Lists}}
|
||||||
|
<tr>
|
||||||
|
<td>{{$item.AttachmentId}}</td>
|
||||||
|
<td>{{$item.FileName}}</td>
|
||||||
|
<td>{{$item.BookName}}</td>
|
||||||
|
<td>{{$item.FileShortSize}}</td>
|
||||||
|
<td>{{ if $item.IsExist }} 是{{else}}否{{end}}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" data-method="delete" class="btn btn-danger btn-sm" data-id="{{$item.AttachmentId}}" data-loading-text="删除中...">删除</button>
|
||||||
|
<a href="{{urlfor "ManagerController.AttachDetailed" ":id" $item.AttachmentId}}" class="btn btn-success btn-sm">详情</a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{else}}
|
||||||
|
<tr><td>暂无数据</td></tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<nav>
|
||||||
|
{{.PageHtml}}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{template "widgets/footer.tpl" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
|
||||||
|
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
|
||||||
|
<script src="{{cdnjs "/static/layer/layer.js" }}" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
$("#attachList").on("click","button[data-method='delete']",function () {
|
||||||
|
var id = $(this).attr("data-id");
|
||||||
|
var $this = $(this);
|
||||||
|
$(this).button("loading");
|
||||||
|
$.ajax({
|
||||||
|
url : "{{urlfor "ManagerController.AttachDelete"}}",
|
||||||
|
data : { "attach_id" : id },
|
||||||
|
type : "post",
|
||||||
|
dataType : "json",
|
||||||
|
success : function (res) {
|
||||||
|
if(res.errcode === 0){
|
||||||
|
$this.closest("tr").remove().empty();
|
||||||
|
}else {
|
||||||
|
layer.msg(res.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error : function () {
|
||||||
|
layer.msg("服务器异常");
|
||||||
|
},
|
||||||
|
complete : function () {
|
||||||
|
$this.button("reset");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@@ -5,7 +5,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<title>文档管理 - Powered by MinDoc</title>
|
<title>项目管理 - Powered by MinDoc</title>
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
@@ -88,11 +88,9 @@
|
|||||||
<div class="text-center">暂无数据</div>
|
<div class="text-center">暂无数据</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<template v-if="lists.length >= 0">
|
<nav>
|
||||||
<nav>
|
{{.PageHtml}}
|
||||||
{{.PageHtml}}
|
</nav>
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li class="active"><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
@@ -63,11 +65,11 @@
|
|||||||
<span class="fa-class">{{.Model.CommentNumber}}</span>
|
<span class="fa-class">{{.Model.CommentNumber}}</span>
|
||||||
</div>
|
</div>
|
||||||
*/}}-->
|
*/}}-->
|
||||||
<div class="dashboard-item">
|
<a href="{{urlfor "ManagerController.AttachList" }}" class="dashboard-item">
|
||||||
<span class="fa fa-cloud-download" aria-hidden="true"></span>
|
<span class="fa fa-cloud-download" aria-hidden="true"></span>
|
||||||
<span class="fa-class">附件数量</span>
|
<span class="fa-class">附件数量</span>
|
||||||
<span class="fa-class">{{.Model.AttachmentNumber}}</span>
|
<span class="fa-class">{{.Model.AttachmentNumber}}</span>
|
||||||
</div>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li class="active"><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li class="active"><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-right">
|
<div class="page-right">
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
|
||||||
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> 评论管理</a> </li>*/}}
|
||||||
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
|
||||||
|
<li><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<header class="navbar navbar-static-top navbar-fixed-top manual-header" role="banner">
|
<header class="navbar navbar-static-top navbar-fixed-top manual-header" role="banner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header col-sm-12 col-md-6 col-lg-5">
|
<div class="navbar-header col-sm-12 col-md-7 col-lg-6">
|
||||||
<a href="/" class="navbar-brand">
|
<a href="/" class="navbar-brand" title="{{.SITE_NAME}}">
|
||||||
{{if .SITE_TITLE}}
|
{{if .SITE_TITLE}}
|
||||||
{{.SITE_TITLE}}
|
{{.SITE_TITLE}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|