Skip to content

Commit

Permalink
Broke out URL functions into url.js
Browse files Browse the repository at this point in the history
  • Loading branch information
heff committed May 12, 2015
1 parent e0b08db commit bed8670
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 166 deletions.
93 changes: 1 addition & 92 deletions src/js/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,75 +332,6 @@ var setLocalStorage = function(key, value){
}
};

/**
* Get absolute version of relative URL. Used to tell flash correct URL.
* http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
* @param {String} url URL to make absolute
* @return {String} Absolute URL
* @private
*/
var getAbsoluteURL = function(url){
// Check if absolute URL
if (!url.match(/^https?:\/\//)) {
// Convert to absolute URL. Flash hosted off-site needs an absolute URL.
let div = document.createElement('div');
div.innerHTML = `<a href="${url}">x</a>`;
url = div.firstChild.href;
}

return url;
};

/**
* Resolve and parse the elements of a URL
* @param {String} url The url to parse
* @return {Object} An object of url details
*/
var parseUrl = function(url) {
const props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];

// add the url to an anchor and let the browser parse the URL
let a = document.createElement('a');
a.href = url;

// IE8 (and 9?) Fix
// ie8 doesn't parse the URL correctly until the anchor is actually
// added to the body, and an innerHTML is needed to trigger the parsing
let addToBody = (a.host === '' && a.protocol !== 'file:');
let div;
if (addToBody) {
div = document.createElement('div');
div.innerHTML = `<a href="${url}"></a>`;
a = div.firstChild;
// prevent the div from affecting layout
div.setAttribute('style', 'display:none; position:absolute;');
document.body.appendChild(div);
}

// Copy the specific URL properties to a new object
// This is also needed for IE8 because the anchor loses its
// properties when it's removed from the dom
let details = {};
for (var i = 0; i < props.length; i++) {
details[props[i]] = a[props[i]];
}

// IE9 adds the port to the host property unlike everyone else. If
// a port identifier is added for standard ports, strip it.
if (details.protocol === 'http:') {
details.host = details.host.replace(/:80$/, '');
}
if (details.protocol === 'https:') {
details.host = details.host.replace(/:443$/, '');
}

if (addToBody) {
document.body.removeChild(div);
}

return details;
};

/**
* Log messages to the console and history based on the type of message
*
Expand Down Expand Up @@ -534,25 +465,6 @@ arr.forEach = function(array, callback, thisArg) {
return array;
};

/**
* Returns the extension of the passed file name. It will return an empty string if you pass an invalid path
*
* @param {String} path The fileName path like '/path/to/file.mp4'
* @returns {String} The extension in lower case or an empty string if no extension could be found.
*/
var getFileExtension = function(path) {
if(typeof path === 'string'){
let splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
let pathParts = splitPathRe.exec(path);

if (pathParts) {
return pathParts.pop().toLowerCase();
}
}

return '';
};

