define(["jquery", "underscore", "jquery.ajaxQueue"], function($, _) { var Utils = (function () { var Storage = {}; /** * @function * * Adds some data to the Storage object. If data with existent `data_id` * is added, nothing happens. * * @param {string} data_id Unique identifier for the data. * @param {any} data Data that should be stored. * * @returns {object} Object itself for chaining. */ Storage.set = function (data_id, data) { Storage[data_id] = data; return this; }; /** * @function * * Return data from the Storage object by identifier. * * @param {string} data_id Unique identifier of the data. * * @returns {any} Stored data. */ Storage.get= function (data_id) { return Storage[data_id]; }; /** * @function * * Deletes data from the Storage object by identifier. * * @param {string} data_id Unique identifier of the data. * * @returns {boolean} Boolean value that indicate if data is removed. */ Storage.remove = function (data_id) { return (delete Storage[data_id]); }; /** * @function * * Returns model from collection by 'field_name' property. * * @param {object} collection The model (CMS.Models.Metadata) containing * information about metadata setting editors. * @param {string} field_name Name of field that should be found. * * @returns { * object: when model exist, * undefined: when model doesn't exist. * } */ var _getField = function (collection, field_name) { var model; if (collection && field_name) { model = collection.findWhere({ field_name: field_name }); } return model; }; /** * @function * * Parses Youtube link and return video id. * * These are the types of URLs supported: * http://www.youtube.com/watch?v=OEoXaMPEzfM&feature=feedrec_grec_index * http://www.youtube.com/user/IngridMichaelsonVEVO#p/a/u/1/OEoXaMPEzfM * http://www.youtube.com/v/OEoXaMPEzfM?fs=1&hl=en_US&rel=0 * http://www.youtube.com/watch?v=OEoXaMPEzfM#t=0m10s * http://www.youtube.com/embed/OEoXaMPEzfM?rel=0 * http://www.youtube.com/watch?v=OEoXaMPEzfM * http://youtu.be/OEoXaMPEzfM * * @param {string} url Url that should be parsed. * * @returns { * string: Video Id, * undefined: when url has incorrect format or argument is * non-string, video id's length is not equal 11. * } */ var _youtubeParser = (function () { var cache = {}; return function (url) { if (typeof url !== 'string') { return void(0); } if (cache[url]) { return cache[url]; } var regExp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; var match = url.match(regExp); cache[url] = (match && match[1].length === 11) ? match[1] : void(0); return cache[url]; }; }()); /** * @function * * Parses links with html5 video sources in mp4 or webm formats. * * @param {string} url Url that should be parsed. * * @returns { * object: Object with information about the video * (file name, video type), * undefined: when url has incorrect format or argument is * non-string. * } */ var _videoLinkParser = (function () { var cache = {}; return function (url) { if (typeof url !== 'string') { return void(0); } if (cache[url]) { return cache[url]; } var link = document.createElement('a'), match; link.href = url; match = link.pathname .split('/') .pop() .match(/(.+)\.(mp4|webm)$/); if (match) { cache[url] = { video: match[1], type: match[2] }; } return cache[url]; }; }()); /** * @function * * Facade function that parses html5 and youtube links. * * @param {string} url Url that should be parsed. * * @returns { * object: Object with information about the video: * { * mode: "youtube|html5|incorrect", * video: "file_name|youtube_id", * type: "youtube|mp4|webm" * }, * undefined: when argument is non-string. * } */ var _linkParser = function (url) { var result; if (typeof url !== 'string') { return void(0); } if (_youtubeParser(url)) { result = { mode: 'youtube', video: _youtubeParser(url), type: 'youtube' }; } else if (_videoLinkParser(url)) { result = $.extend({mode: 'html5'}, _videoLinkParser(url)); } else { result = { mode: 'incorrect' }; } return result; }; /** * @function * * Returns short-hand youtube url. * * @param {string} video_id Youtube Video Id that will be added to the link. * * @returns {string} Short-hand Youtube url. * * @example * _getYoutubeLink('OEoXaMPEzfM'); => 'http://youtu.be/OEoXaMPEzfM' */ var _getYoutubeLink = function (video_id) { return 'http://youtu.be/' + video_id; }; /** * @function * * Returns list of objects with information about the passed links. * * @param {array} links List of links that will be processed. * * @returns {array} List of objects. * * @examples * var links = [ * 'http://youtu.be/OEoXaMPEzfM', * 'video_name.mp4', * 'video_name.webm' * ] * * _getVideoList(links); // => * [ * {mode: `youtube`, type: `youtube`, ...}, * {mode: `html5`, type: `mp4`, ...}, * {mode: `html5`, type: `webm`, ...} * ] * */ var _getVideoList = function (links) { if ($.isArray(links)) { var arr = [], data; for (var i = 0, len = links.length; i < len; i += 1) { data = _linkParser(links[i]); if (data.mode !== 'incorrect') { arr.push(data); } } return arr; } }; /** * @function * * Synchronizes 2 Backbone collections by 'field_name' property. * * @param {object} fromCollection Collection with which synchronization * will happens. * @param {object} toCollection Collection which will synchronized. * */ var _syncCollections = function (fromCollection, toCollection) { fromCollection.each(function (m) { var model = toCollection.findWhere({ field_name: m.getFieldName() }); if (model) { model.setValue(m.getDisplayValue()); } }); }; /** * @function * * Sends Ajax requests in appropriate format. * * @param {string} action Action that will be invoked on server. Is a part * of url. * @param {string} component_locator the locator of component. * @param {array} videoList List of object with information about inserted * urls. * @param {object} extraParams Extra parameters that can be send to the * server * * @returns {object} XMLHttpRequest object. Using this object, we can attach * callbacks to AJAX request events (for example on 'done', 'fail', * etc.). */ var _command = (function () { // We will store the XMLHttpRequest object that $.ajax() function // returns, to abort an ongoing AJAX request (if necessary) upon // subsequent invocations of _command() function. // // A new AJAX request will be made on each invocation of the // _command() function. var xhr = null; return function (action, component_locator, videoList, extraParams) { var params, data; if (extraParams) { if ($.isPlainObject(extraParams)) { params = extraParams; } else { params = {params: extraParams}; } } data = $.extend( { locator: component_locator }, { videos: videoList }, params ); xhr = $.ajaxQueue({ url: '/transcripts/' + action, data: { data: JSON.stringify(data) }, notifyOnError: false, type: 'get' }); return xhr; }; }()); return { getField: _getField, parseYoutubeLink: _youtubeParser, parseHTML5Link: _videoLinkParser, parseLink: _linkParser, getYoutubeLink: _getYoutubeLink, syncCollections: _syncCollections, command: _command, getVideoList: _getVideoList, Storage: { set: Storage.set, get: Storage.get, remove: Storage.remove } }; }()); return Utils; });