Skip to content

Commit 329f032

Browse files
committed
Merge pull request #385 from dpalou/MOBILE-1224-new
MOBILE-1224 media: Fix media URLs in format-text and external-content
2 parents 917f372 + 822b670 commit 329f032

File tree

2 files changed

+118
-41
lines changed

2 files changed

+118
-41
lines changed

www/core/directives/external_content.js

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,34 +31,71 @@ angular.module('mm.core')
3131
* Attributes accepted:
3232
* - siteid: Reference to the site ID if different than the site the user is connected to.
3333
*/
34-
.directive('mmExternalContent', function($log, $mmFilepool, $mmSite, $mmSitesManager, $mmUtil) {
34+
.directive('mmExternalContent', function($log, $mmFilepool, $mmSite, $mmSitesManager, $mmUtil, $q) {
3535
$log = $log.getInstance('mmExternalContent');
3636

37+
/**
38+
* Add a new source with a certain URL.
39+
*
40+
* @param {Object} dom Current source element. The new source will be a sibling of this element.
41+
* @param {String} url URL to use in the source.
42+
*/
43+
function addSource(dom, url) {
44+
if (dom.tagName !== 'SOURCE') {
45+
return;
46+
}
47+
48+
var e = document.createElement('source');
49+
e.setAttribute('src', url);
50+
e.setAttribute('type', dom.getAttribute('type'));
51+
dom.parentNode.insertBefore(e, dom);
52+
}
53+
54+
/**
55+
* Handle external content, setting the right URL.
56+
*
57+
* @param {String} siteId Site ID.
58+
* @param {Object} dom DOM element.
59+
* @param {String} targetAttr Attribute to modify.
60+
* @param {String} url Original URL to treat.
61+
* @param {String} [component] Component
62+
* @param {Number} [componentId] Component ID.
63+
* @return {Promise} Promise resolved if the element is successfully treated.
64+
*/
3765
function handleExternalContent(siteId, dom, targetAttr, url, component, componentId) {
3866

3967
if (!url || !$mmUtil.isDownloadableUrl(url)) {
4068
$log.debug('Ignoring non-downloadable URL: ' + url);
41-
return;
69+
if (dom.tagName === 'SOURCE') {
70+
// Restoring original src.
71+
addSource(dom, url);
72+
}
73+
return $q.reject();
4274
}
4375

4476
// Get the webservice pluginfile URL, we ignore failures here.
45-
$mmSitesManager.getSite(siteId).then(function(site) {
77+
return $mmSitesManager.getSite(siteId).then(function(site) {
4678
if (!site.canDownloadFiles() && $mmUtil.isPluginFileUrl(url)) {
4779
dom.remove(); // Remove element since it'll be broken.
48-
return;
80+
return $q.reject();
4981
}
5082

5183
var fn;
5284

53-
if (targetAttr === 'src') {
85+
if (targetAttr === 'src' && dom.tagName !== 'SOURCE') {
5486
fn = $mmFilepool.getSrcByUrl;
5587
} else {
5688
fn = $mmFilepool.getUrlByUrl;
5789
}
5890

59-
fn(siteId, url, component, componentId).then(function(finalUrl) {
91+
return fn(siteId, url, component, componentId).then(function(finalUrl) {
6092
$log.debug('Using URL ' + finalUrl + ' for ' + url);
61-
dom.setAttribute(targetAttr, finalUrl);
93+
if (dom.tagName === 'SOURCE') {
94+
// The browser does not catch changes in SRC, we need to add a new source.
95+
addSource(dom, finalUrl);
96+
} else {
97+
dom.setAttribute(targetAttr, finalUrl);
98+
}
6299
});
63100
});
64101
}
@@ -70,20 +107,30 @@ angular.module('mm.core')
70107
},
71108
link: function(scope, element, attrs) {
72109
var dom = element[0],
110+
siteid = scope.siteid || $mmSite.getId(),
73111
component = attrs.component,
74112
componentId = attrs.componentId,
75113
targetAttr,
76-
observe = false,
77-
url;
114+
sourceAttr,
115+
observe = false;
78116

79117
if (dom.tagName === 'A') {
80118
targetAttr = 'href';
119+
sourceAttr = 'href';
81120
if (attrs.hasOwnProperty('ngHref')) {
82121
observe = true;
83122
}
84123

85124
} else if (dom.tagName === 'IMG') {
86125
targetAttr = 'src';
126+
sourceAttr = 'src';
127+
if (attrs.hasOwnProperty('ngSrc')) {
128+
observe = true;
129+
}
130+
131+
} else if (dom.tagName === 'AUDIO' || dom.tagName === 'VIDEO' || dom.tagName === 'SOURCE') {
132+
targetAttr = 'src';
133+
sourceAttr = 'targetSrc';
87134
if (attrs.hasOwnProperty('ngSrc')) {
88135
observe = true;
89136
}
@@ -99,10 +146,10 @@ angular.module('mm.core')
99146
if (!url) {
100147
return;
101148
}
102-
handleExternalContent(scope.siteid || $mmSite.getId(), dom, targetAttr, url, component, componentId);
149+
handleExternalContent(siteid, dom, targetAttr, url, component, componentId);
103150
});
104151
} else {
105-
handleExternalContent(scope.siteid || $mmSite.getId(), dom, targetAttr, attrs[targetAttr], component, componentId);
152+
handleExternalContent(siteid, dom, targetAttr, attrs[sourceAttr] || attrs[targetAttr], component, componentId);
106153
}
107154

108155
}

www/core/directives/formattext.js

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@ angular.module('mm.core')
4242
var extractVariableRegex = new RegExp('{{([^|]+)(|.*)?}}', 'i'),
4343
tagsToIgnore = ['AUDIO', 'VIDEO', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'A'];
4444

45+
/**
46+
* Add mm-external-content and its extra attributes to a certain element.
47+
*
48+
* @param {Object} el DOM element to add the attributes to.
49+
* @param {String} [component] Component.
50+
* @param {Number} [componentId] Component ID.
51+
* @param {String} [siteId] Site ID.
52+
*/
53+
function addExternalContent(el, component, componentId, siteId) {
54+
el.setAttribute('mm-external-content', '');
55+
if (component) {
56+
el.setAttribute('component', component);
57+
if (componentId) {
58+
el.setAttribute('component-id', componentId);
59+
}
60+
}
61+
if (siteId) {
62+
el.setAttribute('siteid', siteId);
63+
}
64+
}
65+
4566
/**
4667
* Returns the number of characters to shorten the text. If the text shouldn't be shortened, returns undefined.
4768
*
@@ -80,6 +101,15 @@ angular.module('mm.core')
80101
}
81102
}
82103

104+
/**
105+
* Add class to adapt media to a certain element.
106+
*
107+
* @param {Object} el Dom element to add the class to.
108+
*/
109+
function addMediaAdaptClass(el) {
110+
angular.element(el).addClass('mm-media-adapt-width');
111+
}
112+
83113
/**
84114
* Format contents and render.
85115
*
@@ -175,44 +205,21 @@ angular.module('mm.core')
175205
return $mmText.formatText(text, attrs.clean, attrs.singleline, shorten).then(function(formatted) {
176206

177207
var el = element[0],
178-
elWidth = el.offsetWidth || el.width || el.clientWidth;
179-
180-
function addMediaAdaptClass(el) {
181-
angular.element(el).addClass('mm-media-adapt-width');
182-
}
183-
184-
// Convert the content into DOM.
185-
var dom = angular.element('<div>').html(formatted);
208+
elWidth = el.offsetWidth || el.width || el.clientWidth,
209+
dom = angular.element('<div>').html(formatted); // Convert the content into DOM.
186210

187211
// Walk through the content to find the links and add our directive to it.
188212
// Important: We need to look for links first because in 'img' we add new links without mm-browser.
189213
angular.forEach(dom.find('a'), function(anchor) {
190-
anchor.setAttribute('mm-external-content', '');
191214
anchor.setAttribute('mm-browser', '');
192-
if (component) {
193-
anchor.setAttribute('component', component);
194-
if (componentId) {
195-
anchor.setAttribute('component-id', componentId);
196-
}
197-
}
198-
if (siteId) {
199-
anchor.setAttribute('siteid', siteId);
200-
}
215+
addExternalContent(anchor, component, componentId, siteId);
201216
});
202217

203218
// Walk through the content to find images, and add our directive.
204219
angular.forEach(dom.find('img'), function(img) {
205220
addMediaAdaptClass(img);
206-
img.setAttribute('mm-external-content', '');
207-
if (component) {
208-
img.setAttribute('component', component);
209-
if (componentId) {
210-
img.setAttribute('component-id', componentId);
211-
}
212-
}
213-
if (siteId) {
214-
img.setAttribute('siteid', siteId);
215-
}
221+
addExternalContent(img, component, componentId, siteId);
222+
216223
// Check if image width has been adapted. If so, add an icon to view the image at full size.
217224
var imgWidth = img.offsetWidth || img.width || img.clientWidth;
218225
if (imgWidth > elWidth) {
@@ -228,8 +235,12 @@ angular.module('mm.core')
228235
}
229236
});
230237

231-
angular.forEach(dom.find('audio'), addMediaAdaptClass);
232-
angular.forEach(dom.find('video'), addMediaAdaptClass);
238+
angular.forEach(dom.find('audio'), function(el) {
239+
treatMedia(el, component, componentId, siteId);
240+
});
241+
angular.forEach(dom.find('video'), function(el) {
242+
treatMedia(el, component, componentId, siteId);
243+
});
233244
angular.forEach(dom.find('iframe'), addMediaAdaptClass);
234245

235246
return dom.html();
@@ -255,6 +266,25 @@ angular.module('mm.core')
255266
}
256267
}
257268

269+
/**
270+
* Add media adapt class and mm-external-content to the media element and their child sources.
271+
*
272+
* @param {Object} el DOM element.
273+
* @param {String} [component] Component.
274+
* @param {Number} [componentId] Component ID.
275+
* @param {String} [siteId] Site ID.
276+
*/
277+
function treatMedia(el, component, componentId, siteId) {
278+
addMediaAdaptClass(el);
279+
280+
addExternalContent(el, component, componentId, siteId);
281+
angular.forEach(angular.element(el).find('source'), function(source) {
282+
source.setAttribute('target-src', source.getAttribute('src'));
283+
source.removeAttribute('src');
284+
addExternalContent(source, component, componentId, siteId);
285+
});
286+
}
287+
258288
return {
259289
restrict: 'E',
260290
scope: true,

0 commit comments

Comments
 (0)