BackboneJS How to add JPlayer - javascript

I'm trying to add the Jquery Jplayer http://jplayer.org to my Backbone App but cant get it running. I set up the script into my RequireJS config file and my console tells me that the script is loaded. So I setup a View to test it which looks like this:
define([
'app',
'backbone',
'audioplayer'
],
function (App, Backbone, audioplayer) {
var audioplayer = App.module();
var audioplayer = Backbone.View.extend({
template: 'audioplayer',
initialize: function() {
var self = this;
$("#jquery_jplayer_1").jPlayer({
ready: function(event) {
$(this).jPlayer("setMedia", {
title: "Cro Magnon Man",
mp3: "http://jplayer.org/audio/mp3/TSP-01-Cro_magnon_man.mp3",
oga: "http://jplayer.org/audio/ogg/TSP-01-Cro_magnon_man.ogg"
});
},
swfPath: "http://jplayer.org/latest/js",
supplied: "mp3, oga"
});
}
});
return audioplayer;
}
);
and my HTML template:
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_container_1" class="jp-audio">
<div class="jp-type-single">
<div class="jp-gui jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
<li>stop</li>
<li>mute</li>
<li>unmute</li>
<li>max volume</li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-volume-bar">
<div class="jp-volume-bar-value"></div>
</div>
<div class="jp-current-time"></div>
<div class="jp-duration"></div>
</div>
<div class="jp-details">
<ul>
<li><span class="jp-title"></span></li>
</ul>
</div>
</div>
</div>
All I got is the html on my view, but I'm not able to play the track
what am I doing wrong?

So the issue is you are trying to init player with non-existing DOM. Here is a rule that any Jquery plugins should be launched after BB or Marionette View render.
So in your case u have to move $("#jquery_jplayer_1").jPlayer({}) after view render like
render: function() {
.... some render logic ....
$("#jquery_jplayer_1").jPlayer({...})
}

Related

Angular trigger js 'onclick' event

