增加文本比较功能
|
@ -40,6 +40,12 @@ const (
|
|||
BookObserver = 3
|
||||
)
|
||||
|
||||
const (
|
||||
LoggerOperate = "operate"
|
||||
LoggerSystem = "system"
|
||||
LoggerException = "exception"
|
||||
LoggerDocument = "document"
|
||||
)
|
||||
const (
|
||||
//本地账户校验
|
||||
AuthMethodLocal = "local"
|
||||
|
|
|
@ -458,7 +458,7 @@ func (c *DocumentController) Upload() {
|
|||
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)
|
||||
if strings.HasPrefix(attachment.HttpPath, "//") {
|
||||
|
@ -1078,6 +1078,11 @@ func (c *DocumentController) RestoreHistory() {
|
|||
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) {
|
||||
for _, item := range docs {
|
||||
|
|
|
@ -12,6 +12,9 @@ import (
|
|||
"github.com/lifei6671/godoc/conf"
|
||||
"github.com/lifei6671/godoc/models"
|
||||
"github.com/lifei6671/godoc/utils"
|
||||
"path/filepath"
|
||||
"github.com/lifei6671/godoc/commands"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ManagerController struct {
|
||||
|
@ -511,3 +514,105 @@ func (c *ManagerController) PrivatelyOwned() {
|
|||
}
|
||||
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/orm"
|
||||
"github.com/lifei6671/godoc/conf"
|
||||
"github.com/lifei6671/godoc/utils"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
"time"
|
||||
"github.com/lifei6671/godoc/conf"
|
||||
"sync/atomic"
|
||||
"github.com/astaxie/beego/orm"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
Logger_Operate = "operate"
|
||||
Logger_System = "system"
|
||||
Logger_Exception = "exception"
|
||||
)
|
||||
var loggerQueue = &logQueue{ channel : make(chan *Logger,100),isRuning : 0 }
|
||||
|
||||
type logQueue struct {
|
||||
channel chan *Logger
|
||||
isRuning int32
|
||||
}
|
||||
|
||||
// Logger struct .
|
||||
type Logger struct {
|
||||
LoggerId int64 `orm:"pk;auto;unique;column(log_id)" json:"log_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"`
|
||||
Content string `orm:"column(content);type(text)" json:"content"`
|
||||
OriginalData string `orm:"column(original_data);type(text)" json:"original_data"`
|
||||
|
@ -41,7 +45,34 @@ func NewLogger() *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/books/transfer", &controllers.ManagerController{},"post:Transfer")
|
||||
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/password", &controllers.SettingController{},"*:Password")
|
||||
|
@ -59,6 +63,7 @@ func init() {
|
|||
beego.Router("/api/:key/create",&controllers.DocumentController{},"post:Create")
|
||||
beego.Router("/api/:key/delete", &controllers.DocumentController{},"post:Delete")
|
||||
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/delete", &controllers.DocumentController{},"*:DeleteHistory")
|
||||
|
|
|
@ -48,6 +48,9 @@ h6 {
|
|||
font-size: .8em;
|
||||
font-weight: 200
|
||||
}
|
||||
table>tbody>tr:hover{
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
.m-manual:not(.manual-mobile) ::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
width: 7px;
|
||||
|
|
|
@ -25,6 +25,12 @@ textarea{
|
|||
color: green;
|
||||
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{
|
||||
height: 9px;
|
||||
|
@ -51,7 +57,10 @@ textarea{
|
|||
}
|
||||
.manual-header .navbar-brand,.manual-header a {
|
||||
font-weight: 500;
|
||||
color: #563d7c
|
||||
color: #563d7c;
|
||||
max-width: 300px;
|
||||
white-space:nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.manual-reader .slidebar {
|
||||
margin: 5px 10px 0 0;
|
||||
|
|
|
@ -72,7 +72,8 @@ function getSiblingSort (node) {
|
|||
};
|
||||
}
|
||||
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 () {
|
||||
window.vueApp = new Vue({
|
||||
|
|
|
@ -37,4 +37,12 @@ Date.prototype.format = function(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);
|
||||
}
|
||||
}
|
||||
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 = '![](' + $res.url + ')';
|
||||
window.editor.insertValue(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onchange : function () {
|
||||
resetEditorChanged(true);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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('&') : '';
|
||||
}
|
||||
});
|
|
@ -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>
|
After Width: | Height: | Size: 274 B |
After Width: | Height: | Size: 243 B |
After Width: | Height: | Size: 319 B |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 236 B |
After Width: | Height: | Size: 218 B |
After Width: | Height: | Size: 288 B |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 230 B |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 266 B |
After Width: | Height: | Size: 252 B |
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 234 B |
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
After Width: | Height: | Size: 652 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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; }
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
|
@ -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; }
|
|
@ -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; }
|
|
@ -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"
|
||||
"path/filepath"
|
||||
"io"
|
||||
"math"
|
||||
)
|
||||
|
||||
func AbsolutePath(p string) (string,error) {
|
||||
|
@ -50,3 +51,58 @@ func CopyFile(dstName, srcName string) (written int64, err error) {
|
|||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 v-else>
|
||||
<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>
|
||||
<button type="button" class="btn btn-sm close" @click="removeAttach(item.attachment_id)">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
|
|
|
@ -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>
|
|
@ -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 name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>文档管理 - Powered by MinDoc</title>
|
||||
<title>项目管理 - Powered by MinDoc</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<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><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.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
|
@ -88,11 +88,9 @@
|
|||
<div class="text-center">暂无数据</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<template v-if="lists.length >= 0">
|
||||
<nav>
|
||||
{{.PageHtml}}
|
||||
</nav>
|
||||
</template>
|
||||
<nav>
|
||||
{{.PageHtml}}
|
||||
</nav>
|
||||
</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><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.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<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.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.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||
</ul>
|
||||
</div>
|
||||
<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.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.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="page-right">
|
||||
|
@ -63,11 +65,11 @@
|
|||
<span class="fa-class">{{.Model.CommentNumber}}</span>
|
||||
</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-class">附件数量</span>
|
||||
<span class="fa-class">{{.Model.AttachmentNumber}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</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.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><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">
|
||||
|
|
|
@ -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.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.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<header class="navbar navbar-static-top navbar-fixed-top manual-header" role="banner">
|
||||
<div class="container">
|
||||
<div class="navbar-header col-sm-12 col-md-6 col-lg-5">
|
||||
<a href="/" class="navbar-brand">
|
||||
<div class="navbar-header col-sm-12 col-md-7 col-lg-6">
|
||||
<a href="/" class="navbar-brand" title="{{.SITE_NAME}}">
|
||||
{{if .SITE_TITLE}}
|
||||
{{.SITE_TITLE}}
|
||||
{{else}}
|
||||
|
|