Converted uses of bindonce to Angular one-time bindings.

This commit is contained in:
Peter Deltchev 2016-02-14 02:53:27 -08:00
parent 7ab0b907c5
commit cbce336478
21 changed files with 172 additions and 485 deletions

View file

@ -439,6 +439,7 @@ class Track extends Model implements Searchable
$returnValue = self::mapPrivateTrackSummary($track);
$returnValue['album_id'] = $track->album_id;
$returnValue['show_songs'] = $showSongs;
$returnValue['cover_id'] = $track->cover_id;
$returnValue['real_cover_url'] = $track->getCoverUrl(Image::NORMAL);
$returnValue['cover_url'] = $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null;
$returnValue['released_at'] = $track->released_at ? $track->released_at->toDateString() : null;

View file

@ -1,64 +1,66 @@
<div class="resource-details album-details" bindonce="album">
<div class="resource-details album-details">
<ul class="dropdowns">
<li class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle" ng-disabled="album.is_downloadable == 0" auto-close="outsideClick">
Downloads
</a>
<ul class="dropdown-menu" ng-show="album.is_downloadable == 1">
<li bindonce ng-repeat="format in album.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="!format.isCacheable" bo-href="format.url">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<ul class="dropdown-menu" ng-show="::album.is_downloadable == 1">
<li ng-repeat="format in ::album.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="::!format.isCacheable" ng-href="{{::format.url}}">
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
<a ng-if="format.isCacheable" ng-click="getCachedAlbum(album.id, format.name);" href="">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<a ng-if="::format.isCacheable" ng-click="getCachedAlbum(album.id, format.name);" href="">
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
</li>
<li ng-show="isInProgress" class="cache-loading"><img src="/images/loading.gif" /></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This may take up to a few minutes.</small></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This may take a few minutes.</small></li>
</ul>
</li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share</a></li>
<li><pfm-favourite-button resource="album" type="album"></pfm-favourite-button></li>
<li bo-show="album.permissions.edit"><a class="btn btn-small" bo-href="'/account/albums/edit/' + album.id">Edit</a></li>
<li><pfm-favourite-button resource="::album" type="album"></pfm-favourite-button></li>
<li ng-show="::album.permissions.edit"><a class="btn btn-small" ng-href="/account/albums/edit/{{::album.id}}">Edit</a></li>
</ul>
<header>
<h1 bo-text="album.title"></h1>
<h1>{{::album.title}}</h1>
<h2>
by: <a bo-href="album.user.url" bo-text="album.user.name"></a>
by: <a ng-href="{{::album.user.url}}">{{::album.user.name}}</a>
</h2>
</header>
<div class="stretch-to-bottom details-columns">
<div class="right">
<a colorbox ng-href="{{album.covers.original}}" pfm-eat-click><img class="cover" pfm-src-loader="album.covers.normal" pfm-src-size="normal" /></a>
<a colorbox ng-href="{{::album.covers.original}}" pfm-eat-click>
<img class="cover" pfm-src-loader="::album.covers.normal" pfm-src-size="normal" />
</a>
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="album.share.tumblrUrl" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('/images/tumblr-share.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{album.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" bo-src="album.share.twitterUrl" style="width:130px; height:20px;"></iframe>
<a class="tumblr" ng-href="{{::album.share.tumblrUrl}}" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('/images/tumblr-share.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{::album.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" ng-src="{{::album.share.twitterUrl}}" style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Published: <strong bo-text="album.created_at | date:'medium'"></strong></li>
<li>Views: <strong bo-text="album.stats.views"></strong></li>
<li>Downloads: <strong bo-text="album.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="album.stats.favourites"></strong></li>
<li>Published: <strong>{{::album.created_at | date:'medium'}}</strong></li>
<li>Views: <strong>{{::album.stats.views}}</strong></li>
<li>Downloads: <strong>{{::album.stats.downloads}}</strong></li>
<li>Favourites: <strong>{{::album.stats.favourites}}</strong></li>
</ul>
</div>
<div class="left">
<div class="description" bo-show="album.description.length">
<div class="description" ng-show="::album.description.length">
<h2>Description</h2>
<p marked="album.description"></p>
<p marked="::album.description"></p>
</div>
<h2>Tracks</h2>
<pfm-tracks-list tracks="album.tracks" class="condensed no-artist"></pfm-tracks-list>
<pfm-tracks-list tracks="::album.tracks" class="condensed no-artist"></pfm-tracks-list>
<pfm-comments type="album" resource="album"></pfm-comments>
<pfm-comments type="album" resource="::album"></pfm-comments>
</div>
</div>
</div>

View file

@ -1,18 +1,20 @@
<div class="resource-details artist-details" ng-class="{'x-archived': artist.is_archived}" bindonce="artist">
<div class="resource-details artist-details" ng-class="::{'x-archived': artist.is_archived}">
<ul class="dropdowns">
<li class="dropdown">
<a href="#" class="btn btn-small" ng-class="{'btn-primary': !artist.user_data.is_following}" ng-show="auth.isLogged && auth.user.id != artist.id" pfm-eat-click ng-click="toggleFollow()">
<a href="#" class="btn btn-small" ng-class="{'btn-primary': !artist.user_data.is_following}" ng-show="::auth.isLogged && auth.user.id != artist.id" pfm-eat-click ng-click="toggleFollow()">
<span ng-hide="artist.user_data.is_following">Follow</span>
<span ng-show="artist.user_data.is_following">Following!</span>
</a>
</li>
</ul>
<header>
<h1 bo-text="artist.name"></h1>
<h1>{{::artist.name}}</h1>
<ul class="tabs">
<li ng-class="{active: stateIncludes('content.artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
<li ng-class="{active: stateIncludes('content.artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
<li ng-hide="artist.is_archived" ng-class="{active: stateIncludes('content.artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
<li ng-class="{active: stateIncludes('content.artist.profile')}"><a ng-href="{{::artist.slug}}">Profile</a></li>
<li ng-class="{active: stateIncludes('content.artist.content')}"><a ng-href="{{::artist.slug}}/content">Content</a></li>
<li ng-hide="::artist.is_archived" ng-class="::{active: stateIncludes('content.artist.favourites')}">
<a ng-href="{{::artist.slug}}/favourites">Favourites</a>
</li>
</ul>
</header>
<div class="stretch-to-bottom">

View file

@ -1,14 +1,14 @@
<div ng-show="content.albums.length">
<div ng-show="::content.albums.length">
<h2>Albums</h2>
<pfm-albums-list albums="content.albums"></pfm-albums-list>
<pfm-albums-list albums="::content.albums"></pfm-albums-list>
</div>
<div ng-show="content.singles.length">
<div ng-show="::content.singles.length">
<h2>Singles</h2>
<pfm-tracks-list tracks="content.singles" class="four-columns no-artist"></pfm-tracks-list>
<pfm-tracks-list tracks="::content.singles" class="four-columns no-artist"></pfm-tracks-list>
</div>
<div ng-show="content.albumTracks.length">
<div ng-show="::content.albumTracks.length">
<h2>Part of an Album</h2>
<pfm-tracks-list tracks="content.albumTracks" class="four-columns no-artist"></pfm-tracks-list>
<pfm-tracks-list tracks="::content.albumTracks" class="four-columns no-artist"></pfm-tracks-list>
</div>

View file

@ -1,23 +1,23 @@
<div class="row-fluid">
<div class="span6">
<div bo-show="artist.bio.trim().length">
<div ng-show="::artist.bio.trim().length">
<h2>Bio</h2>
<div class="description">
<p marked="artist.bio"></p>
<p marked="::artist.bio"></p>
</div>
</div>
<div bo-show="artist.is_archived">
<div ng-show="::artist.is_archived">
<h2>Archived profile</h2>
<p>This is an archived artist profile that&#39;s part of the MLP
Music Archive. If it&#39;s yours, email
<a href="mailto:feld0@pony.fm" target="_blank">feld0@pony.fm</a> to claim it!</p>
</div>
<pfm-comments type="user" resource="artist"></pfm-comments>
<pfm-comments type="user" resource="::artist"></pfm-comments>
</div>
<div class="span6 cover-image">
<h2>Recent Tracks</h2>
<pfm-tracks-list tracks="artist.latest_tracks" class="two-columns no-artist" />
<pfm-tracks-list tracks="::artist.latest_tracks" class="two-columns no-artist" />
</div>
</div>

View file

@ -1,16 +1,16 @@
<ul class="albums-listing {{class}}">
<li bindonce ng-repeat="album in albums track by album.id">
<a bo-href="album.url">
<img class="image" pfm-src-loader="album.covers.small" pfm-src-size="small" />
<ul class="albums-listing {{::class}}">
<li ng-repeat="album in albums track by album.id">
<a ng-href="{{::album.url}}">
<img class="image" pfm-src-loader="::album.covers.small" pfm-src-size="small" />
<span class="info">
<span class="title" bo-text="album.title"></span>
<span class="title">{{::album.title}}</span>
<span class="published">
by <span bo-text="album.user.name"></span>
by <span>{{::album.user.name}}</span>
</span>
<span class="stats">
<strong bo-text="album.stats.favourites"></strong> <i class="icon-star"></i>
<strong bo-text="album.stats.comments"></strong> <i class="icon-comment"></i>
<strong bo-text="album.stats.downloads"></strong> <i class="icon-download"></i>
<strong>{{::album.stats.favourites}}</strong> <i class="icon-star"></i>
<strong>{{::album.stats.comments}}</strong> <i class="icon-comment"></i>
<strong>{{::album.stats.downloads}}</strong> <i class="icon-download"></i>
</span>
</span>
</a>

View file

@ -1,21 +1,20 @@
<div class="comments" bindonce>
<div class="comments">
<h2>All Comments ({{resource.comments.length}})</h2>
<form class="pfm-form" ng-submit="addComment()" ng-show="auth.isLogged">
<form class="pfm-form" ng-submit="addComment()" ng-show="::auth.isLogged">
<div class="form-row">
<input type="text" ng-model="content" placeholder="Write a comment..." />
<input type="text" ng-model="content" placeholder="Write a comment&hellip;" />
</div>
</form>
<ul>
<li ng-show="resource.comments.length == 0" class="empty">
There are no comments yet!
</li>
<li bindonce ng-repeat="comment in resource.comments">
<img pfm-src-loader="comment.user.avatars.thumbnail" pfm-src-size="thumbnail" />
<li ng-repeat="comment in resource.comments">
<img pfm-src-loader="::comment.user.avatars.thumbnail" pfm-src-size="thumbnail" />
<div class="content">
<a bo-href="comment.user.url" bo-text="comment.user.name"></a>
<a ng-href="{{::comment.user.url}}">{{::comment.user.name}}</a>
<span marked="comment.content"></span>
<div class="meta" bo-text="comment.created_at.date | momentFromNow">
</div>
<div class="meta">{{::comment.created_at.date | momentFromNow}}</div>
</div>
</li>
</ul>

View file

@ -1,16 +1,16 @@
<ul class="playlists-listing {{class}}">
<li bindonce ng-repeat="playlist in playlists track by playlist.id">
<a bo-href="playlist.url">
<img class="image" pfm-src-loader="playlist.covers.small" pfm-src-size="small" />
<ul class="playlists-listing {{::class}}">
<li ng-repeat="playlist in playlists track by playlist.id">
<a ng-href="{{::playlist.url}}">
<img class="image" pfm-src-loader="::playlist.covers.small" pfm-src-size="small" />
<span class="info">
<span class="title" bo-text="playlist.title"></span>
<span class="title">{{::playlist.title}}</span>
<span class="published">
by <span bo-text="playlist.user.name"></span>
by {{::playlist.user.name}}
</span>
<span class="stats">
<strong bo-text="playlist.stats.favourites"></strong> <i class="icon-star"></i>
<strong bo-text="playlist.stats.comments"></strong> <i class="icon-comment"></i>
<strong bo-text="playlist.stats.downloads"></strong> <i class="icon-download"></i>
<strong>{{::playlist.stats.favourites}}</strong> <i class="icon-star"></i>
<strong>{{::playlist.stats.comments}}</strong> <i class="icon-comment"></i>
<strong>{{::playlist.stats.downloads}}</strong> <i class="icon-download"></i>
</span>
</span>
</a>

View file

@ -82,7 +82,7 @@
<div class="row-fluid">
<div class="form-row span6" ng-class="{'has-error': errors.cover != null}">
<label class="strong">Track Cover: </label>
<pfm-image-upload set-image="setCover" image="track.cover" />
<pfm-image-upload set-image="setCover" image="track.cover_url" />
</div>
<div class="form-row span6" ng-class="{'has-error': errors.released_at != null}">
<label for="released_at" class="strong">Release Date:</label>

View file

@ -3,5 +3,5 @@
<i class="icon-play" ng-show="!track.isPlaying"></i>
<i class="icon-pause" ng-hide="!track.isPlaying"></i>
</a>
<img pfm-src-loader="track.covers.thumbnail" pfm-src-size="thumbnail" />
<img pfm-src-loader="::track.covers.thumbnail" pfm-src-size="thumbnail" />
</div>

View file

@ -1,5 +1,5 @@
<ul class="tracks-listing {{class}}">
<li bindonce ng-repeat="track in tracks track by track.id" ng-class="{'can-favourite': auth.isLogged, 'is-favourited': auth.isLogged && track.user_data.is_favourited, 'is-playing': track.isPlaying, 'has-played': auth.isLogged && track.user_data.views}">
<li ng-repeat="track in tracks track by track.id" ng-class="{'can-favourite': auth.isLogged, 'is-favourited': auth.isLogged && track.user_data.is_favourited, 'is-playing': track.isPlaying, 'has-played': auth.isLogged && track.user_data.views}">
<div class="image">
<a href="#" class="play-button" pfm-eat-click ng-click="play(track)">
<i class="icon-play" ng-show="!track.isPlaying"></i>
@ -8,17 +8,19 @@
<img pfm-src-loader="track.covers.thumbnail" pfm-src-size="thumbnail" />
</div>
<div class="icons">
<span><i bo-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a pfm-eat-click class="icon-favourite" href="#" ng-click="toggleFavourite(track)" bo-show="auth.isLogged"><i class="icon-star-empty"></i></a>
<span><i ng-class="::{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a pfm-eat-click class="icon-favourite" href="#" ng-click="toggleFavourite(track)" ng-show="::auth.isLogged">
<i class="icon-star-empty"></i>
</a>
</div>
<a class="info" bo-href="track.url">
<span class="title" bo-text="track.title"></span>
<span class="stats" bo-title="track.stats.favourites +' Favourites / '+ track.stats.comments +' Comments / '+ track.stats.plays +' Plays'">
<strong bo-text="track.stats.favourites"></strong>f
<strong bo-text="track.stats.comments"></strong>c
<strong bo-text="track.stats.plays"></strong>p
<a class="info" ng-href="{{::track.url}}">
<span class="title">{{::track.title}}</span>
<span class="stats" title="track.stats.favourites +' Favourites / '+ track.stats.comments +' Comments / '+ track.stats.plays +' Plays'">
<strong>{{::track.stats.favourites}}</strong>f
<strong>{{::track.stats.comments}}</strong>c
<strong>{{::track.stats.plays}}</strong>p
</span>
<span class="artist" bo-text="track.user.name + ' / ' + track.genre.name"></span>
<span class="artist">{{::track.user.name}} / {{::track.genre.name}}</span>
</a>
</li>
<li ng-if="!tracks.length" class="empty">

View file

@ -1,13 +1,13 @@
<ul class="users-listing">
<li class="artist" ng-class="{'x-archived': user.is_archived}" ng-repeat="user in users track by user.id" bindonce>
<a bo-href="user.url">
<li class="artist" ng-class="{'x-archived': user.is_archived}" ng-repeat="user in users track by user.id">
<a ng-href="{{::user.url}}">
<img class="image" pfm-src-loader="user.avatars.small" pfm-src-size="small" />
<span class="info">
<span class="title" bo-text="user.name"></span>
<span class="title">{{::user.name}}</span>
<span ng-hide="user.is_archived" class="published">
joined <span bo-text="user.created_at.date | momentFromNow"></span>
joined {{::user.created_at.date | momentFromNow}}
</span>
<span ng-show="user.is_archived" class="published">
<span ng-show="::user.is_archived" class="published">
archived artist
</span>
</span>

View file

@ -1,63 +1,65 @@
<div class="resource-details playlist-details" bindonce="playlist">
<div class="resource-details playlist-details">
<ul class="dropdowns">
<li class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle" auto-close="outsideClick">
Downloads
</a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="format in playlist.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="!format.isCacheable" bo-href="format.url">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<li ng-repeat="format in ::playlist.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="::!format.isCacheable" ng-href="{{::format.url}}">
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
<a ng-if="format.isCacheable" ng-click="getCachedPlaylist(playlist.id, format.name);" href="">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<a ng-if="::format.isCacheable" ng-click="getCachedPlaylist(playlist.id, format.name);" href="">
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
</li>
<li ng-show="isInProgress" class="cache-loading"><img src="/images/loading.gif" /></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This may take up to a few minutes.</small></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This may take a few minutes.</small></li>
</ul>
</li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share</a></li>
<li><pfm-favourite-button resource="playlist" type="playlist"></pfm-favourite-button></li>
<li><pfm-favourite-button resource="::playlist" type="playlist"></pfm-favourite-button></li>
</ul>
<header>
<h1 bo-text="playlist.title"></h1>
<h1>{{::playlist.title}}</h1>
<h2>
created by: <a bo-href="playlist.user.url" bo-text="playlist.user.name"></a>
curated by: <a ng-href="{{::playlist.user.url}}">{{::playlist.user.name}}</a>
</h2>
</header>
<div class="stretch-to-bottom details-columns">
<div class="right">
<a colorbox ng-href="{{playlist.covers.original}}" pfm-eat-click><img class="cover" pfm-src-loader="playlist.covers.normal" pfm-src-size="normal" /></a>
<a colorbox ng-href="{{::playlist.covers.original}}" pfm-eat-click>
<img class="cover" pfm-src-loader="::playlist.covers.normal" pfm-src-size="normal" />
</a>
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="playlist.share.tumblrUrl" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('/images/tumblr-share.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{playlist.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" bo-src="playlist.share.twitterUrl" style="width:130px; height:20px;"></iframe>
<a class="tumblr" ng-href="{{::playlist.share.tumblrUrl}}" title="Share on Tumblr" style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('/images/tumblr-share.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{::playlist.url}}" data-width="450" data-layout="button_count" data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0" scrolling="no" ng-src="{{::playlist.share.twitterUrl}}" style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Created: <strong bo-text="playlist.created_at | date:'medium'"></strong></li>
<li>Views: <strong bo-text="playlist.stats.views"></strong></li>
<li>Downloads: <strong bo-text="playlist.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="playlist.stats.favourites"></strong></li>
<li>Created: <strong>{{::playlist.created_at | date:'medium'}}</strong></li>
<li>Views: <strong>{{::playlist.stats.views}}</strong></li>
<li>Downloads: <strong>{{::playlist.stats.downloads}}</strong></li>
<li>Favourites: <strong>{{::playlist.stats.favourites}}</strong></li>
</ul>
</div>
<div class="left">
<div class="description" bo-show="playlist.description.length">
<div class="description" ng-show="::playlist.description.length">
<h2>Description</h2>
<p marked="playlist.description"></p>
<p marked="::playlist.description"></p>
</div>
<h2>Tracks</h2>
<pfm-tracks-list tracks="playlist.tracks"></pfm-tracks-list>
<pfm-tracks-list tracks="::playlist.tracks"></pfm-tracks-list>
<pfm-comments type="playlist" resource="playlist"></pfm-comments>
<pfm-comments type="playlist" resource="::playlist"></pfm-comments>
</div>
</div>
</div>

View file

@ -1,5 +1,5 @@
<div>
<h1>PUT EDIT STUFF HERE</h1>
<a bo-href="track.url">Cancel</a>
<a ng-href="{{::track.url}}">Cancel</a>
</div>

View file

@ -1,34 +1,34 @@
<div class="resource-details track-details" bindonce="track">
<div class="resource-details track-details">
<ul class="dropdowns">
<li class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle" ng-disabled="track.is_downloadable == 0" auto-close="outsideClick">
<a href="#" class="btn btn-small btn-info dropdown-toggle" ng-disabled="::track.is_downloadable == 0" auto-close="outsideClick">
Downloads
</a>
<ul class="dropdown-menu" ng-show="track.is_downloadable == 1">
<li bindonce ng-repeat="format in track.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="!format.isCacheable" bo-href="format.url">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<ul class="dropdown-menu" ng-show="::track.is_downloadable == 1">
<li ng-repeat="format in ::track.formats" ng-hide="isInProgress">
<a target="_blank" ng-if="::!format.isCacheable" ng-href="{{::format.url}}">
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
<a ng-if="format.isCacheable" ng-click="getCachedTrack(track.id, format.name);" href="">
<span bo-text="format.name"></span>
<small bo-text="'(' + format.size + ')'"></small>
<span>{{::format.name}}</span>
<small>({{::format.size}})</small>
</a>
</li>
<li ng-show="isInProgress" class="cache-loading"><img src="/images/loading.gif" /></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This'll take a few seconds.</small></li>
<li ng-show="isInProgress" class="cache-loading"><small>We&#39;re getting your download ready! This&#39;ll take a few seconds.</small></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="btn btn-small dropdown-toggle" ng-show="auth.isLogged">Add to Playlist</a>
<a href="#" class="btn btn-small dropdown-toggle" ng-show="::auth.isLogged">Add to Playlist</a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="playlist in playlists">
<li ng-repeat="playlist in playlists">
<a ng-class="{disabled: playlist.message, 'btn-success': playlist.message}"
bo-href="playlist.url"
ng-href="{{::playlist.url}}"
pfm-eat-click
ng-click="addToPlaylist(playlist); $event.stopPropagation()"
>
<span ng-hide="playlist.message" bo-text="playlist.title"></span>
<span ng-hide="playlist.message">{{::playlist.title}}</span>
<span ng-show="playlist.message">{{playlist.message}}</span>
</a>
</li>
@ -37,19 +37,19 @@
</li>
<li><a href="#" class="btn" pfm-eat-click ng-click="share()">Share or Embed</a></li>
<li><pfm-favourite-button resource="track" type="track"></pfm-favourite-button></li>
<li bo-show="track.permissions.edit"><a class="btn btn-small" bo-href="'/account/tracks/edit/' + track.id">Edit</a></li>
<li><pfm-favourite-button resource="::track" type="track"></pfm-favourite-button></li>
<li ng-show="::track.permissions.edit"><a class="btn btn-small" ng-href="/account/tracks/edit/{{::track.id}}">Edit</a></li>
</ul>
<header>
<pfm-track-player track="track"></pfm-track-player>
<h1 bo-text="track.title"></h1>
<pfm-track-player track="::track"></pfm-track-player>
<h1>{{::track.title}}</h1>
<h2>
<span bo-show="track.album">
from: <a bo-href="track.album.url" bo-text="track.album.title"></a>
<span ng-show="::track.album">
from: <a ng-href="{{::track.album.url}}" ng-text="{{::track.album.title}}"></a>
</span>
by: <a bo-href="track.user.url" bo-text="track.user.name"></a>
by: <a ng-href="{{::track.user.url}}">{{::track.user.name}}</a>
</h2>
</header>

View file

@ -5,11 +5,11 @@
</a>
<a class="btn" pfm-eat-click ng-click="clearFilter('trackTypes')"><i class="icon-remove"></i></a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="type in filters.trackTypes.values track by type.id"
<li ng-repeat="type in ::filters.trackTypes.values track by type.id"
ng-class="{selected: query.isIdSelected('trackTypes', type.id)}"
>
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('trackTypes', type.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
<a pfm-eat-click href="#" ng-click="setListFilter('trackTypes', type.id);" bo-text="type.title"></a>
<a pfm-eat-click href="#" ng-click="setListFilter('trackTypes', type.id);">{{::type.title}}</a>
</li>
</ul>
</li>
@ -19,11 +19,11 @@
</a>
<a class="btn" pfm-eat-click ng-click="clearFilter('showSongs')"><i class="icon-remove"></i></a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="song in filters.showSongs.values track by song.id"
<li ng-repeat="song in ::filters.showSongs.values track by song.id"
ng-class="{selected: query.isIdSelected('showSongs', song.id)}"
>
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('showSongs', song.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
<a pfm-eat-click href="#" ng-click="setListFilter('showSongs', song.id);" bo-text="song.title"></a>
<a pfm-eat-click href="#" ng-click="setListFilter('showSongs', song.id);">{{::song.title}}</a>
</li>
</ul>
</li>
@ -33,9 +33,9 @@
</a>
<a class="btn" pfm-eat-click ng-click="clearFilter('genres')"><i class="icon-remove"></i></a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="genre in filters.genres.values" ng-class="{selected: query.isIdSelected('genres', genre.id)}">
<li ng-repeat="genre in ::filters.genres.values" ng-class="{selected: query.isIdSelected('genres', genre.id)}">
<a class="dont-close" pfm-eat-click href="#" ng-click="toggleListFilter('genres', genre.id); $event.stopPropagation();"><i class="icon-plus"></i></a>
<a pfm-eat-click href="#" ng-click="setListFilter('genres', genre.id);" bo-text="genre.title"></a>
<a pfm-eat-click href="#" ng-click="setListFilter('genres', genre.id);">{{::genre.title}}</a>
</li>
</ul>
</li>
@ -45,10 +45,10 @@
</a>
<a class="btn" pfm-eat-click ng-click="clearFilter('isVocal')"><i class="icon-remove"></i></a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="item in filters.isVocal.values track by $index"
<li ng-repeat="item in ::filters.isVocal.values track by $index"
ng-class="{selected: item == query.filters.isVocal}"
>
<a pfm-eat-click href="#" ng-click="setFilter('isVocal', item);" bo-text="item.title"></a>
<a pfm-eat-click href="#" ng-click="setFilter('isVocal', item);">{{::item.title}}</a>
</li>
</ul>
</li>
@ -58,8 +58,8 @@
</a>
<a class="btn" pfm-eat-click ng-click="clearFilter('sort')"><i class="icon-remove"></i></a>
<ul class="dropdown-menu">
<li bindonce ng-repeat="filter in filters.sort.values track by $index" ng-class="{selected: filter == query.filters.sort}">
<a pfm-eat-click href="#" ng-click="setFilter('sort', filter)" bo-text="filter.title"></a>
<li ng-repeat="filter in ::filters.sort.values track by $index" ng-class="{selected: filter == query.filters.sort}">
<a pfm-eat-click href="#" ng-click="setFilter('sort', filter)">{{::filter.title}}</a>
</li>
</ul>
</li>
@ -68,8 +68,8 @@
<div class="pagination" ng-if="totalPages > 1">
<ul>
<li ng-class="{disabled: !prevPage}"><a href="#" ng-click="gotoPage(prevPage);" pfm-eat-click>Prev</a></li>
<li bindonce ng-repeat="page in pages track by page" ng-class="{active: page == currentPage}">
<a href="#" ng-click="gotoPage(page);" pfm-eat-click bo-text="page"></a>
<li ng-repeat="page in pages track by page" ng-class="{active: page == currentPage}">
<a href="#" ng-click="gotoPage(page);" pfm-eat-click>{{::page}}</a>
</li>
<li ng-class="{disabled: !nextPage}"><a href="#" ng-click="gotoPage(nextPage);" pfm-eat-click>Next</a></li>
<li class="pagination-jump">

View file

@ -5,38 +5,38 @@
</a>
<div class="share-buttons" pfm-share-buttons>
<a class="tumblr" bo-href="track.share.tumblrUrl"
<a class="tumblr" ng-href="{{::track.share.tumblrUrl}}"
title="Share on Tumblr"
style="display:inline-block; overflow:hidden; width:20px; height:20px; background:url('/images/tumblr-share.png') top left no-repeat transparent;"></a>
<div class="facebook fb-like" data-href="{{track.url}}"
<div class="facebook fb-like" data-href="{{::track.url}}"
data-width="450" data-layout="button_count"
data-show-faces="true" data-send="false"></div>
<iframe class="twitter" allowtransparency="true" frameborder="0"
scrolling="no" bo-src="track.share.twitterUrl"
scrolling="no" ng-src="{{::track.share.twitterUrl}}"
style="width:130px; height:20px;"></iframe>
</div>
<ul class="stats">
<li>Published: <strong bo-text="track.published_at"></strong></li>
<li>Views: <strong bo-text="track.stats.views"></strong></li>
<li>Plays: <strong bo-text="track.stats.plays"></strong></li>
<li>Downloads: <strong bo-text="track.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="track.stats.favourites"></strong></li>
<li>Published: <strong>{{::track.published_at}}</strong></li>
<li>Views: <strong>{{::track.stats.views}}</strong></li>
<li>Plays: <strong>{{::track.stats.plays}}</strong></li>
<li>Downloads: <strong>{{::track.stats.downloads}}</strong></li>
<li>Favourites: <strong>{{::track.stats.favourites}}</strong></li>
</ul>
</div>
<div class="left">
<div class="description" bo-show="track.description.length">
<div class="description" ng-show="::track.description.length">
<h2>Description</h2>
<p marked="track.description"></p>
</div>
<div bo-show="track.is_vocal && track.lyrics.length" class="lyrics-panel">
<div ng-show="::track.is_vocal && track.lyrics.length" class="lyrics-panel">
<h2>Lyrics</h2>
<div class="lyrics revealable">
<div class="reveal">
<a href="#">Click to reveal full lyrics...</a>
<a href="#">Click to reveal full lyrics&hellip;</a>
</div>
<p class="content" bo-html="track.lyrics | noHTML | nl2br"></p>
<p class="content" ng-html="::track.lyrics | noHTML | nl2br"></p>
</div>
</div>

View file

@ -16,7 +16,7 @@
window.pfm.preloaders = {}
module = angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable', 'pasvaz.bindonce', 'angularytics', 'ngSanitize', 'hc.marked']
module = angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable', 'angularytics', 'ngSanitize', 'hc.marked']
if window.pfm.environment == 'production'
module.run [
@ -48,7 +48,9 @@ module.config [
# This fixes resource loading on IE
$sceDelegateProvider.resourceUrlWhitelist [
'self',
'/templates/directives/*'
'/templates/directives/*',
# Used for the "Tweet" button on content item pages
'https://platform.twitter.com/widgets/tweet_button.html**'
]
if window.pfm.environment == 'production'

View file

@ -64,6 +64,7 @@ angular.module('ponyfm').directive 'pfmImageUpload', () ->
$scope.uploadImage = () ->
$uploader.trigger 'click'
return
$scope.clearImage = () ->
$scope.imageObject = $scope.imageFile = $scope.imageUrl = null

View file

@ -161,7 +161,8 @@ angular.module('ponyfm').directive 'pfmTrackEditor', () ->
track_type_id: track.track_type_id
released_at: utc_release_date
remove_cover: false
cover: track.cover_url
cover_id: track.cover_id
cover_url: track.cover_url
album_id: track.album_id
is_published: track.is_published
is_listed: track.is_listed

View file

@ -1,325 +0,0 @@
(function () {
"use strict";
/**
* Bindonce - Zero watches binding for AngularJs
* @version v0.3.3
* @link https://github.com/Pasvaz/bindonce
* @author Pasquale Vazzana <pasqualevazzana@gmail.com>
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
var bindonceModule = angular.module('pasvaz.bindonce', []);
bindonceModule.directive('bindonce', function ()
{
var toBoolean = function (value)
{
if (value && value.length !== 0)
{
var v = angular.lowercase("" + value);
value = !(v === 'f' || v === '0' || v === 'false' || v === 'no' || v === 'n' || v === '[]');
}
else
{
value = false;
}
return value;
};
var msie = parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
if (isNaN(msie))
{
msie = parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
}
var bindonceDirective =
{
restrict: "AM",
controller: ['$scope', '$element', '$attrs', '$interpolate', function ($scope, $element, $attrs, $interpolate)
{
var showHideBinder = function (elm, attr, value)
{
var show = (attr === 'show') ? '' : 'none';
var hide = (attr === 'hide') ? '' : 'none';
elm.css('display', toBoolean(value) ? show : hide);
};
var classBinder = function (elm, value)
{
if (angular.isObject(value) && !angular.isArray(value))
{
var results = [];
angular.forEach(value, function (value, index)
{
if (value) results.push(index);
});
value = results;
}
if (value)
{
elm.addClass(angular.isArray(value) ? value.join(' ') : value);
}
};
var transclude = function (transcluder, scope)
{
transcluder.transclude(scope, function (clone)
{
var parent = transcluder.element.parent();
var afterNode = transcluder.element && transcluder.element[transcluder.element.length - 1];
var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
angular.forEach(clone, function (node)
{
parentNode.insertBefore(node, afterNextSibling);
});
});
};
var ctrl =
{
watcherRemover: undefined,
binders: [],
group: $attrs.boName,
element: $element,
ran: false,
addBinder: function (binder)
{
this.binders.push(binder);
// In case of late binding (when using the directive bo-name/bo-parent)
// it happens only when you use nested bindonce, if the bo-children
// are not dom children the linking can follow another order
if (this.ran)
{
this.runBinders();
}
},
setupWatcher: function (bindonceValue)
{
var that = this;
this.watcherRemover = $scope.$watch(bindonceValue, function (newValue)
{
if (newValue === undefined) return;
that.removeWatcher();
that.checkBindonce(newValue);
}, true);
},
checkBindonce: function (value)
{
var that = this, promise = (value.$promise) ? value.$promise.then : value.then;
// since Angular 1.2 promises are no longer
// undefined until they don't get resolved
if (typeof promise === 'function')
{
promise(function ()
{
that.runBinders();
});
}
else
{
that.runBinders();
}
},
removeWatcher: function ()
{
if (this.watcherRemover !== undefined)
{
this.watcherRemover();
this.watcherRemover = undefined;
}
},
runBinders: function ()
{
while (this.binders.length > 0)
{
var binder = this.binders.shift();
if (this.group && this.group != binder.group) continue;
var value = binder.scope.$eval((binder.interpolate) ? $interpolate(binder.value) : binder.value);
switch (binder.attr)
{
case 'boIf':
if (toBoolean(value))
{
transclude(binder, binder.scope.$new());
}
break;
case 'boSwitch':
var selectedTranscludes, switchCtrl = binder.controller[0];
if ((selectedTranscludes = switchCtrl.cases['!' + value] || switchCtrl.cases['?']))
{
binder.scope.$eval(binder.attrs.change);
angular.forEach(selectedTranscludes, function (selectedTransclude)
{
transclude(selectedTransclude, binder.scope.$new());
});
}
break;
case 'boSwitchWhen':
var ctrl = binder.controller[0];
ctrl.cases['!' + binder.attrs.boSwitchWhen] = (ctrl.cases['!' + binder.attrs.boSwitchWhen] || []);
ctrl.cases['!' + binder.attrs.boSwitchWhen].push({ transclude: binder.transclude, element: binder.element });
break;
case 'boSwitchDefault':
var ctrl = binder.controller[0];
ctrl.cases['?'] = (ctrl.cases['?'] || []);
ctrl.cases['?'].push({ transclude: binder.transclude, element: binder.element });
break;
case 'hide':
case 'show':
showHideBinder(binder.element, binder.attr, value);
break;
case 'class':
classBinder(binder.element, value);
break;
case 'text':
binder.element.text(value);
break;
case 'html':
binder.element.html(value);
break;
case 'style':
binder.element.css(value);
break;
case 'disabled':
binder.element.prop('disabled', value);
break;
case 'src':
binder.element.attr(binder.attr, value);
if (msie) binder.element.prop('src', value);
break;
case 'attr':
angular.forEach(binder.attrs, function (attrValue, attrKey)
{
var newAttr, newValue;
if (attrKey.match(/^boAttr./) && binder.attrs[attrKey])
{
newAttr = attrKey.replace(/^boAttr/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
newValue = binder.scope.$eval(binder.attrs[attrKey]);
binder.element.attr(newAttr, newValue);
}
});
break;
case 'href':
case 'alt':
case 'title':
case 'id':
case 'value':
binder.element.attr(binder.attr, value);
break;
}
}
this.ran = true;
}
};
angular.extend(this, ctrl);
}],
link: function (scope, elm, attrs, bindonceController)
{
var value = attrs.bindonce && scope.$eval(attrs.bindonce);
if (value !== undefined)
{
bindonceController.checkBindonce(value);
}
else
{
bindonceController.setupWatcher(attrs.bindonce);
elm.bind("$destroy", bindonceController.removeWatcher);
}
}
};
return bindonceDirective;
});
angular.forEach(
[
{ directiveName: 'boShow', attribute: 'show' },
{ directiveName: 'boHide', attribute: 'hide' },
{ directiveName: 'boClass', attribute: 'class' },
{ directiveName: 'boText', attribute: 'text' },
{ directiveName: 'boBind', attribute: 'text' },
{ directiveName: 'boHtml', attribute: 'html' },
{ directiveName: 'boSrcI', attribute: 'src', interpolate: true },
{ directiveName: 'boSrc', attribute: 'src' },
{ directiveName: 'boHrefI', attribute: 'href', interpolate: true },
{ directiveName: 'boHref', attribute: 'href' },
{ directiveName: 'boAlt', attribute: 'alt' },
{ directiveName: 'boTitle', attribute: 'title' },
{ directiveName: 'boId', attribute: 'id' },
{ directiveName: 'boStyle', attribute: 'style' },
{ directiveName: 'boDisabled', attribute: 'disabled' },
{ directiveName: 'boValue', attribute: 'value' },
{ directiveName: 'boAttr', attribute: 'attr' },
{ directiveName: 'boIf', transclude: 'element', terminal: true, priority: 1000 },
{ directiveName: 'boSwitch', require: 'boSwitch', controller: function () { this.cases = {}; } },
{ directiveName: 'boSwitchWhen', transclude: 'element', priority: 800, require: '^boSwitch' },
{ directiveName: 'boSwitchDefault', transclude: 'element', priority: 800, require: '^boSwitch' }
],
function (boDirective)
{
var childPriority = 200;
return bindonceModule.directive(boDirective.directiveName, function ()
{
var bindonceDirective =
{
priority: boDirective.priority || childPriority,
transclude: boDirective.transclude || false,
terminal: boDirective.terminal || false,
require: ['^bindonce'].concat(boDirective.require || []),
controller: boDirective.controller,
compile: function (tElement, tAttrs, transclude)
{
return function (scope, elm, attrs, controllers)
{
var bindonceController = controllers[0];
var name = attrs.boParent;
if (name && bindonceController.group !== name)
{
var element = bindonceController.element.parent();
bindonceController = undefined;
var parentValue;
while (element[0].nodeType !== 9 && element.length)
{
if ((parentValue = element.data('$bindonceController'))
&& parentValue.group === name)
{
bindonceController = parentValue;
break;
}
element = element.parent();
}
if (!bindonceController)
{
throw new Error("No bindonce controller: " + name);
}
}
bindonceController.addBinder(
{
element: elm,
attr: boDirective.attribute || boDirective.directiveName,
attrs: attrs,
value: attrs[boDirective.directiveName],
interpolate: boDirective.interpolate,
group: name,
transclude: transclude,
controller: controllers.slice(1),
scope: scope
});
};
}
};
return bindonceDirective;
});
})
})();