medium-editor-rails 1.0.0 → 1.1.0

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.
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