增加文本比较功能

pull/77/head
Minho 2017-06-09 18:14:55 +08:00
parent 33ad75a088
commit fc9a237259
63 changed files with 14512 additions and 23 deletions

View File

@ -40,6 +40,12 @@ const (
BookObserver = 3
)
const (
LoggerOperate = "operate"
LoggerSystem = "system"
LoggerException = "exception"
LoggerDocument = "document"
)
const (
//本地账户校验
AuthMethodLocal = "local"

View File

@ -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 {

View File

@ -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")
}

View File

@ -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
}

View File

@ -0,0 +1,61 @@
package models
import (
"github.com/astaxie/beego/orm"
"github.com/lifei6671/godoc/utils"
"strings"
)
type AttachmentResult struct {
Attachment
IsExist bool
BookName string
DocumentName string
FileShortSize string
Account string
LocalHttpPath string
}
func NewAttachmentResult() *AttachmentResult {
return &AttachmentResult{ IsExist : false }
}
func (m *AttachmentResult) Find(id int) (*AttachmentResult,error) {
o := orm.NewOrm()
attach := NewAttachment()
err := o.QueryTable(m.TableNameWithPrefix()).Filter("attachment_id",id).One(attach)
if err != nil {
return m,err
}
m.Attachment = *attach
book := NewBook()
if e := o.QueryTable(book.TableNameWithPrefix()).Filter("book_id", attach.BookId).One(book, "book_name"); e == nil {
m.BookName = book.BookName
} else {
m.BookName = "[不存在]"
}
doc := NewDocument()
if e := o.QueryTable(doc.TableNameWithPrefix()).Filter("document_id", attach.DocumentId).One(doc, "document_name"); e == nil {
m.DocumentName = doc.DocumentName
} else {
m.DocumentName = "[不存在]"
}
if attach.CreateAt > 0 {
member := NewMember()
if e := o.QueryTable(member.TableNameWithPrefix()).Filter("member_id",attach.CreateAt).One(member,"account");e == nil {
m.Account = member.Account
}
}
m.FileShortSize = utils.FormatBytes(int64(attach.FileSize))
m.LocalHttpPath = strings.Replace(m.FilePath,"\\","/",-1)
return m,nil
}

View File

@ -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)
}
}

View File

@ -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")

View File

@ -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;

View File

@ -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;

View File

@ -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({

View File

@ -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];
}

View File

@ -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);

View File

@ -0,0 +1,85 @@
body { margin: 0; }
#banner { background: transparent url(images/banner.png); width: 33px; height: 30px; position: absolute; left: 3px; top: 3px; }
.wicked-menu { font-family: 'Noto Sans', sans-serif; margin: 2px 0 2px 40px; }
.wicked-menu a.link { margin-left: 10px; }
.ui-widget { font-size:13px; }
/* color dialog */
#dialog-colors { }
#dialog-colors label { width: 85px; display: inline-block; font-weight: bold; padding: 5px; }
#dialog-colors input[type=text] { width: 70px; border: 1px solid #444; float:right; }
#dialog-colors fieldset { -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; border: 1px solid #ccc; width: 222px; padding-right: 15px; }
/* import dialog */
#dialog-upload label { font-weight: bold; display: inline-block; width: 80px; line-height: 1.5em; }
.no-title .ui-dialog-titlebar { display:none; }
.no-title .ui-dialog-content { padding: 0; }
#file-lhs-progress,
#file-rhs-progress { height: 22px; width: 240px; vertical-align: middle; line-height: 1.5em; display: none; }
.progress-label { float: left; width: 100%; color: #fff; font-weight: bold; font-size: .8em; padding-left: 10px; }
/* icons */
.icon-undo { background-image: url(images/undo.png); }
.icon-redo { background-image: url(images/redo.png); }
.icon-save { background-image: url(images/download.png); }
.icon-check { background-image: url(images/check.png); }
.icon-import { background-image: url(images/upload.png); }
.icon-swap { background-image: url(images/swap.png); }
.icon-arrow-right { background-image: url(images/arrow-right.png); }
.icon-arrow-right-v { background-image: url(images/arrow-right-v.png); }
.icon-arrow-right-vv { background-image: url(images/arrow-right-vv.png); }
.icon-arrow-left-v { background-image: url(images/arrow-left-v.png); }
.icon-arrow-left-vv { background-image: url(images/arrow-left-vv.png); }
.icon-arrow-up { background-image: url(images/arrow-up-v.png); }
.icon-arrow-down { background-image: url(images/arrow-down-v.png); }
.icon-x-mark { background-image: url(images/x-mark.png); }
.icon-share { background-image: url(images/share.png); }
.tipsy-inner {
padding: 8px;
text-align: center;
max-width: 250px;
font-family: arial, sans-serif;
font-weight: bold;
font-size: 1.2em;
}
.find {
position: absolute;
top: 0px;
right: 0px;
z-index: 4;
padding: 10px 20px 10px 10px;
background-color: #f5f5f5;
float: right;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-bottom-left-radius: 10px;
max-height: 26px;
-webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
-moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
display: none;
}
.find > button {
padding: 3px 0px;
border: 1px solid #ccc;
border-radius: 3px;
height: 25px;
width: 26px;
vertical-align: top;
cursor: pointer;
}
.find > button:hover {
background-color: #f5f5f5;
border: 1px solid #aaa;
}
.find > button > span.icon {
width: 16px;
height: 16px;
display: inline-block;
text-align: center;
background-position: center center;
}

View File

@ -0,0 +1,703 @@
$(document).ready(function() {
function getParameters() {
var parameters = {};
window.location.search.substr(1).split('&').forEach(function(pair) {
if (pair === '') return;
var parts = pair.split('=');
if (parts.length === 2 && parts[1].search(/^(true|1)$/i) >= 0) {
parameters[parts[0]] = true;
}
else if (parts.length === 2 && parts[1].search(/^(false|0)$/i) >= 0) {
parameters[parts[0]] = false;
}
else parameters[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
});
return {
get: function(name, defaultValue) {
if (parameters.hasOwnProperty(name)) return parameters[name];
return defaultValue;
}
};
}
var parameters = getParameters();
if (parameters.get('test', false)) {
var li = $('<li>Tests</li>');
var ul = $('<ul>');
for (var i = 1; i <= 8; ++i) {
ul.append($('<li id="examples-test' + i + '">Test ' + i + '</li>'));
}
li.append(ul);
$('#main-menu').append(li);
}
function handleFind(column) {
if (!column.length) {
return false;
}
var ed = $('#mergely');
var find = column.find('.find');
var input = find.find('input[type="text"]');
var side = column.attr('id').indexOf('-lhs') > 0 ? 'lhs' : 'rhs';
var origautoupdate = ed.mergely('options').autoupdate;
find.slideDown('fast', function() {
input.focus();
// disable autoupdate, clear both sides of diff
ed.mergely('options', {autoupdate: false});
ed.mergely('unmarkup');
});
find.find('.find-prev').click(function() {
ed.mergely('search', side, input.val(), 'prev');
});
find.find('.find-next').click(function() {
ed.mergely('search', side, input.val(), 'next');
});
find.find('.find-close').click(function() {
find.css('display', 'none')
ed.mergely('options', {autoupdate: origautoupdate});
});
input.keydown(function(evt) {
if (evt.which != 13 && evt.which != 27) return true;
if (evt.which == 27) {
find.css('display', 'none');
ed.mergely('options', {autoupdate: origautoupdate});
}
ed.mergely('search', side, input.val());
return false;
});
}
$(document).keydown(function(event) {
if (!( String.fromCharCode(event.which).toLowerCase() == 'f' && event.ctrlKey)) return true;
event.preventDefault();
var range = window.getSelection().getRangeAt(0);
var column = $(range.commonAncestorContainer).parents('.mergely-column');
handleFind(column);
return false;
});
String.prototype.random = function(length) {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var randomstring = ''
for (var i=0; i<length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
return randomstring;
}
// body is pre-hidden for better rendering
$('body').css("visibility", "");
var ed = $('#mergely');
var menu = $('#main-menu');
var toolbar = $('#toolbar');
ed.mergely({
width: 'auto',
height: 'auto',
cmsettings: {
lineNumbers: true,
readOnly: isSample
}
});
if (parameters.get('lhs', null)) {
var url = parameters.get('lhs');
crossdomainGET(ed, 'lhs', url);
}
if (parameters.get('rhs', null)) {
var url = parameters.get('rhs');
crossdomainGET(ed, 'rhs', url);
}
// set query string options
var urloptions = {};
var optmap = {
au: 'autoupdate',
ws: 'ignorews',
cs: 'ignorecase',
sb: 'sidebar',
vp: 'viewport',
wl: 'wrap_lines',
ln: 'line_numbers'
};
var doopt = false;
for (var name in optmap) {
if (!optmap.hasOwnProperty(name)) continue;
if (parameters.get(name, null) !== null) {
urloptions[optmap[name]] = parameters.get(name);
doopt = true;
}
}
if (parameters.get('rm', null) !== null) {
// special-case url property
urloptions.rhs_margin = parameters.get('rm') ? 'left' : 'right';
}
if (doopt) {
// apply query-string options
ed.mergely('options', urloptions);
}
// set query string colors
// cb: change border
// cg: change background
// ab: added border
// ag: added background
// db: deleted border
// dg: deleted background
var color_defaults = {
cb: 'cccccc', cg: 'fafafa',
ab: 'a3d1ff', ag: 'ddeeff',
db: 'ff7f7f', dg: 'ffe9e9'
};
applyParameterCss(false);
//history.pushState({}, null, '');
window.addEventListener('popstate', function(ev) {
if (ev.state) {
parameters = getParameters();
applyParameterCss(false);
}
});
// Load
if (key.length == 8) {
$.when(
$.ajax({
type: 'GET', async: true, dataType: 'text',
data: { 'key':key, 'name': 'lhs' },
url: '/ajax/handle_get.php',
success: function (response) {
ed.mergely('lhs', response);
},
error: function(xhr, ajaxOptions, thrownError){
}
}),
$.ajax({
type: 'GET', async: true, dataType: 'text',
data: { 'key':key, 'name': 'rhs' },
url: '/ajax/handle_get.php',
success: function (response) {
ed.mergely('rhs', response);
},
error: function(xhr, ajaxOptions, thrownError){
}
})
).done(function() {
var anchor = window.location.hash.substring(1);
if (anchor) {
// if an anchor has been provided, then parse the anchor in the
// form of: 'lhs' or 'rhs', followed by a line, e.g: lhs100.
var m = anchor.match(/([lr]hs)([0-9]+)/);
if (m && m.length == 3) {
console.log(m);
ed.mergely('scrollTo', m[1], parseInt(m[2],10));
}
}
});
}
// find
var find = $('.find');
var flhs = find.clone().attr('id', 'mergely-editor-lhs-find');
var frhs = find.clone().attr('id', 'mergely-editor-rhs-find');
$('#mergely-editor-lhs').append(flhs);
$('#mergely-editor-rhs').append(frhs);
find.remove();
var iconconf = {
'options-autodiff': {
get: function() { return ed.mergely('options').autoupdate },
set: function(value) {
var au = !ed.mergely('options').autoupdate;
ed.mergely('options', {autoupdate: au});
var params = updateQueryStringParam('au', au ? 1 : 0, 1);
updateHistory(params);
}
},
'options-ignorews': {
get: function() { return ed.mergely('options').ignorews },
set: function(value) {
var ws = !ed.mergely('options').ignorews;
ed.mergely('options', {ignorews: ws});
var params = updateQueryStringParam('ws', ws ? 1 : 0, 0);
updateHistory(params);
}
},
'options-ignorecase': {
get: function() { return ed.mergely('options').ignorecase },
set: function(value) {
var cs = !ed.mergely('options').ignorecase;
ed.mergely('options', {ignorecase: cs});
var params = updateQueryStringParam('cs', cs ? 1 : 0, 0);
updateHistory(params);
}
},
'options-sidebars': {
get: function() { console.log('sidebar', this); return ed.mergely('options').sidebar },
set: function(value) {
var sb = !ed.mergely('options').sidebar;
ed.mergely('options', {sidebar: sb});
var params = updateQueryStringParam('sb', sb ? 1 : 0, 1);
updateHistory(params);
}
},
'options-viewport': {
get: function() { console.log('viewport', this); return ed.mergely('options').viewport },
set: function(value) {
var vp = !ed.mergely('options').viewport;
ed.mergely('options', {viewport: vp});
var params = updateQueryStringParam('vp', vp ? 1 : 0, 0);
updateHistory(params);
}
},
'options-swapmargin': {
get: function() { return (ed.mergely('options').rhs_margin == 'left'); },
set: function(value) {
var rm = ed.mergely('options').rhs_margin == 'left' ? 'right' : 'left';
ed.mergely('options', {rhs_margin: rm });
var params = updateQueryStringParam('rm', rm == 'left' ? 1 : 0, 0);
updateHistory(params);
}
},
'options-linenumbers': {
get: function() { console.log('wrap', this); return ed.mergely('options').line_numbers },
set: function(value) {
var ln = !ed.mergely('options').line_numbers;
ed.mergely('options', {line_numbers: ln});
var params = updateQueryStringParam('ln', ln ? 1 : 0, 1);
updateHistory(params);
}
},
'options-wrap': {
get: function() { console.log('wrap', this); return ed.mergely('options').wrap_lines },
set: function(value) {
var wl = !ed.mergely('options').wrap_lines;
ed.mergely('options', {wrap_lines: wl});
var params = updateQueryStringParam('wl', wl ? 1 : 0, 0);
updateHistory(params);
}
},
'edit-left-readonly': {
get: function() { return ed.mergely('cm', 'lhs').getOption('readOnly'); },
set: function(value) { ed.mergely('cm', 'lhs').setOption('readOnly', value); }
},
'edit-right-readonly': {
get: function() { return ed.mergely('cm', 'rhs').getOption('readOnly'); },
set: function(value) { ed.mergely('cm', 'rhs').setOption('readOnly', value); }
}
}
var menu_opts = {
hasIcon: function(id) {
return iconconf.hasOwnProperty(id);
},
getIcon: function(id) {
if (iconconf[id].get()) return 'icon-check';
}
};
function handle_operation(id) {
if (id == 'file-new') {
window.location = '/editor';
}
else if (id == 'file-save') {
// download directly from browser
var text = ed.mergely('diff');
if (navigator.userAgent.toLowerCase().indexOf('msie') === -1) {
if (key == '') key = ''.random(8);
var link = jQuery('<a />', {
href: 'data:application/stream;base64,' + window.btoa(unescape(encodeURIComponent(text))),
target: '_blank',
text: 'clickme',
id: key
});
link.attr('download', key + '.diff');
jQuery('body').append(link);
var a = $('a#' + key);
a[0].click();
a.remove();
}
else {
var blob = new Blob([text]);
window.navigator.msSaveOrOpenBlob(blob, key + '.diff');
}
}
else if (id == 'file-share') {
handleShare(ed);
}
else if (id == 'file-import') {
importFiles(ed);
}
else if (id == 'edit-left-undo') {
ed.mergely('cm', 'lhs').getDoc().undo();
}
else if (id == 'edit-left-redo') {
ed.mergely('cm', 'lhs').getDoc().redo();
}
else if (id == 'edit-right-undo') {
ed.mergely('cm', 'rhs').getDoc().undo();
}
else if (id == 'edit-right-redo') {
ed.mergely('cm', 'rhs').getDoc().redo();
}
else if (id == 'edit-left-find') {
handleFind(ed.find('#mergely-editor-lhs'));
}
else if (id == 'edit-left-merge-right') {
ed.mergely('mergeCurrentChange', 'rhs');
}
else if (id == 'edit-left-merge-right-file') {
ed.mergely('merge', 'rhs');
}
else if ([
'edit-left-readonly',
'edit-right-readonly',
'options-autodiff',
'options-sidebars',
'options-swapmargin',
'options-viewport',
'options-ignorews',
'options-ignorecase',
'options-wrap',
'options-linenumbers',
].indexOf(id) >= 0) {
iconconf[id].set(!iconconf[id].get());
menu.wickedmenu('update', id);
}
else if (id == 'edit-left-clear') {
ed.mergely('clear', 'lhs');
}
else if (id == 'edit-right-find') {
handleFind(ed.find('#mergely-editor-rhs'));
}
else if (id == 'edit-right-merge-left') {
ed.mergely('mergeCurrentChange', 'lhs');
}
else if (id == 'edit-right-merge-left-file') {
ed.mergely('merge', 'lhs');
}
else if (id == 'edit-right-clear') {
ed.mergely('clear', 'rhs');
}
else if (id == 'options-colors') {
colorSettings(ed);
}
else if (id == 'view-swap') {
ed.mergely('swap');
}
else if (id == 'view-refresh') {
ed.mergely('update');
}
else if (id == 'view-change-next') {
ed.mergely('scrollToDiff', 'next');
}
else if (id == 'view-change-prev') {
ed.mergely('scrollToDiff', 'prev');
}
else if (id == 'view-clear') {
ed.mergely('unmarkup');
}
else if (id.indexOf('examples-') == 0) {
var test_config = {
test1: {lhs: 'one\ntwo\nthree', rhs: 'two\nthree'},
test2: {lhs: 'two\nthree', rhs: 'one\ntwo\nthree'},
test3: {lhs: 'one\nthree', rhs: 'one\ntwo\nthree'},
test4: {lhs: 'one\ntwo\nthree', rhs: 'one\nthree'},
test5: {lhs: 'to bee, or not to be', rhs: 'to be, or not to bee'},
test6: {lhs: 'to be, or not to be z', rhs: 'to be, to be'},
test7: {lhs: 'remained, & to assume', rhs: 'and to assume'},
test8: {lhs: 'to be, or not to be', rhs: 'to be, or not to be'}
};
var test = id.split('examples-')[1];
ed.mergely('lhs', test_config[test]['lhs']);
ed.mergely('rhs', test_config[test]['rhs']);
}
return false;
}
menu.wickedmenu(menu_opts).bind('selected', function(ev, id) {
return handle_operation(id);
});
toolbar.wickedtoolbar({}).bind('selected', function(ev, id) {
if (!id) return false;
return handle_operation(id.replace(/^tb-/, ''));
});
toolbar.find('li[title]').tipsy({opacity: 1});
menu.find('li[title]').tipsy({opacity: 1, delayIn: 1000, gravity: 'w'});
function handleShare(ed) {
var fork = $(this).attr('id') == 'fork';
if (key == '') key = ''.random(8);
var count = 0;
function post_save(side, text) {
$.ajax({
type: 'POST', async: true, dataType: 'text',
url: '/ajax/handle_file.php',
data: { 'key': key, 'name': side, 'content': text },
success: function (nkey) {
++count;
if (count == 2) {
var url = '/ajax/handle_save.php?key=' + key;
if (fork) url += '&nkey=' + ''.random(8);
$.ajax({
type: 'GET', async: false, dataType: 'text',
url: url,
success: function (nkey) {
// redirect
if (nkey.length) window.location.href = '/' + $.trim(nkey) + '/';
},
error: function(xhr, ajaxOptions, thrownError){
}
});
}
},
error: function(xhr, ajaxOptions, thrownError){
alert(thrownError);
}
});
}
function save_files() {
var lhs = ed.mergely('get', 'lhs');
var rhs = ed.mergely('get', 'rhs');
post_save('lhs', lhs);
post_save('rhs', rhs);
}
$( '#dialog-confirm' ).dialog({
resizable: false, width: 350, modal: true,
buttons: {
'Save for Sharing': function() {
$( this ).dialog( 'close' );
save_files();
},
Cancel: function() {
$( this ).dialog( 'close' );
}
}
});
}
function crossdomainGET(ed, side, url) {
$.ajax({
type: 'GET', dataType: 'text',
data: {url: url},
url: '/ajax/handle_crossdomain.php',
contentType: 'text/plain',
success: function (response) {
ed.mergely(side, response);
},
error: function(xhr, ajaxOptions, thrownError){
console.error('error', xhr, ajaxOptions, thrownError);
}
});
}
function importFiles(ed) {
// -------------
// file uploader - html5 file upload to browser
function file_load(target, side) {
var file = target.files[0];
var reader = new FileReader();
var $target = $(target);
function trigger(name, event) { $target.trigger(name, event); }
reader.onloadstart = function(evt) { trigger('start'); }
reader.onprogress = function(evt) { trigger('progress', evt); }
reader.onload = function(evt) { trigger('loaded', evt.target.result); }
reader.onerror = function (evt) {
alert(evt.target.error.name);
}
try {
reader.readAsText(file, 'UTF-8');
}
catch (e) {
console.error(e);
alert(e);
}
}
var file_data = {};
$('#file-lhs, #file-rhs').change(function (evt) {
var re = new RegExp('.*[\\\\/](.*)$');
var match = re.exec($(this).val());
var fname = match ? match[1] : 'unknown';
var progressbar = $('#' + evt.target.id + '-progress');
file_load(evt.target);
$(evt.target).bind('start', function(ev){
$(evt.target).css('display', 'none');
progressbar.css('display', 'inline-block');
});
$(evt.target).bind('progress', function(ev, progress){
var loaded = (progress.loaded / progress.total) * 100;
progressbar.find('> .progress-label').text(loaded + '%');
progressbar.progressbar('value', loaded);
});
$(evt.target).bind('loaded', function(ev, file){
progressbar.progressbar('value', 100);
progressbar.find('> .progress-label').text(fname);
file_data[evt.target.id] = file;
});
});
$('#file-lhs-progress').progressbar({value: 0});
$('#file-rhs-progress').progressbar({value: 0});
$('#dialog-upload .tabs').tabs();
function callbackName(data) {
console.log('callbackName', data);
}
$('#dialog-upload').dialog({
dialogClass: 'no-title',
resizable: false,
width: '450px',
modal: true,
buttons: {
Import: function() {
$(this).dialog('close');
var urls = { lhs: $('#url-lhs').val(), rhs: $('#url-rhs').val() };
for (var side in urls) {
var url = urls[side];
if (!url) continue;
crossdomainGET(ed, side, url);
}
if (file_data.hasOwnProperty('file-lhs')) {
ed.mergely('lhs', file_data['file-lhs']);
}
if (file_data.hasOwnProperty('file-rhs')) {
ed.mergely('rhs', file_data['file-rhs']);
}
},
Cancel: function() {
$(this).dialog('close');
}
}
});
}
function colorSettings(ed) {
// get current settings
var sd = $('<span style="display:none" class="mergely ch d lhs start end">C</span>');
var sa = $('<span style="display:none" class="mergely bg a rhs start end">C</span>');
var sc = $('<span style="display:none" class="mergely c rhs start end">C</span>');
$('body').append(sd);
$('body').append(sa);
$('body').append(sc);
var conf = {
'c-border': {id: '#c-border', getColor: function() { return sc.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
'c-bg': {id: '#c-bg', getColor: function() { return sc.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
'a-border': {id: '#a-border', getColor: function() { return sa.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
'a-bg': {id: '#a-bg', getColor: function() { return sa.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
'd-border': {id: '#d-border', getColor: function() { return sd.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
'd-bg': {id: '#d-bg', getColor: function() { return sd.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }}
};
$.each(conf, function(key, item){$(item.id).val(item.getColor()); });
var f = $.farbtastic('#picker');
$('.colorwell').each(function(){ f.linkTo(this); }).focus(function(){
var tthis = $(this);
f.linkTo(this);
var item = conf[tthis.attr('id')];
f.setColor(item.getColor());
});
$('#dialog-colors').dialog({
width: 490, modal: true,
buttons: {
Apply: function() {
var cborder = $('#c-border').val();
var aborder = $('#a-border').val();
var dborder = $('#d-border').val();
var abg = $('#a-bg').val();
var dbg = $('#d-bg').val();
var cbg = $('#c-bg').val();
var textCss = makeColorCss(cborder, cbg, aborder, abg, dborder, dbg);
applyColorCss(textCss, cborder, cbg, aborder, abg, dborder, dbg, true);
},
Reset: function() {
},
Close: function() {
$(this).dialog('close');
}
}
});
}
function makeColorCss(changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground) {
var text =
'.mergely.a.rhs.start{border-top-color:' + addedBorder + ';}\n\
.mergely.a.lhs.start.end,\n\
.mergely.a.rhs.end{border-bottom-color:' + addedBorder + ';}\n\
.mergely.a.rhs{background-color:' + addedBackground + ';}\n\
.mergely.d.lhs{background-color:' + deletedBackground + ';}\n\
.mergely.d.lhs.end,\n\
.mergely.d.rhs.start.end{border-bottom-color:' + deletedBorder + ';}\n\
.mergely.d.rhs.start.end.first{border-top-color:' + deletedBorder + ';}\n\
.mergely.d.lhs.start{border-top-color:' + deletedBorder + ';}\n\
.mergely.c.lhs,\n\
.mergely.c.rhs{background-color:' + changeBackground + ';}\n\
.mergely.c.lhs.start,\n\
.mergely.c.rhs.start{border-top-color:' + changeBorder + ';}\n\
.mergely.c.lhs.end,\n\
.mergely.c.rhs.end{border-bottom-color:' + changeBorder + ';}\n\
.mergely.ch.a.rhs{background-color:' + addedBackground + ';}\n\
.mergely.ch.d.lhs{background-color:' + deletedBackground + ';color: #888;}';
return text;
}
function applyParameterCss(saveState) {
var cb = '#' + parameters.get('cb',color_defaults.cb),
cg = '#' + parameters.get('cg',color_defaults.cg),
ab = '#' + parameters.get('ab',color_defaults.ab),
ag = '#' + parameters.get('ag',color_defaults.ag),
db = '#' + parameters.get('db',color_defaults.db),
dg = '#' + parameters.get('dg',color_defaults.dg);
applyColorCss(makeColorCss(cb, cg, ab, ag, db, dg), cb, cg, ab, ag, db, dg, saveState);
}
function applyColorCss(cssText, changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground, saveState) {
$('<style type="text/css">' + cssText + '</style>').appendTo('head');
ed.mergely('options', {
fgcolor:{a:addedBorder,c:changeBorder,d:deletedBorder}
});
var params = updateQueryStringParam('cb', changeBorder.replace(/#/g, ''), color_defaults.cb);
params = updateQueryStringParam('cg', changeBackground.replace(/#/g, ''), color_defaults.cg, params);
params = updateQueryStringParam('ab', addedBorder.replace(/#/g, ''), color_defaults.ab, params);
params = updateQueryStringParam('ag', addedBackground.replace(/#/g, ''), color_defaults.ag, params);
params = updateQueryStringParam('db', deletedBorder.replace(/#/g, ''), color_defaults.db, params);
params = updateQueryStringParam('dg', deletedBackground.replace(/#/g, ''), color_defaults.dg, params);
if (saveState) {
updateHistory(params);
}
}
function updateHistory(params) {
var baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
window.history.pushState({}, null, baseUrl + params);
}
// Explicitly save/update a url parameter using HTML5's replaceState().
function updateQueryStringParam(key, value, defaultValue, urlQueryString) {
urlQueryString = urlQueryString || document.location.search;
var parts = urlQueryString.replace(/^\?/, '').split(/&/), found = false;
for (var i in parts) {
if (parts[i].startsWith(key + '=')) {
found = true;
if (value === defaultValue) {
// value is default value, remove option
parts.splice(i, 1);
}
else {
// make new value
parts[i] = key + '=' + value;
}
break;
}
else if (parts[i].length === 0) {
parts.splice(i, 1);
break;
}
}
if (!found) {
parts.push(key + '=' + value);
}
return (parts.length) ? '?' + parts.join('&') : '';
}
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,290 @@
<?php
$key = '';
$debug = False;
if (isset($_GET['key'])) {
$key = $_GET['key'];
}
if (isset($_GET['debug'])) {
$debug = filter_var($_GET['debug'], FILTER_VALIDATE_BOOLEAN);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" /><title>Mergely - Diff online, merge documents</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="description" content="Merge and Diff your documents with diff online and share" />
<meta name="keywords" content="diff,merge,compare,jsdiff,comparison,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
<meta name="author" content="Jamie Peabody" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="canonical" href="http://www.mergely.com" />
<link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js"></script>
<link type="text/css" rel="stylesheet" href="/style/mergely-theme/jquery-ui-1.10.1.custom.css" />
<link type='text/css' rel='stylesheet' href='/Mergely/editor/lib/wicked-ui.css' />
<script type="text/javascript" src="/Mergely/editor/lib/wicked-ui.js"></script>
<link type='text/css' rel='stylesheet' href='/Mergely/editor/lib/tipsy/tipsy.css' />
<script type="text/javascript" src="/Mergely/editor/lib/tipsy/jquery.tipsy.js"></script>
<script type="text/javascript" src="/Mergely/editor/lib/farbtastic/farbtastic.js"></script>
<link type="text/css" rel="stylesheet" href="/Mergely/editor/lib/farbtastic/farbtastic.css" />
<?php
if ($debug) {
?>
<script type="text/javascript" src="/Mergely/lib/codemirror.js"></script>
<script type="text/javascript" src="/Mergely/lib/mergely.js"></script>
<script type="text/javascript" src="/Mergely/editor/editor.js"></script>
<?php
}
else {
?>
<script type="text/javascript" src="/Mergely/lib/codemirror.min.js"></script>
<script type="text/javascript" src="/Mergely/lib/mergely.min.js"></script>
<script type="text/javascript" src="/Mergely/editor/editor.min.js"></script>
<?php
}
?>
<link type="text/css" rel="stylesheet" href="/Mergely/lib/codemirror.css" />
<link type="text/css" rel="stylesheet" href="/Mergely/lib/mergely.css" />
<link type='text/css' rel='stylesheet' href='/Mergely/editor/editor.css' />
<script type="text/javascript" src="/Mergely/lib/searchcursor.js"></script>
<script type="text/javascript">
var key = '<?php echo htmlspecialchars($key, ENT_QUOTES, 'UTF-8'); ?>';
var isSample = key == 'usaindep';
</script>
<!-- analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-85576-5']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- google +1 -->
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
</head>
<body style="visibility:hidden">
<div id="fb-root"></div><script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<a href="/"><div id="banner"></div></a>
<!-- menu -->
<ul id="main-menu">
<li accesskey="f">
File
<ul>
<li id="file-new" accesskey="n" data-hotkey="Alt+N">New</li>
<li id="file-import" data-icon="icon-import">Import...</li>
<li id="file-save" accesskey="s" data-hotkey="Alt+S" data-icon="icon-save">Save .diff</li>
<li class="separator"></li>
<li id="file-share" data-icon="icon-share">Share</li>
</ul>
</li>
<li accesskey="l">
Left
<ul>
<li id="edit-left-undo" accesskey="z" data-hotkey="Ctrl+Z" data-icon="icon-undo">Undo</li>
<li id="edit-left-redo" accesskey="y" data-hotkey="Ctrl+Y" data-icon="icon-redo">Redo</li>
<li id="edit-left-find">Find</li>
<li class="separator"></li>
<li id="edit-left-merge-right" data-hotkey="Alt+&rarr;" 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+&larr;" 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+&uarr;" title="View previous change">View prev change</li>
<li id="view-change-next" data-hotkey="Alt+&darr;" 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

View File

@ -0,0 +1,341 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,51 @@
/**
* Farbtastic Color Picker 1.2
* © 2008 Steven Wittens
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
.farbtastic {
position: relative;
}
.farbtastic * {
position: absolute;
cursor: crosshair;
}
.farbtastic, .farbtastic .wheel {
width: 195px;
height: 195px;
}
.farbtastic .color, .farbtastic .overlay {
top: 47px;
left: 47px;
width: 101px;
height: 101px;
}
.farbtastic .wheel {
background: url(wheel.png) no-repeat;
width: 195px;
height: 195px;
}
.farbtastic .overlay {
background: url(mask.png) no-repeat;
}
.farbtastic .marker {
width: 17px;
height: 17px;
margin: -8px 0 0 -8px;
overflow: hidden;
background: url(marker.png) no-repeat;
}

View File

@ -0,0 +1,367 @@
/**
* Farbtastic Color Picker 1.2
* © 2008 Steven Wittens
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
jQuery.fn.farbtastic = function (callback) {
$.farbtastic(this, callback);
return this;
};
jQuery.farbtastic = function (container, callback) {
var container = $(container).get(0);
return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
}
jQuery._farbtastic = function (container, callback) {
// Store farbtastic object
var fb = this;
// Insert markup
$(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
var e = $('.farbtastic', container);
fb.wheel = $('.wheel', container).get(0);
// Dimensions
fb.radius = 84;
fb.square = 100;
fb.width = 194;
// Fix background PNGs in IE6
if (navigator.appVersion.match(/MSIE [0-6]\./)) {
$('*', e).each(function () {
if (this.currentStyle.backgroundImage != 'none') {
var image = this.currentStyle.backgroundImage;
image = this.currentStyle.backgroundImage.substring(5, image.length - 2);
$(this).css({
'backgroundImage': 'none',
'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
});
}
});
}
/**
* Link to the given element(s) or callback.
*/
fb.linkTo = function (callback) {
// Unbind previous nodes
if (typeof fb.callback == 'object') {
$(fb.callback).unbind('keyup', fb.updateValue);
}
// Reset color
fb.color = null;
// Bind callback or elements
if (typeof callback == 'function') {
fb.callback = callback;
}
else if (typeof callback == 'object' || typeof callback == 'string') {
fb.callback = $(callback);
fb.callback.bind('keyup', fb.updateValue);
if (fb.callback.get(0).value) {
fb.setColor(fb.callback.get(0).value);
}
}
return this;
}
fb.updateValue = function (event) {
if (this.value && this.value != fb.color) {
fb.setColor(this.value);
}
}
/**
* Change color with HTML syntax #123456
*/
fb.setColor = function (color) {
var unpack = fb.unpack(color);
// JAMIE WAS HERE rgb(r, g, b) modification
if (!unpack && color) {
color = fb.RGBToHex(color);
if (color) unpack = fb.unpack(color);
}
// JAMIE WAS HERE rgb(r, g, b) modification
if (fb.color != color && unpack) {
fb.color = color;
fb.rgb = unpack;
fb.hsl = fb.RGBToHSL(fb.rgb);
fb.updateDisplay();
}
return this;
}
/**
* Change color with HSL triplet [0..1, 0..1, 0..1]
*/
fb.setHSL = function (hsl) {
fb.hsl = hsl;
fb.rgb = fb.HSLToRGB(hsl);
fb.color = fb.pack(fb.rgb);
fb.updateDisplay();
return this;
}
/////////////////////////////////////////////////////
/**
* Retrieve the coordinates of the given event relative to the center
* of the widget.
*/
fb.widgetCoords = function (event) {
var x, y;
var el = event.target || event.srcElement;
var reference = fb.wheel;
if (typeof event.offsetX != 'undefined') {
// Use offset coordinates and find common offsetParent
var pos = { x: event.offsetX, y: event.offsetY };
// Send the coordinates upwards through the offsetParent chain.
var e = el;
while (e) {
e.mouseX = pos.x;
e.mouseY = pos.y;
pos.x += e.offsetLeft;
pos.y += e.offsetTop;
e = e.offsetParent;
}
// Look for the coordinates starting from the wheel widget.
var e = reference;
var offset = { x: 0, y: 0 }
while (e) {
if (typeof e.mouseX != 'undefined') {
x = e.mouseX - offset.x;
y = e.mouseY - offset.y;
break;
}
offset.x += e.offsetLeft;
offset.y += e.offsetTop;
e = e.offsetParent;
}
// Reset stored coordinates
e = el;
while (e) {
e.mouseX = undefined;
e.mouseY = undefined;
e = e.offsetParent;
}
}
else {
// Use absolute coordinates
var pos = fb.absolutePosition(reference);
x = (event.pageX || 0*(event.clientX + $('html').get(0).scrollLeft)) - pos.x;
y = (event.pageY || 0*(event.clientY + $('html').get(0).scrollTop)) - pos.y;
}
// Subtract distance to middle
return { x: x - fb.width / 2, y: y - fb.width / 2 };
}
/**
* Mousedown handler
*/
fb.mousedown = function (event) {
// Capture mouse
if (!document.dragging) {
$(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
document.dragging = true;
}
// Check which area is being dragged
var pos = fb.widgetCoords(event);
fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
// Process
fb.mousemove(event);
return false;
}
/**
* Mousemove handler
*/
fb.mousemove = function (event) {
// Get coordinates relative to color picker center
var pos = fb.widgetCoords(event);
// Set new HSL parameters
if (fb.circleDrag) {
var hue = Math.atan2(pos.x, -pos.y) / 6.28;
if (hue < 0) hue += 1;
fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
}
else {
var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
fb.setHSL([fb.hsl[0], sat, lum]);
}
return false;
}
/**
* Mouseup handler
*/
fb.mouseup = function () {
// Uncapture mouse
$(document).unbind('mousemove', fb.mousemove);
$(document).unbind('mouseup', fb.mouseup);
document.dragging = false;
}
/**
* Update the markers and styles
*/
fb.updateDisplay = function () {
// Markers
var angle = fb.hsl[0] * 6.28;
$('.h-marker', e).css({
left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
});
$('.sl-marker', e).css({
left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
});
// Saturation/Luminance gradient
$('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
// Linked elements or callback
if (typeof fb.callback == 'object') {
// Set background/foreground color
$(fb.callback).css({
backgroundColor: fb.color,
color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
});
// Change linked value
$(fb.callback).each(function() {
if (this.value && this.value != fb.color) {
this.value = fb.color;
}
});
}
else if (typeof fb.callback == 'function') {
fb.callback.call(fb, fb.color);
}
}
/**
* Get absolute position of element
*/
fb.absolutePosition = function (el) {
var r = { x: el.offsetLeft, y: el.offsetTop };
// Resolve relative to offsetParent
if (el.offsetParent) {
var tmp = fb.absolutePosition(el.offsetParent);
r.x += tmp.x;
r.y += tmp.y;
}
return r;
};
/* Various color utility functions */
fb.pack = function (rgb) {
var r = Math.round(rgb[0] * 255);
var g = Math.round(rgb[1] * 255);
var b = Math.round(rgb[2] * 255);
return '#' + (r < 16 ? '0' : '') + r.toString(16) +
(g < 16 ? '0' : '') + g.toString(16) +
(b < 16 ? '0' : '') + b.toString(16);
}
fb.unpack = function (color) {
if (color.length == 7) {
return [parseInt('0x' + color.substring(1, 3)) / 255,
parseInt('0x' + color.substring(3, 5)) / 255,
parseInt('0x' + color.substring(5, 7)) / 255];
}
else if (color.length == 4) {
return [parseInt('0x' + color.substring(1, 2)) / 15,
parseInt('0x' + color.substring(2, 3)) / 15,
parseInt('0x' + color.substring(3, 4)) / 15];
}
}
fb.HSLToRGB = function (hsl) {
var m1, m2, r, g, b;
var h = hsl[0], s = hsl[1], l = hsl[2];
m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
m1 = l * 2 - m2;
return [this.hueToRGB(m1, m2, h+0.33333),
this.hueToRGB(m1, m2, h),
this.hueToRGB(m1, m2, h-0.33333)];
}
fb.hueToRGB = function (m1, m2, h) {
h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
return m1;
}
// JAMIE WAS HERE
fb.RGBToHex = function(color) {
var exp = new RegExp(/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3}\s*)\)/i);
if(exp.test(color)) {
var results = exp.exec(color);
var r = parseInt(results[1]).toString(16);
var g = parseInt(results[2]).toString(16);
var b = parseInt(results[3]).toString(16);
if (r.length < 2) r = '0' + r;
if (g.length < 2) g = '0' + g;
if (b.length < 2) b = '0' + b;
return '#' + r + g + b;
}
}
// JAMIE WAS HERE
fb.RGBToHSL = function (rgb) {
var min, max, delta, h, s, l;
var r = rgb[0], g = rgb[1], b = rgb[2];
min = Math.min(r, Math.min(g, b));
max = Math.max(r, Math.max(g, b));
delta = max - min;
l = (min + max) / 2;
s = 0;
if (l > 0 && l < 1) {
s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
}
h = 0;
if (delta > 0) {
if (max == r && max != g) h += (g - b) / delta;
if (max == g && max != b) h += (2 + (b - r) / delta);
if (max == b && max != r) h += (4 + (r - g) / delta);
h /= 6;
}
return [h, s, l];
}
// Install mousedown handler (the others are set on the document on-demand)
$('*', e).mousedown(fb.mousedown);
// Init color
fb.setColor('#000000');
// Set linked elements/callback
if (callback) {
fb.linkTo(callback);
}
}

View File

@ -0,0 +1,81 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Papermashup.com | jQuery Color picker</title>
<link href="../style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript" src="farbtastic.js"></script>
<link rel="stylesheet" href="farbtastic.css" type="text/css" />
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var f = $.farbtastic('#picker');
var p = $('#picker').css('opacity', 0.25);
var selected;
$('.colorwell')
.each(function () { f.linkTo(this); $(this).css('opacity', 0.75); })
.focus(function() {
if (selected) {
$(selected).css('opacity', 0.75).removeClass('colorwell-selected');
}
f.linkTo(this);
p.css('opacity', 1);
$(selected = this).css('opacity', 1).addClass('colorwell-selected');
});
});
</script>
<style>
body{
font-family:Verdana, Geneva, sans-serif;
font-size:14px;
margin:0px;
padding:0px;}
.colorwell{
padding:5px;
font-size:18px;
color:#333;
font-family:Verdana, Geneva, sans-serif;
border:1px #CCC solid;}
</style>
</head>
<body>
<div id="header"><a href="http://www.papermashup.com/"><img src="../images/logo.png" width="348" height="63" border="0" /></a></div>
<div id="container">
<h1>jQuery 'Farbtastic' Color Picker</h1>
<form action="" style="width: 500px;">
<div id="picker" style="float: right;"></div>
<div class="form-item"><label for="color1">Color 1:</label><input type="text" id="color1" name="color1" class="colorwell" value="#edfa00" /></div>
<div class="form-item"><label for="color2">Color 2:</label><input type="text" id="color2" name="color2" class="colorwell" value="#ff9505" /></div>
<div class="form-item"><label for="color3">Color 3:</label><input type="text" id="color3" name="color3" class="colorwell" value="#f86c2a" /></div>
</form>
<div class="clear"></div>
</div>
<div id="footer"><a href="http://www.papermashup.com">papermashup.com</a> | <a href="http://papermashup.com/jquery-farbtastic-colour-picker/">Back to tutorial</a></div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-7025232-1");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,61 @@
// This javascript tags file downloads and external links in Google Analytics.
// You need to be using the Google Analytics New Tracking Code (ga.js)
// for this script to work.
// To use, place this file on all pages just above the Google Analytics tracking code.
// All outbound links and links to non-html files should now be automatically tracked.
//
// This script has been provided by Goodwebpractices.com
// Thanks to ShoreTel, MerryMan and Colm McBarron
//
// www.goodwebpractices.com
// VKI has made changes as indicated below.
if (document.getElementsByTagName) {
// Initialize external link handlers
var hrefs = document.getElementsByTagName("a");
for (var l = 0; l < hrefs.length; l++) {
// try {} catch{} block added by erikvold VKI
try{
//protocol, host, hostname, port, pathname, search, hash
if (hrefs[l].protocol == "mailto:") {
startListening(hrefs[l],"click",trackMailto);
} else if (hrefs[l].hostname == location.host) {
var path = hrefs[l].pathname + hrefs[l].search;
var isDoc = path.match(/\.(?:doc|eps|jpg|png|svg|xls|ppt|pdf|xls|zip|txt|vsd|vxd|js|css|rar|exe|wma|mov|avi|wmv|mp3)($|\&|\?)/);
if (isDoc) {
startListening(hrefs[l],"click",trackExternalLinks);
}
} else if (!hrefs[l].href.match(/^javascript:/)) {
startListening(hrefs[l],"click",trackExternalLinks);
}
}
catch(e){
continue;
}
}
}
function startListening (obj,evnt,func) {
if (obj.addEventListener) {
obj.addEventListener(evnt,func,false);
} else if (obj.attachEvent) {
obj.attachEvent("on" + evnt,func);
}
}
function trackMailto (evnt) {
var href = (evnt.srcElement) ? evnt.srcElement.href : this.href;
var mailto = "/mailto/" + href.substring(7);
if (typeof(pageTracker) == "object") pageTracker._trackPageview(mailto);
}
function trackExternalLinks (evnt) {
var e = (evnt.srcElement) ? evnt.srcElement : this;
while (e.tagName != "A") {
e = e.parentNode;
}
var lnk = (e.pathname.charAt(0) == "/") ? e.pathname : "/" + e.pathname;
if (e.search && e.pathname.indexOf(e.search) == -1) lnk += e.search;
if (e.hostname != location.host) lnk = "/external/" + e.hostname + lnk;
if (typeof(pageTracker) == "object") pageTracker._trackPageview(lnk);
}

View File

@ -0,0 +1,258 @@
// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// released under the MIT license
(function($) {
function maybeCall(thing, ctx) {
return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
};
function isElementInDOM(ele) {
while (ele = ele.parentNode) {
if (ele == document) return true;
}
return false;
};
function Tipsy(element, options) {
this.$element = $(element);
this.options = options;
this.enabled = true;
this.fixTitle();
};
Tipsy.prototype = {
show: function() {
var title = this.getTitle();
if (title && this.enabled) {
var $tip = this.tip();
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
$tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
var pos = $.extend({}, this.$element.offset(), {
width: this.$element[0].offsetWidth,
height: this.$element[0].offsetHeight
});
var actualWidth = $tip[0].offsetWidth,
actualHeight = $tip[0].offsetHeight,
gravity = maybeCall(this.options.gravity, this.$element[0]);
var tp;
switch (gravity.charAt(0)) {
case 'n':
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
break;
case 's':
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
break;
case 'e':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
break;
case 'w':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
break;
}
if (gravity.length == 2) {
if (gravity.charAt(1) == 'w') {
tp.left = pos.left + pos.width / 2 - 15;
} else {
tp.left = pos.left + pos.width / 2 - actualWidth + 15;
}
}
$tip.css(tp).addClass('tipsy-' + gravity);
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
if (this.options.className) {
$tip.addClass(maybeCall(this.options.className, this.$element[0]));
}
if (this.options.fade) {
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
} else {
$tip.css({visibility: 'visible', opacity: this.options.opacity});
}
}
},
hide: function() {
if (this.options.fade) {
this.tip().stop().fadeOut(function() { $(this).remove(); });
} else {
this.tip().remove();
}
},
fixTitle: function() {
var $e = this.$element;
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
$e.attr('original-title', $e.attr('title') || '').removeAttr('title');
}
},
getTitle: function() {
var title, $e = this.$element, o = this.options;
this.fixTitle();
var title, o = this.options;
if (typeof o.title == 'string') {
title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
} else if (typeof o.title == 'function') {
title = o.title.call($e[0]);
}
title = ('' + title).replace(/(^\s*|\s*$)/, "");
return title || o.fallback;
},
tip: function() {
if (!this.$tip) {
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
this.$tip.data('tipsy-pointee', this.$element[0]);
}
return this.$tip;
},
validate: function() {
if (!this.$element[0].parentNode) {
this.hide();
this.$element = null;
this.options = null;
}
},
enable: function() { this.enabled = true; },
disable: function() { this.enabled = false; },
toggleEnabled: function() { this.enabled = !this.enabled; }
};
$.fn.tipsy = function(options) {
if (options === true) {
return this.data('tipsy');
} else if (typeof options == 'string') {
var tipsy = this.data('tipsy');
if (tipsy) tipsy[options]();
return this;
}
options = $.extend({}, $.fn.tipsy.defaults, options);
function get(ele) {
var tipsy = $.data(ele, 'tipsy');
if (!tipsy) {
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
$.data(ele, 'tipsy', tipsy);
}
return tipsy;
}
function enter() {
var tipsy = get(this);
tipsy.hoverState = 'in';
if (options.delayIn == 0) {
tipsy.show();
} else {
tipsy.fixTitle();
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
}
};
function leave() {
var tipsy = get(this);
tipsy.hoverState = 'out';
if (options.delayOut == 0) {
tipsy.hide();
} else {
setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
}
};
if (!options.live) this.each(function() { get(this); });
if (options.trigger != 'manual') {
var binder = options.live ? 'live' : 'bind',
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
this[binder](eventIn, enter)[binder](eventOut, leave);
}
return this;
};
$.fn.tipsy.defaults = {
className: null,
delayIn: 0,
delayOut: 0,
fade: false,
fallback: '',
gravity: 'n',
html: false,
live: false,
offset: 0,
opacity: 0.8,
title: 'title',
trigger: 'hover'
};
$.fn.tipsy.revalidate = function() {
$('.tipsy').each(function() {
var pointee = $.data(this, 'tipsy-pointee');
if (!pointee || !isElementInDOM(pointee)) {
$(this).remove();
}
});
};
// Overwrite this method to provide options on a per-element basis.
// For example, you could store the gravity in a 'tipsy-gravity' attribute:
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
// (remember - do not modify 'options' in place!)
$.fn.tipsy.elementOptions = function(ele, options) {
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
};
$.fn.tipsy.autoNS = function() {
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
};
$.fn.tipsy.autoWE = function() {
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
};
/**
* yields a closure of the supplied parameters, producing a function that takes
* no arguments and is suitable for use as an autogravity function like so:
*
* @param margin (int) - distance from the viewable region edge that an
* element should be before setting its tooltip's gravity to be away
* from that edge.
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
* if there are no viewable region edges effecting the tooltip's
* gravity. It will try to vary from this minimally, for example,
* if 'sw' is preferred and an element is near the right viewable
* region edge, but not the top edge, it will set the gravity for
* that element's tooltip to be 'se', preserving the southern
* component.
*/
$.fn.tipsy.autoBounds = function(margin, prefer) {
return function() {
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
boundTop = $(document).scrollTop() + margin,
boundLeft = $(document).scrollLeft() + margin,
$this = $(this);
if ($this.offset().top < boundTop) dir.ns = 'n';
if ($this.offset().left < boundLeft) dir.ew = 'w';
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
return dir.ns + (dir.ew ? dir.ew : '');
}
};
})(jQuery);

View File

@ -0,0 +1,25 @@
.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }
.tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }
/* Rounded corners */
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
/* Uncomment for shadow */
/*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
/* Rules to colour arrows */
.tipsy-arrow-n { border-bottom-color: #000; }
.tipsy-arrow-s { border-top-color: #000; }
.tipsy-arrow-e { border-left-color: #000; }
.tipsy-arrow-w { border-right-color: #000; }
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }

View File

@ -0,0 +1,152 @@
/*
The MIT License (MIT)
Copyright (c) 2013 jamie.peabody@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* menu configurable options */
.wicked-menu { z-index: 7; } /* cm uses index <= 6 */
.wicked-menu { font-size: 13px; }
.wicked-menu, .wicked-menu ul, .wicked-menu li > a.menu-item {
color: #333; /* text color */
}
.wicked-menu li > a { color: #000; text-decoration:none;} /* regular link color */
.wicked-menu li > a:hover { text-decoration:underline; } /* regular link:hover */
.wicked-menu > li.hover > a.menu-item,
.wicked-menu, .wicked-menu ul {
background-color: #fff; /* background color */
}
.wicked-menu > li.hover,
.wicked-menu ul li:hover > ul,
.wicked-menu ul {
border: 1px solid #cbcbcb; /* menu border color */
}
.wicked-menu li:hover { background: #efefef; } /* hover menu background color */
.wicked-menu ul,
.wicked-menu > li.hover,
.wicked-menu ul li:hover > ul { /* drop shadow */
-webkit-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
-moz-box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
box-shadow: rgba(0, 0, 0, .2) 0 2px 4px 0;
}
/* -- global settings -- */
.wicked-menu { margin: 0px; padding: 0px; }
.wicked-menu, .wicked-menu ul { margin: 0; padding: 0; }
.wicked-menu li { display: inline-block; list-style-type: none; cursor:pointer; }
.wicked-menu li > a.menu-item { text-decoration: none; }
.wicked-menu ul { display: none; }
.wicked-menu ul li { width: 100%; position: relative; }
.wicked-menu ul li > a.menu-item > span { padding-left: 10px; }
/* top menu */
.wicked-menu > li > a > *, .wicked-menu > li { display: inline-block; }
.wicked-menu li > ul > li > * { padding: 5px; display: inline-block; } /* padding other menu-item */
.wicked-menu > li > a.menu-item > * { padding: 7px 7px; }
.wicked-menu > li { position: relative; border: 1px solid transparent; }
.wicked-menu > li.hover > a.menu-item > * { padding: 7px 7px 3px 7px; }
.wicked-menu > li.hover > a.menu-item {
/* lose the top-level focus indicator on hover */
outline: none;
position: relative;
display: inline-block;
z-index: 8;
}
/* menu items */
.wicked-menu li.hover > ul,
.wicked-menu ul li:hover > ul { display: block; position: absolute; }
.wicked-menu ul li:hover > ul { margin-top: 5px; }
/* drop menu */
.wicked-menu ul { z-index: 7; min-width: 210px; top: 2.1em; left: -1px; }
.wicked-menu > li.hover {
/* for the top-level menu, after hovering do not show background */
background: transparent; position: relative;
}
.wicked-menu ul > li > a.menu-item { line-height: 2.35em; display:inline-block; width:100%; padding: 0; }
/* menu layout for icons and hotkeys */
.wicked-menu span.hotkey { float: right; margin-right: 10px; }
.wicked-menu ul > li > a.menu-item > span.icon {
padding-left: 31px;
background-position: 7px center;
background-color: transparent;
background-repeat: no-repeat;
}
.wicked-menu ul li:hover > ul { min-width: 210px; top: 0px; left: 100%; }
.wicked-menu li.separator { border-top: 1px solid #e5e5e5; height: 3px; display: block; line-height: 3em; margin-top: 3px; }
.wicked-menu li.separator:hover { background: transparent; cursor:default; }
/* -------------------------------------------------------------------------- */
/* toolbar configurable options */
.wicked-toolbar {
background-color: #f5f5f5;
height: 30px;
border: 1px solid #e5e5e5;
border-right: 0;
border-left: 0;
margin: 0;
}
.wicked-toolbar li span {
width: 1px;
color: transparent;
display: inline-block;
}
.wicked-toolbar li {
height: 22px;
width: 28px;
margin: 3px;
vertical-align: middle;
display: inline-block;
text-align: center;
border: 1px solid transparent;
}
.wicked-toolbar li.separator {
border-right:1px solid #e5e5e5;
width: 1px;
}
.wicked-toolbar li.hover {
border: 1px solid #ccc;
border-radius: 2px;
box-shadow: rgba(0, 0, 0, .1) 0 1px 3px 0;
-webkit-transition: all 0.25s ease;
-moz-transition: all 0.25s ease;
-o-transition: all 0.25s ease;
transition: all 0.25s ease;
}
.wicked-toolbar .icon {
width: 16px;
height: 16px;
background-position: center center;
background-color: transparent;
background-repeat: no-repeat;
vertical-align: middle;
}
.wicked-toolbar a {
display: block;
vertical-align: middle;
height: 100%;
text-decoration: none;
}

View File

@ -0,0 +1,288 @@
/*
The MIT License (MIT)
Copyright (c) 2013 jamie.peabody@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
;(function( $, window, document, undefined ){
var pluginName = 'wickedtoolbar';
var SHIFT = new RegExp(/shift/i);
var ALT = new RegExp(/alt/i);
var CTRL = new RegExp(/ctrl/i);
var ARROW_DOWN = new RegExp(/↓/);
var ARROW_UP = new RegExp(/↑/);
var ARROW_LEFT = new RegExp(/←/);
var ARROW_RIGHT = new RegExp(/→/);
var keys = {
shift: 16,
alt: 17,
ctrl: 18,
meta: 91,
arrow_up: 38,
arrow_down: 40,
arrow_left: 37,
arrow_right: 39
};
var defaults = {
hasIcon: function(id) { },
getIcon: function(id) { }
};
function MenuBase(element, options) {
var self = this;
this.element = $(element);
this.settings = $.extend({}, defaults, options);
this.bindings = [];
// for each menu item, modify and wrap in div
this.element.find('li').each(function () {
var tthis = $(this);
// since the DOM is modifying wrt to icons, it can match the li[data-cion] from
// the HTML definition, or the span.icon from the modified DOM
var icons = tthis.closest('ul').find('li[data-icon], span.icon').length > 0;
var tnode = tthis.contents().filter(function() { return this.nodeType == 3; }).first();
var text = tnode.text().trim();
// remove the text node
tnode.remove();
if (!text || !text.length) return; // not a regular menu item
// change: <li>Text</li>
// to: <li>
// <a>
// <span>Text</span>
// </a>
// </li>
var li = tthis;
var div = $('<a class="menu-item" href="#">');
div.click(function(ev) {
$(this).focus();
// li.id > a
var id = $(this).parent().attr('id');
if (id) {
self.element.trigger('selected', [id]);
$(this).parents('.hover').removeClass('hover');
}
return false;
});
var span;
if (self.settings._type == 'menu') {
span = $('<span>' + text + '</span>');
}
else {
span = $('<span></span>');
}
div.append(span);
if (self.settings._type == 'menu') {
// accesskey
var accesskey = tthis.attr('accesskey');
if (accesskey) {
div.attr('accesskey', accesskey);
tthis.removeAttr('accesskey');
}
// hotkey
var hotkey = tthis.attr('data-hotkey');
if (hotkey) {
tthis.removeAttr('data-hotkey');
div.append('<span class="hotkey">' + hotkey + '</span>');
if (!accesskey) {
// add our own handler
var parts = hotkey.split('+');
var bind = {};
for (var i = 0; i < parts.length; ++i) {
if (SHIFT.test(parts[i])) {
bind.shiftKey = true;
}
else if (ALT.test(parts[i])) {
bind.altKey = true;
}
else if (CTRL.test(parts[i])) {
bind.ctrlKey = true;
}
else if (ARROW_DOWN.test(parts[i])) {
bind.which = keys.arrow_down;
}
else if (ARROW_UP.test(parts[i])) {
bind.which = keys.arrow_up;
}
else if (ARROW_RIGHT.test(parts[i])) {
bind.which = keys.arrow_right;
}
else if (ARROW_LEFT.test(parts[i])) {
bind.which = keys.arrow_left;
}
}
bind.target = div;
self.bindings.push(bind);
}
}
}
// icon
var id = tthis.attr('id'), icon;
if (self.settings.hasIcon(id)) {
span.addClass('icon');
icon = self.settings.getIcon(id);
if (icon) {
span.addClass(icon);
}
}
icon = tthis.attr('data-icon');
if (icon) {
tthis.removeAttr('data-icon');
span.addClass('icon ' + icon);
}
else if (icons) {
span.addClass('icon');
}
li.prepend(div);
});
$(document).on('keydown', function(ev) {
for (var i = 0; i < self.bindings.length; ++i) {
var bind = self.bindings[i];
// handle custom key events
if ((bind.shiftKey === undefined ? true : (bind.shiftKey === ev.shiftKey)) &&
(bind.ctrlKey === undefined ? true : (bind.ctrlKey === ev.ctrlKey)) &&
(bind.altKey === undefined ? true : (bind.altKey === ev.altKey)) &&
bind.which && ev.which && (bind.which === ev.which)) {
bind.target.trigger('click');
ev.preventDefault();
}
}
});
}
MenuBase.prototype.update = function (id) {
var li = this.element.find('#' + id), icon;
var span = li.find('span:first-child');
if (this.settings.hasIcon(id)) {
span.removeClass(); // this could be brutally unfair
span.addClass('icon');
icon = this.settings.getIcon(id);
if (icon) {
span.addClass(icon);
}
}
};
// ------------
// Menu
// ------------
function Menu(element, options) {
options._type = 'menu';
$.extend(this, new MenuBase(element, options)) ;
this.constructor();
}
Menu.prototype.constructor = function () {
this.element.addClass('wicked-ui wicked-menu');
var self = this;
var dohover = function(ev) {
$(this).parent().addClass('hover');
if ($(this).closest('ul').hasClass('wicked-menu')) {
// if the closest ul is a 'menu' (i.e. if this item is a top-level menu), then
// aply focus
$(this).focus();
}
if (!self.accessing) {
// Set 'accessing' to true and one document click to cancel it
self.accessing = true;
$(document).one('click', function() {
if (!self.accessing) return;
self.accessing = false;
self.element.find('.hover').removeClass('hover');
});
}
};
this.element.find('> li > a.menu-item').click(dohover);
this.element.find('> li > ul > li ul.drop-menu').each(function() {
// li > a + ul
$(this).prev('a.menu-item').addClass('icon-arrow-right');
$(this).prev('a.menu-item').hover(dohover);
$(this).prev('a.menu-item').mouseleave(
function() {
$(this).parent().removeClass('hover');
}
);
});
this.element.find('> li > a.menu-item').hover(
function() {
if (!self.accessing) return;
self.element.find('.hover').removeClass('hover');
$.proxy(dohover, this)();
}
);
};
// ------------
// Toolbar
// ------------
function Toolbar(element, options) {
options._type = 'toolbar';
$.extend(this, new MenuBase(element, options)) ;
this.constructor();
}
Toolbar.prototype.constructor = function () {
this.element.addClass('wicked-ui wicked-toolbar');
this.element.find('> li > a.menu-item').hover(
function(){ $(this).parent().addClass('hover'); },
function(){ $(this).parent().removeClass('hover'); }
);
};
var plugins = { wickedmenu: Menu, wickedtoolbar: Toolbar };
for (var key in plugins) {
(function(name, Plugin){
$.fn[name] = function (options) {
var args = arguments;
return this.each(function () {
if (typeof options === 'object' || !options) {
if (!$.data(this, 'plugin_' + name)) {
$.data(this, 'plugin_' + name, new Plugin( this, options ));
}
}
else {
var d = $.data(this, 'plugin_' + name);
if (!d) {
$.error('jQuery.' + name + ' plugin does not exist');
return;
}
return d[options](Array.prototype.slice.call(args, 1));
}
});
};
})(key, plugins[key])
}
})( jQuery, window, document );

View File

@ -0,0 +1,334 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
background-color: #7e7;
}
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor { position: absolute; }
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,45 @@
/* required */
.mergely-column textarea { width: 80px; height: 200px; }
.mergely-column { float: left; }
.mergely-margin { float: left; }
.mergely-canvas { float: left; width: 28px; }
/* resizeable */
.mergely-resizer { width: 100%; height: 100%; }
/* style configuration */
.mergely-column { border: 1px solid #ccc; }
.mergely-active { border: 1px solid #a3d1ff; }
.mergely.a,.mergely.d,.mergely.c { color: #000; }
.mergely.a.rhs.start { border-top: 1px solid #a3d1ff; }
.mergely.a.lhs.start.end,
.mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; }
.mergely.a.rhs { background-color: #ddeeff; }
.mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; }
.mergely.d.lhs { background-color: #ffe9e9; }
.mergely.d.lhs.end,
.mergely.d.rhs.start.end { border-bottom: 1px solid #f8e8e8; }
.mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #f8e8e8; }
.mergely.d.lhs.start { border-top: 1px solid #f8e8e8; }
.mergely.c.lhs,
.mergely.c.rhs { background-color: #fafafa; }
.mergely.c.lhs.start,
.mergely.c.rhs.start { border-top: 1px solid #a3a3a3; }
.mergely.c.lhs.end,
.mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
.mergely.ch.a.rhs { background-color: #ddeeff; }
.mergely.ch.d.lhs { background-color: #ffe9e9; text-decoration: line-through; color: red !important; }
.mergely.current.start { border-top: 1px solid #000 !important; }
.mergely.current.end { border-bottom: 1px solid #000 !important; }
.mergely.current.lhs.a.start.end,
.mergely.current.rhs.d.start.end { border-top: 0 !important; }
.mergely.current.CodeMirror-linenumber { color: #F9F9F9; font-weight: bold; background-color: #777; }
.CodeMirror-linenumber { cursor: pointer; }
.CodeMirror-code { color: #717171; }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,131 @@
(function(){
var Pos = CodeMirror.Pos;
function SearchCursor(cm, query, pos, caseFold) {
this.atOccurrence = false; this.cm = cm;
if (caseFold == null && typeof query == "string") caseFold = false;
pos = pos ? cm.clipPos(pos) : Pos(0, 0);
this.pos = {from: pos, to: pos};
// The matches method is filled in based on the type of query.
// It takes a position and a direction, and returns an object
// describing the next occurrence of the query, or null if no
// more matches were found.
if (typeof query != "string") { // Regexp match
if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
this.matches = function(reverse, pos) {
if (reverse) {
query.lastIndex = 0;
var line = cm.getLine(pos.line).slice(0, pos.ch), match = query.exec(line), start = 0;
while (match) {
start += match.index + 1;
line = line.slice(start);
query.lastIndex = 0;
var newmatch = query.exec(line);
if (newmatch) match = newmatch;
else break;
}
start--;
} else {
query.lastIndex = pos.ch;
var line = cm.getLine(pos.line), match = query.exec(line),
start = match && match.index;
}
if (match && match[0])
return {from: Pos(pos.line, start),
to: Pos(pos.line, start + match[0].length),
match: match};
};
} else { // String query
if (caseFold) query = query.toLowerCase();
var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
var target = query.split("\n");
// Different methods for single-line and multi-line queries
if (target.length == 1) {
if (!query.length) {
// Empty string would match anything and never progress, so
// we define it to match nothing instead.
this.matches = function() {};
} else {
this.matches = function(reverse, pos) {
var line = fold(cm.getLine(pos.line)), len = query.length, match;
if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
: (match = line.indexOf(query, pos.ch)) != -1)
return {from: Pos(pos.line, match),
to: Pos(pos.line, match + len)};
};
}
} else {
this.matches = function(reverse, pos) {
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
if (reverse ? offsetA >= pos.ch || offsetA != match.length
: offsetA <= pos.ch || offsetA != line.length - match.length)
return;
for (;;) {
if (reverse ? !ln : ln == cm.lineCount() - 1) return;
line = fold(cm.getLine(ln += reverse ? -1 : 1));
match = target[reverse ? --idx : ++idx];
if (idx > 0 && idx < target.length - 1) {
if (line != match) return;
else continue;
}
var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
return;
var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
return {from: reverse ? end : start, to: reverse ? start : end};
}
};
}
}
}
SearchCursor.prototype = {
findNext: function() {return this.find(false);},
findPrevious: function() {return this.find(true);},
find: function(reverse) {
var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
function savePosAndFail(line) {
var pos = Pos(line, 0);
self.pos = {from: pos, to: pos};
self.atOccurrence = false;
return false;
}
for (;;) {
if (this.pos = this.matches(reverse, pos)) {
if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
this.atOccurrence = true;
return this.pos.match || true;
}
if (reverse) {
if (!pos.line) return savePosAndFail(0);
pos = Pos(pos.line-1, this.cm.getLine(pos.line-1).length);
}
else {
var maxLine = this.cm.lineCount();
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
pos = Pos(pos.line + 1, 0);
}
}
},
from: function() {if (this.atOccurrence) return this.pos.from;},
to: function() {if (this.atOccurrence) return this.pos.to;},
replace: function(newText) {
if (!this.atOccurrence) return;
var lines = CodeMirror.splitLines(newText);
this.cm.replaceRange(lines, this.pos.from, this.pos.to);
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
}
};
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this, query, pos, caseFold);
});
})();

View File

@ -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
}

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>文档比较 - Powered by MinDoc</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="description" content="Merge and Diff your documents with diff online and share" />
<meta name="keywords" content="diff,merge,compare,jsdiff,comparison,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
<meta name="author" content="Jamie Peabody" />
<link rel="shortcut icon" href="/favicon.ico" />
<link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
<script type="text/javascript" src="/static/jquery/1.12.4/jquery.min.js"></script>
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/lib/wicked-ui.css' />
<script type="text/javascript" src="/static/mergely/editor/lib/wicked-ui.js"></script>
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/lib/tipsy/tipsy.css' />
<script type="text/javascript" src="/static/mergely/editor/lib/tipsy/jquery.tipsy.js"></script>
<script type="text/javascript" src="/static/mergely/editor/lib/farbtastic/farbtastic.js"></script>
<link type="text/css" rel="stylesheet" href="/static/mergely/editor/lib/farbtastic/farbtastic.css" />
<script type="text/javascript" src="/static/mergely/lib/codemirror.min.js"></script>
<script type="text/javascript" src="/static/mergely/lib/mergely.min.js"></script>
<script type="text/javascript" src="/static/mergely/editor/editor.min.js"></script>
<link type="text/css" rel="stylesheet" href="/static/mergely/lib/codemirror.css" />
<link type="text/css" rel="stylesheet" href="/static/mergely/lib/mergely.css" />
<link type='text/css' rel='stylesheet' href='/static/mergely/editor/editor.css' />
<script type="text/javascript" src="/static/mergely/lib/searchcursor.js"></script>
<script type="text/javascript">
var key = '';
var isSample = key == 'usaindep';
</script>
</head>
<body style="visibility:hidden">
<!-- editor -->
<div style="position: absolute;top: 0px;bottom: 10px;left: 5px;right: 5px;overflow-y: hidden;padding-bottom: 2px;">
<div id="mergely"></div>
</div>
</body>
</html>

View File

@ -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>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>附件管理 - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet" type="text/css">
<link href="/static/css/main.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
<script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js" }}"></script>
<![endif]-->
</head>
<body>
<div class="manual-reader">
{{template "widgets/header.tpl" .}}
<div class="container manual-body">
<div class="row">
<div class="page-left">
<ul class="menu">
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
<li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
</ul>
</div>
<div class="page-right">
<div class="m-box">
<div class="box-head">
<strong class="box-title">附件管理</strong>
</div>
</div>
<div class="box-body">
<form>
<div class="form-group">
<label>文件名称</label>
<input type="text" value="{{.Model.FileName}}" class="form-control input-readonly" readonly placeholder="文件名称">
</div>
<div class="form-group">
<label>是否存在</label>
{{if .Model.IsExist }}
<input type="text" value="存在" class="form-control input-readonly" readonly placeholder="项目名称">
{{else}}
<input type="text" value="已删除" class="form-control input-readonly" readonly placeholder="项目名称">
{{end}}
</div>
<div class="form-group">
<label>项目名称</label>
<input type="text" value="{{.Model.BookName}}" class="form-control input-readonly" readonly placeholder="项目名称">
</div>
<div class="form-group">
<label>文档名称</label>
<input type="text" value="{{.Model.DocumentName}}" class="form-control input-readonly" readonly placeholder="文档名称">
</div>
<div class="form-group">
<label>文件路径</label>
<input type="text" value="{{.Model.FilePath}}" class="form-control input-readonly" readonly placeholder="文件路径">
</div>
<div class="form-group">
<label>下载路径</label>
<input type="text" value="{{.Model.HttpPath}}" class="form-control input-readonly" readonly placeholder="文件路径">
</div>
<div class="form-group">
<label>文件大小</label>
<input type="text" value="{{.Model.FileShortSize}}" class="form-control input-readonly" readonly placeholder="文件路径">
</div>
<div class="form-group">
<label>上传时间</label>
<input type="text" value="{{date .Model.CreateTime "Y-m-d H:i:s"}}" class="form-control input-readonly" readonly placeholder="文件路径">
</div>
<div class="form-group">
<label>用户账号</label>
<input type="text" value="{{ .Model.Account }}" class="form-control input-readonly" readonly placeholder="文件路径">
</div>
<div class="form-group">
<a href="{{urlfor "ManagerController.AttachList" }}" class="btn btn-success btn-sm">返回</a>
{{if .Model.IsExist }}
<a href="{{.Model.LocalHttpPath}}" class="btn btn-default btn-sm" target="_blank" title="下载到本地">下载</a>
{{end}}
</div>
</form>
</div>
</div>
</div>
</div>
{{template "widgets/footer.tpl" .}}
</div>
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
<script src="{{cdnjs "/static/vuejs/vue.min.js"}}" type="text/javascript"></script>
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
<script src="/static/js/main.js" type="text/javascript"></script>
</body>
</html>

View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>附件管理 - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="{{cdncss "/static/bootstrap/css/bootstrap.min.css"}}" rel="stylesheet" type="text/css">
<link href="{{cdncss "/static/font-awesome/css/font-awesome.min.css"}}" rel="stylesheet" type="text/css">
<link href="{{cdncss "/static/css/main.css"}}" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="{{cdnjs "/static/html5shiv/3.7.3/html5shiv.min.js"}}"></script>
<script src="{{cdnjs "/static/respond.js/1.4.2/respond.min.js" }}"></script>
<![endif]-->
</head>
<body>
<div class="manual-reader">
{{template "widgets/header.tpl" .}}
<div class="container manual-body">
<div class="row">
<div class="page-left">
<ul class="menu">
<li><a href="{{urlfor "ManagerController.Index"}}" class="item"><i class="fa fa-dashboard" aria-hidden="true"></i> 仪表盘</a> </li>
<li><a href="{{urlfor "ManagerController.Users" }}" class="item"><i class="fa fa-users" aria-hidden="true"></i> 用户管理</a> </li>
<li><a href="{{urlfor "ManagerController.Books" }}" class="item"><i class="fa fa-book" aria-hidden="true"></i> 项目管理</a> </li>
{{/*<li><a href="{{urlfor "ManagerController.Comments" }}" class="item"><i class="fa fa-comments-o" aria-hidden="true"></i> </a> </li>*/}}
<li><a href="{{urlfor "ManagerController.Setting" }}" class="item"><i class="fa fa-cogs" aria-hidden="true"></i> 配置管理</a> </li>
<li class="active"><a href="{{urlfor "ManagerController.AttachList" }}" class="item"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 附件管理</a> </li>
</ul>
</div>
<div class="page-right">
<div class="m-box">
<div class="box-head">
<strong class="box-title">附件管理</strong>
</div>
</div>
<div class="box-body">
<div class="attach-list" id="attachList">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>附件名称</th>
<th>项目名称</th>
<th>文件大小</th>
<th>是否存在</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{{range $index,$item := .Lists}}
<tr>
<td>{{$item.AttachmentId}}</td>
<td>{{$item.FileName}}</td>
<td>{{$item.BookName}}</td>
<td>{{$item.FileShortSize}}</td>
<td>{{ if $item.IsExist }}{{else}}{{end}}</td>
<td>
<button type="button" data-method="delete" class="btn btn-danger btn-sm" data-id="{{$item.AttachmentId}}" data-loading-text="删除中...">删除</button>
<a href="{{urlfor "ManagerController.AttachDetailed" ":id" $item.AttachmentId}}" class="btn btn-success btn-sm">详情</a>
</td>
</tr>
{{else}}
<tr><td>暂无数据</td></tr>
{{end}}
</tbody>
</table>
<nav>
{{.PageHtml}}
</nav>
</div>
</div>
</div>
</div>
</div>
{{template "widgets/footer.tpl" .}}
</div>
<script src="{{cdnjs "/static/jquery/1.12.4/jquery.min.js"}}"></script>
<script src="{{cdnjs "/static/bootstrap/js/bootstrap.min.js"}}"></script>
<script src="{{cdnjs "/static/js/jquery.form.js"}}" type="text/javascript"></script>
<script src="{{cdnjs "/static/layer/layer.js" }}" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$("#attachList").on("click","button[data-method='delete']",function () {
var id = $(this).attr("data-id");
var $this = $(this);
$(this).button("loading");
$.ajax({
url : "{{urlfor "ManagerController.AttachDelete"}}",
data : { "attach_id" : id },
type : "post",
dataType : "json",
success : function (res) {
if(res.errcode === 0){
$this.closest("tr").remove().empty();
}else {
layer.msg(res.message);
}
},
error : function () {
layer.msg("服务器异常");
},
complete : function () {
$this.button("reset");
}
});
});
});
</script>
</body>
</html>

View File

@ -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>

View File

@ -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">

View File

@ -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">

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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}}