SPlayer

SPlayer

Supercharged HTML5 Music Player with Control Panel

This documention is for developers and non-developers. However, if you’re a non-developer, you might get confused. So use the new WordPress-like SPlayer Control Panel Windows Program that requires ZERO-coding skills and helps ANYONE configure, add music and control the UI options.

Control Panel

Starting from SPlayer 2.1, JaguarScript team has added a Control Panel Windows Program to help anyone configure and control SPlayer and UI.

There are already easy instructions in the package that anyone can follow to build SPlayer with your music folder. You don’t even have to copy files or include scripts or read installation instructions, you just have to copy all of your songs and paste them in a specific music folder, then click Build and Save Changes button in the Control Panel, and finally you just have to upload the folder to your Web Hosting.

If you’re a non-developer, you don’t have to continue reading. Use Control Panel. We’re Done.

We would like to add that no HTML5 player has done something like this, or anything similar.

Control Panel Features

Installation

It doesn’t require any external dependency. Just upload production-ready splayer.min.js file from dist folder in the package and to somewhere in your website, and then include it in your page inside your <head> tag like

<script src="path/to/splayer.min.js"></script>

If you want to use the UI, then include its files (It requires jQuery):

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> <link href="path/to/splayer.ui.min.css" rel="stylesheet" type="text/css"> <script src="path/to/splayer.ui.min.js"></script>

Make sure to replace path/to with your path

Custom Build

If you’re a developer, and you want to build a custom build of SPlayer Engine that fits your needs, you might want to follow this instructions.

Requirements (UI requirements included)

  1. Install Node.js
  2. Install Rollup.js: npm install --global rollup
  3. Install Rollup JSON Plugin: npm install @rollup/plugin-json --save-dev
  4. Install Grunt: npm install grunt --save-dev
  5. Install Grunt Uglify Plugin: npm install grunt-contrib-uglify --save-dev
  6. Install Grunt Postcss npm install grunt-postcss pixrem autoprefixer cssnano
  7. Install Grunt Cssmin npm install grunt-contrib-cssmin --save-dev

—save-dev means you should install it inside SPlayer folder

Build

Make changes in src folder, then build:

rollup -c && grunt uglify or npm run build (npm method might not work)

If you want to add custom function, add it to src folder, then export and import in splayer.js file.

Easy Guides

There are examples folder in the package that elaborates the adding and setting mechansim, and there’s also WordPress-like Control Panel Windows program that requires ZERO-coding skills.

After you check the easy guides, if you want to read more check SPlayer.add() and SPlayer.set() docs.

You can do a lot more than this, but these easy guides are for coders and web editors who wants an intro to SPlayer API.

Guide for One Song

Proccess and add song.mp3 with its album, artist, images, etc ( check Track DataObject data ) by simply calling:

S.add("track", "http://www.mywebsite.com/path/to/song.mp3");

// The previeus call creates a Track DataObject with src song.mp3
// and its metadata and other data, then inserts it into the database.

// Or if song.mp3 doesnt have embedded metadata, you can do this
S.add("track", {
    src: "http://www.mywebsite.com/path/to/song.mp3",
    title: "Firework",
    artists: ["Katy Perry"]
});

// We have to mention that in the last call, by setting title and artist,
// SPlayer fetches the entire track metadata from the internet.
// And sets its album whichs (Teenage Dream), artist, images, etc automatically.
// It's truly amazing

Guide for 10 Songs

var songs = [
            "http://www.yourwebsite/path/to/song1.mp3",
            "http://www.yourwebsite/path/to/song2.mp3",
            "http://www.yourwebsite/path/to/song3.mp3",
            "http://www.yourwebsite/path/to/song4.mp3",
            "http://www.yourwebsite/path/to/song5.mp3",
            "http://www.yourwebsite/path/to/song6.mp3",
            "http://www.yourwebsite/path/to/song7.mp3",
            "http://www.yourwebsite/path/to/song8.mp3",
            "http://www.yourwebsite/path/to/song9.mp3",
            "http://www.yourwebsite/path/to/song10.mp3",
            ];

S.add("track", songs);

Guide for One Playlist

var songs = [
            { src: "http://www.yourwebsite/path/to/song1.mp3" },
            { src: "http://www.yourwebsite/path/to/song2.mp3" },
            { src: "http://www.yourwebsite/path/to/song3.mp3" },
            { src: "http://www.yourwebsite/path/to/song4.mp3" },
            { src: "http://www.yourwebsite/path/to/song5.mp3" },
            { src: "http://www.yourwebsite/path/to/song6.mp3" },
            { src: "http://www.yourwebsite/path/to/song7.mp3" },
            { src: "http://www.yourwebsite/path/to/song8.mp3" },
            { src: "http://www.yourwebsite/path/to/song9.mp3" },
            { src: "http://www.yourwebsite/path/to/song10.mp3" },
            ];

S.add("track", songs);

// Create a playlist
S.add("playlist", "My Top 10");

// Select and add (Bind)
S("playlist", { name: "My Top 10" }).add(songs);

Usage

SPlayer.ready(function() {

   // SPlayer is ready, now you can safely use its API.

   // Add track by link
   SPlayer.add("track", "http://www.mywebsite.com/path/to/songfile.mp3");

   // Add track by link and set a custom unique id
   SPlayer.add("track", {
       src: "http://www.mywebsite.com/path/to/songfile2.mp3",
       id: "wow"
   });

   // Select wow track by its id and load it then play it 
   S("tracks", "wow").load();
   S.play();

   // Create "favorites" playlist
   S.add("playlist", "favorites");

   // Select the current loaded,
   // and add it to the "favorites" playlist
   S(':loaded').add("playlist", { name: "favorites" });

   // Select all tracks and loop through all of them,
   // then log their names
   S("tracks").each(function (dataObject) {
       console.log(dataObject.name)       
   });

   // Get a track by its id when processed & ready and log it
   S("tracks", "wow").get(function (dataObject) {
        console.log(dataObject)
   });

   // Import JSON database
   S.set("http://somewhere.com/database.json")

   // There are hundreds of methods to help you do a lot of stuff,
   // not even the sky is the limit, but you get the idea

});

Before we start, this is SPlayer Usage, not the SPlayer UI usage. You don’t have to be a nerd to add music and to use the UI. You don’t have to manually add music or write anything. Just be patient! You need to understand and read. We will get there.

Okay, let’s start:

After you include splayer.min.js in your website, you’re ready to use it just like jQuery. It’s exposed as SPlayer and S as well.

You should first understand how SPlayer works, its mechanism, its API, what Audio formats does it accept and support, and its dataObjects. We will simplify it here, so everything will become easy for you:

SPlayer has database, selector, offline storage, dual HTML5 Audio player, dual Metadata Engine, an API that wraps all of them, and events for each of them.

Database is where you add your tracks, streams, albums, etc .. into it, we call them dataObjects. There are many dataObjects types you can add. Each one has its own thing and designed to do a unique job. Some dataObjects like tracks gets sent into Metadata Engine to be processed. These dataObjects can also be added into each other. You can say like parent/children relation.

