Created
October 7, 2015 13:58
-
-
Save supersupermomonga/ffbadfaaf373c61eb199 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
var factory = { | |
video: function() { | |
var setQuery = function (q) { | |
this.q = q; | |
} | |
var setToken = function (results) { | |
this.token = results.nextPageToken; | |
} | |
var setResults = function (results) { | |
this.total = results.pageInfo.totalResults; | |
this.items = results.items; | |
this.token = results.nextPageToken; | |
} | |
return { | |
q: '', | |
total: 0, | |
items: [], | |
token: {}, | |
setQuery: setQuery, | |
setToken: setToken, | |
setResults: setResults | |
} | |
} | |
} | |
var controller = { | |
search: function($scope, $state, Video) { | |
$scope.q = Video.q; | |
$scope.submit = function () { | |
Video.setQuery(this.q); | |
google.script.run | |
.withSuccessHandler(function(results) { | |
Video.setResults(results); | |
var options = {}; | |
if ($state.current.name == 'result') { | |
options['reload'] = true; | |
} | |
$state.go('result', { q: Video.q }, options); | |
}) | |
.withFailureHandler(function(res) { | |
$state.go('error'); | |
}) | |
.searchByKeyword(Video.q) | |
} | |
}, | |
main: function($scope, $state, Video) { | |
$scope.total = Video.total; | |
$scope.items = Video.items; | |
$scope.showPlayer = function(item) { | |
google.script.run.showPlayer(item.id.videoId); | |
} | |
$scope.outputable = (Video.total > 0) ? true : false; | |
$scope.outputToSpreadsheet = function() { | |
google.script.run.outputToSpreadsheet(Video.q, Video.items); | |
} | |
$scope.paginate = (Video.token != null) ? true : false; | |
$scope.addItems = function() { | |
google.script.run | |
.withSuccessHandler(function(results) { | |
Video.setToken(results); | |
for(var i in results.items) { | |
$scope.items.push(results.items[i]); | |
} | |
}) | |
.withFailureHandler(function(res) { | |
$state.go('error'); | |
}) | |
.searchByKeyword(Video.q, Video.token) | |
} | |
} | |
} | |
var template = { | |
search: '<div class="search-container"><form ng-submit="submit()"><div class="input-group"><input type="text" ng-model="q" ng-value="q" class="form-control" placeholder="Search..." /><span class="input-group-btn"><button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button></span></div></form></div>', | |
result: '<div class="main-container"><div class="state-container">{{ total | number:0 }} results</div><div class="result-container"><div class="media" ng-repeat="item in items"><div class="media-left media-top"><a class="media-thumb" ng-click="showPlayer(item)"><img class="media-object" src="{{ item.snippet.thumbnails.default.url }}" width="120" height="90" alt="" /><span>{{ item.snippet.publishedAt | date: "mediumDate" }}</span></a></div><div class="media-body"><h6 class="media-heading"><a ng-click="showPlayer(item)">{{ item.snippet.title }}</a></h6><p class="media-caption">{{ item.snippet.description }}</p></div></div></div><div class="paginate" ng-if="paginate"><button type="button" class="btn btn-default btn-sm btn-block" ng-click="addItems()">More</button></div></div><div class="output-container" ng-if="outputable"><button type="button" class="btn btn-default btn-block" ng-click="outputToSpreadsheet()"><span class="glyphicon glyphicon-save-file"></span>Output to spreadsheet</button></div>', | |
error: '<div class="main-container"><div class="state-container">System Error</div></div>' | |
} | |
var routes = function ($stateProvider, $urlRouterProvider) { | |
$urlRouterProvider.otherwise('/search'); | |
$stateProvider | |
.state('search', { | |
url: '/search', | |
views: { | |
search: { | |
template: template.search, | |
controller: 'SearchCtrl' | |
} | |
} | |
}) | |
.state('result', { | |
url: '/result/:q', | |
views: { | |
search: { | |
template: template.search, | |
controller: 'SearchCtrl' | |
}, | |
main: { | |
template: template.result, | |
controller: 'MainCtrl' | |
} | |
} | |
}) | |
.state('error', { | |
url: '/error', | |
views: { | |
search: { | |
template: template.search, | |
controller: 'SearchCtrl' | |
}, | |
main: { | |
template: template.error | |
} | |
} | |
}) | |
} | |
var app = angular.module('app', ['ui.router']); | |
app.factory('Video', factory.video); | |
app.controller('SearchCtrl', controller.search); | |
app.controller('MainCtrl', controller.main); | |
app.config(routes); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="stylesheet" src="//normalize-css.googlecode.com/svn/trunk/normalize.css" /> | |
<!--<link rel="stylesheet" href="//ssl.gstatic.com/docs/script/css/add-ons1.css" />--> | |
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" /> | |
<style type="text/css"> | |
html, body { | |
position: relative; | |
height: 100%; | |
font-family: "Helvetica Neue", Helvetica, Arial; | |
-webkit-font-smoothing: antialiased; | |
} | |
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { | |
display: none !important; | |
} | |
a { | |
cursor: pointer; | |
} | |
.search-container { | |
position: fixed; | |
z-index: 10; | |
width: 100%; | |
padding: 15px; | |
background: #cc181e; | |
} | |
.output-container { | |
position: fixed; | |
left: 0; | |
bottom: 0; | |
z-index: 10; | |
width: 100%; | |
padding: 15px; | |
background: #0f9d58; | |
} | |
.main-container { | |
padding: 65px 0; | |
} | |
.state-container { | |
padding: 10px 15px; | |
border-bottom: 1px solid #f0f0f0; | |
font-size: 80%; | |
text-align: right; | |
} | |
.result-container { | |
width: 100%; | |
padding: 15px 15px 0 15px; | |
} | |
.media-thumb { | |
display: block; | |
position: relative; | |
width: 120px; | |
height: 68px; | |
overflow: hidden; | |
} | |
.media-thumb:hover { | |
opacity: .85; | |
} | |
.media-thumb img { | |
margin-top: -11px; | |
} | |
.media-thumb span { | |
display: inline-block; | |
position: absolute; | |
bottom: 2px; | |
right: 2px; | |
padding: 2px; | |
background: rgba(0, 0, 0, .75); | |
color: #fff; | |
font-size: 75%; | |
} | |
.media-caption { | |
color: #767676; | |
font-size: 75%; | |
} | |
.paginate { | |
padding: 15px; | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function onOpen() { | |
var ui = SpreadsheetApp.getUi(); | |
ui.createMenu('YouTube') | |
.addItem('Search', 'showSidebar') | |
.addItem('Play', 'showModalDialog') | |
.addToUi(); | |
} | |
function onInstall() { | |
onOpen(); | |
} | |
function onEdit() { | |
onOpen(); | |
} | |
function showSidebar() { | |
var html = HtmlService.createTemplateFromFile('sidebar').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle('YouTube::Search'); | |
SpreadsheetApp.getUi().showSidebar(html); | |
} | |
function showModalDialog() { | |
var videoId = SpreadsheetApp.getActiveSheet().getActiveCell().getValue(); | |
PropertiesService.getScriptProperties().setProperty('VIDEO_ID', videoId); | |
var html = HtmlService.createTemplateFromFile('player').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setWidth(420).setHeight(315); | |
SpreadsheetApp.getUi().showModalDialog(html, 'YouTube::Play'); | |
} | |
function include(filename) { | |
return HtmlService.createHtmlOutputFromFile(filename).getContent(); | |
} | |
function searchByKeyword(q, nextPageToken) { | |
var options = { | |
q: q, | |
maxResults: 50, | |
type: 'video', | |
order: 'date' | |
}; | |
if (nextPageToken != null) { | |
options['pageToken'] = nextPageToken; | |
} | |
return YouTube.Search.list('id,snippet', options); | |
} | |
function showPlayer(videoId) { | |
PropertiesService.getScriptProperties().setProperty('VIDEO_ID', videoId); | |
var html = HtmlService.createTemplateFromFile('player').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setWidth(420).setHeight(315); | |
SpreadsheetApp.getUi().showModalDialog(html, 'YouTube::Play'); | |
} | |
function getYouTubeUrl() { | |
var videoId = PropertiesService.getScriptProperties().getProperty('VIDEO_ID'); | |
return 'https://www.youtube.com/embed/'+videoId+'?cc_load_policy=0&vq=highres&rel=0&loop=1&autoplay=1'; | |
} | |
function outputToSpreadsheet(q, items) { | |
try { | |
var ss = SpreadsheetApp.getActiveSpreadsheet(), | |
sheet = ss.insertSheet(q, 0), | |
header = ['videoId', 'title', 'description', 'channelId', 'channelTitle', 'publishedAt', 'thumbnailsDefaultUrl', 'thumbnailsHighUrl', 'thumbnailsMediumUrl']; | |
sheet.appendRow(header); | |
sheet.setFrozenRows(1); | |
for(var i in items) { | |
var item = items[i]; | |
sheet.appendRow([ | |
item.id.videoId, | |
item.snippet.title, | |
item.snippet.description, | |
item.snippet.channelId, | |
item.snippet.channelTitle, | |
item.snippet.publishedAt, | |
item.snippet.thumbnails['default']['url'], | |
item.snippet.thumbnails['high']['url'], | |
item.snippet.thumbnails['medium']['url'] | |
]); | |
} | |
ui.alert('Complete'); | |
} catch(ex) { | |
ui.alert(ex.toString()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<base target="_top"> | |
<?!= include('_stylesheet'); ?> | |
</head> | |
<body> | |
<iframe width="420" height="315" src="<?!= getYouTubeUrl(); ?>" frameborder="0" allowfullscreen></iframe> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment