events.js 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692
  1. var feedbackData;
  2. function getSpotifyInfo(title, cb, artist) {
  3. var q = "";
  4. q = title;
  5. if (artist !== undefined) {
  6. q += " artist:" + artist;
  7. }
  8. $.ajax({
  9. type: "GET",
  10. url: 'https://api.spotify.com/v1/search?q=' + encodeURIComponent(q) + '&type=track',
  11. applicationType: "application/json",
  12. contentType: "json",
  13. success: function (data) {
  14. cb(data);
  15. }
  16. });
  17. }
  18. function executeCommand(command, params){
  19. if (command === "help" || command === "commands") {
  20. $('#helpModal').modal('show');
  21. return true;
  22. } else if (command === "volume") {
  23. if (params.length === 1) {
  24. var volume = Number(params[0]);
  25. if (volume >= 0 || volume <= 100) {
  26. if (volume === 0) {
  27. $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off")
  28. } else {
  29. $("#volume-icon").removeClass("fa-volume-off").addClass("fa-volume-down")
  30. }
  31. $("#volume-slider").slider("setValue", volume);
  32. if (YTPlayer !== undefined) {
  33. YTPlayer.setVolume(volume);
  34. localStorage.setItem("volume", volume);
  35. }
  36. return true;
  37. }
  38. }
  39. } else if(command === "mute"){
  40. $("#volume-slider").slider("setValue", 0);
  41. $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off");
  42. if (YTPlayer !== undefined) {
  43. YTPlayer.setVolume(0);
  44. localStorage.setItem("volume", 0);
  45. }
  46. } else if(command === "ban"){
  47. var user = params[0];
  48. var time = params[1];
  49. var reason = params[2];
  50. Meteor.call("banUser", user, time, reason, function(err, res){
  51. if(err){
  52. console.log(err);
  53. }
  54. });
  55. } else if(command === "silence"){
  56. var user = params[0];
  57. var time = params[1];
  58. Meteor.call("muteUser", user, time, function(err, res){
  59. if(err){
  60. console.log(err);
  61. }
  62. });
  63. } else if(command === "unban"){
  64. var user = params[0];
  65. Meteor.call("unbanUser", user, function(err, res){
  66. if(err){
  67. console.log(err);
  68. }
  69. });
  70. } else if(command === "unsilence"){
  71. var user = params[0];
  72. Meteor.call("unsilenceUser", user, function(err, res){
  73. if(err){
  74. console.log(err);
  75. }
  76. });
  77. } else if(command === "pause"){
  78. Meteor.call("pauseRoom", Session.get("type"), function(err, res){
  79. if(err){
  80. console.log(err);
  81. }
  82. });
  83. } else if(command === "resume"){
  84. Meteor.call("resumeRoom", Session.get("type"), function(err, res){
  85. if(err){
  86. console.log(err);
  87. }
  88. });
  89. } else if(command === "shuffle"){
  90. Meteor.call("shufflePlaylist", Session.get("type"), function(err, res){
  91. if(err){
  92. console.log(err);
  93. }
  94. });
  95. } else if(command === "skip"){
  96. Meteor.call("skipSong", Session.get("type"), function(err, res){
  97. if(err){
  98. console.log(err);
  99. }
  100. });
  101. }
  102. }
  103. function sendMessage() {
  104. var message = $("#chat-input").val();
  105. if (!$("#chat-input").hasClass("disabled")) {
  106. if (message.length > 0 && message[0] !== " ") {
  107. if (message[0] === "/") {
  108. message = message.split("");
  109. message.shift();
  110. message = message.join("");
  111. var params = message.split(" ");
  112. params = params.map(function(param) {
  113. return param.replace(/\r?\n|\r/g, "");
  114. });
  115. var command = params.shift();
  116. command = command.replace(/\r?\n|\r/g, "");
  117. if (executeCommand(command, params)) {
  118. $("#chat-input").val("");
  119. } else {
  120. $("#chat-input").val("");
  121. }
  122. } else {
  123. $("#chat-input").addClass("disabled");
  124. $("#chat-input").attr("disabled", "");
  125. Meteor.call("sendMessage", Session.get("type"), message, function (err, res) {
  126. if(err){
  127. $("#chat-input").val("");
  128. $("#chat-input").removeAttr("disabled");
  129. $("#chat-input").removeClass("disabled");
  130. }
  131. if (res) {
  132. $("#chat-input").val("");
  133. $("#chat-input").removeAttr("disabled");
  134. $("#chat-input").removeClass("disabled");
  135. }
  136. });
  137. }
  138. }
  139. }
  140. }
  141. function sendMessageGlobal() {
  142. var message = $("#global-chat-input").val();
  143. if (!$("#global-chat-input").hasClass("disabled")) {
  144. if (message.length > 0 && message[0] !== " ") {
  145. if (message[0] === "/") {
  146. message = message.split("");
  147. message.shift();
  148. message = message.join("");
  149. var params = message.split(" ");
  150. var command = params.shift();
  151. command = command.replace(/\r?\n|\r/g, "");
  152. if (executeCommand(command, params)) {
  153. $("#global-chat-input").val("");
  154. } else {
  155. $("#global-chat-input").val("");
  156. }
  157. } else {
  158. $("#global-chat-input").addClass("disabled");
  159. $("#global-chat-input").attr("disabled", "");
  160. Meteor.call("sendMessage", "global", message, function (err, res) {
  161. if (res) {
  162. $("#global-chat-input").val("");
  163. }
  164. $("#global-chat-input").removeClass("disabled");
  165. $("#global-chat-input").removeAttr("disabled");
  166. });
  167. }
  168. }
  169. }
  170. }
  171. Template.admin.events({
  172. "click #croom_create": function() {
  173. Meteor.call("createRoom", $("#croom_display").val(), $("#croom_tag").val(), function (err, res) {
  174. if (err) {
  175. alert("Error " + err.error + ": " + err.reason);
  176. } else {
  177. window.location = "/" + $("#croom_tag").val();
  178. }
  179. });
  180. },
  181. "click a": function(e){
  182. var id = e.currentTarget.id;
  183. console.log(id.toLowerCase());
  184. Session.set("playlistToEdit", id);
  185. },
  186. "click #croom_create": function() {
  187. Meteor.call("createRoom", $("#croom_display").val(), $("#croom_tag").val(), $("#two").prop("checked"), function (err, res) {
  188. if (err) {
  189. alert("Error " + err.error + ": " + err.reason);
  190. } else {
  191. window.location = "/" + $("#croom_tag").val();
  192. }
  193. });
  194. },
  195. "click #rreset_confirm": function(){
  196. $('#confirmModal').modal('hide');
  197. Meteor.call("resetRating");
  198. },
  199. "click #edit_desc": function(){
  200. console.log($(this));
  201. console.log($(this)[0].type);
  202. Session.set("roomDesc", $(this)[0].type);
  203. },
  204. "click #submit_desc": function(){
  205. var description = $("#desc_text").val();
  206. Meteor.call("editRoomDesc", Session.get("roomDesc"), description);
  207. $("#desc-modal").closeModal();
  208. }
  209. });
  210. Template.alertsDashboard.events({
  211. "click #calart-create": function() {
  212. Meteor.call("addAlert", $("#calert-description").val(), $("#calert-priority").val().toLowerCase(), function (err, res) {
  213. if (err) {
  214. alert("Error " + err.error + ": " + err.reason);
  215. } else {
  216. $("#calert-description").val("");
  217. }
  218. });
  219. },
  220. "click #ralert-button": function() {
  221. Meteor.call("removeAlerts");
  222. }
  223. });
  224. Template.feedback.events({
  225. "click #feedback_submit": function(){
  226. if($("#feedback_message").val().length !== 0){
  227. Meteor.call("sendFeedback", $("#feedback_message").val());
  228. $("#feedback_message").val("");
  229. $("#modal1").closeModal()
  230. }
  231. },
  232. "click .upvote": function(){
  233. var message = $(this).parent("card").prevObject[0].message;
  234. Meteor.call("upvoteFeedback", message);
  235. },
  236. "click #delete": function(){
  237. var message = $(this).parent("card").prevObject[0].message;
  238. Meteor.call("deleteFeedback", message);
  239. },
  240. "click #edit": function(){
  241. $("#editModal").click()
  242. var data = Feedback.findOne({"message": $(this).parent("card").prevObject[0].message});
  243. feedbackData = data.message;
  244. $("#edit_feedback_message").val(data.message);
  245. },
  246. "click #edit_feedback_submit": function(){
  247. var oldMessage = feedbackData;
  248. var newMessage = $("#edit_feedback_message").val()
  249. $("#edit_feedback_message").val("")
  250. Meteor.call("updateFeedback", oldMessage, newMessage);
  251. $("#editFeedback").closeModal();
  252. }
  253. });
  254. Template.header.events({
  255. "click .logout": function(e){
  256. e.preventDefault();
  257. Meteor.logout();
  258. if (hpSound !== undefined) {
  259. hpSound.stop();
  260. }
  261. },
  262. "click #profile": function(){
  263. window.location = "/u/" + Meteor.user().profile.username;
  264. }
  265. });
  266. Template.login.events({
  267. "submit form": function(e){
  268. e.preventDefault();
  269. Session.set("github", false);
  270. var username = $("#username").val()
  271. var password = $("#password").val();
  272. Meteor.loginWithPassword(username, password, function(err) {
  273. if (err) {
  274. var errAlert = $('<div style="margin-bottom: 0" class="alert alert-danger" role="alert"><strong>Oh Snap!</strong> ' + err.reason + '</div>');
  275. $(".landing").before(errAlert);
  276. Meteor.setTimeout(function() {
  277. errAlert.fadeOut(5000, function() {
  278. errAlert.remove();
  279. });
  280. }, 5000);
  281. } else {
  282. window.location.href = "/";
  283. }
  284. });
  285. },
  286. "click #github-login": function(){
  287. Meteor.loginWithGithub({loginStyle: "redirect"}, function(err, res) {
  288. console.log(err, res);
  289. });
  290. }
  291. });
  292. Template.playlist.events({
  293. "keyup #search-playlist": function(){
  294. if($("#search-playlist").val().length === 0){
  295. $(".pl-item").show();
  296. } else {
  297. $(".pl-item").hide();
  298. var input = $("#search-playlist").val().toLowerCase();
  299. $(".pl-item strong").each(function(i, el){
  300. if($(el).text().toLowerCase().indexOf(input) !== -1){
  301. $(el).parent(".pl-item").show();
  302. }
  303. })
  304. $(".pl-item #pl-artist").each(function(i, el){
  305. if($(el).text().toLowerCase().indexOf(input) !== -1){
  306. $(el).parent(".pl-item").show();
  307. }
  308. })
  309. }
  310. },
  311. "click #pl-item": function(){
  312. console.log($(this).text());
  313. }
  314. });
  315. Template.profile.events({
  316. //Edit real name
  317. "click #edit-name": function(){
  318. $("#name").hide();
  319. $("#name-div").show();
  320. $("#edit-name").hide();
  321. $("#cancel-edit").show();
  322. },
  323. "click #submit-name": function(){
  324. var user = Meteor.user();
  325. $("#name").show();
  326. $("#name-div").hide();
  327. $("#edit-name").show();
  328. $("#cancel-edit").hide();
  329. var realname = $("#input-name").val();
  330. var username = user.profile.username;
  331. $("#name").text("Name: " + realname);
  332. $("#input-name").val("")
  333. Meteor.call("updateRealName", realname);
  334. },
  335. "click #cancel-edit": function(){
  336. $("#name").show();
  337. $("#name-div").hide();
  338. $("#edit-name").show();
  339. $("#cancel-edit").hide();
  340. $("#input-name").val("");
  341. },
  342. //Edit username
  343. "click #edit-username": function(){
  344. $("#username").hide();
  345. $("#username-div").show();
  346. $("#edit-username").hide();
  347. $("#cancel-username").show();
  348. },
  349. "click #submit-username": function(){
  350. var user = Meteor.user()
  351. $("#username").show();
  352. $("#username-div").hide();
  353. $("#edit-username").show();
  354. $("#cancel-username").hide();
  355. var username = user.username;
  356. var newUserName = $("#input-username").val();
  357. $("#profile-name").text(newUserName)
  358. $("#username").text("Username: " + newUserName);
  359. $("#input-username").val("")
  360. Meteor.call("updateUserName", newUserName);
  361. window.location = "/u/" + newUserName;
  362. },
  363. "click #cancel-username": function(){
  364. $("#username").show();
  365. $("#username-div").hide();
  366. $("#edit-username").show();
  367. $("#cancel-username").hide();
  368. $("#input-username").val("");
  369. },
  370. // Admins only Edit Rank
  371. "click #edit-rank": function() {
  372. $("#rank").hide();
  373. $("#rank-div").show();
  374. $("#edit-rank").hide();
  375. $("#cancel-rank").show();
  376. },
  377. "click #submit-rank": function() {
  378. $("#rank").show();
  379. $("#rank-div").hide();
  380. $("#edit-rank").show();
  381. $("#cancel-rank").hide();
  382. var newRank = $("#select-rank option:selected").val();
  383. var username = Session.get("username");
  384. console.log(username, newRank);
  385. },
  386. "click #cancel-rank": function() {
  387. $("#rank").show();
  388. $("#rank-div").hide();
  389. $("#edit-rank").show();
  390. $("#cancel-rank").hide();
  391. }
  392. });
  393. var seekerBarInterval = undefined;
  394. Template.queues.events({
  395. /* TODO Add undo delete button */
  396. "input #id": function() {
  397. console.log("Change!");
  398. $("#previewPlayerContainer").addClass("hide-preview");
  399. },
  400. "input #img": function() {
  401. var url = $("#img").val();
  402. console.log(url);
  403. Session.set("image_url", url);
  404. },
  405. "click .preview-button": function(e){
  406. Session.set("song", this);
  407. $("#previewModal").openModal();
  408. },
  409. "click #previewImageButton": function() {
  410. $("#preview-image").attr("src", Session.get("song").img);
  411. },
  412. "click .edit-queue-button": function(e){
  413. Session.set("song", this);
  414. Session.set("genre", $(e.target).data("genre"));
  415. Session.set("type", "queue");
  416. $("#mid").val(this.mid).change();
  417. $("#artist").val(this.artist).change();
  418. $("#title").val(this.title).change();
  419. $("#img").val(this.img).change();
  420. $("#id").val(this.id).change();
  421. $("#likes").val(this.likes).change();
  422. $("#dislikes").val(this.dislikes).change();
  423. $("#duration").val(this.duration).change();
  424. $("#skip-duration").val(this.skipDuration).change();
  425. $("#previewPlayerContainer").addClass("hide-preview");
  426. Session.set("image_url", this.img);
  427. Session.set("editing", true);
  428. $("#editModal").openModal({
  429. complete : function() {
  430. Session.set("editing", false);
  431. if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
  432. YTPlayer.stopVideo();
  433. }
  434. }
  435. });
  436. },
  437. "click .add-song-button": function(e){
  438. var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
  439. Meteor.call("addSongToPlaylist", genre, this, function(err) {
  440. console.log(err);
  441. if (err) {
  442. var $toastContent = $('<span><strong>Song not added.</strong> ' + err.reason + '</span>');
  443. Materialize.toast($toastContent, 8000);
  444. }
  445. });
  446. },
  447. "click .deny-song-button": function(e){
  448. var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
  449. Meteor.call("removeSongFromQueue", genre, this.mid);
  450. },
  451. "click #play": function() {
  452. var duration = Session.get("song").duration;
  453. var d = moment.duration(parseInt(duration), 'seconds');
  454. $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  455. $("#previewPlayerContainer").removeClass("hide-preview");
  456. var song = Session.get("song");
  457. var id = song.id;
  458. var volume = localStorage.getItem("volume") || 20;
  459. if (song.duration !== 0) {
  460. $("#play").attr("disabled", true);
  461. $("#stop").attr("disabled", false);
  462. $("#pause").attr("disabled", false);
  463. $("#forward").attr("disabled", false);
  464. if (YTPlayer === undefined) {
  465. YTPlayer = new YT.Player("previewPlayer", {
  466. height: 540,
  467. width: 568,
  468. videoId: id,
  469. playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3, showinfo: 0, fs: 0},
  470. events: {
  471. 'onReady': function(event) {
  472. event.target.seekTo(Number(song.skipDuration));
  473. event.target.playVideo();
  474. event.target.setVolume(volume);
  475. },
  476. 'onStateChange': function(event){
  477. if (event.data == YT.PlayerState.PAUSED) {
  478. if (seekerBarInterval !== undefined) {
  479. Meteor.clearInterval(seekerBarInterval);
  480. seekerBarInterval = undefined;
  481. }
  482. }
  483. if (event.data == YT.PlayerState.UNSTARTED) {
  484. if (seekerBarInterval !== undefined) {
  485. Meteor.clearInterval(seekerBarInterval);
  486. seekerBarInterval = undefined;
  487. }
  488. $(".seeker-bar").css({width: "0"});
  489. $("#time-elapsed").text("0:00");
  490. $("#previewPlayerContainer").addClass("hide-preview");
  491. }
  492. if (event.data == YT.PlayerState.PLAYING) {
  493. seekerBarInterval = Meteor.setInterval(function() {
  494. var duration = Session.get("song").duration;
  495. var timeElapsed = YTPlayer.getCurrentTime();
  496. var skipDuration = Session.get("song").skipDuration;
  497. if (duration <= (timeElapsed - skipDuration)) {
  498. YTPlayer.stopVideo();
  499. $("#play").attr("disabled", false);
  500. $("#stop").attr("disabled", true);
  501. $("#pause").attr("disabled", true);
  502. $("#forward").attr("disabled", true);
  503. $("#previewPlayerContainer").addClass("hide-preview");
  504. $(".seeker-bar").css({width: "0"});
  505. $("#time-elapsed").text("0:00");
  506. Meteor.clearInterval(seekerBarInterval);
  507. } else {
  508. var percentComplete = (timeElapsed - skipDuration) / duration * 100;
  509. $(".seeker-bar").css({width: percentComplete + "%"});
  510. var d = moment.duration(timeElapsed - skipDuration, 'seconds');
  511. $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  512. }
  513. }, 100);
  514. $("#play").attr("disabled", true);
  515. $("#stop").attr("disabled", false);
  516. $("#pause").attr("disabled", false);
  517. $("#forward").attr("disabled", false);
  518. } else {
  519. $("#play").attr("disabled", false);
  520. $("#stop").attr("disabled", true);
  521. $("#pause").attr("disabled", true);
  522. $("#forward").attr("disabled", true);
  523. }
  524. }
  525. }
  526. });
  527. } else {
  528. if (YTPlayer.getPlayerState() === 2) {
  529. YTPlayer.playVideo();
  530. } else {
  531. console.log(id, song.skipDuration, song.duration);
  532. YTPlayer.loadVideoById(id);
  533. YTPlayer.seekTo(Number(song.skipDuration));
  534. }
  535. }
  536. $("#previewPlayerContainer").removeClass("hide-preview");
  537. }
  538. },
  539. "click #stop": function() {
  540. $("#play").attr("disabled", false);
  541. $("#stop").attr("disabled", true);
  542. $("#pause").attr("disabled", true);
  543. $("#forward").attr("disabled", true);
  544. if (previewEndSongTimeout !== undefined) {
  545. Meteor.clearTimeout(previewEndSongTimeout);
  546. }
  547. if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
  548. YTPlayer.stopVideo();
  549. }
  550. },
  551. "click #pause": function() {
  552. $("#play").attr("disabled", false);
  553. $("#stop").attr("disabled", false);
  554. $("#pause").attr("disabled", true);
  555. $("#forward").attr("disabled", true);
  556. if (previewEndSongTimeout !== undefined) {
  557. Meteor.clearTimeout(previewEndSongTimeout);
  558. }
  559. if (YTPlayer !== undefined && YTPlayer.pauseVideo !== undefined) {
  560. YTPlayer.pauseVideo();
  561. }
  562. },
  563. "click #forward": function() {
  564. var error = false;
  565. if (YTPlayer !== undefined) {
  566. var duration = Number(Session.get("song").duration) | 0;
  567. var skipDuration = Number(Session.get("song").skipDuration) | 0;
  568. if (YTPlayer.getDuration() < duration + skipDuration) {
  569. var $toastContent = $('<span><strong>Error.</strong> The song duration is longer than the length of the video.</span>');
  570. Materialize.toast($toastContent, 8000);
  571. error = true;
  572. } else {
  573. YTPlayer.seekTo(skipDuration + duration - 10);
  574. }
  575. }
  576. if (!error) {
  577. if (previewEndSongTimeout !== undefined) {
  578. Meteor.clearTimeout(previewEndSongTimeout);
  579. }
  580. previewEndSongTimeout = Meteor.setTimeout(function() {
  581. if (YTPlayer !== undefined) {
  582. YTPlayer.stopVideo();
  583. }
  584. $("#play").attr("disabled", false);
  585. $("#stop").attr("disabled", true);
  586. $("#pause").attr("disabled", true);
  587. $("#forward").attr("disabled", true);
  588. $("#previewPlayerContainer").addClass("hide-preview");
  589. }, 10000);
  590. }
  591. },
  592. "click #get-spotify-info": function() {
  593. var search = $("#title").val();
  594. var artistName = $("#artist").val();
  595. getSpotifyInfo(search, function(data) {
  596. for(var i in data){
  597. for(var j in data[i].items){
  598. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  599. $("#img").val(data[i].items[j].album.images[2].url).change();
  600. $("#duration").val(data[i].items[j].duration_ms / 1000).change();
  601. return;
  602. }
  603. }
  604. }
  605. }, artistName);
  606. },
  607. "click #save-song-button": function() {
  608. var newSong = {};
  609. newSong.mid = $("#mid").val();
  610. newSong.id = $("#id").val();
  611. newSong.likes = Number($("#likes").val());
  612. newSong.dislikes = Number($("#dislikes").val());
  613. newSong.title = $("#title").val();
  614. newSong.artist = $("#artist").val();
  615. newSong.img = $("#img").val();
  616. newSong.duration = Number($("#duration").val());
  617. newSong.skipDuration = $("#skip-duration").val();
  618. newSong.requestedBy = Session.get("song").requestedBy;
  619. if(newSong.skipDuration === undefined){
  620. newSong.skipDuration = 0;
  621. }
  622. Meteor.call("updateQueueSong", Session.get("genre"), Session.get("song"), newSong, function(err, res) {
  623. console.log(err, res);
  624. if (err) {
  625. var $toastContent = $('<span><strong>Song not saved.</strong> ' + err.reason + '</span>');
  626. Materialize.toast($toastContent, 8000);
  627. } else {
  628. Session.set("song", newSong);
  629. }
  630. });
  631. }
  632. });
  633. Template.manageStation.events({
  634. /* TODO Add undo delete button */
  635. "input #id": function() {
  636. $("#previewPlayerContainer").addClass("hide-preview");
  637. },
  638. "input #img": function() {
  639. var url = $("#img").val();
  640. Session.set("image_url", url);
  641. },
  642. "click .preview-button": function(e){
  643. Session.set("song", this);
  644. $("#previewModal").openModal();
  645. },
  646. "click #previewImageButton": function() {
  647. $("#preview-image").attr("src", Session.get("song").img);
  648. },
  649. "click .edit-song-button": function(e){
  650. Session.set("song", this);
  651. Session.set("genre", $(e.target).data("genre"));
  652. $("#mid").val(this.mid).change();
  653. $("#artist").val(this.artist).change();
  654. $("#title").val(this.title).change();
  655. $("#img").val(this.img).change();
  656. $("#id").val(this.id).change();
  657. $("#likes").val(this.likes).change();
  658. $("#dislikes").val(this.dislikes).change();
  659. $("#duration").val(this.duration).change();
  660. $("#skip-duration").val(this.skipDuration).change();
  661. $("#previewPlayerContainer").addClass("hide-preview");
  662. Session.set("image_url", this.img);
  663. Session.set("editing", true);
  664. $("#editModal").openModal({
  665. complete : function() {
  666. Session.set("editing", false);
  667. if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
  668. YTPlayer.stopVideo();
  669. }
  670. }
  671. });
  672. },
  673. "click .remove-song-button": function(e){
  674. var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
  675. Meteor.call("removeSongFromPlaylist", genre, this.mid);
  676. },
  677. "click #play": function() {
  678. var duration = Session.get("song").duration;
  679. var d = moment.duration(parseInt(duration), 'seconds');
  680. $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  681. $("#previewPlayerContainer").removeClass("hide-preview");
  682. var song = Session.get("song");
  683. var id = song.id;
  684. var volume = localStorage.getItem("volume") || 20;
  685. if (song.duration !== 0) {
  686. $("#play").attr("disabled", true);
  687. $("#stop").attr("disabled", false);
  688. $("#pause").attr("disabled", false);
  689. $("#forward").attr("disabled", false);
  690. if (YTPlayer === undefined) {
  691. YTPlayer = new YT.Player("previewPlayer", {
  692. height: 540,
  693. width: 568,
  694. videoId: id,
  695. playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3, showinfo: 0, fs: 0},
  696. events: {
  697. 'onReady': function(event) {
  698. event.target.seekTo(Number(song.skipDuration));
  699. event.target.playVideo();
  700. event.target.setVolume(volume);
  701. },
  702. 'onStateChange': function(event){
  703. if (event.data == YT.PlayerState.PAUSED) {
  704. if (seekerBarInterval !== undefined) {
  705. Meteor.clearInterval(seekerBarInterval);
  706. seekerBarInterval = undefined;
  707. }
  708. }
  709. if (event.data == YT.PlayerState.UNSTARTED) {
  710. if (seekerBarInterval !== undefined) {
  711. Meteor.clearInterval(seekerBarInterval);
  712. seekerBarInterval = undefined;
  713. }
  714. $(".seeker-bar").css({width: "0"});
  715. $("#time-elapsed").text("0:00");
  716. $("#previewPlayerContainer").addClass("hide-preview");
  717. }
  718. if (event.data == YT.PlayerState.PLAYING) {
  719. seekerBarInterval = Meteor.setInterval(function() {
  720. var duration = Session.get("song").duration;
  721. var timeElapsed = YTPlayer.getCurrentTime();
  722. var skipDuration = Session.get("song").skipDuration;
  723. if (duration <= (timeElapsed - skipDuration)) {
  724. YTPlayer.stopVideo();
  725. $("#play").attr("disabled", false);
  726. $("#stop").attr("disabled", true);
  727. $("#pause").attr("disabled", true);
  728. $("#forward").attr("disabled", true);
  729. $("#previewPlayerContainer").addClass("hide-preview");
  730. $(".seeker-bar").css({width: "0"});
  731. $("#time-elapsed").text("0:00");
  732. Meteor.clearInterval(seekerBarInterval);
  733. } else {
  734. var percentComplete = (timeElapsed - skipDuration) / duration * 100;
  735. $(".seeker-bar").css({width: percentComplete + "%"});
  736. var d = moment.duration(timeElapsed - skipDuration, 'seconds');
  737. $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  738. }
  739. }, 100);
  740. $("#play").attr("disabled", true);
  741. $("#stop").attr("disabled", false);
  742. $("#pause").attr("disabled", false);
  743. $("#forward").attr("disabled", false);
  744. } else {
  745. $("#play").attr("disabled", false);
  746. $("#stop").attr("disabled", true);
  747. $("#pause").attr("disabled", true);
  748. $("#forward").attr("disabled", true);
  749. }
  750. }
  751. }
  752. });
  753. } else {
  754. if (YTPlayer.getPlayerState() === 2) {
  755. YTPlayer.playVideo();
  756. } else {
  757. console.log(id, song.skipDuration, song.duration);
  758. YTPlayer.loadVideoById(id);
  759. YTPlayer.seekTo(Number(song.skipDuration));
  760. }
  761. }
  762. $("#previewPlayerContainer").removeClass("hide-preview");
  763. }
  764. },
  765. "click #stop": function() {
  766. $("#play").attr("disabled", false);
  767. $("#stop").attr("disabled", true);
  768. $("#pause").attr("disabled", true);
  769. $("#forward").attr("disabled", true);
  770. if (previewEndSongTimeout !== undefined) {
  771. Meteor.clearTimeout(previewEndSongTimeout);
  772. }
  773. if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
  774. YTPlayer.stopVideo();
  775. }
  776. },
  777. "click #pause": function() {
  778. $("#play").attr("disabled", false);
  779. $("#stop").attr("disabled", false);
  780. $("#pause").attr("disabled", true);
  781. $("#forward").attr("disabled", true);
  782. if (previewEndSongTimeout !== undefined) {
  783. Meteor.clearTimeout(previewEndSongTimeout);
  784. }
  785. if (YTPlayer !== undefined && YTPlayer.pauseVideo !== undefined) {
  786. YTPlayer.pauseVideo();
  787. }
  788. },
  789. "click #forward": function() {
  790. var error = false;
  791. if (YTPlayer !== undefined) {
  792. var duration = Number(Session.get("song").duration) | 0;
  793. var skipDuration = Number(Session.get("song").skipDuration) | 0;
  794. if (YTPlayer.getDuration() < duration + skipDuration) {
  795. var $toastContent = $('<span><strong>Error.</strong> The song duration is longer than the length of the video.</span>');
  796. Materialize.toast($toastContent, 8000);
  797. error = true;
  798. } else {
  799. YTPlayer.seekTo(skipDuration + duration - 10);
  800. }
  801. }
  802. if (!error) {
  803. if (previewEndSongTimeout !== undefined) {
  804. Meteor.clearTimeout(previewEndSongTimeout);
  805. }
  806. previewEndSongTimeout = Meteor.setTimeout(function() {
  807. if (YTPlayer !== undefined) {
  808. YTPlayer.stopVideo();
  809. }
  810. $("#play").attr("disabled", false);
  811. $("#stop").attr("disabled", true);
  812. $("#pause").attr("disabled", true);
  813. $("#forward").attr("disabled", true);
  814. $("#previewPlayerContainer").addClass("hide-preview");
  815. }, 10000);
  816. }
  817. },
  818. "click #get-spotify-info": function() {
  819. var search = $("#title").val();
  820. var artistName = $("#artist").val();
  821. getSpotifyInfo(search, function(data) {
  822. for(var i in data){
  823. for(var j in data[i].items){
  824. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  825. $("#img").val(data[i].items[j].album.images[2].url).change();
  826. $("#duration").val(data[i].items[j].duration_ms / 1000).change();
  827. return;
  828. }
  829. }
  830. }
  831. }, artistName);
  832. },
  833. "click #save-song-button": function() {
  834. var newSong = {};
  835. newSong.mid = $("#mid").val();
  836. newSong.id = $("#id").val();
  837. newSong.likes = Number($("#likes").val());
  838. newSong.dislikes = Number($("#dislikes").val());
  839. newSong.title = $("#title").val();
  840. newSong.artist = $("#artist").val();
  841. newSong.img = $("#img").val();
  842. newSong.duration = Number($("#duration").val());
  843. newSong.skipDuration = $("#skip-duration").val();
  844. newSong.requestedBy = Session.get("song").requestedBy;
  845. Meteor.call("updatePlaylistSong", Session.get("genre"), Session.get("song"), newSong, function(err, res) {
  846. console.log(err, res);
  847. if (err) {
  848. var $toastContent = $('<span><strong>Song not saved.</strong> ' + err.reason + '</span>');
  849. Materialize.toast($toastContent, 8000);
  850. } else {
  851. Session.set("song", newSong);
  852. }
  853. });
  854. }
  855. });
  856. Template.register.events({
  857. "submit form": function(e){
  858. e.preventDefault();
  859. var username = $("#username").val()
  860. var email = $("#email").val()
  861. var password = $("#password").val();
  862. var captchaData = grecaptcha.getResponse();
  863. console.log(captchaData)
  864. Meteor.call("createUserMethod", {username: username, email: email, password: password}, captchaData, function(err, res) {
  865. grecaptcha.reset();
  866. if (err) {
  867. console.log(err);
  868. var errAlert = $('<div style="margin-bottom: 0" class="alert alert-danger" role="alert"><strong>Oh Snap!</strong> ' + err.reason + '</div>');
  869. $(".landing").before(errAlert);
  870. Meteor.setTimeout(function() {
  871. errAlert.fadeOut(5000, function() {
  872. errAlert.remove();
  873. });
  874. }, 5000);
  875. } else {
  876. Meteor.loginWithPassword(username, password);
  877. Accounts.onLogin(function(){
  878. window.location.href = "/";
  879. })
  880. }
  881. });
  882. },
  883. "click #github-login": function(){
  884. Meteor.loginWithGithub({loginStyle: "redirect"}, function(err, res) {
  885. console.log(err, res);
  886. });
  887. }
  888. });
  889. Template.room.events({
  890. "click #youtube-playlist-button": function () {
  891. if (!Session.get("importingPlaylist")) {
  892. var playlist_link = $("#youtube-playlist-input").val();
  893. var playlist_id = gup("list", playlist_link);
  894. var ytImportQueue = [];
  895. var totalVideos = 0;
  896. var videosInvalid = 0;
  897. var videosInQueue = 0;
  898. var videosInPlaylist = 0;
  899. var ranOnce = false;
  900. Session.set("importingPlaylist", true);
  901. $("#youtube-playlist-button").attr("disabled", "");
  902. $("#youtube-playlist-button").addClass("disabled");
  903. $("#youtube-playlist-input").attr("disabled", "");
  904. $("#youtube-playlist-input").addClass("disabled");
  905. $("#playlist-import-queue").empty();
  906. $("#playlist-import-queue").hide();
  907. $("#add-youtube-playlist").addClass("hidden-2");
  908. $("#import-progress").attr("aria-valuenow", 0);
  909. $("#import-progress").css({width: "0%"});
  910. $("#import-progress").text("0%");
  911. function makeAPICall(playlist_id, nextPageToken) {
  912. if (nextPageToken !== undefined) {
  913. nextPageToken = "&pageToken=" + nextPageToken;
  914. } else {
  915. nextPageToken = "";
  916. }
  917. $.ajax({
  918. type: "GET",
  919. url: "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=" + playlist_id + nextPageToken + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
  920. applicationType: "application/json",
  921. contentType: "json",
  922. success: function (data) {
  923. if (!ranOnce) {
  924. ranOnce = true;
  925. totalVideos = data.pageInfo.totalResults;
  926. }
  927. var nextToken = data.nextPageToken;
  928. for (var i in data.items) {
  929. var item = data.items[i];
  930. if (item.snippet.thumbnails !== undefined) {
  931. var genre = Session.get("type");
  932. if (Playlists.find({
  933. type: genre,
  934. "songs.id": item.snippet.resourceId.videoId
  935. }, {songs: {$elemMatch: {id: item.snippet.resourceId.videoId}}}).count() !== 0) {
  936. videosInPlaylist++;
  937. } else if (Queues.find({
  938. type: genre,
  939. "songs.id": item.snippet.resourceId.videoId
  940. }, {songs: {$elemMatch: {id: item.snippet.resourceId.videoId}}}).count() !== 0) {
  941. videosInQueue++;
  942. } else {
  943. $("#playlist-import-queue").append(
  944. "<div class='youtube-import-queue-item'>" +
  945. "<img src='" + item.snippet.thumbnails.medium.url + "' class='song-result-thumbnail'/>" +
  946. "<div>" +
  947. "<span class='song-result-title'>" + item.snippet.title + "</span>" +
  948. "<span class='song-result-channel'>" + item.snippet.channelTitle + "</span>" +
  949. "</div>" +
  950. "<i class='fa fa-times remove-import-song'></i>" +
  951. "</div>"
  952. );
  953. var percentage = ytImportQueue.length / (totalVideos - videosInvalid) * 100;
  954. $("#import-progress").attr("aria-valuenow", percentage.toFixed(2));
  955. $("#import-progress").css({width: percentage + "%"});
  956. $("#import-progress").text(percentage.toFixed(1) + "%");
  957. ytImportQueue.push({
  958. title: item.snippet.title,
  959. id: item.snippet.resourceId.videoId
  960. });
  961. }
  962. } else {
  963. videosInvalid++;
  964. }
  965. }
  966. if (nextToken !== undefined) {
  967. makeAPICall(playlist_id, nextToken);
  968. } else {
  969. $("#playlist-import-queue > div > i").click(function () {
  970. var title = $(this).parent().find("div > .song-result-title").text();
  971. for (var i in ytImportQueue) {
  972. if (ytImportQueue[i].title === title) {
  973. ytImportQueue.splice(i, 1);
  974. }
  975. }
  976. $(this).parent().remove();
  977. Session.set("YTImportQueue", ytImportQueue);
  978. });
  979. Session.set("importingPlaylist", false);
  980. $("#import-progress").attr("aria-valuenow", 100);
  981. $("#import-progress").css({width: "100%"});
  982. $("#import-progress").text("100%");
  983. $("#youtube-playlist-button").removeAttr("disabled");
  984. $("#youtube-playlist-button").removeClass("disabled");
  985. $("#youtube-playlist-input").removeAttr("disabled");
  986. $("#youtube-playlist-input").removeClass("disabled");
  987. $("#playlist-import-queue").show();
  988. $("#add-youtube-playlist").removeClass("hidden-2");
  989. Session.set("YTImportQueue", ytImportQueue);
  990. }
  991. }
  992. })
  993. }
  994. makeAPICall(playlist_id);
  995. }
  996. },
  997. "click #add-youtube-playlist": function () {
  998. var YTImportQueue = Session.get("YTImportQueue");
  999. $("#youtube-playlist-button").attr("disabled", "");
  1000. $("#youtube-playlist-button").addClass("disabled");
  1001. $("#youtube-playlist-input").attr("disabled", "");
  1002. $("#youtube-playlist-input").addClass("disabled");
  1003. $("#import-progress").attr("aria-valuenow", 0);
  1004. $("#import-progress").css({width: "0%"});
  1005. $("#import-progress").text("0%");
  1006. var failed = 0;
  1007. var success = 0;
  1008. var processed = 0;
  1009. var total = YTImportQueue.length;
  1010. YTImportQueue.forEach(function (song) {
  1011. var songData = {type: "YouTube", id: song.id, title: song.title, artist: "", img: ""};
  1012. Meteor.call("addSongToQueue", Session.get("type"), songData, function (err, res) {
  1013. if (err) {
  1014. console.log(err);
  1015. failed++;
  1016. } else {
  1017. success++;
  1018. }
  1019. processed++;
  1020. var percentage = processed / total * 100;
  1021. $("#import-progress").attr("aria-valuenow", percentage.toFixed(2));
  1022. $("#import-progress").css({width: percentage + "%"});
  1023. $("#import-progress").text(percentage.toFixed(1) + "%");
  1024. });
  1025. });
  1026. },
  1027. "click #chat-tab": function () {
  1028. $("#chat-tab").removeClass("unread-messages");
  1029. },
  1030. "click #global-chat-tab": function () {
  1031. $("#global-chat-tab").removeClass("unread-messages");
  1032. },
  1033. "click #sync": function () {
  1034. if (Session.get("currentSong") !== undefined) {
  1035. var room = Rooms.findOne({type: Session.get("type")});
  1036. if (room !== undefined) {
  1037. var timeIn = Date.now() - Session.get("currentSong").started - room.timePaused;
  1038. var skipDuration = Number(Session.get("currentSong").skipDuration) | 0;
  1039. if (YTPlayer !== undefined) {
  1040. YTPlayer.seekTo(skipDuration + timeIn / 1000);
  1041. }
  1042. }
  1043. }
  1044. },
  1045. "click #lock": function () {
  1046. Meteor.call("lockRoom", Session.get("type"));
  1047. },
  1048. "click #unlock": function () {
  1049. Meteor.call("unlockRoom", Session.get("type"));
  1050. },
  1051. "click #chat-tab": function (e) {
  1052. Meteor.setTimeout(function () {
  1053. $("#chat-ul").scrollTop(100000);
  1054. }, 1);
  1055. },
  1056. "click #global-chat-tab": function (e) {
  1057. Meteor.setTimeout(function () {
  1058. $("#global-chat-ul").scrollTop(100000);
  1059. }, 1);
  1060. },
  1061. "click #submit": function () {
  1062. sendMessage();
  1063. Meteor.setTimeout(function () {
  1064. $("#chat-ul").scrollTop(100000);
  1065. }, 1000)
  1066. },
  1067. "click #global-submit": function () {
  1068. sendMessageGlobal();
  1069. Meteor.setTimeout(function () {
  1070. $("#global-chat-ul").scrollTop(100000);
  1071. }, 1000)
  1072. },
  1073. "keyup #chat-input": function (e) {
  1074. if (e.type === "keyup" && e.which === 13) {
  1075. e.preventDefault();
  1076. if (!$('#chat-input').data('dropdownshown')) {
  1077. sendMessage();
  1078. Meteor.setTimeout(function () {
  1079. $("#chat-ul").scrollTop(100000);
  1080. }, 1000)
  1081. }
  1082. }
  1083. },
  1084. "keyup #global-chat-input": function (e) {
  1085. if (e.type === "keyup" && e.which === 13) {
  1086. e.preventDefault();
  1087. if (!$('#global-chat-input').data('dropdownshown')) {
  1088. sendMessageGlobal();
  1089. Meteor.setTimeout(function () {
  1090. $("#global-chat-ul").scrollTop(100000);
  1091. }, 1000)
  1092. }
  1093. }
  1094. },
  1095. "click #like": function (e) {
  1096. $("#like").blur();
  1097. Meteor.call("likeSong", Session.get("currentSong").mid);
  1098. },
  1099. "click #dislike": function (e) {
  1100. $("#dislike").blur();
  1101. Meteor.call("dislikeSong", Session.get("currentSong").mid);
  1102. },
  1103. "click #vote-skip": function () {
  1104. Meteor.call("voteSkip", type, function (err, res) {
  1105. $("#vote-skip").attr("disabled", true);
  1106. });
  1107. },
  1108. "click #report-prev": function (e) {
  1109. if (Session.get("previousSong") !== undefined) {
  1110. Session.set("reportPrevious", true);
  1111. $("#report-prev").prop("disabled", true);
  1112. $("#report-curr").prop("disabled", false);
  1113. }
  1114. },
  1115. "click #report-curr": function (e) {
  1116. Session.set("reportPrevious", false);
  1117. $("#report-prev").prop("disabled", false);
  1118. $("#report-curr").prop("disabled", true);
  1119. },
  1120. "click #report-modal": function () {
  1121. Session.set("currentSongR", Session.get("currentSong"));
  1122. Session.set("previousSongR", Session.get("previousSong"));
  1123. },
  1124. "click #add-song-button": function (e) {
  1125. e.preventDefault();
  1126. parts = location.href.split('/');
  1127. var roomType = parts.pop();
  1128. var genre = roomType.toLowerCase();
  1129. var type = $("#type").val();
  1130. id = $("#id").val();
  1131. var title = $("#title").val();
  1132. var artist = $("#artist").val();
  1133. var img = $("#img").val();
  1134. var songData = {type: type, id: id, title: title, artist: artist, img: img};
  1135. if (Playlists.find({
  1136. type: genre,
  1137. "songs.id": songData.id
  1138. }, {songs: {$elemMatch: {id: songData.id}}}).count() !== 0) {
  1139. $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> This song is already in the playlist.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
  1140. $(this).remove();
  1141. });
  1142. } else if (Queues.find({
  1143. type: genre,
  1144. "songs.id": songData.id
  1145. }, {songs: {$elemMatch: {id: songData.id}}}).count() !== 0) {
  1146. $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> This song has already been requested.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
  1147. $(this).remove();
  1148. });
  1149. } else {
  1150. Meteor.call("addSongToQueue", genre, songData, function (err, res) {
  1151. console.log(err, res);
  1152. if (err) {
  1153. $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> Something went wrong.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
  1154. $(this).remove();
  1155. });
  1156. } else {
  1157. $("<div class='alert alert-success alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song added.</strong> Your song has been added to the queue.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
  1158. $(this).remove();
  1159. });
  1160. }
  1161. });
  1162. }
  1163. $("#close-modal-a").click();
  1164. },
  1165. "click #toggle-video": function (e) {
  1166. e.preventDefault();
  1167. if (Session.get("mediaHidden")) {
  1168. $("#media-container").removeClass("hidden");
  1169. $("#toggle-video").text("Hide video");
  1170. Session.set("mediaHidden", false);
  1171. } else {
  1172. $("#media-container").addClass("hidden");
  1173. $("#toggle-video").text("Show video");
  1174. Session.set("mediaHidden", true);
  1175. }
  1176. },
  1177. "click #return": function (e) {
  1178. $("#add-info").hide();
  1179. $("#search-info").show();
  1180. },
  1181. "click #search-song": function () {
  1182. var songs = [];
  1183. $("#song-results").empty();
  1184. $.ajax({
  1185. type: "GET",
  1186. url: "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + $("#song-input").val() + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
  1187. applicationType: "application/json",
  1188. contentType: "json",
  1189. success: function (data) {
  1190. for (var i in data.items) {
  1191. var item = data.items[i];
  1192. $("#song-results").append(
  1193. "<div>" +
  1194. "<img src='" + item.snippet.thumbnails.medium.url + "' class='song-result-thumbnail'/>" +
  1195. "<div>" +
  1196. "<span class='song-result-title'>" + item.snippet.title + "</span>" +
  1197. "<span class='song-result-channel'>" + item.snippet.channelTitle + "</span>" +
  1198. "</div>" +
  1199. "</div>"
  1200. );
  1201. songs.push({title: item.snippet.title, id: item.id.videoId});
  1202. }
  1203. $("#song-results > div").click(function () {
  1204. $("#search-info").hide();
  1205. $("#add-info").show();
  1206. var title = $(this).find("div > .song-result-title").text();
  1207. for (var i in songs) {
  1208. if (songs[i].title === title) {
  1209. var songObj = {
  1210. id: songs[i].id,
  1211. title: songs[i].title,
  1212. type: "youtube"
  1213. };
  1214. $("#title").val(songObj.title);
  1215. $("#artist").val("");
  1216. $("#id").val(songObj.id);
  1217. getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function (data) {
  1218. if (data.tracks.items.length > 0) {
  1219. $("#title").val(data.tracks.items[0].name);
  1220. var artists = [];
  1221. $("#img").val(data.tracks.items[0].album.images[2].url);
  1222. data.tracks.items[0].artists.forEach(function (artist) {
  1223. artists.push(artist.name);
  1224. });
  1225. $("#artist").val(artists.join(", "));
  1226. }
  1227. });
  1228. }
  1229. }
  1230. })
  1231. }
  1232. })
  1233. },
  1234. "click #volume-icon": function () {
  1235. var volume = 0;
  1236. var slider = $("#volume-slider").slider();
  1237. $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off")
  1238. if (YTPlayer !== undefined) {
  1239. YTPlayer.setVolume(volume);
  1240. localStorage.setItem("volume", volume);
  1241. $("#volume-slider").slider("setValue", volume);
  1242. }
  1243. },
  1244. "click #play": function () {
  1245. Meteor.call("resumeRoom", type);
  1246. },
  1247. "click #pause": function () {
  1248. Meteor.call("pauseRoom", type);
  1249. },
  1250. "click #skip": function () {
  1251. Meteor.call("skipSong", type);
  1252. },
  1253. "click #shuffle": function () {
  1254. Meteor.call("shufflePlaylist", type);
  1255. },
  1256. "change input": function (e) {
  1257. if (e.target && e.target.id) {
  1258. var partsOfId = e.target.id.split("-");
  1259. partsOfId[1] = partsOfId[1].charAt(0).toUpperCase() + partsOfId[1].slice(1);
  1260. var camelCase = partsOfId.join("");
  1261. Session.set(camelCase, e.target.checked);
  1262. }
  1263. },
  1264. "click #report-song-button": function () {
  1265. var room = Session.get("type");
  1266. var reportData = {};
  1267. reportData.song = Session.get("currentSong").mid;
  1268. reportData.type = [];
  1269. reportData.reason = [];
  1270. $(".report-layer-1 > .checkbox input:checked").each(function () {
  1271. reportData.type.push(this.id);
  1272. if (this.id == "report-other") {
  1273. var otherText = $(".other-textarea").val();
  1274. }
  1275. });
  1276. $(".report-layer-2 input:checked").each(function () {
  1277. reportData.reason.push(this.id);
  1278. });
  1279. console.log(reportData);
  1280. Meteor.call("submitReport", room, reportData, Session.get("id"), function () {
  1281. $("#close-modal-r").click();
  1282. });
  1283. },
  1284. "change #si_or_pl": function () {
  1285. if ($("#select_playlist").is(':selected')) {
  1286. $("#search-info").hide();
  1287. $("#playlist-import").show();
  1288. }
  1289. if ($("#select_single").is(':selected')) {
  1290. $("#search-info").show();
  1291. $("#playlist-import").hide();
  1292. }
  1293. },
  1294. "click #close-modal-a": function () {
  1295. $("#select_single").attr("selected", true);
  1296. $("#search-info").show();
  1297. $("#playlist-import").hide();
  1298. }
  1299. });
  1300. Template.room.helpers({
  1301. singleVideo: function() {
  1302. return true;
  1303. },
  1304. chat: function() {
  1305. Meteor.setTimeout(function() {
  1306. var elem = document.getElementById('chat');
  1307. if (elem !== undefined && elem !== null) {
  1308. elem.scrollTop = elem.scrollHeight;
  1309. }
  1310. }, 100);
  1311. return Chat.find({type: Session.get("type")}, {sort: {time: -1}, limit: 50 }).fetch().reverse();
  1312. },
  1313. globalChat: function() {
  1314. Meteor.setTimeout(function() {
  1315. var elem = document.getElementById('global-chat');
  1316. if (elem !== undefined && elem !== null) {
  1317. elem.scrollTop = elem.scrollHeight;
  1318. }
  1319. }, 100);
  1320. return Chat.find({type: "global"}, {sort: {time: -1}, limit: 50 }).fetch().reverse();
  1321. },
  1322. likes: function() {
  1323. var playlist = Playlists.findOne({type: Session.get("type")});
  1324. var likes = 0;
  1325. playlist.songs.forEach(function(song) {
  1326. if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
  1327. likes = song.likes;
  1328. return;
  1329. }
  1330. });
  1331. return likes;
  1332. },
  1333. dislikes: function() {
  1334. var playlist = Playlists.findOne({type: Session.get("type")});
  1335. var dislikes = 0;
  1336. playlist.songs.forEach(function(song) {
  1337. if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
  1338. dislikes = song.dislikes;
  1339. return;
  1340. }
  1341. });
  1342. return dislikes;
  1343. },
  1344. liked: function() {
  1345. if (Meteor.userId()) {
  1346. var currentSong = Session.get("currentSong");
  1347. if (currentSong && Meteor.user().profile.liked.indexOf(currentSong.mid) !== -1) {
  1348. return "active";
  1349. } else {
  1350. return "";
  1351. }
  1352. } else {
  1353. "";
  1354. }
  1355. },
  1356. disliked: function() {
  1357. if (Meteor.userId()) {
  1358. var currentSong = Session.get("currentSong");
  1359. if (currentSong && Meteor.user().profile.disliked.indexOf(currentSong.mid) !== -1) {
  1360. return "active";
  1361. } else {
  1362. return "";
  1363. }
  1364. } else {
  1365. "";
  1366. }
  1367. },
  1368. type: function() {
  1369. var parts = location.href.split('/');
  1370. var id = parts.pop().toLowerCase();
  1371. return Rooms.findOne({type: id}).display;
  1372. },
  1373. users: function() {
  1374. var parts = location.href.split('/');
  1375. var id = parts.pop().toLowerCase();
  1376. return Rooms.findOne({type: id}).users;
  1377. },
  1378. title: function(){
  1379. return Session.get("title");
  1380. },
  1381. artist: function(){
  1382. return Session.get("artist");
  1383. },
  1384. loaded: function() {
  1385. return Session.get("loaded");
  1386. },
  1387. paused: function() {
  1388. return Session.get("state") === "paused";
  1389. },
  1390. private: function() {
  1391. return Rooms.findOne({type: Session.get("type")}).private === true;
  1392. },
  1393. report: function() {
  1394. return Session.get("reportObj");
  1395. },
  1396. reportSong: function() {
  1397. return Session.get("reportSong");
  1398. },
  1399. reportTitle: function() {
  1400. return Session.get("reportTitle");
  1401. },
  1402. reportAuthor: function() {
  1403. return Session.get("reportAuthor");
  1404. },
  1405. reportDuration: function() {
  1406. return Session.get("reportDuration");
  1407. },
  1408. reportAudio: function() {
  1409. return Session.get("reportAudio");
  1410. },
  1411. reportAlbumart: function() {
  1412. return Session.get("reportAlbumart");
  1413. },
  1414. reportOther: function() {
  1415. return Session.get("reportOther");
  1416. },
  1417. currentSong: function() {
  1418. return Session.get("currentSong");
  1419. },
  1420. previousSong: function() {
  1421. return Session.get("previousSong");
  1422. },
  1423. currentSongR: function() {
  1424. return Session.get("currentSongR");
  1425. },
  1426. previousSongR: function() {
  1427. return Session.get("previousSongR");
  1428. },
  1429. reportingSong: function() {
  1430. if (Session.get("reportPrevious")) {
  1431. return Session.get("previousSongR");
  1432. } else {
  1433. return Session.get("currentSongR");
  1434. }
  1435. },
  1436. votes: function(){
  1437. return Rooms.findOne({type: Session.get("type")}).votes;
  1438. }
  1439. });
  1440. Template.room.onCreated(function () {
  1441. Chat.after.find(function(userId, selector) {
  1442. if (selector.type === "global") {
  1443. if (!$("#global-chat-tab").hasClass("active")) {
  1444. $("#global-chat-tab").addClass("unread-messages");
  1445. }
  1446. } else if(selector.type === Session.get("type")) {
  1447. if (!$("#chat-tab").hasClass("active")) {
  1448. $("#chat-tab").addClass("unread-messages");
  1449. }
  1450. }
  1451. });
  1452. Session.set("reportSong", false);
  1453. Session.set("reportTitle", false);
  1454. Session.set("reportAuthor", false);
  1455. Session.set("reportDuration", false);
  1456. Session.set("reportAudio", false);
  1457. Session.set("reportAlbumart", false);
  1458. Session.set("reportOther", false);
  1459. if (resizeSeekerbarInterval !== undefined) {
  1460. Meteor.clearInterval(resizeSeekerbarInterval);
  1461. resizeSeekerbarInterval = undefined;
  1462. }
  1463. YTPlayer = undefined;
  1464. Session.set("videoHidden", false);
  1465. var tag = document.createElement("script");
  1466. tag.src = "https://www.youtube.com/iframe_api";
  1467. var firstScriptTag = document.getElementsByTagName('script')[0];
  1468. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  1469. Session.set("singleVideo", true);
  1470. var currentSong = undefined;
  1471. var currentSongR = undefined;
  1472. function getTimeElapsed() {
  1473. if (currentSong !== undefined) {
  1474. var room = Rooms.findOne({type: type});
  1475. if (room !== undefined) {
  1476. return Date.now() - currentSong.started - room.timePaused;
  1477. }
  1478. }
  1479. return 0;
  1480. }
  1481. function getSongInfo(songData){
  1482. Session.set("title", songData.title);
  1483. Session.set("artist", songData.artist);
  1484. Session.set("id", songData.id);
  1485. $("#song-img").attr("src", songData.img);
  1486. Session.set("duration", parseInt(songData.duration));
  1487. var d = moment.duration(parseInt(songData.duration), 'seconds');
  1488. $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1489. Session.set("timeFormat", d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1490. }
  1491. function resizeSeekerbar() {
  1492. if (Session.get("state") === "playing") {
  1493. $("#seeker-bar").width(((getTimeElapsed() / 1000) / Session.get("duration") * 100) + "%");
  1494. }
  1495. }
  1496. function startSong() {
  1497. $("#time-elapsed").text("0:00");
  1498. $("#vote-skip").attr("disabled", false);
  1499. if (currentSong !== undefined) {
  1500. if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) YTPlayer.stopVideo();
  1501. var volume = localStorage.getItem("volume") || 20;
  1502. if ($("#player").length !== 1) {
  1503. $("#media-container").append('<div id="player" class="embed-responsive-item"></div>');
  1504. }
  1505. $("#player").show();
  1506. function loadVideo() {
  1507. if (!Session.get("YTLoaded")) {
  1508. Session.set("loadVideoTimeout", Meteor.setTimeout(function () {
  1509. loadVideo();
  1510. }, 500));
  1511. } else {
  1512. if (YTPlayer === undefined) {
  1513. YTPlayer = new YT.Player("player", {
  1514. height: 540,
  1515. width: 960,
  1516. videoId: currentSong.id,
  1517. playerVars: {controls: 0, iv_load_policy: 3, rel: 0, showinfo: 0},
  1518. events: {
  1519. 'onReady': function (event) {
  1520. if (currentSong.skipDuration === undefined) {
  1521. currentSong.skipDuration = 0;
  1522. }
  1523. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1524. event.target.playVideo();
  1525. event.target.setVolume(volume);
  1526. resizeSeekerbar();
  1527. },
  1528. 'onStateChange': function (event) {
  1529. if (Session.get("YTLoaded")) {
  1530. if (event.data == YT.PlayerState.PAUSED && Session.get("state") === "playing") {
  1531. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1532. event.target.playVideo();
  1533. }
  1534. if (event.data == YT.PlayerState.PLAYING && Session.get("state") === "paused") {
  1535. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1536. event.target.pauseVideo();
  1537. }
  1538. }
  1539. }
  1540. }
  1541. });
  1542. } else {
  1543. YTPlayer.loadVideoById(currentSong.id);
  1544. if (currentSong.skipDuration === undefined) {
  1545. currentSong.skipDuration = 0;
  1546. }
  1547. YTPlayer.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1548. }
  1549. Session.set("pauseVideo", false);
  1550. getSongInfo(currentSong);
  1551. }
  1552. }
  1553. loadVideo();
  1554. }
  1555. }
  1556. Session.set("loaded", false);
  1557. Meteor.subscribe("rooms", function() {
  1558. var parts = location.href.split('/');
  1559. var id = parts.pop();
  1560. var type = id.toLowerCase();
  1561. Session.set("type", type);
  1562. if (Rooms.find({type: type}).count() !== 1) {
  1563. window.location = "/";
  1564. } else {
  1565. StationSubscription = Meteor.subscribe(type);
  1566. Session.set("loaded", true);
  1567. minterval = Meteor.setInterval(function () {
  1568. var room = Rooms.findOne({type: type});
  1569. if (room !== undefined) {
  1570. if (room.state === "paused" || Session.get("pauseVideo")) {
  1571. Session.set("state", "paused");
  1572. // TODO Fix issue where sometimes nothing loads with the YT is not defined error. The error points to around this.
  1573. if (YTPlayer !== undefined && YTPlayer.getPlayerState !== undefined && YTPlayer.getPlayerState() === 1) {
  1574. YTPlayer.pauseVideo();
  1575. }
  1576. } else {
  1577. Session.set("state", "playing");
  1578. if (YTPlayer !== undefined && YTPlayer.getPlayerState !== undefined && YTPlayer.getPlayerState() !== 1) {
  1579. YTPlayer.playVideo();
  1580. }
  1581. }
  1582. }
  1583. if (room.currentSong.song !== undefined && (currentSongR === undefined || room.currentSong.started !== currentSongR.started)) {
  1584. Session.set("previousSong", currentSong);
  1585. currentSongR = room.currentSong;
  1586. currentSong = room.currentSong.song;
  1587. currentSong.started = room.currentSong.started;
  1588. Session.set("currentSong", currentSong);
  1589. Meteor.clearTimeout(Session.get("loadVideoTimeout"));
  1590. startSong();
  1591. }
  1592. if (currentSong !== undefined) {
  1593. if (room !== undefined) {
  1594. var duration = (Date.now() - currentSong.started - room.timePaused) / 1000;
  1595. var song_duration = currentSong.duration;
  1596. if (song_duration <= duration) {
  1597. Session.set("pauseVideo", true);
  1598. }
  1599. var d = moment.duration(duration, 'seconds');
  1600. if (Session.get("state") === "playing") {
  1601. $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1602. }
  1603. }
  1604. }
  1605. }, 100);
  1606. resizeSeekerbarInterval = Meteor.setInterval(function () {
  1607. resizeSeekerbar();
  1608. }, 500);
  1609. }
  1610. });
  1611. });
  1612. // Settings Template
  1613. Template.settings.events({
  1614. "click #save-settings": function() {
  1615. Meteor.call("updateSettings", $("#showRating").is(":checked"));
  1616. },
  1617. "click #delete-account": function(){
  1618. $("#delete-account").text("Click to confirm");
  1619. $("#delete-account").click(function(){
  1620. var bool = confirm("Are you sure you want to delete your account?");
  1621. if(bool) {
  1622. Meteor.call("deleteAccount");
  1623. } else{
  1624. $("#delete-account").text("Delete");
  1625. }
  1626. })
  1627. },
  1628. "click #change-password": function(){
  1629. var oldPassword = $("#old-password").val();
  1630. var newPassword= $("#new-password").val();
  1631. var confirmPassword = $("#confirm-password").val();
  1632. if(newPassword === confirmPassword){
  1633. Accounts.changePassword(oldPassword, newPassword, function(err){
  1634. if(err){
  1635. $("#old-password").val("");
  1636. $("#new-password").val("");
  1637. $("#confirm-password").val("");
  1638. $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Oh Snap! </strong>" + err.reason + "</div>").prependTo($("#head")).delay(7000).fadeOut(1000, function() { $(this).remove(); });
  1639. } else {
  1640. $("#old-password").val("");
  1641. $("#new-password").val("");
  1642. $("#confirm-password").val("");
  1643. $("<div class='alert alert-success alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Hooray!</strong> You changed your password successfully.</div>").prependTo($("#head")).delay(7000).fadeOut(1000, function() { $(this).remove(); });
  1644. }
  1645. });
  1646. }
  1647. }
  1648. });
  1649. var previewEndSongTimeout = undefined;