Just like jQuery, SPlayer API has static methods, instance prototypes, and properties. The static methods are SPlayer Global Methods, and instance prototypes are for SPlayer Selector.

Selector is used to select dataObjects from database, and do something with them. Select and execute mechanism. You can maniplate, traverse, and do a lot of things.

Let’s elaborate;

If you want to play a song.mp3. What would you do? How do you think the mechanism looks like?

Do you think it looks like this?

SPlayer.playSong("http://www.yourwebsite.com/path/to/song.mp3") or something like SPlayer.audio.play("song.mp3")

No.

If you want to remove a track, or store it in the offline storage. How do you think the call looks like?

If you want to pause audio. How do you think the call looks like?

SPlayer is logical. We hope the next lines helps you understand the whole SPlayer API.

First, you have to add song.mp3 to database:

S.add("track", { src: "http://www.yourwebsite.com/path/to/song.mp3", id: 10 })

Let’s listen to it: Select, and execute. Remember?

S("track", 10).load()
S.play()

If you want to remove it, then let’s remove it:

S("track", 10).remove()

That’s it.

SPlayer package also includes an external UI plugin, which’s an interface for SPlayer API. Not part of it.

SPlayer might take a while to initialize, so make sure you wait for ready event. It’s recommended to use SPlayer.ready() and not SPlayer.on("ready")

Audio Formats

The accepted audio formats are: MP3, OGG, OGA, AAC, M4A and MP4.

The accepted audio codecs are: audio/mpeg, audio/mp3, audio/ogg, audio/x-m4a, audio/m4a, audio/x-mp4, audio/mp4, audio/mp4a, audio/x-aac, audio/aac, audio/aacp.

SPlayer does Real Audio Support, It doesn’t just count on native browser codec support. We recommend you to use MP3 or M4A.

To read more about Audio Formats: Click here

Currently: OGG, OGA files aren’t supported by the Embedded Metadata Parser

SRC Inputs

Track links and live streams are supported.
For example: “http://www.mywebsite.com/path/to/songfile.mp3

Metadata Engine will get only the necessary bytes for reading the tags. But if your links are hosted on another server (CORS), the following headers are expected:

Access-Control-Allow-Headers: If-Modified-Since, Range

Access-Control-Expose-Headers: Content-Length, Content-Range

Metadata parser still work without these headers configured on the server. However, it will download the entire file instead of only the necessary bytes.

Fetching the entier file isn’t enabled by default, it’s not recommended, and it’s odd to let the users fetch the entire file to get metadata unless you just wanted to create setJSON. But if you want to allow fetching the entire file, check allowFetchingEntireFile option. However, it still might not work, if CORS isn’t supported by the server. So you better host your music on your own server. In our SPlayer UI Demo, we don’t even fetch anything, we give the users an already-processed dataObjects using JSON Import, we recommend to do the same

Files/Blobs

Binary Files are supported including Flobs [1]

If you wish to add FileList, you need to loop and add

[1]: Flob is a Blob object with File properties (name, lastModifiedDate).

Base64

Data URLs with Base64-encoded strings are supported.

SPlayer converts Base64 to Blob files for better performance and compatibility reasons

JSON Inputs

SPlayer does support JSON data in SPlayer.add() and SPlayer.set().

You can use it like:

SPlayer.add(JSONInput)

JSON data for SPlayer.add() and SPlayer.set() are different. SPlayer.add() accepts Objects, and SPlayer.set() accepts Array of dataObjects. And both requires JSON to be signed with SPlayer Marker (__splayer__)

Strings

JSON String for add()

"{"__splayer__":true, "track":"http://www.yourwebsite.com/path/to/songfile.mp3", "playlist":"wow", "collections":["Col 1","Col 2"]}"

JSON String for set()

"["__splayer__", dataObject, dataObject2, ...]"

setJSON is an Array of already processed dataObjects.

Files/Blobs

JSON files that contain the above JSON strings are supported.

You should know that this is async, not sync, unlike direct JSON string add/set

URLs

You can let SPlayer fetch your JSON file for you and then parse it.

"http://www.mywebsite.com/path/to/mytracks.json"

You can use it like:

SPlayer.add("http://www.mywebsite.com/path/to/mytracks.json")

You should know that this is async, not sync, unlike direct JSON string add/set

Folder JSON Generator

In the package, there’s also Folder JSON Generator HTML5 App that helps anyone to build setJSON (database JSON) and addJSON. Instructions is in the package.

However, you don’t have to use it. SPlayer has a Control Panel that can do a similar job.

dataObjects

Every dataObject type has native props, you can add your own custom props with custom data as well. Some of their props must never be overridden like id and others.

There are two kinds of dataObjects:

  1. track, stream, album, artist, genre, playlist, collection
  2. storage, history, queue, task, _

The second one are mostly used internally, you can’t create new objects of them, you shouldn’t touch them unless you know what you’re doing. However, you can still select them, because they are very helpful for you. If you want to check or show the stored dataObjects you can simply call S("storage").has("track", 1), if you want to proccess a song earlier, you can simply call S("task").children("track", 1).move(0) … We hope you got the idea.

Each dataObject accepts specific dataObjects: For example, you can’t add stream dataObject to track dataObject, but you can add stream dataObject to playlist dataObject. Check dataObject props to know what types does it accept.

When we add/bind dataObject to another, it’s added simplified ({type, id}), not the complete, to avoid circular references and memory issues.

All dataObjects contains private props you shouldn’t care about EXCEPT when storing and extracting and using tracks, streams, etc..

Take a look:

track

{ type: "track", id: ..., src: ..., name: ..., title: ..., duration: ..., format: ..., input: ..., date: ..., images: ..., comment: ..., wiki: ..., year: ..., stats: { ended: { count: ..., lastModifiedDate: ... }, load: { count: ..., lastModifiedDate: ... } }, ready: ..., playable: ..., availability: ..., playlists: ..., collections: ..., albums: ..., artists: ..., genres: ..., storage: ..., queue: ..., history: ..., task: ..., _: ... }

Accepted dataObjects to be added into: playlists, collections, albums, artists, genres, storage, queue, history, task, _.

stream

{ type: "stream", id: ..., src: ..., name: ..., duration: ..., format: ..., input: ..., date: ..., stats: { ended: { count: ..., lastModifiedDate: ... }, load: { count: ..., lastModifiedDate: ... } }, ready: ..., playable: ..., availability: ..., playlists: ..., collections: ..., albums: ..., artists: ..., genres: ..., storage: ..., queue: ..., history: ..., task: ..., _: ... }

Accepted dataObjects to be added into: playlists, collections, albums, artists, genres, storage, queue, history, task, _.

Again, you can add your own custom props, it means you can add title prop if you like. The reason why it’s different from track object props, because metadata parser doesn’t support streams therefore no title, images, etc.

playlist

{ type: "playlist", id: ..., name: ..., date: ..., ready: ..., tracks: ..., streams: ..., collections: ..., storage: ..., history: ..., _: ... }

Accepted dataObjects to be added into: tracks, streams, collections, storage, history, _.

album

{ type: "album", id: ..., name: ..., date: ..., images: ..., wiki: ..., year: ..., ready: ..., tracks: ..., streams: ..., collections: ..., artists: ..., genres: ..., storage: ..., task: ..., history: ..., _: ... }

Accepted dataObjects to be added into: tracks, streams, collections, artists, genres, storage, task, history, _.

artist

{ type: "artist", id: ..., name: ..., date: ..., images: ..., wiki: ..., ready: ..., tracks: ..., streams: ..., collections: ..., albums: ..., genres: ..., storage: ..., task: ..., history: ..., _: ... }

Accepted dataObjects to be added into: tracks, streams, collections, albums, genres, storage, task, history, _.

genre

{ type: "genre", id: ..., name: ..., date: ..., ready: ..., tracks: ..., streams: ..., collections: ..., albums: ..., artists: ..., storage: ..., history: ..., _: ... }

Accepted dataObjects to be added into: tracks, streams, collections, albums, artists, storage, history, _.

collection

{ type: "collection", id: ..., name: ..., date: ..., ready: ..., tracks: ..., streams: ..., playlists: ..., albums: ..., artists: ..., genres: ..., storage: ..., history: ..., _: ... }

Accepted dataObjects to be added into: tracks, streams, playlists, albums, artists, genres, storage, history, _.

storage

{ type: "collection", id: ..., name: ..., ready: ..., tracks: ..., streams: ..., playlists: ..., collections: ..., albums: ..., artists: ..., genres: ..., queue: ..., history: ..., _: ... }

SPlayer Storage.

This is Storage dataObjects, not the actual storage engine. You can iterate and view them monitor it to see live changes.

However, don’t add, remove or manipulate this Storage dataObject wihtout knowing what you doing. This is used internally by SPlayer. You can check this storage dataObject if it has a certain stored dataObject or stuff like that.

If you want to store or remove dataObjects from storage. Use these APIs .store() and .release()

Accepted dataObjects to be added into: tracks, streams, playlists, collections, albums, artists, genres, queue, history, _.

Select it: S("storage")

queue

{ type: "queue", id: ..., name: ..., ready: ..., tracks: ..., streams: ..., storage: ..., _: ... }

SPlayer Play Queue.

You can add, remove, move, etc dataObjects in queue. Do whatever you want. This is the internal SPlayer Play Queue.

Accepted dataObjects to be added into: tracks, streams, storage, _.

Select it: S("queue")

history

{ type: "history", id: ..., name: ..., ready: ..., tracks: ..., streams: ..., playlists: ..., collections: ..., albums: ..., artists: ..., genres: ..., storage: ..., _: ... }

SPlayer History.

You can get tracks, streams, etc from it. And iterate and view them or monitor it to see live changes.

Accepted dataObjects to be added into: tracks, streams, playlists, collections, albums, artists, genres, storage, _.

Select it: S("history")

task

{ type: "task", id: ..., name: ..., ready: ..., tracks: ..., streams: ..., albums: ..., artists: ..., _: ... }

SPlayer Task Manager. You can move dataObjects to index=0, if you want them to be processed sonner.

However, don’t remove dataObjects from it, unless you know exactly what you’re doing.

Accepted dataObjects to be added into: tracks, streams, albums, artists, _.

Select it: S("task")

_

_ means private. It’s used for some APIs like .not(), so you shouldn’t touch it, unless you know exactly what you’re doing.

If you do want to touch it, add, remove, etc dataObjects to it for some reason. Make sure you empty it after you use it.

Select it: S("_")

{ type: "_", id: ..., name: ..., ready: ..., tracks: ..., streams: ..., playlists: ..., collections: ..., albums: ..., artists: ..., genres: ..., history: ..., storage: ..., task: ... }

Accepted dataObjects to be added into: tracks, streams, playlists, collections, albums, artists, genres, history, storage, task.

API Handy Guide

Config

Database

Audio

Manipulation

Traversing

Miscellaneous

Events/States

Import/Export

Storage/Cache/Download

Share/URLReader

Session

Queue

History

Task Manager

Other

API Documentation

In short, sync/async simple jQuery-like API that does powerful jobs.

In jQuery, you select then you execute like $("body").addClass("active"), or you use one of its handy methods like jQuery.ajax().

In SPlayer, it’s the same. If you know jQuery API you already know SPlayer API.

There are three types of APIs. Static methods like SPlayer.config(), Instance prototypes like .get(), Static objects like SPlayer.session.

Knowing the differnace between static methods and instance prototypes is essential, there are global methods that affects all the data and there are prototypes that affects selected data

We developed this piece of art just to make everything easy and simple for you. Developers and non-developers can do complicated jobs with simple calls.

We even created SPlayer UI Plugin, which’s an interface for SPlayer API, can be launched with one call.

Methods

SPlayer.add()

// Add track by link
SPlayer.add("track", "http://www.yourwebsite.com/path/to/songfile.mp3");

// Add another track with custom unique Id
SPlayer.add("track", {
    id: "unique-id",
    src: srcInput
});

// Add Playlist
SPlayer.add("playlist", "My favorites");

// Add Multiple tracks by links
SPlayer.add("track", ["http://www.yourwebsite.com/path/to/songfile.mp3", "http://www.yourwebsite.com/path/to/songfile2.mp3"]);

// Add multiple dataObjects
SPlayer.add({
    tracks: ...,
    albums: ...,
    collections: ...
})

// Add JSON
// Note: Please check JSON inputs
SPlayer.add(JSONInput)

// Add track with artist.
//  
// With this call, you add Firework track with
// its full metadata (images, wiki, etc..),
// It also adds its genres,
// adds Katy Perry artist dataObject with its metadata,
// and it also finds this track album (which's Teenage Dream),
// and adds it as well with its metadata.
// Everything is automated. This is incredible.
// However, this track ready event isn't connected to its albums
// and artists. That means every dataObject has its own ready event.
//
// What's goine on behind the scenes is far from simple, It's a marvelous art.
// This adding mechanism is awesome
// since it automatically binds children and parent.
// However, this mechanism is used internally
// and its adding options is limited.
// If you just want to add dataObjects into each other,
// just use .add() prototype.
SPlayer.add("track", {
     src: "http://www.yourwebsite.com/path/to/firework.mp3",
     title: "Firework",
     artists: ["Katy Perry"]
})

add(type, value, options)

Add data (tracks, streams, albums, artists, genres, playlists, collections) to the database.

Please check supported dataObjects and src inputs.
You can add JSON data as well. Check JSON inputs.

You can’t add duplicated data (i.e. same src inputs), if you wish to force add duplicated data, then set custom unique id.

This add() is automated. If you have 100 tracks with the correct metadata, you just have to add the tracks. SPlayer will automatically add their albums, artists and genres, and binds them together. It’s incredible.

You must add the full path to your song.

Not all adds are sync, JSON URL and JSON Blob adds are async, you can monitor add event using SPlayer.one() or SPlayer.on() if you want.

SPlayer.audio()

// Get Active audio engine
SPlayer.audio(function (audio) {

   console.log("SPlayer active audio engine:", audio)

});

// Or 
SPlayer.audio(); // It returns active audio engine

// Get audio engine id 0
// Note: It could be the active or not
SPlayer.audio(function (audio0) {

   console.log("SPlayer id=0 audio engine:", audio0)

}, {
engine: 0
});

Get audio engine.

audio(callback, options)

SPlayer.buffered()

SPlayer.buffered(function (STimeRanges) {
    // do something with STimeRanges
})

Get buffered audio data.

buffered(callback, options)

SPlayer.clear()

SPlayer.clear();

Clear SPlayer database, storage and events.

clear()

SPlayer.config()

<script src="path/to/splayer.min.js"></script>
<script>
   // It's recommended to configure SPlayer right after
   // SPlayer.js file load, and just once.
   SPlayer.config({
      multithreading: false,
      autoRestore: false,
      autoUrlize: false
   })

</script>
SPlayer.config({
   metadata: "complete",
   autoRestore: false
})

config(options)

Configure SPlayer.

You can configure SPlayer whenever you want, you don’t have to wait for ready event. BUT configuring some options like autoRestore, and multithreading requires you to call config() before SPlayer initialization and can only be configured once, that means you must call config() right after SPlayer JS file load

  1. allowFetchingEntireFile allow metadata parser to fetch the entire file, If it failed to get the necessary bytes for reading the tags from the CORS links.
    Type: Boolean
    Default: false

    Note: even if you allowFetchingEntireFile, it may not be able to fetch the entire file, because that depends on the server

  2. internetService choose the internet music service API to fetch Internet Metadata. All are well-supported.
    Type: String
    Default: "lastfm", "itunes", "deezer"

    lastfm is recommended. itunes is the slowest it fetches metadata every 3 seconds

  3. corsProxy CORS proxy used to fetch internet metadata.
    Type: String
    Default: ********

    We need CORS proxy to fetch metadata for itunes and deezer and artist images.

  4. lastfmKey Required lastfm API key if you wanna use lastfm service.
    Type: String
    Default: ********

  5. enhanceAutocorrect We enhance lastfm/deezer autocorrect by processing its artist first, get correct name, then process track/album (Since autocorrect on some lastfm/deezer track/album API is broken). We prefer internet album name over album name inside embedded track.
    Type: Boolean
    Default: true

    Highly recommended! It increases your chance of getting accurate track/album metadata.

  6. shareParams set the share params type. Hash param or URL Query String.
    Type: String
    Default: "url"
    Options: "url", "hash"

    It’s recommended to stick to URL Query String.

    Hash Params works with Browser History API.

  7. defaultDataObjectsForStreams enable default dataObjects (such as unknown album, unknown artist, and other genre) for streams as default.
    Type: Boolean
    Default: false

    You can still add them of course

  8. maxProcessing since SPlayer processes multiple tracks, albums, and artists at once, we allow to set the max dataObjects parallel proccessing count.
    Type: Number/String
    Default: "auto" Options: 8, 12, "auto"

    Don’t set a low number. If you enable enhanceAutocorrect, this should be 10+. 1 or 2 isn’t recommended. Still limited by interval.

  9. history history. With enabling this option, you get to see your recent plays. Type: Boolean
    Default: true

  10. historyLimit set the max history count.
    Type: Number
    Default: 50

  11. lastSession store last session on close (aka window.onbeforeunload).
    Type: Boolean
    Default: true

  12. autoRestore restore last session before ready event.
    Type: Boolean
    Default: true

  13. volume set the default volume.
    Type: String/Number
    Options: 90, "50%", etc..
    Default: 80

  14. muted set the default muted.
    Type: Boolean
    Default: false

  15. rate set the default rate.
    Type: String/Number
    Options: 0.5, 0.8, "slower", "slow", "normal", "fast", "faster", "2x", "3x", etc ..
    Default: 1

SPlayer.duration()

SPlayer.duration(function (duration) {

    console.log(duration);

})

duration(callback, options)

Get audio duration.

SPlayer.error()

SPlayer.error(function () {

    console.log('SPlayer Initialization Error. Unsupported Web Browser.');

})

error(callback)

Call function if SPlayer is unsupported on the current web browser.

SPlayer.extract()

SPlayer.extract(function () {

    console.log("Data has been successfully extracted and inserted.");

})

extract(callback)

Extract data from the offline storage, and insert them directly into the database.

autoExtract in the config is enabled by default. So this extract() gets automatically called before SPlayer ready event.

SPlayer.finished()

SPlayer.finished("next");

// Or

SPlayer.finished("replay"); // aka loop

finished(fn)

Do something when audio is ended. (This could be used to implement loop, auto play the next, or shuffle.)

SPlayer.has()

if (SPlayer.has("track", 123654987)) {
   doSomething();
}

// Check if SPlayer has a track
if (SPlayer.has("track")) {
   doSomething();
}

// Check if SPlayer has track id=123987456 and playlist id=wow
if (SPlayer.has({
    track: 123987456,
    playlist: "wow"
})) {
   doSomething();
}

has(type, value, _options)

Check if SPlayer has dataObject(s).

Returns: Boolean

SPlayer.is()

if (SPlayer.is("offline")) {
   doSomething();
}

is(stateName)

Check SPlayer live states.

Check out States

Returns: Boolean

SPlayer.mute()

SPlayer.mute()

mute()

Mute audio.

SPlayer.next()

SPlayer.next()

next()

Load and play the next track/stream in queue.

SPlayer.off()

SPlayer.off("load")

// Or

var wow = function () { ... };
var awesome = function () { .. };

SPlayer.on("pause", wow);
SPlayer.on("pause", awesome);

// Remove wow fn
SPlayer.off("pause", wow);

off(type, fn, _dataObject)

Remove an event handler.

SPlayer.on()

SPlayer.on("mute", function() {
   console.log("Why did you mute me?")
})

// Or

var wow = function () { ... };

SPlayer.on("mute", wow);

// Set custom event

var customEvent = function () { ... };

SPlayer.on("jumbo-mumbo", customEvent);

// then trigger it whenver you want like
SPlayer.trigger("jumbo-mumbo");

on(type, fn, _dataObject, _callback)

Add an event handler. (Do something when something happens).

Check Events

You can add custom event handler, not part of the SPlayer Events, and trigger it whenever you want.

SPlayer.one()

var wow = function () { ... };

SPlayer.one("mute", wow);

one(type, fn, _dataObject)

Add an event handler … but call it only once.

Check Events

You can add custom event handler, not part of the SPlayer Events, and trigger it whenever you want it.

SPlayer.pause()

SPlayer.pause()

pause()

Pause audio.

SPlayer.play()

SPlayer.play()

play()

Play audio.

SPlayer.played()

SPlayer.played(function (STimeRanges) {
    // do something with STimeRanges
})

Get played audio data.

played(callback, options)

SPlayer.prev()

SPlayer.prev()

prev()

Load and play the pervious track/stream in queue.

SPlayer.rate()

SPlayer.rate(2);

// Or

SPlayer.rate("2x");

// Or

SPlayer.rate("fast")

SPlayer.rate(); // returns rate

SPlayer.rate(function (rate) {
    console.log(rate)
})

rate(value)

Get or set audio rate.

SPlayer.ready()

SPlayer.ready(function () {
   // Wow, SPlayer is ready. do something!
})

ready(callback)

Call function if/when SPlayer is ready.

The difference between SPlayer.ready(callback) and SPlayer.on("ready", callback), is that in on(), an event listener added after the event fires is never executed.

SPlayer.reload()

SPlayer.reload();

reload()

Reload audio.

Will basically just call ActiveAudioEngine.load()

SPlayer.remaining()

SPlayer.remaining(function (rem) {

   console.log(rem)

})

remaining()

Get the remaining audio time.

SPlayer.replay()

SPlayer.replay()

replay()

Replay audio. Or call it loop if you may.

SPlayer.reshuffle()

SPlayer.reshuffle()

reshuffle()

Reset shuffle list.

Let’s say that you’re playing 10 tracks, and one is playing right now. You only get to call shuffle() 9 times. You can call reshuffle() to reset the shuffle virtual list.

SPlayer.restore()

SPlayer.restore()

restore(props)

Restore SPlayer last session.

SPlayer.saveSession()

SPlayer.saveSession()

saveSession()

Save SPlayer.session in the offline storage.

This saveSession() gets automatically called on SPlayer close event

SPlayer.set()

SPlayer.set([dataObject, dataObject2]);

SPlayer.set(dataObject);

SPlayer.set(JSONInput);

set(data, _assets)

Insert dataObjects directly into the database (Will override existing dataObjects if found).

Not all sets are sync, JSON URL and JSON Blob sets are async, you can monitor set event if you want.

This set can override existing internal DataObjects like storage, queue, history, etc..

SPlayer.shuffle()

SPlayer.shuffle()

shuffle()

Load and play the shuffled track/stream in queue.

SPlayer.stop()

SPlayer.stop()

stop()

Stop audio.

SPlayer.time()

SPlayer.time(); // returns time directly

SPlayer.time(function (time) {
    console.log(time)
});

SPlayer.time(30) // Set current time to 30 seconds

time(value, options)

Get or set audio current time.

SPlayer.toggle()

// Play if audio was paused, or pause if audio was playing.
SPlayer.toggle("play"); 

// Same affect as toggle("play")
SPlayer.toggle("pause"); 

// Toggle between play and stop.
// Play if audio was stopped, or stop if audio was playing.
SPlayer.toggle("play", "stop");

toggle(between, and)

Toggle states (play, pause, stop, mute, unmute). That means if audio was muted, and you called toggle("mute"), it gets unmuted.

SPlayer.trigger()

SPlayer.trigger("load")

SPlayer.trigger("stop", [1, "wow"])

trigger(type, data, _dataObject)

Trigger an event handler. Check out Events

SPlayer.unload()

SPlayer.unload()

unload()

Unload audio.

dataObject gets unloaded and queue gets emptied as well.

SPlayer.unmute()

SPlayer.unmute()

unmute()

Unmute audio.

SPlayer.urlize()

SPlayer.urlize()

urlize()

Read and execute SPlayer URL code.

URL examples:

http://www.website.com/?splayer=S(track,692471516).load();S.play()

http://www.website.com/#splayer=S(track,692471516).load();S.play()