export {
capitalize,
obj,
Expand All @@ -579,10 +491,7 @@ export {
round,
createTimeRange,
setLocalStorage,
getAbsoluteURL,
parseUrl,
log,
findPosition,
arr,
getFileExtension
arr
};
5 changes: 3 additions & 2 deletions src/js/tech/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import Tech from './tech';
import * as Lib from '../lib';
import * as Dom from '../utils/dom.js';
import * as Url from '../utils/url.js';
import FlashRtmpDecorator from './flash-rtmp';
import Component from '../component';
import window from 'global/window';
Expand Down Expand Up @@ -105,7 +106,7 @@ class Flash extends Tech {

setSrc(src) {
// Make sure source URL is absolute.
src = Lib.getAbsoluteURL(src);
src = Url.getAbsoluteURL(src);
this.el_.vjs_src(src);

// Currently the SWF doesn't autoplay if you load a source later.
Expand Down Expand Up @@ -216,7 +217,7 @@ Flash.nativeSourceHandler.canHandleSource = function(source){
var type;

function guessMimeType(src) {
var ext = Lib.getFileExtension(src);
var ext = Url.getFileExtension(src);
if (ext) {
return `video/${ext}`;
}
Expand Down
3 changes: 2 additions & 1 deletion src/js/tech/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Tech from './tech.js';
import Component from '../component';
import * as Lib from '../lib';
import * as Dom from '../utils/dom.js';
import * as Url from '../utils/url.js';
import * as Fn from '../utils/fn.js';
import * as VjsUtil from '../util';
import document from 'global/document';
Expand Down Expand Up @@ -411,7 +412,7 @@ Html5.nativeSourceHandler.canHandleSource = function(source){
return canPlayType(source.type);
} else if (source.src) {
// If no type, fall back to checking 'video/[EXTENSION]'
ext = Lib.getFileExtension(source.src);
ext = Url.getFileExtension(source.src);

return canPlayType(`video/${ext}`);
}
Expand Down
91 changes: 91 additions & 0 deletions src/js/utils/url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import document from 'global/document';

/**
* Resolve and parse the elements of a URL
* @param {String} url The url to parse
* @return {Object} An object of url details
*/
var parseUrl = function(url) {
const props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];

// add the url to an anchor and let the browser parse the URL
let a = document.createElement('a');
a.href = url;

// IE8 (and 9?) Fix
// ie8 doesn't parse the URL correctly until the anchor is actually
// added to the body, and an innerHTML is needed to trigger the parsing
let addToBody = (a.host === '' && a.protocol !== 'file:');
let div;
if (addToBody) {
div = document.createElement('div');
div.innerHTML = `<a href="${url}"></a>`;
a = div.firstChild;
// prevent the div from affecting layout
div.setAttribute('style', 'display:none; position:absolute;');
document.body.appendChild(div);
}

// Copy the specific URL properties to a new object
// This is also needed for IE8 because the anchor loses its
// properties when it's removed from the dom
let details = {};
for (var i = 0; i < props.length; i++) {
details[props[i]] = a[props[i]];
}

// IE9 adds the port to the host property unlike everyone else. If
// a port identifier is added for standard ports, strip it.
if (details.protocol === 'http:') {
details.host = details.host.replace(/:80$/, '');
}
if (details.protocol === 'https:') {
details.host = details.host.replace(/:443$/, '');
}

if (addToBody) {
document.body.removeChild(div);
}

return details;
};

/**
* Get absolute version of relative URL. Used to tell flash correct URL.
* http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
* @param {String} url URL to make absolute
* @return {String} Absolute URL
* @private
*/
var getAbsoluteURL = function(url){
// Check if absolute URL
if (!url.match(/^https?:\/\//)) {
// Convert to absolute URL. Flash hosted off-site needs an absolute URL.
let div = document.createElement('div');
div.innerHTML = `<a href="${url}">x</a>`;
url = div.firstChild.href;
}

return url;
};

/**
* Returns the extension of the passed file name. It will return an empty string if you pass an invalid path
*
* @param {String} path The fileName path like '/path/to/file.mp4'
* @returns {String} The extension in lower case or an empty string if no extension could be found.
*/
var getFileExtension = function(path) {
if(typeof path === 'string'){
let splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
let pathParts = splitPathRe.exec(path);

if (pathParts) {
return pathParts.pop().toLowerCase();
}
}

return '';
};

export { parseUrl, getAbsoluteURL, getFileExtension };
4 changes: 2 additions & 2 deletions src/js/xhr.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as VjsUtils from './util';
import * as Lib from './lib';
import * as Url from './utils/url.js';
import window from 'global/window';

/**
Expand Down Expand Up @@ -66,7 +66,7 @@ var xhr = function(options, callback){
// Store a reference to the url on the request instance
request.uri = options.uri;

let urlInfo = Lib.parseUrl(options.uri);
let urlInfo = Url.parseUrl(options.uri);
let winLoc = window.location;

let successHandler = function(){
Expand Down
70 changes: 1 addition & 69 deletions test/unit/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ import * as Lib from '../../src/js/lib.js';
import window from 'global/window';
import document from 'global/document';

q.module('Lib', {
'setup': function() {
// Allow for stubbing createElement, should replace with sinon now
this.createElement = document.createElement;
},
'teardown': function() {
document.createElement = this.createElement;
}
});
q.module('Lib');

test('should make a string start with an uppercase letter', function(){
var foo = Lib.capitalize('bar');
Expand Down Expand Up @@ -108,44 +100,6 @@ test('should create a fake timerange', function(){
ok(tr.end() === 10);
});

test('should get an absolute URL', function(){
// Errors on compiled tests that don't use unit.html. Need a better solution.
// ok(Lib.getAbsoluteURL('unit.html') === window.location.href);
ok(Lib.getAbsoluteURL('http://asdf.com') === 'http://asdf.com');
ok(Lib.getAbsoluteURL('https://asdf.com/index.html') === 'https://asdf.com/index.html');
});

test('should parse the details of a url correctly', function(){
equal(Lib.parseUrl('#').protocol, window.location.protocol, 'parsed relative url protocol');
equal(Lib.parseUrl('#').host, window.location.host, 'parsed relative url host');

equal(Lib.parseUrl('http://example.com').protocol, 'http:', 'parsed example url protocol');
equal(Lib.parseUrl('http://example.com').hostname, 'example.com', 'parsed example url hostname');

equal(Lib.parseUrl('http://example.com:1234').port, '1234', 'parsed example url port');
});

test('should strip port from hosts using http or https', function() {
var url;

// attempts to create elements will return an anchor tag that
// misbehaves like IE9
document.createElement = function() {
return {
hostname: 'example.com',
host: 'example.com:80',
protocol: 'http:',
port: '80',
pathname: '/domain/relative/url',
hash: ''
};
};

url = Lib.parseUrl('/domain/relative/url');
ok(!(/.*:80$/).test(url.host), ':80 is not appended to the host');
});


test('Lib.findPosition should find top and left position', function() {
var d = document.createElement('div'),
position = Lib.findPosition(d);
Expand Down Expand Up @@ -236,25 +190,3 @@ test('should loop through each element of an array', function() {

ok(sum, 6);
});

//getFileExtension tests
test('should get the file extension of the passed path', function() {
equal(Lib.getFileExtension('/foo/bar/test.video.wgg'), 'wgg');
equal(Lib.getFileExtension('test./video.mp4'), 'mp4');
equal(Lib.getFileExtension('.bar/test.video.m4v'), 'm4v');
equal(Lib.getFileExtension('foo/.bar/test.video.flv'), 'flv');
equal(Lib.getFileExtension('foo/.bar/test.video.flv?foo=bar'), 'flv');
equal(Lib.getFileExtension('http://www.test.com/video.mp4'), 'mp4');
equal(Lib.getFileExtension('http://foo/bar/test.video.wgg'), 'wgg');

//edge cases
equal(Lib.getFileExtension('http://...'), '');
equal(Lib.getFileExtension('foo/.bar/testvideo'), '');
equal(Lib.getFileExtension(''), '');
equal(Lib.getFileExtension(null), '');
equal(Lib.getFileExtension(undefined), '');

//with capital letters
equal(Lib.getFileExtension('test.video.MP4'), 'mp4');
equal(Lib.getFileExtension('test.video.FLV'), 'flv');
});
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit bed8670

Please sign in to comment.