mirror of https://github.com/artf/grapesjs.git
committed by
GitHub
146 changed files with 5688 additions and 3054 deletions
@ -0,0 +1,10 @@ |
|||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
end_of_line = lf |
||||
|
insert_final_newline = true |
||||
|
|
||||
|
[*.js] |
||||
|
charset = utf-8 |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
@ -0,0 +1,3 @@ |
|||||
|
test |
||||
|
index.html |
||||
|
webpack.config.js |
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,26 +1,24 @@ |
|||||
module.exports = { |
module.exports = { |
||||
|
|
||||
run(editor, sender) { |
run(editor, sender) { |
||||
var config = editor.Config; |
const bm = editor.BlockManager; |
||||
var pfx = config.stylePrefix; |
const pn = editor.Panels; |
||||
var bm = editor.BlockManager; |
|
||||
var panelC; |
if (!this.blocks) { |
||||
if(!this.blocks){ |
bm.render(); |
||||
this.blocks = $('<div/>').get(0); |
const id = 'views-container'; |
||||
this.blocks.appendChild(bm.render()); |
const blocks = document.createElement('div'); |
||||
var panels = editor.Panels; |
const panels = pn.getPanel(id) || pn.addPanel({id}); |
||||
if(!panels.getPanel('views-container')) |
blocks.appendChild(bm.getContainer()); |
||||
panelC = panels.addPanel({id: 'views-container'}); |
panels.set('appendContent', blocks).trigger('change:appendContent'); |
||||
else |
this.blocks = blocks; |
||||
panelC = panels.getPanel('views-container'); |
|
||||
panelC.set('appendContent', this.blocks).trigger('change:appendContent'); |
|
||||
} |
} |
||||
|
|
||||
this.blocks.style.display = 'block'; |
this.blocks.style.display = 'block'; |
||||
}, |
}, |
||||
|
|
||||
stop() { |
stop() { |
||||
if(this.blocks) |
const blocks = this.blocks; |
||||
this.blocks.style.display = 'none'; |
blocks && (blocks.style.display = 'none'); |
||||
} |
} |
||||
}; |
}; |
||||
|
|||||
@ -0,0 +1,9 @@ |
|||||
|
module.exports = { |
||||
|
|
||||
|
run(editor) { |
||||
|
const comp = editor.getSelected(); |
||||
|
const coll = comp && comp.collection; |
||||
|
coll && coll.parent && editor.select(coll.parent); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
@ -1,40 +1,11 @@ |
|||||
module.exports = { |
module.exports = { |
||||
|
|
||||
stylePrefix : 'rte-', |
stylePrefix : 'rte-', |
||||
toolbarId : 'toolbar', |
|
||||
|
|
||||
// If true, moves the toolbar below the element when the top canvas
|
// If true, moves the toolbar below the element when the top canvas
|
||||
// edge is reached
|
// edge is reached
|
||||
adjustToolbar: 1, |
adjustToolbar: 1, |
||||
|
|
||||
// Default toolbar commands
|
// Default RTE actions
|
||||
commands : [{ |
actions: ['bold', 'italic', 'underline', 'strikethrough', 'link'], |
||||
command: 'bold', |
|
||||
title: 'Bold', |
|
||||
class: 'fa fa-bold', |
|
||||
},{ |
|
||||
command: 'italic', |
|
||||
title: 'Italic', |
|
||||
class: 'fa fa-italic', |
|
||||
},{ |
|
||||
command: 'underline', |
|
||||
title: 'Underline', |
|
||||
class: 'fa fa-underline', |
|
||||
},{ |
|
||||
command: 'strikethrough', |
|
||||
title: 'Strikethrough', |
|
||||
class: 'fa fa-strikethrough', |
|
||||
group: 'format' |
|
||||
},{ |
|
||||
command: 'insertHTML', |
|
||||
title: 'Link', |
|
||||
class: 'fa fa-link', |
|
||||
args: '<a class="link" href="">${content}</a>', |
|
||||
}/*,{ |
|
||||
command: 'fontSize', |
|
||||
options: [ |
|
||||
{name: 'Huge', value: '7'}, |
|
||||
{name: 'Normal', value: '5'}, |
|
||||
{value: '1'} |
|
||||
] |
|
||||
}*/], |
|
||||
}; |
}; |
||||
|
|||||
@ -1,21 +0,0 @@ |
|||||
var Backbone = require('backbone'); |
|
||||
|
|
||||
module.exports = Backbone.Model.extend({ |
|
||||
|
|
||||
idAttribute: 'command', |
|
||||
|
|
||||
defaults: { |
|
||||
command: '', |
|
||||
type: '', |
|
||||
title: '', |
|
||||
class: '', |
|
||||
options: [], |
|
||||
}, |
|
||||
|
|
||||
initialize() { |
|
||||
var opts = this.get('options'); |
|
||||
if(opts.length) |
|
||||
this.set('type', 'select'); |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
@ -1,6 +0,0 @@ |
|||||
var Backbone = require('backbone'); |
|
||||
var CommandButton = require('./CommandButton'); |
|
||||
|
|
||||
module.exports = Backbone.Collection.extend({ |
|
||||
model: CommandButton, |
|
||||
}); |
|
||||
@ -0,0 +1,245 @@ |
|||||
|
// The initial version of this RTE was borrowed from https://github.com/jaredreich/pell
|
||||
|
// and adapted to the GrapesJS's need
|
||||
|
|
||||
|
import {on, off} from 'utils/mixins' |
||||
|
|
||||
|
const RTE_KEY = '_rte'; |
||||
|
|
||||
|
const defActions = { |
||||
|
bold: { |
||||
|
name: 'bold', |
||||
|
icon: '<b>B</b>', |
||||
|
attributes: {title: 'Bold'}, |
||||
|
result: (rte) => rte.exec('bold') |
||||
|
}, |
||||
|
italic: { |
||||
|
name: 'italic', |
||||
|
icon: '<i>I</i>', |
||||
|
attributes: {title: 'Italic'}, |
||||
|
result: (rte) => rte.exec('italic') |
||||
|
}, |
||||
|
underline: { |
||||
|
name: 'underline', |
||||
|
icon: '<u>U</u>', |
||||
|
attributes: {title: 'Underline'}, |
||||
|
result: (rte) => rte.exec('underline') |
||||
|
}, |
||||
|
strikethrough: { |
||||
|
name: 'strikethrough', |
||||
|
icon: '<strike>S</strike>', |
||||
|
attributes: {title: 'Strike-through'}, |
||||
|
result: (rte) => rte.exec('strikeThrough') |
||||
|
}, |
||||
|
link: { |
||||
|
icon: `<span style="transform:rotate(45deg)">⫘</span>`, |
||||
|
name: 'link', |
||||
|
attributes: { |
||||
|
style: 'font-size:1.4rem;padding:0 4px 2px;', |
||||
|
title: 'Link', |
||||
|
}, |
||||
|
result: (rte) => rte.insertHTML(`<a class="link" href="">${rte.selection()}</a>`) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default class RichTextEditor { |
||||
|
|
||||
|
constructor(settings = {}) { |
||||
|
const el = settings.el; |
||||
|
|
||||
|
if (el[RTE_KEY]) { |
||||
|
return el[RTE_KEY]; |
||||
|
} |
||||
|
|
||||
|
el[RTE_KEY] = this; |
||||
|
this.setEl(el); |
||||
|
this.updateActiveActions = this.updateActiveActions.bind(this); |
||||
|
|
||||
|
const settAct = settings.actions || []; |
||||
|
settAct.forEach((action, i) => { |
||||
|
if (typeof action === 'string') { |
||||
|
action = defActions[action]; |
||||
|
} else if (defActions[action.name]) { |
||||
|
action = {...defActions[action.name], ...action}; |
||||
|
} |
||||
|
settAct[i] = action; |
||||
|
}); |
||||
|
const actions = settAct.length ? settAct : |
||||
|
Object.keys(defActions).map(action => defActions[action]) |
||||
|
|
||||
|
settings.classes = { ...{ |
||||
|
actionbar: 'actionbar', |
||||
|
button: 'action', |
||||
|
active: 'active', |
||||
|
}, ...settings.classes}; |
||||
|
|
||||
|
const classes = settings.classes; |
||||
|
let actionbar = settings.actionbar; |
||||
|
this.actionbar = actionbar; |
||||
|
this.settings = settings; |
||||
|
this.classes = classes; |
||||
|
this.actions = actions; |
||||
|
|
||||
|
if (!actionbar) { |
||||
|
const actionbarCont = settings.actionbarContainer; |
||||
|
actionbar = document.createElement('div'); |
||||
|
actionbar.className = classes.actionbar; |
||||
|
actionbarCont.appendChild(actionbar); |
||||
|
this.actionbar = actionbar; |
||||
|
actions.forEach(action => this.addAction(action)) |
||||
|
} |
||||
|
|
||||
|
settings.styleWithCSS && this.exec('styleWithCSS'); |
||||
|
this.syncActions(); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
setEl(el) { |
||||
|
this.el = el; |
||||
|
this.doc = el.ownerDocument; |
||||
|
} |
||||
|
|
||||
|
updateActiveActions() { |
||||
|
this.getActions().forEach(action => { |
||||
|
const btn = action.btn; |
||||
|
const update = action.update; |
||||
|
const active = this.classes.active; |
||||
|
const name = action.name; |
||||
|
const doc = this.doc; |
||||
|
btn.className = btn.className.replace(active, '').trim(); |
||||
|
|
||||
|
// doc.queryCommandValue(name) != 'false'
|
||||
|
if (doc.queryCommandState(name)) { |
||||
|
btn.className += ` ${active}`; |
||||
|
} |
||||
|
|
||||
|
update && update(this, action); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
enable() { |
||||
|
if (this.enabled) { |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
this.actionbarEl().style.display = ''; |
||||
|
this.el.contentEditable = true; |
||||
|
on(this.el, 'mouseup keyup', this.updateActiveActions) |
||||
|
this.syncActions(); |
||||
|
this.updateActiveActions(); |
||||
|
this.el.focus(); |
||||
|
this.enabled = 1; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
disable() { |
||||
|
this.actionbarEl().style.display = 'none'; |
||||
|
this.el.contentEditable = false; |
||||
|
off(this.el, 'mouseup keyup', this.updateActiveActions); |
||||
|
this.enabled = 0; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Sync actions with the current RTE |
||||
|
*/ |
||||
|
syncActions() { |
||||
|
this.getActions().forEach(action => { |
||||
|
const event = action.event || 'click'; |
||||
|
action.btn[`on${event}`] = e => { |
||||
|
action.result(this, action); |
||||
|
this.updateActiveActions(); |
||||
|
}; |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Add new action to the actionbar |
||||
|
* @param {Object} action |
||||
|
* @param {Object} [opts={}] |
||||
|
*/ |
||||
|
addAction(action, opts = {}) { |
||||
|
const sync = opts.sync; |
||||
|
const btn = document.createElement('span'); |
||||
|
const icon = action.icon; |
||||
|
const attr = action.attributes || {}; |
||||
|
btn.className = this.classes.button; |
||||
|
action.btn = btn; |
||||
|
|
||||
|
for (let key in attr) { |
||||
|
btn.setAttribute(key, attr[key]); |
||||
|
} |
||||
|
|
||||
|
if (typeof icon == 'string') { |
||||
|
btn.innerHTML = icon; |
||||
|
} else { |
||||
|
btn.appendChild(icon); |
||||
|
} |
||||
|
|
||||
|
this.actionbarEl().appendChild(btn); |
||||
|
|
||||
|
if (sync) { |
||||
|
this.actions.push(action); |
||||
|
this.syncActions(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the array of current actions |
||||
|
* @return {Array} |
||||
|
*/ |
||||
|
getActions() { |
||||
|
return this.actions; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the Selection instance |
||||
|
* @return {Selection} |
||||
|
*/ |
||||
|
selection() { |
||||
|
return this.doc.getSelection() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute the command |
||||
|
* @param {string} command Command name |
||||
|
* @param {any} [value=null Command's arguments |
||||
|
*/ |
||||
|
exec(command, value = null) { |
||||
|
this.doc.execCommand(command, false, value); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the actionbar element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
actionbarEl() { |
||||
|
return this.actionbar; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Set custom HTML to the selection, useful as the default 'insertHTML' command |
||||
|
* doesn't work in the same way on all browsers |
||||
|
* @param {string} value HTML string |
||||
|
*/ |
||||
|
insertHTML(value) { |
||||
|
let lastNode; |
||||
|
const doc = this.doc; |
||||
|
const sel = doc.getSelection(); |
||||
|
|
||||
|
if (sel && sel.rangeCount) { |
||||
|
const node = doc.createElement('div'); |
||||
|
const range = sel.getRangeAt(0); |
||||
|
range.deleteContents(); |
||||
|
node.innerHTML = value; |
||||
|
Array.prototype.slice.call(node.childNodes).forEach(nd => { |
||||
|
range.insertNode(nd); |
||||
|
lastNode = nd; |
||||
|
}) |
||||
|
|
||||
|
sel.removeAllRanges(); |
||||
|
sel.addRange(range); |
||||
|
this.el.focus(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,42 +0,0 @@ |
|||||
var Backbone = require('backbone'); |
|
||||
var CommandButtonView = require('./CommandButtonView'); |
|
||||
|
|
||||
module.exports = CommandButtonView.extend({ |
|
||||
|
|
||||
initialize(o, config) { |
|
||||
CommandButtonView.prototype.initialize.apply(this, arguments); |
|
||||
}, |
|
||||
|
|
||||
getInput() { |
|
||||
var m = this.model; |
|
||||
if(!this.input){ |
|
||||
var cmd = m.get('command'); |
|
||||
var input = '<select data-edit="' + cmd +'">'; |
|
||||
var opts = m.get('options'); |
|
||||
var label = m.get('title') || m.get('command'); |
|
||||
input += '<option>' + label + '</option>'; |
|
||||
for(var i = 0, len = opts.length; i < len; i++){ |
|
||||
var opt = opts[i]; |
|
||||
var value = opt.value; |
|
||||
var name = opt.name || value; |
|
||||
input += '<option value="' + value + '">' + name + '</option>'; |
|
||||
} |
|
||||
input += '</select>'; |
|
||||
this.input = $(input); |
|
||||
} |
|
||||
return this.input; |
|
||||
}, |
|
||||
|
|
||||
getInputCont() { |
|
||||
var input = this.getInput(); |
|
||||
var pfx = this.ppfx; |
|
||||
var cont = $('<div class="'+pfx+'field '+pfx+'select"><div class="'+pfx+'sel-arrow"><div class="'+pfx+'d-s-arrow"></div></div></div>'); |
|
||||
return cont.append(input); |
|
||||
}, |
|
||||
|
|
||||
render(...args) { |
|
||||
CommandButtonView.prototype.render.apply(this, args); |
|
||||
this.$el.html(this.getInputCont()); |
|
||||
return this; |
|
||||
} |
|
||||
}); |
|
||||
@ -1,16 +0,0 @@ |
|||||
var Backbone = require('backbone'); |
|
||||
|
|
||||
module.exports = Backbone.View.extend({ |
|
||||
tagName: 'a', |
|
||||
|
|
||||
initialize(o, config) { |
|
||||
this.config = config || {}; |
|
||||
this.ppfx = this.config.pStylePrefix || ''; |
|
||||
this.className = this.config.stylePrefix + 'btn ' + this.model.get('class'); |
|
||||
}, |
|
||||
|
|
||||
render() { |
|
||||
this.$el.addClass(this.className); |
|
||||
return this; |
|
||||
} |
|
||||
}); |
|
||||
@ -1,76 +0,0 @@ |
|||||
var Backbone = require('backbone'); |
|
||||
var CommandButtonView = require('./CommandButtonView'); |
|
||||
var CommandButtonSelectView = require('./CommandButtonSelectView'); |
|
||||
|
|
||||
module.exports = Backbone.View.extend({ |
|
||||
|
|
||||
attributes : { |
|
||||
'data-role': 'editor-toolbar', |
|
||||
}, |
|
||||
|
|
||||
initialize(o) { |
|
||||
this.config = o.config || {}; |
|
||||
var pfx = this.config.stylePrefix || ''; |
|
||||
this.id = pfx + this.config.toolbarId; |
|
||||
this.listenTo(this.collection, 'add', this.addTo); |
|
||||
this.$el.data('helper', 1); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new model to the collection |
|
||||
* @param {Model} model |
|
||||
* @private |
|
||||
* */ |
|
||||
addTo(model) { |
|
||||
this.add(model); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render new model inside the view |
|
||||
* @param {Model} model |
|
||||
* @param {Object} fragment Fragment collection |
|
||||
* @private |
|
||||
* */ |
|
||||
add(model, fragment) { |
|
||||
var frag = fragment || null; |
|
||||
var viewObj = CommandButtonView; |
|
||||
|
|
||||
switch (model.get('type')) { |
|
||||
case 'select': |
|
||||
viewObj = CommandButtonSelectView; |
|
||||
break; |
|
||||
} |
|
||||
var args = model.get('args'); |
|
||||
var attrs = { |
|
||||
'title': model.get('title'), |
|
||||
'data-edit': model.get('command'), |
|
||||
}; |
|
||||
if(args) |
|
||||
attrs['data-args'] = args; |
|
||||
var view = new viewObj({ |
|
||||
model, |
|
||||
attributes: attrs, |
|
||||
}, this.config); |
|
||||
|
|
||||
var rendered = view.render().el; |
|
||||
|
|
||||
if(frag) |
|
||||
frag.appendChild(rendered); |
|
||||
else |
|
||||
this.$el.append(rendered); |
|
||||
}, |
|
||||
|
|
||||
render() { |
|
||||
var frag = document.createDocumentFragment(); |
|
||||
this.$el.empty(); |
|
||||
|
|
||||
this.collection.each(function(model){ |
|
||||
this.add(model, frag); |
|
||||
}, this); |
|
||||
|
|
||||
this.$el.append(frag); |
|
||||
this.$el.attr('id', this.id ); |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
@ -1,231 +0,0 @@ |
|||||
var readFileIntoDataUrl = fileInfo => { |
|
||||
var loader = $.Deferred(), |
|
||||
fReader = new FileReader(); |
|
||||
fReader.onload = e => { |
|
||||
loader.resolve(e.target.result); |
|
||||
}; |
|
||||
fReader.onerror = loader.reject; |
|
||||
fReader.onprogress = loader.notify; |
|
||||
fReader.readAsDataURL(fileInfo); |
|
||||
return loader.promise(); |
|
||||
}; |
|
||||
$.fn.cleanHtml = function () { |
|
||||
var html = $(this).html(); |
|
||||
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, ''); |
|
||||
}; |
|
||||
$.fn.wysiwyg = function (userOptions) { |
|
||||
var editor = this, |
|
||||
selectedRange, |
|
||||
options, |
|
||||
toolbarBtnSelector, |
|
||||
updateToolbar = () => { |
|
||||
var actCls = options.activeToolbarClass; |
|
||||
if (actCls) { |
|
||||
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () { |
|
||||
var el = $(this); |
|
||||
var command = el.data(options.commandRole); |
|
||||
var doc = editor.get(0).ownerDocument; |
|
||||
if (doc.queryCommandState(command)) { |
|
||||
el.addClass(actCls); |
|
||||
} else { |
|
||||
el.removeClass(actCls); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
}, |
|
||||
execCommand = (commandWithArgs, valueArg) => { |
|
||||
var commandArr = commandWithArgs.split(' '), |
|
||||
command = commandArr.shift(), |
|
||||
args = commandArr.join(' ') + (valueArg || ''); |
|
||||
//document.execCommand("insertHTML", false, "<span class='own-class'>"+ document.getSelection()+"</span>");
|
|
||||
editor.get(0).ownerDocument.execCommand("styleWithCSS", false, true); |
|
||||
editor.get(0).ownerDocument.execCommand(command, 0, args); |
|
||||
updateToolbar(); |
|
||||
editor.trigger('change'); |
|
||||
}, |
|
||||
/* |
|
||||
bindHotkeys = function (hotKeys) { |
|
||||
$.each(hotKeys, function (hotkey, command) { |
|
||||
editor.keydown(hotkey, function (e) { |
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) { |
|
||||
e.preventDefault(); |
|
||||
e.stopPropagation(); |
|
||||
execCommand(command); |
|
||||
} |
|
||||
}).keyup(hotkey, function (e) { |
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) { |
|
||||
e.preventDefault(); |
|
||||
e.stopPropagation(); |
|
||||
} |
|
||||
}); |
|
||||
}); |
|
||||
}, |
|
||||
*/ |
|
||||
getCurrentRange = () => { |
|
||||
var sel = window.getSelection(); |
|
||||
if (sel.getRangeAt && sel.rangeCount) { |
|
||||
return sel.getRangeAt(0); |
|
||||
} |
|
||||
}, |
|
||||
saveSelection = () => { |
|
||||
selectedRange = getCurrentRange(); |
|
||||
}, |
|
||||
restoreSelection = () => { |
|
||||
var selection = window.getSelection(); |
|
||||
if (selectedRange) { |
|
||||
try { |
|
||||
selection.removeAllRanges(); |
|
||||
} catch (ex) { |
|
||||
document.body.createTextRange().select(); |
|
||||
document.selection.empty(); |
|
||||
} |
|
||||
|
|
||||
selection.addRange(selectedRange); |
|
||||
} |
|
||||
}, |
|
||||
insertFiles = files => { |
|
||||
editor.focus(); |
|
||||
$.each(files, (idx, fileInfo) => { |
|
||||
if (/^image\//.test(fileInfo.type)) { |
|
||||
$.when(readFileIntoDataUrl(fileInfo)).done(dataUrl => { |
|
||||
execCommand('insertimage', dataUrl); |
|
||||
}).fail(e => { |
|
||||
options.fileUploadError("file-reader", e); |
|
||||
}); |
|
||||
} else { |
|
||||
options.fileUploadError("unsupported-file-type", fileInfo.type); |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
markSelection = (input, color) => { |
|
||||
restoreSelection(); |
|
||||
if (document.queryCommandSupported('hiliteColor')) { |
|
||||
document.execCommand('hiliteColor', 0, color || 'transparent'); |
|
||||
} |
|
||||
saveSelection(); |
|
||||
input.data(options.selectionMarker, color); |
|
||||
}, |
|
||||
bindToolbar = (toolbar, options) => { |
|
||||
toolbar.find(toolbarBtnSelector).unbind().click(function () { |
|
||||
restoreSelection(); |
|
||||
//editor.focus(); // cause defocus on selects
|
|
||||
var doc = editor.get(0).ownerDocument; |
|
||||
var el = $(this); |
|
||||
var comm = el.data(options.commandRole); |
|
||||
var args = el.data('args'); |
|
||||
if(args){ |
|
||||
args = args.replace('${content}', doc.getSelection()); |
|
||||
execCommand(comm, args); |
|
||||
}else{ |
|
||||
doc.execCommand(comm); |
|
||||
} |
|
||||
saveSelection(); |
|
||||
}); |
|
||||
toolbar.find('[data-toggle=dropdown]').click(restoreSelection); |
|
||||
var dName = '[data-' + options.commandRole + ']'; |
|
||||
toolbar.find('select'+dName).on('webkitspeechchange change', function(){ |
|
||||
var newValue = this.value; |
|
||||
restoreSelection(); |
|
||||
if (newValue) { |
|
||||
editor.focus(); |
|
||||
execCommand($(this).data(options.commandRole), newValue); |
|
||||
} |
|
||||
saveSelection(); |
|
||||
}); |
|
||||
toolbar.find('input[type=text]'+dName,', select'+dName).on('webkitspeechchange change', function () { |
|
||||
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */ |
|
||||
this.value = ''; |
|
||||
restoreSelection(); |
|
||||
if (newValue) { |
|
||||
editor.focus(); |
|
||||
execCommand($(this).data(options.commandRole), newValue); |
|
||||
} |
|
||||
saveSelection(); |
|
||||
}).on('focus', function () { |
|
||||
var input = $(this); |
|
||||
if (!input.data(options.selectionMarker)) { |
|
||||
markSelection(input, options.selectionColor); |
|
||||
input.focus(); |
|
||||
} |
|
||||
}).on('blur', function () { |
|
||||
var input = $(this); |
|
||||
if (input.data(options.selectionMarker)) { |
|
||||
markSelection(input, false); |
|
||||
} |
|
||||
}); |
|
||||
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () { |
|
||||
restoreSelection(); |
|
||||
if (this.type === 'file' && this.files && this.files.length > 0) { |
|
||||
insertFiles(this.files); |
|
||||
} |
|
||||
saveSelection(); |
|
||||
this.value = ''; |
|
||||
}); |
|
||||
}, |
|
||||
initFileDrops = () => { |
|
||||
editor.on('dragenter dragover', false) |
|
||||
.on('drop', e => { |
|
||||
var dataTransfer = e.originalEvent.dataTransfer; |
|
||||
e.stopPropagation(); |
|
||||
e.preventDefault(); |
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { |
|
||||
insertFiles(dataTransfer.files); |
|
||||
} |
|
||||
}); |
|
||||
}; |
|
||||
/** Disable the editor |
|
||||
* @date 2015-03-19 */ |
|
||||
if(typeof userOptions=='string' && userOptions=='destroy'){ |
|
||||
editor.attr('contenteditable', false).unbind('mouseup keyup mouseout dragenter dragover'); |
|
||||
$(window).unbind('touchend'); |
|
||||
return this; |
|
||||
} |
|
||||
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions); |
|
||||
var dName = '[data-' + options.commandRole + ']'; |
|
||||
toolbarBtnSelector = 'a'+dName+',button'+dName+',input[type=button]'+dName+', select'+dName; |
|
||||
//bindHotkeys(options.hotKeys);
|
|
||||
if (options.dragAndDropImages) { |
|
||||
initFileDrops(); |
|
||||
} |
|
||||
bindToolbar($(options.toolbarSelector), options); |
|
||||
editor.attr('contenteditable', true).on('mouseup keyup mouseout', () => { |
|
||||
saveSelection(); |
|
||||
updateToolbar(); |
|
||||
}); |
|
||||
$(window).bind('touchend', e => { |
|
||||
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0), |
|
||||
currentRange = getCurrentRange(), |
|
||||
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset); |
|
||||
if (!clear || isInside) { |
|
||||
saveSelection(); |
|
||||
updateToolbar(); |
|
||||
} |
|
||||
}); |
|
||||
return this; |
|
||||
}; |
|
||||
$.fn.wysiwyg.defaults = { |
|
||||
/* |
|
||||
hotKeys: { |
|
||||
'ctrl+b meta+b': 'bold', |
|
||||
'ctrl+i meta+i': 'italic', |
|
||||
'ctrl+u meta+u': 'underline', |
|
||||
'ctrl+z meta+z': 'undo', |
|
||||
'ctrl+y meta+y meta+shift+z': 'redo', |
|
||||
'ctrl+l meta+l': 'justifyleft', |
|
||||
'ctrl+r meta+r': 'justifyright', |
|
||||
'ctrl+e meta+e': 'justifycenter', |
|
||||
'ctrl+j meta+j': 'justifyfull', |
|
||||
'shift+tab': 'outdent', |
|
||||
'tab': 'indent' |
|
||||
}, |
|
||||
*/ |
|
||||
toolbarSelector: '[data-role=editor-toolbar]', |
|
||||
commandRole: 'edit', |
|
||||
activeToolbarClass: 'btn-info', |
|
||||
selectionMarker: 'edit-focus-marker', |
|
||||
selectionColor: 'darkgrey', |
|
||||
dragAndDropImages: true, |
|
||||
fileUploadError(reason, detail) { console.log("File upload error", reason, detail); } |
|
||||
}; |
|
||||
|
|
||||
module.exports = $; |
|
||||
@ -0,0 +1,9 @@ |
|||||
|
const Property = require('./PropertyInteger'); |
||||
|
|
||||
|
module.exports = Property.extend({ |
||||
|
|
||||
|
defaults: Object.assign({}, Property.prototype.defaults, { |
||||
|
showInput: 1, |
||||
|
}), |
||||
|
|
||||
|
}); |
||||
@ -1,6 +1,5 @@ |
|||||
var Backbone = require('backbone'); |
const Sector = require('./Sector'); |
||||
var Sector = require('./Sector'); |
|
||||
|
|
||||
module.exports = Backbone.Collection.extend({ |
module.exports = require('backbone').Collection.extend({ |
||||
model: Sector, |
model: Sector, |
||||
}); |
}); |
||||
|
|||||
@ -1,31 +1,27 @@ |
|||||
var Backbone = require('backbone'); |
const InputColor = require('domain_abstract/ui/InputColor'); |
||||
var PropertyView = require('./PropertyView'); |
|
||||
var InputColor = require('domain_abstract/ui/InputColor'); |
|
||||
|
|
||||
module.exports = PropertyView.extend({ |
module.exports = require('./PropertyIntegerView').extend({ |
||||
|
|
||||
initialize(options) { |
setValue(value, opts = {}) { |
||||
PropertyView.prototype.initialize.apply(this, arguments); |
opts = Object.assign({}, opts, {silent: 1}); |
||||
this.className += ` ${this.pfx}file`; |
this.inputInst.setValue(value, opts); |
||||
}, |
}, |
||||
|
|
||||
renderInput() { |
onRender() { |
||||
if (!this.input) { |
if (!this.input) { |
||||
var inputColor = new InputColor({ |
const ppfx = this.ppfx; |
||||
|
const inputColor = new InputColor({ |
||||
target: this.target, |
target: this.target, |
||||
model: this.model, |
model: this.model, |
||||
ppfx: this.ppfx |
ppfx |
||||
}); |
}); |
||||
this.input = inputColor.render(); |
const input = inputColor.render(); |
||||
this.$el.append(this.input.$el); |
this.el.querySelector(`.${ppfx}fields`).appendChild(input.el); |
||||
this.$input = this.input.inputEl; |
this.$input = input.inputEl; |
||||
this.$color = this.input.colorEl; |
this.$color = input.colorEl; |
||||
|
this.input = this.$input.get(0); |
||||
|
this.inputInst = input; |
||||
} |
} |
||||
this.setValue(this.componentValue); |
|
||||
}, |
|
||||
|
|
||||
setValue(value) { |
|
||||
this.input.setValue(value, {silent: 1}); |
|
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
|
|||||
@ -1,30 +1,39 @@ |
|||||
var PropertyView = require('./PropertyView'); |
const InputNumber = require('domain_abstract/ui/InputNumber'); |
||||
var InputNumber = require('domain_abstract/ui/InputNumber'); |
const $ = Backbone.$; |
||||
|
|
||||
module.exports = PropertyView.extend({ |
module.exports = require('./PropertyView').extend({ |
||||
|
|
||||
initialize(options) { |
templateInput() { |
||||
PropertyView.prototype.initialize.apply(this, arguments); |
return ''; |
||||
this.listenTo(this.model, 'change:unit', this.valueChanged); |
|
||||
this.listenTo(this.model, 'el:change', this.elementUpdated); |
|
||||
}, |
}, |
||||
|
|
||||
renderInput() { |
init() { |
||||
|
const model = this.model; |
||||
|
this.listenTo(model, 'change:unit', this.modelValueChanged); |
||||
|
this.listenTo(model, 'el:change', this.elementUpdated); |
||||
|
}, |
||||
|
|
||||
|
setValue(value) { |
||||
|
this.inputInst.setValue(value, {silent: 1}); |
||||
|
}, |
||||
|
|
||||
|
onRender() { |
||||
|
const ppfx = this.ppfx; |
||||
|
|
||||
if (!this.input) { |
if (!this.input) { |
||||
var inputNumber = new InputNumber({ |
const inputNumber = new InputNumber({ |
||||
model: this.model, |
model: this.model, |
||||
ppfx: this.ppfx |
ppfx: this.ppfx |
||||
}); |
}); |
||||
this.input = inputNumber.render(); |
const input = inputNumber.render(); |
||||
this.$el.append(this.input.$el); |
const fields = this.el.querySelector(`.${ppfx}fields`); |
||||
this.$input = this.input.inputEl; |
fields.appendChild(input.el); |
||||
this.$unit = this.input.unitEl; |
this.$input = input.inputEl; |
||||
|
this.unit = input.unitEl; |
||||
|
this.$unit = $(this.unit); |
||||
|
this.input = this.$input.get(0); |
||||
|
this.inputInst = input; |
||||
} |
} |
||||
this.setValue(this.componentValue); |
|
||||
}, |
|
||||
|
|
||||
setValue(value) { |
|
||||
this.input.setValue(value, {silent: 1}); |
|
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
|
|||||
@ -1,74 +1,69 @@ |
|||||
var Backbone = require('backbone'); |
module.exports = require('./PropertyView').extend({ |
||||
var PropertyView = require('./PropertyView'); |
|
||||
|
|
||||
module.exports = PropertyView.extend({ |
templateInput() { |
||||
|
|
||||
templateField() { |
|
||||
const pfx = this.pfx; |
const pfx = this.pfx; |
||||
const ppfx = this.ppfx; |
const ppfx = this.ppfx; |
||||
return ` |
return ` |
||||
<div class="${ppfx}field ${ppfx}field-radio"> |
<div class="${ppfx}field ${ppfx}field-radio"> |
||||
<span id="${pfx}input-holder"></span> |
<span id="${pfx}input-holder"></span> |
||||
</div> |
</div> |
||||
<div style="clear:both"></div> |
|
||||
`;
|
`;
|
||||
}, |
}, |
||||
|
|
||||
initialize(options) { |
onRender() { |
||||
PropertyView.prototype.initialize.apply(this, arguments); |
const pfx = this.pfx; |
||||
|
const ppfx = this.ppfx; |
||||
|
const itemCls = `${ppfx}radio-item-label`; |
||||
const model = this.model; |
const model = this.model; |
||||
this.list = model.get('list') || model.get('options') || []; |
const prop = model.get('property'); |
||||
this.className = this.className + ' '+ this.pfx +'list'; |
const options = model.get('list') || model.get('options') || []; |
||||
}, |
|
||||
|
|
||||
/** @inheritdoc */ |
if (!this.input) { |
||||
renderInput() { |
if(options && options.length) { |
||||
var pfx = this.pfx; |
let inputStr = ''; |
||||
var ppfx = this.ppfx; |
|
||||
var itemCls = ppfx + 'radio-item-label'; |
|
||||
var prop = this.property; |
|
||||
|
|
||||
if(!this.$input) { |
options.forEach(el => { |
||||
if(this.list && this.list.length) { |
let cl = el.className ? `${el.className} ${pfx}icon ${itemCls}` : ''; |
||||
var input = ''; |
let id = `${prop}-${el.value}`; |
||||
_.each(this.list, el => { |
let labelTxt = el.name || el.value; |
||||
var cl = el.className ? el.className + ' ' + pfx + 'icon ' + itemCls : '', |
let titleAttr = el.title ? `title="${el.title}"` : ''; |
||||
id = prop + '-' + el.value, |
inputStr += ` |
||||
labelTxt = el.name ? el.name : el.value; |
<div class="${ppfx}radio-item"> |
||||
var titleAttr = el.title ? 'title="' + el.title + '"': ''; |
<input type="radio" class="${pfx}radio" id="${id}" name="${prop}" value="${el.value}"/> |
||||
input += '<div class="' + ppfx + 'radio-item">'+ |
<label class="${cl || itemCls}" ${titleAttr} for="${id}">${cl ? '' : labelTxt}</label> |
||||
'<input class="'+pfx+'radio" type="radio" id="'+ id +'" name="'+prop+'" value="'+el.value+'" />'+ |
</div> |
||||
'<label class="'+(cl ? cl : itemCls)+'" ' + titleAttr + ' for="'+ id +'">' + (cl ? '' : labelTxt) + '</label></div>'; |
`;
|
||||
}); |
}); |
||||
this.input = input; |
|
||||
this.$inputEl = $(this.input); |
const inputHld = this.el.querySelector(`#${pfx}input-holder`); |
||||
this.$el.find('#'+ pfx +'input-holder').html(this.$inputEl); |
inputHld.innerHTML = `<div>${inputStr}</div>`; |
||||
this.$input = this.$inputEl.find('input[name="'+this.property+'"]'); |
this.input = inputHld.firstChild; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
this.setValue(this.componentValue); |
|
||||
}, |
}, |
||||
|
|
||||
/** |
|
||||
* Returns value from input |
|
||||
* @return {string} |
|
||||
*/ |
|
||||
getInputValue() { |
getInputValue() { |
||||
return this.$input ? this.$el.find('input:checked').val() : ''; |
const inputChk = this.getCheckedEl(); |
||||
|
return inputChk ? inputChk.value : ''; |
||||
}, |
}, |
||||
|
|
||||
/** @inheritdoc */ |
getCheckedEl() { |
||||
setValue(value) { |
const input = this.getInputEl(); |
||||
var v = this.model.get('value') || this.model.getDefaultValue(); |
return input ? input.querySelector('input:checked') : ''; |
||||
|
}, |
||||
if(value) |
|
||||
v = value; |
|
||||
|
|
||||
if(this.$input) |
setValue(value) { |
||||
this.$input.filter('[value="'+v+'"]').prop('checked', true); |
const model = this.model; |
||||
|
let val = value || model.get('value') || model.getDefaultValue(); |
||||
|
const input = this.getInputEl(); |
||||
|
const inputIn = input ? input.querySelector(`[value="${val}"]`) : ''; |
||||
|
|
||||
this.model.set({value: v},{silent: true}); |
if (inputIn) { |
||||
|
inputIn.checked = true; |
||||
|
} else { |
||||
|
const inputChk = this.getCheckedEl(); |
||||
|
inputChk && (inputChk.checked = false); |
||||
|
} |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
|
|||||
@ -0,0 +1,59 @@ |
|||||
|
const InputNumber = require('domain_abstract/ui/InputNumber'); |
||||
|
const Property = require('./PropertyIntegerView'); |
||||
|
|
||||
|
module.exports = Property.extend({ |
||||
|
|
||||
|
events: { |
||||
|
'change': 'inputValueChanged', |
||||
|
'input': 'inputValueChangedSoft', |
||||
|
}, |
||||
|
|
||||
|
templateInput(model) { |
||||
|
const ppfx = this.ppfx; |
||||
|
return ` |
||||
|
<div class="${ppfx}field ${ppfx}field-range"> |
||||
|
<input type="range" |
||||
|
min="${model.get('min')}" |
||||
|
max="${model.get('max')}" |
||||
|
step="${model.get('step')}"/> |
||||
|
</div> |
||||
|
`;
|
||||
|
}, |
||||
|
|
||||
|
getSliderEl() { |
||||
|
if (!this.slider) { |
||||
|
this.slider = this.el.querySelector('input[type=range]'); |
||||
|
} |
||||
|
|
||||
|
return this.slider; |
||||
|
}, |
||||
|
|
||||
|
inputValueChanged() { |
||||
|
const model = this.model; |
||||
|
const step = model.get('step'); |
||||
|
this.getInputEl().value = this.getSliderEl().value; |
||||
|
const value = this.getInputValue() - step; |
||||
|
model.set('value', value, {avoidStore: 1}).set('value', value + step); |
||||
|
this.elementUpdated(); |
||||
|
}, |
||||
|
|
||||
|
inputValueChangedSoft() { |
||||
|
this.getInputEl().value = this.getSliderEl().value; |
||||
|
this.model.set('value', this.getInputValue(), {avoidStore: 1}); |
||||
|
this.elementUpdated(); |
||||
|
}, |
||||
|
|
||||
|
setValue(value) { |
||||
|
this.getSliderEl().value = value; |
||||
|
this.inputInst.setValue(value, {silent: 1}); |
||||
|
}, |
||||
|
|
||||
|
onRender() { |
||||
|
Property.prototype.onRender.apply(this, arguments); |
||||
|
const model = this.model; |
||||
|
|
||||
|
if (!model.get('showInput')) { |
||||
|
this.inputInst.el.style.display = 'none'; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,41 @@ |
|||||
|
.#{$rte-prefix} { |
||||
|
&toolbar { |
||||
|
@extend .#{$app-prefix}bg-main; |
||||
|
@extend .#{$app-prefix}no-user-select; |
||||
|
|
||||
|
border: 1px solid $mainDkColor; |
||||
|
position: absolute; |
||||
|
border-radius: 3px; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
&actionbar { |
||||
|
display: flex; |
||||
|
} |
||||
|
|
||||
|
&action { |
||||
|
@extend .#{$app-prefix}color-main; |
||||
|
|
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 5px; |
||||
|
min-width: 25px; |
||||
|
border-right: 1px solid $mainDkColor; |
||||
|
text-align: center; |
||||
|
cursor: pointer; |
||||
|
outline: none; |
||||
|
|
||||
|
&:last-child { |
||||
|
border-right: none; |
||||
|
} |
||||
|
|
||||
|
&:hover { |
||||
|
background-color: $mainLhColor; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&active { |
||||
|
background-color: $mainDkColor; |
||||
|
} |
||||
|
} |
||||
@ -1,78 +1,76 @@ |
|||||
|
|
||||
|
|
||||
/* Class names prefixes */ |
/* Class names prefixes */ |
||||
|
|
||||
$app-prefix: 'gjs-' !default; |
$app-prefix: 'gjs-' !default; |
||||
$nv-prefix: $app-prefix + 'nv-' !default; |
$nv-prefix: $app-prefix + 'nv-' !default; |
||||
$rte-prefix: $app-prefix + 'rte-' !default; |
$rte-prefix: $app-prefix + 'rte-' !default; |
||||
$comp-prefix: $app-prefix + 'comp-' !default; |
$comp-prefix: $app-prefix + 'comp-' !default; |
||||
$mdl-prefix: $app-prefix + 'mdl-' !default; |
$mdl-prefix: $app-prefix + 'mdl-' !default; |
||||
$am-prefix: $app-prefix + 'am-' !default; |
$am-prefix: $app-prefix + 'am-' !default; |
||||
$cm-prefix: $app-prefix + 'cm-' !default; |
$cm-prefix: $app-prefix + 'cm-' !default; |
||||
$pn-prefix: $app-prefix + 'pn-' !default; |
$pn-prefix: $app-prefix + 'pn-' !default; |
||||
$com-prefix: $app-prefix + 'com-' !default; |
$com-prefix: $app-prefix + 'com-' !default; |
||||
$sm-prefix: $app-prefix + 'sm-' !default; |
$sm-prefix: $app-prefix + 'sm-' !default; |
||||
$cv-prefix: $app-prefix + 'cv-' !default; |
$cv-prefix: $app-prefix + 'cv-' !default; |
||||
$clm-prefix: $app-prefix + 'clm-' !default; |
$clm-prefix: $app-prefix + 'clm-' !default; |
||||
$trt-prefix: $app-prefix + 'trt-' !default; |
$trt-prefix: $app-prefix + 'trt-' !default; |
||||
|
|
||||
|
|
||||
/* Colors / Theme */ |
/* Colors / Theme */ |
||||
|
|
||||
|
|
||||
/* Dark theme */ |
/* Dark theme */ |
||||
$mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-gradient(top, #fca99b 0%, #6e2842 100%) */ |
$mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-gradient(top, #fca99b 0%, #6e2842 100%) */ |
||||
$fontColor: #ddd !default; /* l: #d8d7db */ |
$fontColor: #ddd !default; /* l: #d8d7db */ |
||||
$fontColorActive: #f8f8f8 !default; |
$fontColorActive: #f8f8f8 !default; |
||||
|
|
||||
/* Light theme |
/* Light theme |
||||
$mainColor: #fff; |
$mainColor: #fff; |
||||
$fontColor: #9299a3; |
$fontColor: #9299a3; |
||||
$fontColorActive: #4f8ef7; |
$fontColorActive: #4f8ef7; |
||||
*/ |
*/ |
||||
|
|
||||
$mainDkColor: rgba(0, 0, 0, 0.3) !default;/* darken($mainColor, 4%) - #383838 */ |
$mainDkColor: rgba(0, 0, 0, 0.2) !default;/* darken($mainColor, 4%) - #383838 */ |
||||
$mainDklColor: rgba(0, 0, 0, 0.1) !default; |
$mainDklColor: rgba(0, 0, 0, 0.1) !default; |
||||
$mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */ |
$mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */ |
||||
$mainLhlColor: rgba(255, 255, 255, 0.7) !default; |
$mainLhlColor: rgba(255, 255, 255, 0.7) !default; |
||||
$fontColorDk: #777 !default; |
$fontColorDk: #777 !default; |
||||
$mainFont: Helvetica, sans-serif !default; |
$mainFont: Helvetica, sans-serif !default; |
||||
$colorBlue: #3b97e3 !default; |
$colorBlue: #3b97e3 !default; |
||||
$colorRed: #dd3636 !default; |
$colorRed: #dd3636 !default; |
||||
$colorYell: #ffca6f !default; |
$colorYell: #ffca6f !default; |
||||
$colorGreen: #62c462 !default; |
$colorGreen: #62c462 !default; |
||||
$tagBg: #804f7b !default; |
$tagBg: #804f7b !default; |
||||
$secColor: $tagBg !default; |
$secColor: $tagBg !default; |
||||
$imageCompDim: 50px !default; |
$imageCompDim: 50px !default; |
||||
$leftWidth: 15% !default; |
$leftWidth: 15% !default; |
||||
|
|
||||
/* Color Helpers */ |
/* Color Helpers */ |
||||
$colorHighlight: #71b7f1 !default; |
$colorHighlight: #71b7f1 !default; |
||||
$colorWarn: #ffca6f !default; |
$colorWarn: #ffca6f !default; |
||||
|
|
||||
/* Canvas */ |
/* Canvas */ |
||||
$hndlMargin: -5px !default; |
$hndlMargin: -5px !default; |
||||
|
|
||||
/* Components / Inputs */ |
/* Components / Inputs */ |
||||
$lightBorder: rgba(255, 255, 255, 0.05) !default; |
$lightBorder: rgba(255, 255, 255, 0.05) !default; |
||||
$inputFontColor: $mainLhlColor !default; /* #d5d5d5 */ |
$inputFontColor: $mainLhlColor !default; /* #d5d5d5 */ |
||||
$arrowColor: $mainLhlColor !default; /* b1b1b1 */ |
$arrowColor: $mainLhlColor !default; /* b1b1b1 */ |
||||
$darkTextShadow: $mainDkColor !default; /* #252525 */ |
$darkTextShadow: $mainDkColor !default; /* #252525 */ |
||||
$darkBorder: rgba(0, 0, 0, 0.15) !default; /* 303030 */ |
$darkBorder: rgba(0, 0, 0, 0.15) !default; /* 303030 */ |
||||
$colorpSize: 22px !default; |
$colorpSize: 22px !default; |
||||
$inputPadding: 5px !default; // Has to be a single value |
$inputPadding: 5px !default; // Has to be a single value |
||||
|
|
||||
/* Class manager */ |
/* Class manager */ |
||||
$addBtnBg: lighten($mainDkColor, 10%) !default; |
$addBtnBg: lighten($mainDkColor, 10%) !default; |
||||
$paddElClm: 5px 6px !default; |
$paddElClm: 5px 6px !default; |
||||
|
|
||||
/* File uploader */ |
/* File uploader */ |
||||
$uploadPadding: 150px 10px !default; |
$uploadPadding: 150px 10px !default; |
||||
|
|
||||
/* Commands */ |
/* Commands */ |
||||
$animSpeed: 0.2s !default; |
$animSpeed: 0.2s !default; |
||||
|
|
||||
/* Fonts */ |
/* Fonts */ |
||||
$fontPath: '../fonts' !default; |
$fontPath: '../fonts' !default; |
||||
$fontName: 'main-fonts' !default; |
$fontName: 'main-fonts' !default; |
||||
$fontV: 20 !default;//random(1000) |
$fontV: 20 !default;//random(1000) |
||||
|
|||||
File diff suppressed because it is too large
@ -0,0 +1,309 @@ |
|||||
|
module.exports = ({$, Backbone}) => { |
||||
|
if (Backbone) { |
||||
|
const ViewProt = Backbone.View.prototype; |
||||
|
const eventNsMap = {}; |
||||
|
ViewProt.eventNsMap = eventNsMap; |
||||
|
|
||||
|
ViewProt.delegate = function(eventName, selector, listener) { |
||||
|
const vid = '.delegateEvents' + this.cid; |
||||
|
this.$el.on(eventName, selector, listener); |
||||
|
//return this;
|
||||
|
let eventMap = eventNsMap[vid]; |
||||
|
|
||||
|
if (!eventMap) { |
||||
|
eventMap = []; |
||||
|
eventNsMap[vid] = eventMap; |
||||
|
} |
||||
|
|
||||
|
eventMap.push({eventName, selector, listener}); |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
ViewProt.undelegateEvents = function() { |
||||
|
const vid = '.delegateEvents' + this.cid; |
||||
|
if (this.$el) { |
||||
|
//this.$el.off(); return this;
|
||||
|
let eventMap = eventNsMap[vid]; |
||||
|
|
||||
|
if (eventMap) { |
||||
|
eventMap.forEach(({eventName, selector, listener}) => { |
||||
|
this.$el.off(eventName); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
ViewProt.undelegate = function(ev, sel, list) { |
||||
|
const vid = '.delegateEvents' + this.cid; |
||||
|
//this.$el.off(ev, sel, list); return this;
|
||||
|
let eventMap = eventNsMap[vid]; |
||||
|
|
||||
|
if (eventMap) { |
||||
|
eventMap.forEach(({eventName, selector, listener}) => { |
||||
|
if (eventName == ev && selector == sel) { |
||||
|
this.$el.off(eventName); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
if ($) { |
||||
|
const fn = $.fn; |
||||
|
|
||||
|
const splitNamespace = function(name) { |
||||
|
const namespaceArray = name.split('.') |
||||
|
return ( name.indexOf('.') !== 0 ? [namespaceArray[0], namespaceArray.slice(1)] : [null, namespaceArray] ); |
||||
|
} |
||||
|
/* |
||||
|
const CashEvent = function(node, eventName, namespaces, delegate, originalCallback, runOnce) { |
||||
|
|
||||
|
const eventCache = getData(node,'_cashEvents') || setData(node, '_cashEvents', {}); |
||||
|
const remove = function(c, namespace){ |
||||
|
if ( c && originalCallback !== c ) { return; } |
||||
|
if ( namespace && this.namespaces.indexOf(namespace) < 0 ) { return; } |
||||
|
node.removeEventListener(eventName, callback); |
||||
|
}; |
||||
|
const callback = function(e) { |
||||
|
var t = this; |
||||
|
if (delegate) { |
||||
|
t = e.target; |
||||
|
|
||||
|
while (t && !matches(t, delegate)) { |
||||
|
if (t === this) { |
||||
|
return (t = false); |
||||
|
} |
||||
|
t = t.parentNode; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (t) { |
||||
|
originalCallback.call(t, e, e.data); |
||||
|
if ( runOnce ) { remove(); } |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
this.remove = remove; |
||||
|
this.namespaces = namespaces; |
||||
|
|
||||
|
node.addEventListener(eventName, callback); |
||||
|
|
||||
|
eventCache[eventName] = eventCache[eventName] || []; |
||||
|
eventCache[eventName].push(this); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
*/ |
||||
|
|
||||
|
const on = $.prototype.on; |
||||
|
const off = $.prototype.off; |
||||
|
const trigger = $.prototype.trigger; |
||||
|
const offset = $.prototype.offset; |
||||
|
const getEvents = (eventName) => eventName.split(/[,\s]+/g); |
||||
|
const getNamespaces = (eventName) => eventName.split('.'); |
||||
|
|
||||
|
fn.on = function(eventName, delegate, callback, runOnce) { |
||||
|
|
||||
|
if (typeof eventName == 'string') { |
||||
|
const events = getEvents(eventName); |
||||
|
|
||||
|
if (events.length == 1) { |
||||
|
eventName = events[0]; |
||||
|
let namespaces = getNamespaces(eventName); |
||||
|
|
||||
|
if (eventName.indexOf('.') !== 0) { |
||||
|
eventName = namespaces[0]; |
||||
|
} |
||||
|
|
||||
|
namespaces = namespaces.slice(1); |
||||
|
|
||||
|
if (namespaces.length) { |
||||
|
//console.log('Found event with namespaces', namespaces, eventName, delegate, this);
|
||||
|
const cashNs = this.data('_cashNs') || []; |
||||
|
// cashNs[namespace]
|
||||
|
this.data('_cashNs', namespaces); // for each ns need to store '.store' => eventName, delegate, callback
|
||||
|
} |
||||
|
|
||||
|
return on.call(this, eventName, delegate, callback, runOnce); |
||||
|
} else { |
||||
|
events.forEach((eventName) => |
||||
|
this.on(eventName, delegate, callback, runOnce)); |
||||
|
return this; |
||||
|
} |
||||
|
} else { |
||||
|
return on.call(this, eventName, delegate, callback, runOnce) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn.off = function(eventName, callback) { |
||||
|
if (typeof eventName == 'string') { |
||||
|
const events = getEvents(eventName); |
||||
|
|
||||
|
if (events.length == 1) { |
||||
|
eventName = events[0]; |
||||
|
let namespaces = getNamespaces(eventName); |
||||
|
|
||||
|
if (eventName.indexOf('.') !== 0) { |
||||
|
eventName = namespaces[0]; |
||||
|
} |
||||
|
|
||||
|
namespaces = namespaces.slice(1); |
||||
|
|
||||
|
if (namespaces.length) { |
||||
|
// Have to off only with the same namespace
|
||||
|
} |
||||
|
|
||||
|
return off.call(this, eventName, callback); |
||||
|
} else { |
||||
|
events.forEach((eventName) => this.off(eventName, callback)); |
||||
|
return this; |
||||
|
} |
||||
|
} else { |
||||
|
return off.call(this, eventName, callback); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn.trigger = function(eventName, data) { |
||||
|
if (eventName instanceof $.Event) { |
||||
|
return this.trigger(eventName.type, data); |
||||
|
} |
||||
|
|
||||
|
if (typeof eventName == 'string') { |
||||
|
const events = getEvents(eventName); |
||||
|
|
||||
|
if (events.length == 1) { |
||||
|
eventName = events[0]; |
||||
|
let namespaces = getNamespaces(eventName); |
||||
|
|
||||
|
if (eventName.indexOf('.') !== 0) { |
||||
|
eventName = namespaces[0]; |
||||
|
} |
||||
|
|
||||
|
namespaces = namespaces.slice(1); |
||||
|
|
||||
|
if (namespaces.length) { |
||||
|
// have to trigger with same namespaces and eventName
|
||||
|
} |
||||
|
|
||||
|
return trigger.call(this, eventName, data); |
||||
|
} else { |
||||
|
events.forEach((eventName) => this.trigger(eventName, data)); |
||||
|
return this; |
||||
|
} |
||||
|
} else { |
||||
|
return trigger.call(this, eventName, data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fn.hide = function() { |
||||
|
return this.css('display', 'none'); |
||||
|
} |
||||
|
|
||||
|
fn.show = function() { |
||||
|
return this.css('display', 'block'); |
||||
|
} |
||||
|
|
||||
|
fn.focus = function() { |
||||
|
const el = this.get(0); |
||||
|
el && el.focus(); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
fn.remove = function () { |
||||
|
return this.each(node => { |
||||
|
return node.parentNode && node.parentNode.removeChild(node); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// For spectrum compatibility
|
||||
|
fn.bind = function(ev, h) { |
||||
|
return this.on(ev, h); |
||||
|
} |
||||
|
|
||||
|
fn.unbind = function(ev, h) { |
||||
|
return this.off(ev, h); |
||||
|
} |
||||
|
|
||||
|
fn.click = function(h) { |
||||
|
return h ? this.on('click', h) : this.trigger('click'); |
||||
|
} |
||||
|
|
||||
|
fn.change = function(h) { |
||||
|
return h ? this.on('change', h) : this.trigger('change'); |
||||
|
} |
||||
|
|
||||
|
fn.keydown = function(h) { |
||||
|
return h ? this.on('keydown', h) : this.trigger('keydown'); |
||||
|
} |
||||
|
|
||||
|
fn.delegate = function(selector, events, data, handler) { |
||||
|
if (!handler) { |
||||
|
handler = data; |
||||
|
} |
||||
|
|
||||
|
return this.on(events, selector, function(e) { |
||||
|
e.data = data; |
||||
|
handler(e); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
fn.scrollLeft = function() { |
||||
|
let el = this.get(0); |
||||
|
el = el.nodeType == 9 ? el.defaultView : el; |
||||
|
let win = el instanceof Window ? el : null; |
||||
|
return win ? win.pageXOffset : el.scrollLeft || 0; |
||||
|
} |
||||
|
|
||||
|
fn.scrollTop = function() { |
||||
|
let el = this.get(0); |
||||
|
el = el.nodeType == 9 ? el.defaultView : el; |
||||
|
let win = el instanceof Window ? el : null; |
||||
|
return win ? win.pageYOffset : el.scrollTop || 0; |
||||
|
} |
||||
|
|
||||
|
fn.offset = function(coords) { |
||||
|
let top, left; |
||||
|
|
||||
|
if (coords) { |
||||
|
top = coords.top; |
||||
|
left = coords.left; |
||||
|
} |
||||
|
|
||||
|
if (typeof top != 'undefined') { |
||||
|
this.css('top', `${top}px`); |
||||
|
} |
||||
|
if (typeof left != 'undefined') { |
||||
|
this.css('left', `${left}px`); |
||||
|
} |
||||
|
|
||||
|
return offset.call(this); |
||||
|
}; |
||||
|
|
||||
|
$.map = function(items, clb) { |
||||
|
const ar = []; |
||||
|
|
||||
|
for (var i = 0; i < items.length; i++) { |
||||
|
ar.push(clb(items[i], i)); |
||||
|
} |
||||
|
|
||||
|
return ar; |
||||
|
} |
||||
|
|
||||
|
$.inArray = function(val, arr) { |
||||
|
return arr.indexOf(val); |
||||
|
} |
||||
|
|
||||
|
$.Event = function(src, props) { |
||||
|
if (!(this instanceof $.Event) ) { |
||||
|
return new $.Event(src, props); |
||||
|
} |
||||
|
|
||||
|
this.type = src; |
||||
|
this.isDefaultPrevented = () => false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
const on = (el, ev, fn) => { |
||||
|
ev = ev.split(/\s+/); |
||||
|
el = el instanceof Array ? el : [el]; |
||||
|
|
||||
|
for (let i = 0; i < ev.length; ++i) { |
||||
|
el.forEach(elem => elem.addEventListener(ev[i], fn)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const off = (el, ev, fn) => { |
||||
|
ev = ev.split(/\s+/); |
||||
|
el = el instanceof Array ? el : [el]; |
||||
|
|
||||
|
for (let i = 0; i < ev.length; ++i) { |
||||
|
el.forEach(elem => elem.removeEventListener(ev[i], fn)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export {on, off} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue