scrivito_editors 1.0.0 → 1.1.0.rc1

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: 2cabd5e5db7880e7993d507da0f919bf9e6b0add
4
- data.tar.gz: 47d2dccbc8e88d51521ee955615ab7b50b336321
3
+ metadata.gz: 6e3270ccf6587292e9e95e6451970a021be1650c
4
+ data.tar.gz: ccb599722a4db3e062a13ad5be2fd99fbe0d10d9
5
5
  SHA512:
6
- metadata.gz: d789d26827cd715b11027bcb221ac482f9bef6580c4dbd3b2ae2c0bfbbe58ec0060118b060ca4b6185080c0d6fc4611ceb5aecfb8bfd9e96a5d5b07aae1118b3
7
- data.tar.gz: 500b87661f31212548638c5bccf525836bb1d5aa66bd67b0052d9b109fdcb8a49473d9fd51be4f3b341ba81af35819c0ecf2884fd640994fbfd03e95c677229e
6
+ metadata.gz: 384bfe1abec2ddf9c28a932818d2ce237a902e7140071ed5e2d1f702d1134ae8d0969957bf16ec5f6ed38f1a11c181ac2ddc936f4de5b7e8e76b7e95d8912c44
7
+ data.tar.gz: 231c54b4d4f644f5e145ab10a6fde84cedbc49afab87543e6a509b0d223a92616b9ea4a57509c58d44293ea0142db626d01260868e2bc40c2de51a7b582deef3
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Scrivito Editors
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/scrivito_editors.png)](http://badge.fury.io/rb/scrivito_editors)
3
+ [![Gem Version](https://badge.fury.io/rb/scrivito_editors.svg)](https://badge.fury.io/rb/scrivito_editors)
4
4
 
5
5
  The [Scrivito](http://scrivito.com) Editors gem is a collection of useful standard
6
6
  JavaScript editors based on the Scrivito SDK. The editors allow to edit all CMS
@@ -1,34 +1,38 @@
1
1
  (function() {
2
- var activate, clear, save, template,
3
- indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4
-
5
- clear = '__scrivito_editors_enum_clear';
2
+ var activate, blur, change, save, template;
6
3
 
7
4
  template = function(values) {
8
5
  var element;
9
6
  element = $('<select></select>').addClass('form-control');
10
7
  $.each(values, function(index, value) {
11
- var text;
12
- if (value === clear) {
13
- text = '';
14
- } else {
15
- text = value;
16
- }
17
- return $('<option></option>').attr('value', value).text(text).appendTo(element);
8
+ return $('<option></option>').attr('value', value).text(value).appendTo(element);
18
9
  });
19
10
  return element;
20
11
  };
21
12
 
22
- save = function(event) {
13
+ save = function(event, options) {
23
14
  var cmsField, content, element;
24
15
  element = $(event.currentTarget);
25
- cmsField = element.data('cmsField');
16
+ cmsField = element.data('scrivitoEditorsCmsField');
26
17
  content = element.val();
27
- if (content === clear) {
18
+ if (content === '') {
28
19
  content = null;
29
20
  }
30
21
  return cmsField.scrivito('save', content).done(function() {
31
- return cmsField.trigger('save.scrivito_editors');
22
+ cmsField.trigger('scrivito_editors:save');
23
+ if (options != null ? options.blur : void 0) {
24
+ return cmsField.trigger('scrivito_editors:blur');
25
+ }
26
+ });
27
+ };
28
+
29
+ change = function(event) {
30
+ return save(event);
31
+ };
32
+
33
+ blur = function(event) {
34
+ return save(event, {
35
+ blur: true
32
36
  });
33
37
  };
34
38
 
@@ -36,18 +40,11 @@
36
40
  var cmsField;
37
41
  cmsField = $(element);
38
42
  return cmsField.on('click', function() {
39
- var content, selected, values;
43
+ var content, values;
40
44
  content = cmsField.scrivito('content');
41
45
  values = cmsField.scrivito('allowed_values');
42
- if (indexOf.call(values, '') < 0) {
43
- values.push(clear);
44
- }
45
- if (content) {
46
- selected = content;
47
- } else {
48
- selected = clear;
49
- }
50
- template(values).data('cmsField', cmsField).val(selected).insertAfter(cmsField).change(save).focusout(save).focus();
46
+ values.unshift('');
47
+ template(values).data('scrivitoEditorsCmsField', cmsField).val(content || '').insertAfter(cmsField).change(change).blur(blur).focus();
51
48
  return cmsField.hide();
52
49
  });
53
50
  };
@@ -24,7 +24,12 @@
24
24
  var files, ref, ref1;
25
25
  el.removeClass('image-editor-dragover');
26
26
  if (((ref = (files = (ref1 = e.originalEvent.dataTransfer) != null ? ref1.files : void 0)) != null ? ref.length : void 0) === 1) {
27
+ el.addClass('scrivito_element_overlay');
27
28
  callback(el, files[0]);
29
+ } else {
30
+ el.children().not('img').css({
31
+ pointerEvents: 'auto'
32
+ });
28
33
  }
29
34
  return false;
30
35
  });
@@ -1,10 +1,10 @@
1
1
  (function() {
2
2
  scrivito.editors.html_editor = {
3
3
  can_edit: function(element) {
4
- return scrivito.editors.redactor_editor.can_edit(element);
4
+ return scrivito.editors.medium_editor.can_edit(element);
5
5
  },
6
6
  activate: function(element) {
7
- return scrivito.editors.redactor_editor.activate(element);
7
+ return scrivito.editors.medium_editor.activate(element);
8
8
  }
9
9
  };
10
10
 
@@ -52,39 +52,29 @@
52
52
  };
53
53
 
54
54
  setup_image_kit_container = function(element, dialog) {
55
- var container, fallbackUrl, image, url;
55
+ var container, image;
56
56
  container = $(".image_kit_start");
57
57
  image = new Image();
58
- url = element.scrivito("content").url;
59
- image.crossOrigin = "Anonymous";
60
- image.src = url;
61
- fallbackUrl = url;
62
- if (url.indexOf("?") < 0) {
63
- fallbackUrl = url + "?=" + new Date().getTime();
64
- } else {
65
- fallbackUrl = url + "&=" + new Date().getTime();
66
- }
67
- image.onerror = function() {
68
- if (image.src === fallbackUrl) {
58
+ return element.scrivito('content').no_cache_url().then(function(no_cache_url) {
59
+ image.crossOrigin = "Anonymous";
60
+ image.src = no_cache_url;
61
+ image.onerror = function() {
69
62
  return $("<div style='padding:20px'>\n <h1>We're sorry,</h1>\n <p>Scrivito can't edit this image in your browser. What now?</p>\n <ul>\n <li>Check for browser updates</li>\n <li>Try using a different browser</li>\n <li>Contact us at\n <a href=\"https://scrivito.com/support\" target=\"_blank\">https://scrivito.com/support</a>\n </li>\n </ul>\n</div>").appendTo(container);
70
- } else {
71
- console.info("Scrivito detected a probable CORS browser cache mismatch, trying uncached load");
72
- return image.src = fallbackUrl;
73
- }
74
- };
75
- return image.onload = function() {
76
- var kit;
77
- kit = setup_image_kit(image, container);
78
- kit.ui.selectOperations({
79
- except: "stickers"
80
- });
81
- kit.run();
82
- return dialog.when_closed.then((function(_this) {
83
- return function() {
84
- return save_edited_image(element, kit);
85
- };
86
- })(this));
87
- };
63
+ };
64
+ return image.onload = function() {
65
+ var kit;
66
+ kit = setup_image_kit(image, container);
67
+ kit.ui.selectOperations({
68
+ except: "stickers"
69
+ });
70
+ kit.run();
71
+ return dialog.when_closed.then((function(_this) {
72
+ return function() {
73
+ return save_edited_image(element, kit);
74
+ };
75
+ })(this));
76
+ };
77
+ });
88
78
  };
89
79
 
90
80
  save_edited_image = function(element, kit) {
@@ -1,5 +1,5 @@
1
1
  (function() {
2
- var activate, openContentBrowser, save, template;
2
+ var activate, fetchDescription, openContentBrowser, save, template;
3
3
 
4
4
  scrivito.on('load', function() {
5
5
  return scrivito.define_editor('link', scrivito.editors.link_editor);
@@ -14,18 +14,22 @@
14
14
  }
15
15
  };
16
16
 
17
+ fetchDescription = function(cmsField, objId) {
18
+ return scrivito.description_for_editor([objId]).then(function(descriptions) {
19
+ var urlInput;
20
+ urlInput = cmsField.find('[name=url]');
21
+ if (descriptions[0] && urlInput.not(':focus')) {
22
+ return urlInput.val(descriptions[0]);
23
+ }
24
+ });
25
+ };
26
+
17
27
  activate = function(cmsField) {
18
- var link, obj_id;
28
+ var link;
19
29
  link = cmsField.scrivito('content') || {};
20
30
  cmsField.html(template(link));
21
- if (obj_id = link.obj_id) {
22
- scrivito.description_for_editor([obj_id]).then(function(descriptions) {
23
- var urlInput;
24
- urlInput = cmsField.find('[name=url]');
25
- if (!urlInput.is(':focus')) {
26
- return urlInput.val(descriptions[0]);
27
- }
28
- });
31
+ if (link.obj_id) {
32
+ fetchDescription(cmsField, link.obj_id);
29
33
  }
30
34
  cmsField.on('blur', 'li input', function() {
31
35
  return save(cmsField);
@@ -35,24 +39,24 @@
35
39
  return cmsField.find('[name=url]').on('focus', function() {
36
40
  var input, raw;
37
41
  input = $(this);
38
- raw = input.data('value');
42
+ raw = input.attr('data-value');
39
43
  if (raw) {
40
44
  input.val(raw);
41
45
  }
42
- return input.data('value', null);
46
+ return input.attr('data-value', null);
43
47
  });
44
48
  };
45
49
 
46
50
  template = function(link) {
47
51
  var obj_url;
48
- obj_url = link.obj_id && ("/" + link.obj_id);
52
+ obj_url = link.obj_id && scrivito.path_for_id(link.obj_id);
49
53
  return $("<ul>\n <li data-id=\"" + link.obj_id + "\" data-title=\"" + link.title + "\" data-url=\"" + link.url + "\">\n <input type=\"text\" name=\"title\" value=\"" + (link.title || '') + "\" placeholder=\"Title\" />\n <input type=\"text\" name=\"url\" value=\"" + (link.url || obj_url || '') + "\"\n data-value=\"" + (link.url || obj_url || '') + "\" placeholder=\"Url\" class=\"editing-url\" />\n <div class=\"actions\">\n <a href=\"#\" class=\"scrivito_open_content_browser editing-button editing-green\">\n <i class=\"editing-icon editing-icon-search\" />\n </a>\n </div>\n </li>\n</ul>");
50
54
  };
51
55
 
52
56
  openContentBrowser = function(cmsField) {
53
57
  var id, linkItem;
54
58
  linkItem = cmsField.find('li');
55
- id = linkItem.data('id');
59
+ id = linkItem.attr('data-id');
56
60
  scrivito.content_browser.open({
57
61
  selection: id ? [id] : [],
58
62
  selection_mode: 'single',
@@ -61,10 +65,11 @@
61
65
  }).done(function(selection) {
62
66
  var url, val;
63
67
  if (id = selection[0]) {
64
- url = "/" + id;
68
+ url = scrivito.path_for_id(id);
65
69
  val = "Content browser selection (" + url + ")";
66
- linkItem.data('id', id).find('[name=url]').data('value', url).val(val);
67
- return save(cmsField);
70
+ linkItem.attr('data-id', id).find('[name=url]').attr('data-value', url).val(val);
71
+ save(cmsField);
72
+ return fetchDescription(cmsField, id);
68
73
  }
69
74
  });
70
75
  return false;
@@ -75,7 +80,7 @@
75
80
  li = cmsField.find('li');
76
81
  title = li.find('[name=title]').val();
77
82
  urlInput = li.find('[name=url]');
78
- url = urlInput.data('value') || urlInput.val();
83
+ url = urlInput.attr('data-value') || urlInput.val();
79
84
  value = url ? {
80
85
  title: title,
81
86
  url: url
@@ -1,5 +1,5 @@
1
1
  (function() {
2
- var activate, addLink, attachHandlers, attachLinkHandlers, fetchDescriptions, linkTemplate, openContentBrowser, removeLink, render, save, storeLastSaved;
2
+ var activate, addLink, attachHandlers, attachLinkHandlers, fetchDescriptions, linkTemplate, objIdsFor, openContentBrowser, removeLink, render, save, storeLastSaved;
3
3
 
4
4
  scrivito.on('load', function() {
5
5
  return scrivito.define_editor('linklist', scrivito.editors.linklist_editor);
@@ -18,7 +18,7 @@
18
18
  var linklist;
19
19
  linklist = cmsField.scrivito('content');
20
20
  render(cmsField, linklist);
21
- fetchDescriptions(cmsField, linklist);
21
+ fetchDescriptions(cmsField, objIdsFor(linklist));
22
22
  attachHandlers(cmsField);
23
23
  return storeLastSaved(cmsField, linklist);
24
24
  };
@@ -34,27 +34,15 @@
34
34
  return cmsField.append('<button class="editing-button editing-green add-link">\n <i class="editing-icon editing-icon-plus"></i>\n</button>');
35
35
  };
36
36
 
37
- fetchDescriptions = function(cmsField, linklist) {
38
- var link, obj_ids;
39
- obj_ids = (function() {
40
- var j, len, results;
41
- results = [];
42
- for (j = 0, len = linklist.length; j < len; j++) {
43
- link = linklist[j];
44
- if (link.obj_id) {
45
- results.push(link.obj_id);
46
- }
47
- }
48
- return results;
49
- })();
50
- if (obj_ids.length) {
51
- return scrivito.description_for_editor(obj_ids).then(function(descriptions) {
52
- var i, j, len, obj_id, results, urlInput;
37
+ fetchDescriptions = function(cmsField, objIds) {
38
+ if (objIds.length) {
39
+ return scrivito.description_for_editor(objIds).then(function(descriptions) {
40
+ var i, j, len, objId, results, urlInput;
53
41
  results = [];
54
- for (i = j = 0, len = obj_ids.length; j < len; i = ++j) {
55
- obj_id = obj_ids[i];
56
- urlInput = cmsField.find("[data-id='" + obj_id + "'] [name=url]");
57
- if (!urlInput.is(':focus')) {
42
+ for (i = j = 0, len = objIds.length; j < len; i = ++j) {
43
+ objId = objIds[i];
44
+ urlInput = cmsField.find("[data-id='" + objId + "'] [name=url]");
45
+ if (descriptions[i] && urlInput.not(':focus')) {
58
46
  results.push(urlInput.val(descriptions[i]));
59
47
  } else {
60
48
  results.push(void 0);
@@ -65,6 +53,18 @@
65
53
  }
66
54
  };
67
55
 
56
+ objIdsFor = function(linklist) {
57
+ var j, len, link, results;
58
+ results = [];
59
+ for (j = 0, len = linklist.length; j < len; j++) {
60
+ link = linklist[j];
61
+ if (link.obj_id) {
62
+ results.push(link.obj_id);
63
+ }
64
+ }
65
+ return results;
66
+ };
67
+
68
68
  attachHandlers = function(cmsField) {
69
69
  var j, len, li, ref, results, ul;
70
70
  ul = cmsField.find('ul');
@@ -95,17 +95,17 @@
95
95
  }).find('[name=url]').on('focus', function() {
96
96
  var input, raw;
97
97
  input = $(this);
98
- raw = input.data('value');
98
+ raw = input.attr('data-value');
99
99
  if (raw) {
100
100
  input.val(raw);
101
101
  }
102
- return input.data('value', null);
102
+ return input.attr('data-value', null);
103
103
  });
104
104
  };
105
105
 
106
106
  linkTemplate = function(link) {
107
107
  var obj_url;
108
- obj_url = link.obj_id && ("/" + link.obj_id);
108
+ obj_url = link.obj_id && scrivito.path_for_id(link.obj_id);
109
109
  return $("<li " + (link.obj_id ? "data-id='" + link.obj_id + "'" : void 0) + " data-title=\"" + link.title + "\" data-url=\"" + link.url + "\">\n <input type=\"text\" name=\"title\" value=\"" + (link.title || '') + "\" placeholder=\"Title\" />\n <input type=\"text\" name=\"url\" value=\"" + (link.url || obj_url || '') + "\"\n data-value=\"" + (link.url || obj_url || '') + "\" placeholder=\"Url\" class=\"editing-url\" />\n <div class=\"actions\">\n <a href=\"#\" class=\"scrivito_open_content_browser editing-button editing-green\">\n <i class=\"editing-icon editing-icon-search\" />\n </a>\n <a href=\"#\" class=\"editing-button editing-red delete\">\n <i class=\"editing-icon editing-icon-trash\" />\n </a>\n </div>\n</li>");
110
110
  };
111
111
 
@@ -120,7 +120,7 @@
120
120
  li = $(li);
121
121
  title = li.find('[name=title]').val();
122
122
  input = li.find('[name=url]');
123
- url = input.data('value') || input.val();
123
+ url = input.attr('data-value') || input.val();
124
124
  if (url) {
125
125
  results.push({
126
126
  title: title,
@@ -135,7 +135,7 @@
135
135
  value = $.grep(value, function(n) {
136
136
  return n;
137
137
  });
138
- lastSaved = cmsField.data('scrivito-editors-linklist-last-saved');
138
+ lastSaved = cmsField.attr('data-scrivito-editors-linklist-last-saved');
139
139
  if (JSON.stringify(value) !== JSON.stringify(lastSaved)) {
140
140
  return cmsField.scrivito('save', value).done(function() {
141
141
  cmsField.trigger('save.scrivito_editors');
@@ -154,7 +154,7 @@
154
154
 
155
155
  openContentBrowser = function(cmsField, li) {
156
156
  var id;
157
- id = li.data('id');
157
+ id = li.attr('data-id');
158
158
  scrivito.content_browser.open({
159
159
  selection: id ? [id] : [],
160
160
  selection_mode: 'single',
@@ -164,10 +164,11 @@
164
164
  return function(selection) {
165
165
  var url, val;
166
166
  if (id = selection[0]) {
167
- url = "/" + id;
167
+ url = scrivito.path_for_id(id);
168
168
  val = "Content browser selection (" + url + ")";
169
- li.data('id', id).find('[name=url]').data('value', url).val(val);
170
- return save(cmsField);
169
+ li.attr('data-id', id).find('[name=url]').attr('data-value', url).val(val);
170
+ save(cmsField);
171
+ return fetchDescriptions(cmsField, [id]);
171
172
  }
172
173
  };
173
174
  })(this));
@@ -181,7 +182,7 @@
181
182
  };
182
183
 
183
184
  storeLastSaved = function(cmsField, lastSaved) {
184
- return cmsField.data('scrivito-editors-linklist-last-saved', lastSaved);
185
+ return cmsField.attr('data-scrivito-editors-linklist-last-saved', lastSaved);
185
186
  };
186
187
 
187
188
  }).call(this);
@@ -1,5 +1,5 @@
1
1
  (function() {
2
- var ScrivitoAnchor, activate, editorOptions;
2
+ var ScrivitoAnchor, activate, customOptions, defaultOptions, editorOptions;
3
3
 
4
4
  ScrivitoAnchor = MediumEditor.extensions.anchor.extend({
5
5
  name: 'scrivito_anchor',
@@ -26,9 +26,8 @@
26
26
  input = form.find('.medium-editor-toolbar-input');
27
27
  return form.find('.medium-editor-toolbar-browse').on('click', (function(_this) {
28
28
  return function() {
29
- var cmsField, matches, selection;
30
- matches = input.val().match(/\b([a-f0-9]{16})\b/);
31
- selection = matches != null ? [matches[1]] : [];
29
+ var cmsField, id, selection;
30
+ selection = (id = scrivito.id_from_path(input.val())) ? [id] : [];
32
31
  cmsField = $(_this.base.origElements);
33
32
  scrivito.content_browser.open({
34
33
  filter: cmsField.data('scrivitoEditorsFilter'),
@@ -38,7 +37,11 @@
38
37
  }).always(function() {
39
38
  return input.focus();
40
39
  }).done(function(selection) {
41
- return input.val(selection);
40
+ if (selection.length) {
41
+ return input.val(scrivito.path_for_id(selection[0]));
42
+ } else {
43
+ return input.val('');
44
+ }
42
45
  });
43
46
  return false;
44
47
  };
@@ -55,28 +58,36 @@
55
58
  }
56
59
  });
57
60
 
58
- editorOptions = function(toolbarOptions) {
59
- var options;
60
- options = {
61
+ editorOptions = function() {
62
+ return $.extend({}, defaultOptions(), customOptions());
63
+ };
64
+
65
+ defaultOptions = function() {
66
+ return {
61
67
  anchorPreview: false,
62
68
  extensions: {
63
69
  scrivito_anchor: new ScrivitoAnchor
64
70
  },
71
+ placeholder: false,
65
72
  toolbar: {
66
- buttons: ['h1', 'h2', 'h3', 'bold', 'italic', 'scrivito_anchor', 'underline', 'orderedlist', 'unorderedlist', 'indent', 'outdent', 'justifyLeft', 'justifyCenter', 'justifyFull']
73
+ buttons: ['bold', 'italic', 'scrivito_anchor', 'h2', 'h3', 'unorderedlist', 'orderedlist'],
74
+ standardizeSelectionStart: true
67
75
  }
68
76
  };
69
- if (toolbarOptions) {
70
- options.toolbar = toolbarOptions;
77
+ };
78
+
79
+ customOptions = function() {
80
+ if (typeof scrivito.editors.medium_editor.options === 'function') {
81
+ return scrivito.editors.medium_editor.options();
82
+ } else {
83
+ return scrivito.editors.medium_editor.options;
71
84
  }
72
- options.toolbar.standardizeSelectionStart = true;
73
- return options;
74
85
  };
75
86
 
76
87
  activate = function(element) {
77
88
  var cmsField;
78
89
  cmsField = $(element);
79
- return new MediumEditor(cmsField, editorOptions(cmsField.data('medium-editor-toolbar'))).subscribe('editableInput', function() {
90
+ return new MediumEditor(cmsField, editorOptions()).subscribe('editableInput', function() {
80
91
  return cmsField.scrivito('save', cmsField.html());
81
92
  });
82
93
  };
@@ -87,6 +98,9 @@
87
98
  },
88
99
  activate: function(element) {
89
100
  return activate(element);
101
+ },
102
+ options: function() {
103
+ return {};
90
104
  }
91
105
  };
92
106
 
@@ -33,7 +33,7 @@
33
33
  })(this));
34
34
  },
35
35
  insert: function(id) {
36
- return this.image.insert("<img src='/" + id + "'>");
36
+ return this.image.insert("<img src='" + (scrivito.path_for_id(id)) + "'>");
37
37
  }
38
38
  };
39
39
  };
@@ -8,7 +8,6 @@
8
8
  return self = {
9
9
  init: function() {
10
10
  this.modal.addTemplate('scrivito_link_manager_browse', self.browseButtonHtml);
11
- this.modal.addTemplate('scrivito_link_manager_url', '/$id');
12
11
  this.modal.addCallback('imageEdit', self.addBrowseToModal);
13
12
  return this.modal.addCallback('link', self.addBrowseToModal);
14
13
  },
@@ -36,19 +35,15 @@
36
35
  })(this));
37
36
  },
38
37
  getObjIds: function() {
39
- var matches;
40
- matches = self.urlInput().val().match(/[\/:]([a-f0-9]{16})\b/);
41
- if (matches != null) {
42
- return [matches[1]];
38
+ var id;
39
+ if (id = scrivito.id_from_path(self.urlInput().val())) {
40
+ return [id];
43
41
  } else {
44
42
  return [];
45
43
  }
46
44
  },
47
45
  setObjId: function(id) {
48
- return self.urlInput().val(self.toUrl(id));
49
- },
50
- toUrl: function(id) {
51
- return this.modal.getTemplate('scrivito_link_manager_url').replace("$id", id);
46
+ return self.urlInput().val(scrivito.path_for_id(id));
52
47
  }
53
48
  };
54
49
  };
@@ -4,11 +4,13 @@
4
4
  activate = function(element) {
5
5
  var cmsField, objId;
6
6
  cmsField = $(element);
7
- objId = cmsField.scrivito('content');
8
- if (objId && !cmsField.children().length) {
9
- scrivito.description_for_editor([objId]).then(function(results) {
10
- return cmsField.text(results[0]);
11
- });
7
+ if (!cmsField.is('video, audio, img')) {
8
+ objId = cmsField.scrivito('content');
9
+ if (objId && !cmsField.children().length) {
10
+ scrivito.description_for_editor([objId]).then(function(results) {
11
+ return cmsField.text(results[0]);
12
+ });
13
+ }
12
14
  }
13
15
  return cmsField.on('click', function(event) {
14
16
  var filterContext, filters, isImage, selected;
@@ -42,13 +42,9 @@
42
42
  save = function(cmsField) {
43
43
  var content;
44
44
  content = getCurrentContent(cmsField);
45
- if (content !== cmsField.scrivito('content')) {
46
- return cmsField.scrivito('save', content).done(function() {
47
- return cmsField.trigger('save.scrivito_editors');
48
- });
49
- } else {
50
- return $.Deferred().resolve();
51
- }
45
+ return cmsField.scrivito('save', content).done(function() {
46
+ return cmsField.trigger('scrivito_editors:save');
47
+ });
52
48
  };
53
49
 
54
50
  getCurrentContent = function(cmsField) {
@@ -8,6 +8,17 @@
8
8
  field = $(element);
9
9
  return field.tagEditor({
10
10
  initialTags: field.scrivito('content'),
11
+ autocomplete: {
12
+ source: (function(_this) {
13
+ return function(request, response) {
14
+ var fieldName;
15
+ fieldName = $(element).data("scrivitoFieldName");
16
+ return scrivito.suggest_completion(fieldName, request.term).then(function(suggestions) {
17
+ return response(suggestions);
18
+ });
19
+ };
20
+ })(this)
21
+ },
11
22
  onChange: function(field, editor, tags) {
12
23
  return field.scrivito('save', tags);
13
24
  }
@@ -2,3 +2,4 @@
2
2
  //= require jquery-ui/datepicker
3
3
  //= require jquery-ui/slider
4
4
  //= require jquery-ui-timepicker-addon.min
5
+ //= require jquery-ui/autocomplete
@@ -5,10 +5,14 @@
5
5
  }
6
6
  .scrivito-editor-binary-button-container:not(.scrivito-editor-image-button-container) {
7
7
  display:block; position: relative;
8
- background: rgba(0,0,0,.1);
9
8
  box-shadow: 0 0 0 2px rgba(0,0,0,.2);
10
9
  min-height: 90px; padding:5px;
11
10
  }
11
+
12
+ .scrivito-editor-binary-button-container:not(.scrivito-editor-image-button-container):not(.scrivito_element_overlay) {
13
+ background: rgba(0,0,0,.1);
14
+ }
15
+
12
16
  .scrivito-editor-image-button-container .editing-button,
13
17
  .scrivito-editor-binary-button-container .editing-button {
14
18
  padding: 5px 8px; margin: 0px;
@@ -4,7 +4,7 @@
4
4
  *= require_self
5
5
  */
6
6
  .medium-toolbar-arrow-under::after { top: auto;}
7
- .medium-editor-toolbar { z-index: 11112; margin:0 10px; background:rgba(67, 148, 57, 0.9);
7
+ .medium-editor-toolbar { z-index: 111112; margin:0 10px; background:rgba(67, 148, 57, 0.9);
8
8
  border-radius:4px;}
9
9
  .medium-editor-toolbar li button { height:40px; min-width:40px; padding:10px;
10
10
  border:none; margin:1px; background:rgba(0,0,0,.1);
@@ -4,7 +4,7 @@
4
4
  */
5
5
  [data-scrivito-display-mode="editing"] [data-scrivito-editors-placeholder]:empty:not(:focus):before {
6
6
  content: attr(data-scrivito-editors-placeholder);
7
- color: #999;
7
+ color: rgba(64, 64, 64, 0.53);
8
8
  display: inline-block;
9
9
  font-size: 13px;
10
10
  font-style: normal;
@@ -24,6 +24,7 @@
24
24
  /* Firefox: Let the input cursor appear at the expected position */
25
25
  [data-scrivito-display-mode="editing"] [data-scrivito-editors-placeholder]:empty:focus:after,
26
26
  [data-scrivito-display-mode="editing"] [data-scrivito-editors-placeholder]:empty:focus:before {
27
- content: " ";
27
+ content: "\200b";
28
+ color: transparent;
28
29
  display: inline-block;
29
30
  }
@@ -1,5 +1,6 @@
1
1
  /*
2
2
  *= require jquery.tag-editor
3
+ *= require jquery-ui/autocomplete
3
4
  */
4
5
 
5
6
  [data-scrivito-field-type=stringlist]+.tag-editor .tag-editor-delete { padding-right: 10px; }
@@ -625,7 +625,7 @@ MediumEditor.extensions = {};
625
625
  /*
626
626
  * Take an element, and break up all of its text content into unique pieces such that:
627
627
  * 1) All text content of the elements are in separate blocks. No piece of text content should span
628
- * span multiple blocks. This means no element return by this function should have
628
+ * across multiple blocks. This means no element return by this function should have
629
629
  * any blocks as children.
630
630
  * 2) The union of the textcontent of all of the elements returned here covers all
631
631
  * of the text within the element.
@@ -2307,6 +2307,10 @@ MediumEditor.extensions = {};
2307
2307
  // Detecting keydown on the contenteditables
2308
2308
  this.attachToEachElement('keydown', this.handleKeydown);
2309
2309
  break;
2310
+ case 'editableKeydownSpace':
2311
+ // Detecting keydown for SPACE on the contenteditables
2312
+ this.setupListener('editableKeydown');
2313
+ break;
2310
2314
  case 'editableKeydownEnter':
2311
2315
  // Detecting keydown for ENTER on the contenteditables
2312
2316
  this.setupListener('editableKeydown');
@@ -2519,8 +2523,13 @@ MediumEditor.extensions = {};
2519
2523
  },
2520
2524
 
2521
2525
  handleKeydown: function (event) {
2526
+
2522
2527
  this.triggerCustomEvent('editableKeydown', event, event.currentTarget);
2523
2528
 
2529
+ if (MediumEditor.util.isKey(event, MediumEditor.util.keyCode.SPACE)) {
2530
+ return this.triggerCustomEvent('editableKeydownSpace', event, event.currentTarget);
2531
+ }
2532
+
2524
2533
  if (MediumEditor.util.isKey(event, MediumEditor.util.keyCode.ENTER) || (event.ctrlKey && MediumEditor.util.isKey(event, MediumEditor.util.keyCode.M))) {
2525
2534
  return this.triggerCustomEvent('editableKeydownEnter', event, event.currentTarget);
2526
2535
  }
@@ -3322,7 +3331,7 @@ MediumEditor.extensions = {};
3322
3331
  var targetCheckbox = this.getAnchorTargetCheckbox(),
3323
3332
  buttonCheckbox = this.getAnchorButtonCheckbox(),
3324
3333
  opts = {
3325
- url: this.getInput().value
3334
+ url: this.getInput().value.trim()
3326
3335
  };
3327
3336
 
3328
3337
  if (this.linkValidation) {
@@ -3442,6 +3451,7 @@ MediumEditor.extensions = {};
3442
3451
 
3443
3452
  MediumEditor.extensions.anchor = AnchorForm;
3444
3453
  }());
3454
+
3445
3455
  (function () {
3446
3456
  'use strict';
3447
3457
 
@@ -3460,6 +3470,11 @@ MediumEditor.extensions = {};
3460
3470
  */
3461
3471
  previewValueSelector: 'a',
3462
3472
 
3473
+ /* showWhenToolbarIsVisible: [boolean]
3474
+ * determines whether the anchor tag preview shows up when the toolbar is visible
3475
+ */
3476
+ showWhenToolbarIsVisible: false,
3477
+
3463
3478
  init: function () {
3464
3479
  this.anchorPreview = this.createPreview();
3465
3480
 
@@ -3611,7 +3626,7 @@ MediumEditor.extensions = {};
3611
3626
 
3612
3627
  // only show when toolbar is not present
3613
3628
  var toolbar = this.base.getExtensionByName('toolbar');
3614
- if (toolbar && toolbar.isDisplayed && toolbar.isDisplayed()) {
3629
+ if (!this.showWhenToolbarIsVisible && toolbar && toolbar.isDisplayed && toolbar.isDisplayed()) {
3615
3630
  return true;
3616
3631
  }
3617
3632
 
@@ -3774,11 +3789,26 @@ MediumEditor.extensions = {};
3774
3789
  },
3775
3790
 
3776
3791
  performLinking: function (contenteditable) {
3777
- // Perform linking on a paragraph level basis as otherwise the detection can wrongly find the end
3778
- // of one paragraph and the beginning of another paragraph to constitute a link, such as a paragraph ending
3779
- // "link." and the next paragraph beginning with "my" is interpreted into "link.my" and the code tries to create
3780
- // a link across blockElements - which doesn't work and is terrible.
3781
- // (Medium deletes the spaces/returns between P tags so the textContent ends up without paragraph spacing)
3792
+ /*
3793
+ Perform linking on blockElement basis, blockElements are HTML elements with text content and without
3794
+ child element.
3795
+
3796
+ Example:
3797
+ - HTML content
3798
+ <blockquote>
3799
+ <p>link.</p>
3800
+ <p>my</p>
3801
+ </blockquote>
3802
+
3803
+ - blockElements
3804
+ [<p>link.</p>, <p>my</p>]
3805
+
3806
+ otherwise the detection can wrongly find the end of one paragraph and the beginning of another paragraph
3807
+ to constitute a link, such as a paragraph ending "link." and the next paragraph beginning with "my" is
3808
+ interpreted into "link.my" and the code tries to create a link across blockElements - which doesn't work
3809
+ and is terrible.
3810
+ (Medium deletes the spaces/returns between P tags so the textContent ends up without paragraph spacing)
3811
+ */
3782
3812
  var blockElements = MediumEditor.util.splitByBlockElements(contenteditable),
3783
3813
  documentModified = false;
3784
3814
  if (blockElements.length === 0) {
@@ -3917,6 +3947,7 @@ MediumEditor.extensions = {};
3917
3947
 
3918
3948
  MediumEditor.extensions.autoLink = AutoLink;
3919
3949
  }());
3950
+
3920
3951
  (function () {
3921
3952
  'use strict';
3922
3953
 
@@ -4090,6 +4121,191 @@ MediumEditor.extensions = {};
4090
4121
  MediumEditor.extensions.keyboardCommands = KeyboardCommands;
4091
4122
  }());
4092
4123
 
4124
+ (function () {
4125
+ 'use strict';
4126
+
4127
+ var FontNameForm = MediumEditor.extensions.form.extend({
4128
+
4129
+ name: 'fontname',
4130
+ action: 'fontName',
4131
+ aria: 'change font name',
4132
+ contentDefault: '&#xB1;', // ±
4133
+ contentFA: '<i class="fa fa-font"></i>',
4134
+
4135
+ fonts: ['', 'Arial', 'Verdana', 'Times New Roman'],
4136
+
4137
+ init: function () {
4138
+ MediumEditor.extensions.form.prototype.init.apply(this, arguments);
4139
+ },
4140
+
4141
+ // Called when the button the toolbar is clicked
4142
+ // Overrides ButtonExtension.handleClick
4143
+ handleClick: function (event) {
4144
+ event.preventDefault();
4145
+ event.stopPropagation();
4146
+
4147
+ if (!this.isDisplayed()) {
4148
+ // Get FontName of current selection (convert to string since IE returns this as number)
4149
+ var fontName = this.document.queryCommandValue('fontName') + '';
4150
+ this.showForm(fontName);
4151
+ }
4152
+
4153
+ return false;
4154
+ },
4155
+
4156
+ // Called by medium-editor to append form to the toolbar
4157
+ getForm: function () {
4158
+ if (!this.form) {
4159
+ this.form = this.createForm();
4160
+ }
4161
+ return this.form;
4162
+ },
4163
+
4164
+ // Used by medium-editor when the default toolbar is to be displayed
4165
+ isDisplayed: function () {
4166
+ return this.getForm().style.display === 'block';
4167
+ },
4168
+
4169
+ hideForm: function () {
4170
+ this.getForm().style.display = 'none';
4171
+ this.getSelect().value = '';
4172
+ },
4173
+
4174
+ showForm: function (fontName) {
4175
+ var select = this.getSelect();
4176
+
4177
+ this.base.saveSelection();
4178
+ this.hideToolbarDefaultActions();
4179
+ this.getForm().style.display = 'block';
4180
+ this.setToolbarPosition();
4181
+
4182
+ select.value = fontName || '';
4183
+ select.focus();
4184
+ },
4185
+
4186
+ // Called by core when tearing down medium-editor (destroy)
4187
+ destroy: function () {
4188
+ if (!this.form) {
4189
+ return false;
4190
+ }
4191
+
4192
+ if (this.form.parentNode) {
4193
+ this.form.parentNode.removeChild(this.form);
4194
+ }
4195
+
4196
+ delete this.form;
4197
+ },
4198
+
4199
+ // core methods
4200
+
4201
+ doFormSave: function () {
4202
+ this.base.restoreSelection();
4203
+ this.base.checkSelection();
4204
+ },
4205
+
4206
+ doFormCancel: function () {
4207
+ this.base.restoreSelection();
4208
+ this.clearFontName();
4209
+ this.base.checkSelection();
4210
+ },
4211
+
4212
+ // form creation and event handling
4213
+ createForm: function () {
4214
+ var doc = this.document,
4215
+ form = doc.createElement('div'),
4216
+ select = doc.createElement('select'),
4217
+ close = doc.createElement('a'),
4218
+ save = doc.createElement('a'),
4219
+ option;
4220
+
4221
+ // Font Name Form (div)
4222
+ form.className = 'medium-editor-toolbar-form';
4223
+ form.id = 'medium-editor-toolbar-form-fontname-' + this.getEditorId();
4224
+
4225
+ // Handle clicks on the form itself
4226
+ this.on(form, 'click', this.handleFormClick.bind(this));
4227
+
4228
+ // Add font names
4229
+ for (var i = 0; i<this.fonts.length; i++) {
4230
+ option = doc.createElement('option');
4231
+ option.innerHTML = this.fonts[i];
4232
+ option.value = this.fonts[i];
4233
+ select.appendChild(option);
4234
+ }
4235
+
4236
+ select.className = 'medium-editor-toolbar-select';
4237
+ form.appendChild(select);
4238
+
4239
+ // Handle typing in the textbox
4240
+ this.on(select, 'change', this.handleFontChange.bind(this));
4241
+
4242
+ // Add save buton
4243
+ save.setAttribute('href', '#');
4244
+ save.className = 'medium-editor-toobar-save';
4245
+ save.innerHTML = this.getEditorOption('buttonLabels') === 'fontawesome' ?
4246
+ '<i class="fa fa-check"></i>' :
4247
+ '&#10003;';
4248
+ form.appendChild(save);
4249
+
4250
+ // Handle save button clicks (capture)
4251
+ this.on(save, 'click', this.handleSaveClick.bind(this), true);
4252
+
4253
+ // Add close button
4254
+ close.setAttribute('href', '#');
4255
+ close.className = 'medium-editor-toobar-close';
4256
+ close.innerHTML = this.getEditorOption('buttonLabels') === 'fontawesome' ?
4257
+ '<i class="fa fa-times"></i>' :
4258
+ '&times;';
4259
+ form.appendChild(close);
4260
+
4261
+ // Handle close button clicks
4262
+ this.on(close, 'click', this.handleCloseClick.bind(this));
4263
+
4264
+ return form;
4265
+ },
4266
+
4267
+ getSelect: function () {
4268
+ return this.getForm().querySelector('select.medium-editor-toolbar-select');
4269
+ },
4270
+
4271
+ clearFontName: function () {
4272
+ MediumEditor.selection.getSelectedElements(this.document).forEach(function (el) {
4273
+ if (el.nodeName.toLowerCase() === 'font' && el.hasAttribute('face')) {
4274
+ el.removeAttribute('face');
4275
+ }
4276
+ });
4277
+ },
4278
+
4279
+ handleFontChange: function () {
4280
+ var font = this.getSelect().value;
4281
+ if (font === '') {
4282
+ this.clearFontName();
4283
+ } else {
4284
+ this.execAction('fontName', { name: font });
4285
+ }
4286
+ },
4287
+
4288
+ handleFormClick: function (event) {
4289
+ // make sure not to hide form when clicking inside the form
4290
+ event.stopPropagation();
4291
+ },
4292
+
4293
+ handleSaveClick: function (event) {
4294
+ // Clicking Save -> create the font size
4295
+ event.preventDefault();
4296
+ this.doFormSave();
4297
+ },
4298
+
4299
+ handleCloseClick: function (event) {
4300
+ // Click Close -> close the form
4301
+ event.preventDefault();
4302
+ this.doFormCancel();
4303
+ }
4304
+ });
4305
+
4306
+ MediumEditor.extensions.fontName = FontNameForm;
4307
+ }());
4308
+
4093
4309
  (function () {
4094
4310
  'use strict';
4095
4311
 
@@ -5354,15 +5570,26 @@ MediumEditor.extensions = {};
5354
5570
 
5355
5571
  // Event handlers that shouldn't be exposed externally
5356
5572
 
5573
+ function handleDisableExtraSpaces(event) {
5574
+ var node = MediumEditor.selection.getSelectionStart(this.options.ownerDocument),
5575
+ textContent = node.textContent,
5576
+ caretPositions = MediumEditor.selection.getCaretOffsets(node);
5577
+
5578
+ if ((textContent[caretPositions.left - 1] === undefined) || (textContent[caretPositions.left - 1] === ' ') || (textContent[caretPositions.left] === undefined)) {
5579
+ event.preventDefault();
5580
+ }
5581
+ }
5582
+
5357
5583
  function handleDisabledEnterKeydown(event, element) {
5358
5584
  if (this.options.disableReturn || element.getAttribute('data-disable-return')) {
5359
5585
  event.preventDefault();
5360
5586
  } else if (this.options.disableDoubleReturn || element.getAttribute('data-disable-double-return')) {
5361
5587
  var node = MediumEditor.selection.getSelectionStart(this.options.ownerDocument);
5362
5588
 
5363
- // if current text selection is empty OR previous sibling text is empty
5364
- if ((node && node.textContent.trim() === '') ||
5365
- (node.previousElementSibling && node.previousElementSibling.textContent.trim() === '')) {
5589
+ // if current text selection is empty OR previous sibling text is empty OR it is not a list
5590
+ if ((node && node.textContent.trim() === '' && node.nodeName.toLowerCase() !== 'li') ||
5591
+ (node.previousElementSibling && node.previousElementSibling.nodeName.toLowerCase() !== 'br' &&
5592
+ node.previousElementSibling.textContent.trim() === '')) {
5366
5593
  event.preventDefault();
5367
5594
  }
5368
5595
  }
@@ -5702,6 +5929,11 @@ MediumEditor.extensions = {};
5702
5929
  this.subscribe('editableKeydownDelete', handleBlockDeleteKeydowns.bind(this));
5703
5930
  this.subscribe('editableKeydownEnter', handleBlockDeleteKeydowns.bind(this));
5704
5931
 
5932
+ // Bind double space event
5933
+ if (this.options.disableExtraSpaces) {
5934
+ this.subscribe('editableKeydownSpace', handleDisableExtraSpaces.bind(this));
5935
+ }
5936
+
5705
5937
  // disabling return or double return
5706
5938
  if (this.options.disableReturn || this.options.disableDoubleReturn) {
5707
5939
  this.subscribe('editableKeydownEnter', handleDisabledEnterKeydown.bind(this));
@@ -5828,6 +6060,10 @@ MediumEditor.extensions = {};
5828
6060
  return this.options.ownerDocument.execCommand('fontSize', false, opts.size);
5829
6061
  }
5830
6062
 
6063
+ if (action === 'fontName') {
6064
+ return this.options.ownerDocument.execCommand('fontName', false, opts.name);
6065
+ }
6066
+
5831
6067
  if (action === 'createLink') {
5832
6068
  return this.createLink(opts);
5833
6069
  }
@@ -6057,6 +6293,9 @@ MediumEditor.extensions = {};
6057
6293
  case 'fileDragging':
6058
6294
  extension = new MediumEditor.extensions.fileDragging(opts);
6059
6295
  break;
6296
+ case 'fontname':
6297
+ extension = new MediumEditor.extensions.fontName(this.options.fontName);
6298
+ break;
6060
6299
  case 'fontsize':
6061
6300
  extension = new MediumEditor.extensions.fontSize(opts);
6062
6301
  break;
@@ -6410,6 +6649,7 @@ MediumEditor.extensions = {};
6410
6649
  delay: 0,
6411
6650
  disableReturn: false,
6412
6651
  disableDoubleReturn: false,
6652
+ disableExtraSpaces: false,
6413
6653
  disableEditing: false,
6414
6654
  autoLink: false,
6415
6655
  elementsContainer: false,
@@ -6438,7 +6678,7 @@ MediumEditor.parseVersionString = function (release) {
6438
6678
 
6439
6679
  MediumEditor.version = MediumEditor.parseVersionString.call(this, ({
6440
6680
  // grunt-bump looks for this:
6441
- 'version': '5.8.3'
6681
+ 'version': '5.10.0'
6442
6682
  }).version);
6443
6683
 
6444
6684
  return MediumEditor;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scrivito_editors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scrivito
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-07 00:00:00.000000000 Z
11
+ date: 2016-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jquery-ui-rails
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
47
+ version: 1.1.0.rc1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 1.0.0
54
+ version: 1.1.0.rc1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: scrivito_sdk
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.0.0
61
+ version: 1.1.0.rc1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.0
68
+ version: 1.1.0.rc1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: coffee-rails
71
71
  requirement: !ruby/object:Gem::Requirement