I'm trying to trigger an 'onclick' event inside of an angular controller.
<div id="galerie">
<h2>{{main.Page.title()}}</h2>
<hr>
<div class="row">
<div class="col-sm-4 col-xs-6" ng-repeat="i in page.getLans() track by $index">
<a ng-click="page.selectGalerie($index+1)" href>Playground Vol.{{$index+1}}</a>
</div>
</div>
<div id="links">
<a id="galerieLink_{{$index}}" href="img/galerie/pg{{page.galerie.volume}}/{{file}}" ng-repeat="file in page.galerie.files">{{$index}} </a>
</div>
<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls">
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev">‹</a>
<a class="next">›</a>
<a class="close">×</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
</div>
<script>
document.getElementById('links').onclick = function (event) {
event = event || window.event;
var target = event.target || event.srcElement;
var link = target.src ? target.parentNode : target;
var options = {index: link, event: event};
console.log(options);
var links = this.getElementsByTagName('a');
blueimp.Gallery(links, options);
};
</script>
I was trying it this way inside my controller:
angular.element('#galerieLink_0').trigger('click');
But it doesn't work.
Angular is not jquery. functionality belongs in the controller.
var app = angular.module("app", []);
app.controller("foo",["$scope",function($scope){
$scope.clickCount = 0;
$scope.counter = function() { $scope.clickCount++; }
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="foo">
<div ng-bind="clickCount"></div>
<button ng-click="counter()" >+1</button>
</div>

Meteor Nested Routing Using BlazeLayout

I'm trying to use flow-router to render templates within a template based on nested routes. Rereading that confused me so I'll give an example.
Main Container:
<body>
<header>
<div id="headerRight">
<span class="headerButton" id="teachButton">Teach</span>
</div>
</header>
<div class="container" style="padding: 50px;">
{{> mainLayout}}
</div>
</body>
<template name="mainLayout">
<main>
{{>Template.dynamic template=main}}
</main>
</template>
Main Container JS:
FlowRouter.route('/', {
action: function() {
BlazeLayout.render("mainLayout", {main: "base"});
}
});
FlowRouter.route('/createCourse', {
action: function() {
BlazeLayout.render("mainLayout", {main: "courseChooseCont"});
}
});
Nested Routes:
<template name="courseChooseCont">
<header>
<i class="fa fa-times" aria-hidden="true"></i>
</header>
<ul>
<li>Category</li>
<li>Availability</li>
<li>Simple Availability</li>
</ul>
{{> courseLayout}}
<div name="courseMain"></div>
<div class="bottomBar">
<div class="back">Back</div>
<div class="next">Next</div>
</div>
</template>
<template name="courseLayout">
<main>
{{>Template.dynamic template=content}}
</main>
</template>
Nested Routes JS:
var createCourse = FlowRouter.group({
prefix: '/createCourse'
});
createCourse.route('/', {
action: function() {
BlazeLayout.render("courseLayout", {content: "base"});
}
});
createCourse.route('/availabilityCheck', {
action: function() {
BlazeLayout.render("courseLayout", {content: "availabilityCheck"});
}
});
createCourse.route('/simpleAvailability', {
action: function() {
BlazeLayout.render("courseLayout", {content: "simpleAvailability"});
}
});
When I render the nested routes it seems to overwrite the "courseChooseCont" template that should be housing the nested template and is simply displaying the nested template inside the 'Main Container'.
I'm assuming I'm using BlazeLayout wrong but I can't seem to find a solution.

Compile error for Angular JS with js/ajax.js and index.html

When I compile my code there is an error with angular.
The code is written from a book, and it works when I load the page using the code at the end of the question.
There seems to be two issues from what I have read. Where do I put the $scope and $compile code?
Mostly, the question is how do I load a document ready trigger with a button for angular JS?
Or should I always load the angular js and hide the code?
<div id="myTabs">
<div class="menu">
<ul class= "tabs">
<li >LIST</li>
<li >GRID</li>
<li >GRID</li>
</ul>
</div>
<div class="container" style="margin-top:100px">
<div id="a">
</div>
<div id="b">
<ul class="gallery-items" id="grid">
</ul>
</div>
<div id="c" >
<div ng-controller="myController">
<div ng-repeat="item in items">
<img ng-src="{{item.img}}" />
{{item.description}}<br>
Rating: {{item.rating}} stars<br>
<span ng-repeat="idx in stars"
ng-class=
"{true: 'star', false: 'empty'}[idx <= item.rating]"
ng-click="adjustRating(item, idx)">
</span>
<hr>
</div>
</div>
</div>
</div>
ajax.js has a function that calls the #c tab to load
$(document).ready(function(){
$('#listC').click(function(){
angular.module('myApp', [])
.controller('myController', ['$scope', function($scope) {
$scope.stars = [1,2,3,4,5];
$scope.items = [100];
$.ajax({
type:'post',
url:'changeView.php',
data:{action: 'getGrid'},
success:function(data){
var data = JSON.parse(data);
for (i=0;i<data.length;i++) {
var imageLI = makeImage(data[i]['imageID'], data[i]['name'], data[i]['desc']);
$scope.items[i] = imageLI;
}
}
});
console.log($scope.items);
$scope.adjustRating = function(item, value){
item.rating = value;
};
}]);
});
$('#listC').trigger('click');
function makeImage(ID, name, description){
var image = {
description: description,
img: '../uploads/'+name,
rating: 4
}
return image;

Render Backbone View on click (via Router push state)

I've got an app with 3 pages which I'm trying to render on click. The first page is a landing page. The other two should be rendered upon clicking a link. They are all contained inside of the same container div#modal-content
My HTML is as follows:
<script type="text/x-handlebars-template" id="landingPage">
<div>
<div class="auth-wrapper">
<div class="logo">
<img src="img/login/logo-landing.png"/>
</div>
<div class="to-auth-buttons-wrapper">
<a class="btn-to-auth btn-login" href="#signup-page">Sign Up</a>
<a class="btn-to-auth btn-signup" href="#login-page">Log In</a>
</div>
</div>
</div>
</script>
My router function is as follows:
var Approuter = Backbone.Router.extend({
initialize: function() {
console.log('router initialized');
Backbone.history.start({ pushState: true });
},
routes: {
'': 'main',
'signup-page' : 'signup',
'login-page' : 'login'
},
main: function() {
this.landing = new LandingView({ el: $('#modal-content') });
slider.slidePage(this.landing.$el);
},
signup: function() {
this.signuppage = new SignUpView({ el: $('#modal-content') });
console.log("LANDING VIEW: Signup clicked");
},
login: function() {
this.loginpage = new LoginView({ el: $('#modal-content') });
console.log("LANDING VIEW: Login clicked");
}
});
And the view files are as follows:
var SignUpView = Backbone.View.extend({
initialize: function() {
this.render();
},
render: function() {
var template = Handlebars.compile($('#signUpPage').html());
this.$el.html(template);
},
});
and
var LoginView = Backbone.View.extend({
initialize: function() {
this.render();
},
render: function() {
var template = Handlebars.compile($('#loginPage').html());
this.$el.html(template);
},
});
Additionally, here are my templates:
<div id="modal-content">
<script type="text/x-handlebars-template" id="landingPage">
<div>
<div class="auth-wrapper">
<div class="logo">
<img src="img/login/logo-landing.png"/>
</div>
<div class="to-auth-buttons-wrapper">
<a class="btn-to-auth btn-login" href="#/signup-page">Sign Up</a>
<a class="btn-to-auth btn-signup" href="#/login-page">Log In</a>
</div>
</div>
</div>
</script>
<script type="text/x-handlebars-template" id="signUpPage">
<div>
<div class="header">
Back
</div>
<div class="auth-wrapper">
<div class="logo">
<img src="img/login/logo-landing.png"/>
</div>
<form method="post" id="userSignUp">
<input class="form-control input-signin" type="text" name="username" placeholder="Name" id="userName">
<input class="form-control input-signin" type="text" name="useremail" placeholder="Email" id="userEmail">
<input class="form-control input-signin" type="text" name="userpass" placeholder="Password" id="userPassword">
<a class="btn-to-auth btn-login js-btn-login">Sign Up</a>
</form>
</div>
</div>
</script>
<script type="text/x-handlebars-template" id="loginPage">
<div>
<div class="header">
Back
</div>
<div class="auth-wrapper">
<div class="logo">
<img src="img/login/logo-landing.png"/>
</div>
<form method="post" id="userSignIn">
<input class="form-control input-signin" type="text" name="useremail" placeholder="Email" id="userEmail">
<input class="form-control input-signin" type="password" name="userpass" placeholder="Password" id="userPassword">
<a class="btn-to-auth btn-login js-btn-login">Log In</a>
</form>
</div>
</div>
</script>
</div>
My Problem
Upon clicking the a#signup-page or a#login-page links, I can see the url change to "localhost/#signup-page", but the view is not being rendered.
BUT
When I refresh the page at localhost/#signup-page or localhost/#login-page, I see the views are rendered.
Where am I going wrong?
Please take a look at the code above:
<html>
<body>
<div class="action">
<a name="routeOne" href="#routeTwo">routeOne</a>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<a name="routeTwo" href="#routeOne">routeTwo</a>
</div>
<div class="output"></div>
<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/underscore.js"></script>
<script type="text/javascript" src="lib/backbone.js"></script>
<script type="text/javascript">
var Approuter = Backbone.Router.extend({
initialize: function() {
console.log('router initialized');
Backbone.history.start({pushState:true});
},
routes: {
'': 'main',
'routeOne' : 'routeOne',
'routeTwo' : 'routeTwo'
},
main: function() {
console.log("main");
},
routeOne: function() {
console.log("routeOne");
},
routeTwo: function() {
console.log("routeTwo");
}
});
var routes = new Approuter();
</script>
</body>
</html>
Edit1: Differences between Routes and pushState
Backbone Routes enable you to monitoring hasChange history events (changes in url) and trigger some js code when found some change at url (http://localhost/backbone-test/#someRoute), That's amazing because we can trigger some complex actions done by user at your web site, just calling an url.
pushState enable you to hide this '#' hash and turn your url more readable, but as the backbone documentation said
"if you have a route of /documents/100, your web server must be able
to serve that page, if the browser visits that URL directly."
Then, if you use pushState:true your url become more readable, http://localhost/backbone-test/#someRoute to http://localhost/backbone-test/someRoute but you need to create a back-end to answer directly access to you readable url.
When pushState is true and you call href="#someRoute" the browser understand this as a html anchor.

issue with multiple instances of jPlayer in FF and IE

i have a page that calls for multiple instances of jplayer. everything works fine in Chrome/Safari, but in FF and IE, the first instance of the player loads the 'play' button and progress bar, but the audio doesn't work.
for the 2nd and 3rd instance, the 'play' button is there, but there's no progress bar, and no audio. i'm 90% sure this is an issue with my js file, which looks like this:
$(document).ready(function() {
$("#jquery_jplayer_1").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: "media/demo.mp3"
});
},
ended: function (event) {
$(this);
},
supplied: "mp3"
}).bind($.jPlayer.event.play, function() { // Using a jPlayer event to avoid both jPlayers playing together.
$(this).jPlayer("pauseOthers");
});
$("#jquery_jplayer_2").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: "media/English_Commercial Demo.mp3"
});
},
ended: function (event) {
$(this);
},
cssSelectorAncestor:"#jp_interface_2",
supplied: "mp3"
}).bind($.jPlayer.event.play, function() {
$(this).jPlayer("pauseOthers");
});
$("#jquery_jplayer_3").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: "media/English_Narration_Demo.mp3"
});
},
ended: function (event) {
$(this);
},
cssSelectorAncestor:"#jp_interface_3",
supplied: "mp3"
}).bind($.jPlayer.event.play, function() {
$(this).jPlayer("pauseOthers");
});
and heres the html:
<div class="players">
<div class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_interface_1" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
</div>
</div>
</div>
<div class="players">
<div class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_2" class="jp-jplayer">
</div>
<div id="jp_interface_2" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress2">
<div class="jp-seek-bar">
<div class="jp-play-bar">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_3" class="jp-jplayer"></div>
<div id="jp_interface_3" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress2">
<div class="jp-seek-bar">
<div class="jp-play-bar">
</div>
</div>
</div>
</div>
</div>
</div>
i've removed some of the inline styling and other extraneous things like Download buttons, but can add the full code if this is too confusing/ugly (i'm sure theres an extra in there somewhere).
Neither Firefox nor IE will play an MP3 file unless you supply a valid swfPath.
You are supplying a .jp-interface element as the CSS Ancestor but this is incorrect - you need to supply "the cssSelector of an ancestor of all cssSelectors" (see the docs)
try the changes to your code i made in this Fiddle - see if it works for you.
the new HTML markup looks like this
<div class="players">
<div id="jp_container_1" class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_1" class="jp-jplayer"></div>
<div id="jp_interface_1" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="players">
<div id="jp_container_2" class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_2" class="jp-jplayer"></div>
<div id="jp_interface_2" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="players">
<div id="jp_container_3" class="jp-audio">
<div class="jp-type-single">
<div id="jquery_jplayer_3" class="jp-jplayer"></div>
<div id="jp_interface_3" class="jp-interface">
<ul class="jp-controls">
<li>play</li>
<li>pause</li>
</ul>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
</div>
</div>
</div>
</div>
and the new Javascript:
$("#jquery_jplayer_1").jPlayer({
swfPath: "http://www.jplayer.org/latest/js/Jplayer.swf",
ready: function () {
$(this).jPlayer("setMedia", { mp3: "http://www.freesfx.co.uk/rx2/mp3s/3/2665_1315685839.mp3" });
},
play: function () { $(this).jPlayer("pauseOthers"); },
supplied: "mp3"
});
$("#jquery_jplayer_2").jPlayer({
swfPath: "http://www.jplayer.org/latest/js/Jplayer.swf",
ready: function () {
$(this).jPlayer("setMedia", { mp3: "http://www.freesfx.co.uk/rx2/mp3s/3/2664_1315685834.mp3" });
},
play: function () { $(this).jPlayer("pauseOthers"); },
cssSelectorAncestor:"#jp_interface_2",
supplied: "mp3"
});
$("#jquery_jplayer_3").jPlayer({
swfPath: "http://www.jplayer.org/latest/js/Jplayer.swf",
ready: function () {
$(this).jPlayer("setMedia", { mp3: "http://www.freesfx.co.uk/rx2/mp3s/3/2660_1315685820.mp3" });
},
play: function () { $(this).jPlayer("pauseOthers"); },
cssSelectorAncestor:"#jp_interface_3",
supplied: "mp3"
});
FF doesn't actually play MP3 files but instead plays OGG files. If the demo songs in the above corrected example code from Lloyd works but when you change the MP3 path to an MP3 file on your server and it doesn't work then make sure your server has the MIME type "application/ogg" (without quotes). The server will see the MP3 file in the code and play it as if it were an OGG application file. I'm not sure why this works on my server. This is not my discovery but rather a tip I found on the Internet. Hope it works for you.
Also make sure the HTML head has Lloyd's new Javascript and is wrapped like this:
<head>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.6.4.js'></script>
<script type='text/javascript' src="http://www.jplayer.org/latest/js/jquery.jplayer.min.js"></script>
<script type='text/javascript'>
//<![CDATA[
$(function(){
Lloyd's javascript code goes here
});
//]]>
</script>
</head>
Tip: Click on Lloyd's "fiddle" link - the "Play" links work.
i don't know why it dosn't work in ie... but opera and ff don't play mp3 file
swfPath: "js",
supplied: "mp3",
wmode: "window"
In order to play them, there is Jplayer.swf file in js folder. You should write swfPath: "write the track of Jplayer.swf"...

Categories