medium-editor-rails 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfa61058f24f4aaef259ebf7d18b0669562b4e92
4
- data.tar.gz: e8c632c87912135a6b0a00a8a2d730e1ef4e3c87
3
+ metadata.gz: 86d22c2442a80cae4e0997c6a788c195496b2836
4
+ data.tar.gz: f4f81a42f77f9b2c3c7ace98cd4269ac413ac328
5
5
  SHA512:
6
- metadata.gz: 1cc900d59e3b0a79d9c7e0ca7bf95dc2e099c11d19225984932df294d37596c5ca8f01a4a70c0951ca6fb897daab4edb17cbe670d6c864cf97efcfe38a7c4986
7
- data.tar.gz: e38c565f410987e53920976f1aea84cddf77ce65403f0c4ade06d4106a6af53c9fef55a2c6427c9293a82e3805a2078eadff6f9080a4a0827ae28d73df78d9eb
6
+ metadata.gz: 525972afada765ebaf19a3f578f91dee550ba2265156cd90cd593d9cec71b30be68ae12b373c50b2e178a1e8da7274a2cab78cfa751cfc675912736d2a0174fc
7
+ data.tar.gz: 3d55b39f3304655c211e16be61c5d0ba6199055d0ea0950443b5a08ee73e58d560e400a8ae9b8353844331dcbe9c6c8deff369cf54baf806bf1262c5e899cd22
data/CHANGELOG.md CHANGED
@@ -1,6 +1,15 @@
1
1
 
2
2
  #### [Current]
3
+ * [6e3450b](../../commit/6e3450b) - __(Ahmet Sezgin Duran)__ Bump versions 1.1.0 and 2.1.0
4
+ * [c3d9387](../../commit/c3d9387) - __(Ahmet Sezgin Duran)__ Update Medium Editor files
5
+ * [ecf87f3](../../commit/ecf87f3) - __(Ahmet Sezgin Duran)__ Merge tag '1.0.0' into develop
6
+
7
+ 1.0.0
8
+
9
+ #### 1.0.0
10
+ * [959341e](../../commit/959341e) - __(Ahmet Sezgin Duran)__ Dump changelog
3
11
  * [fb35ea2](../../commit/fb35ea2) - __(Ahmet Sezgin Duran)__ Bump versions 1.0.0 and 2.0.0
12
+ * [97d7aeb](../../commit/97d7aeb) - __(Ahmet Sezgin Duran)__ Update Medium Editor files
4
13
  * [937e1f2](../../commit/937e1f2) - __(Ahmet Sezgin Duran)__ Merge tag '0.13.1' into develop
5
14
 
6
15
  0.13.1 0.13.1
