
var UTILS={urlRe:/(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/,isInt:function(n){return(typeof n==='number'&&isFinite(n)&&n%1===0);},none:function(obj){return obj===null||obj===undefined;},zip:function(arrays){if(!Array.prototype.map){Array.prototype.map=function(callback,thisArg){var T,A,k;for(var i in this){if(this[i]===null||this[i]===undefined){throw new TypeError(' this is null or not defined');}}
var O=Object(this);var len=O.length>>>0;if(typeof callback!=='function'){throw new TypeError(callback+' is not a function');}
if(thisArg){T=thisArg;}
A=new Array(len);k=0;while(k<len){var kValue,mappedValue;if(k in O){var Pk=k.toString();kValue=O[Pk];mappedValue=callback.call(T,kValue,k,O);A[Pk]=mappedValue;}
k++;}
return A;};}
return arrays[0].map(function(_,i){return arrays.map(function(array){return array[i];});});},listify:function(obj){if(UTILS.none(obj)){return[];}else if(!angular.isArray(obj)){return[obj];}
return obj;},objectToQueryString:function(a){var prefix,s,add,name,r20,output;s=[];r20=/%20/g;add=function(key,value){value=(typeof value=='function')?value():(value===null?'':value);s[s.length]=encodeURIComponent(key)+'='+encodeURIComponent(value);};if(a instanceof Array){for(name in a){add(name,a[name]);}}else{for(prefix in a){this.buildParams(prefix,a[prefix],add);}}
output=s.join('&').replace(r20,'+');return output;},buildParams:function(prefix,obj,add){var name,i,l,rbracket;rbracket=/\[\]$/;if(obj instanceof Array){for(i=0,l=obj.length;i<l;i++){if(rbracket.test(prefix)){add(prefix,obj[i]);}else{this.buildParams(prefix+'['+(typeof obj[i]==='object'?i:'')+']',obj[i],add);}}}else if(typeof obj=='object'){for(name in obj){this.buildParams(prefix+'['+name+']',obj[name],add);}}else{add(prefix,obj);}}};angular.module('ngEmbedApp',[]).factory('API',function($http,$q,$timeout){var responseCache={};return{log:function(level,message){if(!UTILS.none(window.console)&&!UTILS.none(window.console[level])){window.console[level].apply(window.console,[message]);}},build:function(method,urls,options){options=UTILS.none(options)?{}:options;var secure=options.secure;if(UTILS.none(secure)){secure=window.location.protocol==='https:'?true:false;}
var base=(secure?'https':'http')+'://'+'api.embed.ly'+'/'+(method==='objectify'?'2/':'1/')+method;var query=UTILS.none(options.query)?{}:options.query;query.key=options.key;base+='?'+UTILS.objectToQueryString(query);base+='&urls='+urls.map(encodeURIComponent).join(',');return base;},batch:function(list,split){var batches=[],current=[];angular.forEach(list,function(obj,i){current.push(obj);if(current.length===split){batches.push(current);current=[];}});if(current.length!==0){batches.push(current);}
return batches;},request:function(method,urls,options){options=angular.extend({},typeof options==='object'&&options);if(UTILS.none(options.key)){this.log('error','Embedly Angular requires an API Key. Please sign up for one at http://embed.ly');return null;}
urls=UTILS.listify(urls);var deferred=$q.defer();var valid_urls=[],rejects=[],valid;angular.forEach(urls,function(url,i){valid=false;if(UTILS.urlRe.test(url)){valid=true;if(!UTILS.none(options.urlRegExp)&&options.urlRegExp.test&&!options.urlRegExp.test(url)){valid=false;}}
if(valid===true){if(responseCache[url]){$timeout(function(){deferred.notify(responseCache[url]);});}else{valid_urls.push(url);}}else{rejects.push({url:url,original_url:url,error:true,invalid:true,type:'error',error_message:'Invalid URL "'+url+'"'});}});var batches=this.batch(valid_urls,options.batch),self=this;angular.forEach(batches,function(batch,i){$http({method:'GET',url:self.build(method,batch,options)}).success(function(data,status,headers,config){var zipped=UTILS.zip([batch,data]);angular.forEach(zipped,function(obj,i){var result=obj[1];result.original_url=obj[0];result.invalid=false;responseCache[result.original_url]=result;deferred.notify(result);});}).error(function(data,status,headers,config){deferred.resolve(data);});});if(rejects.length){angular.forEach(rejects,function(reject,i){deferred.notify(reject);});}
return deferred;},};}).factory('Embedly',function($q){var Embedly=function(element,url,options){this.init(element,url,options);};Embedly.prototype={init:function(elem,original_url,options){this.elem=elem;this.$elem=angular.element(elem);this.original_url=original_url;this.options=options;this.loaded=$q.defer();var self=this;this.loaded.promise.then(function(){self.$elem.triggerHandler('loaded',[self]);});this.$elem.triggerHandler('initialized',[this]);},progress:function(obj){angular.extend(this,obj);if(this.options.display){this.options.display.apply(this,[this,this.elem]);}
else if(this.options.endpoint==='oembed'){this.display();}
this.loaded.resolve(this);},imageStyle:function(){var style=[],units;if(this.options.addImageStyles){if(this.options.query.maxwidth){style.push('max-width: '+(this.options.query.maxwidth)+'px');}
if(this.options.query.maxheight){style.push('max-height: '+(this.options.query.maxheight)+'px');}}
return style.join(';');},display:function(){if(this.type==='error'){return false;}
this.title=this.title||this.url;this.style=this.imageStyle();var html;if(UTILS.none(this.url)&&!UTILS.none(this.thumbnail_url)){this.url=this.thumbnail_url;}
if(this.type==='photo'){html='<a href="'+this.original_url+'" target="_blank">';html+='<img style="'+this.style+'" src="'+this.url+'" alt="'+this.title+'" /></a>';}
else if(this.type==='video'||this.type==='rich'){html=this.html;}
else{html+=(!UTILS.none(this.thumbnail_url))?'<img src="'+this.thumbnail_url+'" class="thumb" style="'+this.style+'"/>':'';html+=(!UTILS.none(this.original_url))?'<a href="'+this.original_url+'">'+this.title+'</a>':'';html+=(!UTILS.none(this.provider_name))?'<a href="'+this.provider_url+'" class="provider">'+this.provider_name+'</a>':'';html+=(!UTILS.none(this.description))?'<div class="description">'+this.description+'</div>':'';}
html='<'+this.options.wrapElement+' class="'+this.options.className+'">'+html+'</'+this.options.wrapElement+'>';this.code=html;if(this.options.method==='after'){this.$elem.after(this.code);}else if(this.options.method==='afterParent'){this.$elem.parent().after(this.code);}else if(this.options.method==='replaceParent'){this.$elem.parent().replaceWith(this.code);}
else{this.$elem.replaceWith(this.code);}
this.$elem.triggerHandler('displayed',[this]);}};return{get:function(element,url,options){return new Embedly(element,url,options);}};}).controller('ngEmbedlyController',function($scope){var defaults={key:null,endpoint:'oembed',secure:null,query:{},method:'replace',addImageStyles:true,wrapElement:'div',className:'embed',batch:20,urlRegExp:null,display:null,};var options={};if(!UTILS.none($scope.key)){options.key=$scope.key;}
if(!UTILS.none($scope.endpoint)){options.endpoint=$scope.endpoint;}
if(!UTILS.none($scope.secure)){if(typeof $scope.secure==='boolean'){options.secure=$scope.secure;}}
if(!UTILS.none($scope.query)){if($scope.query.maxwidth&&!UTILS.isInt($scope.query.maxwidth)){delete $scope.query.maxwidth;}
if($scope.query.maxheight&&!UTILS.isInt($scope.query.maxheight)){delete $scope.query.maxheight;}
if($scope.query.width&&!UTILS.isInt($scope.query.width)){delete $scope.query.width;}
if($scope.query.autoplay&&typeof $scope.query.autoplay!=='boolean'){delete $scope.query.autoplay;}
options.query=$scope.query;}
if(!UTILS.none($scope.method)){options.method=$scope.method;}
if(!UTILS.none($scope.addImageStyles)){options.addImageStyles=$scope.addImageStyles;}
if(!UTILS.none($scope.wrapElement)){options.wrapElement=$scope.wrapElement;}
if(!UTILS.none($scope.className)){options.className=$scope.className;}
if(!UTILS.none($scope.batch)){if(UTILS.isInt($scope.batch)){options.batch=$scope.batch;}}
if(!UTILS.none($scope.urlRegExp)){options.urlRegExp=$scope.urlRegExp;}
if(!UTILS.none($scope.display)){if(typeof $scope.display==='function'){options.display=$scope.display;}}
$scope.options=angular.extend({},defaults,typeof options==='object'&&options);}).directive('ngEmbedly',function($timeout,API,Embedly){return{scope:{key:'=',endpoint:'=',secure:'=',query:'=',method:'=',addImageStyles:'=',wrapElement:'=',className:'=',batch:'=',urlRegExp:'=',display:'=',},controller:'ngEmbedlyController',link:function($scope,$element){var options=$scope.options;$timeout(function(){var nodes={};var create=function(elem){if(!angular.element(elem).data('embedly')){var url=angular.element(elem).attr('href');var node=Embedly.get(elem,url,options);angular.element(elem).data('embedly',node);if(nodes.hasOwnProperty(url)){nodes[url].push(node);}else{nodes[url]=[node];}}};var elems=angular.forEach($element,function(){if(!UTILS.none(angular.element($element).attr('href'))){create($element);}else{angular.forEach(($element.find('a')),function(elm){if(!UTILS.none(angular.element(elm).attr('href'))){create(elm);}});}});var nodeUrls=[];for(var key in nodes){nodeUrls.push(key);}
var deferred=API.request(options.endpoint,nodeUrls,options);if(deferred){deferred.promise.then(null,null,function(obj){angular.forEach(nodes[obj.original_url],function(node,i){node.progress(obj);});});}});}};}).directive('ngEmbedUrls',function($compile,$timeout,API,Embedly){return{scope:{key:'=',endpoint:'=',secure:'=',query:'=',method:'=',addImageStyles:'=',wrapElement:'=',className:'=',batch:'=',urlRegExp:'=',display:'=',urls:'='},controller:'ngEmbedlyController',link:function($scope,$element){var options=$scope.options;var nodes={};var response={};$scope.$watch('urls',function(){$element.children().remove();var nodeUrls=[];for(var i in $scope.urls){var url=$scope.urls[i];if(nodeUrls.indexOf(url)===-1){var wrapper=angular.element('<div></div>');var elem=angular.element('<div></div>');var node=Embedly.get(elem,url,options);nodes[url]=node;nodeUrls.push(url);angular.element(elem).data('embedly',node);wrapper.append(elem);$element.append(wrapper);}}
var deferred=API.request(options.endpoint,nodeUrls,options);if(deferred){deferred.promise.then(null,null,function(obj){response[obj.original_url]=obj;nodes[obj.original_url].progress(obj);});}});}};});