@financial-times/n-myft-ui 28.0.7 → 28.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@
4
4
  data-myft-ui="saved"
5
5
  action="/myft/save/{{contentId}}"
6
6
  data-js-action="/__myft/api/core/saved/content/{{contentId}}?method=put"
7
- {{#ifEquals @root.flags.professorLists 'variant'}}data-myft-ui-variant="createListAndSaveArticleVariant"{{/ifEquals}}>
7
+ {{#if @root.flags.manageArticleLists}}data-myft-ui-save-new="manageArticleLists"{{/if}}>
8
8
  {{> n-myft-ui/components/csrf-token/input}}
9
9
  <div
10
10
  class="n-myft-ui__announcement o-normalise-visually-hidden"
package/myft/ui/lists.js CHANGED
@@ -179,8 +179,8 @@ function handleArticleSaved (contentId) {
179
179
  function openCreateListAndAddArticleOverlay (contentId) {
180
180
  return myFtClient.getAll('created', 'list')
181
181
  .then(createdLists => createdLists.filter(list => !list.isRedirect))
182
- .then(createdLists => {
183
- return !createdLists.length ? showCreateListAndAddArticleOverlay(contentId) : showArticleSavedOverlay(contentId);
182
+ .then(() => {
183
+ return showCreateListAndAddArticleOverlay(contentId);
184
184
  });
185
185
  }
186
186
 
@@ -192,8 +192,8 @@ function initialEventListeners () {
192
192
  // Checks if the createListAndSaveArticle variant is active
193
193
  // and will show the variant overlay if the user has no lists,
194
194
  // otherwise it will show the classic overlay
195
- const createListVariant = event.currentTarget.querySelector('[data-myft-ui-variant="createListAndSaveArticleVariant"]');
196
- if (createListVariant) {
195
+ const createNewListDesign = event.currentTarget.querySelector('[data-myft-ui-save-new="manageArticleLists"]');
196
+ if (createNewListDesign) {
197
197
  return openCreateListAndAddArticleOverlay(contentId);
198
198
  }
199
199
 
@@ -5,20 +5,14 @@ import getToken from './lib/get-csrf-token';
5
5
 
6
6
  const csrfToken = getToken();
7
7
 
8
- let lists;
8
+ let lists = [];
9
+ let haveLoadedLists = false;
9
10
 
10
- export default async function showSaveArticleToListVariant (name, contentId) {
11
- try {
12
- await openSaveArticleToListVariant (name, contentId);
13
- } catch(error) {
14
- handleError(error);
15
- }
16
- }
17
-
18
- async function openSaveArticleToListVariant (name, contentId) {
11
+ export default async function openSaveArticleToListVariant (name, contentId) {
19
12
  function createList (list) {
20
13
  if(!list) {
21
- return;
14
+ if (!lists.length) attachDescription();
15
+ return contentElement.addEventListener('click', openFormHandler, { once: true });
22
16
  }
23
17
 
24
18
  myFtClient.add('user', null, 'created', 'list', uuid(), { name: list, token: csrfToken })
@@ -33,6 +27,10 @@ async function openSaveArticleToListVariant (name, contentId) {
33
27
  triggerCreateListEvent(contentId);
34
28
  contentElement.addEventListener('click', openFormHandler, { once: true });
35
29
  });
30
+ })
31
+ .catch(() => {
32
+ if (!lists.length) attachDescription();
33
+ return contentElement.addEventListener('click', openFormHandler, { once: true });
36
34
  });
37
35
  }
38
36
 
@@ -66,8 +64,9 @@ async function openSaveArticleToListVariant (name, contentId) {
66
64
  });
67
65
  }
68
66
 
69
- if (!lists) {
67
+ if (!haveLoadedLists) {
70
68
  lists = await getLists(contentId);
69
+ haveLoadedLists = true;
71
70
  }
72
71
 
73
72
  const overlays = Overlay.getOverlays();
@@ -77,7 +76,7 @@ async function openSaveArticleToListVariant (name, contentId) {
77
76
  }
78
77
 
79
78
  const headingElement = HeadingElement();
80
- let [contentElement, removeDescription] = ContentElement(!lists.length);
79
+ let [contentElement, removeDescription, attachDescription] = ContentElement(!lists.length);
81
80
 
82
81
  const createListOverlay = new Overlay(name, {
83
82
  html: contentElement,
@@ -87,36 +86,37 @@ async function openSaveArticleToListVariant (name, contentId) {
87
86
  class: 'myft-ui-create-list-variant',
88
87
  });
89
88
 
90
- const realignListener = realignOverlay(window.scrollY);
91
-
92
89
  function outsideClickHandler (e) {
93
- try {
94
- const overlayContent = document.querySelector('.o-overlay__content');
95
- if(!overlayContent || !overlayContent.contains(e.target)) {
96
- createListOverlay.close();
97
- }
98
- } catch(error) {
99
- handleError(error);
90
+ const overlayContent = document.querySelector('.o-overlay__content');
91
+ if(createListOverlay.visible && (!overlayContent || !overlayContent.contains(e.target))) {
92
+ createListOverlay.close();
100
93
  }
101
94
  }
102
95
 
103
96
  function openFormHandler () {
104
- try {
105
- const formElement = FormElement(createList);
106
- const overlayContent = document.querySelector('.o-overlay__content');
107
- removeDescription();
108
- overlayContent.insertAdjacentElement('beforeend', formElement);
109
- formElement.elements[0].focus();
110
- } catch(error) {
111
- handleError(error);
112
- }
97
+ const formElement = FormElement(createList);
98
+ const overlayContent = document.querySelector('.o-overlay__content');
99
+ removeDescription();
100
+ overlayContent.insertAdjacentElement('beforeend', formElement);
101
+ formElement.elements[0].focus();
102
+ }
103
+
104
+ function getScrollHandler (target) {
105
+ return realignOverlay(window.scrollY, target);
106
+ }
107
+
108
+ function resizeHandler () {
109
+ positionOverlay(createListOverlay.wrapper);
113
110
  }
114
111
 
115
112
  createListOverlay.open();
113
+
114
+ const scrollHandler = getScrollHandler(createListOverlay.wrapper);
115
+
116
116
  createListOverlay.wrapper.addEventListener('oOverlay.ready', (data) => {
117
- realignListener(data.currentTarget);
117
+ positionOverlay(data.currentTarget);
118
118
 
119
- if (lists && lists.length) {
119
+ if (lists.length) {
120
120
  const listElement = ListsElement(lists, addToList, removeFromList);
121
121
  const overlayContent = document.querySelector('.o-overlay__content');
122
122
  overlayContent.insertAdjacentElement('afterbegin', listElement);
@@ -125,12 +125,16 @@ async function openSaveArticleToListVariant (name, contentId) {
125
125
  contentElement.addEventListener('click', openFormHandler, { once: true });
126
126
 
127
127
  document.querySelector('.article-content').addEventListener('click', outsideClickHandler, { once: true });
128
+
129
+ window.addEventListener('scroll', scrollHandler);
130
+
131
+ window.addEventListener('oViewport.resize', resizeHandler);
128
132
  });
129
133
 
130
- window.addEventListener('scroll', realignListener(createListOverlay.wrapper, window.scrollY));
134
+ createListOverlay.wrapper.addEventListener('oOverlay.destroy', () => {
135
+ window.removeEventListener('scroll', scrollHandler);
131
136
 
132
- window.addEventListener('oViewport.resize', () => {
133
- realignListener(createListOverlay.wrapper);
137
+ window.removeEventListener('oViewport.resize', resizeHandler);
134
138
  });
135
139
  }
136
140
 
@@ -157,16 +161,12 @@ function FormElement (createList) {
157
161
  const formElement = stringToHTMLElement(formString);
158
162
 
159
163
  function handleSubmit (event) {
160
- try {
161
- event.preventDefault();
162
- event.stopPropagation();
163
- const inputListName = formElement.querySelector('input[name="list-name"]');
164
- createList(inputListName.value);
165
- inputListName.value = '';
166
- formElement.remove();
167
- } catch(error) {
168
- handleError(error);
169
- }
164
+ event.preventDefault();
165
+ event.stopPropagation();
166
+ const inputListName = formElement.querySelector('input[name="list-name"]');
167
+ createList(inputListName.value);
168
+ inputListName.value = '';
169
+ formElement.remove();
170
170
  }
171
171
 
172
172
  formElement.querySelector('button[type="submit"]').addEventListener('click', handleSubmit);
@@ -174,12 +174,14 @@ function FormElement (createList) {
174
174
  return formElement;
175
175
  }
176
176
 
177
- function ContentElement (description) {
177
+ function ContentElement (hasDescription) {
178
+ const description = '<p class="myft-ui-create-list-variant-add-description">Lists are a simple way to curate your content</p>';
179
+
178
180
  const content = `
179
181
  <div class="myft-ui-create-list-variant-footer">
180
182
  <button class="myft-ui-create-list-variant-add">Add to a new list</button>
181
- ${description ? `
182
- <p class="myft-ui-create-list-variant-add-description">Lists are a simple way to curate your content</p>
183
+ ${hasDescription ? `
184
+ ${description}
183
185
  ` : ''}
184
186
  </div>
185
187
  `;
@@ -193,7 +195,12 @@ function ContentElement (description) {
193
195
  }
194
196
  }
195
197
 
196
- return [contentElement, removeDescription];
198
+ function attachDescription () {
199
+ const descriptionElement = stringToHTMLElement(description);
200
+ contentElement.insertAdjacentElement('beforeend', descriptionElement);
201
+ }
202
+
203
+ return [contentElement, removeDescription, attachDescription];
197
204
  }
198
205
 
199
206
  function HeadingElement () {
@@ -256,36 +263,41 @@ function ListCheckboxElement (addToList, removeFromList) {
256
263
  };
257
264
  }
258
265
 
259
- function realignOverlay (originalScrollPosition) {
260
- return function (target, currentScrollPosition) {
261
- try {
262
- if(currentScrollPosition && Math.abs(currentScrollPosition - originalScrollPosition) < 120) {
263
- return;
264
- }
265
-
266
- originalScrollPosition = currentScrollPosition;
267
-
268
- target.style['min-width'] = '340px';
269
- target.style['width'] = '100%';
270
- target.style['margin-top'] = '-50px';
271
- target.style['left'] = 0;
272
-
273
- if (isMobile()) {
274
- target.style['position'] = 'absolute';
275
- target.style['margin-left'] = 0;
276
- target.style['margin-top'] = 0;
277
- target.style['top'] = calculateLargerScreenHalf(target) === 'ABOVE' ? '-120px' : '50px';
278
- } else {
279
- target.style['position'] = 'absolute';
280
- target.style['margin-left'] = '45px';
281
- target.style['top'] = '220px';
282
- }
283
- } catch (error) {
284
- handleError(error);
266
+ function realignOverlay (originalScrollPosition, target) {
267
+ return function () {
268
+ const currentScrollPosition = window.scrollY;
269
+
270
+ if(Math.abs(currentScrollPosition - originalScrollPosition) < 120) {
271
+ return;
285
272
  }
273
+
274
+ if (currentScrollPosition) {
275
+ originalScrollPosition = currentScrollPosition;;
276
+ }
277
+
278
+ positionOverlay(target);
286
279
  };
287
280
  }
288
281
 
282
+ function positionOverlay (target) {
283
+ target.style['min-width'] = '340px';
284
+ target.style['width'] = '100%';
285
+ target.style['margin-top'] = '-50px';
286
+ target.style['left'] = 0;
287
+
288
+ if (isMobile()) {
289
+ const shareNavComponent = document.querySelector('.share-nav__horizontal');
290
+ target.style['position'] = 'absolute';
291
+ target.style['margin-left'] = 0;
292
+ target.style['margin-top'] = 0;
293
+ target.style['top'] = calculateLargerScreenHalf(shareNavComponent) === 'ABOVE' ? '-120px' : '50px';
294
+ } else {
295
+ target.style['position'] = 'absolute';
296
+ target.style['margin-left'] = '45px';
297
+ target.style['top'] = '220px';
298
+ }
299
+ }
300
+
289
301
  function isMobile () {
290
302
  const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
291
303
 
@@ -293,6 +305,10 @@ function isMobile () {
293
305
  }
294
306
 
295
307
  function calculateLargerScreenHalf (target) {
308
+ if (!target) {
309
+ return 'BELOW';
310
+ }
311
+
296
312
  const vh = Math.min(document.documentElement.clientHeight || 0, window.innerHeight || 0);
297
313
 
298
314
  const targetBox = target.getBoundingClientRect();
@@ -357,13 +373,3 @@ function triggerCreateListEvent (contentId) {
357
373
  bubbles: true
358
374
  }));
359
375
  }
360
-
361
- function handleError (error) {
362
- document.body.dispatchEvent(new CustomEvent('oErrors.log', {
363
- bubbles: true,
364
- detail: {
365
- error,
366
- info: { component: 'professorLists' },
367
- }
368
- }));
369
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-myft-ui",
3
- "version": "28.0.7",
3
+ "version": "28.1.0",
4
4
  "description": "Client side component for interaction with myft",
5
5
  "main": "server.js",
6
6
  "scripts": {