data/README.md CHANGED
@@ -8,7 +8,7 @@ This gem integrates [Medium Editor](https://github.com/daviferreira/medium-edito
8
8
 
9
9
  ## Version
10
10
 
11
- The latest version of Medium Editor bundled by this gem is [2.0.0](https://github.com/daviferreira/medium-editor/releases)
11
+ The latest version of Medium Editor bundled by this gem is [2.1.0](https://github.com/daviferreira/medium-editor/releases)
12
12
 
13
13
  ## Installation
14
14
 
@@ -1,6 +1,6 @@
1
1
  module MediumEditorRails
2
2
  module Rails
3
- VERSION = '1.0.0'
4
- MEDIUM_EDITOR_VERSION = '2.0.0'
3
+ VERSION = '1.1.0'
4
+ MEDIUM_EDITOR_VERSION = '2.1.0'
5
5
  end
6
6
  end
@@ -30,6 +30,54 @@ else if (typeof define === 'function' && define.amd) {
30
30
  return b;
31
31
  }
32
32
 
33
+ // https://github.com/jashkenas/underscore
34
+ var now = Date.now || function() {
35
+ return new Date().getTime();
36
+ };
37
+
38
+ // https://github.com/jashkenas/underscore
39
+ function throttle(func, wait) {
40
+ var THROTTLE_INTERVAL = 50,
41
+ context,
42
+ args,
43
+ result,
44
+ timeout = null,
45
+ previous = 0,
46
+ later;
47
+
48
+ if (!wait && wait !== 0) {
49
+ wait = THROTTLE_INTERVAL;
50
+ }
51
+
52
+ later = function() {
53
+ previous = now();
54
+ timeout = null;
55
+ result = func.apply(context, args);
56
+ if (!timeout) {
57
+ context = args = null;
58
+ }
59
+ };
60
+
61
+ return function() {
62
+ var currNow = now(),
63
+ remaining = wait - (currNow - previous);
64
+ context = this;
65
+ args = arguments;
66
+ if (remaining <= 0 || remaining > wait) {
67
+ clearTimeout(timeout);
68
+ timeout = null;
69
+ previous = currNow;
70
+ result = func.apply(context, args);
71
+ if (!timeout) {
72
+ context = args = null;
73
+ }
74
+ } else if (!timeout) {
75
+ timeout = setTimeout(later, remaining);
76
+ }
77
+ return result;
78
+ };
79
+ }
80
+
33
81
  function isDescendant(parent, child) {
34
82
  var node = child.parentNode;
35
83
  while (node !== null) {
@@ -41,6 +89,35 @@ else if (typeof define === 'function' && define.amd) {
41
89
  return false;
42
90
  }
43
91
 
92
+ // Find the next node in the DOM tree that represents any text that is being
93
+ // displayed directly next to the targetNode (passed as an argument)
94
+ // Text that appears directly next to the current node can be:
95
+ // - A sibling text node
96
+ // - A descendant of a sibling element
97
+ // - A sibling text node of an ancestor
98
+ // - A descendant of a sibling element of an ancestor
99
+ function findAdjacentTextNodeWithContent(rootNode, targetNode, ownerDocument) {
100
+ var pastTarget = false,
101
+ nextNode,
102
+ nodeIterator = ownerDocument.createNodeIterator(rootNode, NodeFilter.SHOW_TEXT);
103
+
104
+ // Use a native NodeIterator to iterate over all the text nodes that are descendants
105
+ // of the rootNode. Once past the targetNode, choose the first non-empty text node
106
+ nextNode = nodeIterator.nextNode();
107
+ while (nextNode) {
108
+ if (nextNode === targetNode) {
109
+ pastTarget = true;
110
+ } else if (pastTarget) {
111
+ if (nextNode.nodeType === 3 && nextNode.nodeValue.length > 0) {
112
+ break;
113
+ }
114
+ }
115
+ nextNode = nodeIterator.nextNode();
116
+ }
117
+
118
+ return nextNode;
119
+ }
120
+
44
121
  // http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element
45
122
  // by Tim Down
46
123
  function saveSelection() {
@@ -160,6 +237,7 @@ else if (typeof define === 'function' && define.amd) {
160
237
  disableAnchorForm: false,
161
238
  disablePlaceholders: false,
162
239
  elementsContainer: false,
240
+ standardizeSelectionStart: false,
163
241
  contentWindow: window,
164
242
  ownerDocument: document,
165
243
  firstHeader: 'h3',
@@ -190,7 +268,7 @@ else if (typeof define === 'function' && define.amd) {
190
268
  }
191
269
  this.parentElements = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre'];
192
270
  if (!this.options.elementsContainer) {
193
- this.options.elementsContainer = document.body;
271
+ this.options.elementsContainer = this.options.ownerDocument.body;
194
272
  }
195
273
 
196
274
  while (this.options.elementsContainer.querySelector('#medium-editor-toolbar-' + uniqueId)) {
@@ -205,7 +283,8 @@ else if (typeof define === 'function' && define.amd) {
205
283
  setup: function () {
206
284
  this.events = [];
207
285
  this.isActive = true;
208
- this.initElements()
286
+ this.initThrottledMethods()
287
+ .initElements()
209
288
  .bindSelect()
210
289
  .bindPaste()
211
290
  .setPlaceholders()
@@ -220,14 +299,34 @@ else if (typeof define === 'function' && define.amd) {
220
299
  },
221
300
 
222
301
  off: function(target, event, listener, useCapture) {
223
- var index = this.events.indexOf([target, event, listener, useCapture]),
302
+ var index = this.indexOfListener(target, event, listener, useCapture),
224
303
  e;
225
304
  if(index !== -1) {
226
- e = this.events.splice(index, 1);
305
+ e = this.events.splice(index, 1)[0];
227
306
  e[0].removeEventListener(e[1], e[2], e[3]);
228
307
  }
229
308
  },
230
309
 
310
+ indexOfListener: function(target, event, listener, useCapture) {
311
+ var i, n, item;
312
+ for (i = 0, n = this.events.length; i < n; i = i + 1) {
313
+ item = this.events[i];
314
+ if (item[0] === target && item[1] === event && item[2] === listener && item[3] === useCapture) {
315
+ return i;
316
+ }
317
+ }
318
+ return -1;
319
+ },
320
+
321
+ delay: function(fn) {
322
+ var self = this;
323
+ setTimeout(function() {
324
+ if (self.isActive) {
325
+ fn();
326
+ }
327
+ }, this.options.delay);
328
+ },
329
+
231
330
  removeAllEvents: function() {
232
331
  var e = this.events.pop();
233
332
  while(e) {
@@ -236,8 +335,32 @@ else if (typeof define === 'function' && define.amd) {
236
335
  }
237
336
  },
238
337
 
338
+ initThrottledMethods: function() {
339
+ var self = this;
340
+
341
+ // handleResize is throttled because:
342
+ // - It will be called when the browser is resizing, which can fire many times very quickly
343
+ // - For some event (like resize) a slight lag in UI responsiveness is OK and provides performance benefits
344
+ this.handleResize = throttle(function() {
345
+ if (self.isActive) {
346
+ self.positionToolbarIfShown();
347
+ }
348
+ });
349
+
350
+ // handleBlur is throttled because:
351
+ // - This method could be called many times due to the type of event handlers that are calling it
352
+ // - We want a slight delay so that other events in the stack can run, some of which may
353
+ // prevent the toolbar from being hidden (via this.keepToolbarAlive).
354
+ this.handleBlur = throttle(function() {
355
+ if (self.isActive && !self.keepToolbarAlive) {
356
+ self.hideToolbarActions();
357
+ }
358
+ });
359
+
360
+ return this;
361
+ },
362
+
239
363
  initElements: function () {
240
- this.updateElementList();
241
364
  var i,
242
365
  addToolbar = false;
243
366
  for (i = 0; i < this.elements.length; i += 1) {
@@ -248,6 +371,8 @@ else if (typeof define === 'function' && define.amd) {
248
371
  this.elements[i].setAttribute('data-placeholder', this.options.placeholder);
249
372
  }
250
373
  this.elements[i].setAttribute('data-medium-element', true);
374
+ this.elements[i].setAttribute('role', 'textbox');
375
+ this.elements[i].setAttribute('aria-multiline', true);
251
376
  this.bindParagraphCreation(i);
252
377
  if (!this.options.disableToolbar && !this.elements[i].getAttribute('data-disable-toolbar')) {
253
378
  addToolbar = true;
@@ -264,20 +389,23 @@ else if (typeof define === 'function' && define.amd) {
264
389
  },
265
390
 
266
391
  setElementSelection: function (selector) {
267
- this.elementSelection = selector;
268
- this.updateElementList();
269
- },
270
-
271
- updateElementList: function () {
272
- this.elements = typeof this.elementSelection === 'string' ? this.options.ownerDocument.querySelectorAll(this.elementSelection) : this.elementSelection;
273
- if (this.elements.nodeType === 1) {
274
- this.elements = [this.elements];
392
+ if (!selector) {
393
+ selector = [];
394
+ }
395
+ // If string, use as query selector
396
+ if (typeof selector === 'string') {
397
+ selector = this.options.ownerDocument.querySelectorAll(selector);
275
398
  }
399
+ // If element, put into array
400
+ if (isElement(selector)) {
401
+ selector = [selector];
402
+ }
403
+ // Convert NodeList (or other array like object) into an array
404
+ this.elements = Array.prototype.slice.apply(selector);
276
405
  },
277
406
 
278
407
  bindBlur: function(i) {
279
408
  var self = this,
280
- timeout,
281
409
  blurFunction = function(e){
282
410
  // If it's not part of the editor, or the toolbar
283
411
  if ( e.target !== self.toolbar
@@ -288,37 +416,17 @@ else if (typeof define === 'function' && define.amd) {
288
416
 
289
417
  // Activate the placeholder
290
418
  if (!self.options.disablePlaceholders) {
291
- self.placeholderWrapper(self.elements[0], e);
419
+ self.placeholderWrapper(e, self.elements[0]);
292
420
  }
293
421
 
294
- clearTimeout(timeout);
295
422
  // Hide the toolbar after a small delay so we can prevent this on toolbar click
296
- timeout = setTimeout(function(){
297
- if ( !self.keepToolbarAlive ) {
298
- self.hideToolbarActions();
299
- }
300
- }, 200);
423
+ self.handleBlur();
301
424
  }
302
425
  };
303
426
 
304
427
  // Hide the toolbar when focusing outside of the editor.
305
- this.on(document.body, 'click', blurFunction, true);
306
- this.on(document.body, 'focus', blurFunction, true);
307
-
308
- return this;
309
- },
310
-
311
- bindKeypress: function(i) {
312
- if (this.options.disablePlaceholders) {
313
- return this;
314
- }
315
-
316
- var self = this;
317
-
318
- // Set up the keypress events
319
- this.on(this.elements[i], 'keypress', function(event){
320
- self.placeholderWrapper(this,event);
321
- });
428
+ this.on(this.options.ownerDocument.body, 'click', blurFunction, true);
429
+ this.on(this.options.ownerDocument.body, 'focus', blurFunction, true);
322
430
 
323
431
  return this;
324
432
  },
@@ -358,9 +466,7 @@ else if (typeof define === 'function' && define.amd) {
358
466
  this.bindReturn(i)
359
467
  .bindTab(i)
360
468
  .bindBlur(i)
361
- .bindClick(i)
362
- .bindKeypress(i);
363
-
469
+ .bindClick(i);
364
470
  }
365
471
 
366
472
  return this;
@@ -368,7 +474,6 @@ else if (typeof define === 'function' && define.amd) {
368
474
 
369
475
  // Two functions to handle placeholders
370
476
  activatePlaceholder: function (el) {
371
-
372
477
  if (!(el.querySelector('img')) &&
373
478
  !(el.querySelector('blockquote')) &&
374
479
  el.textContent.replace(/^\s+|\s+$/g, '') === '') {
@@ -376,9 +481,10 @@ else if (typeof define === 'function' && define.amd) {
376
481
  el.classList.add('medium-editor-placeholder');
377
482
  }
378
483
  },
379
- placeholderWrapper: function (el, e) {
484
+ placeholderWrapper: function (evt, el) {
485
+ el = el || evt.target;
380
486
  el.classList.remove('medium-editor-placeholder');
381
- if (e.type !== 'keypress') {
487
+ if (evt.type !== 'keypress') {
382
488
  this.activatePlaceholder(el);
383
489
  }
384
490
  },
@@ -454,7 +560,7 @@ else if (typeof define === 'function' && define.amd) {
454
560
  node = getSelectionStart.call(self);
455
561
  tagName = node.tagName.toLowerCase();
456
562
  if (tagName === 'a') {
457
- document.execCommand('unlink', false, null);
563
+ self.options.ownerDocument.execCommand('unlink', false, null);
458
564
  }
459
565
  }
460
566
  });
@@ -465,7 +571,7 @@ else if (typeof define === 'function' && define.amd) {
465
571
  editorElement;
466
572
 
467
573
  if (node && node.getAttribute('data-medium-element') && node.children.length === 0 && !(self.options.disableReturn || node.getAttribute('data-disable-return'))) {
468
- document.execCommand('formatBlock', false, 'p');
574
+ self.options.ownerDocument.execCommand('formatBlock', false, 'p');
469
575
  }
470
576
  if (e.which === 13) {
471
577
  node = getSelectionStart.call(self);
@@ -475,10 +581,10 @@ else if (typeof define === 'function' && define.amd) {
475
581
  if (!(self.options.disableReturn || editorElement.getAttribute('data-disable-return')) &&
476
582
  tagName !== 'li' && !self.isListItemChild(node)) {
477
583
  if (!e.shiftKey) {
478
- document.execCommand('formatBlock', false, 'p');
584
+ self.options.ownerDocument.execCommand('formatBlock', false, 'p');
479
585
  }
480
586
  if (tagName === 'a') {
481
- document.execCommand('unlink', false, null);
587
+ self.options.ownerDocument.execCommand('unlink', false, null);
482
588
  }
483
589
  }
484
590
  }
@@ -528,7 +634,7 @@ else if (typeof define === 'function' && define.amd) {
528
634
  var tag = getSelectionStart.call(self).tagName.toLowerCase();
529
635
  if (tag === 'pre') {
530
636
  e.preventDefault();
531
- document.execCommand('insertHtml', null, ' ');
637
+ self.options.ownerDocument.execCommand('insertHtml', null, ' ');
532
638
  }
533
639
 
534
640
  // Tab to indent list structures!
@@ -537,9 +643,9 @@ else if (typeof define === 'function' && define.amd) {
537
643
 
538
644
  // If Shift is down, outdent, otherwise indent
539
645
  if (e.shiftKey) {
540
- document.execCommand('outdent', e);
646
+ self.options.ownerDocument.execCommand('outdent', e);
541
647
  } else {
542
- document.execCommand('indent', e);
648
+ self.options.ownerDocument.execCommand('indent', e);
543
649
  }
544
650
  }
545
651
  }
@@ -550,26 +656,26 @@ else if (typeof define === 'function' && define.amd) {
550
656
  buttonTemplate: function (btnType) {
551
657
  var buttonLabels = this.getButtonLabels(this.options.buttonLabels),
552
658
  buttonTemplates = {
553
- 'bold': '<button class="medium-editor-action medium-editor-action-bold" data-action="bold" data-element="b">' + buttonLabels.bold + '</button>',
554
- 'italic': '<button class="medium-editor-action medium-editor-action-italic" data-action="italic" data-element="i">' + buttonLabels.italic + '</button>',
555
- 'underline': '<button class="medium-editor-action medium-editor-action-underline" data-action="underline" data-element="u">' + buttonLabels.underline + '</button>',
556
- 'strikethrough': '<button class="medium-editor-action medium-editor-action-strikethrough" data-action="strikethrough" data-element="strike">' + buttonLabels.strikethrough +'</button>',
557
- 'superscript': '<button class="medium-editor-action medium-editor-action-superscript" data-action="superscript" data-element="sup">' + buttonLabels.superscript + '</button>',
558
- 'subscript': '<button class="medium-editor-action medium-editor-action-subscript" data-action="subscript" data-element="sub">' + buttonLabels.subscript + '</button>',
559
- 'anchor': '<button class="medium-editor-action medium-editor-action-anchor" data-action="anchor" data-element="a">' + buttonLabels.anchor + '</button>',
560
- 'image': '<button class="medium-editor-action medium-editor-action-image" data-action="image" data-element="img">' + buttonLabels.image + '</button>',
561
- 'header1': '<button class="medium-editor-action medium-editor-action-header1" data-action="append-' + this.options.firstHeader + '" data-element="' + this.options.firstHeader + '">' + buttonLabels.header1 + '</button>',
562
- 'header2': '<button class="medium-editor-action medium-editor-action-header2" data-action="append-' + this.options.secondHeader + '" data-element="' + this.options.secondHeader + '">' + buttonLabels.header2 + '</button>',
563
- 'quote': '<button class="medium-editor-action medium-editor-action-quote" data-action="append-blockquote" data-element="blockquote">' + buttonLabels.quote + '</button>',
564
- 'orderedlist': '<button class="medium-editor-action medium-editor-action-orderedlist" data-action="insertorderedlist" data-element="ol">' + buttonLabels.orderedlist + '</button>',
565
- 'unorderedlist': '<button class="medium-editor-action medium-editor-action-unorderedlist" data-action="insertunorderedlist" data-element="ul">' + buttonLabels.unorderedlist + '</button>',
566
- 'pre': '<button class="medium-editor-action medium-editor-action-pre" data-action="append-pre" data-element="pre">' + buttonLabels.pre + '</button>',
567
- 'indent': '<button class="medium-editor-action medium-editor-action-indent" data-action="indent" data-element="ul">' + buttonLabels.indent + '</button>',
568
- 'outdent': '<button class="medium-editor-action medium-editor-action-outdent" data-action="outdent" data-element="ul">' + buttonLabels.outdent + '</button>',
569
- 'justifyCenter': '<button class="medium-editor-action medium-editor-action-justifyCenter" data-action="justifyCenter" data-element="">' + buttonLabels.justifyCenter + '</button>',
570
- 'justifyFull': '<button class="medium-editor-action medium-editor-action-justifyFull" data-action="justifyFull" data-element="">' + buttonLabels.justifyFull + '</button>',
571
- 'justifyLeft': '<button class="medium-editor-action medium-editor-action-justifyLeft" data-action="justifyLeft" data-element="">' + buttonLabels.justifyLeft + '</button>',
572
- 'justifyRight': '<button class="medium-editor-action medium-editor-action-justifyRight" data-action="justifyRight" data-element="">' + buttonLabels.justifyRight + '</button>'
659
+ 'bold': '<button class="medium-editor-action medium-editor-action-bold" data-action="bold" data-element="b" aria-label="bold">' + buttonLabels.bold + '</button>',
660
+ 'italic': '<button class="medium-editor-action medium-editor-action-italic" data-action="italic" data-element="i" aria-label="italic">' + buttonLabels.italic + '</button>',
661
+ 'underline': '<button class="medium-editor-action medium-editor-action-underline" data-action="underline" data-element="u" aria-label="underline">' + buttonLabels.underline + '</button>',
662
+ 'strikethrough': '<button class="medium-editor-action medium-editor-action-strikethrough" data-action="strikethrough" data-element="strike" aria-label="strike through">' + buttonLabels.strikethrough +'</button>',
663
+ 'superscript': '<button class="medium-editor-action medium-editor-action-superscript" data-action="superscript" data-element="sup" aria-label="superscript">' + buttonLabels.superscript + '</button>',
664
+ 'subscript': '<button class="medium-editor-action medium-editor-action-subscript" data-action="subscript" data-element="sub" aria-label="subscript">' + buttonLabels.subscript + '</button>',
665
+ 'anchor': '<button class="medium-editor-action medium-editor-action-anchor" data-action="anchor" data-element="a" aria-label="link">' + buttonLabels.anchor + '</button>',
666
+ 'image': '<button class="medium-editor-action medium-editor-action-image" data-action="image" data-element="img" aria-label="image">' + buttonLabels.image + '</button>',
667
+ 'header1': '<button class="medium-editor-action medium-editor-action-header1" data-action="append-' + this.options.firstHeader + '" data-element="' + this.options.firstHeader + '" aria-label="h1">' + buttonLabels.header1 + '</button>',
668
+ 'header2': '<button class="medium-editor-action medium-editor-action-header2" data-action="append-' + this.options.secondHeader + '" data-element="' + this.options.secondHeader + ' "aria-label="h2">' + buttonLabels.header2 + '</button>',
669
+ 'quote': '<button class="medium-editor-action medium-editor-action-quote" data-action="append-blockquote" data-element="blockquote" aria-label="blockquote">' + buttonLabels.quote + '</button>',
670
+ 'orderedlist': '<button class="medium-editor-action medium-editor-action-orderedlist" data-action="insertorderedlist" data-element="ol" aria-label="ordered list">' + buttonLabels.orderedlist + '</button>',
671
+ 'unorderedlist': '<button class="medium-editor-action medium-editor-action-unorderedlist" data-action="insertunorderedlist" data-element="ul" aria-label="unordered list">' + buttonLabels.unorderedlist + '</button>',
672
+ 'pre': '<button class="medium-editor-action medium-editor-action-pre" data-action="append-pre" data-element="pre" aria-label="preformatted text">' + buttonLabels.pre + '</button>',
673
+ 'indent': '<button class="medium-editor-action medium-editor-action-indent" data-action="indent" data-element="ul" aria-label="indent">' + buttonLabels.indent + '</button>',
674
+ 'outdent': '<button class="medium-editor-action medium-editor-action-outdent" data-action="outdent" data-element="ul" aria-label="outdent">' + buttonLabels.outdent + '</button>',
675
+ 'justifyCenter': '<button class="medium-editor-action medium-editor-action-justifyCenter" data-action="justifyCenter" data-element="" aria-label="center justify">' + buttonLabels.justifyCenter + '</button>',
676
+ 'justifyFull': '<button class="medium-editor-action medium-editor-action-justifyFull" data-action="justifyFull" data-element="" aria-label="full justify">' + buttonLabels.justifyFull + '</button>',
677
+ 'justifyLeft': '<button class="medium-editor-action medium-editor-action-justifyLeft" data-action="justifyLeft" data-element="" aria-label="left justify">' + buttonLabels.justifyLeft + '</button>',
678
+ 'justifyRight': '<button class="medium-editor-action medium-editor-action-justifyRight" data-action="justifyRight" data-element="" aria-label="right justify">' + buttonLabels.justifyRight + '</button>'
573
679
  };
574
680
  return buttonTemplates[btnType] || false;
575
681
  },
@@ -647,13 +753,13 @@ else if (typeof define === 'function' && define.amd) {
647
753
  this.anchorForm = this.toolbar.querySelector('.medium-editor-toolbar-form-anchor');
648
754
  this.anchorInput = this.anchorForm.querySelector('input.medium-editor-toolbar-anchor-input');
649
755
  this.anchorTarget = this.anchorForm.querySelector('input.medium-editor-toolbar-anchor-target');
650
- this.anchorButton = this.anchorForm.querySelector('input.medium-editor-toolbar-anchor-button');
756
+ this.anchorButton = this.anchorForm.querySelector('input.medium-editor-toolbar-anchor-button');
651
757
  }
652
758
  return this;
653
759
  },
654
760
 
655
761
  createToolbar: function () {
656
- var toolbar = document.createElement('div');
762
+ var toolbar = this.options.ownerDocument.createElement('div');
657
763
  toolbar.id = 'medium-editor-toolbar-' + this.id;
658
764
  toolbar.className = 'medium-editor-toolbar';
659
765
 
@@ -674,7 +780,7 @@ else if (typeof define === 'function' && define.amd) {
674
780
  //TODO: actionTemplate
675
781
  toolbarButtons: function () {
676
782
  var btns = this.options.buttons,
677
- ul = document.createElement('ul'),
783
+ ul = this.options.ownerDocument.createElement('ul'),
678
784
  li,
679
785
  i,
680
786
  btn,
@@ -686,13 +792,13 @@ else if (typeof define === 'function' && define.amd) {
686
792
  for (i = 0; i < btns.length; i += 1) {
687
793
  if (this.options.extensions.hasOwnProperty(btns[i])) {
688
794
  ext = this.options.extensions[btns[i]];
689
- btn = ext.getButton !== undefined ? ext.getButton() : null;
795
+ btn = ext.getButton !== undefined ? ext.getButton(this) : null;
690
796
  } else {
691
797
  btn = this.buttonTemplate(btns[i]);
692
798
  }
693
799
 
694
800
  if (btn) {
695
- li = document.createElement('li');
801
+ li = this.options.ownerDocument.createElement('li');
696
802
  if (isElement(btn)) {
697
803
  li.appendChild(btn);
698
804
  } else {
@@ -706,14 +812,14 @@ else if (typeof define === 'function' && define.amd) {
706
812
  },
707
813
 
708
814
  toolbarFormAnchor: function () {
709
- var anchor = document.createElement('div'),
710
- input = document.createElement('input'),
711
- target_label = document.createElement('label'),
712
- target = document.createElement('input'),
713
- button_label = document.createElement('label'),
714
- button = document.createElement('input'),
715
- close = document.createElement('a'),
716
- save = document.createElement('a');
815
+ var anchor = this.options.ownerDocument.createElement('div'),
816
+ input = this.options.ownerDocument.createElement('input'),
817
+ target_label = this.options.ownerDocument.createElement('label'),
818
+ target = this.options.ownerDocument.createElement('input'),
819
+ button_label = this.options.ownerDocument.createElement('label'),
820
+ button = this.options.ownerDocument.createElement('input'),
821
+ close = this.options.ownerDocument.createElement('a'),
822
+ save = this.options.ownerDocument.createElement('a');
717
823
 
718
824
  close.setAttribute('href', '#');
719
825
  close.className = 'medium-editor-toobar-anchor-close';
@@ -759,23 +865,18 @@ else if (typeof define === 'function' && define.amd) {
759
865
 
760
866
  bindSelect: function () {
761
867
  var self = this,
762
- timer = '',
763
868
  i;
764
869
 
765
870
  this.checkSelectionWrapper = function (e) {
766
-
767
871
  // Do not close the toolbar when bluring the editable area and clicking into the anchor form
768
872
  if (!self.options.disableAnchorForm && e && self.clickingIntoArchorForm(e)) {
769
873
  return false;
770
874
  }
771
875
 
772
- clearTimeout(timer);
773
- timer = setTimeout(function () {
774
- self.checkSelection();
775
- }, self.options.delay);
876
+ self.checkSelection();
776
877
  };
777
878
 
778
- this.on(document.documentElement, 'mouseup', this.checkSelectionWrapper);
879
+ this.on(this.options.ownerDocument.documentElement, 'mouseup', this.checkSelectionWrapper);
779
880
 
780
881
  for (i = 0; i < this.elements.length; i += 1) {
781
882
  this.on(this.elements[i], 'keyup', this.checkSelectionWrapper);
@@ -785,11 +886,21 @@ else if (typeof define === 'function' && define.amd) {
785
886
  return this;
786
887
  },
787
888
 
889
+ stopSelectionUpdates: function() {
890
+ this.preventSelectionUpdates = true;
891
+ },
892
+
893
+ startSelectionUpdates: function() {
894
+ this.preventSelectionUpdates = false;
895
+ },
896
+
788
897
  checkSelection: function () {
789
898
  var newSelection,
790
899
  selectionElement;
791
900
 
792
- if (this.keepToolbarAlive !== true && !this.options.disableToolbar) {
901
+ if (!this.preventSelectionUpdates &&
902
+ this.keepToolbarAlive !== true &&
903
+ !this.options.disableToolbar) {
793
904
 
794
905
  newSelection = this.options.contentWindow.getSelection();
795
906
  if ((!this.options.updateOnEmptySelection && newSelection.toString().trim() === '') ||
@@ -835,9 +946,48 @@ else if (typeof define === 'function' && define.amd) {
835
946
  },
836
947
 
837
948
  checkSelectionElement: function (newSelection, selectionElement) {
838
- var i;
949
+ var i,
950
+ adjacentNode,
951
+ offset = 0,
952
+ newRange;
839
953
  this.selection = newSelection;
840
954
  this.selectionRange = this.selection.getRangeAt(0);
955
+
956
+ /*
957
+ * In firefox, there are cases (ie doubleclick of a word) where the selectionRange start
958
+ * will be at the very end of an element. In other browsers, the selectionRange start
959
+ * would instead be at the very beginning of an element that actually has content.
960
+ * example:
961
+ * <span>foo</span><span>bar</span>
962
+ *
963
+ * If the text 'bar' is selected, most browsers will have the selectionRange start at the beginning
964
+ * of the 'bar' span. However, there are cases where firefox will have the selectionRange start
965
+ * at the end of the 'foo' span. The contenteditable behavior will be ok, but if there are any
966
+ * properties on the 'bar' span, they won't be reflected accurately in the toolbar
967
+ * (ie 'Bold' button wouldn't be active)
968
+ *
969
+ * So, for cases where the selectionRange start is at the end of an element/node, find the next
970
+ * adjacent text node that actually has content in it, and move the selectionRange start there.
971
+ */
972
+ if (
973
+ this.options.standardizeSelectionStart &&
974
+ this.selectionRange.startOffset === this.selectionRange.startContainer.nodeValue.length
975
+ ) {
976
+ adjacentNode = findAdjacentTextNodeWithContent(this.getSelectionElement(), this.selectionRange.startContainer, this.options.ownerDocument);
977
+ if (adjacentNode) {
978
+ offset = 0;
979
+ while(adjacentNode.nodeValue.substr(offset, 1).trim().length === 0) {
980
+ offset = offset + 1;
981
+ }
982
+ newRange = this.options.ownerDocument.createRange();
983
+ newRange.setStart(adjacentNode, offset);
984
+ newRange.setEnd(this.selectionRange.endContainer, this.selectionRange.endOffset);
985
+ this.selection.removeAllRanges();
986
+ this.selection.addRange(newRange);
987
+ this.selectionRange = newRange;
988
+ }
989
+ }
990
+
841
991
  for (i = 0; i < this.elements.length; i += 1) {
842
992
  if (this.elements[i] === selectionElement) {
843
993
  this.setToolbarButtonStates()
@@ -894,12 +1044,12 @@ else if (typeof define === 'function' && define.amd) {
894
1044
 
895
1045
  setToolbarPosition: function () {
896
1046
  // document.documentElement for IE 9
897
- var scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop,
1047
+ var scrollTop = (this.options.ownerDocument.documentElement && this.options.ownerDocument.documentElement.scrollTop) || this.options.ownerDocument.body.scrollTop,
898
1048
  container = this.elements[0],
899
1049
  containerRect = container.getBoundingClientRect(),
900
1050
  containerTop = containerRect.top + scrollTop,
901
1051
  buttonHeight = 50,
902
- selection = window.getSelection(),
1052
+ selection = this.options.contentWindow.getSelection(),
903
1053
  range,
904
1054
  boundary,
905
1055
  middleBoundary,
@@ -910,7 +1060,7 @@ else if (typeof define === 'function' && define.amd) {
910
1060
  return this;
911
1061
  }
912
1062
 
913
- this.toolbar.classList.add('medium-editor-toolbar-active');
1063
+ this.showToolbar();
914
1064
 
915
1065
  if ( this.options.staticToolbar ) {
916
1066
 
@@ -1137,9 +1287,21 @@ else if (typeof define === 'function' && define.amd) {
1137
1287
  return firstChild;
1138
1288
  },
1139
1289
 
1140
- hideToolbarActions: function () {
1141
- this.keepToolbarAlive = false;
1142
- if (this.toolbar !== undefined && this.toolbar.classList.contains('medium-editor-toolbar-active')) {
1290
+ isToolbarShown: function() {
1291
+ return this.toolbar && this.toolbar.classList.contains('medium-editor-toolbar-active');
1292
+ },
1293
+
1294
+ showToolbar: function() {
1295
+ if (this.toolbar && !this.isToolbarShown()) {
1296
+ this.toolbar.classList.add('medium-editor-toolbar-active');
1297
+ if (this.onShowToolbar) {
1298
+ this.onShowToolbar();
1299
+ }
1300
+ }
1301
+ },
1302
+
1303
+ hideToolbar: function() {
1304
+ if (this.isToolbarShown()) {
1143
1305
  this.toolbar.classList.remove('medium-editor-toolbar-active');
1144
1306
  if (this.onHideToolbar) {
1145
1307
  this.onHideToolbar();
@@ -1147,20 +1309,23 @@ else if (typeof define === 'function' && define.amd) {
1147
1309
  }
1148
1310
  },
1149
1311
 
1312
+ hideToolbarActions: function () {
1313
+ this.keepToolbarAlive = false;
1314
+ this.hideToolbar();
1315
+ },
1316
+
1150
1317
  showToolbarActions: function () {
1151
- var self = this,
1152
- timer;
1318
+ var self = this;
1153
1319
  if (this.anchorForm) {
1154
1320
  this.anchorForm.style.display = 'none';
1155
1321
  }
1156
1322
  this.toolbarActions.style.display = 'block';
1157
1323
  this.keepToolbarAlive = false;
1158
- clearTimeout(timer);
1159
- timer = setTimeout(function () {
1160
- if (self.toolbar && !self.toolbar.classList.contains('medium-editor-toolbar-active')) {
1161
- self.toolbar.classList.add('medium-editor-toolbar-active');
1162
- }
1163
- }, 100);
1324
+ // Using setTimeout + options.delay because:
1325
+ // We will actually be displaying the toolbar, which should be controlled by options.delay
1326
+ this.delay(function () {
1327
+ self.showToolbar();
1328
+ });
1164
1329
  },
1165
1330
 
1166
1331
  saveSelection: function() {
@@ -1218,6 +1383,11 @@ else if (typeof define === 'function' && define.amd) {
1218
1383
 
1219
1384
  self.createLink(this, target, button);
1220
1385
  }
1386
+ else if (e.keyCode === 27) {
1387
+ e.preventDefault();
1388
+ self.showToolbarActions();
1389
+ restoreSelection.call(self, self.savedSelection);
1390
+ }
1221
1391
  });
1222
1392
 
1223
1393
  this.on(linkSave, 'click', function(e) {
@@ -1283,20 +1453,12 @@ else if (typeof define === 'function' && define.amd) {
1283
1453
  boundary = anchorEl.getBoundingClientRect(),
1284
1454
  middleBoundary = (boundary.left + boundary.right) / 2,
1285
1455
  halfOffsetWidth,
1286
- defaultLeft,
1287
- timer;
1456
+ defaultLeft;
1288
1457
 
1289
1458
  self.anchorPreview.querySelector('i').textContent = anchorEl.href;
1290
1459
  halfOffsetWidth = self.anchorPreview.offsetWidth / 2;
1291
1460
  defaultLeft = self.options.diffLeft - halfOffsetWidth;
1292
1461
 
1293
- clearTimeout(timer);
1294
- timer = setTimeout(function () {
1295
- if (self.anchorPreview && !self.anchorPreview.classList.contains('medium-editor-anchor-preview-active')) {
1296
- self.anchorPreview.classList.add('medium-editor-anchor-preview-active');
1297
- }
1298
- }, 100);
1299
-
1300
1462
  self.observeAnchorPreview(anchorEl);
1301
1463
 
1302
1464
  self.anchorPreview.classList.add('medium-toolbar-arrow-over');
@@ -1310,6 +1472,10 @@ else if (typeof define === 'function' && define.amd) {
1310
1472
  self.anchorPreview.style.left = defaultLeft + middleBoundary + 'px';
1311
1473
  }
1312
1474
 
1475
+ if (this.anchorPreview && !this.anchorPreview.classList.contains('medium-editor-anchor-preview-active')) {
1476
+ this.anchorPreview.classList.add('medium-editor-anchor-preview-active');
1477
+ }
1478
+
1313
1479
  return this;
1314
1480
  },
1315
1481
 
@@ -1384,12 +1550,14 @@ else if (typeof define === 'function' && define.amd) {
1384
1550
  range.selectNodeContents(self.activeAnchor);
1385
1551
  sel.removeAllRanges();
1386
1552
  sel.addRange(range);
1387
- setTimeout(function () {
1553
+ // Using setTimeout + options.delay because:
1554
+ // We may actually be displaying the anchor preview, which should be controlled by options.delay
1555
+ this.delay(function () {
1388
1556
  if (self.activeAnchor) {
1389
1557
  self.showAnchorForm(self.activeAnchor.href);
1390
1558
  }
1391
1559
  self.keepToolbarAlive = false;
1392
- }, 100 + self.options.delay);
1560
+ });
1393
1561
 
1394
1562
  }
1395
1563
 
@@ -1415,21 +1583,20 @@ else if (typeof define === 'function' && define.amd) {
1415
1583
  }
1416
1584
 
1417
1585
  // only show when hovering on anchors
1418
- if (this.toolbar.classList.contains('medium-editor-toolbar-active')) {
1586
+ if (this.isToolbarShown()) {
1419
1587
  // only show when toolbar is not present
1420
1588
  return true;
1421
1589
  }
1422
1590
  this.activeAnchor = e.target;
1423
1591
  this.on(this.activeAnchor, 'mouseout', leaveAnchor);
1424
- // show the anchor preview according to the configured delay
1425
- // if the mouse has not left the anchor tag in that time
1426
- setTimeout(function () {
1592
+ // Using setTimeout + options.delay because:
1593
+ // - We're going to show the anchor preview according to the configured delay
1594
+ // if the mouse has not left the anchor tag in that time
1595
+ this.delay(function () {
1427
1596
  if (overAnchor) {
1428
1597
  self.showAnchorPreview(e.target);
1429
1598
  }
1430
- }, self.options.delay);
1431
-
1432
-
1599
+ });
1433
1600
  }
1434
1601
  },
1435
1602
 
@@ -1518,30 +1685,26 @@ else if (typeof define === 'function' && define.amd) {
1518
1685
  input.value = '';
1519
1686
  },
1520
1687
 
1688
+ positionToolbarIfShown: function() {
1689
+ if (this.isToolbarShown()) {
1690
+ this.setToolbarPosition();
1691
+ }
1692
+ },
1693
+
1521
1694
  bindWindowActions: function () {
1522
- var timerResize,
1523
- self = this;
1524
- this.windowResizeHandler = function () {
1525
- clearTimeout(timerResize);
1526
- timerResize = setTimeout(function () {
1527
- if (self.toolbar && self.toolbar.classList.contains('medium-editor-toolbar-active')) {
1528
- self.setToolbarPosition();
1529
- }
1530
- }, 100);
1531
- };
1695
+ var self = this;
1532
1696
 
1533
1697
  // Add a scroll event for sticky toolbar
1534
1698
  if ( this.options.staticToolbar && this.options.stickyToolbar ) {
1535
-
1536
1699
  // On scroll, re-position the toolbar
1537
- this.on(window, 'scroll', function() {
1538
- if (self.toolbar && self.toolbar.classList.contains('medium-editor-toolbar-active')) {
1539
- self.setToolbarPosition();
1540
- }
1700
+ this.on(this.options.contentWindow, 'scroll', function() {
1701
+ self.positionToolbarIfShown();
1541
1702
  }, true);
1542
1703
  }
1543
1704
 
1544
- this.on(this.options.contentWindow, 'resize', this.windowResizeHandler);
1705
+ this.on(this.options.contentWindow, 'resize', function() {
1706
+ self.handleResize();
1707
+ });
1545
1708
  return this;
1546
1709
  },
1547
1710
 
@@ -1596,8 +1759,8 @@ else if (typeof define === 'function' && define.amd) {
1596
1759
  return this;
1597
1760
  }
1598
1761
 
1599
- if (window.clipboardData && e.clipboardData === undefined) {
1600
- e.clipboardData = window.clipboardData;
1762
+ if (self.options.contentWindow.clipboardData && e.clipboardData === undefined) {
1763
+ e.clipboardData = self.options.contentWindow.clipboardData;
1601
1764
  // If window.clipboardData exists, but e.clipboardData doesn't exist,
1602
1765
  // we're probably in IE. IE only has two possibilities for clipboard
1603
1766
  // data format: 'Text' and 'URL'.
@@ -1638,29 +1801,14 @@ else if (typeof define === 'function' && define.amd) {
1638
1801
  },
1639
1802
 
1640
1803
  setPlaceholders: function () {
1641
- if (this.options.disablePlaceholders) {
1642
- return this;
1804
+ if (!this.options.disablePlaceholders && this.elements && this.elements.length) {
1805
+ this.elements.forEach(function(el) {
1806
+ this.activatePlaceholder(el);
1807
+ this.on(el, 'blur', this.placeholderWrapper.bind(this));
1808
+ this.on(el, 'keypress', this.placeholderWrapper.bind(this));
1809
+ }.bind(this));
1643
1810
  }
1644
1811
 
1645
- var i,
1646
- activatePlaceholder = function (el) {
1647
- if (!(el.querySelector('img')) &&
1648
- !(el.querySelector('blockquote')) &&
1649
- el.textContent.replace(/^\s+|\s+$/g, '') === '') {
1650
- el.classList.add('medium-editor-placeholder');
1651
- }
1652
- },
1653
- placeholderWrapper = function (e) {
1654
- this.classList.remove('medium-editor-placeholder');
1655
- if (e.type !== 'keypress') {
1656
- activatePlaceholder(this);
1657
- }
1658
- };
1659
- for (i = 0; i < this.elements.length; i += 1) {
1660
- activatePlaceholder(this.elements[i]);
1661
- this.on(this.elements[i], 'blur', placeholderWrapper);
1662
- this.on(this.elements[i], 'keypress', placeholderWrapper);
1663
- }
1664
1812
  return this;
1665
1813
  },
1666
1814
 
@@ -126,7 +126,8 @@
126
126
  -webkit-animation: pop-upwards 160ms forwards linear;
127
127
  -ms-animation: pop-upwards 160ms forwards linear;
128
128
  animation: pop-upwards 160ms forwards linear;
129
- transition: top 0.075s ease-out, left 0.075s ease-out; }
129
+ -webkit-transition: top 0.075s ease-out, left 0.075s ease-out;
130
+ transition: top 0.075s ease-out, left 0.075s ease-out; }
130
131
 
131
132
  .medium-editor-action-bold {
132
133
  font-weight: bolder; }
@@ -167,4 +168,5 @@
167
168
  top: 0;
168
169
  left: 0;
169
170
  content: attr(data-placeholder) !important;
170
- font-style: italic; }
171
+ font-style: italic;
172
+ white-space: pre; }
@@ -9,7 +9,8 @@
9
9
  border: 1px solid #357ebd;
10
10
  background-color: #428bca;
11
11
  border-radius: 4px;
12
- transition: top 0.075s ease-out, left 0.075s ease-out; }
12
+ -webkit-transition: top 0.075s ease-out, left 0.075s ease-out;
13
+ transition: top 0.075s ease-out, left 0.075s ease-out; }
13
14
  .medium-editor-toolbar li button {
14
15
  min-width: 60px;
15
16
  height: 60px;
@@ -18,7 +19,8 @@
18
19
  background-color: transparent;
19
20
  color: #fff;
20
21
  box-sizing: border-box;
21
- transition: background-color 0.2s ease-in, color 0.2s ease-in; }
22
+ -webkit-transition: background-color 0.2s ease-in, color 0.2s ease-in;
23
+ transition: background-color 0.2s ease-in, color 0.2s ease-in; }
22
24
  .medium-editor-toolbar li button:hover {
23
25
  background-color: #3276b1;
24
26
  color: #fff; }
@@ -9,10 +9,12 @@
9
9
  .medium-editor-toolbar {
10
10
  border: 1px solid #000;
11
11
  background-color: #242424;
12
+ background: -webkit-linear-gradient(bottom, #242424, rgba(36, 36, 36, 0.75));
12
13
  background: linear-gradient(bottom, #242424, rgba(36, 36, 36, 0.75));
13
14
  border-radius: 5px;
14
15
  box-shadow: 0 0 3px #000;
15
- transition: top 0.075s ease-out, left 0.075s ease-out; }
16
+ -webkit-transition: top 0.075s ease-out, left 0.075s ease-out;
17
+ transition: top 0.075s ease-out, left 0.075s ease-out; }
16
18
  .medium-editor-toolbar li button {
17
19
  min-width: 50px;
18
20
  height: 50px;
@@ -22,9 +24,11 @@
22
24
  border-left: 1px solid rgba(255, 255, 255, 0.1);
23
25
  background-color: #242424;
24
26
  color: #fff;
27
+ background: -webkit-linear-gradient(bottom, #242424, rgba(36, 36, 36, 0.89));
25
28
  background: linear-gradient(bottom, #242424, rgba(36, 36, 36, 0.89));
26
29
  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3);
27
- transition: background-color 0.2s ease-in; }
30
+ -webkit-transition: background-color 0.2s ease-in;
31
+ transition: background-color 0.2s ease-in; }
28
32
  .medium-editor-toolbar li button:hover {
29
33
  background-color: #000;
30
34
  color: yellow; }
@@ -37,6 +41,7 @@
37
41
  .medium-editor-toolbar li .medium-editor-button-active {
38
42
  background-color: #000;
39
43
  color: #fff;
44
+ background: -webkit-linear-gradient(bottom, #242424, rgba(0, 0, 0, 0.89));
40
45
  background: linear-gradient(bottom, #242424, rgba(0, 0, 0, 0.89)); }
41
46
 
42
47
  .medium-editor-toolbar-form-anchor {
@@ -17,7 +17,8 @@
17
17
  border-right: 1px solid #9ccea6;
18
18
  background-color: transparent;
19
19
  color: #fff;
20
- transition: background-color 0.2s ease-in, color 0.2s ease-in; }
20
+ -webkit-transition: background-color 0.2s ease-in, color 0.2s ease-in;
21
+ transition: background-color 0.2s ease-in, color 0.2s ease-in; }
21
22
  .medium-editor-toolbar li button:hover {
22
23
  background-color: #346a3f;
23
24
  color: #fff; }
@@ -5,6 +5,7 @@
5
5
  border: 1px solid #cdd6e0;
6
6
  background-color: #dee7f0;
7
7
  background-color: rgba(222, 231, 240, 0.95);
8
+ background: -webkit-linear-gradient(bottom, #dee7f0, #ffffff);
8
9
  background: linear-gradient(bottom, #dee7f0, #ffffff);
9
10
  border-radius: 2px;
10
11
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45); }
@@ -15,7 +16,8 @@
15
16
  border-right: 1px solid #cdd6e0;
16
17
  background-color: transparent;
17
18
  color: #40648a;
18
- transition: background-color 0.2s ease-in, color 0.2s ease-in; }
19
+ -webkit-transition: background-color 0.2s ease-in, color 0.2s ease-in;
20
+ transition: background-color 0.2s ease-in, color 0.2s ease-in; }
19
21
  .medium-editor-toolbar li button:hover {
20
22
  background-color: #5c90c7;
21
23
  background-color: rgba(92, 144, 199, 0.45);
@@ -30,6 +32,7 @@
30
32
  background-color: #5c90c7;
31
33
  background-color: rgba(92, 144, 199, 0.45);
32
34
  color: #000;
35
+ background: -webkit-linear-gradient(bottom, #dee7f0, rgba(0, 0, 0, 0.1));
33
36
  background: linear-gradient(bottom, #dee7f0, rgba(0, 0, 0, 0.1)); }
34
37
 
35
38
  .medium-editor-toolbar-form-anchor {
@@ -14,9 +14,11 @@
14
14
  background-color: transparent;
15
15
  color: #889aac;
16
16
  box-shadow: inset 0 0 3px #f8f8e6;
17
+ background: -webkit-linear-gradient(top, #fff, rgba(0, 0, 0, 0.1));
17
18
  background: linear-gradient(top, #fff, rgba(0, 0, 0, 0.1));
18
19
  text-shadow: 1px 4px 6px #def, 0 0 0 #000, 1px 4px 6px #def;
19
- transition: background-color 0.2s ease-in; }
20
+ -webkit-transition: background-color 0.2s ease-in;
21
+ transition: background-color 0.2s ease-in; }
20
22
  .medium-editor-toolbar li button:hover {
21
23
  background-color: #fff;
22
24
  color: #000;
@@ -31,6 +33,7 @@
31
33
  background-color: #ccc;
32
34
  color: #000;
33
35
  color: rgba(0, 0, 0, 0.8);
36
+ background: -webkit-linear-gradient(bottom, #fff, rgba(0, 0, 0, 0.2));
34
37
  background: linear-gradient(bottom, #fff, rgba(0, 0, 0, 0.2)); }
35
38
 
36
39
  .medium-editor-toolbar-form-anchor {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: medium-editor-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmet Sezgin Duran
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-07 00:00:00.000000000 Z
11
+ date: 2015-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties