sir-trevor-rails 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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) {
|