720 lines
19 KiB
JavaScript
720 lines
19 KiB
JavaScript
//
|
||
// mep-feature-tracks.js with instructure customizations
|
||
//
|
||
// to see the diff, run:
|
||
//
|
||
// upstream_url='https://raw.githubusercontent.com/johndyer/mediaelement/743f4465231dc20e6f9e96a5cb8b9d5299ceddd3/src/js/mep-feature-tracks.js'
|
||
// diff -bu \
|
||
// <(curl -s "${upstream_url}") \
|
||
// public/javascripts/mediaelement/mep-feature-tracks-instructure.js
|
||
//
|
||
(function($) {
|
||
|
||
// add extra default options
|
||
$.extend(mejs.MepDefaults, {
|
||
// this will automatically turn on a <track>
|
||
startLanguage: '',
|
||
|
||
tracksText: mejs.i18n.t('Captions/Subtitles'),
|
||
|
||
// option to remove the [cc] button when no <track kind="subtitles"> are present
|
||
hideCaptionsButtonWhenEmpty: true,
|
||
|
||
// If true and we only have one track, change captions to popup
|
||
toggleCaptionsButtonWhenOnlyOne: false,
|
||
|
||
// #id or .class
|
||
slidesSelector: ''
|
||
});
|
||
|
||
$.extend(MediaElementPlayer.prototype, {
|
||
|
||
hasChapters: false,
|
||
|
||
buildtracks: function(player, controls, layers, media) {
|
||
// INSTRUCTURE added code (the '&& !player.options.can_add_captions' part)
|
||
if (player.tracks.length == 0 && !player.options.can_add_captions)
|
||
return;
|
||
|
||
var t = this,
|
||
i,
|
||
options = '';
|
||
|
||
if (t.domNode.textTracks) { // if browser will do native captions, prefer mejs captions, loop through tracks and hide
|
||
for (var i = t.domNode.textTracks.length - 1; i >= 0; i--) {
|
||
t.domNode.textTracks[i].mode = "hidden";
|
||
}
|
||
}
|
||
player.chapters =
|
||
$('<div class="mejs-chapters mejs-layer"></div>')
|
||
.prependTo(layers).hide();
|
||
player.captions =
|
||
$('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>')
|
||
.prependTo(layers).hide();
|
||
player.captionsText = player.captions.find('.mejs-captions-text');
|
||
player.captionsButton =
|
||
$('<div class="mejs-button mejs-captions-button">'+
|
||
'<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '" aria-label="' + t.options.tracksText + '"></button>'+
|
||
'<div class="mejs-captions-selector">'+
|
||
'<ul>'+
|
||
'<li>'+
|
||
'<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' +
|
||
'<label for="' + player.id + '_captions_none">' + mejs.i18n.t('None') +'</label>'+
|
||
'</li>' +
|
||
'</ul>'+
|
||
'</div>'+
|
||
'</div>')
|
||
.appendTo(controls);
|
||
|
||
|
||
var subtitleCount = 0;
|
||
for (i=0; i<player.tracks.length; i++) {
|
||
if (player.tracks[i].kind == 'subtitles') {
|
||
subtitleCount++;
|
||
}
|
||
}
|
||
|
||
// if only one language then just make the button a toggle
|
||
if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitleCount == 1){
|
||
// click
|
||
player.captionsButton.on('click',function() {
|
||
if (player.selectedTrack == null) {
|
||
var lang = player.tracks[0].srclang;
|
||
} else {
|
||
var lang = 'none';
|
||
}
|
||
player.setTrack(lang);
|
||
});
|
||
} else {
|
||
// hover
|
||
player.captionsButton.hover(function() {
|
||
$(this).find('.mejs-captions-selector').css('visibility','visible');
|
||
}, function() {
|
||
$(this).find('.mejs-captions-selector').css('visibility','hidden');
|
||
})
|
||
|
||
// handle clicks to the language radio buttons
|
||
.on('click','input[type=radio]',function() {
|
||
lang = this.value;
|
||
player.setTrack(lang);
|
||
});
|
||
|
||
}
|
||
|
||
if (!player.options.alwaysShowControls) {
|
||
// move with controls
|
||
player.container
|
||
.bind('controlsshown', function () {
|
||
// push captions above controls
|
||
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
||
|
||
})
|
||
.bind('controlshidden', function () {
|
||
if (!media.paused) {
|
||
// move back to normal place
|
||
player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover');
|
||
}
|
||
});
|
||
} else {
|
||
player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover');
|
||
}
|
||
|
||
player.trackToLoad = -1;
|
||
player.selectedTrack = null;
|
||
player.isLoadingTrack = false;
|
||
|
||
|
||
|
||
// add to list
|
||
for (i=0; i<player.tracks.length; i++) {
|
||
if (player.tracks[i].kind == 'subtitles') {
|
||
// INSTRUCTURE added third src argument
|
||
player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label, player.tracks[i].src);
|
||
}
|
||
}
|
||
|
||
// INSTRUCTURE added code
|
||
if (player.options.can_add_captions) player.addUploadTrackButton();
|
||
|
||
// start loading tracks
|
||
player.loadNextTrack();
|
||
|
||
|
||
media.addEventListener('timeupdate',function(e) {
|
||
player.displayCaptions();
|
||
}, false);
|
||
|
||
if (player.options.slidesSelector != '') {
|
||
player.slidesContainer = $(player.options.slidesSelector);
|
||
|
||
media.addEventListener('timeupdate',function(e) {
|
||
player.displaySlides();
|
||
}, false);
|
||
|
||
}
|
||
|
||
media.addEventListener('loadedmetadata', function(e) {
|
||
player.displayChapters();
|
||
}, false);
|
||
|
||
player.container.hover(
|
||
function () {
|
||
// chapters
|
||
if (player.hasChapters) {
|
||
player.chapters.css('visibility','visible');
|
||
player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight());
|
||
}
|
||
},
|
||
function () {
|
||
if (player.hasChapters && !media.paused) {
|
||
player.chapters.fadeOut(200, function() {
|
||
$(this).css('visibility','hidden');
|
||
$(this).css('display','block');
|
||
});
|
||
}
|
||
});
|
||
|
||
// check for autoplay
|
||
if (player.node.getAttribute('autoplay') !== null) {
|
||
player.chapters.css('visibility','hidden');
|
||
}
|
||
},
|
||
|
||
setTrack: function(lang){
|
||
|
||
var t = this,
|
||
i;
|
||
|
||
if (lang == 'none') {
|
||
t.selectedTrack = null;
|
||
t.captionsButton.removeClass('mejs-captions-enabled');
|
||
} else {
|
||
for (i=0; i<t.tracks.length; i++) {
|
||
if (t.tracks[i].srclang == lang) {
|
||
if (t.selectedTrack == null)
|
||
t.captionsButton.addClass('mejs-captions-enabled');
|
||
t.selectedTrack = t.tracks[i];
|
||
t.captions.attr('lang', t.selectedTrack.srclang);
|
||
t.displayCaptions();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
loadNextTrack: function() {
|
||
var t = this;
|
||
|
||
t.trackToLoad++;
|
||
if (t.trackToLoad < t.tracks.length) {
|
||
t.isLoadingTrack = true;
|
||
t.loadTrack(t.trackToLoad);
|
||
} else {
|
||
// add done?
|
||
t.isLoadingTrack = false;
|
||
|
||
t.checkForTracks();
|
||
}
|
||
},
|
||
|
||
loadTrack: function(index){
|
||
var
|
||
t = this,
|
||
track = t.tracks[index],
|
||
after = function() {
|
||
|
||
track.isLoaded = true;
|
||
|
||
// create button
|
||
//t.addTrackButton(track.srclang);
|
||
t.enableTrackButton(track.srclang, track.label);
|
||
|
||
t.loadNextTrack();
|
||
|
||
};
|
||
|
||
|
||
$.ajax({
|
||
url: track.src,
|
||
dataType: "text",
|
||
success: function(d) {
|
||
|
||
// parse the loaded file
|
||
if (typeof d == "string" && (/<tt\s+xml/ig).exec(d)) {
|
||
track.entries = mejs.TrackFormatParser.dfxp.parse(d);
|
||
} else {
|
||
track.entries = mejs.TrackFormatParser.webvvt.parse(d);
|
||
}
|
||
|
||
after();
|
||
|
||
if (track.kind == 'chapters') {
|
||
t.media.addEventListener('play', function(e) {
|
||
if (t.media.duration > 0) {
|
||
t.displayChapters(track);
|
||
}
|
||
}, false);
|
||
}
|
||
|
||
if (track.kind == 'slides') {
|
||
t.setupSlides(track);
|
||
}
|
||
},
|
||
error: function() {
|
||
t.loadNextTrack();
|
||
}
|
||
});
|
||
},
|
||
|
||
enableTrackButton: function(lang, label) {
|
||
var t = this;
|
||
|
||
if (label === '') {
|
||
label = mejs.language.codes[lang] || lang;
|
||
}
|
||
|
||
t.captionsButton
|
||
.find('input[value=' + lang + ']')
|
||
.prop('disabled',false)
|
||
.siblings('label')
|
||
.html( label );
|
||
|
||
// auto select
|
||
if (t.options.startLanguage == lang) {
|
||
$('#' + t.id + '_captions_' + lang).click();
|
||
}
|
||
|
||
t.adjustLanguageBox();
|
||
},
|
||
|
||
// INSTRUCTURE added code
|
||
addUploadTrackButton: function() {
|
||
var t = this;
|
||
|
||
$('<a href="#" style="color:white">Upload subtitles</a>')
|
||
.appendTo(t.captionsButton.find('ul'))
|
||
.wrap('<li>')
|
||
.click(function(e){
|
||
e.preventDefault();
|
||
require(['compiled/widget/UploadMediaTrackForm'], function(UploadMediaTrackForm){
|
||
new UploadMediaTrackForm(t.options.mediaCommentId, t.media.src);
|
||
});
|
||
});
|
||
t.adjustLanguageBox();
|
||
},
|
||
|
||
// INSTRUCTURE added src argument
|
||
addTrackButton: function(lang, label, src) {
|
||
var t = this;
|
||
if (label === '') {
|
||
label = mejs.language.codes[lang] || lang;
|
||
}
|
||
|
||
// INSTRUCTURE added code
|
||
var deleteButtonHtml = '';
|
||
if (t.options.can_add_captions) {
|
||
deleteButtonHtml = '<a href="#" data-remove="li" data-confirm="Are you sure you want to delete this track?" data-url="' + src + '">×</a>';
|
||
}
|
||
|
||
t.captionsButton.find('ul').append(
|
||
$('<li>'+
|
||
'<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' +
|
||
'<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+
|
||
// INSTRUCTURE added code
|
||
deleteButtonHtml +
|
||
'</li>')
|
||
);
|
||
|
||
t.adjustLanguageBox();
|
||
|
||
// remove this from the dropdownlist (if it exists)
|
||
t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove();
|
||
},
|
||
|
||
adjustLanguageBox:function() {
|
||
var t = this;
|
||
// adjust the size of the outer box
|
||
t.captionsButton.find('.mejs-captions-selector').height(
|
||
t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) +
|
||
t.captionsButton.find('.mejs-captions-translations').outerHeight(true)
|
||
);
|
||
},
|
||
|
||
checkForTracks: function() {
|
||
var
|
||
t = this,
|
||
hasSubtitles = false;
|
||
|
||
// check if any subtitles
|
||
if (t.options.hideCaptionsButtonWhenEmpty) {
|
||
for (i=0; i<t.tracks.length; i++) {
|
||
if (t.tracks[i].kind == 'subtitles') {
|
||
hasSubtitles = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// INSTRUCTURE added code (second half of conditional)
|
||
if (!hasSubtitles && !t.options.can_add_captions) {
|
||
t.captionsButton.hide();
|
||
t.setControlsSize();
|
||
}
|
||
}
|
||
},
|
||
|
||
displayCaptions: function() {
|
||
|
||
if (typeof this.tracks == 'undefined')
|
||
return;
|
||
|
||
var
|
||
t = this,
|
||
i,
|
||
track = t.selectedTrack;
|
||
|
||
if (track != null && track.isLoaded) {
|
||
for (i=0; i<track.entries.times.length; i++) {
|
||
if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){
|
||
t.captionsText.html(track.entries.text[i]);
|
||
t.captions.show().height(0);
|
||
return; // exit out if one is visible;
|
||
}
|
||
}
|
||
t.captions.hide();
|
||
} else {
|
||
t.captions.hide();
|
||
}
|
||
},
|
||
|
||
setupSlides: function(track) {
|
||
var t = this;
|
||
|
||
t.slides = track;
|
||
t.slides.entries.imgs = [t.slides.entries.text.length];
|
||
t.showSlide(0);
|
||
|
||
},
|
||
|
||
showSlide: function(index) {
|
||
if (typeof this.tracks == 'undefined' || typeof this.slidesContainer == 'undefined') {
|
||
return;
|
||
}
|
||
|
||
var t = this,
|
||
url = t.slides.entries.text[index],
|
||
img = t.slides.entries.imgs[index];
|
||
|
||
if (typeof img == 'undefined' || typeof img.fadeIn == 'undefined') {
|
||
|
||
t.slides.entries.imgs[index] = img = $('<img src="' + url + '">')
|
||
.on('load', function() {
|
||
img.appendTo(t.slidesContainer)
|
||
.hide()
|
||
.fadeIn()
|
||
.siblings(':visible')
|
||
.fadeOut();
|
||
|
||
});
|
||
|
||
} else {
|
||
|
||
if (!img.is(':visible') && !img.is(':animated')) {
|
||
|
||
//console.log('showing existing slide');
|
||
|
||
img.fadeIn()
|
||
.siblings(':visible')
|
||
.fadeOut();
|
||
}
|
||
}
|
||
|
||
},
|
||
|
||
displaySlides: function() {
|
||
|
||
if (typeof this.slides == 'undefined')
|
||
return;
|
||
|
||
var
|
||
t = this,
|
||
slides = t.slides,
|
||
i;
|
||
|
||
for (i=0; i<slides.entries.times.length; i++) {
|
||
if (t.media.currentTime >= slides.entries.times[i].start && t.media.currentTime <= slides.entries.times[i].stop){
|
||
|
||
t.showSlide(i);
|
||
|
||
return; // exit out if one is visible;
|
||
}
|
||
}
|
||
},
|
||
|
||
displayChapters: function() {
|
||
var
|
||
t = this,
|
||
i;
|
||
|
||
for (i=0; i<t.tracks.length; i++) {
|
||
if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) {
|
||
t.drawChapters(t.tracks[i]);
|
||
t.hasChapters = true;
|
||
break;
|
||
}
|
||
}
|
||
},
|
||
|
||
drawChapters: function(chapters) {
|
||
var
|
||
t = this,
|
||
i,
|
||
dur,
|
||
//width,
|
||
//left,
|
||
percent = 0,
|
||
usedPercent = 0;
|
||
|
||
t.chapters.empty();
|
||
|
||
for (i=0; i<chapters.entries.times.length; i++) {
|
||
dur = chapters.entries.times[i].stop - chapters.entries.times[i].start;
|
||
percent = Math.floor(dur / t.media.duration * 100);
|
||
if (percent + usedPercent > 100 || // too large
|
||
i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in
|
||
{
|
||
percent = 100 - usedPercent;
|
||
}
|
||
//width = Math.floor(t.width * dur / t.media.duration);
|
||
//left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration);
|
||
//if (left + width > t.width) {
|
||
// width = t.width - left;
|
||
//}
|
||
|
||
t.chapters.append( $(
|
||
'<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' +
|
||
'<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' +
|
||
'<span class="ch-title">' + chapters.entries.text[i] + '</span>' +
|
||
'<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '–' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' +
|
||
'</div>' +
|
||
'</div>'));
|
||
usedPercent += percent;
|
||
}
|
||
|
||
t.chapters.find('div.mejs-chapter').click(function() {
|
||
t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) );
|
||
if (t.media.paused) {
|
||
t.media.play();
|
||
}
|
||
});
|
||
|
||
t.chapters.show();
|
||
}
|
||
});
|
||
|
||
|
||
|
||
mejs.language = {
|
||
codes: {
|
||
af:'Afrikaans',
|
||
sq:'Albanian',
|
||
ar:'Arabic',
|
||
be:'Belarusian',
|
||
bg:'Bulgarian',
|
||
ca:'Catalan',
|
||
zh:'Chinese',
|
||
'zh-cn':'Chinese Simplified',
|
||
'zh-tw':'Chinese Traditional',
|
||
hr:'Croatian',
|
||
cs:'Czech',
|
||
da:'Danish',
|
||
nl:'Dutch',
|
||
en:'English',
|
||
et:'Estonian',
|
||
tl:'Filipino',
|
||
fi:'Finnish',
|
||
fr:'French',
|
||
gl:'Galician',
|
||
de:'German',
|
||
el:'Greek',
|
||
ht:'Haitian Creole',
|
||
iw:'Hebrew',
|
||
hi:'Hindi',
|
||
hu:'Hungarian',
|
||
is:'Icelandic',
|
||
id:'Indonesian',
|
||
ga:'Irish',
|
||
it:'Italian',
|
||
ja:'Japanese',
|
||
ko:'Korean',
|
||
lv:'Latvian',
|
||
lt:'Lithuanian',
|
||
mk:'Macedonian',
|
||
ms:'Malay',
|
||
mt:'Maltese',
|
||
no:'Norwegian',
|
||
fa:'Persian',
|
||
pl:'Polish',
|
||
pt:'Portuguese',
|
||
//'pt-pt':'Portuguese (Portugal)',
|
||
ro:'Romanian',
|
||
ru:'Russian',
|
||
sr:'Serbian',
|
||
sk:'Slovak',
|
||
sl:'Slovenian',
|
||
es:'Spanish',
|
||
sw:'Swahili',
|
||
sv:'Swedish',
|
||
tl:'Tagalog',
|
||
th:'Thai',
|
||
tr:'Turkish',
|
||
uk:'Ukrainian',
|
||
vi:'Vietnamese',
|
||
cy:'Welsh',
|
||
yi:'Yiddish'
|
||
}
|
||
};
|
||
|
||
/*
|
||
Parses WebVVT format which should be formatted as
|
||
================================
|
||
WEBVTT
|
||
|
||
1
|
||
00:00:01,1 --> 00:00:05,000
|
||
A line of text
|
||
|
||
2
|
||
00:01:15,1 --> 00:02:05,000
|
||
A second line of text
|
||
|
||
===============================
|
||
|
||
Adapted from: http://www.delphiki.com/html5/playr
|
||
*/
|
||
mejs.TrackFormatParser = {
|
||
webvvt: {
|
||
// match start "chapter-" (or anythingelse)
|
||
pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/,
|
||
pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/,
|
||
|
||
parse: function(trackText) {
|
||
var
|
||
i = 0,
|
||
lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/),
|
||
entries = {text:[], times:[]},
|
||
timecode,
|
||
text;
|
||
for(; i<lines.length; i++) {
|
||
// check for the line number
|
||
if (this.pattern_identifier.exec(lines[i])){
|
||
// skip to the next line where the start --> end time code should be
|
||
i++;
|
||
timecode = this.pattern_timecode.exec(lines[i]);
|
||
|
||
if (timecode && i<lines.length){
|
||
i++;
|
||
// grab all the (possibly multi-line) text that follows
|
||
text = lines[i];
|
||
i++;
|
||
while(lines[i] !== '' && i<lines.length){
|
||
text = text + '\n' + lines[i];
|
||
i++;
|
||
}
|
||
text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
|
||
// Text is in a different array so I can use .join
|
||
entries.text.push(text);
|
||
entries.times.push(
|
||
{
|
||
start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]),
|
||
stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]),
|
||
settings: timecode[5]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
return entries;
|
||
}
|
||
},
|
||
// Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420
|
||
dfxp: {
|
||
parse: function(trackText) {
|
||
trackText = $(trackText).filter("tt");
|
||
var
|
||
i = 0,
|
||
container = trackText.children("div").eq(0),
|
||
lines = container.find("p"),
|
||
styleNode = trackText.find("#" + container.attr("style")),
|
||
styles,
|
||
begin,
|
||
end,
|
||
text,
|
||
entries = {text:[], times:[]};
|
||
|
||
|
||
if (styleNode.length) {
|
||
var attributes = styleNode.removeAttr("id").get(0).attributes;
|
||
if (attributes.length) {
|
||
styles = {};
|
||
for (i = 0; i < attributes.length; i++) {
|
||
styles[attributes[i].name.split(":")[1]] = attributes[i].value;
|
||
}
|
||
}
|
||
}
|
||
|
||
for(i = 0; i<lines.length; i++) {
|
||
var style;
|
||
var _temp_times = {
|
||
start: null,
|
||
stop: null,
|
||
style: null
|
||
};
|
||
if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin"));
|
||
if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end"));
|
||
if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end"));
|
||
if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin"));
|
||
if (styles) {
|
||
style = "";
|
||
for (var _style in styles) {
|
||
style += _style + ":" + styles[_style] + ";";
|
||
}
|
||
}
|
||
if (style) _temp_times.style = style;
|
||
if (_temp_times.start == 0) _temp_times.start = 0.200;
|
||
entries.times.push(_temp_times);
|
||
text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>");
|
||
entries.text.push(text);
|
||
if (entries.times.start == 0) entries.times.start = 2;
|
||
}
|
||
return entries;
|
||
}
|
||
},
|
||
split2: function (text, regex) {
|
||
// normal version for compliant browsers
|
||
// see below for IE fix
|
||
return text.split(regex);
|
||
}
|
||
};
|
||
|
||
// test for browsers with bad String.split method.
|
||
if ('x\n\ny'.split(/\n/gi).length != 3) {
|
||
// add super slow IE8 and below version
|
||
mejs.TrackFormatParser.split2 = function(text, regex) {
|
||
var
|
||
parts = [],
|
||
chunk = '',
|
||
i;
|
||
|
||
for (i=0; i<text.length; i++) {
|
||
chunk += text.substring(i,i+1);
|
||
if (regex.test(chunk)) {
|
||
parts.push(chunk.replace(regex, ''));
|
||
chunk = '';
|
||
}
|
||
}
|
||
parts.push(chunk);
|
||
return parts;
|
||
}
|
||
}
|
||
|
||
})(mejs.$);
|