URL code could be SPlayer Selector (but limited to ID only and without " or '), instance prototypes, or SPlayer Global Methods. Or all of them separated using ;, just like how you normaly write code. But limited of course, you can only call SPlayer Code. SPlayer Urlizer doesn’t use eval to run URL Code.

It depends on shareParam in the config()

SPlayer.volume()

// Get volume
SPlayer.volume(function (vol) {
    console.log(vol)
})

SPlayer.volume(); // Returns volume

// Set volume to 10 percent
SPlayer.volume(10)

// Or
SPlayer.volume("10%")

volume(value)

Get or set volume.

Prototypes (Selector API)

Selector and action.

.add()

S("playlist", 1).add("tracks")

add(type, value)

Add/bind dataObject(s) to the set of the matched dataObjects.

Don’t confuse it with SPlayer.add(), this one is different

.and()

S("track").and("album", 1)

and(type, value)

It returns a new SPlayer Object with selected dataObjects added to the set of the matched dataObjects.

.blobify()

S("tracks").blobify();


S("artists").blobify(function () {
    // Succesfully converted artists images
}, {
   images: true
})

blobify(callback, options)

Convert src or/and images URLs to Blob (Make them Offline ready).

Used to cache music and their images

.children()

S("playlist", 1).children("track")

S("collections").children("album artist")

children(type, value)

It returns a new SPlayer Object with the matched dataObjects children, and adds .parent prop to the SPlayer Object pointing to the pervious set of the matched dataObjects.

.contains()

S("track", [50, 93, 655, 45454, 65]).contains("track", 65) // Returns true.

contains(type, value, options)

Check if the set of the matched dataObjects contains the matched selector.

Returns: Boolean

.dequeue()

S("track", 6546).dequeue();

// Equals this
S("queue").children("track, 6546").remove();

dequeue()

Remove the set of the matched dataObjects from queue.

.download()

S("track").download()

download()

Download the set of the matched track dataObjects.

.each()

S("tracks").each(function (track, index) {
   console.log(track, index)
})

S("playlist", 50).children("stream").each(function (stream) {
   console.log(stream)
})

each(callback)

Iterate over the SPlayer Object, executing a callback function for each matched dataObject.

.edit()

S("track", 45).edit("wow", "wow data")

S("playlist", 45).edit("name", "new playlist name")

edit(prop, value)

Edit or set props to the set of the matched dataObjects.

It’s used to safely edit dataObjects props, but it doesn’t wait for ready event.
You can also edit src and name props in database. But you can’t edit certain props such as type and id.

.empty()

S("playlist", 65).add("tracks streams")

S("playlist").empty();

// Or

S("playlist").empty("tracks");

// Equals this,
// but empty() is 2x faster than this call.
S("playlist").children("tracks").remove();

empty(types)

Remove child dataObjects of the set of the matched dataObjects.

This is unlink mechanism, It won’t remove child dataObjects from database.

.enqueue()

S("track:first").enqueue()

enqueue()

Add the set of the matched dataObjects to queue, right after the current loaded or at first.

It’s like (Add to Queue / Play Next) mechanism

.eq()

S("tracks").eq(0)

S("tracks").eq(10)

eq(index)

It returns a new SPlayer Object with the dataObject at specified index.

.filter()

S("tracks albums artists").filter("tracks")

// Or you could use function to filter them
S("tracks").filter(function (dataObject) {
    return dataObject.title.indexOf('wow') > -1
})

filter(type, value, options)

It returns a new filtered SPlayer Object and reduced to those match the selector, and adds .selection prop to the SPlayer Object pointing to the pervious set of the matched dataObjects.

.first()

S("tracks").first()

first()

It returns a new SPlayer Object with the first dataObject in the set of the matched dataObjects.

.get()

S("track", 10).get(function (dataObject) {
    console.log("dataObject is ready:", dataObject)
})


// Get if/when all tracks are ready
S("tracks").get(function(tracks) {

    console.log("All tracks are ready")

    // tracks is SPlayer Object
    tracks.each(...)

})

get(callback)

Get the set of the dataObjects (or a single dataObject) if/when ready.

.has()

if (S("playlist", 1).has("track", 90)) {
   // do something
}


// If playlist id=1 and playlist id=2 has track id=1
if (S("playlist", [1, 2]).has("track", 1)) {
   // do something
}

has(type, value)

Determine if the set of the matched dataObjects has a matched children.

Returns: Boolean

.init()

init()

SPlayer private selector function.

.last()

S("tracks").last()

last()

It returns a new SPlayer Object with the last dataObject in the set of the matched dataObjects.

.load()

// Load track id=9653, and add all tracks to queue.
S("track", 9653).load()

// This is different that the above.
// This loads track id=9653,  
// and adds all playlist track to queue.
S("playlist", 1).children("track", 9653).load();


// This is different too.
// This loads track id=9653,
// and it doesn't change or touch the queue.
S("queue").children("track", 9653).load();

load()

Load track/stream dataObject into the audio engine.

If the the track/stream was preloaded using .preload(), SPlayer will switch audio engine and load the preloaded/cached track/stream.

When you load dataObject, the queue changes based on the SPlayer().parent, history gets updated, and more.

If the .parent was queue, then SPlayer won’t change queue. ( That’s useful for loading nowplaying tracks/streams. )

This API checks for SPlayer().parent, so how you call this API is very important!

.move()

// Move the last track to index=0 (the first).
S("track:last").move(0);

// Move the last track of playlist to index=0 (the first)
// But the context/parent is playlist here.
S("playlist", 1).children("track:last").move(0);

move(index)

Move the set of the matched dataObjects to a specific index.

This API checks for SPlayer().parent, so how you call this API is very important!

.not()

// Select all tracks except the first one.
S("tracks").not("track:first")

not(type, value)

It returns a new SPlayer Object containing the set of the matched dataObjects without those that match the selector, and adds .selection prop to the SPlayer Object pointing to the pervious set of the matched dataObjects.

.off() / on() / one() / trigger()

// dataObject play event
S("track", 10).on("play", function () {
    console.log("Track id=10 is playing")
})

// Or global play event
S.on("play", function (dataObject) {

   if (dataObject.type === "track" && dataObject.id === 10) {
       console.log("Track id=10 is playing")
   }

   console.log("Currently playing is:", dataObject);

})

These APIs are just like the global methods SPlayer.off(), SPlayer.on(), SPlayer.one(), SPlayer.trigger(), but these will set events for the set of the matched dataObjects.

Please check Events, and notice the differnce between [G], and [GD] events.

However, using them isn’t necessary, because we always return dataObjects as arguments to Global Events, you could just check them using if statment.

.preload()

// Preload track id=9, and add all tracks to queue.
S("track", 9).preload();


// then you can load it later like this.
// SPlayer automatically switches the audio engine.
// And BOOM! it's already cached.
S("track", 9).load();


// Or preload/buffer the next track
// immediately after loading a track.
//
// This will make SPlayer to load and play the first track,
// and buffer the next.
S.on("load", function () {
    S(":next").preload();
});

preload(options)

Preload track/stream dataObject into the background audio engine.

By preloading track/stream, you get to load() it without waiting, which will create gapless playback.

You can even preload the same track to create truly gapless loop.

It only preloads the first dataObject in the set of the matched dataObjects.

If you want to attach an event to the background audio engine events, you can. Just check Preload Events

.ready()

S("tracks").ready(function (track) {
   console.log("This track is ready:" track)
})

ready(callback, options)

Iterate over the set of the matched dataObjects and callback each one if/when ready.

.release()

S("track", 41).release();

release(callback, options)

Release the set of the matched dataObjects from storage (Remove from the offline stroage).

.remove()

// Remove track id=1 entirely from database.
S("track", 1).remove();

// Remove/unlink track id=1 from playlist only..
S("playlist", 10).children("track", 1).remove();

// It still exists in database ..
S("track", 1)

// .. you can add it just right back.
S("playlist", 10).add("track", 1);

remove()

Remove the set of the matched dataObjects entirely from database or unlink them from other dataObjects.

This API checks for SPlayer().parent, so how you call this API is very important!

.reverse()

S("track").reverse()

reverse()

It returns a new SPlayer Object containing a reversed set of the matched dataObjects.

S("track").search("title", "let me");

// Select all tracks, and then do search for
// tracks that have large images ("large", and "extralarge")
S("track").search("images", [{size: "large"}])

// Smart search:
// This searchs in most of track dataObjects props
// (name, title, artists, albums, etc ..)
// If there's a match it returns it.
//
// It's slower than direct prop search,
// but this is incredible.
S("track").search("katy perry")


// Advanced algorithm-based search:
//
// This is of course slower than the others.
S("artists").search("name", "kacy berry", {algorithm: true}); // => Returns Katy Perry artist.

search(prop, value, options)

Search in the set of the matched dataObjects, and return a new SPlayer Object with the matched results.

It’s not case sensitive search. And there are two ways to search, one is normal, and the other is algorithm-based search that uses advanced Jaro-Winkler distance algorithm for Strings.

You can also search in a specified dataObject prop, or you could just let SPlayer automatically and smartly search by just value.

.share()

S("track", 10).share(); // Returns share link

S("track", 45).share(function (shareLink) {
   // do something with share link.
})

S("track", 62).share(false, {
    site: "twitter"
})

share(callback, options)

Share dataObject(s) (track, stream, album, etc ..) on Facebook/Twitter or get share link.

It uses Facebook Dialog Feed API and Twitter Web Intents API.

The share link can be read by SPlayer.urlize()

Sharing on Facebook requires app_id

.shuffle()

S("track").shuffle()

shuffle()

It returns a new SPlayer Object containing a shuffled set of the matched dataObjects.

This is different than SPlayer.shuffle()

.slice()

S("tracks").slice(0, 10)

slice(start, end)

It returns a new SPlayer Object containing a sliced set of the matched dataObjects. From start index to the end (end not included).

.sort()

// This returns a new SPlayer Object containing
// a sorted tracks.
S("tracks").sort("title", "ascending");


// This returns a new SPlayer Object containing
// sorted tracks and it does sort ALL tracks in database.
S("tracks").sort("title", "ascending", {modify: true});

// This returns a new SPlayer Object containing
// TRACK id=1 and sort ALL tracks in database as well.
// That's because the internal mechanism of this API,
// it sorts dataObjects by types.
S("track", 1).sort("title", "ascending", {modify: true});

// This returns a new SPlayer Object containg
// sorted playlist id=1 tracks.
// It does sorts playlist id=1 tracks in the database.
S("playlist", 1).children("tracks").sort("title", "ascending", {modify: true});


// Sort by image size.
// Notice what how we matched the types.
S("tracks").sort("images", [{size: "ascending"}])

sort(prop, order, options)

It returns a new SPlayer Object containing a sorted set of the matched dataObjects. It also can sort dataObjects in the database.

How you call this API is important, so pay attention to .parent prop

.store()

S("track", 10).store()

store(callback, options)

Store the set of the matched dataObjects.

By storing dataObjects with their metadata, you can extract them back with one call using SPlayer.extract() them back with ready metadata.

.toArray()

S("tracks").toArray()

// Or

var result = [];

// Or push them to result array.
S("tracks").toArray(result);

toArray(array)

It returns an Array of the set of the matched dataObjects, not an Array-like object.

.toBlob()

S("track").toBlob()

toBlob(options)

It converts the set of the matched dataObjects to JSON, then it creates a Blob from the JSON-stringified array and returns it.

You can also download the Blob file.

.toJSON()

S("tracks").toJSON()

toJSON()

It returns a JSON-stringified array of the set of the matched dataObjects with SPlayer Marker (__splayer__).

If the set of the matched dataObjects contains binary data, like Blob src, src prop will be empty

.unique()

S("track").unique()

unique()

It returns a new SPlayer Object containing unique dataObjects, it doesn’t return duplications if found.

.even()

S("track").even()

even()

(Max Edition) It returns a new SPlayer Object containing even dataObjects.

.odd()

S("track").odd()

odd()

(Max Edition) It returns a new SPlayer Object containing odd dataObjects.

.push()


// Any dataObject
var dataObject = S('album', 6523)[0];

// Select all tracks and add this dataObject to SPlayer Object list
S("track").push(dataObject)

// Or
var dataObject2 = S('artist', 215465)[0];
S("track").push(dataObject, dataObject2);

push(dataObject, dataObject2, ...)

(Max Edition) It adds one or more dataObjects to the end of the set of the matched dataObjects.

.unshift()


// Any dataObject
var dataObject = S('album', 6523)[0];

// Select all tracks and add this dataObject to SPlayer Object list
S("track").unshift(dataObject);

// Or
var dataObject2 = S('artist', 215465)[0];
S("track").unshift(dataObject, dataObject2);

unshift(dataObject, dataObject2, ...)

(Max Edition) It adds one or more dataObjects to the beginning of the set of the matched dataObjects.

Please note that, if multiple dataObjects are passed as parameters, they’re inserted in chunk at the beginning of the list, in the exact same order they were passed as parameters.

.shift()

S("track").shift()

shift()

(Max Edition) It removes the first dataObject from the set of the matched dataObjects and returns a new SPlayer Object containing that removed dataObject.

Please note that, it returns SPlayer Object with the dataObject, instead of pure dataObject, to enable SPlayer API chain.

.pop()

S("track").pop()

pop()

(Max Edition) It removes the last dataObject from the set of the matched dataObjects and returns a new SPlayer Object containing that removed dataObject.

Please note that, it returns SPlayer Object with the dataObject, instead of pure dataObject, to enable SPlayer API chain.

.every()

S("track").and('albums').every(function (dataObject) {
   return dataObject.type === 'track' // You can do any test here
}); // It returns false

every(testingFunction)

(Max Edition) It tests whether all dataObjects in the set pass the test implemented by the provided function.

Returns: Boolean

.some()

S("track").and('albums').some(function (dataObject) {
   return dataObject.type === 'track' // You can do any test here
}); // It returns true

some(testingFunction)

(Max Edition) It tests whether at least one dataObject in the set pass the test implemented by the provided function.

Returns: Boolean

Properties

SPlayer.session

SPlayer last session.

You can add your own custom props

Props:

SPlayer.support

Check SPlayer features support. SPlayer does real support checks, unlike any other library. real formats/codec support and real audio attributes support (autoplay, preload).

Did you know that iOS doesn’t support autoplay feature? SPlayer does a real autoplay test to return correct result.

FYI SPlayer error event gets called if no essential, storage, and metadata support. So if you want to run SPlayer partially, you can.

Props:

SPlayer._

SPlayer exposes some private functions and objects, but they are not part of the SPlayer Public API. If you’re nerdy enough, you will figure them out by yourself.

SPlayer.scripts

SPlayer exposes some useful functions, like folderToAddJSON. To read more about this function, check Pro-tips.

Attention: In the package there’s a Folder JSON Generator HTML5 App, you can use to generate and download SPlayer JSONs

SPlayer().length

SPlayer Array-like Object length.

SPlayer().splayer

SPlayer Version.

SPlayer().parent

The previous set of the dataObjects (also called parent).

SPlayer().selection

The selection set of the dataObjects.

Selector

// Select all tracks
S("track")

// Or
S("tracks")

// Select id=1 track
S("track", 1)

// Select track id=10, and id=24

// Select id=90 playlist
S("playlist", [10, 24])

// Select collection called "My Col"
S("collection", {
   name: "My Col"
})

// Reselect dataObject
S(dataObject)

// Other examples
S([dataObject, dataObject2])

S(simplifiedDataObject)

S(S("track"))

Select dataObjects from database. It’s similar to jQuery selector, it returns Array-like SPlayer Object ( a set of dataObjects ) with SPlayer Selector API.

S(type, value, _options)

You can use S or SPlayer. They are the same.

It’s case-sensitive selector

The selected dataObjects might not be ready yet. This is sync selecting. If you want to make sure you get them ready, please select and use .get()

Type Selector

S("tracks")

S("track")

// Multi selector
S("tracks albums artists")

Select dataObject(s) by type.

ID Selector

S("track", 123)

S("album", 6)

Select dataObject by id.

It’s very fast.

Property Selector

S("track", {
   src: "http://www.yourwebsite.com/path/to/songfile.mp3"
})

S("track", {
   src: srcInput // Yes, src input can be Blob/File.
})

// Select all tracks that has embedded images.
S("track", {
   images: [{
      type: "embedded"
   }]
});


// Select all tracks that doesn't have any images.
S("track", {
   images: undefined
})

Select dataObject(s) by custom property.

id, name, src are direct. Other props will loop for them. It does accept these types Boolean/String/Number/Object/Array/undefined

Notice how when we selected tracks that has embedded images with [{ .. }], because images is Array in dataObject. You must match types.

dataObject Selector

S(dataObject)


S([dataObject, dataObject2])


S([simplifedDataObject, simplifedDataObject2])

// dataObject.artists = [simplifedDataObject, ...]
S(dataObject.artists)

Reselect simplified and full dataObjects.

*When selecting simplifed dataObjects, It returns a SPlayer Object containing the full dataObjects.

SPlayer Object Selector

var track10 = S("track", 10);

// Clone track10 instance
S(track10)

Clone SPlayer Object instance.

* Selector

S("*")

// Or 
S("tracks streams albums artists genres playlists collections")

// Or this
S("* storage")

// equals this
S("tracks streams albums artists genres playlists collections storage")

Select all normal dataObjects.

Normal dataObjects: tracks, streams, albums, artists, genres, playlists, collections.

:first Selector

// Select the first added track
S("track:first")

// Select the first added track children
S("playlist", 1).children("track:first")

Select the first dataObject.

:last Selector

// Select the last added track
S("track:last")

// Select the last added track children
S("playlist", 1).children("track:last")

Select the last dataObject.

:next Selector

S(":next")

Select the next dataObject in queue.

It doesn’t load and play it, like calling S.next()

:prev Selector

S(":prev")

Select the prev dataObject in queue.

It doesn’t load and play it, like calling S.prev()

:shuffle Selector

S(":shuffle")

Select the shuffled dataObject in queue.

It doesn’t load and play it, like calling S.shuffle()

Important: the SPlayer shuffle mechanism is unique. Calling this selector multiple times will select non-repeated shuffled dataObjects. And if you shuffle all of them, you need to call reshuffle(), to reset the shuffling list.

:loaded Selector

S(":loaded")

Select the loaded dataObject.

:preloaded Selector

S(":preloaded")

Select the preloaded dataObject.

:parent Selector

S(":parent")

Select the parent dataObject.

Events

If you want to use Events, check on(), one(), off(), trigger().

[GD]: Global Event and dataObject Event.
like ready, there’s dataObject ready event and SPlayer ready event.

[G]: Global Event.
like close, there’s only SPlayer close event, there isn’t dataObject close event.

Window Events

Audio Events

Read more about Audio Events

Preload Events

Background audio Events.

When you call preload() to preload a certain track/stream, there are background events that gets fired, if you want to listen to them, here there are:

These events contains same data but for the preloaded dataObject

Extra API Events

States

SPlayer Live States.

These states will be automatically updated with events.

Plugins

How to Create a Basic Plugin

Sometimes you want to make a piece of functionality available throughout your code. For example, perhaps you want a single method you can call on a SPlayer selection that performs a series of operations on the selection (dataObjects: tracks, streams, albums, etc..). In this case, you may want to write a plugin.

How SPlayer Selector Works 101

Before we write our own plugins, we must first understand a little about how SPlayer works. Take a look at this code:

S("track", 1512469).edit( "info", "this track is awesome" );

This is some pretty basic SPlayer code, but do you know what’s happening behind the scenes? Whenever you use the S function to select dataObjects, it returns a SPlayer object. This object contains all of the methods (instance prototypes) you’ve been using (.edit(), .get(), etc.) and all of the dataObjects that fit your selector. The SPlayer object gets these methods from the S.prototype object. This object contains all of the SPlayer object instance prototypes, and if we want to write our own methods, it will need to contain those as well.

Basic Plugin Authoring

Let’s say we want to create a plugin that adds an image within a set of retrieved dataObjects that don’t have images. All we have to do is add a function called imagie to S.prototype and it will be available just like any other SPlayer object prototypes.

S.prototype.imagie = function() {

    // Filter the dataObjects that don't contain
    // images and then add custom image
    this.filter('*', {
        images: undefined    
    }).edit( "images", "http://www.yourwebsite.com/path/to/customImage.jpg" );

};

S("track").imagie(); // Adds custom image to tracks that don't have images.

Notice that to use .edit(), another prototype, we use this, not S(this). This is because our imagie function is a part of the same object as .edit().

Chaining

This works, but there are a couple of things we need to do for our plugin to survive in the real world. One of SPlayer Selector’s features is chaining, when you link five or six actions onto one selector. This is accomplished by having all SPlayer object prototypes return the original SPlayer object again (there are a few exceptions: .has() returns Boolean, and is not chainable). Making our plugin method chainable takes one line of code:

S.prototype.imagie = function() {

    // Filter the dataObjects that don't contain
    // images and then add custom image
    this.filter('*', {
        images: undefined    
    }).edit( "images", "http://www.yourwebsite.com/path/to/customImage.jpg" );

    return this;

};

S("track").imagie().download();

Adding Scope

We need to put all of our code inside of an Immediately Invoked Function Expression, and then pass the function SPlayer, and name the parameter S:

(function ( S ) {

    S.prototype.imagie = function () {
        ...
    }

}( SPlayer ));

In addition, the primary purpose of an Immediately Invoked Function is to allow us to have our own private variables.

(function ( S ) {

    var imageLink = "http://path/to/customImage.jpg";

    S.prototype.imagie = function () {

        this.filter('*', {
            images: undefined    
        }).edit( "images", "http://www.yourwebsite.com/path/to/customImage.jpg" ); 

        return this; // Or you could just return this.filter();

    }

}( SPlayer ));

It’s good practice when writing plugins to only take up one slot within S.prototype. This reduces both the chance that your plugin will be overridden, and the chance that your plugin will override other plugins. In other words, this is bad:

(function( S ) {

    S.prototype.imagie = function() {
        ...
    };

    S.prototype.anotherImage = function() {

        this.filter('*', {
            images: undefined    
        }).edit( "images", "http://www.yourwebsite.com/path/to/customImage.jpg" );  

        return this;

    };

}( SPlayer ));

It would be much better to have one slot, and use parameters to control what action that one slot performs.

(function( S ) {

    S.prototype.imagie = function( link ) {

        this.filter('*', {
            images: undefined    
        }).edit( "images", "http://www.yourwebsite.com/path/to/customImage.jpg" ); 

        return this;

    };

}( SPlayer ));

Using the each() Prototype

Your typical SPlayer object will contain references to any number of dataObjects, and that’s why SPlayer objects are often referred to as set. If you want to do any manipulating with specific dataObjects then you need to use .each()to loop through the dataObjects.

S.prototype.myNewPlugin = function() {

    return this.each(function(dataObject) {
        // Do something to each dataObject here.
    });

};

Notice that we return the results of .each() instead of returning this. Since .each() is already chainable, it returns this, which we then return. This is a better way to maintain chainability than what we’ve been doing so far.

There are also Advanced Plugin Concepts, but we are going to leave that to you.

UI Plugin

SPlayer UI Plugin is a colorful, jaw-dropping, intelligent Groove-like interface for SPlayer API. It’s event-driven music player, built with jQuery, powered by SPlayer, and can be launched with one call.

How Does it Work?

SPlayer UI is an interface for SPlayer API, so when you add tracks using SPlayer API, they will show on SPlayer UI. When you remove a track, it will be removed from SPlayer UI. If SPlayer database is empty, UI will be empty too, get it? It reads database and monitors its changes, and it’s bound to most of SPlayer APIs.

However, most of SPlayer API are bound to SPlayer, not all of them. JaguarScript is still working on that. This doesn’t mean anything to you if you don’t want to control UI by external calls.

Installation

SPlayer UI Plugin requires SPlayer and jQuery, to install it make sure both of these are included in your website. If they are not included, then include them

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> <script src="path/to/splayer.ui.min.js"></script> <link rel="stylesheet" type="text/css" src="path/to/splayer.ui.min.css"></link>

Make sure to replace path/to with your path

Then you can call it with one call, anytime you want.

Usage

var options = {
   container: ...
}

SPlayer.ui(options);

Options

API

SPlayer.ui.open()

// Open Albums tab
SPlayer.ui.open("albums");

// Open artist id=15
SPlayer.ui.open("artist", 15);

open(page, value)

Open Page.

SPlayer.ui.back()

SPlayer.ui.back()

back()

Go Back to the previous page.

SPlayer.ui.destroy()

SPlayer.ui.destroy()

destroy()

Destroy UI.

Performance

Notes & Pro-Tips

Browser Support

Chrome 8+, FireFox 4+, IE 10+, Opera 15+, Safari 6+, Edge and others.

If you want to support older browsers, it could work, but not all SPlayer features. And the ready event won’t be triggered, error will be triggered.