Moved to jquery 1.11.2, moved to medium.js improved browser tests.
This commit is contained in:
parent
0fcfca12e9
commit
c5bb0f4393
16 changed files with 19927 additions and 916 deletions
|
@ -1,367 +0,0 @@
|
||||||
//@ sourceMappingURL=jquery.caret.map
|
|
||||||
/*
|
|
||||||
Implement Github like autocomplete mentions
|
|
||||||
http://ichord.github.com/At.js
|
|
||||||
|
|
||||||
Copyright (c) 2013 chord.luo@gmail.com
|
|
||||||
Licensed under the MIT license.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
本插件操作 textarea 或者 input 内的插入符
|
|
||||||
只实现了获得插入符在文本框中的位置,我设置
|
|
||||||
插入符的位置.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
(function(factory) {
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
return define(['jquery'], factory);
|
|
||||||
} else {
|
|
||||||
return factory(window.jQuery);
|
|
||||||
}
|
|
||||||
})(function($) {
|
|
||||||
"use strict";
|
|
||||||
var EditableCaret, InputCaret, Mirror, Utils, discoveryIframeOf, methods, oDocument, oFrame, oWindow, pluginName, setContextBy;
|
|
||||||
pluginName = 'caret';
|
|
||||||
EditableCaret = (function() {
|
|
||||||
function EditableCaret($inputor) {
|
|
||||||
this.$inputor = $inputor;
|
|
||||||
this.domInputor = this.$inputor[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
EditableCaret.prototype.setPos = function(pos) {
|
|
||||||
return this.domInputor;
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getIEPosition = function() {
|
|
||||||
return this.getPosition();
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getPosition = function() {
|
|
||||||
var inputor_offset, offset;
|
|
||||||
offset = this.getOffset();
|
|
||||||
inputor_offset = this.$inputor.offset();
|
|
||||||
offset.left -= inputor_offset.left;
|
|
||||||
offset.top -= inputor_offset.top;
|
|
||||||
return offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getOldIEPos = function() {
|
|
||||||
var preCaretTextRange, textRange;
|
|
||||||
textRange = oDocument.selection.createRange();
|
|
||||||
preCaretTextRange = oDocument.body.createTextRange();
|
|
||||||
preCaretTextRange.moveToElementText(this.domInputor);
|
|
||||||
preCaretTextRange.setEndPoint("EndToEnd", textRange);
|
|
||||||
return preCaretTextRange.text.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getPos = function() {
|
|
||||||
var clonedRange, pos, range;
|
|
||||||
if (range = this.range()) {
|
|
||||||
clonedRange = range.cloneRange();
|
|
||||||
clonedRange.selectNodeContents(this.domInputor);
|
|
||||||
clonedRange.setEnd(range.endContainer, range.endOffset);
|
|
||||||
pos = clonedRange.toString().length;
|
|
||||||
clonedRange.detach();
|
|
||||||
return pos;
|
|
||||||
} else if (oDocument.selection) {
|
|
||||||
return this.getOldIEPos();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getOldIEOffset = function() {
|
|
||||||
var range, rect;
|
|
||||||
range = oDocument.selection.createRange().duplicate();
|
|
||||||
range.moveStart("character", -1);
|
|
||||||
rect = range.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
height: rect.bottom - rect.top,
|
|
||||||
left: rect.left,
|
|
||||||
top: rect.top
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.getOffset = function(pos) {
|
|
||||||
var clonedRange, offset, range, rect;
|
|
||||||
if (oWindow.getSelection && (range = this.range())) {
|
|
||||||
if (range.endOffset - 1 < 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
clonedRange = range.cloneRange();
|
|
||||||
clonedRange.setStart(range.endContainer, range.endOffset - 1);
|
|
||||||
clonedRange.setEnd(range.endContainer, range.endOffset);
|
|
||||||
rect = clonedRange.getBoundingClientRect();
|
|
||||||
offset = {
|
|
||||||
height: rect.height,
|
|
||||||
left: rect.left + rect.width,
|
|
||||||
top: rect.top
|
|
||||||
};
|
|
||||||
clonedRange.detach();
|
|
||||||
} else if (oDocument.selection) {
|
|
||||||
offset = this.getOldIEOffset();
|
|
||||||
}
|
|
||||||
if (offset) {
|
|
||||||
offset.top += $(oWindow).scrollTop();
|
|
||||||
offset.left += $(oWindow).scrollLeft();
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
EditableCaret.prototype.range = function() {
|
|
||||||
var sel;
|
|
||||||
if (!oWindow.getSelection) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sel = oWindow.getSelection();
|
|
||||||
if (sel.rangeCount > 0) {
|
|
||||||
return sel.getRangeAt(0);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return EditableCaret;
|
|
||||||
|
|
||||||
})();
|
|
||||||
InputCaret = (function() {
|
|
||||||
function InputCaret($inputor) {
|
|
||||||
this.$inputor = $inputor;
|
|
||||||
this.domInputor = this.$inputor[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
InputCaret.prototype.getIEPos = function() {
|
|
||||||
var endRange, inputor, len, normalizedValue, pos, range, textInputRange;
|
|
||||||
inputor = this.domInputor;
|
|
||||||
range = oDocument.selection.createRange();
|
|
||||||
pos = 0;
|
|
||||||
if (range && range.parentElement() === inputor) {
|
|
||||||
normalizedValue = inputor.value.replace(/\r\n/g, "\n");
|
|
||||||
len = normalizedValue.length;
|
|
||||||
textInputRange = inputor.createTextRange();
|
|
||||||
textInputRange.moveToBookmark(range.getBookmark());
|
|
||||||
endRange = inputor.createTextRange();
|
|
||||||
endRange.collapse(false);
|
|
||||||
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
|
|
||||||
pos = len;
|
|
||||||
} else {
|
|
||||||
pos = -textInputRange.moveStart("character", -len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.getPos = function() {
|
|
||||||
if (oDocument.selection) {
|
|
||||||
return this.getIEPos();
|
|
||||||
} else {
|
|
||||||
return this.domInputor.selectionStart;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.setPos = function(pos) {
|
|
||||||
var inputor, range;
|
|
||||||
inputor = this.domInputor;
|
|
||||||
if (oDocument.selection) {
|
|
||||||
range = inputor.createTextRange();
|
|
||||||
range.move("character", pos);
|
|
||||||
range.select();
|
|
||||||
} else if (inputor.setSelectionRange) {
|
|
||||||
inputor.setSelectionRange(pos, pos);
|
|
||||||
}
|
|
||||||
return inputor;
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.getIEOffset = function(pos) {
|
|
||||||
var h, textRange, x, y;
|
|
||||||
textRange = this.domInputor.createTextRange();
|
|
||||||
pos || (pos = this.getPos());
|
|
||||||
textRange.move('character', pos);
|
|
||||||
x = textRange.boundingLeft;
|
|
||||||
y = textRange.boundingTop;
|
|
||||||
h = textRange.boundingHeight;
|
|
||||||
return {
|
|
||||||
left: x,
|
|
||||||
top: y,
|
|
||||||
height: h
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.getOffset = function(pos) {
|
|
||||||
var $inputor, offset, position;
|
|
||||||
$inputor = this.$inputor;
|
|
||||||
if (oDocument.selection) {
|
|
||||||
offset = this.getIEOffset(pos);
|
|
||||||
offset.top += $(oWindow).scrollTop() + $inputor.scrollTop();
|
|
||||||
offset.left += $(oWindow).scrollLeft() + $inputor.scrollLeft();
|
|
||||||
return offset;
|
|
||||||
} else {
|
|
||||||
offset = $inputor.offset();
|
|
||||||
position = this.getPosition(pos);
|
|
||||||
return offset = {
|
|
||||||
left: offset.left + position.left - $inputor.scrollLeft(),
|
|
||||||
top: offset.top + position.top - $inputor.scrollTop(),
|
|
||||||
height: position.height
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.getPosition = function(pos) {
|
|
||||||
var $inputor, at_rect, end_range, format, html, mirror, start_range;
|
|
||||||
$inputor = this.$inputor;
|
|
||||||
format = function(value) {
|
|
||||||
return $('<div></div>').text(value).html().replace(/\r\n|\r|\n/g, "<br/>").replace(/\s/g, " ");
|
|
||||||
};
|
|
||||||
if (pos === void 0) {
|
|
||||||
pos = this.getPos();
|
|
||||||
}
|
|
||||||
start_range = $inputor.val().slice(0, pos);
|
|
||||||
end_range = $inputor.val().slice(pos);
|
|
||||||
html = "<span style='position: relative; display: inline;'>" + format(start_range) + "</span>";
|
|
||||||
html += "<span id='caret' style='position: relative; display: inline;'>|</span>";
|
|
||||||
html += "<span style='position: relative; display: inline;'>" + format(end_range) + "</span>";
|
|
||||||
mirror = new Mirror($inputor);
|
|
||||||
return at_rect = mirror.create(html).rect();
|
|
||||||
};
|
|
||||||
|
|
||||||
InputCaret.prototype.getIEPosition = function(pos) {
|
|
||||||
var h, inputorOffset, offset, x, y;
|
|
||||||
offset = this.getIEOffset(pos);
|
|
||||||
inputorOffset = this.$inputor.offset();
|
|
||||||
x = offset.left - inputorOffset.left;
|
|
||||||
y = offset.top - inputorOffset.top;
|
|
||||||
h = offset.height;
|
|
||||||
return {
|
|
||||||
left: x,
|
|
||||||
top: y,
|
|
||||||
height: h
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return InputCaret;
|
|
||||||
|
|
||||||
})();
|
|
||||||
Mirror = (function() {
|
|
||||||
Mirror.prototype.css_attr = ["borderBottomWidth", "borderLeftWidth", "borderRightWidth", "borderTopStyle", "borderRightStyle", "borderBottomStyle", "borderLeftStyle", "borderTopWidth", "boxSizing", "fontFamily", "fontSize", "fontWeight", "height", "letterSpacing", "lineHeight", "marginBottom", "marginLeft", "marginRight", "marginTop", "outlineWidth", "overflow", "overflowX", "overflowY", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "textAlign", "textOverflow", "textTransform", "whiteSpace", "wordBreak", "wordWrap"];
|
|
||||||
|
|
||||||
function Mirror($inputor) {
|
|
||||||
this.$inputor = $inputor;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mirror.prototype.mirrorCss = function() {
|
|
||||||
var css,
|
|
||||||
_this = this;
|
|
||||||
css = {
|
|
||||||
position: 'absolute',
|
|
||||||
left: -9999,
|
|
||||||
top: 0,
|
|
||||||
zIndex: -20000
|
|
||||||
};
|
|
||||||
if (this.$inputor.prop('tagName') === 'TEXTAREA') {
|
|
||||||
this.css_attr.push('width');
|
|
||||||
}
|
|
||||||
$.each(this.css_attr, function(i, p) {
|
|
||||||
return css[p] = _this.$inputor.css(p);
|
|
||||||
});
|
|
||||||
return css;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mirror.prototype.create = function(html) {
|
|
||||||
this.$mirror = $('<div></div>');
|
|
||||||
this.$mirror.css(this.mirrorCss());
|
|
||||||
this.$mirror.html(html);
|
|
||||||
this.$inputor.after(this.$mirror);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mirror.prototype.rect = function() {
|
|
||||||
var $flag, pos, rect;
|
|
||||||
$flag = this.$mirror.find("#caret");
|
|
||||||
pos = $flag.position();
|
|
||||||
rect = {
|
|
||||||
left: pos.left,
|
|
||||||
top: pos.top,
|
|
||||||
height: $flag.height()
|
|
||||||
};
|
|
||||||
this.$mirror.remove();
|
|
||||||
return rect;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Mirror;
|
|
||||||
|
|
||||||
})();
|
|
||||||
Utils = {
|
|
||||||
contentEditable: function($inputor) {
|
|
||||||
return !!($inputor[0].contentEditable && $inputor[0].contentEditable === 'true');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
methods = {
|
|
||||||
pos: function(pos) {
|
|
||||||
if (pos || pos === 0) {
|
|
||||||
return this.setPos(pos);
|
|
||||||
} else {
|
|
||||||
return this.getPos();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
position: function(pos) {
|
|
||||||
if (oDocument.selection) {
|
|
||||||
return this.getIEPosition(pos);
|
|
||||||
} else {
|
|
||||||
return this.getPosition(pos);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
offset: function(pos) {
|
|
||||||
var offset;
|
|
||||||
offset = this.getOffset(pos);
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
oDocument = null;
|
|
||||||
oWindow = null;
|
|
||||||
oFrame = null;
|
|
||||||
setContextBy = function(settings) {
|
|
||||||
var iframe;
|
|
||||||
if (iframe = settings != null ? settings.iframe : void 0) {
|
|
||||||
oFrame = iframe;
|
|
||||||
oWindow = iframe.contentWindow;
|
|
||||||
return oDocument = iframe.contentDocument || oWindow.document;
|
|
||||||
} else {
|
|
||||||
oFrame = void 0;
|
|
||||||
oWindow = window;
|
|
||||||
return oDocument = document;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
discoveryIframeOf = function($dom) {
|
|
||||||
var error;
|
|
||||||
oDocument = $dom[0].ownerDocument;
|
|
||||||
oWindow = oDocument.defaultView || oDocument.parentWindow;
|
|
||||||
try {
|
|
||||||
return oFrame = oWindow.frameElement;
|
|
||||||
} catch (_error) {
|
|
||||||
error = _error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.fn.caret = function(method, value, settings) {
|
|
||||||
var caret;
|
|
||||||
if (methods[method]) {
|
|
||||||
if ($.isPlainObject(value)) {
|
|
||||||
setContextBy(value);
|
|
||||||
value = void 0;
|
|
||||||
} else {
|
|
||||||
setContextBy(settings);
|
|
||||||
}
|
|
||||||
caret = Utils.contentEditable(this) ? new EditableCaret(this) : new InputCaret(this);
|
|
||||||
return methods[method].apply(caret, [value]);
|
|
||||||
} else {
|
|
||||||
return $.error("Method " + method + " does not exist on jQuery.caret");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$.fn.caret.EditableCaret = EditableCaret;
|
|
||||||
$.fn.caret.InputCaret = InputCaret;
|
|
||||||
$.fn.caret.Utils = Utils;
|
|
||||||
return $.fn.caret.apis = methods;
|
|
||||||
});
|
|
||||||
|
|
||||||
}).call(this);
|
|
|
@ -1,203 +0,0 @@
|
||||||
/**
|
|
||||||
* jQuery plugin for getting position of cursor in textarea
|
|
||||||
|
|
||||||
* @license under GNU license
|
|
||||||
* @author Bevis Zhao (i@bevis.me, http://bevis.me)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// workaround to work with jquery 1.9
|
|
||||||
// http://api.jquery.com/jQuery.browser/
|
|
||||||
(function(){
|
|
||||||
if (!jQuery.browser) {
|
|
||||||
jQuery.browser={};
|
|
||||||
jQuery.browser.msie = false;
|
|
||||||
jQuery.browser.version = 0;
|
|
||||||
if( navigator.userAgent.match(/MSIE ([0-9]+)\./) ){
|
|
||||||
jQuery.browser.msie = true;
|
|
||||||
jQuery.browser.version = RegExp.$1;
|
|
||||||
}
|
|
||||||
else if ( !navigator.userAgent.match(/mozilla/i) && !navigator.userAgent.match(/webkit/i) ){
|
|
||||||
jQuery.browser.mozilla = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
var calculator = {
|
|
||||||
// key styles
|
|
||||||
primaryStyles: ['fontFamily', 'fontSize', 'fontWeight', 'fontVariant', 'fontStyle',
|
|
||||||
'paddingLeft', 'paddingTop', 'paddingBottom', 'paddingRight',
|
|
||||||
'marginLeft', 'marginTop', 'marginBottom', 'marginRight',
|
|
||||||
'borderLeftColor', 'borderTopColor', 'borderBottomColor', 'borderRightColor',
|
|
||||||
'borderLeftStyle', 'borderTopStyle', 'borderBottomStyle', 'borderRightStyle',
|
|
||||||
'borderLeftWidth', 'borderTopWidth', 'borderBottomWidth', 'borderRightWidth',
|
|
||||||
'line-height', 'outline'],
|
|
||||||
|
|
||||||
specificStyle: {
|
|
||||||
'word-wrap': 'break-word',
|
|
||||||
'overflow-x': 'hidden',
|
|
||||||
'overflow-y': 'auto'
|
|
||||||
},
|
|
||||||
|
|
||||||
simulator : $('<div id="textarea_simulator"/>').css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
visibility: 'hidden'
|
|
||||||
}).appendTo(document.body),
|
|
||||||
|
|
||||||
toHtml : function(text) {
|
|
||||||
return text.replace(/</g,'<').replace(/>/g,'>').replace(/\n/g, '<br>')
|
|
||||||
.split(' ').join('<span style="white-space:prev-wrap"> </span>');
|
|
||||||
},
|
|
||||||
// calculate position
|
|
||||||
getCaretPosition: function() {
|
|
||||||
var cal = calculator, self = this, element = self[0], elementOffset = self.offset();
|
|
||||||
|
|
||||||
// IE has easy way to get caret offset position
|
|
||||||
if ($.browser.msie && $.browser.version <= 9) {
|
|
||||||
// must get focus first
|
|
||||||
element.focus();
|
|
||||||
var range = document.selection.createRange();
|
|
||||||
$('#hskeywords').val(element.scrollTop);
|
|
||||||
return {
|
|
||||||
left: range.boundingLeft - elementOffset.left,
|
|
||||||
top: parseInt(range.boundingTop) - elementOffset.top + element.scrollTop
|
|
||||||
+ document.documentElement.scrollTop + parseInt(self.getComputedStyle("fontSize"))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
cal.simulator.empty();
|
|
||||||
// clone primary styles to imitate textarea
|
|
||||||
$.each(cal.primaryStyles, function(index, styleName) {
|
|
||||||
self.cloneStyle(cal.simulator, styleName);
|
|
||||||
});
|
|
||||||
|
|
||||||
// caculate width and height
|
|
||||||
cal.simulator.css($.extend({
|
|
||||||
'width': self.width(),
|
|
||||||
'height': self.height()
|
|
||||||
}, cal.specificStyle));
|
|
||||||
|
|
||||||
var value = (self.val() || self.text()), cursorPosition = self.getCursorPosition();
|
|
||||||
var beforeText = value.substring(0, cursorPosition),
|
|
||||||
afterText = value.substring(cursorPosition);
|
|
||||||
|
|
||||||
var before = $('<span class="before"/>').html(cal.toHtml(beforeText)),
|
|
||||||
focus = $('<span class="focus"/>'),
|
|
||||||
after = $('<span class="after"/>').html(cal.toHtml(afterText));
|
|
||||||
|
|
||||||
cal.simulator.append(before).append(focus).append(after);
|
|
||||||
var focusOffset = focus.offset(), simulatorOffset = cal.simulator.offset();
|
|
||||||
// alert(focusOffset.left + ',' + simulatorOffset.left + ',' + element.scrollLeft);
|
|
||||||
return {
|
|
||||||
top: focusOffset.top - simulatorOffset.top - element.scrollTop
|
|
||||||
// calculate and add the font height except Firefox
|
|
||||||
+ ($.browser.mozilla ? 0 : parseInt(self.getComputedStyle("fontSize"))),
|
|
||||||
left: focus[0].offsetLeft - cal.simulator[0].offsetLeft - element.scrollLeft
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.extend({
|
|
||||||
setCursorPosition : function(position){
|
|
||||||
if(this.length == 0) return this;
|
|
||||||
return $(this).setSelection(position, position);
|
|
||||||
},
|
|
||||||
setSelection: function(selectionStart, selectionEnd) {
|
|
||||||
if(this.length == 0) return this;
|
|
||||||
input = this[0];
|
|
||||||
|
|
||||||
if (input.createTextRange) {
|
|
||||||
var range = input.createTextRange();
|
|
||||||
range.collapse(true);
|
|
||||||
range.moveEnd('character', selectionEnd);
|
|
||||||
range.moveStart('character', selectionStart);
|
|
||||||
range.select();
|
|
||||||
} else if (input.setSelectionRange) {
|
|
||||||
input.focus();
|
|
||||||
input.setSelectionRange(selectionStart, selectionEnd);
|
|
||||||
} else {
|
|
||||||
var el = this.get(0);
|
|
||||||
|
|
||||||
var range = document.createRange();
|
|
||||||
range.collapse(true);
|
|
||||||
range.setStart(el.childNodes[0], selectionStart);
|
|
||||||
range.setEnd(el.childNodes[0], selectionEnd);
|
|
||||||
|
|
||||||
var sel = window.getSelection();
|
|
||||||
sel.removeAllRanges();
|
|
||||||
sel.addRange(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
getComputedStyle: function(styleName) {
|
|
||||||
if (this.length == 0) return;
|
|
||||||
var thiz = this[0];
|
|
||||||
var result = this.css(styleName);
|
|
||||||
result = result || ($.browser.msie ?
|
|
||||||
thiz.currentStyle[styleName]:
|
|
||||||
document.defaultView.getComputedStyle(thiz, null)[styleName]);
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
// easy clone method
|
|
||||||
cloneStyle: function(target, styleName) {
|
|
||||||
var styleVal = this.getComputedStyle(styleName);
|
|
||||||
if (!!styleVal) {
|
|
||||||
$(target).css(styleName, styleVal);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cloneAllStyle: function(target, style) {
|
|
||||||
var thiz = this[0];
|
|
||||||
for (var styleName in thiz.style) {
|
|
||||||
var val = thiz.style[styleName];
|
|
||||||
typeof val == 'string' || typeof val == 'number'
|
|
||||||
? this.cloneStyle(target, styleName)
|
|
||||||
: NaN;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getCursorPosition : function() {
|
|
||||||
var element = input = this[0];
|
|
||||||
var value = (input.value || input.innerText)
|
|
||||||
|
|
||||||
if(!this.data("lastCursorPosition")){
|
|
||||||
this.data("lastCursorPosition",0);
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastCursorPosition = this.data("lastCursorPosition");
|
|
||||||
|
|
||||||
if (document.selection) {
|
|
||||||
input.focus();
|
|
||||||
var sel = document.selection.createRange();
|
|
||||||
var selLen = document.selection.createRange().text.length;
|
|
||||||
sel.moveStart('character', -value.length);
|
|
||||||
lastCursorPosition = sel.text.length - selLen;
|
|
||||||
} else if (input.selectionStart || input.selectionStart == '0') {
|
|
||||||
return input.selectionStart;
|
|
||||||
} else if (typeof window.getSelection != "undefined" && window.getSelection().rangeCount>0) {
|
|
||||||
try{
|
|
||||||
var selection = window.getSelection();
|
|
||||||
var range = selection.getRangeAt(0);
|
|
||||||
var preCaretRange = range.cloneRange();
|
|
||||||
preCaretRange.selectNodeContents(element);
|
|
||||||
preCaretRange.setEnd(range.endContainer, range.endOffset);
|
|
||||||
lastCursorPosition = preCaretRange.toString().length;
|
|
||||||
}catch(e){
|
|
||||||
lastCursorPosition = this.data("lastCursorPosition");
|
|
||||||
}
|
|
||||||
} else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
|
|
||||||
var textRange = document.selection.createRange();
|
|
||||||
var preCaretTextRange = document.body.createTextRange();
|
|
||||||
preCaretTextRange.moveToElementText(element);
|
|
||||||
preCaretTextRange.setEndPoint("EndToEnd", textRange);
|
|
||||||
lastCursorPosition = preCaretTextRange.text.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.data("lastCursorPosition",lastCursorPosition);
|
|
||||||
return lastCursorPosition;
|
|
||||||
},
|
|
||||||
getCaretPosition: calculator.getCaretPosition
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,44 +1,17 @@
|
||||||
(function ($) {
|
(function ($) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# mode: textonly/richtext / disable b/i/u/enter + strip on paste
|
# mode: textonly/richtext / disable b/i/u/enter + strip on paste
|
||||||
# pasteOnlyText: true
|
# pasteOnlyText: true
|
||||||
# maxlength: 123
|
# maxlength: 123
|
||||||
# multiline: true / disable enter + strip on paste
|
# multiline: true / disable enter + strip on paste
|
||||||
# placeholder: 'some placeholder'
|
# placeholder: 'some placeholder'
|
||||||
#
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var pluginName = 'ce',
|
var pluginName = 'ce',
|
||||||
defaults = {
|
defaults = {
|
||||||
mode: 'richtext',
|
mode: 'richtext',
|
||||||
multiline: true,
|
multiline: true,
|
||||||
allowKey: {
|
|
||||||
8: true, // backspace
|
|
||||||
9: true, // tab
|
|
||||||
16: true, // shift
|
|
||||||
17: true, // ctrl
|
|
||||||
18: true, // alt
|
|
||||||
20: true, // cabslock
|
|
||||||
37: true, // up
|
|
||||||
38: true, // right
|
|
||||||
39: true, // down
|
|
||||||
40: true, // left
|
|
||||||
91: true, // cmd left
|
|
||||||
92: true, // cmd right
|
|
||||||
},
|
|
||||||
extraAllowKey: {
|
|
||||||
65: true, // a + ctrl - select all
|
|
||||||
67: true, // c + ctrl - copy
|
|
||||||
86: true, // v + ctrl - paste
|
|
||||||
88: true, // x + ctrl - cut
|
|
||||||
90: true, // z + ctrl - undo
|
|
||||||
},
|
|
||||||
richTextFormatKey: {
|
|
||||||
66: true, // b
|
|
||||||
73: true, // i
|
|
||||||
85: true, // u
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function Plugin( element, options ) {
|
function Plugin( element, options ) {
|
||||||
|
@ -47,232 +20,34 @@
|
||||||
|
|
||||||
this.options = $.extend( {}, defaults, options) ;
|
this.options = $.extend( {}, defaults, options) ;
|
||||||
|
|
||||||
|
this._defaults = defaults;
|
||||||
|
this._name = pluginName;
|
||||||
|
|
||||||
// take placeholder from markup
|
// take placeholder from markup
|
||||||
if ( !this.options.placeholder && this.$element.data('placeholder') ) {
|
if ( !this.options.placeholder && this.$element.data('placeholder') ) {
|
||||||
this.options.placeholder = this.$element.data('placeholder')
|
this.options.placeholder = this.$element.data('placeholder')
|
||||||
}
|
}
|
||||||
|
|
||||||
this._defaults = defaults;
|
// link input
|
||||||
this._name = pluginName;
|
if ( !this.options.multiline ) {
|
||||||
|
editorMode = Medium.inlineMode
|
||||||
this.preventInput = false
|
|
||||||
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin.prototype.init = function () {
|
|
||||||
var _this = this
|
|
||||||
|
|
||||||
// set focus class
|
|
||||||
this.$element.on('focus', function (e) {
|
|
||||||
_this.$element.closest('.form-control').addClass('focus')
|
|
||||||
}).on('blur', function (e) {
|
|
||||||
_this.$element.closest('.form-control').removeClass('focus')
|
|
||||||
})
|
|
||||||
|
|
||||||
// process placeholder
|
|
||||||
if ( this.options.placeholder ) {
|
|
||||||
this.updatePlaceholder( 'add' )
|
|
||||||
this.$element.on('focus', function (e) {
|
|
||||||
_this.updatePlaceholder( 'remove' )
|
|
||||||
}).on('blur', function (e) {
|
|
||||||
_this.updatePlaceholder( 'add' )
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxlength check
|
// link textarea
|
||||||
//this.options.maxlength = 10
|
else if ( this.options.multiline && this.options.mode != 'richtext' ) {
|
||||||
if ( this.options.maxlength ) {
|
editorMode = Medium.partialMode
|
||||||
this.$element.on('keydown', function (e) {
|
|
||||||
console.log('maxlength', e.keyCode, _this.allowKey(e))
|
|
||||||
// check control key
|
|
||||||
if ( _this.allowKey(e) ) {
|
|
||||||
_this.maxLengthOk()
|
|
||||||
}
|
|
||||||
// check type ahead key
|
|
||||||
else {
|
|
||||||
if ( !_this.maxLengthOk( true ) ) {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).on('keyup', function (e) {
|
|
||||||
// check control key
|
|
||||||
if ( _this.allowKey(e) ) {
|
|
||||||
_this.maxLengthOk()
|
|
||||||
}
|
|
||||||
// check type ahead key
|
|
||||||
else {
|
|
||||||
if ( !_this.maxLengthOk( true ) ) {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).on('focus', function (e) {
|
|
||||||
_this.maxLengthOk()
|
|
||||||
}).on('blur', function (e) {
|
|
||||||
_this.maxLengthOk()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle enter
|
// rich text
|
||||||
this.$element.on('keydown', function (e) {
|
|
||||||
console.log('keydown', e.keyCode)
|
|
||||||
if ( _this.preventInput ) {
|
|
||||||
console.log('preventInput', _this.preventInput)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// strap the return key being pressed
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
// disbale multi line
|
|
||||||
if ( !_this.options.multiline ) {
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// limit check
|
|
||||||
if ( !_this.maxLengthOk( true ) ) {
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//newLine = "<br></br>"
|
|
||||||
newLine = "\n<br>"
|
|
||||||
if (document.selection) {
|
|
||||||
var range = document.selection.createRange()
|
|
||||||
newLine = "<br/>" // ie is not supporting \n :(
|
|
||||||
range.pasteHTML(newLine)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
// workaround for chrome - insert <br> directly after <br> is ignored -
|
|
||||||
// insert <br>, if it hasn't change add it twice again
|
|
||||||
var oldValue = _this.$element.html().trim()
|
|
||||||
document.execCommand('insertHTML', false, newLine)
|
|
||||||
var newValue = _this.$element.html().trim()
|
|
||||||
console.log('ON', oldValue, '--', newValue)
|
|
||||||
//if ( oldValue == newValue || oldValue == newValue.substr( 0, newValue.length - newLine.length ) ) {
|
|
||||||
//if ( oldValue == newValue.substr( 0, newValue.length - newLine.length ) ) {
|
|
||||||
if ( oldValue == newValue ) {
|
|
||||||
var oldValue = _this.$element.html().trim()
|
|
||||||
document.execCommand('insertHTML', false, newLine)
|
|
||||||
console.log('Autoinsert 1th-br')
|
|
||||||
var newValue = _this.$element.html().trim()
|
|
||||||
if ( oldValue == newValue ) {
|
|
||||||
console.log('Autoinsert 2th-br')
|
|
||||||
document.execCommand('insertHTML', false, ' ' + newLine) // + newLine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent the default behaviour of return key pressed
|
|
||||||
e.preventDefault()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// just paste text
|
|
||||||
if ( this.options.mode === 'textonly' ) {
|
|
||||||
this.$element.on('paste', function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
var text
|
|
||||||
if (window.clipboardData) { // IE
|
|
||||||
text = window.clipboardData.getData('Text')
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
text = (e.originalEvent || e).clipboardData.getData('text/plain')
|
|
||||||
}
|
|
||||||
var overlimit = false
|
|
||||||
if (text) {
|
|
||||||
|
|
||||||
// replace new lines
|
|
||||||
if ( !_this.options.multiline ) {
|
|
||||||
text = text.replace(/\n/g, '')
|
|
||||||
text = text.replace(/\r/g, '')
|
|
||||||
text = text.replace(/\t/g, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
// limit length, limit paste string
|
|
||||||
if ( _this.options.maxlength ) {
|
|
||||||
var pasteLength = text.length
|
|
||||||
var currentLength = _this.$element.text().length
|
|
||||||
var overSize = ( currentLength + pasteLength ) - _this.options.maxlength
|
|
||||||
if ( overSize > 0 ) {
|
|
||||||
text = text.substr( 0, pasteLength - overSize )
|
|
||||||
overlimit = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert new text
|
|
||||||
if (document.selection) { // IE
|
|
||||||
var range = document.selection.createRange()
|
|
||||||
range.pasteHTML(text)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.execCommand('inserttext', false, text)
|
|
||||||
}
|
|
||||||
_this.maxLengthOk( overlimit )
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable rich text b/u/i
|
|
||||||
if ( this.options.mode === 'textonly' ) {
|
|
||||||
this.$element.on('keydown', function (e) {
|
|
||||||
if ( _this.richTextKey(e) ) {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// add/remove placeholder
|
|
||||||
Plugin.prototype.updatePlaceholder = function(type) {
|
|
||||||
if ( !this.options.placeholder ) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var holder = this.$element
|
|
||||||
var text = holder.text().trim()
|
|
||||||
var placeholder = '<span class="placeholder">' + this.options.placeholder + '</span>'
|
|
||||||
|
|
||||||
// add placholder if no text exists
|
|
||||||
if ( type === 'add') {
|
|
||||||
if ( !text ) {
|
|
||||||
holder.html( placeholder )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty placeholder text
|
|
||||||
else {
|
else {
|
||||||
if ( text === this.options.placeholder ) {
|
editorMode = Medium.richMode
|
||||||
setTimeout(function(){
|
|
||||||
document.execCommand('selectAll', false, '');
|
|
||||||
document.execCommand('delete', false, '');
|
|
||||||
document.execCommand('selectAll', false, '');
|
|
||||||
document.execCommand('removeFormat', false, '');
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// disable/enable input
|
|
||||||
Plugin.prototype.input = function(type) {
|
|
||||||
if ( type === 'off' ) {
|
|
||||||
this.preventInput = true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.preventInput = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// max length check
|
|
||||||
Plugin.prototype.maxLengthOk = function(typeAhead) {
|
|
||||||
var length = this.$element.text().length
|
|
||||||
if (typeAhead) {
|
|
||||||
length = length + 1
|
|
||||||
}
|
|
||||||
if ( length > this.options.maxlength ) {
|
|
||||||
|
|
||||||
|
// max length validation
|
||||||
|
var validation = function(element) {
|
||||||
|
console.log('pp', element, $(element))
|
||||||
// try to set error on framework form
|
// try to set error on framework form
|
||||||
var parent = this.$element.parent().parent()
|
var parent = $(element).parent().parent()
|
||||||
if ( parent.hasClass('controls') ) {
|
if ( parent.hasClass('controls') ) {
|
||||||
parent.addClass('has-error')
|
parent.addClass('has-error')
|
||||||
setTimeout($.proxy(function(){
|
setTimeout($.proxy(function(){
|
||||||
|
@ -284,42 +59,24 @@
|
||||||
|
|
||||||
// set validation on element
|
// set validation on element
|
||||||
else {
|
else {
|
||||||
this.$element.addClass('invalid')
|
$(element).addClass('invalid')
|
||||||
setTimeout($.proxy(function(){
|
setTimeout($.proxy(function(){
|
||||||
this.$element.removeClass('invalid')
|
$(element).removeClass('invalid')
|
||||||
}, this), 1000)
|
}, this), 1000)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
new Medium({
|
||||||
}
|
element: element,
|
||||||
|
modifier: 'auto',
|
||||||
// check if key is allowed, even if length limit is reached
|
placeholder: this.options.placeholder || '',
|
||||||
Plugin.prototype.allowKey = function(e) {
|
autofocus: false,
|
||||||
if ( this.options.allowKey[ e.keyCode ] ) {
|
autoHR: false,
|
||||||
return true
|
mode: editorMode,
|
||||||
}
|
maxLength: this.options.maxlength || -1,
|
||||||
if ( ( e.ctrlKey || e.metaKey ) && this.options.extraAllowKey[ e.keyCode ] ) {
|
maxLengthReached: validation,
|
||||||
return true
|
});
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if rich text key is pressed
|
|
||||||
Plugin.prototype.richTextKey = function(e) {
|
|
||||||
// e.altKey
|
|
||||||
// e.ctrlKey
|
|
||||||
// e.metaKey
|
|
||||||
// on mac block e.metaKey + i/b/u
|
|
||||||
if ( !e.altKey && e.metaKey && this.options.richTextFormatKey[ e.keyCode ] ) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// on win block e.ctrlKey + i/b/u
|
|
||||||
if ( !e.altKey && e.ctrlKey && this.options.richTextFormatKey[ e.keyCode ] ) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get value
|
// get value
|
||||||
|
@ -332,9 +89,17 @@
|
||||||
// strip html signes if multi line exists
|
// strip html signes if multi line exists
|
||||||
if ( this.options.multiline ) {
|
if ( this.options.multiline ) {
|
||||||
var text = this.$element.html()
|
var text = this.$element.html()
|
||||||
|
//console.log('h2a 1', text)
|
||||||
|
text = text.replace(/<p><br><\/p>/g, "\n") // new line as /p
|
||||||
|
text = text.replace(/<p><br\/><\/p>/g, "\n") // new line as /p
|
||||||
|
text = text.replace(/<\/p>/g, "\n") // new line as /p
|
||||||
text = text.replace(/<br>/g, "\n") // new line as br
|
text = text.replace(/<br>/g, "\n") // new line as br
|
||||||
text = text.replace(/<div>/g, "\n") // in some caes, new line als div
|
text = text.replace(/<\/div>/g, "\n") // in some caes, new line als div
|
||||||
text = $("<div>" + text + "</div>").text().trim()
|
text = text.replace(/<.+?>/g, "") // new line as /p
|
||||||
|
text = $("<div>" + text + "</div>").text()
|
||||||
|
text = text.replace(/ /g, " ")
|
||||||
|
text = text.replace(/\s+$/g, '');
|
||||||
|
//console.log('h2a 2', text)
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
return this.$element.text().trim()
|
return this.$element.text().trim()
|
||||||
|
@ -358,18 +123,3 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}(jQuery));
|
}(jQuery));
|
||||||
|
|
||||||
/* TODO: paste
|
|
||||||
@$('.ticket-title-update').bind(
|
|
||||||
'drop'
|
|
||||||
(e) =>
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
t2 = e.originalEvent.dataTransfer.getData("text/plain")# : window.event.dataTransfer.getData("Text");
|
|
||||||
|
|
||||||
@log('drop', t2, e.keyCode, e.clipboardData, e, $(e.target).text().length)
|
|
||||||
|
|
||||||
document.execCommand('inserttext', false, '123123');
|
|
||||||
#document.execCommand('inserttext', false, prompt('Paste something.'));
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
|
|
|
@ -174,25 +174,29 @@
|
||||||
|
|
||||||
// update widget position
|
// update widget position
|
||||||
Plugin.prototype.updatePosition = function() {
|
Plugin.prototype.updatePosition = function() {
|
||||||
console.log('uP')
|
|
||||||
this.$widget.find('.dropdown-menu').scrollTop( 300 );
|
this.$widget.find('.dropdown-menu').scrollTop( 300 );
|
||||||
//if ( !this.$element.is(':visible') ) return
|
if ( !this.$element.is(':visible') ) return
|
||||||
var position = this.$element.caret('position');
|
|
||||||
console.log('PP', position)
|
// get cursor position
|
||||||
|
var marker = '<span id="js-cursor-position"></span>'
|
||||||
|
Medium.Injector.prototype.inject( marker )
|
||||||
|
position = $('#js-cursor-position').position()
|
||||||
|
$('#js-cursor-position').remove()
|
||||||
if (!position) return
|
if (!position) return
|
||||||
var widgetHeight = this.$widget.find('ul').height() + 85
|
|
||||||
this.$widget.css('top', position.top - widgetHeight)
|
// set position of widget
|
||||||
if ( !this.isActive() ) {
|
var height = this.$element.height()
|
||||||
this.$widget.css('left', position.left)
|
var widgetHeight = this.$widget.find('ul').height() //+ 60 // + height
|
||||||
}
|
var top = -( widgetHeight + height ) + position.top
|
||||||
|
this.$widget.css('top', top)
|
||||||
|
this.$widget.css('left', position.left)
|
||||||
}
|
}
|
||||||
|
|
||||||
// open widget
|
// open widget
|
||||||
Plugin.prototype.open = function() {
|
Plugin.prototype.open = function() {
|
||||||
this.active = true
|
this.active = true
|
||||||
if (this.ce) {
|
this.updatePosition()
|
||||||
this.ce.input('off')
|
|
||||||
}
|
|
||||||
b = $.proxy(function() {
|
b = $.proxy(function() {
|
||||||
this.$widget.addClass('open')
|
this.$widget.addClass('open')
|
||||||
}, this)
|
}, this)
|
||||||
|
@ -203,9 +207,6 @@
|
||||||
Plugin.prototype.close = function() {
|
Plugin.prototype.close = function() {
|
||||||
this.active = false
|
this.active = false
|
||||||
this.cutInput()
|
this.cutInput()
|
||||||
if (this.ce) {
|
|
||||||
this.ce.input('on')
|
|
||||||
}
|
|
||||||
this.$widget.removeClass('open')
|
this.$widget.removeClass('open')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +215,36 @@
|
||||||
return this.active
|
return this.active
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// paste some content
|
||||||
|
Plugin.prototype.paste = function(string) {
|
||||||
|
if (document.selection) { // IE
|
||||||
|
var range = document.selection.createRange()
|
||||||
|
range.pasteHTML(string)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
document.execCommand('insertHTML', false, string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cut some content
|
||||||
|
Plugin.prototype.cut = function(string) {
|
||||||
|
var sel = window.getSelection()
|
||||||
|
if ( !sel || sel.rangeCount < 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var range = sel.getRangeAt(0)
|
||||||
|
var clone = range.cloneRange()
|
||||||
|
|
||||||
|
// improve error handling
|
||||||
|
start = range.startOffset - string.length
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
clone.setStart(range.startContainer, start)
|
||||||
|
clone.setEnd(range.startContainer, range.startOffset)
|
||||||
|
clone.deleteContents()
|
||||||
|
}
|
||||||
|
|
||||||
// select text module and insert into text
|
// select text module and insert into text
|
||||||
Plugin.prototype.take = function(id) {
|
Plugin.prototype.take = function(id) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
@ -223,15 +254,9 @@
|
||||||
for (var i = 0; i < this.collection.length; i++) {
|
for (var i = 0; i < this.collection.length; i++) {
|
||||||
var item = this.collection[i]
|
var item = this.collection[i]
|
||||||
if ( item.id == id ) {
|
if ( item.id == id ) {
|
||||||
var content = item.content + "\n"
|
var content = item.content + "<br/>\n"
|
||||||
this.cutInput()
|
this.cutInput()
|
||||||
if (document.selection) { // IE
|
this.paste(content)
|
||||||
var range = document.selection.createRange()
|
|
||||||
range.pasteHTML(content)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.execCommand('insertHTML', false, content)
|
|
||||||
}
|
|
||||||
this.close()
|
this.close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -248,17 +273,7 @@
|
||||||
this.buffer = ''
|
this.buffer = ''
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var range = sel.getRangeAt(0)
|
this.cut(this.buffer)
|
||||||
var clone = range.cloneRange()
|
|
||||||
|
|
||||||
// improve error handling
|
|
||||||
start = range.startOffset - this.buffer.length
|
|
||||||
if (start < 0) {
|
|
||||||
start = 0
|
|
||||||
}
|
|
||||||
clone.setStart(range.startContainer, start)
|
|
||||||
clone.setEnd(range.startContainer, range.startOffset)
|
|
||||||
clone.deleteContents()
|
|
||||||
this.buffer = ''
|
this.buffer = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1951
app/assets/javascripts/app/lib/base/medium.js
Normal file
1951
app/assets/javascripts/app/lib/base/medium.js
Normal file
File diff suppressed because it is too large
Load diff
16582
app/assets/javascripts/app/lib/core/jquery-ui-1.11.2.js
vendored
Executable file
16582
app/assets/javascripts/app/lib/core/jquery-ui-1.11.2.js
vendored
Executable file
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,3 @@
|
||||||
<div class="richtext form-control">
|
<div class="richtext form-control">
|
||||||
<div contenteditable="true" id="<%= @attribute.id %>" data-name="<%= @attribute.name %>" class="<%= @attribute.class %>"><%= @attribute.value %></div>
|
<div contenteditable="true" id="<%= @attribute.id %>" data-name="<%= @attribute.name %>" class="<%= @attribute.class %>"><%- @A2H(@attribute.value) %></div>
|
||||||
</div>
|
</div>
|
|
@ -6,7 +6,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
//= require ./app/lib/core/jquery-2.1.1.js
|
//= require ./app/lib/core/jquery-2.1.1.js
|
||||||
//= require ./app/lib/core/jquery-ui-1.8.23.custom.min.js
|
//= require ./app/lib/core/jquery-ui-1.11.2.js
|
||||||
//= require ./app/lib/core/underscore-1.7.0.js
|
//= require ./app/lib/core/underscore-1.7.0.js
|
||||||
|
|
||||||
//= require ./app/lib/animations/velocity.min.js
|
//= require ./app/lib/animations/velocity.min.js
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
*= require ./bootstrap.css
|
*= require ./bootstrap.css
|
||||||
*= require ./cropper.min.css
|
*= require ./cropper.min.css
|
||||||
*= require ./fineuploader.css
|
*= require ./fineuploader.css
|
||||||
*= require ./ui-lightness/jquery-ui-1.8.23.custom.css
|
*= require ./ui-lightness/jquery-ui-1.11.2.css
|
||||||
*= require ./jquery.noty.css
|
*= require ./jquery.noty.css
|
||||||
*= require ./bootstrap-tokenfield.css
|
*= require ./bootstrap-tokenfield.css
|
||||||
*= require ./noty_theme_twitter.css
|
*= require ./noty_theme_twitter.css
|
||||||
*= require ./sew.css
|
*= require ./sew.css
|
||||||
|
*= require ./medium.css
|
||||||
*= require ./fira-sans.css
|
*= require ./fira-sans.css
|
||||||
*= require ./zammad.css.scss
|
*= require ./zammad.css.scss
|
||||||
*
|
*
|
||||||
|
|
44
app/assets/stylesheets/medium.css
Normal file
44
app/assets/stylesheets/medium.css
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
.Medium{
|
||||||
|
position: relative;
|
||||||
|
min-height: 10px;
|
||||||
|
}
|
||||||
|
.Medium-clear{
|
||||||
|
background: transparent !important;
|
||||||
|
background-color: transparent !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
}
|
||||||
|
.Medium,
|
||||||
|
.Medium p:first-child{
|
||||||
|
margin-top:0;
|
||||||
|
}
|
||||||
|
.Medium p:last-child{
|
||||||
|
margin-bottom:0;
|
||||||
|
}
|
||||||
|
.Medium p:empty {
|
||||||
|
display: block;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
.Medium-paste-hook{
|
||||||
|
position: absolute;
|
||||||
|
opacity:0;
|
||||||
|
}
|
||||||
|
.Medium-placeholder{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.Medium-placeholder div{
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
|
||||||
|
filter: alpha(opacity=50);
|
||||||
|
opacity: 0.5;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.Medium-placeholder-rich div{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.Medium-inline,
|
||||||
|
.Medium-placeholder-inline div,
|
||||||
|
.Medium-inlineRich,
|
||||||
|
.Medium-placeholder-inlineRich div{
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
1225
app/assets/stylesheets/ui-lightness/jquery-ui-1.11.2.css
vendored
Executable file
1225
app/assets/stylesheets/ui-lightness/jquery-ui-1.11.2.css
vendored
Executable file
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
require 'browser_test_helper'
|
require 'browser_test_helper'
|
||||||
|
|
||||||
class AgentTicketActionLevel5Test < TestCase
|
class AgentTicketActionLevel0Test < TestCase
|
||||||
def test_I
|
def test_I
|
||||||
random = 'text_module_test_' + rand(99999999).to_s
|
random = 'text_module_test_' + rand(99999999).to_s
|
||||||
random2 = 'text_module_test_' + rand(99999999).to_s
|
random2 = 'text_module_test_' + rand(99999999).to_s
|
||||||
|
@ -122,12 +122,12 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'watch_for',
|
:execute => 'watch_for',
|
||||||
:area => '.active [data-name="body"]',
|
:area => '.active div[data-name=body]',
|
||||||
:value => '',
|
:value => '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'wait',
|
:execute => 'wait',
|
||||||
:value => 1,
|
:value => 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'set_ticket_attributes',
|
:execute => 'set_ticket_attributes',
|
||||||
|
@ -156,7 +156,7 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'match',
|
:execute => 'match',
|
||||||
:css => '.active [data-name="body"]',
|
:css => '.active div[data-name=body]',
|
||||||
:value => 'some content' + random,
|
:value => 'some content' + random,
|
||||||
:match_result => true,
|
:match_result => true,
|
||||||
},
|
},
|
||||||
|
@ -313,10 +313,13 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
:execute => 'wait',
|
:execute => 'wait',
|
||||||
:value => 1,
|
:value => 1,
|
||||||
},
|
},
|
||||||
|
# instance.execute_script( '$(".content.active div[data-name=body]").focus()' )
|
||||||
|
#execute] == 'js'
|
||||||
|
# result = instance.execute_script( action[:value
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
:execute => 'match',
|
:execute => 'match',
|
||||||
:css => '.active [data-name="body"]',
|
:css => '.active div[data-name=body]',
|
||||||
:value => 'some content ' + random,
|
:value => 'some content ' + random,
|
||||||
:match_result => true,
|
:match_result => true,
|
||||||
},
|
},
|
||||||
|
@ -382,7 +385,7 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
:execute => 'match',
|
:execute => 'match',
|
||||||
:css => '.active [data-name="body"]',
|
:css => '.active div[data-name=body]',
|
||||||
:value => 'some content Braun' + random,
|
:value => 'some content Braun' + random,
|
||||||
:match_result => true,
|
:match_result => true,
|
||||||
},
|
},
|
||||||
|
@ -460,7 +463,7 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
:execute => 'match',
|
:execute => 'match',
|
||||||
:css => '.active [data-name="body"]',
|
:css => '.active div[data-name=body]',
|
||||||
:value => 'some content Braun' + random,
|
:value => 'some content Braun' + random,
|
||||||
:match_result => true,
|
:match_result => true,
|
||||||
},
|
},
|
||||||
|
@ -561,7 +564,7 @@ class AgentTicketActionLevel5Test < TestCase
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
:execute => 'match',
|
:execute => 'match',
|
||||||
:css => '.active [data-name="body"]',
|
:css => '.active div[data-name=body]',
|
||||||
:value => 'some content ' + lastname,
|
:value => 'some content ' + lastname,
|
||||||
:match_result => true,
|
:match_result => true,
|
||||||
},
|
},
|
|
@ -104,7 +104,7 @@ class AgentTicketActionsLevel3Test < TestCase
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'wait',
|
:execute => 'wait',
|
||||||
:value => 5,
|
:value => 6,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
|
@ -155,6 +155,10 @@ class AgentTicketActionsLevel3Test < TestCase
|
||||||
},
|
},
|
||||||
|
|
||||||
# check edit screen in instance 2
|
# check edit screen in instance 2
|
||||||
|
{
|
||||||
|
:execute => 'wait',
|
||||||
|
:value => 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
:where => :instance2,
|
:where => :instance2,
|
||||||
:execute => 'verify_ticket_attributes',
|
:execute => 'verify_ticket_attributes',
|
||||||
|
|
|
@ -21,7 +21,7 @@ class AgentTicketActionLevel4Test < TestCase
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'wait',
|
:execute => 'wait',
|
||||||
:value => 6,
|
:value => 10,
|
||||||
},
|
},
|
||||||
|
|
||||||
# reload instances, verify autosave
|
# reload instances, verify autosave
|
||||||
|
|
|
@ -45,7 +45,7 @@ class CustomerTicketCreateTest < TestCase
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'wait',
|
:execute => 'wait',
|
||||||
:value => 4,
|
:value => 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:execute => 'check',
|
:execute => 'check',
|
||||||
|
|
|
@ -378,14 +378,17 @@ class TestCase < Test::Unit::TestCase
|
||||||
# },
|
# },
|
||||||
end
|
end
|
||||||
if action[:body]
|
if action[:body]
|
||||||
element = instance.find_element( { :css => '.content.active [data-name="body"]' } )
|
instance.execute_script( '$(".content.active div[data-name=body]").focus()' )
|
||||||
|
sleep 0.5
|
||||||
|
element = instance.find_element( { :css => '.content.active div[data-name=body]' } )
|
||||||
element.clear
|
element.clear
|
||||||
element.send_keys( action[:body] )
|
element.send_keys( action[:body] )
|
||||||
# check if body is filled / in case use workaround
|
# check if body is filled / in case use workaround
|
||||||
body = element.text
|
body = element.text
|
||||||
#puts "body '#{body}'"
|
#puts "body '#{body}'"
|
||||||
if !body || body.empty? || body == '' || body == ' '
|
if !body || body.empty? || body == '' || body == ' '
|
||||||
result = instance.execute_script( '$(".content.active [data-name=body]").text("' + action[:body] + '")' )
|
puts "DBODY WORKSAROUND"
|
||||||
|
result = instance.execute_script( '$(".content.active div[data-name=body]").text("' + action[:body] + '").focus()' )
|
||||||
#puts "r #{result.inspect}"
|
#puts "r #{result.inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -426,7 +429,9 @@ class TestCase < Test::Unit::TestCase
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
end
|
end
|
||||||
if action[:body]
|
if action[:body]
|
||||||
element = instance.find_element( { :css => '.active .newTicket [data-name="body"]' } )
|
instance.execute_script( '$(".active .newTicket div[data-name=body]").focus()' )
|
||||||
|
sleep 0.5
|
||||||
|
element = instance.find_element( { :css => '.active .newTicket div[data-name=body]' } )
|
||||||
element.clear
|
element.clear
|
||||||
element.send_keys( action[:body] )
|
element.send_keys( action[:body] )
|
||||||
|
|
||||||
|
@ -434,7 +439,8 @@ class TestCase < Test::Unit::TestCase
|
||||||
body = element.text
|
body = element.text
|
||||||
#puts "body '#{body}'"
|
#puts "body '#{body}'"
|
||||||
if !body || body.empty? || body == '' || body == ' '
|
if !body || body.empty? || body == '' || body == ' '
|
||||||
result = instance.execute_script( '$(".content.active .newTicket [data-name=body]").text("' + action[:body] + '").focus()' )
|
puts "DBODY WORKSAROUND"
|
||||||
|
result = instance.execute_script( '$(".active .newTicket div[data-name=body]").text("' + action[:body] + '").focus()' )
|
||||||
#puts "r #{result.inspect}"
|
#puts "r #{result.inspect}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -444,7 +450,7 @@ class TestCase < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
sleep 0.8
|
sleep 0.8
|
||||||
#instance.execute_script( '$(".content.active .newTicket form").submit()' )
|
#instance.execute_script( '$(".content.active .newTicket form").submit()' )
|
||||||
instance.find_element( { :css => '.content.active .newTicket button.submit' } ).click
|
instance.find_element( { :css => '.active .newTicket button.submit' } ).click
|
||||||
sleep 1
|
sleep 1
|
||||||
(1..16).each {|loop|
|
(1..16).each {|loop|
|
||||||
if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
|
if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
|
||||||
|
|
Loading…
Reference in a new issue