scrivito_editors 1.0.0 → 1.1.0.rc1

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