sir-trevor-rails 0.1.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore
CHANGED
@@ -1,32 +1,32 @@
|
|
1
|
-
// Sir Trevor, v0.1
|
1
|
+
// Sir Trevor, v0.2.1
|
2
2
|
|
3
3
|
(function ($, _){
|
4
4
|
|
5
5
|
var root = this,
|
6
6
|
SirTrevor;
|
7
7
|
|
8
|
-
SirTrevor = root.SirTrevor = {};
|
9
|
-
SirTrevor.DEBUG =
|
8
|
+
SirTrevor = root.SirTrevor = {};
|
9
|
+
SirTrevor.DEBUG = false;
|
10
10
|
SirTrevor.SKIP_VALIDATION = false;
|
11
11
|
|
12
|
-
/*
|
12
|
+
/*
|
13
13
|
Define default attributes that can be extended through an object passed to the
|
14
14
|
initialize function of SirTrevor
|
15
15
|
*/
|
16
16
|
|
17
17
|
SirTrevor.DEFAULTS = {
|
18
18
|
baseCSSClass: "sir-trevor",
|
19
|
-
errorClass: "
|
19
|
+
errorClass: "error",
|
20
20
|
defaultType: "Text",
|
21
21
|
spinner: {
|
22
22
|
className: 'spinner',
|
23
|
-
lines: 9,
|
24
|
-
length: 8,
|
25
|
-
width: 3,
|
26
|
-
radius: 6,
|
27
|
-
color: '#000',
|
28
|
-
speed: 1.4,
|
29
|
-
trail: 57,
|
23
|
+
lines: 9,
|
24
|
+
length: 8,
|
25
|
+
width: 3,
|
26
|
+
radius: 6,
|
27
|
+
color: '#000',
|
28
|
+
speed: 1.4,
|
29
|
+
trail: 57,
|
30
30
|
shadow: false,
|
31
31
|
left: '50%',
|
32
32
|
top: '50%'
|
@@ -45,7 +45,7 @@
|
|
45
45
|
required: [],
|
46
46
|
uploadUrl: '/attachments',
|
47
47
|
baseImageUrl: '/sir-trevor-uploads/'
|
48
|
-
};
|
48
|
+
};
|
49
49
|
|
50
50
|
SirTrevor.Blocks = {};
|
51
51
|
SirTrevor.Formatters = {};
|
@@ -261,7 +261,7 @@
|
|
261
261
|
};
|
262
262
|
|
263
263
|
$.fn.chars = function() {
|
264
|
-
count = (this.attr('contenteditable')!==undefined) ? this.text().length :
|
264
|
+
count = (this.attr('contenteditable')!==undefined) ? this.text().length : this.val().length;
|
265
265
|
return count;
|
266
266
|
};
|
267
267
|
|
@@ -531,13 +531,11 @@
|
|
531
531
|
|
532
532
|
|
533
533
|
var Block = SirTrevor.Block = function(instance, data) {
|
534
|
-
|
535
534
|
this.instance = instance;
|
536
535
|
this.type = this._getBlockType();
|
537
536
|
|
538
|
-
this.store("create", this, { data: data });
|
537
|
+
this.store("create", this, { data: data });
|
539
538
|
|
540
|
-
//this.data = data;
|
541
539
|
this.uploadsCount = 0;
|
542
540
|
this.blockID = _.uniqueId(this.className + '-');
|
543
541
|
|
@@ -550,21 +548,22 @@
|
|
550
548
|
};
|
551
549
|
|
552
550
|
var blockOptions = [
|
553
|
-
"className",
|
551
|
+
"className",
|
554
552
|
"toolbarEnabled",
|
555
553
|
"formattingEnabled",
|
556
|
-
"dropEnabled",
|
557
|
-
"title",
|
558
|
-
"limit",
|
559
|
-
"editorHTML",
|
560
|
-
"dropzoneHTML",
|
561
|
-
"validate",
|
562
|
-
"loadData",
|
554
|
+
"dropEnabled",
|
555
|
+
"title",
|
556
|
+
"limit",
|
557
|
+
"editorHTML",
|
558
|
+
"dropzoneHTML",
|
559
|
+
"validate",
|
560
|
+
"loadData",
|
563
561
|
"toData",
|
564
562
|
"onDrop",
|
565
563
|
"onContentPasted",
|
566
564
|
"onBlockRender",
|
567
565
|
"beforeBlockRender",
|
566
|
+
"setTextLimit",
|
568
567
|
"toMarkdown",
|
569
568
|
"toHTML"
|
570
569
|
];
|
@@ -596,6 +595,7 @@
|
|
596
595
|
loadData: function(data) {},
|
597
596
|
onBlockRender: function(){},
|
598
597
|
beforeBlockRender: function(){},
|
598
|
+
setTextLimit: function() {},
|
599
599
|
toMarkdown: function(markdown){ return markdown; },
|
600
600
|
toHTML: function(html){ return html; },
|
601
601
|
|
@@ -608,11 +608,10 @@
|
|
608
608
|
this.beforeBlockRender();
|
609
609
|
|
610
610
|
// Insert before the marker
|
611
|
-
this.instance.formatBar.hide();
|
612
611
|
this.instance.marker.hide();
|
613
612
|
this.instance.marker.$el.before(this.$el);
|
614
613
|
|
615
|
-
// Do we have a dropzone?
|
614
|
+
// Do we have a dropzone?
|
616
615
|
if (this.dropEnabled) {
|
617
616
|
this._initDragDrop();
|
618
617
|
}
|
@@ -628,8 +627,8 @@
|
|
628
627
|
this.save();
|
629
628
|
|
630
629
|
// Add UI elements
|
631
|
-
this.$el.append($('<span>',{ 'class':
|
632
|
-
this.$el.append($('<span>',{ 'class':
|
630
|
+
this.$el.append($('<span>',{ 'class': this.instance.baseCSS("drag-handle"), draggable: true }));
|
631
|
+
this.$el.append($('<span>',{ 'class': this.instance.baseCSS("remove-block") }));
|
633
632
|
|
634
633
|
// Stop events propagating through to the container
|
635
634
|
this.$el
|
@@ -645,20 +644,18 @@
|
|
645
644
|
this._initPaste();
|
646
645
|
|
647
646
|
// Delete
|
648
|
-
this.$('.
|
647
|
+
this.$('.' + this.instance.baseCSS("remove-block")).bind('click', this.onDeleteClick);
|
649
648
|
|
650
649
|
// Handle text blocks
|
651
650
|
if (this.$$('.text-block').length > 0) {
|
652
651
|
document.execCommand("styleWithCSS", false, false);
|
653
652
|
document.execCommand("insertBrOnReturn", false, true);
|
654
653
|
|
655
|
-
// Bind our text block to show the format bar
|
656
|
-
this.$$('.text-block')
|
657
|
-
.focus(this.onBlockFocus)
|
658
|
-
.blur(this.onBlockBlur);
|
659
|
-
|
660
654
|
// Strip out all the HTML on paste
|
661
|
-
this.$$('.text-block')
|
655
|
+
this.$$('.text-block')
|
656
|
+
.bind('paste', this._handleContentPaste)
|
657
|
+
.bind('focus', this.onBlockFocus)
|
658
|
+
.bind('blur', this.onBlockBlur);
|
662
659
|
|
663
660
|
// Formatting
|
664
661
|
this._initFormatting();
|
@@ -676,11 +673,10 @@
|
|
676
673
|
// Reorderable
|
677
674
|
this._initReordering();
|
678
675
|
|
679
|
-
this._initTextLimits();
|
680
|
-
|
681
676
|
// Set ready state
|
682
|
-
this.$el.addClass('
|
677
|
+
this.$el.addClass(this.instance.baseCSS('item-ready'));
|
683
678
|
|
679
|
+
this.setTextLimit();
|
684
680
|
this.onBlockRender();
|
685
681
|
},
|
686
682
|
|
@@ -740,13 +736,14 @@
|
|
740
736
|
|
741
737
|
if ((required && content.length === 0) || too_long) {
|
742
738
|
// Error!
|
743
|
-
field.addClass(this.instance.options.errorClass)
|
744
|
-
'class': 'error-marker',
|
745
|
-
'html': '!'
|
746
|
-
}));
|
739
|
+
field.addClass(this.instance.baseCSS(this.instance.options.errorClass));
|
747
740
|
errors++;
|
748
|
-
}
|
741
|
+
}
|
749
742
|
}, this));
|
743
|
+
|
744
|
+
if (errors > 0) {
|
745
|
+
this.$el.addClass(this.instance.baseCSS('block-with-errors'));
|
746
|
+
}
|
750
747
|
|
751
748
|
return (errors === 0);
|
752
749
|
},
|
@@ -818,23 +815,7 @@
|
|
818
815
|
var item = $(ev.target);
|
819
816
|
item.parent().removeClass('dragging');
|
820
817
|
this.instance.marker.hide();
|
821
|
-
|
822
|
-
|
823
|
-
onBlockFocus: function(ev) {
|
824
|
-
_.delay(_.bind(function(){
|
825
|
-
this.instance.formatBar.clicked = false;
|
826
|
-
if(this.formattingEnabled) {
|
827
|
-
this.instance.formatBar.show(this.$el);
|
828
|
-
}
|
829
|
-
}, this), 250);
|
830
|
-
},
|
831
|
-
|
832
|
-
onBlockBlur: function(ev) {
|
833
|
-
_.delay(_.bind(function(){
|
834
|
-
if(!this.instance.formatBar.clicked && this.formattingEnabled) {
|
835
|
-
this.instance.formatBar.hide();
|
836
|
-
}
|
837
|
-
}, this), 250);
|
818
|
+
this.instance.formatBar.show();
|
838
819
|
},
|
839
820
|
|
840
821
|
onDeleteClick: function(ev) {
|
@@ -850,6 +831,14 @@
|
|
850
831
|
textBlock.html(this.instance._toHTML(this.instance._toMarkdown(textBlock.html(), this.type),this.type));
|
851
832
|
}
|
852
833
|
},
|
834
|
+
|
835
|
+
onBlockFocus: function(e) {
|
836
|
+
this.$el.addClass('focussed');
|
837
|
+
},
|
838
|
+
|
839
|
+
onBlockBlur: function(e) {
|
840
|
+
this.$el.removeClass('focussed');
|
841
|
+
},
|
853
842
|
|
854
843
|
/*
|
855
844
|
Generic Upload Attachment Function
|
@@ -863,7 +852,6 @@
|
|
863
852
|
/* Private methods */
|
864
853
|
|
865
854
|
_loadData: function() {
|
866
|
-
|
867
855
|
SirTrevor.log("loadData for " + this.blockID);
|
868
856
|
|
869
857
|
this.loading();
|
@@ -880,14 +868,16 @@
|
|
880
868
|
},
|
881
869
|
|
882
870
|
_beforeValidate: function() {
|
883
|
-
this.errors = [];
|
884
|
-
this
|
871
|
+
this.errors = [];
|
872
|
+
var errorClass = this.instance.baseCSS("error");
|
873
|
+
this.$el.removeClass(this.instance.baseCSS('block-with-errors'));
|
874
|
+
this.$('.' + errorClass).removeClass(errorClass);
|
885
875
|
this.$('.error-marker').remove();
|
886
876
|
},
|
887
877
|
|
888
878
|
_handleContentPaste: function(ev) {
|
889
879
|
// We need a little timeout here
|
890
|
-
var timed = function(ev){
|
880
|
+
var timed = function(ev){
|
891
881
|
// Delegate this off to the super method that can be overwritten
|
892
882
|
this.onContentPasted(ev);
|
893
883
|
};
|
@@ -905,21 +895,18 @@
|
|
905
895
|
types = e.dataTransfer.types,
|
906
896
|
type, data = [];
|
907
897
|
|
908
|
-
this.instance.formatBar.hide();
|
909
898
|
this.instance.marker.hide();
|
910
|
-
this.$dropzone.removeClass('
|
899
|
+
this.$dropzone.removeClass('drag-enter');
|
911
900
|
|
912
901
|
/*
|
913
902
|
Check the type we just received,
|
914
903
|
delegate it away to our blockTypes to process
|
915
|
-
*/
|
904
|
+
*/
|
916
905
|
|
917
|
-
if (!_.isUndefined(types))
|
918
|
-
|
919
|
-
if (_.include(types, 'Files') || _.include(types, 'text/plain') || _.include(types, 'text/uri-list'))
|
920
|
-
{
|
906
|
+
if (!_.isUndefined(types)) {
|
907
|
+
if (_.include(types, 'Files') || _.include(types, 'text/plain') || _.include(types, 'text/uri-list')) {
|
921
908
|
this.onDrop(e.dataTransfer);
|
922
|
-
}
|
909
|
+
}
|
923
910
|
}
|
924
911
|
},
|
925
912
|
|
@@ -928,12 +915,12 @@
|
|
928
915
|
|
929
916
|
// Set
|
930
917
|
var editor = $('<div>', {
|
931
|
-
'class':
|
918
|
+
'class': this.instance.baseCSS("editor-block") + ' ' + this._getBlockClass(),
|
932
919
|
html: el
|
933
920
|
});
|
934
921
|
|
935
|
-
this.$el = $('<div>', {
|
936
|
-
'class': this.instance.
|
922
|
+
this.$el = $('<div>', {
|
923
|
+
'class': this.instance.baseCSS("block"),
|
937
924
|
id: this.blockID,
|
938
925
|
"data-type": this.type,
|
939
926
|
"data-instance": this.instance.ID,
|
@@ -951,13 +938,16 @@
|
|
951
938
|
if (SirTrevor.Blocks[block].prototype == Object.getPrototypeOf(this)) {
|
952
939
|
objName = block;
|
953
940
|
}
|
954
|
-
}
|
941
|
+
}
|
955
942
|
return objName;
|
956
943
|
},
|
944
|
+
|
945
|
+
_getBlockClass: function() {
|
946
|
+
return this.className + '-block';
|
947
|
+
},
|
957
948
|
|
958
949
|
/*
|
959
950
|
* Init functions for adding functionality
|
960
|
-
*
|
961
951
|
*/
|
962
952
|
|
963
953
|
_initDragDrop: function() {
|
@@ -965,18 +955,24 @@
|
|
965
955
|
|
966
956
|
this.$dropzone = $("<div>", {
|
967
957
|
html: this.dropzoneHTML,
|
968
|
-
class: "dropzone " + this.
|
958
|
+
'class': "dropzone " + this._getBlockClass()
|
969
959
|
});
|
970
960
|
this.$el.append(this.$dropzone);
|
971
961
|
this.$editor.hide();
|
972
|
-
|
962
|
+
|
973
963
|
// Bind our drop event
|
974
|
-
this.$dropzone.
|
975
|
-
|
964
|
+
this.$dropzone.bind('drop', this._handleDrop)
|
965
|
+
.bind('dragenter', function(e) { halt(e); $(this).addClass('drag-enter'); })
|
966
|
+
.bind('dragover', function(e) {
|
967
|
+
e.originalEvent.dataTransfer.dropEffect = "copy";
|
968
|
+
halt(e);
|
969
|
+
$(this).addClass('drag-enter');
|
970
|
+
})
|
971
|
+
.bind('dragleave', function(e) { halt(e); $(this).removeClass('drag-enter'); });
|
976
972
|
},
|
977
973
|
|
978
974
|
_initReordering: function() {
|
979
|
-
this.$('.handle
|
975
|
+
this.$('.' + this.instance.baseCSS("drag-handle"))
|
980
976
|
.bind('dragstart', this.onDragStart)
|
981
977
|
.bind('dragend', this.onDragEnd)
|
982
978
|
.bind('drag', this.instance.marker.show);
|
@@ -1013,7 +1009,6 @@
|
|
1013
1009
|
var Format = SirTrevor.Formatter = function(options){
|
1014
1010
|
this.formatId = _.uniqueId('format-');
|
1015
1011
|
this._configure(options || {});
|
1016
|
-
this.className = SirTrevor.DEFAULTS.baseCSSClass + "-format-" + this.options.className;
|
1017
1012
|
this.initialize.apply(this, arguments);
|
1018
1013
|
};
|
1019
1014
|
|
@@ -1073,7 +1068,7 @@
|
|
1073
1068
|
SirTrevor.Blocks.Quote = SirTrevor.Block.extend({
|
1074
1069
|
|
1075
1070
|
title: "Quote",
|
1076
|
-
className: "
|
1071
|
+
className: "quote",
|
1077
1072
|
limit: 0,
|
1078
1073
|
|
1079
1074
|
editorHTML: function() {
|
@@ -1328,9 +1323,6 @@
|
|
1328
1323
|
/*
|
1329
1324
|
Text Block
|
1330
1325
|
*/
|
1331
|
-
|
1332
|
-
var tb_template =
|
1333
|
-
|
1334
1326
|
SirTrevor.Blocks.Text = SirTrevor.Block.extend({
|
1335
1327
|
|
1336
1328
|
title: "Text",
|
@@ -1344,7 +1336,7 @@
|
|
1344
1336
|
}
|
1345
1337
|
});
|
1346
1338
|
var t_template = '<p>Drop tweet link here</p><div class="input text"><label>or paste URL:</label><input type="text" class="paste-block"></div>';
|
1347
|
-
var tweet_template = '<div class="tweet
|
1339
|
+
var tweet_template = '<div class="tweet"><img src="<%= user.profile_image_url %>" class="tweet-avatar"><div class="tweet-body"><p class="tweet-user"><a href="http://twitter.com/#!/<%= user.screen_name %>" class="tweet-user">@<%= user.screen_name %></a> on Twitter</p><p class="tweet-text"><%= text %></p><time><%= created_at %></time></div></div>';
|
1348
1340
|
|
1349
1341
|
SirTrevor.Blocks.Tweet = SirTrevor.Block.extend({
|
1350
1342
|
|
@@ -1407,7 +1399,7 @@
|
|
1407
1399
|
|
1408
1400
|
// Make our AJAX call
|
1409
1401
|
$.ajax({
|
1410
|
-
url: "
|
1402
|
+
url: "http://api.twitter.com/1/statuses/show/" + tweetID + ".json",
|
1411
1403
|
dataType: "JSONP",
|
1412
1404
|
success: _.bind(tweetCallbackSuccess, this),
|
1413
1405
|
error: _.bind(tweetCallbackFail, this)
|
@@ -1576,8 +1568,8 @@
|
|
1576
1568
|
|
1577
1569
|
if(link && link.length > 0) {
|
1578
1570
|
|
1579
|
-
if (!link_regex.test(link)) {
|
1580
|
-
link = "http://" + link;
|
1571
|
+
if (!link_regex.test(link)) {
|
1572
|
+
link = "http://" + link;
|
1581
1573
|
}
|
1582
1574
|
|
1583
1575
|
document.execCommand(this.cmd, false, link);
|
@@ -1591,37 +1583,6 @@
|
|
1591
1583
|
cmd: "unlink"
|
1592
1584
|
});
|
1593
1585
|
|
1594
|
-
var Heading1 = SirTrevor.Formatter.extend({
|
1595
|
-
|
1596
|
-
title: "H1",
|
1597
|
-
className: "heading h1",
|
1598
|
-
cmd: "formatBlock",
|
1599
|
-
param: "H1",
|
1600
|
-
|
1601
|
-
toMarkdown: function(markdown) {
|
1602
|
-
return markdown.replace(/<h1>([^*|_]+)<\/h1>/mg,"#$1#\n");
|
1603
|
-
},
|
1604
|
-
|
1605
|
-
toHTML: function(html) {
|
1606
|
-
return html.replace(/(?:#)([^*|_]+)(?:#)/mg,"<h1>$1</h1>");
|
1607
|
-
}
|
1608
|
-
});
|
1609
|
-
|
1610
|
-
var Heading2 = SirTrevor.Formatter.extend({
|
1611
|
-
title: "H2",
|
1612
|
-
className: "heading h2",
|
1613
|
-
cmd: "formatBlock",
|
1614
|
-
param: "H2",
|
1615
|
-
|
1616
|
-
toMarkdown: function(markdown) {
|
1617
|
-
return markdown.replace(/<h2>([^*|_]+)<\/h2>/mg,"##$1##\n");
|
1618
|
-
},
|
1619
|
-
|
1620
|
-
toHTML: function(html) {
|
1621
|
-
return html.replace(/(?:##)([^*|_]+)(?:##)/mg,"<h2>$1</h2>");
|
1622
|
-
}
|
1623
|
-
});
|
1624
|
-
|
1625
1586
|
/*
|
1626
1587
|
Create our formatters and add a static reference to them
|
1627
1588
|
*/
|
@@ -1629,8 +1590,6 @@
|
|
1629
1590
|
SirTrevor.Formatters.Italic = new Italic();
|
1630
1591
|
SirTrevor.Formatters.Link = new Link();
|
1631
1592
|
SirTrevor.Formatters.Unlink = new UnLink();
|
1632
|
-
//SirTrevor.Formatters.Heading1 = new Heading1();
|
1633
|
-
//SirTrevor.Formatters.Heading2 = new Heading2();
|
1634
1593
|
/* Marker */
|
1635
1594
|
/*
|
1636
1595
|
SirTrevor Marker
|
@@ -1649,22 +1608,28 @@
|
|
1649
1608
|
bound: ["onButtonClick", "show", "hide", "onDrop"],
|
1650
1609
|
|
1651
1610
|
render: function() {
|
1652
|
-
|
1653
|
-
var marker = $('<
|
1654
|
-
'class': this.instance.
|
1655
|
-
html: '<p>' + this.options.addText + '</p
|
1611
|
+
|
1612
|
+
var marker = $('<div>', {
|
1613
|
+
'class': this.instance.baseCSS(this.options.baseCSSClass),
|
1614
|
+
html: '<p>' + this.options.addText + '</p>'
|
1615
|
+
});
|
1616
|
+
|
1617
|
+
var btns_cont = $("<div>", {
|
1618
|
+
'class': this.instance.baseCSS("buttons")
|
1656
1619
|
});
|
1620
|
+
|
1621
|
+
marker.append(btns_cont);
|
1657
1622
|
|
1658
1623
|
// Bind to the wrapper
|
1659
1624
|
this.instance.$wrapper.append(marker);
|
1660
1625
|
|
1661
1626
|
// Cache our elements for later use
|
1662
1627
|
this.$el = marker;
|
1663
|
-
this.$btns =
|
1628
|
+
this.$btns = btns_cont;
|
1664
1629
|
this.$p = this.$el.find('p');
|
1665
1630
|
|
1666
1631
|
// Add all of our buttons
|
1667
|
-
var blockName, block;
|
1632
|
+
var blockName, block;
|
1668
1633
|
|
1669
1634
|
for (blockName in this.instance.blockTypes) {
|
1670
1635
|
if (SirTrevor.Blocks.hasOwnProperty(blockName)) {
|
@@ -1673,11 +1638,11 @@
|
|
1673
1638
|
this.$btns.append(
|
1674
1639
|
$("<a>", {
|
1675
1640
|
"href": "#",
|
1676
|
-
"class": this.options.buttonClass + " new-" + block.prototype.className,
|
1641
|
+
"class": this.instance.baseCSS(this.options.buttonClass) + " new-" + block.prototype.className,
|
1677
1642
|
"data-type": blockName,
|
1678
1643
|
"text": block.prototype.title,
|
1679
1644
|
click: this.onButtonClick
|
1680
|
-
})
|
1645
|
+
})
|
1681
1646
|
);
|
1682
1647
|
}
|
1683
1648
|
}
|
@@ -1687,64 +1652,69 @@
|
|
1687
1652
|
if(this.$btns.children().length === 0) this.$el.addClass('hidden');
|
1688
1653
|
|
1689
1654
|
// Bind our marker to the wrapper
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
this.$
|
1655
|
+
var throttled_show = _.throttle(this.show, 0),
|
1656
|
+
throttled_hide = _.throttle(this.hide, 0);
|
1657
|
+
|
1658
|
+
this.instance.$outer.bind('mouseover', throttled_show)
|
1659
|
+
.bind('mouseout', throttled_hide)
|
1660
|
+
.bind('dragover', throttled_show);
|
1661
|
+
|
1662
|
+
this.$el.bind('dragover', halt);
|
1694
1663
|
|
1695
1664
|
// Bind the drop function onto here
|
1696
|
-
this.instance.$outer.dropArea()
|
1697
|
-
|
1698
|
-
|
1665
|
+
this.instance.$outer.dropArea()
|
1666
|
+
.bind('dragleave', throttled_hide)
|
1667
|
+
.bind('drop', this.onDrop);
|
1699
1668
|
|
1700
|
-
this.$el.addClass(
|
1669
|
+
this.$el.addClass(this.instance.baseCSS("item-ready"));
|
1701
1670
|
},
|
1702
1671
|
|
1703
|
-
show: function(ev){
|
1704
|
-
|
1672
|
+
show: function(ev) {
|
1673
|
+
var target = $(ev.target),
|
1674
|
+
target_parent = target.parent();
|
1675
|
+
|
1676
|
+
if (target.is(this.$el) || target.is(this.$btns) || target_parent.is(this.$el) || target_parent.is(this.$btns)) {
|
1677
|
+
this.$el.addClass(this.instance.baseCSS("item-ready"));
|
1678
|
+
return;
|
1679
|
+
}
|
1680
|
+
|
1705
1681
|
if(ev.type == 'drag' || ev.type == 'dragover') {
|
1682
|
+
this.$el.addClass('drop-zone');
|
1706
1683
|
this.$p.text(this.options.dropText);
|
1707
1684
|
this.$btns.hide();
|
1708
1685
|
} else {
|
1686
|
+
this.$el.removeClass('drop-zone');
|
1709
1687
|
this.$p.text(this.options.addText);
|
1710
1688
|
this.$btns.show();
|
1711
1689
|
}
|
1690
|
+
|
1691
|
+
// Check to see we're not over the formatting bar
|
1692
|
+
if (target.is(this.instance.formatBar.$el) || target_parent.is(this.instance.formatBar.$el)) {
|
1693
|
+
return this.hide();
|
1694
|
+
}
|
1712
1695
|
|
1713
1696
|
var mouse_enter = (ev) ? ev.originalEvent.pageY - this.instance.$wrapper.offset().top : 0;
|
1714
|
-
|
1697
|
+
|
1715
1698
|
// Do we have any sedit blocks?
|
1716
1699
|
if (this.instance.blocks.length > 0) {
|
1717
1700
|
|
1718
1701
|
// Find the closest block to this position
|
1719
|
-
var closest_block =
|
1720
|
-
wrapper = this.instance.$wrapper,
|
1721
|
-
blockClass = "." + this.instance.options.baseCSSClass + "-block";
|
1722
|
-
|
1723
|
-
var blockIterator = function(block, index) {
|
1724
|
-
block = $(block);
|
1725
|
-
var block_top = block.position().top - 40,
|
1726
|
-
block_bottom = block.position().top + block.outerHeight(true) - 40;
|
1727
|
-
|
1728
|
-
if(block_top <= mouse_enter && mouse_enter < block_bottom) {
|
1729
|
-
closest_block = block;
|
1730
|
-
}
|
1731
|
-
};
|
1732
|
-
_.each(wrapper.find(blockClass), _.bind(blockIterator, this));
|
1702
|
+
var closest_block = this.findClosestBlock(mouse_enter);
|
1733
1703
|
|
1734
1704
|
// Position it
|
1735
1705
|
if (closest_block) {
|
1736
1706
|
this.$el.insertBefore(closest_block);
|
1737
1707
|
} else if(mouse_enter > 0) {
|
1738
|
-
this.$el.insertAfter(
|
1708
|
+
this.$el.insertAfter(this.instance.cachedDomBlocks.last());
|
1739
1709
|
} else {
|
1740
|
-
this.$el.insertBefore(
|
1710
|
+
this.$el.insertBefore(this.instance.cachedDomBlocks.first());
|
1741
1711
|
}
|
1742
1712
|
}
|
1743
|
-
this.$el.addClass(
|
1713
|
+
this.$el.addClass(this.instance.baseCSS("item-ready"));
|
1744
1714
|
},
|
1745
1715
|
|
1746
|
-
hide: function(ev){
|
1747
|
-
this.$el.removeClass(
|
1716
|
+
hide: function(ev){
|
1717
|
+
this.$el.removeClass(this.instance.baseCSS("item-ready"));
|
1748
1718
|
},
|
1749
1719
|
|
1750
1720
|
onDrop: function(ev){
|
@@ -1758,9 +1728,27 @@
|
|
1758
1728
|
marker.after(block);
|
1759
1729
|
}
|
1760
1730
|
},
|
1731
|
+
|
1732
|
+
findClosestBlock: function(mouse_enter) {
|
1733
|
+
var closest_block = false;
|
1734
|
+
|
1735
|
+
var blockIterator = function(block, index) {
|
1736
|
+
block = $(block);
|
1737
|
+
|
1738
|
+
var block_top = block.offset().top - 40,
|
1739
|
+
block_bottom = block.offset().top + block.outerHeight(true) - 40;
|
1740
|
+
|
1741
|
+
if(block_top <= mouse_enter && mouse_enter < block_bottom) {
|
1742
|
+
closest_block = block;
|
1743
|
+
}
|
1744
|
+
};
|
1745
|
+
_.each(this.instance.cachedDomBlocks, _.bind(blockIterator, this));
|
1746
|
+
|
1747
|
+
return closest_block;
|
1748
|
+
},
|
1761
1749
|
|
1762
1750
|
remove: function(){ this.$el.remove(); },
|
1763
|
-
|
1751
|
+
|
1764
1752
|
onButtonClick: function(ev){
|
1765
1753
|
halt(ev);
|
1766
1754
|
var button = $(ev.target);
|
@@ -1774,11 +1762,9 @@
|
|
1774
1762
|
},
|
1775
1763
|
|
1776
1764
|
move: function(top) {
|
1777
|
-
this.$el.css({
|
1778
|
-
|
1779
|
-
|
1780
|
-
this.$el.show();
|
1781
|
-
this.$el.addClass('sir-trevor-item-ready');
|
1765
|
+
this.$el.css({ top: top })
|
1766
|
+
.show()
|
1767
|
+
.addClass(this.instance.baseCSS("item-ready"));
|
1782
1768
|
}
|
1783
1769
|
});
|
1784
1770
|
|
@@ -1796,7 +1782,7 @@
|
|
1796
1782
|
var FormatBar = SirTrevor.FormatBar = function(options, editorInstance) {
|
1797
1783
|
this.instance = editorInstance;
|
1798
1784
|
this.options = _.extend({}, SirTrevor.DEFAULTS.formatBar, options || {});
|
1799
|
-
this.className = this.instance.
|
1785
|
+
this.className = this.instance.baseCSS(this.options.baseCSSClass);
|
1800
1786
|
this.clicked = false;
|
1801
1787
|
this._bindFunctions();
|
1802
1788
|
};
|
@@ -1806,7 +1792,6 @@
|
|
1806
1792
|
bound: ["onFormatButtonClick"],
|
1807
1793
|
|
1808
1794
|
render: function(){
|
1809
|
-
|
1810
1795
|
var bar = $("<div>", {
|
1811
1796
|
"class": this.className
|
1812
1797
|
});
|
@@ -1821,7 +1806,7 @@
|
|
1821
1806
|
if (SirTrevor.Formatters.hasOwnProperty(formatName)) {
|
1822
1807
|
format = SirTrevor.Formatters[formatName];
|
1823
1808
|
$("<button>", {
|
1824
|
-
'class':
|
1809
|
+
'class': this.instance.baseCSS("format-button"),
|
1825
1810
|
'text': format.title,
|
1826
1811
|
'data-type': formatName,
|
1827
1812
|
'data-cmd': format.cmd,
|
@@ -1830,45 +1815,56 @@
|
|
1830
1815
|
}
|
1831
1816
|
}
|
1832
1817
|
|
1818
|
+
var throttled_scroll = _.throttle(_.bind(this.handleDocumentScroll, this), 150);
|
1819
|
+
$(document).bind('scroll', throttled_scroll);
|
1820
|
+
|
1833
1821
|
if(this.$el.find('button').length === 0) this.$el.addClass('hidden');
|
1834
|
-
|
1835
|
-
this.hide();
|
1836
|
-
this.$el.bind('mouseout', _.bind(function(ev){ halt(ev); this.clicked = false; }, this));
|
1837
|
-
this.$el.bind('mouseover', halt);
|
1822
|
+
this.show();
|
1838
1823
|
},
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
this.$el.
|
1846
|
-
|
1824
|
+
|
1825
|
+
handleDocumentScroll: function() {
|
1826
|
+
var instance_height = this.instance.$outer.height(),
|
1827
|
+
instance_offset = this.instance.$outer.offset().top,
|
1828
|
+
viewport_top = $(document).scrollTop();
|
1829
|
+
|
1830
|
+
if (this.$el.hasClass('fixed')) {
|
1831
|
+
instance_offset = this.$el.offset().top;
|
1832
|
+
}
|
1833
|
+
|
1834
|
+
if ((viewport_top > 5) && viewport_top >= instance_offset) {
|
1835
|
+
this.$el.addClass('fixed');
|
1836
|
+
this.instance.$wrapper.css({ 'padding-top': '104px' });
|
1837
|
+
} else {
|
1838
|
+
this.$el.removeClass('fixed');
|
1839
|
+
this.instance.$wrapper.css({ 'padding-top': '16px' });
|
1840
|
+
}
|
1847
1841
|
},
|
1848
1842
|
|
1849
|
-
hide: function(){
|
1850
|
-
this.
|
1851
|
-
this.$el.removeClass('sir-trevor-item-ready');
|
1852
|
-
this.$el.hide();
|
1843
|
+
hide: function() {
|
1844
|
+
this.$el.removeClass(this.instance.baseCSS('item-ready'));
|
1853
1845
|
},
|
1854
|
-
|
1846
|
+
|
1847
|
+
show: function() {
|
1848
|
+
this.$el.addClass(this.instance.baseCSS('item-ready'));
|
1849
|
+
},
|
1850
|
+
|
1855
1851
|
remove: function(){ this.$el.remove(); },
|
1856
1852
|
|
1857
1853
|
onFormatButtonClick: function(ev){
|
1858
1854
|
halt(ev);
|
1859
|
-
|
1855
|
+
|
1860
1856
|
var btn = $(ev.target),
|
1861
1857
|
format = SirTrevor.Formatters[btn.attr('data-type')];
|
1862
1858
|
|
1863
|
-
// Do we have a click function defined on this formatter?
|
1859
|
+
// Do we have a click function defined on this formatter?
|
1864
1860
|
if(!_.isUndefined(format.onClick) && _.isFunction(format.onClick)) {
|
1865
1861
|
format.onClick(); // Delegate
|
1866
1862
|
} else {
|
1867
1863
|
// Call default
|
1868
1864
|
document.execCommand(btn.attr('data-cmd'), false, format.param);
|
1869
|
-
}
|
1865
|
+
}
|
1870
1866
|
// Make sure we still show the bar
|
1871
|
-
this
|
1867
|
+
this.show();
|
1872
1868
|
}
|
1873
1869
|
|
1874
1870
|
});
|
@@ -1889,6 +1885,7 @@
|
|
1889
1885
|
this.blockCounts = {}; // Cached block type counts
|
1890
1886
|
this.blocks = []; // Block references
|
1891
1887
|
this.errors = [];
|
1888
|
+
this.cachedDomBlocks = [];
|
1892
1889
|
this.options = _.extend({}, SirTrevor.DEFAULTS, options || {});
|
1893
1890
|
this.ID = _.uniqueId(this.options.baseCSSClass + "-");
|
1894
1891
|
|
@@ -1948,7 +1945,7 @@
|
|
1948
1945
|
|
1949
1946
|
if(!_.isUndefined(this.onEditorRender)) {
|
1950
1947
|
this.onEditorRender();
|
1951
|
-
}
|
1948
|
+
}
|
1952
1949
|
},
|
1953
1950
|
|
1954
1951
|
store: function(){
|
@@ -1978,7 +1975,7 @@
|
|
1978
1975
|
return false;
|
1979
1976
|
}
|
1980
1977
|
|
1981
|
-
var block = new blockType(this, data || {});
|
1978
|
+
var block = new blockType(this, data || {});
|
1982
1979
|
|
1983
1980
|
if (_.isUndefined(this.blockCounts[type])) {
|
1984
1981
|
this.blockCounts[type] = 0;
|
@@ -1998,18 +1995,19 @@
|
|
1998
1995
|
this.marker.$el.find('[data-type="' + type + '"]')
|
1999
1996
|
.addClass('inactive')
|
2000
1997
|
.attr('title','You have reached the limit for this type of block');
|
2001
|
-
}
|
1998
|
+
}
|
2002
1999
|
|
2003
2000
|
SirTrevor.publish("editor/block/createBlock");
|
2004
2001
|
|
2005
2002
|
SirTrevor.log("Block created of type " + type);
|
2003
|
+
this.cachedDomBlocks = this.$wrapper.find('.' + this.baseCSS("block"));
|
2006
2004
|
} else {
|
2007
2005
|
SirTrevor.log("Block type not available " + type);
|
2008
2006
|
}
|
2009
2007
|
},
|
2010
2008
|
|
2011
2009
|
removeBlock: function(block) {
|
2012
|
-
// Blocks exist purely on the dom.
|
2010
|
+
// Blocks exist purely on the dom.
|
2013
2011
|
// Remove the block and decrement the blockCount
|
2014
2012
|
block.remove();
|
2015
2013
|
this.blockCounts[block.type] = this.blockCounts[block.type] - 1;
|
@@ -2017,9 +2015,9 @@
|
|
2017
2015
|
// Remove the block from our store
|
2018
2016
|
this.blocks = _.reject(this.blocks, function(item){ return (item.blockID == block.blockID); });
|
2019
2017
|
if(_.isUndefined(this.blocks)) this.blocks = [];
|
2020
|
-
this.formatBar.hide();
|
2021
2018
|
|
2022
2019
|
SirTrevor.publish("editor/block/removeBlock");
|
2020
|
+
this.cachedDomBlocks = this.$wrapper.find('.' + this.baseCSS("block"));
|
2023
2021
|
|
2024
2022
|
// Remove our inactive class if it's no longer relevant
|
2025
2023
|
if(this._getBlockTypeLimit(block.type) > this.blockCounts[block.type]) {
|
@@ -2066,8 +2064,7 @@
|
|
2066
2064
|
SirTrevor.log("Handling form submission for Editor " + this.ID);
|
2067
2065
|
|
2068
2066
|
var blockLength, block, result, errors = 0;
|
2069
|
-
|
2070
|
-
this.formatBar.hide();
|
2067
|
+
|
2071
2068
|
this.removeErrors();
|
2072
2069
|
// Reset our store
|
2073
2070
|
this.store("reset", this);
|
@@ -2100,7 +2097,7 @@
|
|
2100
2097
|
errors++;
|
2101
2098
|
|
2102
2099
|
} else {
|
2103
|
-
// We need to also validate that we have some data of this type too.
|
2100
|
+
// We need to also validate that we have some data of this type too.
|
2104
2101
|
// This is ugly, but necessary for proper validation on blocks that don't have required fields.
|
2105
2102
|
var blocks = _.filter(this.blocks, function(b){ return (b.type == type && !_.isEmpty(b.getData())); });
|
2106
2103
|
|
@@ -2128,7 +2125,7 @@
|
|
2128
2125
|
|
2129
2126
|
if (_.isUndefined(this.$errors)) {
|
2130
2127
|
this.$errors = $("<div>", {
|
2131
|
-
class: this.
|
2128
|
+
'class': this.baseCSS("errors"),
|
2132
2129
|
html: "<p>You have the following errors: </p><ul></ul>"
|
2133
2130
|
});
|
2134
2131
|
this.$outer.prepend(this.$errors);
|
@@ -2138,7 +2135,7 @@
|
|
2138
2135
|
|
2139
2136
|
_.each(this.errors, _.bind(function(error) {
|
2140
2137
|
list.append($("<li>", {
|
2141
|
-
class: "error-msg",
|
2138
|
+
'class': this.baseCSS("error-msg"),
|
2142
2139
|
html: error.text
|
2143
2140
|
}));
|
2144
2141
|
}, this));
|
@@ -2182,7 +2179,6 @@
|
|
2182
2179
|
},
|
2183
2180
|
|
2184
2181
|
_ensureAndSetElements: function() {
|
2185
|
-
|
2186
2182
|
if(_.isUndefined(this.options.el) || _.isEmpty(this.options.el)) {
|
2187
2183
|
SirTrevor.log("You must provide an el");
|
2188
2184
|
return false;
|
@@ -2192,19 +2188,15 @@
|
|
2192
2188
|
this.el = this.options.el[0];
|
2193
2189
|
this.$form = this.$el.parents('form');
|
2194
2190
|
|
2191
|
+
var blockCSSClass = this.baseCSS("blocks");
|
2192
|
+
|
2195
2193
|
// Wrap our element in lots of containers *eww*
|
2196
|
-
this.$el.wrap($('<div>', {
|
2197
|
-
|
2198
|
-
'class': this.options.baseCSSClass,
|
2199
|
-
dropzone: 'copy link move'
|
2200
|
-
})
|
2201
|
-
)
|
2202
|
-
.wrap($("<div>", {
|
2203
|
-
class: this.options.baseCSSClass + "-blocks"
|
2204
|
-
}));
|
2194
|
+
this.$el.wrap($('<div>', { id: this.ID, 'class': this.options.baseCSSClass, dropzone: 'copy link move' }))
|
2195
|
+
.wrap($("<div>", { 'class': blockCSSClass }));
|
2205
2196
|
|
2206
|
-
this.$outer = this.$form.find('#' + this.ID);
|
2207
|
-
this.$wrapper = this.$outer.find("." +
|
2197
|
+
this.$outer = this.$form.find('#' + this.ID);
|
2198
|
+
this.$wrapper = this.$outer.find("." + blockCSSClass);
|
2199
|
+
|
2208
2200
|
return true;
|
2209
2201
|
},
|
2210
2202
|
|
@@ -2215,7 +2207,7 @@
|
|
2215
2207
|
*/
|
2216
2208
|
_setBlocksAndFormatters: function() {
|
2217
2209
|
this.blockTypes = flattern((_.isUndefined(this.options.blockTypes)) ? SirTrevor.Blocks : this.options.blockTypes);
|
2218
|
-
this.formatters = flattern((_.isUndefined(this.options.formatters)) ? SirTrevor.Formatters : this.options.formatters);
|
2210
|
+
this.formatters = flattern((_.isUndefined(this.options.formatters)) ? SirTrevor.Formatters : this.options.formatters);
|
2219
2211
|
},
|
2220
2212
|
|
2221
2213
|
/* Get our required blocks (if any) */
|
@@ -2256,7 +2248,7 @@
|
|
2256
2248
|
.replace(/(?:<div>)(?:<br>)?([^<>]+)(?:<br>)?(?:<\/div>)/g,"$1\n\n") // ^ (handle content inside divs)
|
2257
2249
|
.replace(/<\/p>/g,"\n\n\n\n") // P tags as line breaks
|
2258
2250
|
.replace(/<(.)?br(.)?>/g,"\n\n") // Convert normal line breaks
|
2259
|
-
.replace(/ /g," ") // Strip white-space entities
|
2251
|
+
.replace(/ /g," ") // Strip white-space entities
|
2260
2252
|
.replace(/</g,"<").replace(/>/g,">"); // Encoding
|
2261
2253
|
|
2262
2254
|
|
@@ -2271,9 +2263,8 @@
|
|
2271
2263
|
}
|
2272
2264
|
|
2273
2265
|
// Strip remaining HTML
|
2274
|
-
markdown = markdown.replace(/<\/?[^>]+(>|$)/g, "");
|
2266
|
+
markdown = markdown.replace(/<\/?[^>]+(>|$)/g, "");
|
2275
2267
|
|
2276
|
-
|
2277
2268
|
return markdown;
|
2278
2269
|
},
|
2279
2270
|
|
@@ -2313,7 +2304,11 @@
|
|
2313
2304
|
.replace(/(?:_)([^*|_(http)]+)(?:_)/g,"<i>$1</i>") // Italic, avoid italicizing two links with underscores next to each other
|
2314
2305
|
.replace(/(?:\*\*)([^*|_]+)(?:\*\*)/g,"<b>$1</b>"); // Bold
|
2315
2306
|
|
2316
|
-
return html;
|
2307
|
+
return html;
|
2308
|
+
},
|
2309
|
+
|
2310
|
+
baseCSS: function(additional) {
|
2311
|
+
return this.options.baseCSSClass + "-" + additional;
|
2317
2312
|
}
|
2318
2313
|
});
|
2319
2314
|
|
@@ -2346,7 +2341,7 @@
|
|
2346
2341
|
if(errors > 0) {
|
2347
2342
|
SirTrevor.publish("onError");
|
2348
2343
|
ev.preventDefault();
|
2349
|
-
}
|
2344
|
+
}
|
2350
2345
|
};
|
2351
2346
|
|
2352
2347
|
SirTrevor.runOnAllInstances = function(method) {
|